/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // 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 = llParseStringKeepNulls(data, ["&", "="], []); integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]); if(i != -1) return llList2String(a, 2*i+1); return ""; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// string wasKeyValueSet(string k, string v, string data) { if(llStringLength(k) == 0) return ""; if(llStringLength(v) == 0) return ""; if(llStringLength(data) == 0) return k + "=" + v; integer i = llListFindList( llList2ListStrided( llParseString2List(data, ["&", "="], []), 0, -1, 2 ), [ k ]); if(i != -1) return llDumpList2String( llListReplaceList( llParseString2List(data, ["&"], []), [ k + "=" + v ], i, i), "&"); return data + "&" + k + "=" + v; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// list wasDualQuicksort(list a, list b) { if(llGetListLength(a) <= 1) return a+b; float pivot_a = llList2Float(a, 0); a = llDeleteSubList(a, 0, 0); string pivot_b = llList2String(b, 0); b = llDeleteSubList(b, 0, 0); list less = []; list less_b = []; list more = []; list more_b = []; do { if(llList2Float(a, 0) < pivot_a) { less += llList2List(a, 0, 0); less_b += llList2List(b, 0, 0); jump continue; } more += llList2List(a, 0, 0); more_b += llList2List(b, 0, 0); @continue; a = llDeleteSubList(a, 0, 0); b = llDeleteSubList(b, 0, 0); } while(llGetListLength(a)); return wasDualQuicksort(less, less_b) + [ pivot_a ] + [ pivot_b ] + wasDualQuicksort(more, more_b); } default { collision_start(integer num) { // filter agent collisions if(llDetectedType(0) & AGENT) return; key agent = llGetOwnerKey(llDetectedKey(0)); integer range = (integer)wasKeyValueGet("range", llList2String(llGetLinkPrimitiveParams(3, [PRIM_DESC]), 0)); // only accept players from a minimum 10 meters range. if(llVecDist(llGetPos(), llList2Vector(llGetObjectDetails(agent, [OBJECT_POS]), 0)) < range) { llInstantMessage(agent, "For the score to register, you must be at least " + (string)range + "m away from the bullseye!"); return; } // calculate distance from origin vector a = llGetRootPosition(); vector b = llDetectedPos(0); vector t = -(a-b)/llGetRootRotation(); float d = llSqrt(llPow(t.x, 2) + llPow(t.y, 2)); // get the top scorers list tags = [ "1", "2", "3" ]; list agents = []; list scores = []; do { string tag = llList2String(tags, 0); list as = llCSV2List(wasKeyValueGet(tag, llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0))); if(llGetListLength(as) != 2) jump continue_get; agents += llList2String(as, 0); scores += llList2String(as, 1); @continue_get; tags = llDeleteSubList(tags, 0, 0); } while(llGetListLength(tags)); // check if the scorer already exists string name = llKey2Name(llGetOwnerKey(llDetectedKey(0))); // if the player does not exist, register them integer i = llListFindList(agents, [name]); if(i == -1) { agents += name; scores += d; jump sort; } // if the score is better, then add it, otherwise keep the score float score = llList2Float(scores, i); if(d > score) jump sort; scores = llListReplaceList(scores, [d], i, i); @sort; // sort them in ascending order (less is better) list scorers = wasDualQuicksort(scores, agents); // and build the store list store = []; // also build the text while we are at it string text = ""; do { string agent = llList2String(scorers, 1); if(agent == "") jump continue_set; string score = llList2String(scorers, 0); if(score == "") jump continue_set; // add to store store += llList2CSV([agent, score]); text += agent; text += " -> "; text += score; text += "\n"; @continue_set; scorers = llDeleteSubList(scorers, 0, 1); // only record the 5 top scorers if(llGetListLength(store) == 3) jump break; } while(llGetListLength(scorers)); @break; // now store the top scorers tags = [ "1", "2", "3" ]; do { string desc = llList2String(llGetLinkPrimitiveParams(2, [PRIM_DESC]), 0); llSetLinkPrimitiveParamsFast(2, [PRIM_DESC, wasKeyValueSet(llList2String(tags, 0), llList2String(store, 0), desc)]); tags = llDeleteSubList(tags, 0, 0); store = llDeleteSubList(store, 0, 0); } while(llGetListLength(store)); // finally, display the scorers llMessageLinked(LINK_SET, 0, text, (string)<1,1,0>); } on_rez(integer num) { llResetScript(); } }