Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Xylor's llGetSim function

Nada Epoch
The Librarian
Join date: 4 Nov 2002
Posts: 1,423
06-12-2003 14:19
Here is a way for objects to figure out which sim they
are currently on. Its a bit complicated (we need a
true llGetSim() function!), but it works =P. In order
for you to use it, you will need a landmark in your
inventory that matches one of the names in the gMap
list. Either change the name in the gMap list to
match your landmark, or change your landmark, or
whatever.

Alternatively, you can create your own gMap list by
putting a landmark for each sim in the world into the
object, then setting USE_HARDCODED=FALSE. Once the
process is complete, say "dump map" and cut and paste
that new map back into the script. Be sure to set
USE_HARDCODED=TRUE, to speed things up.

CODE

///////////////////////////////////
// llGetSim script
//
// Original concept
// - Christopher Omega
//
// Rewrite
// - Xylor Baysklef
///////////////////////////////////

string DUMPMAP_COMMAND = "dump map";

integer GETSIM_REQUEST = 973850000;
integer GETSIM_RETURN = 973850001;
string GETSIM_ERROR_NOTFOUND = "_NOTFOUND";
string GETSIM_ERROR_NO_LMS = "_NO_LMS";
string GETSIM_ERROR_BUSY = "_BUSY";

integer gBusyCount = 0;
integer gBusyThreshhold = 3;

integer SimXSize = 257;
integer SimYSize = 257;

integer USE_HARDCODED = TRUE;
integer DEBUG = FALSE;

integer SIM_RECORD_SIZE = 3;

integer gSimIndex;
integer gNumSims;

list gSimList;
list gCoords;

list gMap = [ "", "", "Bonifacio (171, 21)", "Dore
(131, 210)", "",
"", "Oak Grove (202, 218)", "Morris (172,
176)", "Ahern (151, 103)", "",
"", "", "Rizal (233, 246)", "Lusk (180, 130)",
"",
"", "", "Tehama (14, 241)", "Perry (47, 22)",
"Kissling (122, 60)",
"", "Da Boom (176, 138)", "Freelon (151,
213)", "Clara (20, 20)", "Boardman (162, 186)",
"Immaculate (140, 127)", "Ritch (120, 84)",
"Minna (112, 150)", "Varney (111, 140)", "De Haro
(108, 132)",
"", "Zoe (128, 88)", "Natoma (118, 135)",
"Stillman (165, 116)", "",
"", "Clementina (63, 130)", "Taber (118,
110)", "", "",
"", "", "Welsh (135, 113)", "", "",
"", "Jessie (86, 166)", "Clyde (100, 183)",
"", "",
"", "Stanford (135, 35)", "Hawthorne (172,
106)", "", "",
"", "Federal (172, 173)", "Shipley (202,
35)", "", "" ];
integer gMapXSize = 12;
integer gMapYSize = 5;

string gAnchor;
integer gAnchorX;
integer gAnchorY;

string gCurrentSim;

integer gVerbose = TRUE;
integer gLocked = FALSE;
integer gBuildCoords = FALSE;

// Quick say macro for possible redirection.
Say(string message) {
if (gVerbose)
llWhisper(0, message);
else
llInstantMessage(llGetOwner(), message);
}

// This function builds a list of landmark
// object names in the inventory.
BuildSimList() {
gSimList = [];
gMap = [];
gNumSims =
llGetInventoryNumber(INVENTORY_LANDMARK);


integer i;
string Landmark;
for (i = 0; i < gNumSims; i++) {
Landmark =
llGetInventoryName(INVENTORY_LANDMARK, i);
gSimList += Landmark;
if (DEBUG) Say(Landmark);
}

gSimIndex = 0;
// Lock the map until we are done building it.
gLocked = TRUE;
gBuildCoords = TRUE;
gCoords = [];
llRequestInventoryData( llList2String(gSimList,
gSimIndex) );
}

integer CoordToOffset(float coord) {
integer Offset = llAbs((integer)coord) / SimXSize;

if (coord < 0) {
Offset *= -1;
Offset--;
}
return Offset;
}

SetMapPos(integer XPos, integer YPos, string Name) {
// Calculate the offset so we can fake
// a two dimensional array.
integer index = XPos * gMapYSize + YPos;
list lName = [ Name ];

// Remove a blank entry and replace it
// with the landmark.
gMap = llDeleteSubList(gMap, index, index);
gMap = llListInsertList(gMap, lName, index);
}

BuildMap() {
//Say( (string) gSimList );
integer SimIndex;
string SimName;
list Parsed;
integer SimXPos;
integer SimYPos;

// Calculate the map dimensions.
integer WestBorder;
integer EastBorder;
integer SouthBorder;
integer NorthBorder;

// Sort coords from West to East (x coord)
gCoords = llListSort(gCoords, 3, TRUE);

// Make a list of all y coordinates by shifting
// the gCoords list to the left one and extracting
it.
list YCoords = llList2ListStrided(
llDeleteSubList(gCoords, 0, 0),
0, -1, 3);

YCoords = llListSort(YCoords, 0, TRUE);

WestBorder = llList2Integer(gCoords, 0);
EastBorder = llList2Integer(gCoords, -3);
SouthBorder = llList2Integer(YCoords, 0);
NorthBorder = llList2Integer(YCoords, -1);

// Free up some space.
YCoords = [];

if (DEBUG) Say( (string) WestBorder + " <-> " +
(string) EastBorder + " " +
(string) SouthBorder + " <-> " +
(string) NorthBorder );

gMapXSize = EastBorder - WestBorder + 1;
gMapYSize = NorthBorder - SouthBorder + 1;

if (DEBUG) Say( (string) gMapXSize + " x " +
(string) gMapYSize );

// Create and initialize the map.
gMap = [];
integer i;
integer j;
integer k;
Say("Initializing Map...");
for (i = 0; i < (gMapXSize * gMapYSize); i++) {
gMap += "";
}

// Convert the gCoords list into a map.
while ( llGetListLength(gCoords) ) {
SimXPos = llList2Integer(gCoords, 0) -
WestBorder;
SimYPos = llList2Integer(gCoords, 1) -
SouthBorder;
SimIndex= llList2Integer(gCoords, 2);

SimName = llList2String(gSimList, SimIndex);

if (DEBUG) Say( SimName + ": (" +
(string) SimXPos + ", " +
(string) SimYPos + ")" );

// Insert this landmark into the map.
SetMapPos( SimXPos, SimYPos, SimName );

// Chop off the first record and move on to
the next.
gCoords = llDeleteSubList(gCoords, 0, 2);
}

// Free up some memory.
gSimList = [];

if (DEBUG) DumpMap();

// Set an anchor point.
SetAnchor();

Say("Build process done.");
Say("Say 'dump map' to print a hardcoded
version.");
}

DumpMap() {
// Output the map in a form that can
// be cut and pasted back into this script.
string MapLine;
integer i;
integer j;
integer k;

MapLine = "list gMap = [ \"";
for (i = 0; i < gMapXSize; i++) {
for (j = 0; j < gMapYSize; j++) {
k = i * gMapYSize + j;

MapLine += llList2String(gMap, k) + "\"";
if (j == gMapYSize - 1) {
if (i == gMapXSize - 1) {
MapLine += " ];";
}
else {
MapLine += ",";
}
}
else {
MapLine += ", \"";
}

}
Say(MapLine);
MapLine = "\t\t\"";
}

Say("integer gMapXSize = " + (string)gMapXSize +
";");
Say("integer gMapYSize = " + (string)gMapYSize +
";");
}

SetAnchor() {
// Look up a landmark (that is in the map list)
// and use that as an 'anchor' to compare against.

gNumSims =
llGetInventoryNumber(INVENTORY_LANDMARK);
if (gNumSims == 0) {
Say("No landmark to set anchor with.");
return;
}

// Just use the first landmark.
gAnchor = llGetInventoryName(INVENTORY_LANDMARK,
0);
list lAnchor = [ gAnchor ];

// Search the map for the anchor.
integer AnchorIndex = llListFindList(gMap,
lAnchor);

if (AnchorIndex == -1) {
Say("Anchor '" + gAnchor + "' not found in the
map.");
return;
}

// Split the index into x and y map coordinates.
gAnchorX = AnchorIndex / gMapYSize;
gAnchorY = AnchorIndex - gAnchorX * gMapYSize;

if (DEBUG) Say ("Anchor set to " + gAnchor + " ("
+
(string) gAnchorX + ", " +
(string) gAnchorY + ")" );
}

Activate() {
// We lock out more touches until
// the current search is finished.
if (gLocked)
return;

if (gNumSims == 0) {
Say("No landmarks to check against.");
return;
}

if (DEBUG) Say("Current Pos: " +
(string)llGetPos());

// Check against our anchor and use the map to
// find our sim.
gLocked = TRUE;
if (DEBUG) Say("Searching for current sim, please
wait...");
llRequestInventoryData( gAnchor );
}

default {
state_entry() {
if (!USE_HARDCODED) {
Say("Building Sim List.");
Say("Keep object in the same sim during
this process.");
BuildSimList();
}
else {
// Just use the hardcoded map.
SetAnchor();
}

gCurrentSim = "";

//llListen(0, "", llGetOwner(),
GETSIM_COMMAND);
llListen(0, "", llGetOwner(),
DUMPMAP_COMMAND);
}

changed(integer change) {
// If another landmark is added
// then we need to rebuild the sim list.
if (change == CHANGED_INVENTORY &&
gNumSims !=
llGetInventoryNumber(INVENTORY_LANDMARK)) {
Say("Rebuilding Sim List:");
Say("Keep object in the same sim during
this process.");
BuildSimList();
}
}

touch_start(integer total_number) {
//Activate();
}

listen(integer channel, string name, key id,
string message) {
if (message == DUMPMAP_COMMAND) {
DumpMap();
return;
}
}

link_message(integer sender, integer channel,
string mesg, key id) {
if (channel == GETSIM_REQUEST) {
if (gLocked) {
llMessageLinked(LINK_SET,
GETSIM_RETURN,
GETSIM_ERROR_BUSY,
"");

gBusyCount++;
if (gBusyCount == gBusyThreshhold)
llResetScript();
return;
}

if (gNumSims == 0) {
llMessageLinked(LINK_SET,
GETSIM_RETURN,
GETSIM_ERROR_NO_LMS,
"");
return;
}

// Check against our anchor and use the
map to
// find our sim.
gLocked = TRUE;
gBusyCount = 0;
llRequestInventoryData( gAnchor );
}
}

dataserver(key queryid, string data) {
//if (DEBUG) Say(data);

// Only run if we are locked.
if (!gLocked)
return;

vector vecLM = (vector) data;

// First check to see if are building the
coord list.
if ( gBuildCoords ) {
gCoords += CoordToOffset(vecLM.x);
gCoords += CoordToOffset(vecLM.y);
gCoords += gSimIndex;

if (DEBUG) Say( llList2String(gSimList,
gSimIndex) +
": (" + (string)vecLM.x +
", " + (string) vecLM.y +
")" );

// Move on to the next sim in the list.
gSimIndex++;

if (gSimIndex == gNumSims) {
// Done building the coord list.
gLocked = FALSE;
gBuildCoords = FALSE;

// Now we turn the coord list into a
map.
BuildMap();
return;
}

llRequestInventoryData(
llList2String(gSimList, gSimIndex) );

return;
}

integer OffsetX = gAnchorX -
CoordToOffset(vecLM.x);
integer OffsetY = gAnchorY -
CoordToOffset(vecLM.y);

integer MapIndex = OffsetX * gMapYSize +
OffsetY;
gCurrentSim = llList2String(gMap, MapIndex);
list Parsed = llParseString2List(gCurrentSim,
[" ("], []);
gCurrentSim = llList2String(Parsed, 0);

if (gCurrentSim == "") {
llMessageLinked(LINK_SET, GETSIM_RETURN,
GETSIM_ERROR_NOTFOUND,
"");
}
else {
llMessageLinked(LINK_SET, GETSIM_RETURN,
gCurrentSim, "");
}

gLocked = FALSE;
}
}


And here is an example of how to use it:

CODE

// Example script to call llGetSim

// This script displays the name of the
// current sim, and its position above the object.


///////////////////
// llGetSim header //
///////////////////
integer GETSIM_REQUEST = 973850000;
integer GETSIM_RETURN = 973850001;
string GETSIM_ERROR_NOTFOUND = "_NOTFOUND";
string GETSIM_ERROR_NO_LMS = "_NO_LMS";
string GETSIM_ERROR_BUSY = "_BUSY";

default{
state_entry() {
llSetTimerEvent(5.0);
llListen(0, "", llGetOwner(), "get sim");
llMessageLinked(LINK_SET, GETSIM_REQUEST, "",
"");
}

timer() {
llMessageLinked(LINK_SET, GETSIM_REQUEST, "",
"");
}

listen(integer channel, string name, key id,
string message) {
llMessageLinked(LINK_SET, GETSIM_REQUEST, "",
"");
}

touch_start(integer total_number) {
llMessageLinked(LINK_SET, GETSIM_REQUEST, "",
"");
}

link_message(integer sender, integer channel,
string data, key id) {
if (channel == GETSIM_RETURN) {
if (data == GETSIM_ERROR_NOTFOUND) {
llSay(0, "Sim not found.");
return;
}

if (data == GETSIM_ERROR_NO_LMS) {
llSay(0, "No landmarks.");
return;
}

if (data == GETSIM_ERROR_BUSY) {
llSay(0, "llGetSim process busy.");
return;
}

llSetText("Sim: " + data + "\n" +
(string)llGetPos(), <1, 0, 0>, 1.0);
}
}
}



created by Xylor
06-12-2003
_____________________
i've got nothing. ;)
Nada Epoch
The Librarian
Join date: 4 Nov 2002
Posts: 1,423
Discussion Thread
04-25-2005 09:05
/54/09/44202/1.html
_____________________
i've got nothing. ;)