A map pin is a marker for special locations on the mini map. These can be preset by the module builder or added by the player. Preset map pins often contain the name of the location and are not necessarily static, as they can be revealed and hidden via scripting. Player-set map pins can contain any information the players wishes to associate with the pin and can be added, deleted, and edited as desired, but only for the current area. Text contained by the map pin can be seen by hovering the mouse over the pin.

Accessing player map pins via NWScript[]

Player map pins are local variables stored on the PC object.

  • NW_TOTAL_MAP_PINS - Int of number of map pins player has placed
  • NW_MAP_PIN_NTRY_# - String of map pin text
  • NW_MAP_PIN_XPOS_# - Float of X coordinate
  • NW_MAP_PIN_YPOS_# - Float of Y coordinate
  • NW_MAP_PIN_AREA_# - Object of area

NWScript functions[]

Here are some functions to manipulate the map pins.

Bear in mind that they only get updated on entering the area of the map pin, so if you add or delete one in the same area as oPC, the change will not take place until oPC enters that area again. You can solve this by using the ActivatePortal function and portal the PC to the same location. This will make the update look just like loading the area on enter.

/* Declarations */
// Return iPinID of the first deleted map pin within the personal map pin array
int GetFirstDeletedMapPin(object oPC); 

// Set a personal map pin on oPC. Returns iPinID.
// Defaults: GetArea(oPC) and fX/fY from GetPosition(oPC)
int SetMapPin(object oPC, string sPinText, float fX=-1.0, float fY=-1.0, object oArea=OBJECT_INVALID);

// Mark a map pin as deleted. Not a real delete to maintain the array
void DeleteMapPin(object oPC, int iPinID);

// Returns oArea from iPinID
object GetAreaOfMapPin(object oPC, int iPinID);

/* Implementation */
int GetFirstDeletedMapPin(object oPC)
   int i;
   int iPinID = 0;
   int iTotal = GetLocalInt(oPC, "NW_TOTAL_MAP_PINS");
   if(iTotal > 0) {
       for(i=1; i<=iTotal; i++) {
           if(GetLocalString(oPC, "NW_MAP_PIN_NTRY_" + IntToString(i)) == "DELETED") {
               iPinID = i;
   return iPinID;

int SetMapPin(object oPC, string sPinText, float fX=-1.0, float fY=-1.0, object oArea=OBJECT_INVALID)
   // If oArea is not valid, we use the current area.
   if(oArea == OBJECT_INVALID) { oArea = GetArea(oPC); }
   // if fX and fY are both -1.0, we use the position of oPC
   if(fX == -1.0 && fY == -1.0) {
       vector vPos=GetPosition(oPC);
       fX = vPos.x;
       fY = vPos.y;
   // Find out if we can reuse a deleted map pin
   int iUpdateDeleted = TRUE;
   int iPinID = 0;
   int iTotal = GetLocalInt(oPC, "NW_TOTAL_MAP_PINS");
   if(iTotal > 0) { iPinID = GetFirstDeletedMapPin(oPC); }
   // Otherwise use a new one
   if(iPinID == 0) { iPinID = iTotal + 1; iUpdateDeleted = FALSE; }
   // Set the pin
   string sPinID = IntToString(iPinID);
   SetLocalString(oPC, "NW_MAP_PIN_NTRY_" + sPinID, sPinText);
   SetLocalFloat(oPC, "NW_MAP_PIN_XPOS_" + sPinID, fX);
   SetLocalFloat(oPC, "NW_MAP_PIN_YPOS_" + sPinID, fY);
   SetLocalObject(oPC, "NW_MAP_PIN_AREA_" + sPinID, oArea);
   if(!iUpdateDeleted) { SetLocalInt(oPC, "NW_TOTAL_MAP_PINS", iPinID); }
   return iPinID;

void DeleteMapPin(object oPC, int iPinID)
   string sPinID = IntToString(iPinID);
   // Only mark as deleted if set
   if(GetLocalString(oPC, "NW_MAP_PIN_NTRY_" + sPinID) != "") {
       SetLocalString(oPC, "NW_MAP_PIN_NTRY_" + sPinID, "DELETED");
       SetLocalFloat(oPC, "NW_MAP_PIN_XPOS_" + sPinID, 0.0);
       SetLocalFloat(oPC, "NW_MAP_PIN_YPOS_" + sPinID, 0.0);
       SetLocalObject(oPC, "NW_MAP_PIN_AREA_" + sPinID, OBJECT_INVALID);

object GetAreaOfMapPin(object oPC, int iPinID)
   return GetLocalObject(oPC, "NW_MAP_PIN_AREA_"+IntToString(iPinID));