PDA

View Full Version : Npc walking to object


Miltiades
02-09-2007, 04:42 PM
Need help with a script (again). I want an NPC to walk to an object (a door), then use an animation and opening that door. All this happens in dialog. I first tried to make the NPC walk to the door using this script:

void main() {
AssignCommand(GetObjectByTag("NPC1", 0), ActionMoveToObject(GetObjectByTag("door1", 0), 0, 1.0));
}


But it didn't work. I don't know if I have to put another script in the NPC's utc file or not.

Can someone help me?

stoffe
02-09-2007, 05:07 PM
Need help with a script (again). I want an NPC to walk to an object (a door), then use an animation and opening that door. All this happens in dialog. I first tried to make the NPC walk to the door using this script

Are you in conversation with the door opener NPC directly, or is that another NPC? Something like this should probably work if it's another NPC than the one you started conversation with (assuming this is for TSL):



void ST_OpenDoor(object oTarget) {
if (GetIsObjectValid(oTarget) && (GetObjectType(oTarget) == OBJECT_TYPE_DOOR)) {
SetLocalBoolean(OBJECT_SELF, 87, TRUE);
SetCommandable(TRUE);
ClearAllActions();
ActionForceMoveToObject(oTarget);
ActionDoCommand(SetLocked(oTarget, FALSE));
ActionOpenDoor(oTarget);
ActionDoCommand(SetLocalBoolean(OBJECT_SELF, 87, FALSE));
ActionDoCommand(SetCommandable(TRUE));
SetCommandable(FALSE);
}
else {
SendMessageToPC(GetPartyLeader(), "DEBUG: Invalid door target for " + GetName(OBJECT_SELF) + "!");
}
}

void main() {
object oNPC = GetObjectByTag("NPC1");
object oDor = GetObjectByTag("door1");
if (GetIsObjectValid(oNPC)) {
AssignCommand(oNPC, ST_OpenDoor(oDor));
}
else {
SendMessageToPC(GetPartyLeader(), "DEBUG: Invalid NPC to move!");
}
}


It will disable the AI and lock the action queue of the NPC while moving to prevent it from being interrupted. It should then make the NPC move towards the door and open it. The NPC will have to be able to reach the door from where it's currently standing or it won't work, of course. :)

Miltiades
02-10-2007, 07:28 AM
I get the "Invalid door target for NPC1" in the Feedback. Because the tags of all the doors in the module were the same, I changed the one the NPC needs to walk to to "Hammerhead2".

Besides that, I've made a node without text for the script to activate, but it quickly skips the node. Delaying it hasn't helped, because then the NPC just talks (well, without voice and text, just expressions).

stoffe
02-10-2007, 10:36 AM
I get the "Invalid door target for NPC1" in the Feedback. Because the tags of all the doors in the module were the same, I changed the one the NPC needs to walk to to "Hammerhead2".

Besides that, I've made a node without text for the script to activate, but it quickly skips the node. Delaying it hasn't helped, because then the NPC just talks (well, without voice and text, just expressions).

The developers usually haven't bothered to give generic doors unique tags, so if you need to uniquely identify a door the easiest/safest way is probably to change the tag of the door in question in the area.

As for the dialog, is the NPC who should walk to the door and open it the same as the one the player is conversing with (the dialog owner)? If so it might help if you pause the dialog while they are walking, by modifying the script like:


void ST_OpenDoor(object oTarget) {
if (GetIsObjectValid(oTarget) && (GetObjectType(oTarget) == OBJECT_TYPE_DOOR)) {
SetLocalBoolean(OBJECT_SELF, 87, TRUE);
SetCommandable(TRUE);
ClearAllActions();
ActionPauseConversation();
ActionForceMoveToObject(oTarget);
ActionDoCommand(SetLocked(oTarget, FALSE));
ActionOpenDoor(oTarget);
ActionDoCommand(SetLocalBoolean(OBJECT_SELF, 87, FALSE));
ActionDoCommand(SetCommandable(TRUE));
ActionResumeConversation();
SetCommandable(FALSE);
}
else {
SendMessageToPC(GetPartyLeader(), "DEBUG: Invalid door target for " + GetName(OBJECT_SELF) + "!");
}
}

void main() {
object oNPC = GetObjectByTag("NPC1");
object oDor = GetObjectByTag("door1");

if (GetIsObjectValid(oNPC)) {
AssignCommand(oNPC, ST_OpenDoor(oDor));
}
else {
SendMessageToPC(GetPartyLeader(), "DEBUG: Invalid NPC to move!");
}
}

Miltiades
02-10-2007, 07:17 PM
As for the dialog, is the NPC who should walk to the door and open it the same as the one the player is conversing with (the dialog owner)?


No, it's another NPC. So the previous script should've worked. But I should mention that the door isn't blastable and requires a key and such (edited not only with KT, but with a GFF editor), all to prevent the PC to open the door. Only the NPC should be able to open the door, because the PC passes by the door before meeting the NPC.

Some questions though:

-Do I need to make the door a "plot item"?
-Do I need to make the NPC opening the door a "speaker" or a "listener" in the dialog or neither?
-Do I need to delay the node so the script has time to activate?

Miltiades
02-11-2007, 10:21 AM
Could it be that there's smething wrong in the first part of the script you gave me? That's why the "Invalid door target for" in the Feedback, no?

I've changed the tag of the door into something unique, have tried changing the door's security, so that it can be blasted, and it doesn't requires a key (but I'd rather that it does, so the PC can't open it), I've also tried some things in the dialog, making the NPC the speaker, making a node for the script itself, delaying the node, but nothing helped.

stoffe
02-11-2007, 12:23 PM
-Do I need to make the door a "plot item"?
-Do I need to make the NPC opening the door a "speaker" or a "listener" in the dialog or neither?
-Do I need to delay the node so the script has time to activate?

The script should unlock the door automatically before attempting to open it, so as long as it's possible to open it (i.e. it isn't set to be Static, non-usable or such) it should work.

If the door opener NPC isn't involved in the conversation there should be no need to pause or delay the conversation. The action script assigns the door opener actions to the NPC to perform on its own and the dialog should not affect it, as far as I know.


Could it be that there's smething wrong in the first part of the script you gave me? That's why the "Invalid door target for" in the Feedback, no?

It will only say "DEBUG: Invalid door target for CharName" if the object you pass as the door to be opened is either not valid (i.e. the script couldn't find an object with that tag), or is valid but is not a door object. Check so that you are using valid tags (remember that tags are not necessarily the same as the template name), and that there are no other objects in the same area that use an identical tag that the GetObjectByTag() function might locate before it finds the door.

Miltiades
02-11-2007, 12:38 PM
Okay. Stupid me. Forgot to change the tag in the .git file. Thanks.

Oh yeah, how can I make the NPC do an animation before opening the door? (Like Atton when he's in the cockpit of the EH)

stoffe
02-11-2007, 12:48 PM
Okay. Stupid me. Forgot to change the tag in the .git file. Thanks.

Oh yeah, how can I make the NPC do an animation before opening the door? (Like Atton when he's in the cockpit of the EH)

Should work to insert an action playing an animation briefly just before the door is opened. Like:


void ST_OpenDoor(object oTarget) {
// ST: Only proceed if oTarget is a door.
if (GetIsObjectValid(oTarget) && (GetObjectType(oTarget) == OBJECT_TYPE_DOOR)) {
// ST: Disable AI, clear actions and unlock action queue.
SetLocalBoolean(OBJECT_SELF, 87, TRUE);
SetCommandable(TRUE);
ClearAllActions();

// ST: Queue actions: Move to door, unlock it, play animation and open.
ActionForceMoveToObject(oTarget);
ActionDoCommand(SetLocked(oTarget, FALSE));
ActionDoCommand( SetFacingPoint(GetPosition(oTarget)) );
ActionPlayAnimation( ANIMATION_LOOPING_USE_COMPUTER, 1.0, 1.5);
ActionOpenDoor(oTarget);

// ST: Turn AI back on and unlock action queue.
ActionDoCommand(SetLocalBoolean(OBJECT_SELF, 87, FALSE));
ActionDoCommand(SetCommandable(TRUE));

// ST: Lock action queue to preserve above queued commands.
SetCommandable(FALSE);
}
else {
SendMessageToPC(GetPartyLeader(), "DEBUG: Invalid door target for " + GetName(OBJECT_SELF) + "!");
}
}

void main() {
object oNPC = GetObjectByTag("NPC1"); // ST: Tag of NPC to open door
object oDor = GetObjectByTag("door1"); // ST: Tag of door to open

if (GetIsObjectValid(oNPC)) {
AssignCommand(oNPC, ST_OpenDoor(oDor));
}
else {
SendMessageToPC(GetPartyLeader(), "DEBUG: Invalid NPC to move!");
}
}


Edit: Added an extra action to make sure the NPC faces the door before playing the animation, and fixed a mistake with the animation playing function.

Miltiades
02-11-2007, 12:58 PM
Great! Thanks again.

Miltiades
02-12-2007, 04:30 PM
I'm sorry to bother you again, but how do I change the script if the object the NPC has to walk to is not a door?

stoffe
02-12-2007, 04:48 PM
I'm sorry to bother you again, but how do I change the script if the object the NPC has to walk to is not a door?

Is the NPC still supposed to open a door near the destination object, or should it just move to the object?

Miltiades
02-12-2007, 05:17 PM
Actually, yes, the NPC walks to the object, uses the "Use_Computer" animation and opens the door.

stoffe
02-12-2007, 05:38 PM
Actually, yes, the NPC walks to the object, uses the "Use_Computer" animation and opens the door.

If you want to keep it all to one script, a variant of the above script like this might work:



void ST_MoveAndOpenDoor(object oDoor, object oMove) {
if (!GetIsObjectValid(oMove)) {
SendMessageToPC(GetPartyLeader(), "DEBUG: Invalid move target for " + GetName(OBJECT_SELF) + "!");
return;
}

// ST: Only proceed if oDoor is a door.
if (GetIsObjectValid(oDoor) && (GetObjectType(oDoor) == OBJECT_TYPE_DOOR)) {
// ST: Disable AI, clear actions and unlock action queue.
SetLocalBoolean(OBJECT_SELF, 87, TRUE);
SetCommandable(TRUE);
ClearAllActions();

// ST: Queue actions: Move to target,play animation towards it, open door
ActionForceMoveToObject(oMove, FALSE, 0.8);
ActionDoCommand(SetLocked(oDoor, FALSE));
ActionDoCommand( SetFacingPoint(GetPosition(oMove)) );
ActionPlayAnimation( ANIMATION_LOOPING_USE_COMPUTER, 1.0, 1.5);
ActionDoCommand(AssignCommand(oDoor, ActionOpenDoor(oDoor)));

// ST: Turn AI back on and unlock action queue.
ActionDoCommand(SetLocalBoolean(OBJECT_SELF, 87, FALSE));
ActionDoCommand(SetCommandable(TRUE));

// ST: Lock action queue to preserve above queued commands.
SetCommandable(FALSE);
}
else {
SendMessageToPC(GetPartyLeader(), "DEBUG: Invalid door for " + GetName(OBJECT_SELF) + "!");
}
}

void main() {
object oNPC = GetObjectByTag("NPC1"); // ST: Tag of NPC to open door
object oDoor = GetObjectByTag("door1"); // ST: Tag of door to open
object oMove = GetObjectByTag("target"); // ST: Tag of object to walk to.

if (GetIsObjectValid(oNPC)) {
AssignCommand(oNPC, ST_MoveAndOpenDoor(oDoor, oMove));
}
else {
SendMessageToPC(GetPartyLeader(), "DEBUG: Invalid NPC to move!");
}
}


Set the tag of the target object to move to in the main() function along with the tag of the door and the NPC who should be doing it.