Imagine there is a drawbridge.
The only way to open the drawbridge is by pulling a lever on the otherside.
If the PC tries to open the drawbridge a conversation starts and the NPC tells the player he is allowed to enter or he is not allowed to enter.
If the player is allowed to enter then a script fires which tells the NPC to activate the lever which opens the drawbridge.
The player is then free to enter.
It seems so simple yet for the life of me I cannot find a command which tells the NPC to use/activate/command/do it/?
I know there is always this but... meh
void main()
{
object oDoor = GetObjectByTag("DOOR_TAG");
SetLocked(oDoor,FALSE);
ActionOpenDoor(oDoor);
}
Command a NPC to use a lever, that opens a door, through a conversation.
Débuté par
Friar
, nov. 16 2013 02:08
#1
Posté 16 novembre 2013 - 02:08
#2
Posté 16 novembre 2013 - 02:49
If all this is happening in a cutscene, you can use stock scripts by making the NPC walk to the lever, next nod play the custom animation "activate" I believe, and the door to open. I don't know if there is a ga_* script for opening doors, didn't need one for a while, but lilac's gives one and it works like a charm, this I know.
Sometimes when I can't get the thing I want, I settle for an alternative. That is to make the animation for pulling the lever, but not the actual action.
Sometimes when I can't get the thing I want, I settle for an alternative. That is to make the animation for pulling the lever, but not the actual action.
#3
Posté 16 novembre 2013 - 03:10
I really can be stubborn at times. Its just doesn't it seem like it would be easier if I could do this:
void main()
{
object oLever = GetObjectByTag("bridge_lever");
SetLocked(oDoor,FALSE);
ActionOnLever(oLever);
}
void main()
{
object oLever = GetObjectByTag("bridge_lever");
SetLocked(oDoor,FALSE);
ActionOnLever(oLever);
}
#4
Posté 16 novembre 2013 - 08:04
There is a command DoPlaceableObjectAction.
void main()
{
object oLever = GetObjectByTag("bridge_lever");
DoPlaceableAction(oLever, PLACEABLE_ACTION_USE );
}
void main()
{
object oLever = GetObjectByTag("bridge_lever");
DoPlaceableAction(oLever, PLACEABLE_ACTION_USE );
}
#5
Posté 16 novembre 2013 - 02:54
Ah awesome, thanks diophant
So now I should have the NPC run over to the lever and use it using:
void main()
{
object oLever = GetObjectByTag("bridge_lever");
DoPlaceableObjectAction(oLever, PLACEABLE_ACTION_USE );
}
Also I realized I over simplified the use of the switch but now I have the script reading as such:
int FlipSwitch(object oLever = OBJECT_SELF)
{
//lever animation
if (GetLocalInt(OBJECT_SELF,"nToggle") == 0)
{
PlayAnimation(ANIMATION_PLACEABLE_ACTIVATE,1.0,1.0);
SetLocalInt(OBJECT_SELF,"nToggle",1);//set "ON"
return TRUE;
}
else
{
PlayAnimation(ANIMATION_PLACEABLE_DEACTIVATE,1.0,1.0);
SetLocalInt(OBJECT_SELF,"nToggle",0);//set "OFF"
return FALSE;
}
//end level anaimation
}
void main()
{
if(FlipSwitch())
{
// Add code for ON state
object oTarget;
oTarget = GetObjectByTag("PrisonLabGate");
SetLocked(oTarget, FALSE);
AssignCommand(oTarget, ActionOpenDoor(oTarget));
else
{
// Add code for OFF state, if you wish
object oTarget;
oTarget = GetObjectByTag("bridge_lever");
AssignCommand(oTarget, ActionCloseDoor(oTarget));
SetLocked(oTarget, TRUE);
}
}
Since I'm only starting to get a knack for scripting I'm not sure what this error is
"else" WITHOUT"if" STATEMENT.
So now I should have the NPC run over to the lever and use it using:
void main()
{
object oLever = GetObjectByTag("bridge_lever");
DoPlaceableObjectAction(oLever, PLACEABLE_ACTION_USE );
}
Also I realized I over simplified the use of the switch but now I have the script reading as such:
int FlipSwitch(object oLever = OBJECT_SELF)
{
//lever animation
if (GetLocalInt(OBJECT_SELF,"nToggle") == 0)
{
PlayAnimation(ANIMATION_PLACEABLE_ACTIVATE,1.0,1.0);
SetLocalInt(OBJECT_SELF,"nToggle",1);//set "ON"
return TRUE;
}
else
{
PlayAnimation(ANIMATION_PLACEABLE_DEACTIVATE,1.0,1.0);
SetLocalInt(OBJECT_SELF,"nToggle",0);//set "OFF"
return FALSE;
}
//end level anaimation
}
void main()
{
if(FlipSwitch())
{
// Add code for ON state
object oTarget;
oTarget = GetObjectByTag("PrisonLabGate");
SetLocked(oTarget, FALSE);
AssignCommand(oTarget, ActionOpenDoor(oTarget));
else
{
// Add code for OFF state, if you wish
object oTarget;
oTarget = GetObjectByTag("bridge_lever");
AssignCommand(oTarget, ActionCloseDoor(oTarget));
SetLocked(oTarget, TRUE);
}
}
Since I'm only starting to get a knack for scripting I'm not sure what this error is
"else" WITHOUT"if" STATEMENT.
Modifié par koundog1, 16 novembre 2013 - 02:56 .
#6
Posté 16 novembre 2013 - 03:41
I am the biggest noob when it comes to scripting, but if I had to guess, I would say that you have no closing bracket after the
f(FlipSwitch())
{
// Add code for ON state
object oTarget;
oTarget = GetObjectByTag("PrisonLabGate");
SetLocked(oTarget, FALSE);
AssignCommand(oTarget, ActionOpenDoor(oTarget));
Still, don't take my words for serious. If it's not Lilacs I can't do it
.
f(FlipSwitch())
{
// Add code for ON state
object oTarget;
oTarget = GetObjectByTag("PrisonLabGate");
SetLocked(oTarget, FALSE);
AssignCommand(oTarget, ActionOpenDoor(oTarget));
Still, don't take my words for serious. If it's not Lilacs I can't do it
#7
Posté 16 novembre 2013 - 04:41
like andy wrote, it's just a closing missing closing bracket of the if-part.
#8
Posté 16 novembre 2013 - 06:29
Thanks you two! The lever works great.
After testing my final product with the NPC opening the door, I discovered that he is not going to the lever as instructed. I'm going to work with it when I get back in town monday.
After testing my final product with the NPC opening the door, I discovered that he is not going to the lever as instructed. I'm going to work with it when I get back in town monday.
Modifié par koundog1, 16 novembre 2013 - 06:55 .
#9
Posté 17 novembre 2013 - 08:26
You mean, he is activating the lever from a distance, using his great telekinetic powers? I thought that DoPlaceableCommand forced an NPC to move close to the object, but you can add an additional ActionMoveToObject before calling DoPlaceableAction. Eventually, you also must also call PlayAnimation.koundog1 wrote...
After testing my final product with the NPC opening the door, I discovered that he is not going to the lever as instructed. I'm going to work with it when I get back in town monday.
#10
Posté 17 novembre 2013 - 09:14
Maybe he uses his telekinetic powers because of a delay issue. Someone told me one time, thta everything in NWN2 system is time based. I am not sure what exactly it means, but maybe he has not enough time to move, AND do the action so he chooses to do only one thing?
#11
Posté 17 novembre 2013 - 09:50
i found with making the pc have a seated conversation with another sitting npc - DelayCommand was necessary for everything to work properly. fortunately the delays were relatively short and required little to none trial and error.
#12
Posté 17 novembre 2013 - 10:29
In cases like this, involving stage directions/blocking between NPCs and objects, I almost always resort to using a case-based heartbeat, with many individual stages of action, each of which checks to see if the last one was finished yet before proceeding, and if it wasn't finished, it refires the commands to do it. So one stage, for instance, is to walk over to the lever, and every heartbeat will check how close the NPC is to the lever, and if it's too far away, it'll tell it to walk over to it again. If it's close enough, it tells the NPC to play the animation, etc.
Modifié par Tchos, 17 novembre 2013 - 10:30 .
#13
Posté 18 novembre 2013 - 02:44
If you command an NPC to go and use an object (door, lever, chest, usable placeable, etc), there's no need to block out the sequence of events. They'll run to it (if there's a walkable path to it) and activate it when they get there. I have all sorts of NPCs in my current module activating and deactivating things.
I tend to have additional HB checks just incase they get waylaid before performing the action (like the player talking to them, or they perceive an enemy). That way the command gets re-added to their action queue if necessary. I initially had an HB script command them to use something every six seconds, but if it took them more than six seconds to get there they ended up using it multiple times. Since my lamp posts are toggles, that means one NPC was lighting and extinguishing a lamp in rapid succession every evening, then lighting it again when the next HB cycle came around. Talk about obsessive compulsive disorder!
I tend to have additional HB checks just incase they get waylaid before performing the action (like the player talking to them, or they perceive an enemy). That way the command gets re-added to their action queue if necessary. I initially had an HB script command them to use something every six seconds, but if it took them more than six seconds to get there they ended up using it multiple times. Since my lamp posts are toggles, that means one NPC was lighting and extinguishing a lamp in rapid succession every evening, then lighting it again when the next HB cycle came around. Talk about obsessive compulsive disorder!
#14
Posté 18 novembre 2013 - 02:55
This NPC hates you
.
#15
Posté 18 novembre 2013 - 11:30
I headed you guys wise counsel and I also threw in something to try and itentify the NPC even though it seemed redundant right? I'm sure there is a better way of doing this, especially since this isn't working and I was really thinking it would.
void main()
{
object oPC = GetPCSpeaker();
object oTarget;
oTarget = GetObjectByTag("guard1");
AssignCommand(oTarget, ActionMoveToObject(GetObjectByTag("bridge_lever")));
AssignCommand(oTarget, ActionWait(3.0f));
AssignCommand(oTarget, ActionCloseDoor(GetObjectByTag("bridge_lever")));
object oLever = GetObjectByTag("bridge_lever");
DoPlaceableObjectAction(oLever, PLACEABLE_ACTION_USE );
}
void main()
{
object oPC = GetPCSpeaker();
object oTarget;
oTarget = GetObjectByTag("guard1");
AssignCommand(oTarget, ActionMoveToObject(GetObjectByTag("bridge_lever")));
AssignCommand(oTarget, ActionWait(3.0f));
AssignCommand(oTarget, ActionCloseDoor(GetObjectByTag("bridge_lever")));
object oLever = GetObjectByTag("bridge_lever");
DoPlaceableObjectAction(oLever, PLACEABLE_ACTION_USE );
}
Modifié par koundog1, 18 novembre 2013 - 11:32 .
#16
Posté 19 novembre 2013 - 12:12
I haven't tested this, but I have levers in one of my dungeons, and I think you don't want to issue the ActionCloseDoor command. I think you want to issue the ActionInteractObject() command instead.
And as DannJ said, if the creature is close to the object, the command to tell them to move is not necessary. All you have to do is issue the ActionInteractObject() command and pass in the placeable to interact with, and the creature will do it.
I use a similar strategy that Tchos and DannJ just mentioned - checking to see if an action completed before issuing a command again in a HB script. I do this for NPC's that I want to walk around town. They appear at one doorway, randomly select another door (a waypoint really) and then walk to it, play a door animation, and then disappear (thus looking like they went inside). The trick is to monitor their progress in a HB, because as DannJ mentions, when they perceive things or get interrupted by a conversation, they will stop.
And as DannJ said, if the creature is close to the object, the command to tell them to move is not necessary. All you have to do is issue the ActionInteractObject() command and pass in the placeable to interact with, and the creature will do it.
I use a similar strategy that Tchos and DannJ just mentioned - checking to see if an action completed before issuing a command again in a HB script. I do this for NPC's that I want to walk around town. They appear at one doorway, randomly select another door (a waypoint really) and then walk to it, play a door animation, and then disappear (thus looking like they went inside). The trick is to monitor their progress in a HB, because as DannJ mentions, when they perceive things or get interrupted by a conversation, they will stop.
#17
Posté 19 novembre 2013 - 01:12
Ew yeah! I didn't see that I added that. I was trying to test something else. Lots of experimenting being done on my end.
(Edit) So here is what I am thinking. The script might be thinking the door placeable is being told to get the lever.
I think this because the script is called from a conversation.
The conversation is called from a failure to open the door.
Although I have the node assigning the guard as the speaker there is perhaps a conflict because the guard isn't the original trigger in the conversation.
So maybe I should try a script that opens a new conversation with the guard as the primary participant.
(EDIT 2)
Everything works now!
I have the conversation jump to another conversation. It works I think because the new conversation is specifically assigned to that particular NPC. If any of this makes sense then you might be just as crazy as I am.
(Edit) So here is what I am thinking. The script might be thinking the door placeable is being told to get the lever.
I think this because the script is called from a conversation.
The conversation is called from a failure to open the door.
Although I have the node assigning the guard as the speaker there is perhaps a conflict because the guard isn't the original trigger in the conversation.
So maybe I should try a script that opens a new conversation with the guard as the primary participant.
(EDIT 2)
Everything works now!
I have the conversation jump to another conversation. It works I think because the new conversation is specifically assigned to that particular NPC. If any of this makes sense then you might be just as crazy as I am.
Modifié par koundog1, 19 novembre 2013 - 02:37 .
#18
Posté 19 novembre 2013 - 11:04
I once had a cutscene which included 5 convo jumps. So I guess I know what you're talking about
.
I think cutscenes will behave better if the object meant to do something is also the owner of the convo.
Could be gibberish, but still
.
I think cutscenes will behave better if the object meant to do something is also the owner of the convo.
Could be gibberish, but still





Retour en haut







