Aller au contenu

Photo

How to halt script execution?


  • Veuillez vous connecter pour répondre
19 réponses à ce sujet

#1
popcorn_eater

popcorn_eater
  • Members
  • 27 messages
Hello, I'm fairly new to NWN2 toolset.
But I'm pretty familiar with NWN scripting (used to make PWs with Aurora toolset, nothing spectacular, just for fun)

Ok, so I have an NPC who has OnSpawn() script which contains 
---
ActionWalkRandom()
---


I also need this NPC to stop when PC starts a conversation with him.
Here is what i came up with:

void main()
{
ClearAllActions();
BeginConversation();
 --
}


Now what I need is that NPC would continue his random walk functionm but I DON'T WANT TO use OnConversationEnd() feature. Instead, I want to halt execution of this script until an NPC will be free from conversation with the PC.
So best what I could come up with was:

while (IsInConversation(OBJECT_SELF)) return;

But the damn thing doesn't work, so is there any way to halt execution of such script?


Edit: Seems that [nss] tag is not supported here. A shame.

Modifié par popcorn_eater, 30 septembre 2010 - 05:21 .


#2
diophant

diophant
  • Members
  • 116 messages
Where did you put that last line? The onSpawn script fires only once, when the creature is spawned, and then never again. What you have to do is change the onHeartbeat script. And you should use "if" instead of "while" (although it makes technically no difference in this case).


#3
popcorn_eater

popcorn_eater
  • Members
  • 27 messages
I am aware of that. However, ActionRandomWalk() never stops, unless creature is attacked or ClearAllActions() is used.

void main()
{
ClearAllActions();
BeginConversation();
while (IsInConversation(OBJECT_SELF)) return;
ActionRandomWalk()
}


This is my On Conversation script. 
But this doesn't work, since I can't loop "while" cycle. Is there any way to halt execution in this example?

Again, I DON'T WANT TO use OnConversationEnd() script.

#4
SkywingvL

SkywingvL
  • Members
  • 351 messages
All script execution is synchronous and blocks the server from otherwise running the game world forward while a script is running -- this approach will not work as a result of that.



Timed delays or polling operations are typically implemented via DelayCommand requests or heartbeat scripts.

#5
popcorn_eater

popcorn_eater
  • Members
  • 27 messages

SkywingvL wrote...

All script execution is synchronous and blocks the server from otherwise running the game world forward while a script is running -- this approach will not work as a result of that.

So the answer is no? :(

BTW, this is for Single-Player module.

#6
SkywingvL

SkywingvL
  • Members
  • 351 messages
There's probably going to be a way to accomplish what you are ultimately trying to do here, but it might be necessary to take a different approach.

Can we take a step back for a moment and look more at what you're trying to do that's lead you down this path? (i.e. what effect / end result you're trying to achieve by doing this.)  It wasn't entirely clear to me what you were trying to achieve in the end from your original post.

Modifié par SkywingvL, 30 septembre 2010 - 09:56 .


#7
popcorn_eater

popcorn_eater
  • Members
  • 27 messages
I want my NPC to continue doing ActionRandomWalk() after PC finished talking to him via OnConversation() script which I posted earlier.

#8
_Knightmare_

_Knightmare_
  • Members
  • 643 messages
As SW suggested, an OnHeartbeat script might be your best option. Here's the one I made for a similar situation:

void main()
{
object oSelf = OBJECT_SELF;

// Raise the AI level if needed
if(GetAILevel(oSelf) == AI_LEVEL_VERY_LOW)
	{
	SetAILevel(oSelf, AI_LEVEL_LOW);
	}

// If not currently in combat, conversation or Detect Mode, do Random Walk
if((!GetIsInCombat(oSelf)) && (!IsInConversation(oSelf)) && 
	(GetDetectMode(oSelf) != DETECT_MODE_ACTIVE))
	{
	AssignCommand(oSelf, ActionRandomWalk());
	}
	
// Execute default Heartbeat script
ExecuteScript("nw_c2_default1", oSelf);
}

Providing it works like it should, it may take up to 6 seconds for the NPC to begin random walking again depending on the timing of exiting the convo (will wait until the NPC's next heartbeat which fire every 6 seconds).

#9
popcorn_eater

popcorn_eater
  • Members
  • 27 messages
Well, I am aware of these ways out.
I just wanted to know if such thing is possible to script in NWN2.

Thanks, anyway.

Modifié par popcorn_eater, 30 septembre 2010 - 12:56 .


#10
diophant

diophant
  • Members
  • 116 messages
The onConversation script does not run during the whole conversation. It just fires when you click on the NPC, and starts the actual conversation. Like all scripts in NWN2, it just runs for the glimpse of a second, and starts some actions (or puts them into an action queue), and then it ends. Therefore, you cannot know in this script when the conversation ends.

#11
popcorn_eater

popcorn_eater
  • Members
  • 27 messages
I know, goddamnit.

I just wanted to know if there is any way to pause script execution.

#12
_Knightmare_

_Knightmare_
  • Members
  • 643 messages
Hardly the way to treat people who are just trying to help...

But if that is the only answer you seek:

No, you can not halt script execution in the middle of the script, have a conversation fire off and then resume the script where it left off. What you can do is delay execution of a sepecific scope or command for a specified amount of time, but of course that will not work in this situation. So, the best you can do is set up a pseudo-heartbeat if a normal heartbeat script will not work for you.

Modifié par _Knightmare_, 30 septembre 2010 - 03:00 .


#13
popcorn_eater

popcorn_eater
  • Members
  • 27 messages
Sorry, it wasn't my intention to insult anyone.



Thanks.

#14
Kaldor Silverwand

Kaldor Silverwand
  • Members
  • 1 592 messages
I'm not sure why this wouldn't work:

void main()
{
ClearAllActions();
BeginConversation();
while (IsInConversation(OBJECT_SELF))
{
// loop until the conversation has ended
}

ActionRandomWalk();
}

Alternatively you could set a local variable on the NPC prior to initiating the conversation. Have the while loop check that variable. And then in the end node of the conversation update the variable.

Regards

Modifié par Kaldor Silverwand, 30 septembre 2010 - 09:21 .


#15
popcorn_eater

popcorn_eater
  • Members
  • 27 messages
Well, I tried this before, but to no avail.



I experimented a bit:

First, I tried running with DebugServer, seems that no matter what useless function I insert in "while" loop (GetTag(OBJECT_SELF), for example) conversation won't start until the script execution is ended.

Then I tried running it without DebugServer, conversation started, but creature still wasn't walking random after the conversation has ended.

So, it seems, that there is some kind of protection from such endless loops in-game. Makes sence.



Thanks to everyone again.

#16
diophant

diophant
  • Members
  • 116 messages

Kaldor Silverwand wrote...

I'm not sure why this wouldn't work:

void main()
{
ClearAllActions();
BeginConversation();
while (IsInConversation(OBJECT_SELF))
{
// loop until the conversation has ended
}

ActionRandomWalk();
}

Alternatively you could set a local variable on the NPC prior to initiating the conversation. Have the while loop check that variable. And then in the end node of the conversation update the variable.

Regards


From my understanding of the engine, everything runs sequentiel. Thus, the conversation is started after this script finishes. You can check whether my guessing is correct by making a debug of IsInConversation after BeginConversation.
Scripts that run too long a terminated by a TMI (too many instructions) error, so even if the while codition should return TRUE, the script should abort after some thousand executins of the empty while loop.
From a programmers sight, this behaviour is desireable. Scripts are atomar units that cannot be interrupted by anything, this avoids nasty errors by two parallel scripts reading and writing the same data. The TMI errors prevent scripts from hanging the whole system by accidently using infinite loops.

@popcorn_eater: apologies accepted, I didn't really understand you question until the last posts of Knightmare and Kaldor Silverwand.

#17
Shallina

Shallina
  • Members
  • 1 011 messages
Far more easier solution :

When you speak to the NPC the currect random walk action stop by itself.

So just launch again the random walk at the end of conversation in an action script.

Now if you don't want that final line in an action script, check the on hearbat script.

With a if (!IsInConversation(OBJECT_SELF)){
AssignCommand(OJECT_SELF,ActionRandomWalk());
}

That's the first step, the second step is to launch that function only once when needed, you need to set up a var so it will work only once :

if (GetLocalVar(OBJECT_SELF,"isSpeaking")) {
if (!IsInConversation(OBJECT_SELF)){
SetLocalVar(OBJECT_SELF,"isSpeaking",FALSE);
AssignCommand(OBJECT_SELF,ActionRandomWalk());
}
}
You need To set the local var to true when the NPC begin a conversation.

You don't need an infinite loop in the heartbat script, the script is run every 6 second.

In order to set the isSpeaking var you got 3 option :

NPC on conversation script, PC on conversation script, or an action script in the first node of the conversation.

Best solution is probably to set it up in the NPC on conversation script. You'll use the same script for all NPC concerned. And if you want to alter the way it work later, you'll just have to touch 1 script instead of all the conversation involved.

Modifié par Shallina, 01 octobre 2010 - 11:15 .


#18
Kaldor Silverwand

Kaldor Silverwand
  • Members
  • 1 592 messages
In my King's Festival campaign I have various folks who walk around randomly and have conversations. They do start randomly walking again after the conversation. Usually the conversation is just a one-liner, so it may be that this approach won't work with an extended conversation. The solution requires only two simple scripts.

This script is used as a secondary SpawnScript for the walking creature. If you are using the standard Spawn script, then to have a secondary script called from the standard script, just assign variable SpawnScript on the creature to the name of the secondary script.
// bb_randomwalker_sp
// by Brendan Bellina
// May, 2007

// Use as the spawn script to make a creature walk about.
// Set variable SpawnScript to bb_randomwalker_sp so that
// this will be executed after the standard spawn script.

// Setting variable X2_L_SPAWN_USE_AMBIENT to 1 can also
// make a creature walk about, but it is resource intensive and
// is usually only worthwhile for humanoids.

// If the creature has a conversation then also use
// the on conversation script bb_randomwalker_onconv which
// wraps the conversation so that the creature starts
// walking again afterward.

void main ()
{
	AssignCommand(OBJECT_SELF, ActionRandomWalk());
}

The second script required is used as the on Conversation script of the walker. This wraps the conversation so that after it completes the creature should begin walking again.

// bb_randomwalker_onconv
// by Brendan Bellina
// May, 2007

// Set to the On Conversation script of a
// creature that is randomly walking so that
// it starts walking again after the conversation
// concludes.

void main()
{
	BeginConversation();
	ActionRandomWalk();
}

I know this works for at least one-liner conversations. It may work with longer ones, but I never had a need to test that use case. For NPC's with real conversations I would not have them walking about randomly anyway. Too easy to miss and too hard to offer support.

Regards

Modifié par Kaldor Silverwand, 02 octobre 2010 - 11:17 .


#19
Kaldor Silverwand

Kaldor Silverwand
  • Members
  • 1 592 messages
Interesting side-note. If I post a "Quick Reply" from my Mac using Safari I get double line breaks. Probably because Macs use a different end of line combo than Windows does. But, if I edit the post I just posted and repost it, the double line breaks are removed. Good to know if using a Mac.

#20
SkywingvL

SkywingvL
  • Members
  • 351 messages

Kaldor Silverwand wrote...

Interesting side-note. If I post a "Quick Reply" from my Mac using Safari I get double line breaks. Probably because Macs use a different end of line combo than Windows does. But, if I edit the post I just posted and repost it, the double line breaks are removed. Good to know if using a Mac.


This is a defect in the forum software; I see the same on IE8 on Win7.  Editing and resaving the post will fix the double line breaks.

Modifié par SkywingvL, 03 octobre 2010 - 02:06 .