Add new files
This commit is contained in:
3
FlashLamp/FlashLamp.sol
Normal file
3
FlashLamp/FlashLamp.sol
Normal file
@@ -0,0 +1,3 @@
|
||||
<Solution name="FlashLamp">
|
||||
<Project name="FlashLamp" path="FlashLamp\FlashLamp.prj" active="true"/>
|
||||
</Solution>
|
||||
6
FlashLamp/FlashLamp/FlashLamp.prj
Normal file
6
FlashLamp/FlashLamp/FlashLamp.prj
Normal file
@@ -0,0 +1,6 @@
|
||||
<Project name="FlashLamp" guid="78cd614c-f14e-43cf-9ee7-8679767a0dad">
|
||||
<Object name="Object" guid="1c350625-e0a5-41df-9f63-840d22f72e89" active="true">
|
||||
<Script name="Flash.lsl" guid="3bfc97fd-b1bf-4318-8790-54490b09dc9c">
|
||||
</Script>
|
||||
</Object>
|
||||
</Project>
|
||||
39
FlashLamp/FlashLamp/Object/Flash.lsl
Normal file
39
FlashLamp/FlashLamp/Object/Flash.lsl
Normal file
@@ -0,0 +1,39 @@
|
||||
// :SHOW:
|
||||
// :CATEGORY:Light
|
||||
// :NAME:Flashing Light
|
||||
// :AUTHOR:Unknown
|
||||
// :KEYWORDS:Light
|
||||
// :REV:1
|
||||
// :WORLD:Opensim, Second Life
|
||||
// :DESCRIPTION:
|
||||
// Blinks a light
|
||||
// :CODE:
|
||||
|
||||
|
||||
integer root = 0 ; // change to the number of a prim that you want to flash
|
||||
float timeval = 0.1; //the interval between events, smaller = faster
|
||||
integer counter = 0;
|
||||
|
||||
On() {
|
||||
llSetLinkPrimitiveParamsFast(root,[PRIM_POINT_LIGHT, TRUE, <1,1,1>, 1.0, 10, .1, PRIM_FULLBRIGHT, ALL_SIDES,TRUE, PRIM_GLOW, ALL_SIDES, 1.0]);
|
||||
}
|
||||
Off() {
|
||||
llSetLinkPrimitiveParamsFast(root,[PRIM_POINT_LIGHT, FALSE, <1,1,1>, 1.0, 10, .1, PRIM_FULLBRIGHT, ALL_SIDES,FALSE, PRIM_GLOW, ALL_SIDES, 0.0]);
|
||||
}
|
||||
default
|
||||
{
|
||||
state_entry()
|
||||
{
|
||||
Off();
|
||||
|
||||
llSetTimerEvent(timeval); // between events
|
||||
}
|
||||
timer()
|
||||
{
|
||||
if (counter %2 == 0)
|
||||
On();
|
||||
else
|
||||
Off();
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
|
||||
integer root = 0 ; // change to the number of a prim that you want to flash
|
||||
float timeval = 0.1; //the interval between events, smaller = faster
|
||||
integer counter = 0;
|
||||
|
||||
On() {
|
||||
llSetLinkPrimitiveParamsFast(root,[PRIM_POINT_LIGHT, TRUE, <1,1,1>, 1.0, 10, .1, PRIM_FULLBRIGHT, ALL_SIDES,TRUE, PRIM_GLOW, ALL_SIDES, 1.0]);
|
||||
}
|
||||
Off() {
|
||||
llSetLinkPrimitiveParamsFast(root,[PRIM_POINT_LIGHT, FALSE, <1,1,1>, 1.0, 10, .1, PRIM_FULLBRIGHT, ALL_SIDES,FALSE, PRIM_GLOW, ALL_SIDES, 0.0]);
|
||||
}
|
||||
default
|
||||
{
|
||||
state_entry()
|
||||
{
|
||||
Off();
|
||||
}
|
||||
touch_start(integer total_number)
|
||||
{
|
||||
llSetTimerEvent(timeval); // between events
|
||||
}
|
||||
timer()
|
||||
{
|
||||
if (counter == 0)
|
||||
On();
|
||||
else if (counter == 1)
|
||||
Off();
|
||||
else if (counter == 2)
|
||||
On();
|
||||
else if (counter >= 3) {
|
||||
Off();
|
||||
counter = -1;
|
||||
llSetTimerEvent(0);
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
Submodule GameOfFireAndIce deleted from d446b50561
@@ -1,8 +1,15 @@
|
||||
//:AUTHOR: Chaser.Zaks
|
||||
|
||||
// :SHOW:
|
||||
// :CATEGORY:Meter
|
||||
// :NAME:Lag Meter
|
||||
// :AUTHOR:Chaser.Zaks
|
||||
// :KEYWORDS:Lag Meter
|
||||
// :REV:1
|
||||
// :WORLD:Opensim
|
||||
// :DESCRIPTION:
|
||||
// Lag Meter
|
||||
// :CODE:
|
||||
//Link two boxes then put the script inside.
|
||||
|
||||
//By Chaser.Zaks.
|
||||
//Feel free to redistribute and use in projects(even in sold products, just keep it open source).
|
||||
//DO NOT CLOSE SOURCE OR SELL ALONE.
|
||||
|
||||
@@ -23,65 +30,65 @@ list same_params =[PRIM_SLICE, <0.5, 1.0, 0.0>,PRIM_FULLBRIGHT,ALL_SIDES,TRUE,PR
|
||||
|
||||
default
|
||||
{
|
||||
state_entry()
|
||||
{
|
||||
state_entry()
|
||||
{
|
||||
|
||||
llSetObjectName("Open Source Lag Meter v3");
|
||||
llSetLinkPrimitiveParams(1,same_params+[PRIM_COLOR,ALL_SIDES,<0,0,0>,.4,PRIM_SIZE,<.5,.5,4>]);
|
||||
llSetLinkPrimitiveParams(2,same_params+[PRIM_COLOR,ALL_SIDES,<0,1,0>,1.,PRIM_SIZE,<.4,.4,3.8>,PRIM_POS_LOCAL,<0,0,.04>]);
|
||||
llSetText("Initalizing...",<1,1,0>, 1.0);
|
||||
//First start, Set some stuff.
|
||||
lastrestart = llGetUnixTime();
|
||||
llSetTimerEvent(0.5); //One second is too much checking. Let's not be a resource hog.
|
||||
}
|
||||
changed(integer change)
|
||||
{
|
||||
if(change & CHANGED_REGION_START)
|
||||
lastrestart = llGetUnixTime();
|
||||
}
|
||||
timer(){
|
||||
region = llGetRegionName();
|
||||
avatars = llGetListLength(llGetAgentList(AGENT_LIST_REGION, []));
|
||||
//Restart time
|
||||
lastrestartedcalc = llGetUnixTime()-lastrestart;
|
||||
days=0;
|
||||
hours=0;
|
||||
minutes=0;
|
||||
seconds=0;
|
||||
do{
|
||||
if(lastrestartedcalc>=86399){
|
||||
days++;
|
||||
lastrestartedcalc=lastrestartedcalc-86399;
|
||||
}else if(lastrestartedcalc>=3599){
|
||||
hours++;
|
||||
lastrestartedcalc=lastrestartedcalc-3599;
|
||||
}else if(lastrestartedcalc>=59){
|
||||
minutes++;
|
||||
lastrestartedcalc=lastrestartedcalc-59;
|
||||
}else{
|
||||
seconds++;
|
||||
lastrestartedcalc--;
|
||||
}
|
||||
}while(lastrestartedcalc>=0);
|
||||
float region_time_dilation=llGetRegionTimeDilation();
|
||||
if(region_time_dilation>=0.75)
|
||||
color=<0,1,0>;
|
||||
else if(region_time_dilation>=0.50)
|
||||
color=<1,1,0>;
|
||||
else
|
||||
color=<1,0,0>;
|
||||
integer primsused=llGetParcelPrimCount(llGetPos(), PARCEL_COUNT_TOTAL, MeasureNonParcelPrims);
|
||||
integer maxprims=llGetParcelMaxPrims(llGetPos(), MeasureNonParcelPrims);
|
||||
llSetText(
|
||||
"Region: "+region+
|
||||
"\nAvatars: "+(string)avatars+
|
||||
"\nPrims left: "+(string)(maxprims-primsused)+" ("+(string)primsused+"/"+(string)maxprims+")"+
|
||||
"\nDilation: "+llGetSubString((string)((1.-region_time_dilation)*100.), 0, 3)+"%"+
|
||||
"\nFPS: "+llGetSubString((string)llGetRegionFPS(), 0, 5)+
|
||||
"\nLast restart:\n"+(string)days+" Days, "+(string)hours+" Hours, "+(string)minutes+" Minutes, and "+(string)seconds+" Seconds ago.",
|
||||
//"\nLast restart:\n"+(string)days+":"+(string)hours+":"+(string)minutes+":"+(string)seconds,
|
||||
color, 1.0);
|
||||
//llSetLinkPrimitiveParamsFast(2,[PRIM_SLICE,<0,(region_time_dilation),0>,PRIM_COLOR,ALL_SIDES,color,1]);
|
||||
llSetLinkPrimitiveParamsFast(2,[PRIM_SLICE, <0.5, 1., 0.0>,PRIM_SIZE,<0.4, 0.4, 3.80*region_time_dilation>,PRIM_COLOR,ALL_SIDES,color,1]);
|
||||
}
|
||||
llSetObjectName("Open Source Lag Meter v3");
|
||||
llSetLinkPrimitiveParams(1,same_params+[PRIM_COLOR,ALL_SIDES,<0,0,0>,.4,PRIM_SIZE,<.5,.5,4>]);
|
||||
llSetLinkPrimitiveParams(2,same_params+[PRIM_COLOR,ALL_SIDES,<0,1,0>,1.,PRIM_SIZE,<.4,.4,3.8>,PRIM_POS_LOCAL,<0,0,.04>]);
|
||||
llSetText("Initalizing...",<1,1,0>, 1.0);
|
||||
//First start, Set some stuff.
|
||||
lastrestart = llGetUnixTime();
|
||||
llSetTimerEvent(0.5); //One second is too much checking. Let's not be a resource hog.
|
||||
}
|
||||
changed(integer change)
|
||||
{
|
||||
if(change & CHANGED_REGION_START)
|
||||
lastrestart = llGetUnixTime();
|
||||
}
|
||||
timer(){
|
||||
region = llGetRegionName();
|
||||
avatars = llGetListLength(llGetAgentList(AGENT_LIST_REGION, []));
|
||||
//Restart time
|
||||
lastrestartedcalc = llGetUnixTime()-lastrestart;
|
||||
days=0;
|
||||
hours=0;
|
||||
minutes=0;
|
||||
seconds=0;
|
||||
do{
|
||||
if(lastrestartedcalc>=86399){
|
||||
days++;
|
||||
lastrestartedcalc=lastrestartedcalc-86399;
|
||||
}else if(lastrestartedcalc>=3599){
|
||||
hours++;
|
||||
lastrestartedcalc=lastrestartedcalc-3599;
|
||||
}else if(lastrestartedcalc>=59){
|
||||
minutes++;
|
||||
lastrestartedcalc=lastrestartedcalc-59;
|
||||
}else{
|
||||
seconds++;
|
||||
lastrestartedcalc--;
|
||||
}
|
||||
}while(lastrestartedcalc>=0);
|
||||
float region_time_dilation=llGetRegionTimeDilation();
|
||||
if(region_time_dilation>=0.75)
|
||||
color=<0,1,0>;
|
||||
else if(region_time_dilation>=0.50)
|
||||
color=<1,1,0>;
|
||||
else
|
||||
color=<1,0,0>;
|
||||
integer primsused=llGetParcelPrimCount(llGetPos(), PARCEL_COUNT_TOTAL, MeasureNonParcelPrims);
|
||||
integer maxprims=llGetParcelMaxPrims(llGetPos(), MeasureNonParcelPrims);
|
||||
llSetText(
|
||||
"Region: "+region+
|
||||
"\nAvatars: "+(string)avatars+
|
||||
"\nPrims left: "+(string)(maxprims-primsused)+" ("+(string)primsused+"/"+(string)maxprims+")"+
|
||||
"\nDilation: "+llGetSubString((string)((1.-region_time_dilation)*100.), 0, 3)+"%"+
|
||||
"\nFPS: "+llGetSubString((string)llGetRegionFPS(), 0, 5)+
|
||||
"\nLast restart:\n"+(string)days+" Days, "+(string)hours+" Hours, "+(string)minutes+" Minutes, and "+(string)seconds+" Seconds ago.",
|
||||
//"\nLast restart:\n"+(string)days+":"+(string)hours+":"+(string)minutes+":"+(string)seconds,
|
||||
color, 1.0);
|
||||
//llSetLinkPrimitiveParamsFast(2,[PRIM_SLICE,<0,(region_time_dilation),0>,PRIM_COLOR,ALL_SIDES,color,1]);
|
||||
llSetLinkPrimitiveParamsFast(2,[PRIM_SLICE, <0.5, 1., 0.0>,PRIM_SIZE,<0.4, 0.4, 3.80*region_time_dilation>,PRIM_COLOR,ALL_SIDES,color,1]);
|
||||
}
|
||||
}
|
||||
@@ -2,45 +2,11 @@
|
||||
<Object name="Object" guid="9baa206f-8e8f-49c5-9bdb-68f814087aa8" active="true">
|
||||
<Notecard name="Appearance" guid="a83f9bbd-073d-4153-a42f-204454c5f5dc">
|
||||
</Notecard>
|
||||
<Animation name="avatar_type.bvh" guid="e32738bc-af83-41ff-b8d4-b0de28167f76">
|
||||
</Animation>
|
||||
<Script name="Chatbot Controller.lsl" guid="67003fef-115a-4643-a1b3-9997c6f8699a">
|
||||
</Script>
|
||||
<Snapshot name="Contents.png" guid="d58af53d-6de0-419e-9e69-dbbc53f0ece9">
|
||||
</Snapshot>
|
||||
<Animation name="express_anger.bvh" guid="890adf1b-d955-452f-8fdf-73c4ab35c213">
|
||||
</Animation>
|
||||
<Animation name="express_bored.bvh" guid="e5a7e747-99ca-42fa-bc38-21954b6fe040">
|
||||
</Animation>
|
||||
<Animation name="express_cry.bvh" guid="b01a0603-4b87-4bc0-b799-40514cb5971b">
|
||||
</Animation>
|
||||
<Animation name="express_embarrased.bvh" guid="f3718351-8f05-463d-899a-ac98340c139d">
|
||||
</Animation>
|
||||
<Animation name="express_laugh.bvh" guid="6bdb518f-2d62-4de1-b4b8-a5926a284f45">
|
||||
</Animation>
|
||||
<Animation name="express_repulsed.bvh" guid="e1067566-9d11-44c8-9a50-fe8dd0d1e4cf">
|
||||
</Animation>
|
||||
<Animation name="express_sad.bvh" guid="125f58fa-f68c-48e4-bc51-ca93fca3fe17">
|
||||
</Animation>
|
||||
<Animation name="express_shrug.bvh" guid="f0b7623e-d54e-439f-85ce-f92c35c23565">
|
||||
</Animation>
|
||||
<Animation name="express_surprise.bvh" guid="4daff0ba-d8b1-42c0-ba4c-e51803cfd3bc">
|
||||
</Animation>
|
||||
<Animation name="express_wink.bvh" guid="4ac174ee-6c0b-4ce4-a169-2d78f9f1ea0a">
|
||||
</Animation>
|
||||
<Animation name="express_worry.bvh" guid="fdd53f1b-02c5-483a-bdb4-3aeb26e7de8f">
|
||||
</Animation>
|
||||
<Script name="NPC Control Script.lsl" guid="53d8301f-24d0-4ee9-8e2f-e360d7e189d4">
|
||||
</Script>
|
||||
<Notecard name="Path" guid="dee10dda-f71d-4466-9a43-b16e7dad21cb">
|
||||
</Notecard>
|
||||
<Notecard name="README.txt" guid="345ed00a-fdc2-40a0-8ba1-b6a6bd202d44">
|
||||
</Notecard>
|
||||
<Animation name="Sit.bvh" guid="6ecd8304-9f1b-413c-b1af-1ebcfb82cdc9">
|
||||
</Animation>
|
||||
<Animation name="Stand.bvh" guid="7510d1bd-d168-4454-8076-e602e32e8160">
|
||||
</Animation>
|
||||
<Animation name="Walk.bvh" guid="918f026b-e3a6-41bf-8d9b-50ec90d18f7b">
|
||||
</Animation>
|
||||
</Object>
|
||||
</Project>
|
||||
|
||||
@@ -1,15 +1 @@
|
||||
// :SHOW:
|
||||
// :CATEGORY:ChatBot
|
||||
// :NAME:NPC Chatbot for Opensim
|
||||
// :AUTHOR:Ferd Frederix
|
||||
// :KEYWORDS:
|
||||
// :CREATED:2016-07-27 16:13:54
|
||||
// :EDITED:2016-07-27 15:13:54
|
||||
// :ID:1108
|
||||
// :NUM:1905
|
||||
// :REV:1.0
|
||||
// :WORLD:OpenSim
|
||||
// :DESCRIPTION:
|
||||
// Sample Apperance notecard
|
||||
// :CODE:
|
||||
Appearance notecard will be made here
|
||||
Appearance notecard goes here
|
||||
@@ -1,40 +1,31 @@
|
||||
// :SHOW:
|
||||
// :CATEGORY:ChatBot
|
||||
// :NAME:NPC Chatbot for Opensim
|
||||
// :AUTHOR:Fred Beckhusen (Ferd Frederix)
|
||||
// :KEYWORDS:
|
||||
// :CREATED:2016-07-27 16:13:55
|
||||
// :EDITED:2016-07-27 15:13:55
|
||||
// :ID:1108
|
||||
// :NUM:1906
|
||||
// :NAME:PersonalityForge Chatbot
|
||||
// :AUTHOR:Ferd Frederix
|
||||
// :REV:1.0
|
||||
// :WORLD:OpenSim
|
||||
// :WORLD:Second Life, OpenSim
|
||||
// :DESCRIPTION:
|
||||
// This chatbot is for OpenSim Only. It only works on NPC's with a modified All-In-One NPC script, which is also included
|
||||
// This chatbot is for OpenSim Only. It only works on NPC's.
|
||||
|
||||
// Chatbot for PersonalityForge. Get a free account at http://www.personalityforge.com.
|
||||
// 5,000 chats are free.
|
||||
// :CODE:
|
||||
// Chatbot uses PersonalityForge. Get a free account at http://www.personalityforge.com.
|
||||
// first, get a free account at http://www.personalityforge.com.
|
||||
// fiorst, get a free account at http://www.personalityforge.com.
|
||||
// Get an API ID, and add it to the apiKey :
|
||||
|
||||
string apiKey = "BlahBlah"; // your supplied apiKey from your Chat Bot API subscription
|
||||
|
||||
|
||||
// Add the domain or IP of your OpenSim server to the list of authorized domains at http://www.personalityforge.com/botland/myapi.php
|
||||
// Add a checkmark to the "Enable Simple API" in your account.
|
||||
string apiKey = "keU6Hv3tbk318wn1"; // your supplied apiKey from your Chat Bot API subscription
|
||||
|
||||
// Add the domain *.secondlife.com or your OpenSim server IP to the list of authorized domains at http://www.personalityforge.com/botland/myapi.php
|
||||
// Add a checkmark to the "Enable Simple API" in tyour account.
|
||||
// Click on the Simple API tab and pick a chatbot ID from the list of chatbots under the heading "Selecting A Chat Bot ID"
|
||||
// for example, Countess Elvira is 99232. Put that in chatBot ID below.
|
||||
// Sex Bot Ciran is 100387.
|
||||
// 754 is Liddora a sexy tart
|
||||
|
||||
string chatBotID = "23958"; // the ID of the chat bot you're talking to
|
||||
|
||||
// The first time, you may want to test it with this set to TRUE
|
||||
integer debug = FALSE; // Set this TRUE to see the gory details
|
||||
|
||||
// more constants below
|
||||
integer greeting = TRUE; // if TRUE, say hello when anyone comes up.
|
||||
integer greeting = TRUE; // if TRUE, say hello when anyone comes up.
|
||||
|
||||
integer lookat = FALSE;
|
||||
integer debug = FALSE; // Set this TRUE to see the gory details
|
||||
|
||||
////////// REMOVE THESE IN WORLD ////////////////
|
||||
///////// LSLEDIT DEBUG ONLY////////////////////
|
||||
@@ -45,7 +36,7 @@ integer lookat = FALSE;
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// various tuneable code bits
|
||||
float range = 35; // haw far away an avatar is before we greet them/. No point in making this more than 20, that cannot hear us after that
|
||||
float range = 35; // haw far awy an avatar is before we greet them/. No point in making this more than 20, that cannot hear us after that
|
||||
float wpm = 85; // 33 wpm = 2.75 cps @ 5 chars per word for a typical avatar to type with.
|
||||
// Larger numbers make your NPC answer quicker.
|
||||
float cps;
|
||||
@@ -104,6 +95,7 @@ string KeyValueGet(string var) {
|
||||
|
||||
default
|
||||
{
|
||||
|
||||
on_rez(integer param)
|
||||
{
|
||||
llResetScript();
|
||||
|
||||
@@ -1,24 +1,34 @@
|
||||
// :SHOW:
|
||||
// :CATEGORY:ChatBot
|
||||
// :NAME:NPC Chatbot for Opensim
|
||||
// :AUTHOR:Fred Beckhusen (Ferd Frederix)
|
||||
// :CATEGORY:NPC
|
||||
// :NAME:All_in_1_NPC_Recorder_and_Player
|
||||
// :AUTHOR:Ferd Frederix
|
||||
// :KEYWORDS:
|
||||
// :CREATED:2016-07-27 16:14:00
|
||||
// :EDITED:2016-07-27 15:14:00
|
||||
// :ID:1108
|
||||
// :NUM:1907
|
||||
// :REV:1.0
|
||||
// :CREATED:2013-09-08 18:27:47
|
||||
// :ID:27
|
||||
// :NUM:1612
|
||||
// :REV:1.6
|
||||
// :WORLD:OpenSim
|
||||
// :DESCRIPTION:
|
||||
// Modified All in one NPC recorder player for NPC use
|
||||
// All in one NPC recorder player.
|
||||
// Supports both absolute and relative paths and many new commands
|
||||
// Add animations named "Fly, Walk, Stand and Run"
|
||||
// Click Prim to use.
|
||||
|
||||
// Should be worn as a HUD to record.
|
||||
// Put it on the ground and click Sensor or Start NPC when done.
|
||||
// :CODE:
|
||||
// Rev 1.6 5-24-2014
|
||||
|
||||
// Rev 1.1 10-2-2014 @Sit did not work. Minor tweaks to casting for lslEditor
|
||||
// Rev 1.2 10-14-2014 @ sit had wrong type.
|
||||
// Rev 1.3 relative movement fixed for @fly
|
||||
// Rev 1.4 4-3-2014 allow anyone to use this, non owners and non group members can only start and stop.
|
||||
// Rev 1.5 5-17-2014 set sensor to auto start on reboot of sim
|
||||
// Rev 1.6 5-24-2014 move menu so you can get it by touching, removed many of the KeyValues to RAM for efficiency
|
||||
|
||||
|
||||
//*******************************************************************//
|
||||
// Instructions on how to use this is at http://www.free-lsl-scripts.com/opensim/posts/NPC/
|
||||
// This is an OpenSim-only script.
|
||||
// Author: Fred Beckhusen (Ferd Frederix)
|
||||
// Author: Ferd Frederix
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -28,7 +38,7 @@
|
||||
// rights of fair usage, the disclaimer and warranty conditions. //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// The original NPC controller was from http://was.fm/opensim:npc
|
||||
// Extensive additions and bug fixes by Fred Beckhusem, aka Fred Beckhusen (Ferd Frederix), fred@mitsi.com
|
||||
// Extensive additions and bug fixes by Fred Beckhusem, aka Ferd Frederix, fred@mitsi.com
|
||||
// llSensor had two params swapped
|
||||
// @Wander would wander where it had rezzed, not where it was.
|
||||
// There was no 'no_sensor' event in sit, so if a @sit failed, the NPC got stuck
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
// :SHOW:
|
||||
// :CATEGORY:ChatBot
|
||||
// :NAME:NPC Chatbot for Opensim
|
||||
// :AUTHOR:Ferd Frederix
|
||||
// :KEYWORDS:
|
||||
// :CREATED:2016-07-27 16:14:00
|
||||
// :EDITED:2016-07-27 15:14:00
|
||||
// :ID:1108
|
||||
// :NUM:1908
|
||||
// :REV:1.0
|
||||
// :WORLD:OpenSim
|
||||
// :DESCRIPTION:
|
||||
// Sample Path notecard
|
||||
// :CODE:
|
||||
|
||||
@spawn=Tinker@www.outworldz.com|<0.000000,0.000000,0.500000>
|
||||
@walk=<0,-8,0.5>
|
||||
@sit=LayDown
|
||||
|
||||
9
Opensim Train/Train/Opensim Train/Object/NoteCard.txt
Normal file
9
Opensim Train/Train/Opensim Train/Object/NoteCard.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
SOME NOTES ABOUT THIS SCRIPT
|
||||
|
||||
I'm more of a script hacker than a script editor, and I decided to hack this script. I got rid of the Guide prims and got it to run ON the MESH TRACK! I did this by editing the script and replacing the value of gsSensorTargetName from Guide to Freight. Then I renamed each mesh track to Freight. I found this mostly worked just as well.
|
||||
|
||||
Of course when laying track there's issues for sharp curves and sim borders, no matter what the Guides are called. On the sharp curves I didn't rename the track but simply added the old guides and renamed them as Freight, adding enough for the engine to take the curve. On the sim boarder I put two guides - one on either side - so that their centres were close to the boarder. If I didn't have the curve guides close enough to each other and the straight track, or close enough to the boarder, the script assumes it's the end of the line and reverses! Also, the mesh track's 18.5m long. I extended the rail line by changing to LOCAL mode, duplicating a Freight by pressing SHIFT and moving it 1/2 its length along, then changing its horizontal rotation slightly, and moving it along by another 1/2 length. This works up to 18.5m long, but 20m breaks the line.
|
||||
|
||||
Why use Freight instead of Guide? It occurred to me the key to this script is how the script finds the next guide in the rail line, and that's done by looking for the correct name. But why only have ONE name for guides. You could have several overlapping transparent sets of guides, each one with the name of the service that runs on it. e.g. "Freight" and "Passenger". Ideally it's be good if for example you could also have a "Shared" guide that different services all use, but I'm not sure how to make that happen yet. Also, perhaps when an engine gets to the end of the line and detects that, it not only reverses the engine, but changes gsSensorTargetName to a different value (e.g. "Up" is changed to "Down") and then it returns down a DIFFERENT track/guides!
|
||||
|
||||
Just some ideas. I'm excited that the script works. I really need to learn LSL.
|
||||
1518
Opensim Train/Train/Opensim Train/Object/Opensim Train.lsl
Normal file
1518
Opensim Train/Train/Opensim Train/Object/Opensim Train.lsl
Normal file
File diff suppressed because it is too large
Load Diff
8
Opensim Train/Train/Opensim Train/Opensim Train.prj
Normal file
8
Opensim Train/Train/Opensim Train/Opensim Train.prj
Normal file
@@ -0,0 +1,8 @@
|
||||
<Project name="Opensim Train" guid="932dca8f-78b8-4161-a7ea-311d976591dc">
|
||||
<Object name="Object" guid="6d5198cb-a5ed-47d9-b6a7-40e07b60e223" active="true">
|
||||
<Notecard name="NoteCard.txt" guid="1bcc799e-59fc-40d5-9d00-21012d7d47e2">
|
||||
</Notecard>
|
||||
<Script name="Opensim Train.lsl" guid="17e8cca7-08f4-4437-9822-957494ba26ca">
|
||||
</Script>
|
||||
</Object>
|
||||
</Project>
|
||||
3
Opensim Train/Train/Train.sol
Normal file
3
Opensim Train/Train/Train.sol
Normal file
@@ -0,0 +1,3 @@
|
||||
<Solution name="Train">
|
||||
<Project name="Opensim Train" path="Opensim Train\Opensim Train.prj" active="true"/>
|
||||
</Solution>
|
||||
@@ -1,3 +1,14 @@
|
||||
// :SHOW:
|
||||
// :CATEGORY:Meter
|
||||
// :NAME:Visitor Display
|
||||
// :AUTHOR:Unknown
|
||||
// :KEYWORDS:Visitor Display
|
||||
// :REV:1
|
||||
// :WORLD:Opensim
|
||||
// :DESCRIPTION:
|
||||
// Visitor Display using OsDrawText
|
||||
// :CODE:
|
||||
|
||||
|
||||
list gDetected = [];
|
||||
list gVisitors = [];
|
||||
@@ -6,112 +17,112 @@ string gTime = "";
|
||||
|
||||
display()
|
||||
{
|
||||
string body = "width:512,height:512,aplha:FALSE,bgcolour:black";
|
||||
string draw = "";
|
||||
string log = "";//~ visitatori ~";
|
||||
string ad0 = " * Welcome to My World * \n";
|
||||
string ad1 = "";
|
||||
string ad2 = "";
|
||||
|
||||
integer visitors = llGetListLength(gVisitors) / 3;
|
||||
|
||||
while(visitors--)
|
||||
{
|
||||
log = log + "\n"
|
||||
+ llList2String(gVisitors, visitors * 3 + 2) + " - "
|
||||
+ llList2String(gVisitors, visitors * 3 + 1) + " - "
|
||||
+ llList2String(gVisitors, visitors * 3);
|
||||
}
|
||||
|
||||
draw = osSetFontSize(draw, 12);
|
||||
draw = osMovePen(draw, 16, 16);
|
||||
draw = osSetPenColor(draw, "white");
|
||||
draw = osDrawText(draw, ad2 + "\n" + ad0 + "\n"+ ad1 + "\n" + log);
|
||||
|
||||
osSetDynamicTextureDataBlendFace("", "vector", draw, body, FALSE, 2, 0, FALSE, 4);
|
||||
string body = "width:512,height:512,aplha:FALSE,bgcolour:black";
|
||||
string draw = "";
|
||||
string log = "";//~ visitatori ~";
|
||||
string ad0 = " * Welcome to My World * \n";
|
||||
string ad1 = "";
|
||||
string ad2 = "";
|
||||
|
||||
integer visitors = llGetListLength(gVisitors) / 3;
|
||||
|
||||
while(visitors--)
|
||||
{
|
||||
log = log + "\n"
|
||||
+ llList2String(gVisitors, visitors * 3 + 2) + " - "
|
||||
+ llList2String(gVisitors, visitors * 3 + 1) + " - "
|
||||
+ llList2String(gVisitors, visitors * 3);
|
||||
}
|
||||
|
||||
draw = osSetFontSize(draw, 12);
|
||||
draw = osMovePen(draw, 16, 16);
|
||||
draw = osSetPenColor(draw, "white");
|
||||
draw = osDrawText(draw, ad2 + "\n" + ad0 + "\n"+ ad1 + "\n" + log);
|
||||
|
||||
osSetDynamicTextureDataBlendFace("", "vector", draw, body, FALSE, 2, 0, FALSE, 4);
|
||||
}
|
||||
|
||||
|
||||
string time()
|
||||
{ //0123 4 56 7 89 0 12 3 45
|
||||
//YYYY - MM - DD T hh : mm:ss.ff..fZ
|
||||
string now = llGetTimestamp();
|
||||
return llGetSubString(now,0,9) + " " +
|
||||
llGetSubString(now,11,15);
|
||||
//YYYY - MM - DD T hh : mm:ss.ff..fZ
|
||||
string now = llGetTimestamp();
|
||||
return llGetSubString(now,0,9) + " " +
|
||||
llGetSubString(now,11,15);
|
||||
}
|
||||
|
||||
|
||||
string duration(string timeIn, string timeOut)
|
||||
{
|
||||
integer came = ((integer)llGetSubString(timeIn,11,12) * 60) + (integer)llGetSubString(timeIn,14,15);
|
||||
integer went = ((integer)llGetSubString(timeOut,11,12) * 60) + (integer)llGetSubString(timeOut,14,15);
|
||||
|
||||
if (came == went) if(llGetSubString(timeIn,8,9) != llGetSubString(timeOut,8,9)) went = went + 1440;
|
||||
|
||||
if (came > went) went = went + 1440;
|
||||
went = went - came;
|
||||
|
||||
return llGetSubString("00" + (string)((went - (went % 60)) / 60), -2, -1) + ":" +
|
||||
llGetSubString("00" + (string)(went % 60), -2, -1);
|
||||
integer came = ((integer)llGetSubString(timeIn,11,12) * 60) + (integer)llGetSubString(timeIn,14,15);
|
||||
integer went = ((integer)llGetSubString(timeOut,11,12) * 60) + (integer)llGetSubString(timeOut,14,15);
|
||||
|
||||
if (came == went) if(llGetSubString(timeIn,8,9) != llGetSubString(timeOut,8,9)) went = went + 1440;
|
||||
|
||||
if (came > went) went = went + 1440;
|
||||
went = went - came;
|
||||
|
||||
return llGetSubString("00" + (string)((went - (went % 60)) / 60), -2, -1) + ":" +
|
||||
llGetSubString("00" + (string)(went % 60), -2, -1);
|
||||
}
|
||||
|
||||
|
||||
detectVisitorInOut(list avatars)
|
||||
{
|
||||
integer avatar = llGetListLength(avatars);
|
||||
string name = "";
|
||||
|
||||
while(avatar--)
|
||||
{
|
||||
name = llList2String(avatars, avatar);
|
||||
if (llSubStringIndex((string)gDetected, name) == -1) gVisitors = gVisitors + [name, "00:00", gTime];
|
||||
|
||||
if (llGetListLength(gVisitors) >= 63) gVisitors = llDeleteSubList(gVisitors, 0, 2);
|
||||
}
|
||||
|
||||
avatar = llGetListLength(gDetected);
|
||||
name = "";
|
||||
|
||||
while(avatar--)
|
||||
{
|
||||
name = llList2String(gDetected, avatar);
|
||||
if (llSubStringIndex((string)avatars, name) == -1)
|
||||
{
|
||||
integer position = llListFindList(gVisitors, [name, "00:00"]) + 1;
|
||||
string time = duration(llList2String(gVisitors, position + 1), gTime);
|
||||
gVisitors = llListReplaceList(gVisitors, [time], position, position);
|
||||
}
|
||||
}
|
||||
integer avatar = llGetListLength(avatars);
|
||||
string name = "";
|
||||
|
||||
while(avatar--)
|
||||
{
|
||||
name = llList2String(avatars, avatar);
|
||||
if (llSubStringIndex((string)gDetected, name) == -1) gVisitors = gVisitors + [name, "00:00", gTime];
|
||||
|
||||
if (llGetListLength(gVisitors) >= 63) gVisitors = llDeleteSubList(gVisitors, 0, 2);
|
||||
}
|
||||
|
||||
avatar = llGetListLength(gDetected);
|
||||
name = "";
|
||||
|
||||
while(avatar--)
|
||||
{
|
||||
name = llList2String(gDetected, avatar);
|
||||
if (llSubStringIndex((string)avatars, name) == -1)
|
||||
{
|
||||
integer position = llListFindList(gVisitors, [name, "00:00"]) + 1;
|
||||
string time = duration(llList2String(gVisitors, position + 1), gTime);
|
||||
gVisitors = llListReplaceList(gVisitors, [time], position, position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
visitorOut()
|
||||
{
|
||||
integer avatar = llGetListLength(gDetected);
|
||||
string name = "";
|
||||
|
||||
while(avatar--)
|
||||
{
|
||||
name = llList2String(gDetected, avatar);
|
||||
integer position = llListFindList(gVisitors, [name, "00:00"]) + 1;
|
||||
string time = duration(llList2String(gVisitors, position + 1), gTime);
|
||||
gVisitors = llListReplaceList(gVisitors, [time], position, position);
|
||||
}
|
||||
integer avatar = llGetListLength(gDetected);
|
||||
string name = "";
|
||||
|
||||
while(avatar--)
|
||||
{
|
||||
name = llList2String(gDetected, avatar);
|
||||
integer position = llListFindList(gVisitors, [name, "00:00"]) + 1;
|
||||
string time = duration(llList2String(gVisitors, position + 1), gTime);
|
||||
gVisitors = llListReplaceList(gVisitors, [time], position, position);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
default
|
||||
{
|
||||
state_entry() { llSetTimerEvent(10.0); }
|
||||
state_entry() { llSetTimerEvent(10.0); }
|
||||
|
||||
timer()
|
||||
{
|
||||
list avatarList = osGetAgents();
|
||||
timer()
|
||||
{
|
||||
list avatarList = osGetAgents();
|
||||
|
||||
if ((string)avatarList != (string)gDetected)
|
||||
{
|
||||
gTime = time();
|
||||
if ((string)avatarList != (string)gDetected)
|
||||
{
|
||||
gTime = time();
|
||||
|
||||
if (avatarList != []) detectVisitorInOut(avatarList);
|
||||
else visitorOut();
|
||||
if (avatarList != []) detectVisitorInOut(avatarList);
|
||||
else visitorOut();
|
||||
|
||||
gDetected = avatarList;
|
||||
display();
|
||||
}
|
||||
}
|
||||
gDetected = avatarList;
|
||||
display();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Paramour Traffic Monitor/Paramour Traffic Monitor.sol
Normal file
3
Paramour Traffic Monitor/Paramour Traffic Monitor.sol
Normal file
@@ -0,0 +1,3 @@
|
||||
<Solution name="Paramour Traffic Monitor">
|
||||
<Project name="Paramour Traffic Monitor" path="Paramour Traffic Monitor\Paramour Traffic Monitor.prj" active="true"/>
|
||||
</Solution>
|
||||
@@ -0,0 +1,60 @@
|
||||
// :SHOW:
|
||||
// :CATEGORY:Region Traffic Monitor
|
||||
// :NAME:Region Traffic Monitor Stats Retriever
|
||||
// :AUTHOR:Aine Caoimhe
|
||||
// :KEYWORDS:Region Traffic Monitor
|
||||
// :REV:2.0
|
||||
// :WORLD:Opensim, Second Life
|
||||
// :DESCRIPTION:
|
||||
// Paramour Stats Retriever
|
||||
// :CODE:
|
||||
|
||||
|
||||
|
||||
PARAMOUR REGION TRAFFIC MONITOR AND STATS RETRIEVER v2.0
|
||||
by Aine Caoimhe (LACM) Sept. 2015
|
||||
|
||||
This is a region traffic monitor and greeter script and companion detailed stats retriever intended for high volume regions where the greeter needs to have the minimum possible impact on the region, particularly at peak traffic times.
|
||||
|
||||
I accomplished this by streamlining many of the functions in the basic script v1.0 that I released 2+ years ago, and by altering the storage mechanism somewhat to both spread out the "hit" and to allow it to be used in a very high traffic region where the total visitor count could exceed the ~750 record storage capability limit of a notecard. Now, each month's traffic data is held on a separate notecard and, for further efficiency, tracking is done using UNIC timestamps. Since those aren't particularly human-friendly to read, I've added an optional "reporting" module (the Stats Retriever) that will parse and convert a selected month's data into a list showing day of the week, date and time of each person's visit as well as which grid they call home. There is a summary of that month's traffic supplied at the top. This is handed to the owner as a separate notecard that they can archive or use for whatever other purpose they wish.
|
||||
|
||||
I removed the ability to give Notecards and/or Landmarks as part of the greeter's functions because doing so invokes a rather nasty 2-second thread-locking function that is utterly unsuitable for high traffic regions. Instead, I suggest you place a separate box of these nearby and set it to sell the contents to someone. This transfers the contents without locking up precious script threads. Your greeting message can inform the visitor where to pick those up.
|
||||
|
||||
This script is a region-wide one (it detects and greets anyone entering the region, not just the parcel, and there is no range limit (even on huge vars!). It does require the use of OSSL functions to achieve this (and to store its data)
|
||||
|
||||
You can use the box this comes in as your greeter and put it anywhere in the region you like; or you can pull the scripts out and place them in any other object you like.
|
||||
|
||||
INSTRUCTIONS
|
||||
|
||||
ENSURE OSSL FUNCTIONS ARE ENABLED IN THE REGION
|
||||
The scripts use the following OSSL functions:
|
||||
osGetAvatarList() used to poll who is in the region
|
||||
osGetNotecard() to retrive stored data
|
||||
osMakeNotecard() to presist data reliably
|
||||
osGetGridName() to find out what grid this script is running in
|
||||
osIsNpc() to avoid greeting NPCs
|
||||
|
||||
Details for how to enable OSSL may be found at www.Opensimulator.org
|
||||
|
||||
REZ OR INSERT THE SCRIPTS
|
||||
Either rez the greeter box and use it as your greeter (you'll probably want to change the box's name) or take a copy of the scripts (and this readme notecard) and place them in any existing object in the region to have it act as your greeter.
|
||||
|
||||
The "Stats Retriever" script it optional and if you're content with the basic "floaty stats" report above the greeter you can omit it entirely. You can also add or remove it later since it does all of its work on touch and is otherwise dormant.
|
||||
|
||||
CONFIGURE THE SCRIPTS
|
||||
Both scripts are DISABLED BY DEFAULT to allow you to do the initial configuration settings. Then, once you're ready to use it, simply enable them (see below).
|
||||
|
||||
3.1 Configuring the main Region Traffic Monitor script
|
||||
The top section of the script contains a variety of customizable settings for the monitor that you might wish to adjust. Instructions for each one are contained in the body of the script.
|
||||
Once you're satisfied with the settings, change line 39 to read:
|
||||
integer enabled=TRUE;
|
||||
then save. This will enable the monitor and it will begin to do its thing.
|
||||
|
||||
3.2 Configuring the Stats Retriever script
|
||||
There are no user settings for this script other than to enable or disable it. Once you're ready to use it simply change line 15 to read:
|
||||
integer enabled=TRUE;
|
||||
then save. You will then be able to touch the greeter to obtain the reports. Only the owner can do so.
|
||||
|
||||
LICENSE
|
||||
Both scripts are provided under Creative Commons Attribution-Non-Commercial-ShareAlike 4.0 International license. Please be sure you read and adhere to the terms of this license: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
You can further customize or modify either to meet your own needs.
|
||||
@@ -0,0 +1,348 @@
|
||||
// :SHOW:
|
||||
// :CATEGORY:Region Traffic Monitor
|
||||
// :NAME:Region Traffic Monitor Stats Retriever
|
||||
// :AUTHOR:Aine Caoimhe
|
||||
// :KEYWORDS:Region Traffic Monitor
|
||||
// :REV:2.0
|
||||
// :WORLD:Opensim, Second Life
|
||||
// :DESCRIPTION:
|
||||
// Paramour Stats Retriever
|
||||
// :CODE:
|
||||
|
||||
|
||||
// Paramour Region Traffic Monitor v2.0
|
||||
// By Aine Caoimhe (LACM) Sept 2015
|
||||
// Provided under Creative Commons Attribution-Non-Commercial-ShareAlike 4.0 International license.
|
||||
// Please be sure you read and adhere to the terms of this license: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
//
|
||||
// This version of the region greeter is designed to handle potentially extremely high traffic areas where the number of
|
||||
// unique visitors can exceed the store limits of a single notecard. I have also altered the store logic to make it more
|
||||
// suitable for high traffic locations as well (much lower load). This new version will still fail if you have more than
|
||||
// approximately 750 unique visitors in a single month (notecards can hold only 64KB of data and any attempt to write
|
||||
// more than this fails will result in a blank notecard without generating any error/warning in world or in console).
|
||||
// The exact failure point depends on the lengths of each visitor's name so it could conceivably fail with fewer than
|
||||
// this, or succeed with even 1000 unique visitors...it all depends on the total character count.
|
||||
//
|
||||
// This version DOES NOT include option to give landmarks or notecards to new visitors since this invokes a rather nasty
|
||||
// 3-second thread-lock I consider inappropriate for the kind of region this is intended to serve. Instead, I suggest
|
||||
// putting a separate box nearby that contains those items and is set to touch-to-buy-contents (which results in the
|
||||
// same thing for the visitor but without the painful thread-lock).
|
||||
//
|
||||
// The script tracks user visits by UNIX time (UTC) and uses it for internal calculations so roll-over to a new day
|
||||
// occurs at midnight UTC in all storage and reports. Someone who visits multiple times in a single month will only
|
||||
// be listed once in that month's log, using the date/time of their last visit during that period
|
||||
//
|
||||
// There is an option to display stats as floaty text above the prim containing the script. These stats update each time
|
||||
// someone new enters the region, or hourly if there have been no changes during the previous 60 minutes
|
||||
//
|
||||
// Set the paramters as desired in the User Settings section below or leave them at their suggested defaults if you wish.
|
||||
//
|
||||
// **** REQUIRES OSSL ENABLED IN THE REGION AND SUFFICIENT PERMISSIONS FOR THE SCRIPT OWNER ****
|
||||
// Uses the following OSSL functions:
|
||||
// - osGetAvatarList() used to poll who is in the region
|
||||
// - osGetNotecard() to retrive stored data
|
||||
// - osMakeNotecard() to presist data reliably
|
||||
// - osGetGridName() to find out what grid this script is running in
|
||||
// - osIsNpc() to avoid greeting NPCs
|
||||
//
|
||||
// * * * * * * * * * * * *
|
||||
// * * USER SETTINGS * *
|
||||
// * * * * * * * * * * * *
|
||||
//
|
||||
integer enabled=FALSE;
|
||||
// TRUE = this script is enabled.....FALSE = this script is disabled and you can make other adjustments to the settings without it going through its normal routines
|
||||
// Set it to TRUE to start using the script
|
||||
//
|
||||
// Set the following according to your preferences
|
||||
float pollRate=30.0;
|
||||
// how often (in seconds) to check for a new visitor...shorter values induce higher sim load
|
||||
//
|
||||
float persistDelay=300.0;
|
||||
// when there is new data to persist, how long to wait (in seconds) before writing the notecard. If someone else arrives during this time
|
||||
// the persist timer is reset. This ensures that the action of storing the new notecard doesn't contribute to sim lag during the initial
|
||||
// heavy hit of a login. Keep in mind when shutting down a
|
||||
//
|
||||
string firstGreetMessage="Welcome, $name. Thank you for visiting my region.";
|
||||
// This message will be shown to the guest only on their very first visit. Use the special wildcard string "$name" which will be replaced
|
||||
// by the person's actual name when they are greeted. Replace this generic text with anything you like.
|
||||
//
|
||||
string repeatGreetMessage="Welcome back, $name. Please enjoy your stay.";
|
||||
// This message will be shown on all subsequent visits by a guest. Again, $name will be replaced by the guest's actual name.
|
||||
//
|
||||
integer notifyOwner=TRUE;
|
||||
// TRUE = when someone new enters the region tell the owner who arrived (using region chat if possible)
|
||||
/// FALSE = don't notify the owner
|
||||
//
|
||||
// IMPORTANT!!!!!! DO NOT ENABLE THIS NEXT FEATURE IN ANY HIGH TRAFFIC REGION UNLESS YOU WILL ALWAYS BE PRESENT IN THE REGION AT HIGH TRAFFIC TIMES!!!!!!!
|
||||
// The setting above only notifies you when you're in the region. To be notified when you're in another region requires enabling the next option which will instant-message you
|
||||
// but the function used to send the message requires the use of a VERY NASTY 2-second threadlock function which can result in severe reduction to the
|
||||
// performance of the simulator if used too frequently. You can easily use the reporting functions to find out who has visited the region so only enable this if you absolutely need
|
||||
// to be told immediately when someone arrives, and you should go to that region as soon as possible and remain there if you expect more visitors since each
|
||||
// new arrival will apply this same hit. I only included it as an option at all due to popular request and I won't be sympathetic if its use lags or even crashes your simulator.
|
||||
integer messageOwner=FALSE;
|
||||
// IGNORED if notifyOwner is set to FALSE
|
||||
// TRUE = if the owner is not in the region, send an instant message to the owner to notify then when someone enters. NOT RECOMMENDED!!!!!!!
|
||||
// FALSE = don't message the owner
|
||||
//
|
||||
integer showFloatyStats=TRUE;
|
||||
vector floatyColour=<0.0, 1.0, 0.0>;
|
||||
float floatyAlpha=1.0;
|
||||
// showFloatyStats = TRUE - the sim visitor stats will be shown as floaty text above the prim that contains the script
|
||||
// showFloatyStats = FALSE - no floaty text stats
|
||||
// If you turn on floaty stats, the floatyColour and floatyAlpha control the colour and transparancy of the text using the
|
||||
// standard LSL RGB colour vector (<0,0,0> = black, <1,1,1> = white) and alpha (0.0=invisible, 1.0 = opaque). If off, they're ignored
|
||||
//
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
// DON'T CHANGE ANYTHING BELOW HERE UNLESS YOU KNOW WHAT YOU'RE DOING
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
//
|
||||
integer thisMonth;
|
||||
integer thisYear;
|
||||
list monthList; // UTC | Name | grid | key
|
||||
list masterList; // UTC | Key
|
||||
list greetedList; // key
|
||||
integer lastStatsUpdate;
|
||||
string thisGrid;
|
||||
|
||||
doFloatyUpdate()
|
||||
{
|
||||
lastStatsUpdate=llGetUnixTime();
|
||||
if (!showFloatyStats) return;
|
||||
string stats=llGetRegionName()+" visitor stats\n ";
|
||||
integer visDay;
|
||||
integer day=24*60*60; // how many seconds in a day
|
||||
integer visWeek;
|
||||
integer week=day*7; // how many seconds in a week
|
||||
integer visMonth;
|
||||
integer month=day*30; // how many seconds in 30 days
|
||||
integer i;
|
||||
integer l=llGetListLength(masterList);
|
||||
while (i<l)
|
||||
{
|
||||
integer thisDeltaTime=lastStatsUpdate-llList2Integer(masterList,i);
|
||||
if (thisDeltaTime<=day) visDay++;
|
||||
if (thisDeltaTime<=week) visWeek++;
|
||||
if (thisDeltaTime<=month) visMonth++;
|
||||
// because list is sorted in descending order if we are more than this we can stop
|
||||
if (thisDeltaTime>month) i=l;
|
||||
else i+=2;
|
||||
}
|
||||
stats+="\nIn Region Now: "+(string)llGetListLength(greetedList);
|
||||
stats+="\nLast 24 hours: "+(string)visDay;
|
||||
stats+="\nLast 7 days: "+(string)visWeek;
|
||||
stats+="\nLast 30 days: "+(string)visMonth;
|
||||
stats+="\nAll Time: "+(string)(l/2);
|
||||
stats+="\n(all counts are unique visitors)";
|
||||
llSetText(stats,floatyColour,floatyAlpha);
|
||||
}
|
||||
integer updatePresence()
|
||||
{
|
||||
// returns TRUE if someone new has arrived in the region, else FALSE
|
||||
integer isChanged=FALSE;
|
||||
integer ownerPresent=FALSE;
|
||||
if (llGetAgentSize(llGetOwner())!=ZERO_VECTOR) ownerPresent=TRUE;
|
||||
integer now=llGetUnixTime();
|
||||
list inRegion=osGetAvatarList(); // key, position, name
|
||||
if (llGetAgentSize(llGetOwner())!=ZERO_VECTOR) inRegion=[]+inRegion+[llGetOwner(),ZERO_VECTOR]+llGetObjectDetails(llGetOwner(),[OBJECT_NAME]);
|
||||
integer i;
|
||||
integer l=llGetListLength(inRegion);
|
||||
while (i<l)
|
||||
{
|
||||
key who=llList2Key(inRegion,i);
|
||||
if (!osIsNpc(who)) // don't greet NPCs
|
||||
{
|
||||
// have we already greeted this person?
|
||||
if (llListFindList(greetedList,[who])==-1)
|
||||
{
|
||||
// this is a new arrival so now we need to great them and flag the update
|
||||
isChanged=TRUE;
|
||||
// either way we need to figure out their name and grid
|
||||
string name=llList2String(inRegion,i+2);
|
||||
string grid=thisGrid;
|
||||
integer sep=llSubStringIndex(name," @");
|
||||
if (sep>-1)
|
||||
{
|
||||
// this person is from another grid so extract that and trim it from the name
|
||||
grid =llGetSubString(name,sep+2,-1);
|
||||
name=""+llGetSubString(name,0,sep-1);
|
||||
// a hypergrid name is also using a dot as a separator so fix that
|
||||
sep=llSubStringIndex(name,".");
|
||||
name=""+llGetSubString(name,0,sep-1)+" "+llGetSubString(name,sep+1,-1);
|
||||
}
|
||||
// grid and name are now correct so find out if this is a new visitor and greet them
|
||||
string greeting=repeatGreetMessage; // default to this
|
||||
integer visit=llListFindList(masterList,[who]);
|
||||
if (visit==-1)
|
||||
{
|
||||
// first time visitor we need to add to both master list and monthly list
|
||||
greeting=""+firstGreetMessage; // switch to first time greeting message instead
|
||||
masterList=[]+masterList+[now,who];
|
||||
monthList=[]+monthList+[now,name,grid,who];
|
||||
}
|
||||
else
|
||||
{
|
||||
// return visitor...update master first
|
||||
masterList=[]+llListReplaceList(masterList,[now],visit-1,visit-1);
|
||||
// see if they're also already in this month's list
|
||||
integer monIndex=llListFindList(monthList,[who]);
|
||||
if (monIndex==-1) monthList=[]+monthList+[now,name,grid,who]; // add new to list
|
||||
else monthList=[]+llListReplaceList(monthList,[now],monIndex-3,monIndex-3); // update return to list
|
||||
}
|
||||
// greet the visitor but first subsitute $name with user's name
|
||||
integer swapInd=llSubStringIndex(greeting,"$name");
|
||||
while (swapInd>-1)
|
||||
{
|
||||
greeting=""+llGetSubString(greeting,0,swapInd-1)+name+llGetSubString(greeting,swapInd+5,-1);
|
||||
swapInd=llSubStringIndex(greeting,"$name");
|
||||
}
|
||||
llRegionSayTo(who,0,greeting);
|
||||
// notify owner
|
||||
if (notifyOwner)
|
||||
{
|
||||
if(ownerPresent) llRegionSayTo(llGetOwner(),0,name+" entered the region");
|
||||
else if (messageOwner) llInstantMessage(llGetOwner(),name+" entered your "+llGetRegionName()+" region");
|
||||
}
|
||||
// add to the greeted list
|
||||
greetedList=[]+greetedList+[who];
|
||||
}
|
||||
}
|
||||
i+=3; // next person
|
||||
}
|
||||
// update greetedList to reflect anyone who has left
|
||||
l=llGetListLength(greetedList);
|
||||
while (--l>=0)
|
||||
{
|
||||
if(llListFindList(inRegion,[llList2Key(greetedList,l)])==-1) greetedList=[]+llDeleteSubList(greetedList,l,l);
|
||||
}
|
||||
// if there have been any changes we need to do a few further things
|
||||
if (isChanged)
|
||||
{
|
||||
// sort both lists in descending order
|
||||
masterList=[]+llListSort(masterList,2,FALSE);
|
||||
monthList=[]+llListSort(monthList,4,FALSE);
|
||||
llSensorRepeat("THIS_SHOULD_NEVER_EVER_RETURN_A_SENSOR_RESULT",NULL_KEY,SCRIPTED,0.1,PI,persistDelay);
|
||||
return TRUE;
|
||||
}
|
||||
else return FALSE;
|
||||
}
|
||||
persistData()
|
||||
{
|
||||
// whenever data has changed and new persist needs to happen
|
||||
// clear sensor if there is one
|
||||
llSensorRemove();
|
||||
string cardName="log: "+(string)thisYear+"-";
|
||||
if (thisMonth<10) cardName+="0";
|
||||
cardName+=(string)thisMonth;
|
||||
if (llGetInventoryType(cardName)==INVENTORY_NOTECARD)
|
||||
{
|
||||
llRemoveInventory(cardName);
|
||||
llSleep(0.25); // have to sleep to give it time to register
|
||||
}
|
||||
integer i;
|
||||
integer l=llGetListLength(monthList);
|
||||
string data;
|
||||
while (i<l)
|
||||
{
|
||||
data+=llDumpList2String(llList2List(monthList,i,i+3),"|")+"\n";
|
||||
i+=4;
|
||||
}
|
||||
if (llStringLength(data)>0) osMakeNotecard(cardName,data);
|
||||
}
|
||||
doMonthRollOver(list today)
|
||||
{
|
||||
// triggered by first tick of the timer after month changes so force a persist to close out previous month first
|
||||
persistData();
|
||||
// set new date
|
||||
thisYear=llList2Integer(today,0);
|
||||
thisMonth=llList2Integer(today,1);
|
||||
// put anyone currently in the region into the new month list - build it using previous month's list then replace
|
||||
list newMonthList=[];
|
||||
integer now=llGetUnixTime();
|
||||
integer i=llGetListLength(greetedList);
|
||||
while (--i>-1)
|
||||
{
|
||||
integer index=llListFindList(monthList,[llList2Key(greetedList,i)]);
|
||||
newMonthList=[]+newMonthList+[now]+llList2List(monthList,index-2,index);
|
||||
}
|
||||
monthList=[]+newMonthList;
|
||||
// need to force persist of this new month too
|
||||
persistData();
|
||||
}
|
||||
loadData()
|
||||
{
|
||||
monthList=[];
|
||||
masterList=[];
|
||||
greetedList=[];
|
||||
integer i=llGetInventoryNumber(INVENTORY_NOTECARD);
|
||||
while (--i>-1)
|
||||
{
|
||||
string card=llGetInventoryName(INVENTORY_NOTECARD,i);
|
||||
if (llSubStringIndex(card,"log: ")==0)
|
||||
{
|
||||
integer year=(integer)llGetSubString(card,5,8);
|
||||
integer month=(integer)llGetSubString(card,10,11);
|
||||
list thisData=llParseString2List(osGetNotecard(card),["|","\n"],[]);
|
||||
if ((year==thisYear) && (month==thisMonth)) monthList=[]+thisData;
|
||||
integer e;
|
||||
integer l=llGetListLength(thisData);
|
||||
while (e<l)
|
||||
{
|
||||
key who=llList2Key(thisData,e+3);
|
||||
integer when=llList2Integer(thisData,e);
|
||||
integer index=llListFindList(masterList,[who]);
|
||||
if (index==-1) masterList=[]+masterList+[when,who];
|
||||
else if (llList2Integer(masterList,index-1)<when) masterList=llListReplaceList(masterList,[when],index-1,index-1);
|
||||
e+=4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default
|
||||
{
|
||||
state_entry()
|
||||
{
|
||||
if (!enabled)
|
||||
{
|
||||
llOwnerSay("The main Paramour Traffic Monitor script is currently disabled. To enable it, change line 39 of the script to say enabled=TRUE and save");
|
||||
return;
|
||||
}
|
||||
thisGrid=osGetGridName();
|
||||
if (!showFloatyStats) llSetText("",ZERO_VECTOR,0.0);
|
||||
list today=llParseString2List( llGetTimestamp(), ["-", "T", ":", "."], [] );
|
||||
thisYear=llList2Integer(today,0);
|
||||
thisMonth=llList2Integer(today,1);
|
||||
loadData();
|
||||
llSetTimerEvent(pollRate);
|
||||
}
|
||||
changed (integer change)
|
||||
{
|
||||
if (change & CHANGED_OWNER) llResetScript();
|
||||
else if (change & CHANGED_REGION_START) llResetScript();
|
||||
}
|
||||
on_rez (integer foo)
|
||||
{
|
||||
llResetScript();
|
||||
}
|
||||
sensor(integer num)
|
||||
{
|
||||
llOwnerSay("This should never, ever return a result");
|
||||
llSensorRemove();
|
||||
}
|
||||
no_sensor()
|
||||
{
|
||||
// expected result of there being a change that needs to be persisted
|
||||
llSensorRemove();
|
||||
persistData();
|
||||
}
|
||||
timer()
|
||||
{
|
||||
// check for month roll-over
|
||||
list today=llParseString2List( llGetTimestamp(), ["-", "T", ":", "."], [] );
|
||||
integer newMonth=llList2Integer(today,1);
|
||||
if (newMonth!=thisMonth) doMonthRollOver(today);
|
||||
// update presence list and see if anyone new has arrived or it's time to do a floaty update
|
||||
if (updatePresence()) doFloatyUpdate(); // returns TRUE if there has been a change
|
||||
else if ((llGetUnixTime()-lastStatsUpdate) > 3600) doFloatyUpdate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
// :SHOW:
|
||||
// :CATEGORY:Region Traffic Monitor
|
||||
// :NAME:Region Traffic Monitor Stats Retriever
|
||||
// :AUTHOR:Aine Caoimhe
|
||||
// :KEYWORDS:Region Traffic Monitor
|
||||
// :REV:2.0
|
||||
// :WORLD:Opensim, Second Life
|
||||
// :DESCRIPTION:
|
||||
// Paramour Stats Retriever
|
||||
// :CODE:
|
||||
|
||||
// Paramour Stats Retriever for Region Traffic Monitor 2.0
|
||||
// by Aine Caoimhe (LACM) Setp 2015
|
||||
// Provided under Creative Commons Attribution-Non-Commercial-ShareAlike 4.0 International license.
|
||||
// Please be sure you read and adhere to the terms of this license: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
//
|
||||
// Requires no additional OSSL functions other than the ones that already need to be enabled for the Traffic Monitor
|
||||
//
|
||||
// Simply Place this script in the same prim as the Traffic Monitor script (and log notecards) then touch
|
||||
// Reports are handed to you directly (and very briefly stored in the prim in order to be able to deliver it to you, then deleted)
|
||||
// Times/dates are converted to SL time and is daylight-savings aware
|
||||
// original dates/times stored on source cards are UTC so may overlap to next month on final day
|
||||
// If the floaty text report is sufficient you don't need to put this into the prim at all.
|
||||
// Don't touch to use this during peak traffic periods as it does invoke a thread-locking function.
|
||||
//
|
||||
// There is only 1 user settings for this script to enable or disable it
|
||||
integer enabled=FALSE;
|
||||
// FALSE = disable the script....TRUE = the script is enabled
|
||||
//
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
// DO NOT CHANGE ANYTHING BELOW HERE UNLESS YOU KNOW WHAT YOU'RE DOING
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
//
|
||||
float timeOut=120.0; // 2 minutes to respond to a dialog or remove listener
|
||||
integer myChannel;
|
||||
integer handle;
|
||||
string txtDia;
|
||||
list butDia;
|
||||
list logs;
|
||||
integer indLog;
|
||||
string thisGrid;
|
||||
list months=["months","January","February","March","April","May","June","July","August","September","October","November","December"];
|
||||
|
||||
// ********************** THIS PART COMES FROM SECOND LIFE WIKI: http://wiki.secondlife.com/wiki/Unix2PST_PDT ****************
|
||||
// Convert Unix Time to SLT, identifying whether it is currently PST or PDT (i.e. Daylight Saving aware)
|
||||
// Original script: Omei Qunhua December 2013
|
||||
// Fixed by Aine Caoimhe to work in Opensim Setp 2015
|
||||
// Returns a string containing the SLT date and time, annotated with PST or PDT as appropriate, corresponding to the given Unix time.
|
||||
// e.g. Wed 2013-12-25 06:48 PST
|
||||
//
|
||||
list weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
||||
|
||||
string Unix2PST_PDT(integer insecs)
|
||||
{
|
||||
string str = Convert(insecs - (3600 * 8) ); // PST is 8 hours behind GMT
|
||||
if (llGetSubString(str, -3, -1) == "PDT") // if the result indicates Daylight Saving Time ...
|
||||
str = Convert(insecs - (3600 * 7) ); // ... Recompute at 1 hour later
|
||||
return str;
|
||||
}
|
||||
|
||||
// This leap year test is correct for all years from 1901 to 2099 and hence is quite adequate for Unix Time computations
|
||||
integer LeapYear(integer year)
|
||||
{
|
||||
return !(year & 3);
|
||||
}
|
||||
|
||||
integer DaysPerMonth(integer year, integer month)
|
||||
{
|
||||
if (month == 2) return 28 + LeapYear(year);
|
||||
return 30 + ( (month + (month > 7) ) & 1); // Odd months up to July, and even months after July, have 31 days
|
||||
}
|
||||
|
||||
string Convert(integer insecs)
|
||||
{
|
||||
integer w; integer month; integer daysinyear;
|
||||
integer mins = insecs / 60;
|
||||
integer secs = insecs % 60;
|
||||
integer hours = mins / 60;
|
||||
mins = mins % 60;
|
||||
integer days = hours / 24;
|
||||
hours = hours % 24;
|
||||
integer DayOfWeek = (days + 4) % 7; // 0=Sun thru 6=Sat
|
||||
|
||||
integer years = 1970 + 4 * (days / 1461);
|
||||
days = days % 1461; // number of days into a 4-year cycle
|
||||
|
||||
@loop;
|
||||
daysinyear = 365 + LeapYear(years);
|
||||
if (days >= daysinyear)
|
||||
{
|
||||
days -= daysinyear;
|
||||
++years;
|
||||
jump loop;
|
||||
}
|
||||
++days;
|
||||
|
||||
month=0;
|
||||
w=0;
|
||||
while (days > w)
|
||||
{
|
||||
days -= w;
|
||||
w = DaysPerMonth(years, ++month);
|
||||
}
|
||||
string str = ((string) years + "-" + llGetSubString ("0" + (string) month, -2, -1) + "-" + llGetSubString ("0" + (string) days, -2, -1) + " " +
|
||||
llGetSubString ("0" + (string) hours, -2, -1) + ":" + llGetSubString ("0" + (string) mins, -2, -1) );
|
||||
|
||||
integer LastSunday = days - DayOfWeek;
|
||||
string PST_PDT = " PST"; // start by assuming Pacific Standard Time
|
||||
// Up to 2006, PDT is from the first Sunday in April to the last Sunday in October
|
||||
// After 2006, PDT is from the 2nd Sunday in March to the first Sunday in November
|
||||
if (years > 2006 && month == 3 && LastSunday > 7) PST_PDT = " PDT";
|
||||
if (month > 3) PST_PDT = " PDT";
|
||||
if (month > 10) PST_PDT = " PST";
|
||||
if (years < 2007 && month == 10 && LastSunday > 24) PST_PDT = " PST";
|
||||
return (llList2String(weekdays, DayOfWeek) + " " + str + PST_PDT);
|
||||
}
|
||||
// ***************** END OF FUNCTION FROM SL WIKI ****************************
|
||||
|
||||
doFetch(string cardName)
|
||||
{
|
||||
integer year=(integer)llGetSubString(cardName,5,8);
|
||||
integer month=(integer)llGetSubString(cardName,10,11);
|
||||
list data=llParseString2List(osGetNotecard(cardName),["|","\n"],[]);
|
||||
string details;
|
||||
list grids;
|
||||
integer visCount;
|
||||
integer localCount;
|
||||
integer hgCount;
|
||||
integer i;
|
||||
integer l=llGetListLength(data);
|
||||
while (i<l)
|
||||
{ // UTC | Name | Grid | Key
|
||||
string date=Unix2PST_PDT(llList2Integer(data,i));
|
||||
string name=llList2String(data,i+1);
|
||||
string grid=llList2String(data,i+2);
|
||||
key who=llList2Key(data,i+3);
|
||||
details=date+" "+name+" from "+grid+"\n"+details; // prepend so the list order ends up being from start of month to end
|
||||
visCount++;
|
||||
if (grid==thisGrid) localCount++;
|
||||
else hgCount++;
|
||||
if (llListFindList(grids,[grid])==-1) grids=[]+grids+[grid];
|
||||
i+=4;
|
||||
}
|
||||
string stats="Statistics for the month "+llList2String(months,month)+" "+(string)year;
|
||||
stats+="\n-------------------------------------------------------";
|
||||
stats+="\nTotal unique visitors: "+(string)visCount;
|
||||
stats+="\nLocal users: "+(string)localCount;
|
||||
stats+="\nHypergrid users: "+(string)hgCount;
|
||||
stats+="\nUnique grids: "+(string)llGetListLength(grids);
|
||||
stats+="\n-------------------------------------------------------\n";
|
||||
stats+=details;
|
||||
string cardToGive="Stats for "+llGetRegionName()+" for "+llList2String(months,month)+" "+(string)year;
|
||||
osMakeNotecard(cardToGive,stats);
|
||||
llSleep(0.25); // give it time to be stored
|
||||
llGiveInventory(llGetOwner(),cardToGive);
|
||||
llRemoveInventory(cardToGive);
|
||||
}
|
||||
showMenuMain()
|
||||
{
|
||||
txtDia="Select a log to analyse and convert";
|
||||
butDia=[]+llList2List(logs,indLog,indLog+8);
|
||||
while (llGetListLength(butDia)<9) {butDia=[]+butDia+["-"];}
|
||||
butDia=[]+butDia+["< PREV","DONE","NEXT >"];
|
||||
startListening();
|
||||
}
|
||||
doPrebuild()
|
||||
{
|
||||
integer i=llGetInventoryNumber(INVENTORY_NOTECARD);
|
||||
logs=[];
|
||||
indLog=0;
|
||||
while (--i>=0)
|
||||
{
|
||||
string name=llGetInventoryName(INVENTORY_NOTECARD,i);
|
||||
if (llSubStringIndex(name,"log: ")==0) logs=[]+logs+[llGetSubString(name,5,-1)];
|
||||
}
|
||||
}
|
||||
startListening()
|
||||
{
|
||||
llSetTimerEvent(timeOut);
|
||||
handle=llListen(myChannel,"",llGetOwner(),"");
|
||||
llDialog(llGetOwner(),txtDia,llList2List(butDia,9,11)+llList2List(butDia,6,8)+llList2List(butDia,3,5)+llList2List(butDia,0,2),myChannel);
|
||||
}
|
||||
stopListening()
|
||||
{
|
||||
llSetTimerEvent(0.0);
|
||||
llListenRemove(handle);
|
||||
}
|
||||
|
||||
default
|
||||
{
|
||||
state_entry()
|
||||
{
|
||||
thisGrid=osGetGridName();
|
||||
myChannel=0x80000000|(integer)("0x"+(string)llGetKey());
|
||||
}
|
||||
changed (integer change)
|
||||
{
|
||||
if (change & CHANGED_OWNER) llResetScript();
|
||||
else if (change & CHANGED_REGION_START) llResetScript();
|
||||
}
|
||||
on_rez(integer foo)
|
||||
{
|
||||
llResetScript();
|
||||
}
|
||||
touch_start(integer num)
|
||||
{
|
||||
if (llDetectedKey(0)!=llGetOwner()) return; // owner only can retrieve stats
|
||||
if (enabled)
|
||||
{
|
||||
doPrebuild();
|
||||
showMenuMain();
|
||||
}
|
||||
else llOwnerSay("The stats retriever script is currently set to disabled. To enable to change line 15 to enabled=TRUE and save");
|
||||
}
|
||||
timer()
|
||||
{
|
||||
stopListening();
|
||||
}
|
||||
listen(integer channel, string name, key who, string message)
|
||||
{
|
||||
stopListening();
|
||||
if (message=="DONE") return;
|
||||
else if (message=="-") startListening();
|
||||
else if ((message=="< PREV") || (message=="NEXT >"))
|
||||
{
|
||||
if (message=="NEXT >") indLog+=9;
|
||||
else indLog-=9;
|
||||
if (indLog>=llGetListLength(logs)) indLog=0;
|
||||
if (indLog<=-9) indLog=llGetListLength(logs)-9;
|
||||
if (indLog<0) indLog=0;
|
||||
showMenuMain();
|
||||
}
|
||||
else
|
||||
{
|
||||
string logToFetch="log: "+message;
|
||||
if (llGetInventoryType(logToFetch)!=INVENTORY_NOTECARD)
|
||||
{
|
||||
llOwnerSay("ERROR: could not find that card....rebuilding card list");
|
||||
doPrebuild();
|
||||
showMenuMain();
|
||||
}
|
||||
else doFetch(logToFetch);
|
||||
startListening();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<Project name="Paramour Traffic Monitor" guid="bd010f13-a0a4-4ba2-9e55-b7fa9a54037b">
|
||||
<Object name="Object" guid="e1842e05-1b05-4e95-8d0c-9d3e675a0299" active="true">
|
||||
<Notecard name="Notecard.txt" guid="8bcbe1c0-192a-4114-83b9-9f44d0cfa5ec">
|
||||
</Notecard>
|
||||
<Script name="Paramour+Region+Traffic+Monitor+v2.0.lsl" guid="8a4b91e0-1bd1-4e0f-8de3-19bc05ef1e91">
|
||||
</Script>
|
||||
<Script name="Paramour+Stats+Retriever+for+Region+Traffic+Monitor+2.0 Script 2.lsl" guid="613d0374-accf-4406-b74a-d501c5d1ed1e">
|
||||
</Script>
|
||||
</Object>
|
||||
</Project>
|
||||
@@ -0,0 +1 @@
|
||||
Put a NPC appearance notecard here named "Trash Bot"
|
||||
@@ -1,12 +1,22 @@
|
||||
//:AUTHOR:Unknown
|
||||
//:Name:Trash Collector NPC script
|
||||
|
||||
// comment out for runtime, for LSLEditor use
|
||||
// :SHOW:
|
||||
// :CATEGORY:Presentation
|
||||
// :NAME:Trash Collector
|
||||
// :AUTHOR:Unknown
|
||||
// :KEYWORDS: NPC
|
||||
// :REV:1
|
||||
// :WORLD:Opensim
|
||||
// :DESCRIPTION:
|
||||
// NPC that walks and collects trash
|
||||
// :CODE:
|
||||
// You newed a animation fort your NPC to bend overt and pick stuff up.
|
||||
string pickup="pick up from ground animation";
|
||||
// comment this line out for runtime, for LSLEditor use
|
||||
integer OS_NPC_NO_FLY = 1;
|
||||
float WAIT = 10; // wait 10 secobnds
|
||||
float range = 15; // how far to wander
|
||||
vector start_location = <0,0,0>;
|
||||
|
||||
float WAIT = 10;
|
||||
float range = 15;
|
||||
vector start_location = <355.80, 326.80, 44>;
|
||||
//CODDE
|
||||
|
||||
// define a box in front of the NPC size 'range'
|
||||
vector top;
|
||||
@@ -25,156 +35,154 @@ integer debug = TRUE;
|
||||
|
||||
DEBUG(string str)
|
||||
{
|
||||
if (debug) llSay(0,str);
|
||||
if (debug) llSay(0,str);
|
||||
}
|
||||
|
||||
string pickup="pick up from ground animation";
|
||||
|
||||
TimerEvent(float timesent)
|
||||
{
|
||||
DEBUG("Setting timer: " + (string) timesent);
|
||||
llSetTimerEvent(timesent);
|
||||
DEBUG("Setting timer: " + (string) timesent);
|
||||
llSetTimerEvent(timesent);
|
||||
}
|
||||
create_path(vector start,vector goal)
|
||||
{
|
||||
vector pos = llGetPos();
|
||||
integer direct;
|
||||
list results = llCastRay(start, goal, [ RC_MAX_HITS, 1] );
|
||||
direct=llList2Integer(results, -1);
|
||||
if (!direct)
|
||||
{
|
||||
positions = [start, goal];
|
||||
return;
|
||||
}
|
||||
if (pos.y < goal.y)
|
||||
positions= [start,top, goal];
|
||||
else if (goal.x < pos.x)
|
||||
positions= [start,top,left,goal];
|
||||
else if (goal.x > pos.x)
|
||||
positions= [start,top,right,goal];
|
||||
return;
|
||||
vector pos = llGetPos();
|
||||
integer direct;
|
||||
list results = llCastRay(start, goal, [ RC_MAX_HITS, 1] );
|
||||
direct=llList2Integer(results, -1);
|
||||
if (!direct)
|
||||
{
|
||||
positions = [start, goal];
|
||||
return;
|
||||
}
|
||||
if (pos.y < goal.y)
|
||||
positions= [start,top, goal];
|
||||
else if (goal.x < pos.x)
|
||||
positions= [start,top,left,goal];
|
||||
else if (goal.x > pos.x)
|
||||
positions= [start,top,right,goal];
|
||||
return;
|
||||
}
|
||||
|
||||
send_path(integer homewardbound, list path)
|
||||
{
|
||||
integer length=llGetListLength(path);
|
||||
integer length=llGetListLength(path);
|
||||
|
||||
if(destination < length && destination >= -length)
|
||||
{
|
||||
DEBUG((string) destination);
|
||||
newDest = llList2Vector(path,destination);
|
||||
iWaitCounter = WAIT; // wait to get to a destination.
|
||||
osNpcMoveToTarget(NPCKey, newDest, OS_NPC_NO_FLY );
|
||||
TimerEvent(1);
|
||||
return;
|
||||
} else if (destination == length) {
|
||||
osNpcPlayAnimation(NPCKey,pickup);
|
||||
TimerEvent(3.0);
|
||||
} else if (destination <= -length) {
|
||||
osNpcRemove(NPCKey);
|
||||
TimerEvent(480);
|
||||
checkAV=TRUE;
|
||||
return;
|
||||
}
|
||||
if(destination < length && destination >= -length)
|
||||
{
|
||||
DEBUG((string) destination);
|
||||
newDest = llList2Vector(path,destination);
|
||||
iWaitCounter = WAIT; // wait to get to a destination.
|
||||
osNpcMoveToTarget(NPCKey, newDest, OS_NPC_NO_FLY );
|
||||
TimerEvent(1);
|
||||
return;
|
||||
} else if (destination == length) {
|
||||
osNpcPlayAnimation(NPCKey,pickup);
|
||||
TimerEvent(3.0);
|
||||
} else if (destination <= -length) {
|
||||
osNpcRemove(NPCKey);
|
||||
TimerEvent(480);
|
||||
checkAV=TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
destination= -1;
|
||||
TimerEvent(1);
|
||||
iWaitCounter = WAIT;
|
||||
DEBUG((string)destination);
|
||||
destination= -1;
|
||||
TimerEvent(1);
|
||||
iWaitCounter = WAIT;
|
||||
DEBUG((string)destination);
|
||||
|
||||
}
|
||||
|
||||
init()
|
||||
{
|
||||
vector pos = llGetPos();
|
||||
top = pos + <0,range,0>;
|
||||
right = pos + <range,0,0>;
|
||||
left = pos - <range,0,0>;
|
||||
destination=0;
|
||||
TimerEvent(480); // 8 minutes !!!
|
||||
checkAV=FALSE;
|
||||
destination=0;
|
||||
create_path(start_location,randompos());
|
||||
DEBUG((string)positions);
|
||||
NPCKey=osNpcCreate("Trash", "Bot", start_location, "Trash Bot");
|
||||
send_path(TRUE, positions);
|
||||
vector pos = llGetPos();
|
||||
top = pos + <0,range,0>;
|
||||
right = pos + <range,0,0>;
|
||||
left = pos - <range,0,0>;
|
||||
destination=0;
|
||||
TimerEvent(480); // 8 minutes !!!
|
||||
checkAV=FALSE;
|
||||
destination=0;
|
||||
create_path(llGetPos() + start_location,randompos());
|
||||
DEBUG((string)positions);
|
||||
NPCKey=osNpcCreate("Trash", "Bot", start_location, "Trash Bot");
|
||||
send_path(TRUE, positions);
|
||||
}
|
||||
|
||||
vector randompos()
|
||||
{
|
||||
vector pos= llGetPos();
|
||||
if(llFrand(1)<0.5)
|
||||
{
|
||||
float randx= 18*((llRound(llFrand(1))*2)-1);
|
||||
//llOwnerSay((string)randx);
|
||||
float randy=18*((llRound(llFrand(1))*2)-1);
|
||||
//llOwnerSay((string)randy);
|
||||
return pos+<randx+(3-llFrand(5)),randy+(3-llFrand(5)),0>;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pos+<llFrand(18)-9,-llFrand(30)-7,0>;
|
||||
}
|
||||
vector pos= llGetPos();
|
||||
if(llFrand(1)<0.5)
|
||||
{
|
||||
float randx= 18*((llRound(llFrand(1))*2)-1);
|
||||
//llOwnerSay((string)randx);
|
||||
float randy=18*((llRound(llFrand(1))*2)-1);
|
||||
//llOwnerSay((string)randy);
|
||||
return pos+<randx+(3-llFrand(5)),randy+(3-llFrand(5)),0>;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pos+<llFrand(18)-9,-llFrand(30)-7,0>;
|
||||
}
|
||||
}
|
||||
check_agents()
|
||||
{
|
||||
integer nNew = 0;
|
||||
list avis = llGetAgentList(AGENT_LIST_REGION, []);
|
||||
integer howmany = llGetListLength(avis);
|
||||
integer i;
|
||||
for ( i = 0; i < howmany; i++ ) {
|
||||
if ( ! osIsNpc(llList2Key(avis, i)) )
|
||||
nNew++; // only non-NPC's
|
||||
}
|
||||
if (nNew>0)
|
||||
{
|
||||
checkAV=FALSE;
|
||||
destination=0;
|
||||
create_path(start_location,randompos());
|
||||
DEBUG((string)positions);
|
||||
NPCKey=osNpcCreate("Trash", "Bot", start_location, "Trash Bot");
|
||||
send_path(TRUE, positions);
|
||||
integer nNew = 0;
|
||||
list avis = llGetAgentList(AGENT_LIST_REGION, []);
|
||||
integer howmany = llGetListLength(avis);
|
||||
integer i;
|
||||
for ( i = 0; i < howmany; i++ ) {
|
||||
if ( ! osIsNpc(llList2Key(avis, i)) )
|
||||
nNew++; // only non-NPC's
|
||||
}
|
||||
if (nNew>0)
|
||||
{
|
||||
checkAV=FALSE;
|
||||
destination=0;
|
||||
create_path(start_location,randompos());
|
||||
DEBUG((string)positions);
|
||||
NPCKey=osNpcCreate("Trash", "Bot", start_location, "Trash Bot");
|
||||
send_path(TRUE, positions);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
default
|
||||
{
|
||||
state_entry()
|
||||
{
|
||||
init();
|
||||
}
|
||||
touch_start(integer total_number)
|
||||
{
|
||||
checkAV=FALSE;
|
||||
destination=0;
|
||||
create_path(start_location,randompos());
|
||||
//llOwnerSay((string)positions);
|
||||
NPCKey=osNpcCreate("Trash", "Bot", start_location, "Trash Bot");
|
||||
send_path(TRUE, positions);
|
||||
}
|
||||
timer() {
|
||||
if (checkAV)
|
||||
{
|
||||
check_agents();
|
||||
}
|
||||
if (--iWaitCounter) {
|
||||
state_entry()
|
||||
{
|
||||
init();
|
||||
}
|
||||
touch_start(integer total_number)
|
||||
{
|
||||
checkAV=FALSE;
|
||||
destination=0;
|
||||
create_path(start_location,randompos());
|
||||
//llOwnerSay((string)positions);
|
||||
NPCKey=osNpcCreate("Trash", "Bot", start_location, "Trash Bot");
|
||||
send_path(TRUE, positions);
|
||||
}
|
||||
timer() {
|
||||
if (checkAV)
|
||||
{
|
||||
check_agents();
|
||||
}
|
||||
if (--iWaitCounter) {
|
||||
|
||||
vector tDest = newDest;
|
||||
tDest.z = 0;
|
||||
vector hisDest = osNpcGetPos(NPCKey);
|
||||
hisDest.z = 0;
|
||||
vector tDest = newDest;
|
||||
tDest.z = 0;
|
||||
vector hisDest = osNpcGetPos(NPCKey);
|
||||
hisDest.z = 0;
|
||||
|
||||
if (llVecDist(hisDest, newDest) > 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
//llSetTimerEvent(0);
|
||||
if (destination >= 0)
|
||||
destination++;
|
||||
else
|
||||
destination--;
|
||||
|
||||
send_path(TRUE, positions);
|
||||
}
|
||||
if (llVecDist(hisDest, newDest) > 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
//llSetTimerEvent(0);
|
||||
if (destination >= 0)
|
||||
destination++;
|
||||
else
|
||||
destination--;
|
||||
|
||||
send_path(TRUE, positions);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
<Project name="Trash Collector NPC" guid="c07664f4-2d12-4d4c-8286-b65ed8ad0281">
|
||||
<Object name="NPC Box" guid="5575be97-3a9a-4d40-acc9-54a5d0ce25d5" active="true">
|
||||
<Notecard name="Trash Bot" guid="e086eabb-7262-4810-9f7d-416a04514f56">
|
||||
</Notecard>
|
||||
<Script name="Trash Collector script.lsl" guid="29d71b36-8986-4fd2-aa62-672584ff4fd1">
|
||||
</Script>
|
||||
</Object>
|
||||
|
||||
Reference in New Issue
Block a user