The script ka_hotspot_click_force gets called when the devs needed to make sure a certain NPC is along for the ride. Otherwise, it seems to work very similar to ka_hotspot_click.
I've removed a number of the plot checks to avoid spoilers.
// 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.
// EPF 1/10/06
// TDE 1/31/06 - Added messages for Act 3, and scripting for if any one of a list of companions is required.
// EPF 1/31/06 - Using IsInParty instead of GetIsRosterMemberAvailable().
// TDE 3/23/06 - Fixed a bug in the companion list script
// EPF 3/29/06 -- uses JumpPartyToArea now
// BMA-OEI 4/12/06 - replaced LoadNewModule() with SaveRosterLoadModule()
// TDE 4/25/06 - Added support for excluding companions using "-" instead of ","
#include "kinc_worldmap"
#include "ginc_debug"
#include "ginc_companions"
#include "ginc_transition"
// 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.
//
// TDE - Eric, if this becomes a permanent solution rather than temp, these strings will need to be
// added to dialog.tlk and called with SpeakStringByStrRef(nNum)
void DisplayForceCompanionMessage(int nMessage)
{
object oPC = OBJECT_SELF;
switch(nMessage)
{
case 1:
//You must have xin your party in order to travel to y. Proceed?
SetGlobalString("00_sLastForcedCompanion", "sand");
DisplayMessageBox(oPC,178912, "", "gui_force_comp","",TRUE,"SCREEN_MESSAGEBOX_DEFAULT",66,"",67);
break
// PLOT CHECKS REMOVED HERE!!!!
}
}
void main(string sModule, string sHotspot, int nProbSpecial, int nProbRandom, string sCompanion, string sCompVar, int nCheckValue, int nMessage)
{
string sDestination;
object oDestination;
int nRoll;
object oPC = OBJECT_SELF;
object oFirstPC = GetFirstPC();
object oFM;
if(!GetIsSinglePlayer())
{
if(GetWorldMapLocked())
{
SendMessageToPC(oPC, GetStringByStrRef(STRING_REF_MAP_LOCKED));
return;
}
else
{
SetWorldMapLocked();
}
}
//companion is supposed to be forced at this point
if ( GetGlobalInt(sCompVar) == nCheckValue )
{
// Added by TDE: to allow passing in a list such as "zhjaeve,ammon_jerro"
int iLen;
int iCommaPos = FindSubString( sCompanion, "," ); //find first comma
int iMinusPos = FindSubString( sCompanion, "-" ); //find first minus
int bDisplayMessage = TRUE; //Display the message if is a required companion is NOT in party or an excluded companion is in the party
if ( iCommaPos == -1 && iMinusPos == -1 )
{
//only checking for one companion
if(IsInParty(sCompanion))
{
bDisplayMessage = FALSE;
}
}
else
{
//Checking for multiple companions
//PrettyMessage("Checking for multiple companions");
string sNewString = sCompanion;
int iPosEnd;
int iPosStart;
int bExclude;
while ( iCommaPos != -1 || iMinusPos != -1 )
{
// PrettyDebug("Trying to find " + sNewString);
// determine length
iLen = GetStringLength(sNewString);
// get next comma or - position (returns -1 if not found)
iCommaPos = FindSubString(sNewString, "," );
iMinusPos = FindSubString(sNewString, "-" );
bExclude = FALSE;
if ( iCommaPos == -1 && iMinusPos == -1 )
{
iPosStart = 0;
iPosEnd = iLen;
}
else
{
if ( iMinusPos != -1 && (iCommaPos == -1 || iCommaPos > iMinusPos) )
{
PrettyDebug("Minus Pos = " + IntToString(iMinusPos));
bExclude = TRUE;
iPosStart = iMinusPos + 1; // Minus is the next in the sequence
if (iCommaPos > iMinusPos)
iPosEnd = iCommaPos - 1;
else iPosEnd = iLen;
}
else
{
// PrettyDebug("Comma Pos = " + IntToString(iCommaPos));
iPosStart = 0;
iPosEnd = iCommaPos; // Comma is the next in the sequence
}
}
// get companion name in string
string sTempString = GetSubString(sNewString, iPosStart, iPosEnd);
PrettyMessage("Getting " + sTempString);
// If this companion is in the party, set flag
if ( IsInParty(sTempString) )
{
//PrettyDebug(sTempString + " is in the party.");
if ( bExclude )
{
// PrettyDebug(sTempString + " should NOT be in the party.");
// Make sure they are selectable, so they can be removed from the party
SetIsRosterMemberSelectable(sTempString,TRUE);
bDisplayMessage = TRUE;
break;
}
else
{
PrettyDebug(sTempString + " should be in the party.");
bDisplayMessage = FALSE;
}
}
else PrettyDebug(sTempString + " is NOT in the party.");
// drop first tag and comma
if ( bExclude )
{
// PrettyDebug("Getting index between zero and" + IntToString(iMinusPos));
sNewString = GetSubString(sNewString, 0, iMinusPos);
}
else
{
// PrettyDebug("Getting index between " + IntToString(iPosEnd + 1) + " and " + IntToString(iLen));
sNewString = GetSubString(sNewString, iPosEnd + 1, iLen);
}
}
}
if( bDisplayMessage )
{
// PrettyDebug("Displaying Force Companion Message.");
DisplayForceCompanionMessage(nMessage);
return;
}
}
//we only want one map encounter per player attempt to travel --
//prevents the player getting barraged by module cutscenes
//when he just wants to get to point B.
if(!GetGlobalInt("bPlayedEncounterOnThisClick"))
{
sDestination = GetModuleEncounter(sModule, sHotspot);
if(sDestination == "")
{
nRoll = Random(100);
if(nRoll < nProbSpecial)
{
sDestination = GetSpecialEncounter(sModule, sHotspot);
}
else if(nRoll < nProbSpecial + nProbRandom)
{
sDestination = GetRandomEncounter(sModule, sHotspot);
}
}
}
if(sDestination == "")
{
SetGlobalInt("bPlayedEncounterOnThisClick",FALSE);
sDestination = GetDefaultDestination(sHotspot);
}
else //we're doing an encounter
{
SetGlobalInt("bPlayedEncounterOnThisClick",TRUE);
// unless our present encounter overrides the message with a global variable, we play it
// and return.
if(!GetGlobalInt(ENCOUNTER_MESSAGE_OVERRIDE))
{
ShowEncounterMessage(sDestination, sModule);
return;
}
SetGlobalInt(ENCOUNTER_MESSAGE_OVERRIDE, FALSE);
}
//this variable handles origin-dependent redirection, like changing the point of
//entry in the docks district depending on whether you came from blacklake
//or the merchant quarter. We reset it to its default here. It is set in the
//cliententer scripts of applicable areas.
SetGlobalInt("OriginArea",0);
oDestination = GetObjectByTag(sDestination);
if(GetIsObjectValid(oDestination))
{
ForceRestParty( oPC );
// BMA-OEI 6/14/06
SinglePartyTransition( oPC, oDestination );
//JumpPartyToArea(oPC, oDestination);
}
else
{
ForceRestParty( oPC );
PrettyDebug("Unable to find waypoint in current module. Initiating module transition.");
//LoadNewModule(sModule, sDestination);
SaveRosterLoadModule(sModule, sDestination);
}
}