OnClientEnter question

“if it is not a player controled character at the moment that is entering the object then exit the script.”

that s what is written in those 2 lines.

Yes, of course. I know. What do you mean? :melting_face:

When you load a save and enter the area, the player controlled character is entering the area.

and you exit the script and don’ t execute what’s after so it’s normal that nothing happens

What? :expressionless:

Did you actually read my previous posts?

EDIT: I know what the script does. That’s not the problem here. Again:

I’m no scripter so I might be talking nonsense but I think you’re both looking at this from different angles as I’m a bit confused too.

Is it that you enter the area then save, reload and the script isn’t running any more ? Which probably has something to do with the computer thinking I’ve already done that and nobody’s entering because you’re already in, so why do it again. Maybe the integer is just stored differently and the on enter is a one hit wonder.

Or that you save from outside the area then enter after reloading and it doesn’t work now because that’s weird and means that any save outside the area will stop it working which can’t be right.

@andgalf

Many years ago I also noticed some strange behaviour with reloading a game. So much so that I even (at one time) altered an XML that forced a player to reload from the main menu rather than the base load.

I have forgotten the specifics, but your comments sound familiar to me. I’ll try to locate the post and link it here, and/or try to recall what I actually did to avoid the issue.

Here’s that post I was referring to …

Maybe you can test your situation by the way you reload the game … Try reloading from the Main Menu and not the other way … Make sense?

HOWEVER, since writing that post, I have reverted back to the original XML and allow loading as usual now, so maybe I found an alternative solution to the problem. The point is, though, I also discovered some unusual things happening on the Load Game (that was not via the Main Menu). I will try to see what else I may have done and post back.

EDIT: OK, I found out what was happening by the looks of it, as I have this note in my own area OnClientEnter script notes … Unfortunately, I cannot find the text I quoted.

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// QUOTE: THIS SCRIPT FIRES AFTER THE AREA HAS FINISHED LOADING - SO WILL ONLY FIRE FOR ONE PLAYER
// UNLESS MP PLAYERS ARE JOINING AT A LATER TIME. (ONCE IN GAME ONLY FIRES ONCE PER AREA LOAD FOR HOST!)
// THEREFORE, WE NEED TO CONSIDER USING ALB_AREA_ENTER FOR CODE THAT THEY ALL NEED EACH AREA LOAD
// I ALSO BELIEVE THAT THE ALB_AREA_ENTER (ON AREA ENTER) FIRES *BEFORE* THIS SCRIPT THEN!
// !!!!!!!! MOSTLY TRIGGERS ONLY WHEN THE LEAD PLAYER ENTERS THE AREA !!!!!!!!!!!!!!!!!!
// !!!!! NB: THE DM COULD BE THE HOST, SO WE NEED TO CHECK VIA PC LEADER !!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

I do not include this condition in my own area OnClientEnter, as I believe the script is supposed to run as soon as the area loads, and so we can assume oPC is the main PC anyway. Maybe (for some reason) the condition is not always reliable from this point of view.

i.e. It’s safe not to include this condition check … as the PC will be the host regardless, I suspect. (Or maybe another player in a MP game.)

Furthermore, if you want to ensure an area entry script fires for every creature, you need to use the Area On Enter Script to do that. The OnClientEnter is used more for area setup and variables rather than anything PC specific.

For Players (Main PC’s only): OnClientEnter
For any PC (inc companions): OnEnter

1 Like

Could be, yes. I thought that the game would consider one entering the area when you load the area, but that seems not to be the case…At least I don’t think so, but that’s what this whole thing is about. This is what I wanted to know, what all my questions were about. I would want to know the answer to this about how the game considers things in this case.

Yeah, maybe. I always thought that if you do the On Area Enter thing, the game will run this script as soon as any character moves in an area, and thus slows the game down if you have many areas with such a script, and the On Client Area thing runs when a player character is entering the area. Me including this script with if(!GetIsPC(oPC)) return; is maybe redundant because the game only runs this script when a player enters the area anyway so it might be unnecessary to check this.
In any case, by me including this, perhaps, unnecessary thing, I noticed the OnClientArea script is not run if you load an area your character is already in. I always assumed since the game says it loads an area, when you load a savegame that is, that that way it will always run this script, but maybe it only runs that type of script when you teleport your character from one area to another, and not when you are already there, even if you load a savegame.

EDIT: Since NWN2 loves delays in its scripts. Maybe, just maybe, if I would do a delay on the whole script, it would run even when you load a game (and the character is in that area). I think I’ll test that.

EDIT2: I tested the delay. That changed nothing. I even tested loading from the main menu but that didn’t change anything either.

So, it seems that to me, in conclusion: When loading a savegame with an area your main character is already in, that doesn’t count as the main character entering the area although the game has always made me think that it did. Only when teleporting from another area, and the game loads the new area, does it seem to count as the character “enters” the area.

EDIT3: No, scratch that, this can’t be right… it’s still a very odd. If OnClientEnter is only supposed to run when the main character enters the area, it shouldn’t run at all when loading a savegame, and it still does run for me. However, if I put the

object oPC = GetEnteringObject();

if(!GetIsPC(oPC)) return;

it exits since it doesn’t recognize the main character entering the area…but it’s only supposed to run when the main character enters the area… :woozy_face: :crazy_face:

So, the way I have it working on one area now (I have tested it) is by doing the following:

  1. I wrap the whole OnClientEnter script in a function.
  2. I run that function in the main script by doing a 0.3 second delay.
  3. In the script I write like this instead, and that seems to work great:
object oPC1 = GetFirstPC();
object oArea = GetObjectByTag("Forest");

if(GetArea(oPC1) != oArea) return;

This way the game doesn’t check for any entering of the area, it just looks for if the main character is already, at the moment, in the area. For that to work properly, we need a delay to really make sure the main character is loaded into the area when the check comes.

@andgalf

This is the exact same anomaly I was encountering when I posted that post I linked to above.

However, since that time, I have rewritten many of my OnLoad and OnArea scripts, which may now be working more efficiently. Because, my main PC now always fires the area OnClientEnter script. Debug feedback shows the script firing be it from a normal load, or a save and a reload, regardless of where I reload from.

i.e. I recognise the issue you appear to have encountered, but I no longer have that issue.

To repeat, the OnClentEnter always fires with debug feedback with this line of code … NB: There are some minor conditions in there to do with my setup, but this debug feedback always returns the main PC.

I suppose it may be possible that my function GetMainPC is forcing a MainPC return compared to what just the GetFirstEnteringPC does, but it still relies on that function getting a valid PC in the first place. Also, my SendMessageToAllPCs function just ensures I send the message to all valid players.

// ESSENTIAL TO USE THIS FUNCTION HERE !!!!
	object oPlayer = GetFirstEnteringPC();
			
	// IF SCRIPT CALLED VIA GUI_CLEARGUI MODULE SELECTION
	if(oPlayer == OBJECT_INVALID){oPlayer = OBJECT_SELF;}	
		
	// MAIN PC HAS BEEN AVAILABLE SINCE ALB_AREA_ENTER CODE
	object oMainPC = GetMainPC(oPlayer);
			
	SendMessageToAllPCs(CCBLUE + GetName(oPlayer) + " <<< AREA ON ENTER FIRED >>>");

At the very least, you should be able to send debug feedback to detect the OnClientEnter script is firing every time. If it is not, try posting your full script so it can be looked over.

Further down my same script, I also have a similar setup, but that is to ensure all players in a MP game have entered the area before firing another script. I don’t think this is required for a SP game.

I think I already did those debug messages before, BUT, I also think that I was always using the

object oPC = GetEnteringObject();

if(!GetIsPC(oPC)) return;

code, and that, as has been proven now, does apparently screw things up.

Maybe I’ll just do a test, for curiocity, with using GetFirstEnteringPC instead of GetEnteringObject.

@andgalf

Yes, I would test this too, as I believe your condition check (and GET function used) was the issue in your case.

i.e. It is essential to use this in this script …

object oPlayer = GetFirstEnteringPC();

Ok, this is interesting. I now tested this:

object oPC = GetFirstEnteringPC();
if(!GetIsPC(oPC))return;

and with that, with loading a savegame that is, it didn’t run properly.

So, to me, it now seems like the game runs the OnClientEnter if you teleport to the area, or if you load a savegame with the area, but it doesn’t It still runs the script though, but again, it doesn’t recognize the player character as entering the area when loading a savegame.

Do not use this. And try again.

It sounds like mine may work due to me saving the MainPC as an object via the MODULE OnClientEnter … My GetMainPC function retrieves the MainPC object stored.

Perhaps that work the trick I discovered that resolved my issues.

i.e. I have this script (part) that fires on my OnClientEnter for the module.

object oPlayer = GetEnteringObject();	
	object oHOST = GetTheGameHost();
	
	// SendMessageToAllPCs("MOD ON CLIENT ENTER FIRED FOR " + GetName(oPlayer));
	
	// CLOSE ANY PLEASE WAIT GUIS (HOST ONLY ACTIVATEABLE)
	CloseGUIScreen(oPlayer, "GeneralInfoGUI"); 
	
	// TEMP PREVENT ANY PLAYER TRANSITIONS
	SetGlobalInt("PLAYERENTERING", 1);
	
	if(oPlayer == oHOST)
	{
		// ENSURE MAIN PC HAS ITSELF AS MAIN PC
		if(!GetIsDM(oPlayer)){SetLocalObject(oPlayer, "MYBOSS", oPlayer);}
	}

Player object stored via …

SetLocalObject(oPlayer, “MYBOSS”, oPlayer);

My GetMainPC effectively is this …

object oPC = GetLocalObject(oPlayer, “MYBOSS”);

Where oPlayer is the one in the above area OnClientEnter.

I don’t have to test that since I know that the script will run then…I mean, I tested that before.

However, I don’t think I really tested the validity of the oPC in that case.

I did another test:

object oPC = GetFirstEnteringPC();
object oPC1 = GetFirstPC();

if(GetIsObjectValid(oPC))
{

SendMessageToPC(oPC1,"The object GetFirstEnteringPC is valid!");

}

When loading the game I didn’t get the message. So, again, it seems that when loading a savegame the game doesn’t recognize the main character as entering the area.
And this script you see above, I did with a delay of 0.3 seconds.

Probably right. I haven’t mine setup like that.

OK, so maybe this is the issue I also discovered … and my “FIX” was to do what I said above …

Store the MainPC as an object via the OnClientEnter for the module.
And then retrieve from the OnClientEnter for the area.

That makes sense now then … and sorry it took me a while to remember exactly what I had done to fix this … At least you now know. :slight_smile:

Well, I don’t think I’ll do it like that. I will just have to keep in mind that the game doesn’t check for entering main character when loading a savegame in the same area.

EDIT: At a second a thought there was something wrong with the function GetIsPC but that doesn’t seem to be the case, which is good.

Exactly … But, you may find a very simple script on your module OnClientEnter a very easy solution so you don’t have to keep remembering.

It may be something that you will benefit from in the future, if not immediately now.

Assuming this is the issue …

FOR SINGLE PLAYER ONLY …

MODULE ON CLIENT ENTER

void main() 
{
	object oPlayer = GetEnteringObject();	
	SetLocalObject(oPlayer, "MYBOSS", oPlayer);
}

AREA ON CLIENT ENTER

void main() 
{
	object oPlayer = GetFirstEnteringPC();	
	oPlayer = GetLocalObject(oPlayer, "MYBOSS");
}

A totally unrelated thing: How do you, when posting here on the vault, get a line crossing the text? I’ve seen others do that, but I can’t seem to find that function.

Scratching … Two tildes … ~~ YOUR TEXT ~~ (But without the gaps between text and tildes.)

Scratch this!