The following examples have been taken from the Official Campaign for reference when building a world map for your campaign. Note that these scripts are "kampaign" scripts and do not exist in modules by default.
The script ka_hotspot_click is the most basic world map script from the Official Campaign. It is meant to go in the "ActionScript" field for a hotspot in the world map plugin interface. At end of the script, notice that this calls SaveRosterLoadModule (located in ginc_companion). This function takes two parameters: the name of the module to load and the name of the waypoint the party will jump to. Here are the parameters for this script: string sModule - The file name of the module string sHotspot - The name of the hotspot clicked for the purposes of checking for a special case int nProbSpecial - Percentage chance for a special encounter int nProbRandom - Percentage chance for a random encounter string sDestinationOverride - The waypoint to go to intead of the default for a module string sCustomScript - Name of a custom script to execute There is a percent chance per transition that the party will have an encounter, but it only happens once. I think that the encounter area sends the party along to where they were going after they have completed the encounter. Note the use of GetIsObjectValid(oDest) to determine if the transition is in the current module and SinglePartyTransition( oPC, oDest ) to jump to the waypoint if it is in the current module.
// ka_hotspot_click
//
// Action script for when a hotspot is clicked on the worldmap. Determines the location to send
// the party to.
// BMA-OEI 4/12/06 - replaced LoadNewModule() with SaveRosterLoadModule()
#include "kinc_worldmap"
#include "ginc_debug"
#include "ginc_companions"
#include "ginc_transition"
void JumpParty(object oPartyMember, object oDestination)
{
object oThisArea = GetArea(oPartyMember);
object oJumper = GetFirstFactionMember(oPartyMember);
while (GetIsObjectValid(oJumper))
{
PrettyDebug("Jumping " + GetName(oJumper) + " to " + GetTag(oDestination));
AssignCommand(oJumper, JumpToObject(oDestination));
oJumper = GetNextFactionMember(oPartyMember);
}
}
void main(string sModule, string sHotspot, int nProbSpecial, int nProbRandom, string sDestinationOverride, string sCustomScript)
{
string sDestination;
object oDestination;
int nRoll;
object oPC = OBJECT_SELF;
if(!GetIsSinglePlayer())
{
if(GetWorldMapLocked())
{
SendMessageToPC(oPC, GetStringByStrRef(STRING_REF_MAP_LOCKED));
return;
}
else
{
SetWorldMapLocked();
}
}
//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);
PrettyMessage(sHotspot + " clicked.");
if (sHotspot == "1302OldOwlWell")
{
if (GetGlobalInt("10_met_grobnar") != 1)
{
object oDest = GetObjectByTag("wp_1003_enter");
SetGlobalInt("10_met_grobnar", 1);
if (GetIsObjectValid(oDest))
{
ForceRestParty( oPC );
// BMA-OEI 6/14/06
SinglePartyTransition( oPC, oDest );
//JumpPartyToArea(oPC, oDest);
}
else
{
ForceRestParty( oPC );
//LoadNewModule("1000_Neverwinter_A1", "wp_1003_enter");
SaveRosterLoadModule("1800_Skymirror", "wp_1003_enter");
}
return;
}
}
if(sCustomScript != "")
{
ExecuteScript(sCustomScript, OBJECT_SELF);
}
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);
if(sDestinationOverride == "")
{
sDestination = GetDefaultDestination(sHotspot);
PrettyMessage("Sending to default destination " + sDestination);
}
else
{
sDestination = sDestinationOverride;
}
}
else //we're doing a special, module, or random 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.");
PrettyDebug("Loading module. Destination = " + sDestination);
//LoadNewModule(sModule, sDestination);
SaveRosterLoadModule(sModule, sDestination);
}
}
This is the heart of the world map functions. Not that all the includes and constants work for the OC only.
// kinc_worldmap
//
// Functions and constants for the NWN2 world map functionality
// EPF 12/8/05
#include "ginc_debug"
// the below files contain all the encounter logic
#include "kinc_module1000"
#include "kinc_module1100"
#include "kinc_module1200"
#include "kinc_module1300"
#include "kinc_module1600"
#include "kinc_module1700"
#include "kinc_module1800"
#include "kinc_module1900"
#include "kinc_module2000"
#include "kinc_module2100"
#include "kinc_module2200"
#include "kinc_module2300"
#include "kinc_module2400"
#include "kinc_module2600"
#include "kinc_module3000"
#include "kinc_module3100"
#include "kinc_module3400"
#include "kinc_module3500"
/////////////////////////
// FUNCTION DECLARATIONS
/////////////////////////
// ** hotspot functions **
//make a hotspot visible on the world map
void ShowHotspot(string sHotspot);
//make a hotspot invisible on the world map
void HideHotspot(string sHotspot);
//returns true if a hotspot is visible on the world map
int GetIsHotspotVisible(string sHotspot);
//make all hotspots with numbers between nLow and nHigh (inclusive) visible
void ShowHotspotRange(int nLow, int nHigh);
//make all hotspots with numbers between nLow and nHigh (inclusive) invisible
void HideHotspotRange(int nLow, int nHigh);
//run at the start of a module to associate a hotspot with its default waypoint
void SetupDefaultDestinations(int nAct = -1);
// ** conversion functions **
//hotspot number is the 4-digit area code for the area that the hotspot points to
string GetHotspotNameFromNumber(int nAreaNumber);
int GetHotspotNumberFromName(string sHotspot);
// ** encounter functions **
// returns the waypoint tag for a plot-based critpath encounter or the empty string if none is available
string GetModuleEncounter(string sModule, string sDestHotspot);
// returns the waypoint tag for a non-critpath encounter that isn't just random monsters or the empty string if none is available
string GetSpecialEncounter(string sModule, string sDestHotspot);
// returns the waypoint tag for a random monster encounter or the empty string if none is available
string GetRandomEncounter(string sModule, string sDestHotspot);
// show a "you have encountered a thing on the world map" message. Callback initiates the transition.
void ShowEncounterMessage(string sDestination, string sModule);
// ** world map locout functions **
// multiple PCs simultaneously clicking travel on the world map causes problems. We use a cooldown time to preven this.
void SetWorldMapLocked();
int GetWorldMapLocked();
/////////////////////////
// CONSTANT DECLARATIONS
/////////////////////////
// GENERAL //
// these are used with the Encounter message box
const int STRREF_ENCOUNTER_MESSAGE = 182995;
const string ENCOUNTER_MESSAGE_OVERRIDE = "00_bOverrideEncounterMessage";
const string LAST_DESTINATION = "00_sLastDestination";
const string LAST_MODULE = "00_sLastModule";
const string PC_CLICKER = "oLastWorldMapClicker"; //this is stored on the module not
// these are for locking the world map so only one user can use it at a time
const string WORLD_MAP_LOCKED = "00_bWorldMapLocked";
const string WORLD_MAP_LOCKER = "oWorldMapLocker";
const int STRING_REF_MAP_LOCKED = 183512;
const string WORLD_MAP_LOCKED_DAY = "00_nWorldMapLockDay";
const string WORLD_MAP_LOCKED_HOUR = "00_nWorldMapLockHour";
const string WORLD_MAP_LOCKED_MINUTE = "00_nWorldMapLockMinute";
const string WORLD_MAP_LOCKED_SECOND = "00_nWorldMapLockSecond";
const int WORLD_MAP_LOCK_COOLDOWN = 18; //seconds until we allow another click
const string WORLD_MAP_LOCK_INITIALIZED = "00_bWorldMapLockInit";
// ACT 1 HOTSPOTS HERE //
// 1000
const int HS_NWC_A1 = 1001;
// 1700 Merchant Quarter
const int HS_MQ = 1013;
// 1800 Skymirror and Grobnar
const int HS_GROBNAR = 1003;
const int HS_SKY = 1040;
// 1900 Back Alley
// 1100
const int HS_WEST_HARBOR = 1100;
const int HS_WH_RUINS = 1120;
// 1200
const int HS_WILLOW = 1202;
const int HS_LIZARD1 = 1206;
const int HS_FORTLOCKE = 1209;
const int HS_GRAVEYARD = 1211;
const int HS_BANDITCAMP = 1214;
const int HS_HIGHCLIFF = 1217;
const int HS_HC_SHANDRA = 1208;
const int HS_HC_RUINS = 1218;
const int HS_LIZARD2 = 1220;
const int HS_GLADE = 1223;
const int HS_WIDOW = 1225;
// 1300
const int HS_OOW_A1 = 1302;
const int HS_BG_APPROACH = 1303;
const int HS_IRONFIST = 1308;
const int HS_EG_APPROACH = 1314;
// 1600
const int HS_EMBER = 1616;
const int HS_GITHAPP = 1620;
const int HS_GITHCAVE = 1621;
const int HS_GC_SHANDRA = 1610;
// ACT 2 HOTSPOTS HERE //
//2000
const int HS_NWC_A2 = 2000;
const int HS_NWC_BLACKLAKE = 2024;
const int HS_NWC_MERCHANT = 2013;
//2100
const int HS_CK_COURT = 2100;
//2200
const int HS_PL_A2 = 2200;
const int HS_PL_EMBER = 2210;
const int HS_PL_DUSKWOOD = 2211;
//2300
const int HS_CKA_FARM = 2300;
const int HS_CKA_TUNNEL = 2340;
//2400
const int HS_IR_OGRUINS = 2410;
//2600
const int HS_AJ_EXTERIOR = 2600;
// ACT 3 HOTSPOTS HERE //
//3000
const int HS_PARTY = 0000;
const int HS_HIGHCLIFF_A3 = 3010;
const int HS_LIZARDMEN = 3014;
const int HS_IRONFIST_A3 = 3030;
const int HS_GALARDRYM = 3031;
const int HS_COT_MERE = 3040;
const int HS_REAVER_A = 3050;
const int HS_REAVER_B = 3051;
const int HS_NWC_MERCH = 3063;
const int HS_SH_FARM_A3 = 3070;
const int HS_PORT_LLAST = 3080;
const int HS_WENDER = 3081;
//3100
const int HS_CK_COURT_A3 = 2100;
const int HS_NOLALOTH = 3090;
/////////////////////////
// FUNCTION DEFINITONS
/////////////////////////
void ShowHotspot(string sHotspot)
{
SetGlobalInt("WM_bShow" + sHotspot, TRUE);
}
void HideHotspot(string sHotspot)
{
SetGlobalInt("WM_bShow" + sHotspot, FALSE);
}
int GetIsHotspotVisible(string sHotspot)
{
return GetGlobalInt("WM_bShow" + sHotspot);
}
void ShowHotspotRange(int nLow, int nHigh)
{
string sHotspot;
while(nLow <= nHigh)
{
sHotspot = GetHotspotNameFromNumber(nLow);
if(sHotspot != "")
{
ShowHotspot(sHotspot);
}
nLow++;
}
}
void HideHotspotRange(int nLow, int nHigh)
{
string sHotspot;
while(nLow <= nHigh)
{
sHotspot = GetHotspotNameFromNumber(nLow);
if(sHotspot != "")
{
HideHotspot(sHotspot);
}
nLow++;
}
}
void SetDefaultDestination(string sHotspot, string sDestWP)
{
SetGlobalString("WM_sDestWP" + sHotspot, sDestWP);
}
string GetDefaultDestination(string sHotspot)
{
return GetGlobalString("WM_sDestWP" + sHotspot);
}
void SetupDefaultDestinationsAct1()
{
// 1000 Neverwinter City Act 1
SetDefaultDestination(GetHotspotNameFromNumber(HS_NWC_A1), "10_world_to_docks");
// 1700 Merchant Quarter
SetDefaultDestination(GetHotspotNameFromNumber(HS_MQ), "10_wp_docksi_to_merchant");
// 1800 Skymirror and Grobnar
SetDefaultDestination(GetHotspotNameFromNumber(HS_GROBNAR), "wp_1003_enter");
SetDefaultDestination(GetHotspotNameFromNumber(HS_SKY), "10_wp_OL_to_skymirror");
// 1100 West Harbor
SetDefaultDestination(GetHotspotNameFromNumber(HS_WH_RUINS), "wp_OL_to_1120");
SetDefaultDestination(GetHotspotNameFromNumber(HS_WEST_HARBOR), "tr_1100_from_1120");
// 1200 Highcliff
SetDefaultDestination(GetHotspotNameFromNumber(HS_WILLOW), "wp_OL_to_1202");
SetDefaultDestination(GetHotspotNameFromNumber(HS_LIZARD1), "wp_OL_to_1206");
SetDefaultDestination(GetHotspotNameFromNumber(HS_FORTLOCKE), "wp_OL_to_1209");
SetDefaultDestination(GetHotspotNameFromNumber(HS_GRAVEYARD), "wp_OL_to_1211");
SetDefaultDestination(GetHotspotNameFromNumber(HS_BANDITCAMP), "wp_OL_to_1214");
SetDefaultDestination(GetHotspotNameFromNumber(HS_HIGHCLIFF), "wp_OL_to_1217");
SetDefaultDestination(GetHotspotNameFromNumber(HS_HC_RUINS), "wp_OL_to_1218");
SetDefaultDestination(GetHotspotNameFromNumber(HS_LIZARD2), "wp_OL_to_1220");
SetDefaultDestination(GetHotspotNameFromNumber(HS_HC_SHANDRA), "12_wp_shandra_farm");
SetDefaultDestination(GetHotspotNameFromNumber(HS_GLADE), "wp_1223_enter");
SetDefaultDestination(GetHotspotNameFromNumber(HS_WIDOW), "12_wp_widow");
// 1300 OOW Defaults
SetDefaultDestination(GetHotspotNameFromNumber(HS_OOW_A1), "NG_From_Tavern");
SetDefaultDestination(GetHotspotNameFromNumber(HS_BG_APPROACH), "1303_enter");
SetDefaultDestination(GetHotspotNameFromNumber(HS_IRONFIST), "13_Bonegnash2_To_Bugapproach");
SetDefaultDestination(GetHotspotNameFromNumber(HS_EG_APPROACH), "13_Casavir_To_EGApproach");
// 1600 Githyanki Caves Defaults
SetDefaultDestination(GetHotspotNameFromNumber(HS_GITHAPP), "wp_from_ambush");
SetDefaultDestination(GetHotspotNameFromNumber(HS_EMBER), "wp_from_patrol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_GC_SHANDRA), "wp_shandra_farm");
}
void SetupDefaultDestinationsAct2()
{
SetDefaultDestination(GetHotspotNameFromNumber(HS_NWC_A2),"10_wp_city_to_flagon");
SetDefaultDestination(GetHotspotNameFromNumber(HS_NWC_BLACKLAKE), "wp_from1013_to1024");
SetDefaultDestination(GetHotspotNameFromNumber(HS_NWC_MERCHANT), "10_wp_docksi_to_merchant");
SetDefaultDestination(GetHotspotNameFromNumber(HS_CK_COURT ),"wp_CKA2_start");
SetDefaultDestination(GetHotspotNameFromNumber(HS_PL_A2 ),"2200_wp_entrance");
SetDefaultDestination(GetHotspotNameFromNumber(HS_PL_EMBER ),"2210_wp_entrance");
SetDefaultDestination(GetHotspotNameFromNumber(HS_PL_DUSKWOOD ),"2211_wp_entrance");
SetDefaultDestination(GetHotspotNameFromNumber(HS_CKA_FARM ),"23_wp_pc_ritual_start");
SetDefaultDestination(GetHotspotNameFromNumber(HS_CKA_TUNNEL), "23_wp_tunnel_ext");
SetDefaultDestination(GetHotspotNameFromNumber(HS_IR_OGRUINS ),"2410_wp_entrance");
SetDefaultDestination(GetHotspotNameFromNumber(HS_AJ_EXTERIOR ),"2650_wp_pc");
}
void SetupDefaultDestinationsAct3()
{
SetDefaultDestination(GetHotspotNameFromNumber(HS_PARTY),"wp_30_overland_enter");
SetDefaultDestination(GetHotspotNameFromNumber(HS_HIGHCLIFF_A3),"wp_3010_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_LIZARDMEN),"wp_3014_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_IRONFIST_A3),"wp_3030_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_GALARDRYM),"wp_3031_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_COT_MERE),"wp_3040_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_REAVER_A),"wp_3050_pc");
SetDefaultDestination(GetHotspotNameFromNumber(HS_REAVER_B),"wp_3050_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_NWC_MERCH),"wp_3063_enter");
SetDefaultDestination(GetHotspotNameFromNumber(HS_SH_FARM_A3),"wp_3070_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_PORT_LLAST),"wp_3080_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_WENDER),"wp_3081_enter");
SetDefaultDestination(GetHotspotNameFromNumber(HS_CK_COURT_A3 ),"wp_21_enter_ck");
SetDefaultDestination(GetHotspotNameFromNumber(HS_NOLALOTH ),"wp_3090_from_ol");
}
void SetupDefaultDestinations(int nAct = -1)
{
switch(nAct)
{
case 1:
SetupDefaultDestinationsAct1();
break;
case 2:
SetupDefaultDestinationsAct2();
break;
case 3:
SetupDefaultDestinationsAct3();
break;
default:
SetupDefaultDestinationsAct1();
SetupDefaultDestinationsAct2();
SetupDefaultDestinationsAct3();
break;
}
}
string GetAct1HotspotNameFromNumber(int nAreaNumber)
{
string sName = "";
switch(nAreaNumber)
{
// 1000
case HS_NWC_A1 :
sName = "1001flagon";
break;
// 1700
case HS_MQ :
sName = "1013merchant";
break;
// 1800
case HS_GROBNAR :
sName = "1003grobnar";
break;
case HS_SKY :
sName = "1040sky";
break;
// 1100
case HS_WH_RUINS :
sName = "1120whruins";
break;
case HS_WEST_HARBOR :
sName = "1100harbor";
break;
// 1200
case HS_WILLOW :
sName = "1202willowinn";
break;
case HS_LIZARD1 :
sName = "1206Lizard1";
break;
case HS_FORTLOCKE :
sName = "1209FortLocke";
break;
case HS_GRAVEYARD :
sName = "1211Graveyard";
break;
case HS_BANDITCAMP :
sName = "1214BanditCamp";
break;
case HS_HIGHCLIFF :
sName = "1217Highcliff";
break;
case HS_HC_SHANDRA :
sName = "1208ShandraFarm";
break;
case HS_HC_RUINS :
sName = "1218HC_Castle";
break;
case HS_LIZARD2 :
sName = "1220Lizard2";
break;
case HS_GLADE :
sName = "1223glade";
break;
case HS_WIDOW :
sName = "1225widow";
break;
// 1300
case HS_OOW_A1 :
sName = "1302OldOwlWell";
break;
case HS_BG_APPROACH :
sName = "1303Bonegnasher";
break;
case HS_IRONFIST :
sName = "1308Ironfist";
break;
case HS_EG_APPROACH :
sName = "1314Eyegouger";
break;
// 1600
case HS_EMBER :
sName = "1616ember";
break;
case HS_GITHAPP :
sName = "1620approach";
break;
case HS_GC_SHANDRA :
sName = "1610shfarm";
break;
default:
sName = "";
break;
}
return sName;
}
string GetAct2HotspotNameFromNumber(int nAreaNumber)
{
string sName = "";
switch(nAreaNumber)
{
case HS_NWC_A2 :
sName = "2000Neverwinter_A2";
break;
case HS_NWC_MERCHANT :
sName = "2013MerchantQuarter";
break;
case HS_NWC_BLACKLAKE :
sName = "2024Blacklake";
break;
case HS_CK_COURT :
sName = "2100CrossroadKeep";
break;
case HS_PL_A2 :
sName = "2200PortLlast";
break;
case HS_PL_EMBER :
sName = "2210Ember";
break;
case HS_PL_DUSKWOOD :
sName = "2211Duskwood";
break;
case HS_CKA_FARM :
sName = "2300CKAdventure";
break;
case HS_CKA_TUNNEL :
sName = "2340TunnelExt";
break;
case HS_IR_OGRUINS :
sName = "2410OvergrownRuins";
break;
case HS_AJ_EXTERIOR :
sName = "2600AJExterior";
break;
default:
sName = "";
break;
}
return sName;
}
string GetAct3HotspotNameFromNumber(int nAreaNumber)
{
string sName = "";
switch(nAreaNumber)
{
case HS_PARTY :
sName = "0000PartyCentral";
break;
case HS_HIGHCLIFF_A3 :
sName = "3010Highcliff";
break;
case HS_LIZARDMEN :
sName = "3014Lizardmen";
break;
case HS_IRONFIST_A3 :
sName = "3030Ironfist";
break;
case HS_GALARDRYM :
sName = "3031MtGalardrym";
break;
case HS_COT_MERE :
sName = "3040Mere";
break;
case HS_REAVER_A :
sName = "3050ReaverA";
break;
case HS_REAVER_B :
sName = "3051ReaverB";
break;
case HS_NWC_MERCH :
sName = "3063MerchantQuarter";
break;
case HS_SH_FARM_A3 :
sName = "3070ShandrasFarm";
break;
case HS_PORT_LLAST :
sName = "3080PortLlast";
break;
case HS_WENDER :
sName = "3081Wendersnaven";
break;
case HS_CK_COURT_A3 :
sName = "2100CrossroadKeep";
break;
case HS_NOLALOTH :
sName = "3090Nolaloth";
break;
default:
sName = "";
break;
}
return sName;
}
string GetHotspotNameFromNumber(int nAreaNumber)
{
string sName = "";
// Divide and conquer by act
if(nAreaNumber < 2000)
{
return GetAct1HotspotNameFromNumber(nAreaNumber);
}
else if (nAreaNumber < 3000)
{
return GetAct2HotspotNameFromNumber(nAreaNumber);
}
else
{
return GetAct3HotspotNameFromNumber(nAreaNumber);
}
}
int GetHotspotNumberFromName(string sAreaName)
{
return StringToInt(GetStringLeft(sAreaName, 4));
}
string GetModuleEncounter(string sModule, string sHotspot)
{
int nModule = StringToInt(GetStringLeft(sModule, 4));
PrettyMessage("nModule = " + IntToString(nModule));
SetGlobalString("KA_HOTSPOT_DEST_MODULE",sModule);
SetGlobalString("KA_HOTSPOT_DEST_HOTSPOT",sHotspot);
string sDestination;
switch(nModule)
{
case 1000:
sDestination = Get1000Encounter(sHotspot);
break;
case 1700:
sDestination = Get1700Encounter(sHotspot);
break;
case 1100:
sDestination = Get1100Encounter(sHotspot);
break;
case 1200:
sDestination = Get1200Encounter(sHotspot);
break;
case 1300:
sDestination = Get1300Encounter(sHotspot);
break;
case 1600:
sDestination = Get1600Encounter(sHotspot);
break;
case 2000:
sDestination = Get2000Encounter(sHotspot);
break;
case 2100:
sDestination = Get2100Encounter(sHotspot);
break;
case 2200:
sDestination = Get2200Encounter(sHotspot);
break;
case 2300:
sDestination = Get2300Encounter(sHotspot);
break;
case 2400:
sDestination = Get2400Encounter(sHotspot);
break;
case 2600:
sDestination = Get2600Encounter(sHotspot);
break;
case 3000:
sDestination = Get3000Encounter(sHotspot);
break;
case 3100:
sDestination = Get3100Encounter(sHotspot);
break;
case 3400:
sDestination = Get3400Encounter(sHotspot);
break;
case 3500:
sDestination = Get3500Encounter(sHotspot);
break;
default:
PrettyMessage("kinc_worldmap: invalid module string given to GetModuleEncounter()");
sDestination = "";
}
return sDestination;
}
string GetSpecialEncounter(string sModule, string sHotspot)
{
int nModule = StringToInt(GetStringLeft(sModule, 4));
string sDestination;
switch(nModule)
{
case 1000:
sDestination = Get1000SpecialEncounter(sHotspot);
break;
case 1700:
sDestination = Get1700SpecialEncounter(sHotspot);
break;
case 1100:
sDestination = Get1100SpecialEncounter(sHotspot);
break;
case 1200:
sDestination = Get1200SpecialEncounter(sHotspot);
break;
case 1300:
sDestination = Get1300SpecialEncounter(sHotspot);
break;
case 1600:
sDestination = Get1600SpecialEncounter(sHotspot);
break;
case 2000:
sDestination = Get2000SpecialEncounter(sHotspot);
break;
case 2100:
sDestination = Get2100SpecialEncounter(sHotspot);
break;
case 2200:
sDestination = Get2200SpecialEncounter(sHotspot);
break;
case 2300:
sDestination = Get2300SpecialEncounter(sHotspot);
break;
case 2400:
sDestination = Get2400SpecialEncounter(sHotspot);
break;
case 2600:
sDestination = Get2600SpecialEncounter(sHotspot);
break;
case 3000:
sDestination = Get3000SpecialEncounter(sHotspot);
break;
case 3100:
sDestination = Get3100SpecialEncounter(sHotspot);
break;
case 3400:
sDestination = Get3400SpecialEncounter(sHotspot);
break;
case 3500:
sDestination = Get3500SpecialEncounter(sHotspot);
break;
default:
PrettyError("kinc_worldmap: invalid module string given to GetModuleEncounter()");
sDestination = "";
}
return sDestination;
}
string GetRandomEncounter(string sModule, string sHotspot)
{
return "";
}
void ShowEncounterMessage(string sDestination, string sModule)
{
// so the callback knows where to jump the player to.
SetGlobalString(LAST_DESTINATION, sDestination);
SetGlobalString(LAST_MODULE, sModule);
SetLocalObject(GetModule(),PC_CLICKER, OBJECT_SELF);
SetCommandable(FALSE); //freeze player until the callback is clicked.
DisplayMessageBox(OBJECT_SELF, STRREF_ENCOUNTER_MESSAGE, "", "gui_map_transition");
}
void SetWorldMapLocked()
{
SetGlobalInt(WORLD_MAP_LOCKED_DAY, GetCalendarDay());
SetGlobalInt(WORLD_MAP_LOCKED_HOUR, GetTimeHour());
SetGlobalInt(WORLD_MAP_LOCKED_MINUTE, GetTimeMinute());
SetGlobalInt(WORLD_MAP_LOCKED_SECOND, GetTimeSecond());
SetGlobalInt(WORLD_MAP_LOCK_INITIALIZED, TRUE); //so we know the timer is initialized
PrettyMessage("World map locked at time " + IntToString(GetTimeHour()) + ":" + IntToString(GetTimeMinute()) + ":" + IntToString(GetTimeSecond()));
}
int TimeToSeconds(int nHour, int nMinute, int nSecond)
{
//for ease, we just convert the time into seconds -- 60 for 60 seconds in a minute, 3600 for number of seconds in an hour.
return nSecond + nMinute * 60 + nHour * 3600;
}
int GetWorldMapLocked()
{
if(GetIsSinglePlayer())
{
return FALSE;
}
if(!GetGlobalInt(WORLD_MAP_LOCK_INITIALIZED))
{
return FALSE;
}
int nLockedHour = GetGlobalInt(WORLD_MAP_LOCKED_HOUR);
int nLockedMinute = GetGlobalInt(WORLD_MAP_LOCKED_MINUTE);
int nLockedSecond = GetGlobalInt(WORLD_MAP_LOCKED_SECOND);
int nCurrentHour = GetTimeHour();
int nCurrentMinute = GetTimeMinute();
int nCurrentSecond = GetTimeSecond();
int nTotalLockedSeconds = TimeToSeconds(nLockedHour,nLockedMinute,nLockedSecond);
int nTargetTime = nTotalLockedSeconds + WORLD_MAP_LOCK_COOLDOWN; //10 sec cooldown
int nCurrentSeconds = TimeToSeconds(nCurrentHour,nCurrentMinute,nCurrentSecond);
// PrettyDebug("Target time for unlock = " + IntToString(nTargetTime));
// PrettyDebug("Current time in seconds = " + IntToString(nCurrentSeconds));
//same day
if(nTargetTime < nCurrentSeconds)
{
// PrettyDebug(IntToString(nCurrentSeconds - nTotalLockedSeconds) + " seconds passed since the last transition.");
return FALSE;
}
//we've rolled to the next calendar day
int nLockedDay = GetGlobalInt(WORLD_MAP_LOCKED_DAY);
int nCurrentDay = GetCalendarDay();
//!= is the check here because the day change could roll the month
//so going from month 1 day 28 to month 2 day 0 should still register as a day having passed.
if(nCurrentDay != nLockedDay && nCurrentSeconds > WORLD_MAP_LOCK_COOLDOWN)
{
return FALSE;
}
return TRUE;
}
If you paint down a new map transition, you'll notice that it has an onClick script of gtr_world_map_cl. You'll also noticed that this script doesn't actually exist in new modules. I think what happened is that this script started as a global, but at some point ended up with some code specific to the OC and was removed. Here the script, pulled from 1000_Neverwinder_A1.mod (The Docks).
// gtr_world_map_cl
//
// Transition to the world map
// EPF
// EPF 2/2/06 -- modifying to have a default map for each act if no other map is specified.
// EPF 3/24/06 -- this is now an OnClicked event
// BMA-OEI 6/24/06 -- Added gather party check
// BMA-OEI 8/11/06 -- Autosave before transition
// ChazM 8/21/06 -- updated constant CAMPAIGN_SWITCH_REMOVE_DOMINATED_ON_TRANSITION
// BMA-OEI 8/22/06 -- Replaced auto save w/ AttemptSinglePlayerAutoSave()
#include "ginc_debug"
#include "ginc_autosave"
#include "ginc_transition"
void main()
{
object oPC = GetClickingObject();
if ( GetIsPC( oPC ) == FALSE )
{
return;
}
string sMap = GetLocalString(OBJECT_SELF, "sMap");
string sOrigin = GetLocalString(OBJECT_SELF, "sOrigin");
if(sMap == "")
{
int nAct = GetGlobalInt("00_nAct");
switch(nAct)
{
case 1:
sMap = "Highcliff";
break;
case 2:
sMap = "Act 2";
break;
case 3:
sMap = "Act 3";
break;
default:
sMap = "Highcliff";
break;
}
}
// BMA-OEI 7/04/06 - Check if using remove dominated campaign flag
if ( GetGlobalInt(CAMPAIGN_SWITCH_REMOVE_DOMINATED_ON_TRANSITION) == TRUE )
{
int nRemoved = 0;
object oFM = GetFirstFactionMember( oPC, FALSE );
while ( GetIsObjectValid(oFM) == TRUE )
{
nRemoved = nRemoved + RemoveEffectsByType( oFM, EFFECT_TYPE_DOMINATED );
oFM = GetNextFactionMember( oPC, FALSE );
}
if ( nRemoved > 0 )
{
// Abort transition if dominated effect was found and removed
return;
}
}
// BMA-OEI 6/24/06
if ( GetGlobalInt( VAR_GLOBAL_GATHER_PARTY ) == 1 )
{
if ( IsPartyGathered( oPC ) == FALSE )
{
ReportPartyGather( oPC );
return;
}
}
// BMA-OEI 8/22/06 -- Autosave before transition
AttemptSinglePlayerAutoSave();
ShowWorldMap( sMap, oPC, sOrigin );
}
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);
}
}
This simple script can be placed on a conversation node to make a certain hotspot visible at some point in the plot.
// ka_hotspot_show
//
// Set as visible the hotspot with name sHotspot
#include "kinc_worldmap"
void main(string sHotspot)
{
ShowHotspot(sHotspot);
}
The following function checks to see if a hotspot has been found. It is meant to be placed on the ConditionalScript field of a world map.
// kc_hotspot_show
//
// global conditional script for world map hotspots. Returns TRUE if this hotspot should be displayed
// on the world map.
// EPF 12/8/05
#include "kinc_worldmap"
int StartingConditional(string sHotspot)
{
return GetIsHotspotVisible(sHotspot);
}
This script is an example of one of the encounter scripts that kinc_worldmap includes. It's worth noting that none of the OC module includes seem to do anything with the SpecialEncounter() function.
// kinc_module1000
//
// global include file for the module.
// EPF 12/8/05
// DBR 02/22/06 - if I havn't had the Sand intro, don't warp to the Sunken Flagon.
// DBR 08/03/06 - Initiate Olov ambush if player tries to leave Old Owl Well
#include "ginc_debug"
//const string OLOV_CS_FLAG = "13gb_olov_ambush";
//const string OLOV_CS_WP = "13_Cascamp_To_Olov";
string Get1000Encounter(string sDestHotspot)
{
int nOrigin = GetGlobalInt("OriginArea");
if (GetGlobalInt("13gb_olov_ambush") == 1) //Olov ambush should occur, don't leave Old Owl Well without Ambush occurring.
{
SetGlobalInt("13gb_olov_ambush",2);
PrettyMessage("Time for Olov to appear");
return "13_Cascamp_To_Olov";
}
if ((sDestHotspot=="1001flagon")&&(!GetGlobalInt("10_arrival_done")))
return "10_wp_cs_arrival_elstop";
//Sydney/Johcris scene
if (GetGlobalInt("00b_ReadyJocrisNataleCS")==1)
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
return "1025_wp_player";
}
if (sDestHotspot == "1001flagon" || sDestHotspot == "2000Neverwinter_A2")
{
PrettyMessage("Calling redirection script");
switch (nOrigin)
{
case 1013: //Player coming from Merchant Quarter
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
PrettyMessage("Entering from Merchant Quarter");
SetGlobalInt("district_redirect", 1);
return "10_wp_docksi_to_dockso";
}
break;
case 1600: // Player coming from Blacklake
case 2024:
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
SetGlobalInt("district_redirect", 1);
return "10_wp_docksi_to_dockso";
}
break;
case 1900: // Player coming from Back Alley
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
SetGlobalInt("district_redirect", 1);
return "10_wp_alley_to_docks1_st_exit";
}
break;
}
}
return "";
}
string Get1000SpecialEncounter(string sDestHotspot)
{
return "";
}
The world map include file for the Merchant Quarter shows how the origin variable is used to redirect to a different waypoint, based on which direction the party is coming from.
// kinc_module1700
//
// global include file for the module.
// JYL 04/17/06
// DBR 08/03/06 - Initiate Olov ambush if player tries to leave Old Owl Well
// DBR 08/16/06 - Changed waypoint override to a tag that is not also in the Docks
//const string OLOV_CS_FLAG = "13gb_olov_ambush";
//const string OLOV_CS_WP = "13_Cascamp_To_Olov";
string Get1700Encounter(string sDestHotspot)
{
int nOrigin = GetGlobalInt("OriginArea");
if (GetGlobalInt("13gb_olov_ambush") == 1) //Olov ambush should occur, don't leave Old Owl Well without Ambush occurring.
{
SetGlobalInt("13gb_olov_ambush",2);
//PrettyMessage("Time for Olov to appear");
return "13_Cascamp_To_Olov";
}
if (sDestHotspot=="1013merchant" || sDestHotspot=="2013MerchantQuarter")
{
switch (nOrigin)
{
case 0: // Player entering from outside city
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
SetGlobalInt("district_redirect", 1);
return "10_wp_oow_spawn";
}
break;
case 1000: // Player entering from Docks
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
SetGlobalInt("district_redirect", 1);
return "10_wp_docksi_to_merchant";
}
break;
case 1600: // Player entering from Blacklake
case 2024:
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
SetGlobalInt("district_redirect", 1);
return "wp_from1024_to1013";
}
break;
}
}
return "";
}
string Get1700SpecialEncounter(string sDestHotspot)
{
return "";
}