Hide Main PC through XML coding

I have a vague memory of @Lance_Botelle solving this somehow in some way in a thread where we discussed this maybe 2 years ago, but I can’t find it.

I have a situation in my module where I would like it so that the Main PC is somehow “invisible” (the clicking aspect with the portrait and all), and the player is forced to just controll the companions in the party. I think this might be close to impossible, but then again, I have some vague memory of @Lance_Botelle showing some video where he had accomplished this.

The only thing I could find when trying to locate earlier threads is this:

Maybe what I remember is Lance hiding all the portraits and showing that in a video.

EDIT: Lance found the video and showed me. He was hiding all the portraits. I will still put this thread here if someone somehow has a solution.

2 Likes

So…Lance told me to use the stock script gb_player_ud and make a new version of that as a campaign script. So that when the player tries to controll the PC it reverts to one of the companions instead. So, at the end of a dialogue, I change the controlled character to one of the companions. That works. But then when switching to the main PC, the game won’t switch to the companion even though I’m using my version of gb_player_ud. It just won’t switch to the companion. The script is running and all that, but somehow what I have coded doesn’t do what I want it to. For some odd reason the game seems to think that oNewMain is the same as the default PC. I have tried with an if statement using GetControlledCharacter but then the game engine whines about it looking for an integer…Uugh! What small mistake am I making here? I don’t get it. What function am I supposed to use for this to work. Darn stupid scripting and all it’s peculiarities in needing to use just the right thing for anything to work!

// gb_player_ud
/* 
	 user defined events template
*/  
// ChazM 9/5/06 don't have leader follow himself
// BMA-OEI 09/12/06 -- Added EVENT_PLAYER_CONTROL_CHANGED handler
// MDiekmann 8/7/07 - Modified to run a custom user defined script based on the tag if one exists

#include "ginc_companion"
#include "ginc_debug"
#include "ginc_overland"
#include "x0_i0_assoc"
#include "hench_i0_assoc"
// 		this includes: GetFollowDistance()

void ResetPC(object oNewMain)
{
	object oPC = SetOwnersControlledCompanion(OBJECT_SELF, oNewMain);		
}
	
void main()
{
	string sMyTag = GetTag(OBJECT_SELF);		
	
    int iEvent = GetUserDefinedEventNumber();
//	Jug_Debug(GetName(OBJECT_SELF) + " event num " + IntToString(iEvent));

	//execute custom user-defined script from local string if it exists
	string sUDScript=GetLocalString(OBJECT_SELF, "ud_script");
	if (sUDScript != "")
	{
		ExecuteScript(sUDScript, OBJECT_SELF);
	}
	
    switch (iEvent)
	{
		case EVENT_HEARTBEAT: 	// 1001
			break;	

		case EVENT_PERCEIVE: 	// 1002
			break;	

		case EVENT_END_COMBAT_ROUND: 	// 1003
			break;	

		case EVENT_DIALOGUE: 	// 1004
			break;	

		case EVENT_ATTACKED: 	// 1005
			break;	

		case EVENT_DAMAGED: 	// 1006
			break;
	
		case EVENT_DISTURBED: 	// 1008
			break;	

		case EVENT_SPELL_CAST_AT: 	// 1011
			break;	
			
		case EVENT_PLAYER_CONTROL_CHANGED:
		{
		
			if(GetGlobalInt("chicken"))
			{
				//object oOldActor = GetFirstPC();
				object oNewMain = GetFirstPC(FALSE);
				DelayCommand(0.1, ResetPC(oNewMain)); 	
					
			}
			break;
		}
		
		 // 2052
		case EVENT_TRANSFER_PARTY_LEADER:
		{
			if(GetIsOverlandMap(GetArea(OBJECT_SELF)))
			{
				PrettyDebug("gb_player_ud firing for" + GetName(OBJECT_SELF));
				object oOldActor = GetLocalObject(GetModule(), "oPartyLeader");
				if(GetIsPC(OBJECT_SELF) && oOldActor != OBJECT_SELF)
				{
				
					if(GetCommandable(OBJECT_SELF) && !GetIsDead(OBJECT_SELF) &&
				  	  (GetIsRosterMember(OBJECT_SELF) || GetIsOwnedByPlayer(OBJECT_SELF)) ) 
					{
						SetPartyActor(OBJECT_SELF);
					}
				
					else
						SetPartyActor(oOldActor, OBJECT_SELF);
				}
			}
			
			if(GetAssociateState(NW_ASC_MODE_PUPPET) == TRUE)
				break;
				
//			Jug_Debug(GetName(OBJECT_SELF) + " handle player control change");
			HenchHandlePlayerControlChanged(OBJECT_SELF);
			break;
		}			
	}
}

@andgalf

I sent you a PM.

Basically, try GetFirstPC (TRUE).

Not at main computer to test.

1 Like

Doesn’t make sense to me. I mean, I want to switch the controlled character to every other character BUT the main PC. I’ll try it anyway even if it defies all logic.

EDIT: Just as I thought. At least this time my logic was the same as the game’s logic. Now when using GetFirstPC(TRUE) it switches back to the main PC and that’s the opposite of what I want. How do I get the game to switch back to the last controlled character instead? I don’t get it? Why doesn’t it work?

@andgalf

Ok, I hear you and see it now. Not easy when scrolling on phone.

I’ll try to look more closely when I get back and can do a couple of tests with your version of the script next to my own. It should be doable when we pass the right code.

Worst case scenario, may have to wait until Monday, if too tired tonight.

1 Like

Alright, so I kind of solved this (not happy with my solution though) in my own convoluted way, by doing the script like this instead:

// gb_player_ud
/* 
	 user defined events template
*/  
// ChazM 9/5/06 don't have leader follow himself
// BMA-OEI 09/12/06 -- Added EVENT_PLAYER_CONTROL_CHANGED handler
// MDiekmann 8/7/07 - Modified to run a custom user defined script based on the tag if one exists

#include "ginc_companion"
#include "ginc_debug"
#include "ginc_overland"
#include "x0_i0_assoc"
#include "hench_i0_assoc"
// 		this includes: GetFollowDistance()

void ResetPC(object oNewMain)
{
	object oPC = SetOwnersControlledCompanion(OBJECT_SELF, oNewMain);		
}

void SwitchPC()
{

object oPC = GetFirstPC();
object oNewActor;

object oSabrina = GetObjectByTag("sabrina");
object oCatherine = GetObjectByTag("catherine");
object oNankun = GetObjectByTag("nankun");
object oTeala = GetObjectByTag("teala");
object oFreya = GetObjectByTag("freya");
object oEsfiza = GetObjectByTag("esfiza");
object oAstaxos = GetObjectByTag("astaxos");
object oBargoram = GetObjectByTag("bargoram");

	if(GetFactionEqual(oPC,oSabrina))
	{
	
		 oNewActor = oSabrina;	

	}

	else if(GetFactionEqual(oPC,oCatherine))
	{
	
		 oNewActor = oCatherine;	

	}
	
	else if(GetFactionEqual(oPC,oTeala))
	{
	
		 oNewActor = oTeala;	

	}
	
	else if(GetFactionEqual(oPC,oFreya))
	{
	
		 oNewActor = oFreya;	

	}
	
	else if(GetFactionEqual(oPC,oEsfiza))
	{
	
		 oNewActor = oEsfiza;	

	}
	
	else if(GetFactionEqual(oPC,oAstaxos))
	{
	
		 oNewActor = oAstaxos;	

	}
	
	else if(GetFactionEqual(oPC,oBargoram))
	{
	
		 oNewActor = oBargoram;	

	}
	
	else
	{
	
		SendMessageToPC(oPC,"You have created a serious bug by not having companions in your party!! Please reload!!");
		return;
	}
	
	if(GetIsObjectValid(oNewActor))
	{
		SetOwnersControlledCompanion(oPC,oNewActor);
	}


}
	
void main()
{
	string sMyTag = GetTag(OBJECT_SELF);		
	
    int iEvent = GetUserDefinedEventNumber();
//	Jug_Debug(GetName(OBJECT_SELF) + " event num " + IntToString(iEvent));

	//execute custom user-defined script from local string if it exists
	string sUDScript=GetLocalString(OBJECT_SELF, "ud_script");
	if (sUDScript != "")
	{
		ExecuteScript(sUDScript, OBJECT_SELF);
	}
	
    switch (iEvent)
	{
		case EVENT_HEARTBEAT: 	// 1001
			break;	

		case EVENT_PERCEIVE: 	// 1002
			break;	

		case EVENT_END_COMBAT_ROUND: 	// 1003
			break;	

		case EVENT_DIALOGUE: 	// 1004
			break;	

		case EVENT_ATTACKED: 	// 1005
			break;	

		case EVENT_DAMAGED: 	// 1006
			break;
	
		case EVENT_DISTURBED: 	// 1008
			break;	

		case EVENT_SPELL_CAST_AT: 	// 1011
			break;	
			
		case EVENT_PLAYER_CONTROL_CHANGED:
		{
		
			if(GetGlobalInt("chicken"))
			{
				//object oOldActor = GetFirstPC();
				SwitchPC();
				object oNewMain = GetFirstPC(FALSE);
				DelayCommand(0.1, ResetPC(oNewMain)); 	
					
			}
			break;
		}
		
		 // 2052
		case EVENT_TRANSFER_PARTY_LEADER:
		{
			if(GetIsOverlandMap(GetArea(OBJECT_SELF)))
			{
				PrettyDebug("gb_player_ud firing for" + GetName(OBJECT_SELF));
				object oOldActor = GetLocalObject(GetModule(), "oPartyLeader");
				if(GetIsPC(OBJECT_SELF) && oOldActor != OBJECT_SELF)
				{
				
					if(GetCommandable(OBJECT_SELF) && !GetIsDead(OBJECT_SELF) &&
				  	  (GetIsRosterMember(OBJECT_SELF) || GetIsOwnedByPlayer(OBJECT_SELF)) ) 
					{
						SetPartyActor(OBJECT_SELF);
					}
				
					else
						SetPartyActor(oOldActor, OBJECT_SELF);
				}
			}
			
			if(GetAssociateState(NW_ASC_MODE_PUPPET) == TRUE)
				break;
				
//			Jug_Debug(GetName(OBJECT_SELF) + " handle player control change");
			HenchHandlePlayerControlChanged(OBJECT_SELF);
			break;
		}			
	}
}

We posted the same second apparently.

@andgalf

Double post. Yes. :grinning:

You may end up working it out now before I can take a closer look myself.

The point being, I believe this is the best way to approach what you want to do. I’m just not at PC to do the code and check it. :thinking:

Being realistic, I don’t think I’m going to be able to get to it tonight, but I do think you’ll find the solution by the time I get to it.

If I don’t have time (likely), I’ll check back Monday to see if you got it resolved.

3 Likes

I understand. Even if I have a convoluted solution as of now, I really wish there was a better simpler one.

2 Likes

interesting idea, can you see what it looks like? is it possible to make the pc play as an npc while hiding the pc itself?

It’s not possible to hide the PC. The only thing Lance has managed to do through XML coding is hide all the portraits on the right side of the screen and at the same time switch control to one of the companions .

For my case, that wasn’t an alternative. So instead he showed me a way of editing the stock gb_player_ud script, so that when the player clicks on the PC portrait, it immediately switches back to one of the companions instead.

2 Likes

@andgalf

It was too late for me to look at Saturday, but I believe this will work well for you … There was a key local var check I had forgotten to include on my initial post, which I had forgotten about until I checked again.

// gb_player_ud
/* 
	 user defined events template
*/  
// ChazM 9/5/06 don't have leader follow himself
// BMA-OEI 09/12/06 -- Added EVENT_PLAYER_CONTROL_CHANGED handler
// MDiekmann 8/7/07 - Modified to run a custom user defined script based on the tag if one exists

#include "ginc_companion"
#include "ginc_debug"
#include "ginc_overland"
#include "x0_i0_assoc"
#include "hench_i0_assoc"
// 		this includes: GetFollowDistance()

void ResetPC(object oMainPC, object oPrevious)
{
	SetLocalInt(oMainPC, "STOPINFO", 1);
	DelayCommand(0.1, DeleteLocalInt(oMainPC, "STOPINFO")); // REQUIRED HERE TOO
	SetOwnersControlledCompanion(OBJECT_SELF, oPrevious);		
}

	
void main()
{	
    int iEvent = GetUserDefinedEventNumber();
//	Jug_Debug(GetName(OBJECT_SELF) + " event num " + IntToString(iEvent));

	//execute custom user-defined script from local string if it exists
	string sUDScript=GetLocalString(OBJECT_SELF, "ud_script");
	if (sUDScript != "")
	{
		ExecuteScript(sUDScript, OBJECT_SELF);
	}
	
    switch (iEvent)
	{
		case EVENT_HEARTBEAT: 	// 1001
			break;	

		case EVENT_PERCEIVE: 	// 1002
			break;	

		case EVENT_END_COMBAT_ROUND: 	// 1003
			break;	

		case EVENT_DIALOGUE: 	// 1004
			break;	

		case EVENT_ATTACKED: 	// 1005
			break;	

		case EVENT_DAMAGED: 	// 1006
			break;
	
		case EVENT_DISTURBED: 	// 1008
			break;	

		case EVENT_SPELL_CAST_AT: 	// 1011
			break;	
			
		case EVENT_PLAYER_CONTROL_CHANGED:
		{
		
			// MAIN PC TO TRACK VARIABLES
			object oMainPC = GetFirstPC(TRUE);
				
			//if(GetGlobalInt("chicken"))				// TOO GLOBAL			
			//if(GetLocalInt(OBJECT_SELF, "chicken"))	// BETTER TO BE TARGETTED
			if(GetFirstPC() == OBJECT_SELF && GetGlobalInt("chicken"))				// IF POLY ONLY EVER ON MAIN PC (& USING YOUR GLOBAL)
			{
				object oPrevious = GetLocalObject(oMainPC, "PREVIOUSPC");
				
				// DELAY ALLOWS A POTENTIAL DOUBLE SWITCH WHEN "FIXING" (SHOULD ALREADY BE REMOVED, BUT FORCE HERE TOO!)
				if(GetLocalInt(oMainPC, "STOPINFO")){DelayCommand(0.1, DeleteLocalInt(oMainPC, "STOPINFO")); return;}
				
				DelayCommand(0.1, ResetPC(oMainPC, oPrevious)); 	
					
			}
			
			else
			{
				SetLocalObject(oMainPC, "PREVIOUSPC", OBJECT_SELF);	
			}
			
			break;
		}
		
		 // 2052
		case EVENT_TRANSFER_PARTY_LEADER:
		{
			if(GetIsOverlandMap(GetArea(OBJECT_SELF)))
			{
				PrettyDebug("gb_player_ud firing for" + GetName(OBJECT_SELF));
				object oOldActor = GetLocalObject(GetModule(), "oPartyLeader");
				if(GetIsPC(OBJECT_SELF) && oOldActor != OBJECT_SELF)
				{
				
					if(GetCommandable(OBJECT_SELF) && !GetIsDead(OBJECT_SELF) &&
				  	  (GetIsRosterMember(OBJECT_SELF) || GetIsOwnedByPlayer(OBJECT_SELF)) ) 
					{
						SetPartyActor(OBJECT_SELF);
					}
				
					else
						SetPartyActor(oOldActor, OBJECT_SELF);
				}
			}
			
			if(GetAssociateState(NW_ASC_MODE_PUPPET) == TRUE)
				break;
				
//			Jug_Debug(GetName(OBJECT_SELF) + " handle player control change");
			HenchHandlePlayerControlChanged(OBJECT_SELF);
			break;
		}			
	}
}

Thanks for the reply! I might change my script, but I’ve gotten used to my version now and it seems to work quite well so…well, if I’m lazy I won’t change my script, otherwise I might.

@andgalf

I was not sure how all that faction checking worked for you … I mean if the player has (for example) Sabrina, Catherine and Bargoram in their party and are currently playing Bargoram, won’t the PC always default to the lowest in your checks (Sabrina in this example) as they would return TRUE as a faction member (I thought).

I.e. I think your script may only return the player back to the PC lowest in your list of PCs in your check that they have in the party. If, for example, the player has Sabrina, it will always return them to possess Sabrina and not necessarily the PC they were controlling.

But, I have not tested your script to be sure. The script I provided should always return the player to the PC they had been controlling when trying to switch. :slight_smile: (May help to avoid any confusion if what I say above is the case.)

@andgalf Thank you very much for your answer.
Well, this is not quite what I expected / hoped for.
it’s a pity that you can’t hide it completely - nevertheless, I think that maybe I can do something - with due skill.
I’ll try. If I succeed, I’ll post, and if not, then we have nothing to lose. Thank you all. :grinning:

You are totally correct that this is one of the caveats in my script at the moment, but I found it to be such a minor inconvenience that I let it be. As long as the player learns (and I think the player will learn that pretty quick) that he can’t choose his player character, all will be good. If he is stubborn and persists with choosing his own character, the game will switch back to the one at the top of my list in my script. But, again, no big deal, that’s why I, at the moment, let it be.

I agree that it is a pity, but there are some limitations to the game that is really hard to work around unfortunately.

@andgalf

No problem … your call … I was just working with simpler script and less confusion, which I know you usually like to consider. :grinning:

You’re right, of course. I’m just being lazy at the moment. If I notice that this bothers me too much, I will change to your version of the script.

1 Like

@lord_XD

Check this out for what was done … Ignore the PC shout outs on the reload, that’s just for testing purposes of seeing where they are.

1 Like