Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Library: Multi-item, Multi-author vendor

Apotheus Silverman
I write code.
Join date: 17 Nov 2003
Posts: 416
05-03-2004 18:02
I originally created this vendor to sell an aircraft that Cubey Terra and I jointly created so we can sell them without having to worry about doing any extra accounting or worrying about potential *gasp* trust issues. During its creation I learned that there is a noticeable lack of decent vendor scripts here, so I figure what the heck... I'll give it to the community.

This vendor features:
  1. Multiple item support with different prices per item.
  2. Gives change or refund if incorrect amount is given.
  3. Supports multiple item authors per item. Automatically divides money evenly among all authors.
  4. Notifies all authors of every purchase.
  5. Includes a fail-safe mechanism so an incorrectly-configured vendor cannot inadvertently take people's money and give nothing in return.
  6. Display models rather than images to display items. This lets potential customers get a much better idea of what they're getting before making a purchase versus displaying images of items.




Now, onto the scripts.


Main vendor script:
CODE

// This is the name of the notecard to read items from
string itemDataNotecard = "Item Data";

// Type of thingy this vendor sells (inventory constant)
integer inventoryType = INVENTORY_OBJECT;

// Keeps track of the currently-displayed item (1-indexed)
integer currentItem = 0;

// Floating text color
vector textColor = <1,1,1>;

// Model rez position relative to parent object
vector rezPosition = <-0.1,0,-0.1>;

// Inter-object commands
string commandDerez = "derez";

// How many seconds between automatic item changes
float changeTimer = 300.0;



// This is the channel the main vendor talks to rezzed models on
integer commChannel;

// These lists are synchronized to simulate a structure for each item's data
list items = [];
list models = [];
list prices = [];
list authors = [];

// Required to read the notecard properly
integer notecardLine;
key currentDataRequest;


// Reads the data from the notecard. Each line in the notecard should be
// formatted as follows:
// Item Name, Model Name, Price, Authors
// string (no commas), string (no commas), integer, pipe-delimited list of keys
// Example:
// Abbotts Float Plane v1.0.1, Abbotts Float Plane Model, 500, key|key
InitializationStep1() {
llSay(0, "Reading item data...");
notecardLine = 0;
currentDataRequest = llGetNotecardLine(itemDataNotecard, notecardLine);
}

// Requests debit permission
InitializationStep2() {
// Request debit permission
llRequestPermissions(llGetOwner(), PERMISSION_DEBIT);
}

// Change currently-displayed item
SetCurrentItem(integer item) {
// determine which item to display
integer itemCount = llGetListLength(items) - 1;
currentItem = item;
if (currentItem == -1) {
currentItem = itemCount;
} else if (currentItem > itemCount) {
currentItem = 0;
}

// derez current model
llWhisper(commChannel, commandDerez);

// Build and set hover text
string hoverText = "Item " + (string)(currentItem + 1) + " of " + (string)(itemCount + 1) + "\n" + llList2String(items, currentItem) + "\n$" + (string)llList2String(prices, currentItem);
llSetText(hoverText, textColor, 1.0);

// Say what item is now being displayed
llSay(0, "Now Showing: " + llList2String(items, currentItem));

// rez the new model
llRezObject(llList2String(models, currentItem), llGetPos() + rezPosition, ZERO_VECTOR, ZERO_ROTATION, commChannel);
}

default {
state_entry() {
llSay(0, "Starting up...");

// Initialize commChannel
commChannel = (integer)llFrand(2000000000.0);

// Clear text
llSetText("", textColor, 1.0);

// Read notecard, populate lists
InitializationStep1();
}

run_time_permissions(integer perm) {
if (perm & PERMISSION_DEBIT) {
state vend;
} else {
llSay(0, "You must grant debit permission for me to work properly.");
}
}

dataserver(key query, string data) {
if (query == currentDataRequest) {
currentDataRequest = ""; // Prevent a bug that occurs with dataserver events.
if (data != EOF) {
// Read the current item
list currentList = llCSV2List(data);
string myItemName = llList2String(currentList, 0);
string myModelName = llList2String(currentList, 1);
integer myPrice = llList2Integer(currentList, 2);
string myAuthorsAsString = llList2String(currentList, 3);

items += [myItemName];
models += [myModelName];
prices += [myPrice];
authors += [myAuthorsAsString];

notecardLine++;
// Get the next line
currentDataRequest = llGetNotecardLine(itemDataNotecard, notecardLine);
} else {
// Signal that we are done getting items
InitializationStep2();
}
}
}
}




state vend {
state_entry() {
//llSay(0, "items = " + llDumpList2String(items, ","));
//llSay(0, "models = " + llDumpList2String(models, ","));
//llSay(0, "prices = " + llDumpList2String(prices, ","));
//llSay(0, "authors = " + llDumpList2String(authors, ","));

// Rez initial model
SetCurrentItem(currentItem);

// Start the timer for item autorotation
llSetTimerEvent(changeTimer);

llSay(0, "Multiauthor Multivendor online.");
}

timer() {
// Choose a random item to display. Make sure it's not the current item.
integer newItem = currentItem;
if (llGetListLength(items) > 1) {
while (newItem == currentItem) {
newItem = (integer)(llFrand(llGetListLength(items)) + 1.0);
}
SetCurrentItem(newItem);
}
}

touch(integer total) {
llSay(0, "I sell things! Use the left or right arrows to cycle through the items I am selling, then right-click and \"Pay\" me the displayed amount to purchase an item.");
}

// Someone has given me money
money(key agentkey, integer amount) {
string name = llKey2Name(agentkey);
integer currentPrice = llList2Integer(prices, currentItem);
integer sale;
integer i;

if(amount < currentPrice) {
// Not enough money was given. Cancel sale.
llSay(0, name + " you Paid $" + (string)amount + " - thats not enough money for the current item! Refunding $" + (string)amount + "...");
llGiveMoney(agentkey, amount);
sale = FALSE;
}
else if(amount > currentPrice) {
// Too much money was given. Refund the differnce.
integer change = amount - currentPrice;
llSay(0, name + " you Paid $" + (string)amount + " - your change is $" + (string)change + ".");
llGiveMoney(agentkey, change);
sale = TRUE;
} else {
// The proper amount was given.
sale = TRUE;
}

if (sale) {
// Make sure I have the item in inventory before trying to give it.
integer found = FALSE;
//llSay(0, "searching for " + llList2String(items, currentItem));
for (i = 0; i < llGetInventoryNumber(inventoryType); i++) {
if (llGetInventoryName(inventoryType, i) == llList2String(items, currentItem)) {
found = TRUE;
}
}

if (!found) {
// Display error and refund money
llSay(0, "Erm, I am sorry " + name + ", but it seems that I do not have that item to give to you, so I am refunding the purchase price. Please contact my owner about this issue.");
llGiveMoney(agentkey, currentPrice);
} else {
// Complete the sale
llSay(0, "Thank you for your purchase, " + name + "!");
llGiveInventory(agentkey, llList2String(items, currentItem));

llWhisper(0, "Please wait while I perform accounting activities...");

// Distribute money to the object authors
list myAuthors = llParseString2List(llList2String(authors, currentItem), ["|"], []);

if (llGetListLength(myAuthors) > 0) {
integer shareAmount = (integer)llList2Integer(prices, currentItem) / llGetListLength(myAuthors);
// Eliminate my owner from the authors list
for (i = 0; i < llGetListLength(myAuthors); i++) {
llInstantMessage(llList2Key(myAuthors, i), name + " purchased " + llList2String(items, currentItem) + ". Your share is L$" + (string)shareAmount + ".");
if (llList2Key(myAuthors, i) == llGetOwner()) {
myAuthors = llDeleteSubList(myAuthors, i, i);
}
}
// Pay any remaining authors accordingly
if (shareAmount > 0 && llGetListLength(myAuthors) > 0) {
for (i = 0; i < llGetListLength(myAuthors); i++) {
llGiveMoney(llList2Key(myAuthors, i), shareAmount);
}
}
}
llWhisper(0, "Accounting completed. Thanks again, " + name + "!");
}
}
}

link_message(integer sender, integer num, string message, key id) {
if (message == "next") {
llSetTimerEvent(changeTimer);
SetCurrentItem(currentItem + 1);
} else if (message == "prev") {
llSetTimerEvent(changeTimer);
SetCurrentItem(currentItem - 1);
}
}

on_rez(integer startParam) {
llResetScript();
}
}




Back button script:
CODE

default {
state_entry() {
}

touch_start(integer total_number) {
llMessageLinked(LINK_ROOT, 0, "prev", NULL_KEY);
}
}




Next button script:
CODE

default {
state_entry() {
}

touch_start(integer total_number) {
llMessageLinked(LINK_ROOT, 0, "next", NULL_KEY);
}
}




A basic display model script:
CODE

// Inter-object commands
string commandDerez = "derez";

// This is the channel the main vendor talks to rezzed models on
integer commChannel;

default {
state_entry() {
llTargetOmega(<0,0,1>,0.2,1.0);
}

on_rez(integer startParam) {
commChannel = startParam;
llListen(commChannel, "", NULL_KEY, commandDerez);
}

listen(integer channel, string name, key id, string message) {
llDie();
}
}




Sample "Item Data" notecard:

Abbotts Float Plane v1.0.1, Float Plane Display Model - red stripe, 500, d9bcb9e0-bfa2-4b8b-a8fc-9d996935ef51|0d994ae7-2d6a-4cd3-bdcf-81c82c35928b
Abbotts Float Plane v1.0.1 black feathers, Float Plane Display Model - black feathers, 500, d9bcb9e0-bfa2-4b8b-a8fc-9d996935ef51|0d994ae7-2d6a-4cd3-bdcf-81c82c35928b
Abbotts Float Plane v1.0.1 red-yellow feathers, Float Plane Display Model - red feathers, 500, d9bcb9e0-bfa2-4b8b-a8fc-9d996935ef51|0d994ae7-2d6a-4cd3-bdcf-81c82c35928b
Abbotts Float Plane v1.0.1 stars stripes, Float Plane Display Model - stars stripes, 500, d9bcb9e0-bfa2-4b8b-a8fc-9d996935ef51|0d994ae7-2d6a-4cd3-bdcf-81c82c35928b
_____________________
Apotheus Silverman
Shop SL on the web - SLExchange.com

Visit Abbotts Aerodrome for gobs of flying fun.
Remo Yossarian
Registered User
Join date: 15 Feb 2004
Posts: 121
05-04-2004 11:51
Awesome Apotheus

You saved me about 10 hours trying to reverse engineer one of these. :D

Edit (ok i did not figue out the key stuff. Removed so I dont confuse anyone. buttons are also working fine) thanks Apoth/chris

Apotheus Silverman
I write code.
Join date: 17 Nov 2003
Posts: 416
05-04-2004 18:53
From: someone

What are they?

The keys are the keys of each of the authors' avatars.

From: someone

How do you figure out what keys to use?

If you're selling your own items, make a script that does llSay(0, (string)llGetOwner()); in state_entry. It'll tell you what your key is.

From: someone

What do they do?

These keys tell the script who the author(s) of the current line's item are. It uses them to send notifications and money to the proper people immediately after each sale.

From: someone

The ones in your example at the end are all the same?

The ones in the example are mine and Cubey's, because we jointly created the float planes.
_____________________
Apotheus Silverman
Shop SL on the web - SLExchange.com

Visit Abbotts Aerodrome for gobs of flying fun.
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
05-05-2004 00:22
Apoth, I think I may have found a logic error in your script.

If I interpreted the list of things in your notecard correctly:

From: someone

// Reads the data from the notecard. Each line in the notecard should be
// formatted as follows:
// Item Name, Model Name, Price, Authors

Item Name is stored in the list items,
Model Name is stored in the list models,
Price is stored in the list prices,
and Authors is stored in the list authors.

Item Name is the name of the item that the seller defines in the notecard. Model Name is the name of the model corresponding to Item Name. Model Name is the actual name of the model in the vendors inventory.

Now, if Im right that far, I think you have a problem here:

From: someone
CODE

if (sale) {
// Make sure I have the item in inventory before trying to give it.
integer found = FALSE;
llSay(0, "searching for " + llList2String(items, currentItem));
for (i = 0; i < llGetInventoryNumber(inventoryType); i++) {
if (llGetInventoryName(inventoryType, i) == llList2String(items, currentItem)) {
found = TRUE;
}
}


There, you search the vendor's inventory for the object that has the name name as currentItem's Item Name. Now, If I was right back there, this code should be searching instead for currentItem's Model Name, not currentItem's Item Name. With the code the way it is, if Model Name != Item Name, then you ill have some problems with finding the model that corresponds to the item name.

From: someone
Originally posted by Remo Yossarian
// string (no commas), string (no commas), integer, pipe-delimited list of keys
// Example:
// Abbotts Float Plane v1.0.1, Abbotts Float Plane Model, 500, key|key

What are they?
How do you figure out what keys to use?
What do they do?

The ones in your example at the end are all the same?


I hope you dont mind me answering this one Apotheus :)

I believe the keys Apotheus' script uses are the keys of the agents of the creators of the items.

An agent is how SL servers identify users who are logged in to the grid. Each agent has a key. You can get your agent's key (a.k.a, your key) by creating an object, creating a new script, and inserting this line within state_entry():

llSay(0, (string) llGetOwner());

That will say your agent's key.
Keys of other people can be found by using a sensor, or a touch event.

Here's an example touch-for-key script:
CODE

default {
touch_start(integer n) {
llSay(0, llDetectedName(0) + "'s key is " + (string) llDetectedKey(0));
}
}


If you put this script in an object, when someone touches the object, the object will say their key outloud.

Apotheus' script uses the author's keys to pay each author their share of the price when a user buys an item.

Hope this answers your questions!
==Chris
Apotheus Silverman
I write code.
Join date: 17 Nov 2003
Posts: 416
05-05-2004 17:03
From: someone

There, you search the vendor's inventory for the object that has the name name as currentItem's Item Name. Now, If I was right back there, this code should be searching instead for currentItem's Model Name, not currentItem's Item Name. With the code the way it is, if Model Name != Item Name, then you ill have some problems with finding the model that corresponds to the item name.


I think you're misinterpreting the item data a little bit.

The items list contains the name of the actual items to sell.
The models list contains the name of the display model. The display model plays no factor in the sale. :-)

On another note, I have updated the main vendor script with a small bugfix regarding autorotating items and a small architecture improvement... autorotation timer length it now included at the top of the file.
_____________________
Apotheus Silverman
Shop SL on the web - SLExchange.com

Visit Abbotts Aerodrome for gobs of flying fun.
MadameThespian Underhill
"I'm Aaacting!"
Join date: 18 Dec 2002
Posts: 38
objects won't "derez"
05-23-2004 21:13
In trying out your cool script, Apotheus, I'm having a problem with my objects not derezing. I put 3 objects in the vendor to test it (table, chair, umbrella) and they just rez over the top of each other. I'm not a scripter so it's probably that I'm missing something here. :)

Any help would be appreciated.

Thanks in advance! :D
_____________________
Support the arts...go to the theatre!
Apotheus Silverman
I write code.
Join date: 17 Nov 2003
Posts: 416
05-25-2004 10:50
MadameThespian,

Make sure your display models all contain the Display Model script (the example script in my original post will work). Also make sure the commChannel value is the same in all the Display Model and Vendor scripts.

That's all there is to it!
_____________________
Apotheus Silverman
Shop SL on the web - SLExchange.com

Visit Abbotts Aerodrome for gobs of flying fun.
MadameThespian Underhill
"I'm Aaacting!"
Join date: 18 Dec 2002
Posts: 38
05-26-2004 16:25
Works like a charm, Apotheus!
Thank you,
thank you,
thank you!
:D :D :D
_____________________
Support the arts...go to the theatre!
Apotheus Silverman
I write code.
Join date: 17 Nov 2003
Posts: 416
05-31-2004 11:53
I have just updated both the main vendor and display model scripts with an improvement that makes the commChannel value no longer an issue to worry about. You no longer have to manually change it, and vendors will not interfere with each other in close quarters.

I also removed a stray debugging message that I had inadvertently left in there.

Enjoy!
_____________________
Apotheus Silverman
Shop SL on the web - SLExchange.com

Visit Abbotts Aerodrome for gobs of flying fun.
Chris Byrne
Broccoli Chef
Join date: 21 Mar 2004
Posts: 57
06-01-2004 17:53
This works wonderfully - many thanks, Apotheus!
Alex Farber
Registered User
Join date: 5 Feb 2004
Posts: 82
I am such a newbie
09-02-2004 18:00
I am so sorry for being so new. I put your code in my vendor and it isn't doing anything. Do I need to add my data to the Main Script or something?
Alex Farber
Registered User
Join date: 5 Feb 2004
Posts: 82
One more question
09-06-2004 18:02
I almost have what I am looking for. What do I modify to keep the display from rotating?
Apotheus Silverman
I write code.
Join date: 17 Nov 2003
Posts: 416
09-08-2004 06:29
From: someone
I almost have what I am looking for. What do I modify to keep the display from rotating?

In the display model script, just comment this line:
llTargetOmega(<0,0,1>,0.2,1.0);
_____________________
Apotheus Silverman
Shop SL on the web - SLExchange.com

Visit Abbotts Aerodrome for gobs of flying fun.
Alex Farber
Registered User
Join date: 5 Feb 2004
Posts: 82
Just wanted to say thanks
09-17-2004 11:04
Apotheus,

Just wanted to say thank you for all the help. I finally finished the vendor last night. I had to take a break there for a while. I really do appreciate all the help and won't forget it.

Thanks,
Alex
Ulrika Zugzwang
Magnanimous in Victory
Join date: 10 Jun 2004
Posts: 6,382
10-15-2004 08:59
Apotheus,

I want to give you a genuine thanks. A vendor with the ability to split purchases among multiple users is exactly what we needed for the Neualtenburg Projekt. It's wonderful to see someone release such high-quality code in the forums.

Also, I had a little trouble getting things working at first, so I thought I'd give some instructions for those of my skill level to get the code working as quickly as possible:
  1. Create a vendor prim and put the vendor script in.
  2. Create a previous-button prim and put the previous-button (back-button) script in.
  3. Create a next-button prim and put the next-button script in.
  4. Link all three prims together making the vendor prim the parent prim.
  5. Make a model by rezing an object you want to sell, copy it, shrink it, and remove all contents.
  6. Place the display script inside this model.
  7. Rename the model.
  8. Place the model and the original object for sale into the vendor.
  9. Edit the "Item Data" notecard to include the following data: object name, model name, price, agent keys


That's it! Note that no modification of code is necessary at all anywhere to get things to work. My mistake is that I created a fourth prim that I placed the display script in, thinking the object would rez and derez around that fourth object. For some strange reason it kept vanishing while the models stayed. ;)

~Ulrika~
_____________________
Chik-chik-chika-ahh
Alex Lumiere
Registered User
Join date: 1 Jun 2004
Posts: 228
10-16-2004 10:12
thanks for sharing this code :)
Shadow Weaver
Ancient
Join date: 13 Jan 2003
Posts: 2,808
10-19-2004 12:42
Just for understanding purposes...this is basicaly a rezvendor that displays a model yes?

and if so then all the information calls are transcribed from a Note Card?
_____________________
Everyone here is an adult. This ain't DisneyLand, and Mickey Mouse isn't going to swat you with a stick if you say "holy crapola."<Pathfinder Linden>

New Worlds new Adventures
Formerly known as Jade Wolf my business name has now changed to Dragon Shadow.

Im me in world for Locations of my apparrel

Online Authorized Trademark Licensed Apparel
http://www.cafepress.com/slvisions
OR Visit The Website @
www.slvisions.com
James Beckett
Registered User
Join date: 26 Jun 2004
Posts: 34
10-20-2004 05:02
ok, I'm pretty sure I set it up right n all, but the script doesn't do anything for me :confused:
James Beckett
Registered User
Join date: 26 Jun 2004
Posts: 34
10-20-2004 05:04
ok, I'm sure I set it up right, but the script doesn't do anything for me :confused:
Apotheus Silverman
I write code.
Join date: 17 Nov 2003
Posts: 416
10-20-2004 05:33
From: Shadow Weaver
Just for understanding purposes...this is basicaly a rezvendor that displays a model yes?

and if so then all the information calls are transcribed from a Note Card?

Yes Shadow, the code I have here is for a vendor that rezzes display models. When someone purchases something the payment can be automatically divided between mulitiple people if desired.

All the information about the items being sold and who gets paid reside in a note card.

People have also modified the script in numerous ways. I have seen image-based vendor machines and also machines that rez models AND display images of products at the same time. It would be nice if those people would post their modifications here as well.
_____________________
Apotheus Silverman
Shop SL on the web - SLExchange.com

Visit Abbotts Aerodrome for gobs of flying fun.
Alex Farber
Registered User
Join date: 5 Feb 2004
Posts: 82
10-20-2004 08:42
I modified Apotheus' vendor from rezing display models to just rezing a flat prim shows the ads for my clothes. I didn't do much to the code. Just mostly rearranged the whole thing. It's probably more than what I needed, but it was fun and a learning experience.

If anyone would like a copy, I am a little proud of it and don't mind sharing it with the community so IM me and I will pass it on to ya.

Thanks for all the help on the vendor again Apotheus. Your Awesome!!! ;)
Sensual Casanova
Spoiled Brat
Join date: 28 Feb 2004
Posts: 4,807
10-20-2004 18:26
From: Apotheus Silverman
Yes Shadow, the code I have here is for a vendor that rezzes display models. When someone purchases something the payment can be automatically divided between mulitiple people if desired.

All the information about the items being sold and who gets paid reside in a note card.

People have also modified the script in numerous ways. I have seen image-based vendor machines and also machines that rez models AND display images of products at the same time. It would be nice if those people would post their modifications here as well.


At my shop in Le Cadre I have vendors that show the picture and you have the option to rez it (by touching display)... Amandir Beckenabuer made them, but I am not sure if he is up to sharing the code :)
Zachary Zamboni
Registered User
Join date: 17 Jun 2004
Posts: 7
New Version-With info button handling
10-30-2004 08:14
Apotheus-
I edited your script and added compatibility with notecard info buttons.

Here's the new main script:
CODE
// This is the channel the main vendor talks to rezzed models on 
integer commChannel;

// These lists are synchronized to simulate a structure for each item's data
list items = [];
list models = [];
list prices = [];
list authors = [];
list notecards = [];

// Required to read the notecard properly
integer notecardLine;
key currentDataRequest;


// Reads the data from the notecard. Each line in the notecard should be
// formatted as follows:
// Item Name, Model Name, Price, Authors, Notecardname
// string (no commas), string (no commas), integer, pipe-delimited list of keys, string (no commas)
// Example:
// Abbotts Float Plane v1.0.1, Abbotts Float Plane Model, 500, key|key, Abbots Float Plane Info
InitializationStep1() {
llSay(0, "Reading item data...");
notecardLine = 0;
currentDataRequest = llGetNotecardLine(itemDataNotecard, notecardLine);
}

// Requests debit permission
InitializationStep2() {
// Request debit permission
llRequestPermissions(llGetOwner(), PERMISSION_DEBIT);
}

//give a notecard to the person who requested it
giveCurrentNotecard(key id, integer num)
{
llGiveInventory(id, llList2String(notecards, num);
}
// Change currently-displayed item
SetCurrentItem(integer item) {
// determine which item to display
integer itemCount = llGetListLength(items) - 1;
currentItem = item;
if (currentItem == -1) {
currentItem = itemCount;
} else if (currentItem > itemCount) {
currentItem = 0;
}

// derez current model
llWhisper(commChannel, commandDerez);

// Build and set hover text
string hoverText = "Item " + (string)(currentItem + 1) + " of " + (string)(itemCount + 1) + "\n" + llList2String(items, currentItem) + "\n$" + (string)llList2String(prices, currentItem);
llSetText(hoverText, textColor, 1.0);

// Say what item is now being displayed
llSay(0, "Now Showing: " + llList2String(items, currentItem));

// rez the new model
llRezObject(llList2String(models, currentItem), llGetPos() + rezPosition, ZERO_VECTOR, ZERO_ROTATION, commChannel);
}

default {
state_entry() {
llSay(0, "Starting up...");

// Initialize commChannel
commChannel = (integer)llFrand(2000000000.0);

// Clear text
llSetText("", textColor, 1.0);

// Read notecard, populate lists
InitializationStep1();
}

run_time_permissions(integer perm) {
if (perm & PERMISSION_DEBIT) {
state vend;
} else {
llSay(0, "You must grant debit permission for me to work properly.");
}
}

dataserver(key query, string data) {
if (query == currentDataRequest) {
currentDataRequest = ""; // Prevent a bug that occurs with dataserver events.
if (data != EOF) {
// Read the current item
list currentList = llCSV2List(data);
string myItemName = llList2String(currentList, 0);
string myModelName = llList2String(currentList, 1);
integer myPrice = llList2Integer(currentList, 2);
string myAuthorsAsString = llList2String(currentList, 3);
string myNotecardName = llList2String(currentList, 4);

items += [myItemName];
models += [myModelName];
prices += [myPrice];
authors += [myAuthorsAsString];
notecards += [myNotecardName];

notecardLine++;
// Get the next line
currentDataRequest = llGetNotecardLine(itemDataNotecard, notecardLine);
} else {
// Signal that we are done getting items
InitializationStep2();
}
}
}
}




state vend {
state_entry() {
//llSay(0, "items = " + llDumpList2String(items, ","));
//llSay(0, "models = " + llDumpList2String(models, ","));
//llSay(0, "prices = " + llDumpList2String(prices, ","));
//llSay(0, "authors = " + llDumpList2String(authors, ","));

// Rez initial model
SetCurrentItem(currentItem);

// Start the timer for item autorotation
llSetTimerEvent(changeTimer);

llSay(0, "Multiauthor Multivendor online.");
}

timer() {
// Choose a random item to display. Make sure it's not the current item.
integer newItem = currentItem;
if (llGetListLength(items) > 1) {
while (newItem == currentItem) {
newItem = (integer)(llFrand(llGetListLength(items)) + 1.0);
}
SetCurrentItem(newItem);
}
}

touch(integer total) {
llSay(0, "I sell things! Use the left or right arrows to cycle through the items I am selling, then right-click and \"Pay\" me the displayed amount to purchase an item.");
}

// Someone has given me money
money(key agentkey, integer amount) {
string name = llKey2Name(agentkey);
integer currentPrice = llList2Integer(prices, currentItem);
integer sale;
integer i;

if(amount < currentPrice) {
// Not enough money was given. Cancel sale.
llSay(0, name + " you Paid $" + (string)amount + " - thats not enough money for the current item! Refunding $" + (string)amount + "...");
llGiveMoney(agentkey, amount);
sale = FALSE;
}
else if(amount > currentPrice) {
// Too much money was given. Refund the differnce.
integer change = amount - currentPrice;
llSay(0, name + " you Paid $" + (string)amount + " - your change is $" + (string)change + ".");
llGiveMoney(agentkey, change);
sale = TRUE;
} else {
// The proper amount was given.
sale = TRUE;
}

if (sale) {
// Make sure I have the item in inventory before trying to give it.
integer found = FALSE;
//llSay(0, "searching for " + llList2String(items, currentItem));
for (i = 0; i < llGetInventoryNumber(inventoryType); i++) {
if (llGetInventoryName(inventoryType, i) == llList2String(items, currentItem)) {
found = TRUE;
}
}

if (!found) {
// Display error and refund money
llSay(0, "Erm, I am sorry " + name + ", but it seems that I do not have that item to give to you, so I am refunding the purchase price. Please contact my owner about this issue.");
llGiveMoney(agentkey, currentPrice);
} else {
// Complete the sale
llSay(0, "Thank you for your purchase, " + name + "!");
llGiveInventory(agentkey, llList2String(items, currentItem));

llWhisper(0, "Please wait while I perform accounting activities...");

// Distribute money to the object authors
list myAuthors = llParseString2List(llList2String(authors, currentItem), ["|"], []);

if (llGetListLength(myAuthors) > 0) {
integer shareAmount = (integer)llList2Integer(prices, currentItem) / llGetListLength(myAuthors);
// Eliminate my owner from the authors list
for (i = 0; i < llGetListLength(myAuthors); i++) {
llInstantMessage(llList2Key(myAuthors, i), name + " purchased " + llList2String(items, currentItem) + ". Your share is L$" + (string)shareAmount + ".");
if (llList2Key(myAuthors, i) == llGetOwner()) {
myAuthors = llDeleteSubList(myAuthors, i, i);
}
}
// Pay any remaining authors accordingly
if (shareAmount > 0 && llGetListLength(myAuthors) > 0) {
for (i = 0; i < llGetListLength(myAuthors); i++) {
llGiveMoney(llList2Key(myAuthors, i), shareAmount);
}
}
}
llWhisper(0, "Accounting completed. Thanks again, " + name + "!");
}
}
}

link_message(integer sender, integer num, string message, key id) {
if (message == "next") {
llSetTimerEvent(changeTimer);
SetCurrentItem(currentItem + 1);
} else if (message == "prev") {
llSetTimerEvent(changeTimer);
SetCurrentItem(currentItem - 1);
} else if (llSubStringIndex(message, "givenote") == 0) {
key giveToKey = llGetSubString(message, 8, 1000);
giveCurrentNotecard(giveToKey, currentitem);
}

}

on_rez(integer startParam) {
llResetScript();
}
}


And here's the info button script:
CODE
default
{
touch_start(integer totalnum)
{
llMessageLinked(LINK_ROOT, 0, "givenote"+llDetectedKey(), "");
}
}
Morgaine Dinova
Active Carbon Unit
Join date: 25 Aug 2004
Posts: 968
11-03-2004 12:36
How about having a forum rule that all submitted scripts should at least compile?

I see a missing parenthesis on line 40 of Zachary's modified sources.
_____________________
-- General Mousebutton API, proposal for interactive gaming
-- Mouselook camera continuity, basic UI camera improvements
Dale Zephyr
Registered User
Join date: 23 Sep 2004
Posts: 36
Remove Timer
11-24-2004 16:10
I just finished building a vendor with the scripts and was wondering if there is a way to disable/remove the timer from the script without harm. And, if so, how I would go about doing it. I know a lot of mall owners ask that the vendors we place not have certain things and timers is one of them.

If anyone can offer assistance I'd greatlly appreciate it.

Thanks.
1 2 3 4