Question about Stealth Mode

In an area I want the whole party to go into Stealth Mode to sneak by a few enemies. I then I have setup a number of triggers checking if they are able to sneak past them. There are quite a lot of companions in the party. I find it a bit odd when testing this. It’s like when I click on each of them trying to enter Stealth Mode, some seem to exit Stealth Mode right after I’ve ordered them to enter Stealth Mode. When choosing everyone at the same time and trying to enter Stealth Mode, that doesn’t seem to work either.

Of course, I could just, with the script, check for the main PC, if he’s in Stealth Mode but…

Maybe I’m doing something wrong in the game? Maybe one could force the party into Stealth Mode by scripting? The latter I tried by using the function SetAssociateState, but it only seems to have NW_ASC_AGGRESSIVE_STEALTH, which I don’t know what it is honestly.

Any thoughts on this?

“Your party attempts to sneak past the gnolls.”

int ACTION_MODE_STEALTH = 1;

// Sets the status of modes ACTION_MODE_* on a creature.
void SetActionMode(object oCreature, int nMode, int nStatus);
2 Likes

These looked promising in my tests. Works with associates too:

// stealth_start
/*
	Run this from the last node of a convo.
	This sets the entire party to stealth mode active.
	This quickly cycles and sets control of each party member
	so the stealth visual effect is applied to each character
	then returns back to the original controlled character. 	
*/

void SetStealth(object oFM)
{
	SetOwnersControlledCompanion(GetFirstPC(FALSE), oFM);
	SetActionMode(oFM, ACTION_MODE_STEALTH, TRUE);
}

void BackToStart(object oPC)
{
	SetOwnersControlledCompanion(GetFirstPC(FALSE), oPC);
}

void main()
{
	object oPC = GetFirstPC(FALSE);
	object oFM = GetFirstFactionMember(oPC, FALSE);
	float fDelay = 0.0f;
	
	while (GetIsObjectValid(oFM))
	{
		DelayCommand(fDelay, SetStealth(oFM));
		fDelay += 0.1f;
		oFM = GetNextFactionMember(oPC, FALSE);
	}
	
	DelayCommand(fDelay, BackToStart(oPC));
}

Run this to remove the party stealth:

// stealth_stop
/*
	Run this from a convo.
	This sets the entire party to deactivate stealth mode.
	This quickly cycles and sets control of each party member
	so the stealth visual effect is removed from each character
	then returns back to the original controlled character. 
*/

void SetStealth(object oFM)
{
	SetOwnersControlledCompanion(GetFirstPC(FALSE), oFM);
	SetActionMode(oFM, ACTION_MODE_STEALTH, FALSE);
}

void BackToStart(object oPC)
{
	SetOwnersControlledCompanion(GetFirstPC(FALSE), oPC);
}

void main()
{
	object oPC = GetFirstPC(FALSE);
	object oFM = GetFirstFactionMember(oPC, FALSE);
	float fDelay = 0.0f;
	
	while (GetIsObjectValid(oFM))
	{
		DelayCommand(fDelay, SetStealth(oFM));
		fDelay += 0.1f;
		oFM = GetNextFactionMember(oPC, FALSE);
	}
	
	DelayCommand(fDelay, BackToStart(oPC));
}

Not perfect, but I think it’s what you’re looking for.

2 Likes

Thanks guys! I’ll try this out. :slightly_smiling_face:

@travus, the stealth_stop script I would have liked if it wasn’t run from a conversation. However, I can see nothing in the script that indicates that it must be run from a conversation. I would rather this script was run on a trigger. I’ll test it and see it works like that too.

Ok, so I modified the stealth_stop script. No problems there. It works even if not in a conversation now.

However, the first script just kind of worked. It’s odd. There are quite a lot of companions in the party at this time in the module. They are 6 characters if you include the PC. 4 of them went into stealth mode with @travus script, but one of the companions plus the PC didn’t. Maybe this thing (this game in general) is just a bit buggy. I’ll try it once more and see what happens.

Edit: Tried again, and the EXACT same thing happens. The exact same companion won’t go into stealth mode and the PC won’t enter stealth mode either. You can of course go to those to characters and enter stealth mode by hand but… Looking into it a bit more, it turns out it’s the conversation owner that won’t go into stealth mode as well as the PC.

So, I did another test. I changed float fDelay = 0.0f; to float fDelay = 1.0f;. Now, everyone went into stealth mode, but the same bug I talked about in my first post here happens: The PC goes into stealth mode and directly exits it for some odd reason. The others remain in stealth mode, though.

Yet another 2 tests: I took away the DelayCommand(fDelay, BackToStart(oPC)); just to see what would happen. First test: It circled through the characters and the one in stayed upon, the one selected if you will, went into stealth mode and exited right of the bat. Second test: It did the same, but now three characters exited stealth mode right of the bat (including the one it landed upon, the one selected at the moment).
This is so weird.

That is curious. I tested these scripts from both a convo and a trigger with a large party and they both worked. Although, I highly recommend that if using it from a trigger that you add code so that it fires only once.
Try using the start script from a trigger. Does it still do the same as if fired from a convo?

I tried starting this from a generic trigger instead, and now it works flawlessly. I wonder why that is? This is your code with my modification on the generic trigger:

// stealth_start
/*
	Run this from the last node of a convo.
	This sets the entire party to stealth mode active.
	This quickly cycles and sets control of each party member
	so the stealth visual effect is applied to each character
	then returns back to the original controlled character. /script by travus	
*/

void SetStealth(object oFM)
{
	SetOwnersControlledCompanion(GetFirstPC(FALSE), oFM);
	SetActionMode(oFM, ACTION_MODE_STEALTH, TRUE);
}

void BackToStart(object oPC)
{
	SetOwnersControlledCompanion(GetFirstPC(FALSE), oPC);

}

void main()
{

	object oEnter = GetEnteringObject();
	
	//object oTrigger = OBJECT_SELF;
	
	if(!GetIsPC(oEnter)) return;
	
	if(GetLocalInt(OBJECT_SELF,"Done")) return;
	
	//DestroyObject(oTrigger, 5.0);
		
	SetLocalInt(OBJECT_SELF,"Done",1);


	object oPC = GetFirstPC(FALSE);
	object oFM = GetFirstFactionMember(oPC, FALSE);
	float fDelay = 1.0f;
	
	while (GetIsObjectValid(oFM))
	{
		DelayCommand(fDelay, SetStealth(oFM));
		fDelay += 0.1f;
		oFM = GetNextFactionMember(oPC, FALSE);
	}
	
	DelayCommand(fDelay, BackToStart(oPC));
}

However, I really want the stealth to start at the end of a conversation. When starting this conversation, I use the same generic trigger, but with a different script looking like this:

#include "ginc_ipspeaker"


void main()
{
    object oPC1 = GetEnteringObject();

    if (!GetIsPC(oPC1)) return;
	
	if(GetLocalInt(OBJECT_SELF,"Done")) return;
  
  	object oPC = GetFirstPC(FALSE);
  
 	object oFactionLeader = GetFactionLeader(oPC);
	
	SetLocalInt(OBJECT_SELF,"Done",1);
	
	AssignCommand(oFactionLeader, ClearAllActions());
	
  	SetCutsceneMode(oFactionLeader);
	

 
  	CreateIPSpeaker("loreen", "c_al_partytalk", GetLocation(GetFirstPC()), 0.5f);

	
}

I’m wondering…could it have something to do with ClearAllActions? I’ll try and remove that and see what happens.

I tried another variation of the script triggering the conversation. Same thing happens after the conversation though. The PC and the owner of the conversation won’t go into stealth mode. I don’t know what’s going on.

#include "ginc_ipspeaker"


void main()
{
    object oPC1 = GetEnteringObject();

    if (!GetIsPC(oPC1)) return;
	
	if(GetLocalInt(OBJECT_SELF,"Done")) return;
  
  	object oPC = GetFirstPC(FALSE);
	object oLoreen = GetNearestObjectByTag("loreen");
  
 	object oFactionLeader = GetFactionLeader(oPC);
	
	SetLocalInt(OBJECT_SELF,"Done",1);
	
	AssignCommand(oFactionLeader, ClearAllActions());
	AssignCommand(oLoreen, ClearAllActions());
	
  	SetCutsceneMode(oFactionLeader);
	
	AssignCommand(oLoreen, ActionStartConversation(oFactionLeader, "c_al_partytalk", FALSE, FALSE, TRUE, FALSE));
 
  	//CreateIPSpeaker("loreen", "c_al_partytalk", GetLocation(GetFirstPC()), 0.5f);

	
}

I had to use ClearAllActions for the conversation to even start when using ActionStartConversation. I’m at a loss here.

I found some possible loopholes in the stealth_start script that could possibly cause issue. Here’s the fixed version which I tested using your second variation convo start script. Everything worked - fingers crossed.

// stealth_start
/*
	Place this in the last node of a convo.
	This sets the entire party to stealth mode active.
	This quickly cycles and sets control of each party member
	so the stealth visual effect is applied to each character
	then returns back to the original controlled character. 	
*/

void SetStealth(object oFM)
{
	if (GetAssociateType(oFM) == ASSOCIATE_TYPE_NONE ||
		GetAssociateType(oFM) == ASSOCIATE_TYPE_FAMILIAR)
	{
		SetOwnersControlledCompanion(GetFirstPC(FALSE), oFM);
	}
	
	SetActionMode(oFM, ACTION_MODE_STEALTH, TRUE);
	
	if (GetAssociateType(oFM) == ASSOCIATE_TYPE_HENCHMAN ||
		GetAssociateType(oFM) == ASSOCIATE_TYPE_ANIMALCOMPANION ||
		GetAssociateType(oFM) == ASSOCIATE_TYPE_SUMMONED)
	{
		SetOwnersControlledCompanion(GetFirstPC(FALSE), GetMaster(oFM));
	}
}

void BackToStart(object oPC)
{
	SetOwnersControlledCompanion(GetFirstPC(FALSE), oPC);
}

void main()
{
	object oPC = GetFirstPC(FALSE);
	object oFM = GetFirstFactionMember(oPC, FALSE);
	float fDelay = 0.0f;
	
	while (GetIsObjectValid(oFM))
	{
		if (!GetActionMode(oFM, ACTION_MODE_STEALTH)) 
		{		
			DelayCommand(fDelay, SetStealth(oFM));
			fDelay += 0.2f;
		}
		
		oFM = GetNextFactionMember(oPC, FALSE);
	}
	
	DelayCommand(fDelay, BackToStart(oPC));
}
2 Likes

Thank you so much, @travus!

I used your latest script, and at first it didn’t quite work. Same error (the owner of the conversation and the PC wouldn’t go into stealth mode). Then I again changed the float fDelay = 0.0f; to 1.0f like I did before. This time only the PC wouldn’t go into stealth mode. Then I tried another thing. In my conversation, I had it set to Multiplayer Cutscene TRUE (I hadn’t noticed that) and NWN1-style Dialogue TRUE. I usually mix NWN1 style conversations with NWN2 style, to make it a more diverse experience. When switching to NWN2 style dialogue and running your script on the last node, but with 1.0f delay, it worked like a charm.

In another case in my module where I use special UI thing that 4760 helped me with, I got the same problem with it not working properly because of NWN1 style conversation instead of the NWN2 style. Maybe that style is somehow buggy? Anyone know anything about that, or have had similar experiences?

Edit: One thing I haven’t thought of before is, even if you don’t have text on the last node, and it’s a red node, in NWN1 style conversation you still have to click “Continue” for it to close the dialogue, whereas in NWN2 style if you don’t have anything in the last node, as it just exits the conversation automatically. Maybe clicking that last node somehow interfers with the script being run? Maye you @travus, @kevL_s, @4760 or @Lance_Botelle, who are all very good at scripting, know anything more about this?

Ok, once more I find that NWN2 is a weird and buggy game. I thought everything was well, but when testing another two times, the PC exited stealth mode right of the bat.

I had gone back to my original CreateIPSpeaker, but now I changed it back to the script you see 2 posts above this one, where I use ActionStartConversation. Tested this 4 times, and everytime it worked, so hopefully this will have solved it, but who knows. I’ve thought things were solved before only to experience an old bug reappearing. Oh, well…the player will still know he has to enter stealth mode (probably) so it should be no big problem. You can always order your character to enter stealth by hand.

1 Like

last node can be bothersome …

Could be that that is causing the problems then.

sometimes i just add a blank node (without scripts) at the end of dialog – depends whether it’s a PC-node or NPC-node etc. I had it worked out years ago, how to end dialogs safely, but have forgotten and just deal w/ issues as they seldom arise.

anyway, not saying that’s the case here; just that it could be: beware scripts on end-nodes …

( and other things you pointed out like MultiplayerCutscene and Nwn1-style )

3 Likes

KevL wrote exactly what I would have written! :slight_smile:

1 Like

@Lance_Botelle - So, do you happen to know if it’s more safe to end on a blank NPC node or a blank PC node? And do you know why NWN2 style dialogue seems (at least in two cases for me) safer for these kinds of things?