02-09-2009 08:20
I'm trying to improve the parts of this library radar script (minus the code bits to show time and chat range) that obtain and display the direction of the avatars. A related post had a suggestion by Hewee Zetkin using trig to determine direction:

CODE

float dir = waypoint-current;
float theta = llAtan2(dir.y, dir.x);
[\Code]

http://forums.secondlife.com/showthread.php?t=265026[URL]Each time I try, I get a mess :). Suggestions on how to do this?

[CODE]
//Sable Till - Radar/scannar script.
//You can get a copy of the license this script is under at http://www.gnu.org/copyleft/gpl.html
//Copyright (C) 2006 Sable Till

//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// mod attempt Celty

string status="none";
list people;
integer maxScanDistance=96;
vector color = <0,1,1>;
integer maxPeople = 8;
integer scanType = AGENT;
integer scanFreq=1;
integer scanDistance=10;

integer count(string name)
{
integer i = llListFindList(people, [name]);
if(i ==-1)
{
people+=[name, 0];
return 0;
}
else
{
integer count = llList2Integer(people, i+1);
people=llListReplaceList(people, [count+scanFreq], i+1, i+1);
return count;
}
}

//I'm pretty sure there's a better way to do this but I'm trying to calculate the angle between
//North and the target so I can work out which direction it is in.
float getAngle(vector me, vector target)
{
float hyp = llVecDist(me, target);
float yDiff = target.y-me.y;
float xDiff = target.x-me.x;
float angle = llSin(yDiff/hyp);
if(xDiff>0 && yDiff>0) {
return angle*RAD_TO_DEG;
}
if(xDiff>0 && yDiff<0)
{
return 90-angle*RAD_TO_DEG;
}
if(xDiff<0 && yDiff>0)
{
return angle*RAD_TO_DEG+270;
}
if(xDiff<0 && yDiff<0)
{
return angle*RAD_TO_DEG + 270;
}
return angle*RAD_TO_DEG;
}

default
{
state_entry()
{
llSensorRepeat("", "",scanType, scanDistance, PI, scanFreq);
llSetTimerEvent(15);
}

sensor(integer num_detected)
{
people=[];
string result;
integer n=-1;
integer distance=0;
integer detDist;
string name;

vector pos = llGetPos();
//get the dist, name and direction of everyone we just scanned.
for(n=0;n<num_detected && n<maxPeople;++n)
{
vector detPos = llDetectedPos(n);
detDist = (integer)llVecDist(pos, detPos);
float angle = getAngle(llGetPos(), detPos);
name = llKey2Name(llDetectedKey(n));
if(detDist<96)
{
people+=detDist;
people+=name;
people+=angle;
}
}
//sort the strided list
people = llListSort(people, 3, TRUE);
//construct settext
num_detected = llGetListLength(people)/3;
for(n=0;n<num_detected;++n)
{
detDist=llList2Integer(people, n*3);
name = llList2String(people, n*3+1);
float dir = llList2Float(people, n*3+2);
if(detDist<20)
{
integer cnt = count(name);
}
result+=" ["+(string)detDist+"m]";

if(dir < 0 || dir > 360)
{
llOwnerSay("Error:"+(string)dir+":"+name);
}
//determine which compass direction they are in.
if(dir <= 22.5)
{
result+=" N\n";
}
else
{
if(dir > 22.5 && dir <= 67.5)
{
result+=" NE\n";
}
else
{
if(dir > 67.5 && dir <= 112.5)
{
result+=" E\n";
}
else
{
if(dir > 112.5 && dir <= 157.5)
{
result+=" SE\n";
}
else
{
if(dir > 157.5 && dir <= 202.5)
{
result+=" S\n";
}
else
{
if(dir > 202.5 && dir <= 247.5)
{
result+=" SW\n";
}
else
{
if(dir > 247.5 && dir <= 292.5)
{
result+=" W\n";
}
else
{
if(dir > 292.5 && dir <= 337.5)
{
result+=" NW\n";
}
else
{
if(dir > 337.5 && dir < 360)
{
result+=" N\n";
}
}
}

}}}}}}

distance=detDist;
}

//If we detected more (or the same number of) people as maxPeople then shrink down the scan distance to just
//the distance to the furthest one. Otherwise increment it a bit in case there are people further out.
if(num_detected>=maxPeople) {
scanDistance=distance+10;
llSensorRepeat("", "",scanType, scanDistance, PI, scanFreq);
} else {
if(scanDistance<maxScanDistance) {
scanDistance+=10;
llSensorRepeat("", "",scanType, scanDistance, PI, scanFreq);
}
}

result+="\nStatus:" + status + ":" + (string)scanFreq + ":" + (string)scanDistance + ":" + (string)maxScanDistance;
//adjust max people based on the length of result
if(llStringLength(result)>254) {
maxPeople--;
llOwnerSay("Length is "+(string)llStringLength(result) +
" Decrementing maxPeople to "+(string)maxPeople);
} else {
if(llStringLength(result)<200 && num_detected>maxPeople) {
maxPeople++;
llOwnerSay("Length is "+(string)llStringLength(result) +
" Incrementing maxPeople to "+(string)maxPeople);
}
}
llSetText(result, color, 1);
}

no_sensor() {
llSetText("Status:"+status, color, 1);
maxScanDistance+=10;
llSensorRepeat("", "", scanType, maxScanDistance, PI, scanFreq);
}

//all we do here is check the sims fps and dilation and tone down our scanning if necessary.
timer() {
float fps = llGetRegionFPS();
float timeDilation = llGetRegionTimeDilation();

if(fps<35 || timeDilation <0.9) {
maxScanDistance=32;
if(scanDistance>maxScanDistance) {
scanDistance=maxScanDistance;
}
scanFreq=240;
status = "poor";
llSetTimerEvent(240);
color=<1,0,0>;
} else
{
//sim is slightly lagged, we scan every 120seconds and to a max of 64metres
if(fps<40 || timeDilation<0.95) {
maxScanDistance=64;
if(scanDistance>maxScanDistance) {
scanDistance=maxScanDistance;
}
scanFreq=30;
status = "ok";
llSetTimerEvent(120);
color=<1,1,0>;
} else
//sim is fine, we scan every second and to the max distance possible
{
maxScanDistance=96;
if(scanDistance>maxScanDistance) {
scanDistance=maxScanDistance;
}
scanFreq=1;
llSetTimerEvent(60);
status = "good";
color=<0,1,1>;
}}
llSensorRepeat("", "", scanType, scanDistance, PI, scanFreq);
}
}
[\CODE]