Aller au contenu

Photo

Forced Companion on World Travel


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

#1
andysks

andysks
  • Members
  • 1 645 messages

Hi all. They did this in the OC, but it seems quite complicated to me. Can anyone help me to achieve this? Like need to have Sand in order to travel to Port Last?



#2
kevL

kevL
  • Members
  • 4 056 messages
hey Andy,

To prevent travel:
in a dialog, you could use

gc_is_in_party("Sand")

or in a script
if (GetFactionEqual(GetFirstPC(), GetObjectByTag("Sand")) == TRUE)
- if not, then send a message, or fallthrough to a dialog-node, that says Sand has to be in the party.


Or do you want to bring up the roster menu, or perhaps do an auto-join that may require an increase in party size (like Shandra iirc )?

#3
andysks

andysks
  • Members
  • 1 645 messages

Hi KevL. Sandra like no. I have a 5 member party, and that shouldn't change here.

 

Also, prevent travel might cause confussion. Bringing up the roster menu is the way to go. Detailed explanation follows.

 

What I want, is if you've met 8 companions, and companion no.1 has a quest which tells you to go to a forest so to say. You try to travel there, but as the roster UI pops up, you use companions 2,3,4,5. Seeing as you excluded the one who's quest you want to do, the travel shouldn't happen but instead you get a message that this companion no.1 should be in party for that travel. This is one thought.

 

The second thought/method, you don't even get to select party for a message to happen. Once you try to travel to that forest, companion no.1 is forced in the party and greyd (unselectable for the time being). Meaning you get to choose 3 more, instead of all five. 

 

The messages they use in the OC in the style of "Sand should be in the party..." etc, are not necessary, but they are there on the script as strings I see.

// ka_hotspot_click_force
//
// Action script for when a hotspot is clicked on the worldmap.  Determines the location to send
// the party to.  This variant checks a global variable sCompVar, and if it's equal to nCheckValue, 
// fires a message box instead of sending the player on.  That message box is defined in this file 
// as well, in DisplayForceCompanionMessage.  The nMessage parameter chooses what message box to use.

// Each case here needs to do the following, in this order:
// 1. Set a global string "00_sLastForcedCompanion" to be the roster name of the companion you're forcing to join.
// 2. Display a message box.  Callback script is always gui_force_comp.

//void main declarations etc.

	case 1:
		//You must have Sand in your party in order to travel to Port Llast. Proceed?
		SetGlobalString("00_sLastForcedCompanion", "sand");
		DisplayMessageBox(oPC,178912, "", "gui_force_comp","",TRUE,"SCREEN_MESSAGEBOX_DEFAULT",66,"",67);
		break;

The parameters of the DisplayMessageBox

// oPC           - The player object of the player to show this message box to
// nMessageStrRef- The STRREF for the Message Box message.
// sMessage      - The text to display in the message box. Overrides anything
//               - indicated by the nMessageStrRef
// sOkCB         - The callback script to call if the user clicks OK, defaults
//               - to none. The script name MUST start with 'gui'
// sCancelCB     - The callback script to call if the user clicks Cancel, defaults
//               - to none. The script name MUST start with 'gui'
// bShowCancel   - If TRUE, Cancel Button will appear on the message box.
// sScreenName   - The GUI SCREEN NAME to use in place of the default message box.
//               - The default is SCREEN_MESSAGEBOX_DEFAULT
// nOkStrRef     - The STRREF to display in the OK button, defaults to OK
// sOkString     - The string to show in the OK button. Overrides anything that
//               - nOkStrRef indicates if it is not an empty string
// nCancelStrRef - The STRREF to dispaly in the Cancel button, defaults to Cancel.
// sCancelString - The string to display in the Cancel button. Overrides anything
//               - that nCancelStrRef indicates if it is anything besides empty string

And the gui_force_companion

Sorry for the long message. I just put the scripts here so that you don't search them on your own.

// gui_force_comp
//
// A companion is forced into the party, and the party gui is brought up.
// This is a callback script called from ka_hotspot_click_force.  The function DisplayForceCompanionMessage() defines
// the companion who gets forced into the party, setting it as a global variable.
	
// EPF 1/10/06
// BMA-OEI 8/31/06: Delay to DisplayGuiScreen, Use OBJECT_SELF as PC
// BMA-OEI 9/17/06: If there's room, force companion into party
// BMA-OEI 9/17/06: No longer displays Party Select ( Trigger already prompts Party Select )
// BMA-OEI 10/20/06: " " Unless opened in area other than Crossroad Keep
	
#include "ginc_companion"
#include "ginc_gui"

void main()
{
	object oPC = OBJECT_SELF;
	if ( GetIsPC(oPC) == FALSE ) return;

	object oFM;
	string sCompanion = GetGlobalString("00_sLastForcedCompanion");

	// BMA-OEI 9/17/06: If there's room, force companion into party
	int nPartyLimit = GetRosterNPCPartyLimit();
	int nNPCsInParty = GetNumRosterMembersInParty( oPC );
	
	// Party Limit hit, remove selectable companions
	if ( nNPCsInParty >= nPartyLimit )
	{
		RemoveRosterMembersFromParty( oPC, TRUE, FALSE );
		nNPCsInParty = GetNumRosterMembersInParty( oPC );
	}

	// Free slots available, add required companion
	if ( nNPCsInParty < nPartyLimit )
	{
		AddRosterMemberToParty( sCompanion, oPC );
		SetIsRosterMemberSelectable( sCompanion, FALSE );	
	}

/*
	AddRosterMemberToParty(sCompanion,oPC);
	SetIsRosterMemberSelectable(sCompanion,FALSE);
	
	oFM = GetFirstFactionMember(oPC,FALSE);
	while(GetIsObjectValid(oFM))
	{
		if(GetIsRosterMember(oFM) && GetIsRosterMemberSelectable(GetRosterNameFromObject(oFM)))
		{
			RemoveRosterMemberFromParty(GetRosterNameFromObject(oFM),oPC);
		}
		oFM = GetNextFactionMember(oFM,FALSE);
	}
*/

	// BMA-OEI 10/20/06: Unless opened in area other than Crossroad Keep
	// BMA-OEI 9/17/06: No longer displays Party Select ( Trigger already prompts screen )
	// BMA-OEI 8/31/06: Delay for GUI to update w/ spawned companion
	if ( GetTag( GetArea( oPC ) ) != "3070_sh_farm" )
	{
		DelayCommand( 0.5f, ShowPartySelect( oPC, TRUE, "", FALSE ) );
	}	
}

Seeing all this, I am lost :).



#4
kevL

kevL
  • Members
  • 4 056 messages
here's what it's doing:
- gets current roster limit
- gets current quantity of companions

- compares them, and if party is full
- removes all party members

- then adds the needed companion
- and shows the party select menu

(roughly)


So, show us your current actionScript for the particular worldMap hotSpot (from the Campaign editor), or a default actionScript that works without restriction as yet. Will try to force the NPC and pop the roster menu ...

#5
andysks

andysks
  • Members
  • 1 645 messages

Hmm, does quite some stuff I see. Let's see. These are the scripts I use.

 

This one is for the trigger. A copy actually from the trigger at Crossroad Keep.

#include "ginc_gui"

void main()
{
	object oPC = GetClickingObject();

	if ( !GetIsObjectValid(oPC) )
		oPC = GetEnteringObject();

	if(GetIsPC(oPC))
		ShowPartySelect( oPC, TRUE, "roe_hangout_world_map", TRUE );
}

The action script when we press on a hotspot follows.

#include "inc_roe_travel"

void main(string sTargetWaypoint, string sModule)

{
	DoTravel(sTargetWaypoint, sModule);

}	

Definition of DoTravel on the travel include library, Or a fraction of it. I hope I included the part in question. Seems like it.

void DoTravel(string sTargetWaypoint, string sModule)

{
	object oPC = GetFirstPC();
        // GetWaypointByTag won't work here
	object oTarget = GetObjectByTag(sTargetWaypoint); 
	
	
	// Check if the target exists in the current module
	//SendMessageToPC(GetFirstPC(FALSE), "testing for valid wp-object ...");
	if(GetIsObjectValid(oTarget))
	{
		
		// Target waypoint exists in current module
		// so jump the party to the target
		//SendMessageToPC(GetFirstPC(FALSE), "wp-object VALID");
		DelayCommand(1.2f,SinglePartyTransition(oPC, oTarget));
	}
	else
	{
		//SendMessageToPC(GetFirstPC(FALSE), "wp-object NOT valid");
		// Target waypoint does not exist in module so
		// load the appropriate module 
		// and jump the party to the target
		
		// Don't use this method. We need to save the Roster
		//LoadNewModule(sModule, sTargetWaypoint);
		
		// This saves the Roster and then calls LoadNewModule()
		DelayCommand(1.2f,SaveRosterLoadModule(sModule, sTargetWaypoint));
	}
}

At this point I need to mention that the comments are from ColorsFade. These are some nice and really stable scripts there :).



#6
kevL

kevL
  • Members
  • 4 056 messages
complication: the party select menu shows before you know what the destination is.

Let's see if I have the current sequence right:
- player clicks trigger
- PC runs to trigger and on arrival the party select menu pops up.
- on accepting party, the worldMap pops up.
- on clicking a hotspot icon travel occurs

to overcome complication; for each currently displayed, but restricted hotspot, inform the player with a Message about who's required.

Or, show the player select menu a second time if NPC that's required for hotspot is not in party, along with a simple message about it.

Or force NPC (and Player) into taking NPC, whether or not NPC gets marked selectable, whether or not transition is also then forced automatically since Player has already clicked hotspot. decisions, decisions

i suggest this:
-- player clicks trigger
-- PC runs to trigger and on arrival the party select menu pops up.
-- player selects and/or OK's party choice
-- if a restricted hotspot is chosen,
---- if NPC is in party, Go
---- if NPC is not in party
-------- SendMessageToPC() that NPC must be in party for travel to that particular hotspot. And cancel travel/worldMap.
-- let Player click the trigger to repeat the process ...

( an alternative is to show the player select menu a second time and take it from there ... )

#7
andysks

andysks
  • Members
  • 1 645 messages

I was looking through the library and I saw what I tried one time. Commented it out so that I refer to it in the future, which is now. It didn't work, as you can see by my confusion at the comment :).

/*//If we travel to Kelech-Mor, take Maudril with us.
	//How the hell we do that??????????
	if(sTargetWaypoint == "wp_kelech")
	{
	int nNPCsInParty = GetNumRosterMembersInParty( oPC );
	int nPartyMax = 5;
	// Party Limit hit, remove selectable companions
	if ( nNPCsInParty >= nPartyMax )
	{
		RemoveRosterMembersFromParty( oPC, TRUE, FALSE );
		nNPCsInParty = GetNumRosterMembersInParty( oPC );
	}

	// Free slots available, add required companion
	if ( nNPCsInParty < nPartyMax )
	{
		SetNoticeText(oPC, "You must have maudril with you in order to travel to Kelech-Mor");
		AddRosterMemberToParty( "maudril", oPC );
		SetIsRosterMemberSelectable( "maudril", FALSE );	
	}
	}*/

In any case, I thought of commenting somewhere in the world map name of the hotspot or something like that the companions needed to travel there, so that the played doesn't take the non selectable companion as a bug.

 

Your suggestion sounds good. Simpler than the OC I think. Perhaps a notice text instead of message so that it's quite noticeable.

 

So I need two ifs in my library. 

 

If we select this hotspot,

if this person is in party

GO

if not,

abort and notice text.



#8
kevL

kevL
  • Members
  • 4 056 messages
in 'inc_roe_travel'
int CheckRequiredParty(string sTargetWaypoint)
{
    object oPC = GetFirstPC(FALSE);
    string sNotice = "";

    if (sTargetWaypoint == "tag_of_wp_in_restricted_area_1")
    {
        if (GetFactionEqual(oPC, GetObjectByTag("tag_of_required_npc_1")) == FALSE)
        {
            sNotice = "Required_NPC_1 must be in the party to travel to Restricted_Area_1";
        }
    }
    else if (sTargetWaypoint == "tag_of_wp_in_restricted_area_2")
    {
        if (GetFactionEqual(oPC, GetObjectByTag("tag_of_required_npc_2")) == FALSE)
        {
            sNotice = "Required_NPC_2 must be in the party to travel to Restricted_Area_2";
        }
    }
    // etc.

    if (sNotice != "")
    {
        SendMessageToPC(oPC, sNotice);
        SetNoticeText(oPC, sNotice);
        // both, so when player cancels the notice-box the requirements are still in Chat

        DisplayGuiScreen(oPC, "SCREEN_NOTICEWINDOW", TRUE);
        return FALSE;
    }

    return TRUE;
}
the actionScript
#include "inc_roe_travel"

void main(string sTargetWaypoint, string sModule)
{
    if (CheckRequiredParty(sTargetWaypoint) == FALSE)
    {
        CloseGUIScreen(GetFirstPC(FALSE), "SCREEN_WORLDMAP");
        return;
    }

    DoTravel(sTargetWaypoint, sModule);
}
that sort of thing; testing & further stuff ofc.

#9
andysks

andysks
  • Members
  • 1 645 messages

Good news is that it works perfectly. I know, if it works perfect how can there be bad news :D? A weird bug occurred actually. After I got the travel declined, map closed messages popped etc. I couldn't move my PC. Actually, I couldn't do anything. Keyboard worked perfect, but mouse was not responding. The cursor could move, but no click happened. Not even if I pressed esc to exit the game. Maybe this screenshot shows the problem. As you see, I hover over an NPC and I see a cursor instead of the talk bobble. is this some UI related thing?

 

Edit: The picture had no cursor so the problem wouldn't show. But I hope you understand what happened :).



#10
kevL

kevL
  • Members
  • 4 056 messages
lol computers

try changing bModal in DisplayGuiScreen() to false

that's all i can think of atm.

#11
andysks

andysks
  • Members
  • 1 645 messages

That did it. So cool. Works like a charm. Thanks so much again KevL. This way is so much more simplified than the one in the OC I think.



#12
kevL

kevL
  • Members
  • 4 056 messages
and now for something completely different


  • andysks aime ceci