14 Commits

Author SHA1 Message Date
fd15623809 Bump version (using yyyy.mm.dd again) 2026-03-06 14:35:47 +01:00
9cd39a8d2b Make smartstrip and allowattach in the relay menu work 2026-03-06 14:01:17 +01:00
8723466d74 Check if key is empty string too, closes #1 2026-03-05 17:01:29 +01:00
c42b1f028c update version check url 2026-03-02 08:01:44 +01:00
lickx
c58c4634ba Add creatorkit, closes #110 2026-02-22 04:26:43 +01:00
lickx
8659213ab2 Use sane default if leash length is 0
This should never happen tho
2026-02-15 13:49:13 +01:00
lickx
bcfe397138 Handle outfit changes in a failsafe way 2026-02-10 16:53:56 +01:00
lickx
f9ee2bc9e7 Don't process FloatText prim during hide/unhide 2026-02-02 09:22:43 +01:00
lickx
5e3301d021 Correct channel on oc_grabbypost 2026-02-01 10:30:35 +01:00
lickx
522d1a4f9c Bump device version for the updater check 2026-02-01 10:29:10 +01:00
lickx
1a06aa0b30 Correct the font y 2026-02-01 10:27:38 +01:00
lickx
e34bf53933 Redo how stealth works
Also remove redundant @detach (it is handled by rlvsys)
2026-02-01 10:24:57 +01:00
lickx
1fd6a90089 Rename Owner's HUD -> Remote 2026-01-27 15:03:28 +01:00
lickx
746653149b Update README.md 2026-01-14 12:40:12 +01:00
15 changed files with 114 additions and 138 deletions

View File

@@ -1,6 +1,6 @@
### Welcome to OsCollar
OsCollar is a set of gadgets for submission roleplay for use in the OpenSim metaverse
OsCollar is a set of gadgets for submission roleplay for use in OpenSim grids
#### Finding your way around this repo
@@ -12,18 +12,19 @@ OsCollar is a set of gadgets for submission roleplay for use in the OpenSim meta
> res: Resource of creative content.
> anims: Motions and Animations as .bvh and .avm binaries.
> creatorkit: Sample collar for creators to use as a base
> models: 3D Models as .dae and .blend binaries.
> sounds: Sounds as .wav and .aup binaries.
> textures: Images as .png and .xcf binaries.
> src: Source code of the OsCollar role play device.
> ao: The source code for the animation overrider.
> ao: The source code for the animation overrider HUD.
> apps: Fun features you can add to your device
> device: Everything you need for a full featured device
> extensions: Enhanced features that can be added to a device
> installer: The source code for the updater aka patch
> remote: The source code for the remote control HUD.
> remote: The source code for the Remote HUD.
> spares: Spares and snippets for research and development.
> web: Files for the updater check within the Help/About menu
@@ -31,11 +32,9 @@ OsCollar is a set of gadgets for submission roleplay for use in the OpenSim meta
#### Requirements
Simulator: 0.9.3.1 or newer
or
Dreamgrid: 7.04 or newer
Simulator 0.9.3.1 or newer
- Teleporting to a sim running older versions of OpenSim may result in loss of settings (linkset data) and loss of functionality (non-running scripts)
- Teleporting to a hypergrid sim may result in scripts to stop running and/or reset, unless the destination sim is patched
To avoid problems, the general advice is to only use this on your home grid meeting the minimal requirements or better.
To avoid problems, only use this on your home grid meeting the minimal requirements or better.

Binary file not shown.

View File

@@ -22,7 +22,7 @@
// Debug(string sStr) { llOwnerSay("Debug ["+llGetScriptName()+"]: " + sStr); }
string g_sAppVersion = "2023.03.29";
string g_sAppVersion = "2026.02";
string g_sParentMenu = "Apps";
string g_sSubMenu = "Label";
@@ -68,7 +68,7 @@ list g_lFonts;
string g_sFontTexture = "font_System 01";
integer x = 45;
integer y = 19;
integer y = 20;
integer g_iNumFaces = 6;

View File

@@ -164,6 +164,7 @@ integer CheckCommandAuth(key kCmdGiver, integer iAuth)
SetLength(integer iIn)
{
if (iIn == 0) iIn = 3; // i had a rare edge case where this happened
g_iLength = iIn;
if (g_kLeashedTo != NULL_KEY) {
llTargetRemove(g_iTargetHandle);

View File

@@ -342,7 +342,7 @@ UserCommand(integer iAuth, string sStr, key kID)
}
}
} else if (llGetSubString(sChangetype, 0, 4) == "smart") {
if (iAuth != CMD_WEARER) RelayNotify(kID, "Only wearer can toggle this, since Smartstrip requires the #RLV folder to be setup in a specific way.", 0);
if (kID != g_kWearer) RelayNotify(kID, "Only wearer can toggle this, since Smartstrip requires the #RLV folder to be setup in a specific way.", 0);
else if (sChangevalue == "off") {
g_iSmartStrip = FALSE;
sText = "Smartstrip turned off.\n\nAttachments and clothing, also if layers are somewhere inside #RLV folder directories, will be stripped normally.\n";
@@ -350,7 +350,7 @@ UserCommand(integer iAuth, string sStr, key kID)
sText = "Smartstrip turned on.\n\nAll smartstrip ready folders in the #RLV directory will be removed as a whole when corresponding clothing layers are stripped.\n";
g_iSmartStrip = TRUE;
}
} else if (llGetSubString(sChangetype, 0, 9) == "allowattach") {
} else if (llGetSubString(sChangetype, 0, 10) == "allowattach") {
if (iAuth != CMD_OWNER) RelayNotify(kID, "Access denied!", 0);
else if (sChangevalue == "off") {
g_iAllowAttach = FALSE;

View File

@@ -197,20 +197,17 @@ WearFolder(string sStr, key kID)
llMessageLinked(LINK_DIALOG, NOTIFY, "1"+"Changing outfit!", kID);
string sOutfit = llGetSubString(sStr, llStringLength(g_sPathPrefix), -2);
llMessageLinked(LINK_ROOT, ATTACHMENT_RESPONSE, "CollarCommand|"+(string)g_iAuth+"|ZHAO_ao load "+sOutfit, kID);
// always lock collar during outfit change
llOwnerSay("@detach=n");
// lock the core folder if exists
// Protect against detaching:
llOwnerSay("@detach=n"); // this collar
if (g_sCoreFolder != "") llOwnerSay("@detachallthis:"+g_sCoreFolder+"=n");
// unwear everything that's not locked:
// Remove everything except protected:
llOwnerSay("@remoutfit=force,detach=force");
// ensure everything from core folder is worn:
if (g_sCoreFolder != "") llOwnerSay("@attachallover:"+g_sCoreFolder+"=force");
// wear the chosen outfit:
llOwnerSay("@attachallover:"+sStr+"=force");
// cleanup: unlock core folder if exists
llSleep(1.5);
// Unprotect:
if (g_sCoreFolder != "") llOwnerSay("@detachallthis:"+g_sCoreFolder+"=y");
// cleanup: unlock the collar, only if it was locked temporarily
if (g_iLocked == FALSE) llOwnerSay("@detach=y");
if (g_iLocked == FALSE) llOwnerSay("@detach=y"); // this collar (if it was unlocked)
// Wear the outfit:
llOwnerSay("@attachallover:"+sStr+"=force");
}
doRestrictions()
@@ -652,6 +649,7 @@ default
listen(integer iChan, string sName, key kID, string sMsg)
{
llSetTimerEvent(0.0);
llListenRemove(g_iListener);
if (iChan == g_iFolderRLV) {
if (llStringLength(sMsg) == 1023) llMessageLinked(LINK_DIALOG,NOTIFY,"0"+"\n\nATTENTION: Either some of the names of your outfit folders are too long, or there are too many folders in your Outfits directory. This could lead to gaps in your outfits folder index. For best operability, please consider reducing the overall amount of subfolders within the Outfits directory and use shorter names.\n",g_kWearer);
string sPrompt;

View File

@@ -265,7 +265,7 @@ SafeWord(key kID)
}
llMessageLinked(LINK_THIS, RLV_CMD, "unsit=force", "");
llMessageLinked(LINK_ALL_OTHERS, RLV_CLEAR, "", "");
if (kID != NULL_KEY) llMessageLinked(LINK_DIALOG, NOTIFY, "1"+"RLV restrictions cleared.", kID);
if (kID != NULL_KEY && kID != "") llMessageLinked(LINK_DIALOG, NOTIFY, "1"+"RLV restrictions cleared.", kID);
}
UserCommand(integer iAuth, string sStr, key kID)

View File

@@ -22,7 +22,7 @@
//on menu request, give dialog, with alphabetized list of submenus
//on listen, send submenu link message
string g_sCollarVersion="2025.12";
string g_sCollarVersion="2026.03.06";
key g_kWearer = NULL_KEY;
@@ -87,11 +87,6 @@ integer g_iLocked = FALSE;
integer g_bDetached = FALSE;
integer g_iHide ; // global hide
list g_lCacheAlpha; // integer link, float alpha. for preserving transparent links when unhiding the device
list g_lCacheGlows; // integer link, float glow. for restoring links with glow when unhiding the device
list g_lClosedLockElements; // integer link. links to show when device locked
list g_lOpenLockElements; // integer link. links to show when device unlocked
string g_sDefaultLockSound="sound_lock";
string g_sDefaultUnlockSound="sound_unlock";
string g_sLockSound="sound_lock";
@@ -243,7 +238,6 @@ UserCommand(integer iNum, string sStr, key kID, integer fromMenu) {
g_iLocked = TRUE;
llMessageLinked(LINK_SAVE, LM_SETTING_SAVE, g_sGlobalToken+"locked=1", "");
llMessageLinked(LINK_ROOT, LM_SETTING_RESPONSE, g_sGlobalToken+"locked=1", "");
llOwnerSay("@detach=n");
llMessageLinked(LINK_RLV, RLV_CMD, "detach=n", "main");
llPlaySound(g_sLockSound, 1.0);
SetLockElementAlpha();//EB
@@ -256,7 +250,6 @@ UserCommand(integer iNum, string sStr, key kID, integer fromMenu) {
g_iLocked = FALSE;
llMessageLinked(LINK_SAVE, LM_SETTING_SAVE, g_sGlobalToken+"locked=0", "");
llMessageLinked(LINK_ROOT, LM_SETTING_RESPONSE, g_sGlobalToken+"locked=0", "");
llOwnerSay("@detach=y");
llMessageLinked(LINK_RLV, RLV_CMD, "detach=y", "main");
llPlaySound(g_sUnlockSound, 1.0);
SetLockElementAlpha(); //EB
@@ -270,9 +263,13 @@ UserCommand(integer iNum, string sStr, key kID, integer fromMenu) {
llMessageLinked(LINK_DIALOG, NOTIFY, "0"+"Menus have been fixed!", kID);
//} else llMessageLinked(LINK_DIALOG,NOTIFY,"0"+"%NOACCESS%",kID);
} else if (sCmd == "stealth") Stealth(!g_iHide);
else if (sCmd == "hide") Stealth(TRUE);
else if (sCmd == "show") Stealth(FALSE);
else if (sCmd == "update") {
else if (sCmd == "hide") {
Stealth(TRUE);
if (fromMenu) SettingsMenu(kID, iNum);
} else if (sCmd == "show") {
Stealth(FALSE);
if (fromMenu) SettingsMenu(kID, iNum);
} else if (sCmd == "update") {
if (kID == g_kWearer) {
g_iWillingUpdaters = 0;
g_kCurrentUser = kID;
@@ -330,20 +327,25 @@ string GetTimestamp() {
SetLockElementAlpha() { //EB
if (g_iHide) return ; // ***** if collar is hide, don't do anything
//loop through stored links, setting alpha if element type is lock
integer n;
integer iLinkElements = llGetListLength(g_lOpenLockElements);
for (n = 0; n < iLinkElements; n++) {
llSetLinkAlpha(llList2Integer(g_lOpenLockElements,n), !g_iLocked, ALL_SIDES);
integer idx = llListFindList(g_lCacheGlows, [n]);
if (idx != -1 && (idx %2 == 0))
llSetLinkPrimitiveParamsFast(n, [PRIM_GLOW, ALL_SIDES, llList2Float(g_lCacheGlows, idx+1)]);
}
iLinkElements = llGetListLength(g_lClosedLockElements);
for (n=0; n < iLinkElements; n++) {
llSetLinkAlpha(llList2Integer(g_lClosedLockElements,n), g_iLocked, ALL_SIDES);
integer idx = llListFindList(g_lCacheGlows, [n]);
if (idx != -1 && (idx %2 == 0))
llSetLinkPrimitiveParamsFast(n, [PRIM_GLOW, ALL_SIDES, llList2Float(g_lCacheGlows, idx+1)]);
integer iLink;
for (iLink = LINK_ROOT; iLink < llGetNumberOfPrims(); iLink++) {
string sName = llGetLinkName(iLink);
if (sName=="Lock") llSetLinkAlpha(iLink, !g_iLocked, ALL_SIDES); // openlockelement
else if (sName=="ClosedLock") llSetLinkAlpha(iLink, g_iLocked, ALL_SIDES);
else jump next;
// restore glow (if any):
list lPrimParams = llGetLinkPrimitiveParams(iLink, [PRIM_TEXT, PRIM_DESC]);
list sDesc = llList2String(lPrimParams, 3);
if (llSubStringIndex(sDesc, "noglow") == -1)
{
list lText = llParseString2List(llList2String(lPrimParams, 0), ["~","="], []);
integer idx = llListFindList(lText, ["glow"]);
if (idx != -1) {
float fGlow = llList2Float(lText, idx+1);
if (fGlow > 0.0) llSetLinkPrimitiveParamsFast(iLink, [PRIM_GLOW, ALL_SIDES, fGlow]);
}
}
@next;
}
}
@@ -360,68 +362,53 @@ RebuildMenu() {
llMessageLinked(LINK_ALL_OTHERS, LINK_UPDATE,"LINK_REQUEST","");
}
RebuildCaches() {
g_lCacheAlpha = [-1000, 0.1]; // dummy pair to detect if we lost the lists due to state loss
g_lCacheGlows = [];
g_lOpenLockElements = [];
g_lClosedLockElements = [];
integer iLink;
integer idx;
for (iLink = LINK_ROOT; iLink < llGetNumberOfPrims(); iLink++) {
list lLinkParams = llGetLinkPrimitiveParams(iLink, [PRIM_DESC, PRIM_COLOR, 0, PRIM_GLOW, 0]);
// ^^ returns string desc, vector color, float alpha, float glow. note ALL_SIDES doesn't work on OS, so we use side 0.
string sDesc = llList2String(lLinkParams, 0);
list lSettings = llParseString2List(llToLower(sDesc), ["~"], []);
// is hidden? has alpha?
idx = llListFindList(lSettings, ["hidden"]);
if (idx != -1) g_lCacheAlpha += [iLink, 0.0]; // found hidden setting in prim desc, state-loss-safe.
else {
idx = llListFindList(lSettings, ["alpha"]);
if (idx != -1) g_lCacheAlpha += [iLink, llList2Float(lSettings, idx+1)]; // found desc alpha~f setting
else if (g_iHide == FALSE) {
// backup method, get alpha from prim if collar not hidden yet. NOT state-loss-safe!
float fAlpha = llList2Float(lLinkParams,2);
if (fAlpha < 1.0) g_lCacheAlpha += [iLink, fAlpha];
Stealth(integer iHide) {
if (iHide) {
integer iLink;
integer idx;
for (iLink = LINK_ROOT; iLink < llGetNumberOfPrims(); iLink++) {
list lPrimParams = llGetLinkPrimitiveParams(iLink, [PRIM_DESC, PRIM_COLOR, 0, PRIM_GLOW, 0]);
// ^^ returns [desc, color, alpha, glow]. note ALL_SIDES doesn't work on OS, so we use side 0.
string sText; // stored as key1=value1~key2=value2
string sDesc = llList2String(lPrimParams, 0);
if (llSubStringIndex(sDesc, "FloatText") != 0) { // ignore titler prim
if (llSubStringIndex(sDesc, "hidden") == -1 || llSubStringIndex(sDesc, "nohide") == -1) {
float fAlpha = llList2Float(lPrimParams,2);
if (fAlpha < 1.0) sText = "alpha="+(string)fAlpha;
}
if (llSubStringIndex(sDesc, "noglow") == -1) {
float fGlow = llList2Float(lPrimParams, 3);
if (fGlow > 0.0) sText += "~glow="+(string)fGlow;
}
llSetLinkPrimitiveParamsFast(iLink, [PRIM_TEXT, sText, <1,1,1>, 0.0]);
}
}
// has glows?
idx = llListFindList(lSettings, ["glow"]);
if (idx != -1) g_lCacheGlows += [iLink, llList2Float(lSettings, idx+1)]; // found desc glow~f setting
else if (g_iHide == FALSE) {
// backup method: get glow from prim if collar not hidden yet. NOT state-loss-safe!
float fGlow = llList2Float(lLinkParams, 3);
if (fGlow > 0) g_lCacheGlows += [iLink, fGlow];
}
// is a lock prim?
list lPrimName = llParseString2List(llGetLinkName(iLink), ["~"], []);
if (llListFindList(lPrimName, ["Lock"]) != -1 || llListFindList(lPrimName, ["ClosedLock"]) != -1)
g_lClosedLockElements += [iLink];
else if (llListFindList(lPrimName, ["OpenLock"]) != -1)
g_lOpenLockElements += [iLink];
}
}
Stealth(integer iHide) {
if (llGetListLength(g_lCacheAlpha) == 0) RebuildCaches(); // cache lost, rebuild
if (iHide) {
// Finally, hide:
llSetLinkPrimitiveParamsFast(LINK_SET, [PRIM_GLOW, ALL_SIDES, 0.0]);
llSetLinkAlpha(LINK_SET, 0.0, ALL_SIDES);
} else { // Show
integer iLink;
for (iLink = LINK_ROOT; iLink < llGetNumberOfPrims(); iLink++) {
// restore alpha's:
integer idx = llListFindList(g_lCacheAlpha, [iLink]);
if (idx != -1 && (idx % 2 == 0)) {
float fAlpha = llList2Float(g_lCacheAlpha, idx+1);
llSetLinkAlpha(iLink, fAlpha, ALL_SIDES);
} else llSetLinkAlpha(iLink, 1.0, ALL_SIDES);
// restore glows:
idx = llListFindList(g_lCacheGlows, [iLink]);
if (idx != -1 && (idx %2 == 0)) {
float fGlow = llList2Float(g_lCacheGlows, idx+1);
llSetLinkPrimitiveParamsFast(iLink, [PRIM_GLOW, ALL_SIDES, fGlow]);
list lPrimParams = llGetLinkPrimitiveParams(iLink, [PRIM_TEXT,PRIM_DESC]);
// lPrimParams returns: [hovertext, hovercolor, hoveralpha, desc]
list lText = llParseString2List(llList2String(lPrimParams, 0), ["~","="], []);
string sDesc = llList2String(lPrimParams, 3);
if (llSubStringIndex(sDesc, "FloatText") != 0) { // ignore titler prim
if (llSubStringIndex(sDesc, "hidden") == -1 || llSubStringIndex(sDesc, "nohide") == -1) {
integer idx = llListFindList(lText, ["alpha"]);
if (idx != -1) {
float fAlpha = (float)llList2String(lText, idx+1);
llSetLinkAlpha(iLink, fAlpha, ALL_SIDES); // show alpha'd
} else llSetLinkAlpha(iLink, 1.0, ALL_SIDES); // show all
}
if (llSubStringIndex(sDesc, "noglow") == -1) {
integer idx = llListFindList(lText, ["glow"]);
if (idx != -1) {
float fGlow = (float)llList2String(lText, idx+1);
llSetLinkPrimitiveParamsFast(iLink, [PRIM_GLOW, ALL_SIDES, fGlow]);
}
}
}
}
}
@@ -433,8 +420,6 @@ Stealth(integer iHide) {
init() {
g_iWaitRebuild = TRUE;
llSetTimerEvent(1.0);
if (g_iLocked) llOwnerSay("@detach=n");
SetLockElementAlpha();
}
StartUpdate() {
@@ -448,7 +433,6 @@ default {
g_kWearer = llGetOwner();
if (llGetInventoryType("oc_installer_sys")==INVENTORY_SCRIPT) return;
g_iHide = !(integer)llGetAlpha(ALL_SIDES);
if (llGetListLength(g_lCacheAlpha) == 0) RebuildCaches(); // no dummy pair, so cache lost, rebuild
init();
//Debug("Starting");
}
@@ -515,7 +499,7 @@ default {
else if (sMessage == "Help") UserCommand(iAuth, "help", kAv, TRUE);
else if (sMessage == "Update") UserCommand(iAuth, "update", kAv, TRUE);
else if (sMessage == "Version")
g_kHttpVersion = llHTTPRequest("https://raw.githubusercontent.com/lickx/oscollar-dev/master/web/device", [], "");
g_kHttpVersion = llHTTPRequest("https://git.lotix.org/lotek/oscollar/raw/branch/master/web/device", [], "");
} else if (sMenu == "UpdateConfirmMenu"){
if (sMessage=="Yes") StartUpdate();
else {
@@ -531,11 +515,11 @@ default {
UserCommand(iAuth, sMessage, kAv, TRUE);
return;
} else if (sMessage == "☑ Visible") {
Stealth(TRUE);
llMessageLinked(LINK_ROOT, iAuth, "hide", kAv);
UserCommand(iAuth, "hide", kAv, TRUE);
return;
} else if (sMessage == "☐ Visible") {
Stealth(FALSE);
llMessageLinked(LINK_ROOT, iAuth, "show", kAv);
UserCommand(iAuth, "show", kAv, TRUE);
return;
} else if (sMessage == "Themes") {
llMessageLinked(LINK_ROOT, iAuth, "menu Themes", kAv);
return;
@@ -559,7 +543,7 @@ default {
string sValue = llList2String(lParams, 1);
if (sToken == g_sGlobalToken+"locked") {
g_iLocked = (integer)sValue;
if (g_iLocked) llOwnerSay("@detach=n");
if (g_iLocked) llMessageLinked(LINK_RLV, RLV_CMD, "detach=n", "main");
SetLockElementAlpha();
} else if (sToken == "intern_integrity") g_sIntegrity = sValue;
else if (sToken == "intern_looks") g_iLooks = (integer)sValue;
@@ -570,12 +554,16 @@ default {
if (sValue=="default") g_sUnlockSound=g_sDefaultUnlockSound;
else if ((key)sValue!=NULL_KEY || llGetInventoryType(sValue)==INVENTORY_SOUND) g_sUnlockSound=sValue;
} else if (sToken == g_sGlobalToken+"safeword") g_sSafeWord = sValue;
else if (sToken == g_sGlobalToken+"stealth") g_iHide = (integer)sValue;
} else if (iNum == DIALOG_TIMEOUT) {
integer iMenuIndex = llListFindList(g_lMenuIDs, [kID]);
g_lMenuIDs = llDeleteSubList(g_lMenuIDs, iMenuIndex-1, iMenuIndex-2 + g_iMenuStride);
} else if (iNum == RLV_REFRESH || iNum == RLV_CLEAR) {
} else if (iNum == RLV_REFRESH) {
if (g_iLocked) llMessageLinked(LINK_RLV, RLV_CMD, "detach=n", "main");
else llMessageLinked(LINK_RLV, RLV_CMD, "detach=y", "main");
SetLockElementAlpha();
} else if (iNum == RLV_CLEAR) {
if (g_iLocked) llMessageLinked(LINK_RLV, RLV_CMD, "detach=y", "main");
} else if (iNum == REBOOT && sStr == "reboot") llResetScript();
}
@@ -596,14 +584,10 @@ default {
integer iNewHide=!(integer)llGetAlpha(ALL_SIDES) ; //check alpha
if (g_iHide != iNewHide){ //check there's a difference to avoid infinite loop
g_iHide = iNewHide;
RebuildCaches();
SetLockElementAlpha(); // update hide elements
}
}
if (iChange & CHANGED_LINK) {
llMessageLinked(LINK_ALL_OTHERS,LINK_UPDATE,"LINK_REQUEST","");
RebuildCaches();
}
if (iChange & CHANGED_LINK) llMessageLinked(LINK_ALL_OTHERS,LINK_UPDATE,"LINK_REQUEST","");
if (iChange & CHANGED_REGION) llMessageLinked(LINK_ALL_OTHERS,REGION_CROSSED,"","");
if (iChange & CHANGED_TELEPORT) llMessageLinked(LINK_ALL_OTHERS,REGION_TELEPORT,"","");
}
@@ -612,7 +596,7 @@ default {
if (g_iLocked) {
if(kID == NULL_KEY) {
g_bDetached = TRUE;
llMessageLinked(LINK_DIALOG,NOTIFY_OWNERS, "%WEARERNAME% has attached me while locked at "+GetTimestamp()+"!",kID);
llMessageLinked(LINK_DIALOG,NOTIFY_OWNERS, "%WEARERNAME% has detached me while locked at "+GetTimestamp()+"!",kID);
} else {
if (g_bDetached)
llMessageLinked(LINK_DIALOG,NOTIFY_OWNERS, "%WEARERNAME% has re-attached me at "+GetTimestamp()+"!",kID);
@@ -672,7 +656,7 @@ default {
if (compareVersions(sWebVersion, g_sCollarVersion)) {
llOwnerSay("An update is available!");
// Fetch a list of distribution sites:
g_kHttpDistsites = llHTTPRequest("https://raw.githubusercontent.com/lickx/oscollar-dev/master/web/distsites", [], "");
g_kHttpDistsites = llHTTPRequest("https://git.lotix.org/lotek/oscollar/raw/branch/master/web/distsites", [], "");
} else
llOwnerSay("You are using the most recent version");
} else if (kID == g_kHttpDistsites) {

View File

@@ -1,4 +1,4 @@
## The Owner HUD
## The OsCollar Remote
###### A graphical user interface for ease of access to OsCollar scripted devices.

View File

@@ -18,8 +18,6 @@
// along with this script; if not, see www.gnu.org/licenses/gpl-2.0
//
// Debug(string sStr) { llOwnerSay("Debug ["+llGetScriptName()+"]: " + sStr); }
//chopped from the OpenCollar_Dialog script in slimmer shape for the Owner HUD june 2015 Otto (garvin.twine)
//an adaptation of Schmobag Hogfather's SchmoDialog script

View File

@@ -18,8 +18,6 @@
// along with this script; if not, see www.gnu.org/licenses/gpl-2.0
//
// Debug(string sStr) { llOwnerSay("Debug ["+llGetScriptName()+"]: " + sStr); }
//Adjusted to OpenCollar name convention und format standards June 2015 Otto (garvin.twine)
//Updated Romka(romka.swallowtail)
@@ -292,7 +290,7 @@ DoMenu(string sMenu)
lUtils = ["Reset", UPMENU];
}
if (sMenu == g_sHudMenu) { // Main
sPrompt = "\nCustomize your Owner HUD!";
sPrompt = "\nCustomize your Remote!";
lButtons = ["Rows: "+(string)g_iRows] ;
if (g_iRows > 1) lButtons += llList2List(["Columns >","Alternate >"], g_iColumn, g_iColumn) ;
else lButtons += [" - "] ;
@@ -416,7 +414,7 @@ default
string sButton = llList2String(lParams, 1);
//integer iPage = llList2Integer(lParams, 2);
if (g_sCurrentMenu == g_sHudMenu) { // -- Inside the 'Options' menu, or 'submenu'
// If we press the 'Back' and we are inside the Options menu, go back to OwnerHUD menu
// If we press the 'Back' and we are inside the Options menu, go back to Remote menu
if (sButton == UPMENU) {
llMessageLinked(LINK_SET, SUBMENU, g_sParentMenu, kID);
return;

View File

@@ -18,11 +18,9 @@
// along with this script; if not, see www.gnu.org/licenses/gpl-2.0
//
// Debug(string sStr) { llOwnerSay("Debug ["+llGetScriptName()+"]: " + sStr); }
//merged HUD-menu, HUD-leash and HUD-rezzer into here June 2015 Otto (garvin.twine)
string g_sVersion = "2025.05";
string g_sVersion = "2026.01";
list g_lPartners;
list g_lNewPartnerIDs;
@@ -57,7 +55,7 @@ integer ACC_CMD = 7000;
integer DIALOG = -9000;
integer DIALOG_RESPONSE = -9001;
integer DIALOG_TIMEOUT = -9002;
integer CMD_OWNER_HUD = 10000;
integer CMD_REMOTE = 10000;
integer UPDATE = 5555;
string UPMENU = "BACK";
string g_sListPartners = "List";
@@ -191,7 +189,7 @@ AddPartner(string sID)
if (llListFindList(g_lPartners, [sID]) != -1) return;
if ((key)sID != NULL_KEY) {//don't register any unrecognised
g_lPartners += [sID];//Well we got here so lets add them to the list.
llOwnerSay("\n\n"+NameURI(sID)+" has been registered.\nFor easy selection, add a photo or texture to the Owner HUD called '"+PlainName((key)sID)+"'.\n");//Tell the owner we made it.
llOwnerSay("\n\n"+NameURI(sID)+" has been registered.\nFor easy selection, add a photo or texture to the Remote called '"+PlainName((key)sID)+"'.\n");//Tell the owner we made it.
StorePartners();
}
}
@@ -217,7 +215,7 @@ Dialog(string sPrompt, list lChoices, list lUtilityButtons, integer iPage, strin
MainMenu()
{
string sPrompt = "\nOsCollar - Owner HUD\t"+g_sVersion;
string sPrompt = "\nOsCollar - Remote\t"+g_sVersion;
sPrompt += "\n\nSelected Partner: "+NameURI(g_sActivePartnerID);
list lButtons = g_lMainMenuButtons + g_lMenus;
Dialog(sPrompt, lButtons, [], 0, g_sMainMenu);
@@ -297,7 +295,6 @@ NextPartner(integer iDirection, integer iTouch)
integer iAt = llSubStringIndex(llKey2Name((key)g_sActivePartnerID), "@");
// Convert 'First.Last @grid:port' to 'First Last' if hypergrid name found
if (iDot > 0 && iAt > 0) sActivePartnerName = llGetSubString(sActivePartnerName, 0, iDot-1) +" "+llGetSubString(sActivePartnerName, iDot+1, iAt-2);
llOwnerSay("calling SetPicturePrim for "+sActivePartnerName);
if (g_iPicturePrim) SetPicturePrim(sActivePartnerName);
} else if (g_sActivePartnerID == g_sAllPartners)
if (g_iPicturePrim) llSetLinkPrimitiveParamsFast(g_iPicturePrim,[PRIM_TEXTURE, 1, g_sTextureALL,<1.0, 1.0, 0.0>, ZERO_VECTOR, 0.0]);
@@ -328,7 +325,7 @@ default {
g_iPicturePrim = PicturePrim();
LoadPartners();
if (llGetListLength(g_lPartners) == 0) {
llOwnerSay("\n\nYou are probably wearing this Owner HUD for the first time. I'm opening the menu where you can manage your partners. Make sure that your partners are near you and click Add to register them. To open the menu again, please select the gear (⚙) icon on your HUD.\n");
llOwnerSay("\n\nYou are probably wearing this Remote for the first time. I'm opening the menu where you can manage your partners. Make sure that your partners are near you and click Add to register them. To open the menu again, please select the gear (⚙) icon on your HUD.\n");
}
NextPartner(0,0);
MainMenu();
@@ -398,7 +395,7 @@ default {
}
lParams = [];
} else if (iNum == SUBMENU && sStr == "Main") MainMenu();
else if (iNum == CMD_OWNER_HUD) SendCollarCommand(sStr);
else if (iNum == CMD_REMOTE) SendCollarCommand(sStr);
else if (iNum == UPDATE) {
if (sStr != "") g_lPartners = llCSV2List(sStr);
else llMessageLinked(iSender, UPDATE+1, llList2CSV(g_lPartners),"");

View File

@@ -245,7 +245,7 @@ default
if(k!=menuUser)
{
// calculate collar channel per victim and add a listener
channel=PersonalChannel((string)k,0);
channel=PersonalChannel((string)k,1234);
listeners+=
[
llListen(channel,"",NULL_KEY,"")

View File

@@ -1 +1 @@
2025.12
2026.03.06

1
web/remote Normal file
View File

@@ -0,0 +1 @@
2026.01