corrade-lsl-templates

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 4  →  ?path2? @ 5
/source/sit-and-animate/configuration.txt
@@ -0,0 +1,14 @@
####################### START CONFIGURATION ##################################
 
# All these settings must correspond to the settings in Corrade.ini.
 
# This is the UUID of the Corrade bot.
corrade = "c74590e1-b8a1-495a-aa96-1f4c2bc3b15a"
 
# The name of the group - it can also be the UUID of the group.
group = "My Group"
 
# The password for the group.
password = "mypassword"
 
####################### END CONFIGURATION ###################################
/source/sit-and-animate/corrade-interface.lsl
@@ -0,0 +1,396 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
//
// This is an automatic teleporter, sitter and animator for the Corrade
// Second Life / OpenSim bot. You can find more details about the bot
// by following the URL: http://was.fm/secondlife/scripted_agents/corrade
//
// The sit script works together with a "configuration" notecard and an
// animation that must both be placed in the same primitive as this script.
// The purpose of this script is to demonstrate sitting with Corrade and
// you are free to use, change, and commercialize it under the GNU/GPLv3
// license at: http://www.gnu.org/licenses/gpl.html
//
///////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
string wasKeyValueGet(string k, string data) {
if(llStringLength(data) == 0) return "";
if(llStringLength(k) == 0) return "";
list a = llParseString2List(data, ["&", "="], []);
integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]);
if(i != -1) return llList2String(a, 2*i+1);
return "";
}
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
string wasKeyValueEncode(list data) {
list k = llList2ListStrided(data, 0, -1, 2);
list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2);
data = [];
do {
data += llList2String(k, 0) + "=" + llList2String(v, 0);
k = llDeleteSubList(k, 0, 0);
v = llDeleteSubList(v, 0, 0);
} while(llGetListLength(k) != 0);
return llDumpList2String(data, "&");
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2011 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
vector wasCirclePoint(float radius) {
float x = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
float y = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
if(llPow(x,2) + llPow(y,2) <= llPow(radius,2))
return <x, y, 0>;
return wasCirclePoint(radius);
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
// escapes a string in conformance with RFC1738
string wasURLEscape(string i) {
string o = "";
do {
string c = llGetSubString(i, 0, 0);
i = llDeleteSubString(i, 0, 0);
if(c == "") jump continue;
if(c == " ") {
o += "+";
jump continue;
}
if(c == "\n") {
o += "%0D" + llEscapeURL(c);
jump continue;
}
o += llEscapeURL(c);
@continue;
} while(i != "");
return o;
}
 
// corrade data
string CORRADE = "";
string GROUP = "";
string PASSWORD = "";
 
// for holding the callback URL
string callback = "";
 
// for notecard reading
integer line = 0;
 
// key-value data will be read into this list
list tuples = [];
default {
state_entry() {
if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) {
llOwnerSay("Sorry, could not find an inventory notecard.");
return;
}
// DEBUG
llOwnerSay("Reading configuration file...");
llGetNotecardLine("configuration", line);
}
dataserver(key id, string data) {
if(data == EOF) {
// invariant, length(tuples) % 2 == 0
if(llGetListLength(tuples) % 2 != 0) {
llOwnerSay("Error in configuration notecard.");
return;
}
CORRADE = llList2String(
tuples,
llListFindList(
tuples,
[
"corrade"
]
)
+1);
if(CORRADE == "") {
llOwnerSay("Error in configuration notecard: corrade");
return;
}
GROUP = llList2String(
tuples,
llListFindList(
tuples,
[
"group"
]
)
+1);
if(GROUP == "") {
llOwnerSay("Error in configuration notecard: group");
return;
}
PASSWORD = llList2String(
tuples,
llListFindList(
tuples,
[
"password"
]
)
+1);
if(PASSWORD == "") {
llOwnerSay("Error in configuration notecard: password");
return;
}
// DEBUG
llOwnerSay("Read configuration file...");
state url;
}
if(data == "") jump continue;
integer i = llSubStringIndex(data, "#");
if(i != -1) data = llDeleteSubString(data, i, -1);
list o = llParseString2List(data, ["="], []);
// get rid of starting and ending quotes
string k = llDumpList2String(
llParseString2List(
llStringTrim(
llList2String(
o,
0
),
STRING_TRIM),
["\""], []
), "\"");
string v = llDumpList2String(
llParseString2List(
llStringTrim(
llList2String(
o,
1
),
STRING_TRIM),
["\""], []
), "\"");
if(k == "" || v == "") jump continue;
tuples += k;
tuples += v;
@continue;
llGetNotecardLine("configuration", ++line);
}
on_rez(integer num) {
llResetScript();
}
changed(integer change) {
if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
llResetScript();
}
}
}
state url {
state_entry() {
// DEBUG
llOwnerSay("Requesting URL...");
llRequestURL();
}
http_request(key id, string method, string body) {
if(method != URL_REQUEST_GRANTED) return;
callback = body;
// DEBUG
llOwnerSay("Got URL...");
state detect;
}
on_rez(integer num) {
llResetScript();
}
changed(integer change) {
if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
llResetScript();
}
}
}
state detect {
state_entry() {
// DEBUG
llOwnerSay("Detecting if Corrade is online...");
llSetTimerEvent(5);
}
timer() {
llRequestAgentData((key)CORRADE, DATA_ONLINE);
}
dataserver(key id, string data) {
if(data != "1") {
// DEBUG
llOwnerSay("Corrade is not online, sleeping...");
llSetTimerEvent(30);
return;
}
llSensorRepeat("", (key)CORRADE, AGENT, 10, TWO_PI, 1);
}
no_sensor() {
// DEBUG
llOwnerSay("Teleporting Corrade...");
llInstantMessage((key)CORRADE,
wasKeyValueEncode(
[
"command", "teleport",
"group", wasURLEscape(GROUP),
"password", wasURLEscape(PASSWORD),
"entity", "region",
"region", wasURLEscape(llGetRegionName()),
"position", wasURLEscape(
(string)(
llGetPos() + wasCirclePoint(1)
)
),
"callback", callback
]
)
);
}
sensor(integer num) {
llSetTimerEvent(0);
state notify;
}
http_request(key id, string method, string body) {
llHTTPResponse(id, 200, "OK");
if(wasKeyValueGet("command", body) != "teleport" ||
wasKeyValueGet("success", body) != "True") {
// DEBUG
llOwnerSay("Teleport failed...");
return;
}
llSetTimerEvent(0);
state main;
}
on_rez(integer num) {
llResetScript();
}
changed(integer change) {
if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
llResetScript();
}
}
}
state notify {
state_entry() {
// DEBUG
llOwnerSay("Binding to the permission Corrade notification...");
llInstantMessage(
(key)CORRADE,
wasKeyValueEncode(
[
"command", "notify",
"group", wasURLEscape(GROUP),
"password", wasURLEscape(PASSWORD),
"action", "add",
"type", "permission",
"URL", wasURLEscape(callback),
"callback", wasURLEscape(callback)
]
)
);
llSetTimerEvent(60);
}
http_request(key id, string method, string body) {
llHTTPResponse(id, 200, "OK");
if(wasKeyValueGet("command", body) != "notify" ||
wasKeyValueGet("success", body) != "True") {
// DEBUG
llOwnerSay("Failed to bind to the permission notification...");
state detect;
}
// DEBUG
llOwnerSay("Permission notification installed...");
llSetTimerEvent(0);
state main;
}
timer() {
llSetTimerEvent(0);
// DEBUG
llOwnerSay("Timeout binding to permission notification...");
state detect;
}
on_rez(integer num) {
llResetScript();
}
changed(integer change) {
if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
llResetScript();
}
}
}
state main {
state_entry() {
// DEBUG
llOwnerSay("Waiting...");
llSensorRepeat("", (key)CORRADE, AGENT, 10, TWO_PI, 1);
llSetTimerEvent(60);
}
sensor(integer num) {
// Corrade is already sitting. Do nothing.
if(llAvatarOnSitTarget() == (key)CORRADE) return;
// DEBUG
llOwnerSay("Sending sit command...");
llInstantMessage((key)CORRADE,
wasKeyValueEncode(
[
"command", "sit",
"group", wasURLEscape(GROUP),
"password", wasURLEscape(PASSWORD),
"item", wasURLEscape(
llGetKey()
),
"range", 10
]
)
);
llSensorRepeat("", (key)CORRADE, AGENT, 10, TWO_PI, 10);
}
no_sensor() {
llSensorRemove();
state detect;
}
http_request(key id, string method, string body) {
llHTTPResponse(id, 200, "OK");
if(wasKeyValueGet("type", body) != "permission" ||
wasKeyValueGet("permissions", body) != "TriggerAnimation") return;
// DEBUG
llOwnerSay("Corrade received the permission request to trigger an animation, replying...");
llInstantMessage((key)CORRADE,
wasKeyValueEncode(
[
"command", "replytoscriptpermissionrequest",
"group", wasURLEscape(GROUP),
"password", wasURLEscape(PASSWORD),
"action", "reply",
"item", wasURLEscape(wasKeyValueGet("item", body)),
"task", wasURLEscape(wasKeyValueGet("task", body)),
"permissions", "TriggerAnimation",
"region", wasURLEscape(wasKeyValueGet("region", body))
]
)
);
}
timer() {
if(llAvatarOnSitTarget() == (key)CORRADE) return;
// DEBUG
llOwnerSay("Timeout during sit... Restarting...");
state detect;
}
on_rez(integer num) {
llResetScript();
}
changed(integer change) {
if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
llResetScript();
}
}
}
/source/sit-and-animate/set-sit-target.lsl
@@ -0,0 +1,6 @@
default {
state_entry()
{
llSitTarget(<0,0,0.1>, ZERO_ROTATION);
}
}
/source/sit-and-animate/sit-and-animate.lsl
@@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
 
default {
state_entry() {
llSetTimerEvent(1);
}
timer() {
// If someone is sitting, hide the poseball.
key a = llAvatarOnSitTarget();
if(a == NULL_KEY) {
llSetAlpha(1, ALL_SIDES);
return;
}
llSetAlpha(0, ALL_SIDES);
}
run_time_permissions(integer perm) {
if(perm & PERMISSION_TRIGGER_ANIMATION) {
string o = llGetInventoryName(INVENTORY_ANIMATION, 0);
if(llGetInventoryType(o) != INVENTORY_ANIMATION) return;
key a = llAvatarOnSitTarget();
if(a == NULL_KEY) {
if(perm & PERMISSION_TRIGGER_ANIMATION) {
// DEBUG
llOwnerSay("Animation stopped...");
llSetAlpha(1, ALL_SIDES);
llStopAnimation(o);
}
return;
}
if(perm & PERMISSION_TRIGGER_ANIMATION) {
// DEBUG
llOwnerSay("Animation started...");
llSetAlpha(0, ALL_SIDES);
llStartAnimation(o);
}
}
}
changed(integer change) {
if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
llResetScript();
}
if(change & CHANGED_LINK) {
key a = llAvatarOnSitTarget();
if(a == NULL_KEY) return;
llRequestPermissions(a, PERMISSION_TRIGGER_ANIMATION);
}
}
}