//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.
string status="none";
list people;
integer maxScanDistance;
vector color = <0,1,1>;
integer maxPeople = 8;
integer scanType = AGENT;
integer scanFreq=1;
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;
}
}
//calculate time strings with proper units that are sensibly rounded
string time(integer cnt) {
if(cnt>3600) {
return (string)(cnt/3600)+"hr " + (string)((cnt%3600)/60) +"min";
}else {
if(cnt>60) {
return (string)(cnt/60)+"min";
} else {
return (string)cnt+"s";
}
}
}
//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, 96, PI, scanFreq);
llSetTimerEvent(6);
}
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 && distance<=20) {
result+="<- Chat Range Limit ->\n";
}
result+=name;
if(detDist<20) {
integer cnt = count(name);
result+=" ["+time(cnt)+"]";
}
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) {
maxScanDistance=distance+10;
} else {
maxScanDistance+=10;
}
result+="\nStatus:"+status;
//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();
integer scanDistance;
if(fps<35 || timeDilation <0.9) {
if(maxScanDistance>30) {
scanDistance=30;
}
scanFreq=240;
status = "poor";
llSetTimerEvent(240);
color=<1,0,0>;
} else
{
if(fps<40 || timeDilation<0.95) {
if(maxScanDistance>64) {
scanDistance=64;
} else {
scanDistance=maxScanDistance;
}
scanFreq=30;
status = "ok";
llSetTimerEvent(120);
color=<1,1,0>;
} else
{
if(maxScanDistance>96) {
scanDistance=96;
} else {
scanDistance=maxScanDistance;
}
scanFreq=1;
llSetTimerEvent(60);
status = "good";
color=<0,1,1>;
}}
llSensorRepeat("", "", scanType, scanDistance, PI, scanFreq);
}
}