Persistent map pins!
Posted: Thu Sep 08, 2005 12:21 pm
The thing I find most annoying about NWN PWs is the lack of persistency in the map pins. So of course, that was one of the early things that I coded for World of Greyhawk. Because it's (a) super simple, and (b) I play on other CoPaP worlds so I'm posting this code in the hopes that it will be implemented by others.
The following two functions can be placed in an include file of your choice. The first should be called in the OnClientEnter event, while the second should be called in the OnClientExit event (or, alternatively, if you wish to save the pins on every area transition, call it in the area OnExit):
The table "mappins" has the following format:
pid - Integer
xpos - Float
ypos - Float
areatag - Varchar (64)
pintext - Varchar (255)
At WoG, we use a unique integer to identify players (pid) in our tables rather than the Player Name + Character Name combination, but the code above can be easily changed to accomodate Player Name + Character Name.
The one annoying thing is that on server reset, all previously explored areas are returned to a covered state on the map, and saved pins will not show up until the player uncovers the spot the pin is in. Better than nothing. Of course, on WoG, we are going to uncover the maps (completely) of areas that a character has spent more than 12 hours (in-game time) in. (The code for that can be posted as well if anyone wants to see it... it's also super-simple.)
The following two functions can be placed in an include file of your choice. The first should be called in the OnClientEnter event, while the second should be called in the OnClientExit event (or, alternatively, if you wish to save the pins on every area transition, call it in the area OnExit):
Code: Select all
void GetMapPins (object oPC)
{
// James Surles, WoG, August 2005
int iCounter = 0;
string sCounter;
object oArea;
string sPinText;
float fXPos;
float fYPos;
string sAreaTagName;
string sPCName = GetName(oPC);
string sPlayerName = GetPCPlayerName(oPC);
string sSelect = "SELECT pintext, xpos, ypos, areatag FROM mappins WHERE (pid=" +
IntToString(GetLocalInt(oPC,"ID")) + ")";
SQLExecDirect(sSelect);
int iResult = SQLFetch();
while (iResult == SQL_SUCCESS)
{
sPinText = SQLDecodeSpecialChars(SQLGetData(1));
fXPos = StringToFloat(SQLGetData(2));
fYPos = StringToFloat(SQLGetData(3));
sAreaTagName = SQLDecodeSpecialChars(SQLGetData(4));
oArea = GetObjectByTag(sAreaTagName);
if (GetIsObjectValid(oArea))
{
iCounter++;
sCounter = IntToString(iCounter);
SetLocalString(oPC, "NW_MAP_PIN_NTRY_"+sCounter, sPinText);
SetLocalFloat(oPC, "NW_MAP_PIN_XPOS_"+sCounter, fXPos);
SetLocalFloat(oPC, "NW_MAP_PIN_YPOS_"+sCounter, fYPos);
SetLocalObject(oPC, "NW_MAP_PIN_AREA_"+sCounter, oArea);
}
iResult = SQLFetch();
}
SetLocalInt(oPC, "NW_TOTAL_MAP_PINS", iCounter);
return;
}
Code: Select all
void ExportMapPins(object oPC)
{
// James Surles, WoG, August 2005
int iCounter;
string sCounter;
object oArea;
string sPinText;
float fXPos;
float fYPos;
string sAreaTagName;
string sInsert = "";
string sPCID = IntToString(GetLocalInt(oPC,"ID"));
string sDelete = "DELETE FROM mappins WHERE (pid=" + sPCID + ")";
SQLExecDirect(sDelete);
int iNumPins = GetLocalInt(oPC, "NW_TOTAL_MAP_PINS");
if (iNumPins >= 1)
{
for (iCounter=1; iCounter <= iNumPins; iCounter++)
{
sCounter = IntToString(iCounter);
sPinText = GetLocalString(oPC, "NW_MAP_PIN_NTRY_"+sCounter);
fXPos = GetLocalFloat(oPC, "NW_MAP_PIN_XPOS_"+sCounter);
fYPos = GetLocalFloat(oPC, "NW_MAP_PIN_YPOS_"+sCounter);
oArea = GetLocalObject(oPC, "NW_MAP_PIN_AREA_"+sCounter);
if ((GetStringLength(sPinText) > 0) && GetIsObjectValid(oArea))
{
sAreaTagName = GetTag(oArea);
if (iCounter==1){
sInsert = "(" + sPCID + "," + FloatToString(fXPos) + "," + FloatToString(fYPos) +
",'" + SQLEncodeSpecialChars(sAreaTagName) + "','" + SQLEncodeSpecialChars(sPinText) + "')";
}
else{
sInsert = "(" + sPCID + "," + FloatToString(fXPos) + "," + FloatToString(fYPos) +
",'" + SQLEncodeSpecialChars(sAreaTagName) + "','" + SQLEncodeSpecialChars(sPinText) + "')" + "," + sInsert;
}
}
} // End for
sInsert = "INSERT INTO mappins (pid,xpos,ypos,areatag,pintext) VALUES " + sInsert;
SQLExecDirect(sInsert);
} // End if
return;
}
pid - Integer
xpos - Float
ypos - Float
areatag - Varchar (64)
pintext - Varchar (255)
At WoG, we use a unique integer to identify players (pid) in our tables rather than the Player Name + Character Name combination, but the code above can be easily changed to accomodate Player Name + Character Name.
The one annoying thing is that on server reset, all previously explored areas are returned to a covered state on the map, and saved pins will not show up until the player uncovers the spot the pin is in. Better than nothing. Of course, on WoG, we are going to uncover the maps (completely) of areas that a character has spent more than 12 hours (in-game time) in. (The code for that can be posted as well if anyone wants to see it... it's also super-simple.)