Difference between revisions of "User:Daemonika Nightfire/Scripts/Giver Tutorial"
Line 268: | Line 268: | ||
if(change & CHANGED_OWNER) | if(change & CHANGED_OWNER) | ||
{ | { | ||
// resettet das Script, sobald | // resettet das Script, sobald das Object den Besitzer wechselt | ||
llResetScript(); | llResetScript(); | ||
} | } |
Revision as of 19:12, 18 May 2013
Simple Giver
Der Landmark Giver ist eines der am haeufigsten verwendeten Scripte in SL, beinahe jeder Shop und Club verfuegt ueber so einen. Da es besonders in Malls in hoher Anzahl vorkommt, sollte man darauf achten so wenig wie moeglich ins Script zu schreiben und nach moeglichkeit den Memory begrenzen, um nicht unnoetig Resourcen zu verschwenden. <lsl> /*
*DS* Simple Landmark Giver by Daemonika Nightfire Da es sich hier um ein sehr sehr seeeehr kleines Script handelt, habe ich hier das Memory Limit vorgesehen. Der Grund liegt ganz einfach darin, den gesamten Region Memory auf diesem Weg so wenig wie moeglich zu belasten. Genauere Informationen ueber Script-Memory findest du hier: https://wiki.secondlife.com/wiki/User:Daemonika_Nightfire/Scripts/Memory_Walkthrough
- /
default {
state_entry() { // manuelles Script Limit (fuer einen simplen Giver voellig ausreichend) llSetMemoryLimit(10000); } touch_start(integer total_number) { // ueberprueft den Inhalt, ob eine Landmarke vorhanden ist und gibt diese aus if(llGetInventoryNumber(INVENTORY_LANDMARK) > 0) { llGiveInventory(llDetectedKey(0),llGetInventoryName(INVENTORY_LANDMARK, 0)); } } changed(integer change) { if(change & CHANGED_INVENTORY) { // resettet das Script, sobald sich der Inhalt des Objects aendert llResetScript(); } } on_rez(integer Dae) { // resettet das Script, sobald es gerezzt wird llResetScript(); }
} </lsl>
Natuerlich kann man ein und das selbe Script auch fuer andere Dinge als Landmarken verwenden. Ersetz dazu einfach die Konstanten in den Befehlen llGetInventoryNumber und llGetInventoryName. Die Konstanten beider Befehle sollten natuelrich identisch sein.
<LSL> // Ziemlich nutzlos, dann kann man sich auch das Script sparen. INVENTORY_NONE
// Als Simple Giver nicht zu empfehlen, wenn man nicht moechte, dass das Script mit ausgegeben wird. INVENTORY_ALL
// Ideal fuer jeden Shop und Club. INVENTORY_LANDMARK
// Wird oft im Roleplay verwendet um Regeln zu uebergeben. INVENTORY_NOTECARD
// INVENTORY_SOUND
// INVENTORY_OBJECT
// INVENTORY_GESTURE
// INVENTORY_TEXTURE
// INVENTORY_CLOTHING
// INVENTORY_BODYPART
// INVENTORY_SCRIPT
// INVENTORY_ANIMATION </lsl>
Advanced Giver
Wenn man nun den Kompletten Inhalt, mit Ausnahme des Scriptes ausgeben moechte, empfiehlt es sich folgendes Script zu verwenden. Ein weiterer Vorteil dieses Scripts ist, es vergibt den Inhalt in einem Ordner. llGiveInventoryList( key target, string folder, list inventory );
<LSL> /*
*DS* Give Inventory ALL 2 All by Daemonika Nightfire Dieses Script gibt "jedem", der das Object klickt, den kompletten Inhalt, mit ausnahme des Scripts aus. Anders als bei den aelteren Scripten, wo der Inhalt bei jedem klicken neu ausgelesen wird, speichert dieses Script die Namen des Inhalts bereits im State_entry in eine Liste.
- /
list inventory = []; string name; integer num;
default {
state_entry() { num = llGetInventoryNumber(INVENTORY_ALL); integer i; // ab hier wird das komplette Inventar des Objects ausgelesen for(i = 0; i < num; ++i) { // liesst die Inventar-Namen aus name = llGetInventoryName(INVENTORY_ALL, i); // Diese Funktion, sorgt dafuer, das das Script nicht zur Liste hinzu gefuegt wird if(name != llGetScriptName()) { // fuegt die ausgelesenen Inventar-Namen in die Liste ein. inventory += name; } } } touch_start(integer total_number) { if(llGetListLength(inventory) < 1) { // bloed wenn die Box leer ist ;) llWhisper(0,"No items to offer."); } else { // gibt den gelisteten Inhalt aus (es dauert 3 secunden, bis das Script hier nach wieder reagiert) llGiveInventoryList(llDetectedKey(0), llGetObjectName(), inventory); } } changed(integer change) { if(change & CHANGED_INVENTORY) { // resettet das Script, sobald sich der Inhalt des Objects aendert llResetScript(); } } on_rez(integer Dae) { // resettet das Script, sobald es gerezzt wird llResetScript(); }
} </LSL>
Advanced Giver Comparison
Viele Wege fuehren nach Rom, so auch hier. Es gibt mehrere Varianten das Inventar eines Objects auszulesen und in eine Liste zu speichern. Drum moechte ich hier mal 2 Vergleichen.
Version A | Version B |
---|---|
<lsl>
state_entry() { num = llGetInventoryNumber(INVENTORY_ALL); integer i; for(i = 0; i < num; ++i) { name = llGetInventoryName(INVENTORY_ALL, i); if(name != llGetScriptName()) { inventory += name; } } } </lsl> |
<lsl>
state_entry() { num = llGetInventoryNumber(INVENTORY_ALL); integer i; for(i = 0; i < num; ++i) { name = llGetInventoryName(INVENTORY_ALL, i); inventory += name; } i = llListFindList(inventory, [llGetScriptName()]); inventory = llDeleteSubList(inventory, i, i); } </lsl> |
Version A In der Version A wird das ganze Inventar ausgelesen und die jeweiligen Namen in eine Liste gespeichert. Allerdings wird das Script in der for Schleife uebergangen und nicht mit aufgelistet.
Version B In der Version B passiert das gleiche, jedoch wird hier das Script zuerst mit aufgelistet. Erst nachdem die for Schleife beendet wurde, wird das Script wieder aus der liste entfernt. Das heisst, hier wird anschliessend die ganze Liste noch einmal ausgelesen um einen einzigen Eintrag zu finden. Fazit: Nicht empfehlenswert, wenn man auf Memory angewiesen ist.
Unpacker
Folgendes Script ist eigentlich das gleiche wie oben, nur mit dem Unterschied, dass der Owner-Key als globale Variable gespeichert und beim touch gegen geprueft wird und im changed Event nicht resettet wird, wenn sich etwas am Inventar veraendert.
<lsl> /*
*DS* Give Inventory ALL 2 Owner by Daemonika Nightfire Dieses Script gibt bei klick nur dem Besitzer den kompletten Inhalt, mit ausnahme des Scripts aus. Anders als bei den aelteren Scripten, wo der Inhalt bei jedem klicken neu ausgelesen wird, speichert dieses Script die Namen des Inhalts bereits im State_entry in eine Liste.
- /
key owner;
list inventory = []; string name; integer num;
default {
state_entry() { // Speichert den Besitzer-Key (UUID) owner = llGetOwner(); num = llGetInventoryNumber(INVENTORY_ALL); integer i; // ab hier wird das komplette Inventar des Objects ausgelesen for(i = 0; i < num; ++i) { // liesst die Inventar-Namen aus name = llGetInventoryName(INVENTORY_ALL, i); // Diese Funktion, sorgt dafuer, das das Script nicht zur Liste hinzu gefuegt wird if(name != llGetScriptName()) { // fuegt die ausgelesenen Inventar-Namen in die Liste ein. inventory += name; } } } touch_start(integer total_number) { // reagiert nur, wenn der Besitzer klickt if(llDetectedKey(0) == owner) { if(llGetListLength(inventory) < 1) { // bloed wenn die Box leer ist ;) llWhisper(0,"No items to offer."); } else { // gibt den gelisteten Inhalt aus (es dauert 3 secunden, bis das Script hier nach wieder reagiert) llGiveInventoryList(owner, llGetObjectName(), inventory); } } } changed(integer change) { // Hinweis: // CHANGED_OWNER wird nicht ausgeloest bei Objecten die im Inventar uebergeben werden. if(change & CHANGED_OWNER) { // resettet das Script, sobald das Object den Besitzer wechselt llResetScript(); } // Ein Reset bei CHANGED_INVENTORY ist in Verbindung mit (no copy) Items nicht zu empfehlen. //if(change & CHANGED_INVENTORY) //{ // resettet das Script, sobald sich der Inhalt des Objects aendert //llResetScript(); //} } on_rez(integer Dae) { // resettet das Script, sobald es auf dem Boden gerezzt wird llResetScript(); }
} </lsl>