I started to work on this in 2007. You could only pick 4 items from the pay menu, each had its own price.
So lets rewrite the script! We are going to create a new LSL Script and add a on_rez event to reset the when you rez the bot out of inventory. You should a script that looks like the following:
[code lang="lsl2"] default { state_entry() { llSay(0, "Hello, Avatar!"); } touch_start(integer total_number) { llSay(0, "Touched."); } on_rez(integer start_param) { llResetScript(); } } [/code]
The way llDialog works is buy showing a dialog on a users screen and when they select a option it says it back on a certain channel. So we are going to want to add in a llListen and a Listen event. We also will need to add a integer at the top of the script for the channel, so we can remember the one we are listening on. We are going to need generate a random channel also, so if you have multpal reboots in the same area, they would not conflict.
[code lang="lsl2"] integer chan; default { state_entry() { chan = (integer)(llFrand(-1000000000.0) - 1000000000.0); llListen(chan,"", NULL_KEY,""); } listen(integer channel, string name, key id, string message) { } touch_start(integer total_number) { llSay(0, "Touched."); } on_rez(integer start_param) { llResetScript(); } } [/code]
We also will need to deal with the Linden Dollar, to allow people to pay the bot to order. So lets put in the money events we will need also.
The prices for each type of item is:
- L$1 for drinks like soda, juice
- L$2 for alcoholic drinks
- L$3 for snacks
- L$4 for meals
[code lang="lsl2"]integer chan; integer debit = FALSE; default { state_entry() { chan = (integer)(llFrand(-1000000000.0) - 1000000000.0); llListen(chan,"", NULL_KEY,""); llSetPayPrice(PAY_HIDE,[0,0,0,0]); llRequestPermissions(llGetOwner(),PERMISSION_DEBIT); } listen(integer channel, string name, key id, string message) { } money(key id, integer amount) { } run_time_permissions(integer p) { if(p & PERMISSION_DEBIT) { debit = TRUE; llSetPayPrice(PAY_HIDE, [1,2,3,4]); llOwnerSay("I'm now ready to accept orders!"); } else { llOwnerSay("You must accept permissions in order for this to work... Touch me for premission dialog again."); } } touch_start(integer total_number) { llSay(0, "Touched."); } on_rez(integer start_param) { llResetScript(); } }[/code]
Clicking AKA Touching the robot will give you a pricing menu. Paying it will bring up the ordering menu.
Lets get the touch event done first. In the touch event we are going to check if the item has debit permission or not. If it doesn’t, tell the user the bot isn’t ready for orders, if it’s the owner try to get debit permission again. If it does have debit permission, bring up the pricing list.
Your touch event should look like the following:
[code lang="lsl2"]touch_start(integer total_number) { key avatar = llDetectedKey(0); if (debit) { llDialog(avatar, "Hello " + llGetDisplayName(avatar) + ", I am Billy a robot the serves you food and drinks. My Menu is: \n\nL$1: Drinks \nL$2: Alcoholic Drinks \nL$3: Snacks \nL$4 Meals \n\nYou can pay me the price of the menu item you want, then pick a item. If you don't see anything you like, don't worry as i can refund you.",["Okay"], chan); } else { if (llDetectedKey(0) == llGetOwner()) { llRequestPermissions(avatar,PERMISSION_DEBIT); } else { llDialog(avatar, "Hello " + llGetDisplayName(avatar) + ", I am Billy a robot the serves you food and drinks. I'm sorry to inform you that i can not take orders right now as my owner has not enabled me. I hope you can try me later as i look forward to serving you.",["Okay"], chan); } } }[/code]
When the user clicks the robot they will see a dialog
Now we are going to create 4 list for each menu type category , to track if someone is allowed to buy that item, and to process refunds.
[code lang="lsl2"]list drinkbuyers; list alcoholicbuyers; list snacksbuyers; list mealsbuyers;[/code]
So now we are going to write the code for the money event. We are going to check if they paid 1,2,3 or 4 else give a refund. That debit variable comes in use here also. Even tho they can’t enter in any number and the client will only show 1,2,3,4 some users can use hacked or maybe a custom client would allow any amount. That’s why you should always check the amount in your script.
With that debit permission variable we can issue a refund, else if they didn’t give permission we can give them a message.
[code lang="lsl2"]money(key id, integer amount) { if (amount == 1) // drink { } else if (amount == 2) //alcoholic drink { } else if (amount == 3) // snack { } else if (amount == 4) //meal { } else { if (debit) { llGiveMoney(id, amount); } else { llDialog(id, "Hello " + llGetDisplayName(id) + ", You paid me to wrong amount and i do not have premission to refund you. Please contact the owner of me for a refund.",["Okay"], chan); } } }[/code]
The money event so far knows the price of each menu type the user wants to order, and if they paid the wrong amount if refunds them if it has debit permission or it messages the user to contact the owner of the object to ask for a refund.
Now for each amount, we need to check if they are in the paid list or not, then add them or refund them as they paid twice. If they paid twice, we will need to issue a refund, similar to the way when paying the wrong amount. Since we have 4 items that need this code, we should not repeat this code, we are going to make a custom function called refundalready it will take the id and menu type.
To create a function in LSL you go to the top of the script and write the function name and ( variable inputs ).
[code lang="lsl2"]refundalready(key user, string menu) { }[/code]
Inside of this function you write if and else statements and do everything you can do just about everything you can do in an event. Your refundalready function takes the menu type and do if statements to get the price and title. Then it checks for debit permission and issues a refund or tells the user it does not have permission and to ask the owner. Your function should look like the following:
[code lang="lsl2"]refundalready(key user, string menu) { integer refund; string itemtitle; if (menu == "drink") { refund = 1; itemtitle = "drink"; } else if (menu == "alcoholic") { refund = 2; itemtitle = "alcoholic drink"; } else if (menu == "snack") { refund = 3; itemtitle = "snack"; } else if (menu == "meal") { refund = 4; itemtitle = "meal"; } else { refund = 0; } if (refund > 0) { if (debit) { llGiveMoney(user, refund); llDialog(user, "Hello " + llGetDisplayName(user) + ", You paid me twice for a " + itemtitle + "... I sent you a refund.",["Okay"], chan); } else { llDialog(user, "Hello " + llGetDisplayName(user) + ", You paid me twice for a " + itemtitle + " and i do not have premission to refund you. Please contact the owner of me for a refund.",["Okay"], chan); } } }[/code]
Now we are going to write another custom function to bring up the options menu. A dialog can have 12 buttons, we are going to have to have a “Cancel” button, which will exit and refund. So you have 11 spots for your drinks, food, etc options. We are going to create a ordermenu function as a place holder for now.
[code lang="lsl2"]ordermenu(key user, list menu) { }[/code]
Now we are going to focus on the different amounts in the money event. For each amount we have to write a if statement. We check if they are in the list for that menu type, if they aren’t we add them and show them the menu, else we call the refundalready function.
[code lang="lsl2"]if(llListFindList(drinkbuyers,[id]) == -1) { drinkbuyers+= [id]; ordermenu(id,drinks); } else { refundalready(id,"drink"); }[/code]
So far the script should look like the following:
[code lang="lsl2"]integer chan; integer debit = FALSE; list drinkbuyers; list alcoholicbuyers; list snacksbuyers; list mealsbuyers; refundalready(key user, string menu) { integer refund; string itemtitle; if (menu == "drink") { refund = 1; itemtitle = "drink"; } else if (menu == "alcoholic") { refund = 2; itemtitle = "alcoholic drink"; } else if (menu == "snack") { refund = 3; itemtitle = "snack"; } else if (menu == "meal") { refund = 4; itemtitle = "meal"; } else { refund = 0; } if (refund > 0) { if (debit) { llGiveMoney(user, refund); llDialog(user, "Hello " + llGetDisplayName(user) + ", You paid me twice for a " + itemtitle + "... I sent you a refund.",["Okay"], chan); } else { llDialog(user, "Hello " + llGetDisplayName(user) + ", You paid me twice for a " + itemtitle + " and i do not have premission to refund you. Please contact the owner of me for a refund.",["Okay"], chan); } } } ordermenu(key user, list menu) { } default { state_entry() { chan = (integer)(llFrand(-1000000000.0) - 1000000000.0); llListen(chan,"", NULL_KEY,""); llSetPayPrice(PAY_HIDE,[0,0,0,0]); llRequestPermissions(llGetOwner(),PERMISSION_DEBIT); } listen(integer channel, string name, key id, string message) { } money(key id, integer amount) { if (amount == 1) // drink { if(llListFindList(drinkbuyers,[id]) == -1) { drinkbuyers+= [id]; ordermenu(id,drinks); } else { refundalready(id,"drink"); } } else if (amount == 2) //alcoholic drink { if(llListFindList(alcoholicbuyers,[id]) == -1) { alcoholicbuyers+= [id]; ordermenu(id,alcoholic); } else { refundalready(id,"alcoholic"); } } else if (amount == 3) // snack { if(llListFindList(snacksbuyers,[id]) == -1) { snacksbuyers+= [id]; ordermenu(id,snack); } else { refundalready(id,"snack"); } } else if (amount == 4) //meal { if(llListFindList(mealsbuyers,[id]) == -1) { mealsbuyers+= [id]; ordermenu(id,meal); } else { refundalready(id,"meal"); } } else { if (debit) { llGiveMoney(id, amount); } else { llDialog(id, "Hello " + llGetDisplayName(id) + ", You paid me to wrong amount and i do not have premission to refund you. Please contact the owner of me for a refund.",["Okay"], chan); } } } run_time_permissions(integer p) { if(p & PERMISSION_DEBIT) { debit = TRUE; llSetPayPrice(PAY_HIDE, [1,2,3,4]); llOwnerSay("I'm now ready to accept orders!"); } else { llOwnerSay("You must accept permissions in order for this to work... Touch me for premission dialog again."); } } touch_start(integer total_number) { key avatar = llDetectedKey(0); if (debit) { llDialog(avatar, "Hello " + llGetDisplayName(avatar) + ", I am Billy a robot the serves you food and drinks. My Menu is: \n\nL$1: Drinks \nL$2: Alcoholic Drinks \nL$3: Snacks \nL$4 Meals \n\nYou can pay me the price of the menu item you want, then pick a item. If you don't see anything you like, don't worry as i can refund you.",["Okay"], chan); } else { if (llDetectedKey(0) == llGetOwner()) { llRequestPermissions(avatar,PERMISSION_DEBIT); } else { llDialog(avatar, "Hello " + llGetDisplayName(avatar) + ", I am Billy a robot the serves you food and drinks. I'm sorry to inform you that i can not take orders right now as my owner has not enabled me. I hope you can try me later as i look forward to serving you.",["Okay"], chan); } } } on_rez(integer start_param) { llResetScript(); } }[/code]
Now we are going to create lists of the items for each menu type.
[code lang="lsl2"]list drinks = ["soda","Apple Juice", "Grape Juice", "Water","Smoothie"]; list alcoholic = ["Beer","Wine"]; list snack = ["Chips","Popcorn","Candy bar","Pumkin Pie","Cake"]; list meal = ["Cheeseburger", "Hotdog","Chicken Nuggets"];[/code]
Now we have to write the ordermenu function, it takes the users key and a list of the menu items. It then adds a cancel button to that list and then puts the buttons in human order. Then shows the menu to the user.
[code lang="lsl2"]ordermenu(key user, list menu) { list buttons = menu + "Cancel"; llDialog(user, "Hello " + llGetDisplayName(user) + ", Please pick a item from the menu",order_buttons(buttons), chan); }[/code]
To get them in human order you need to add the order_buttons function
[code lang="lsl2"]list order_buttons(list buttons) { return llList2List(buttons, -3, -1) + llList2List(buttons, -6, -4) + llList2List(buttons, -9, -7) + llList2List(buttons, -12, -10); }[/code]
Now we are going to the touch event again, say they clicked ignored, to bring up the menu again. If they have only 1 item list, show them that else let them pick. To do this we are going to do an if check to see if they are in any of the buyer lists, else show them the menu. If they are in a buyer list we check each one and build a button list. If the count of that list is over 1, add a cancel button and show dialog, else open up the single item menu. Your new touch event should look like the following:
[code lang="lsl2"]touch_start(integer total_number) { key avatar = llDetectedKey(0); if (debit) { if(llListFindList(drinkbuyers,[avatar]) != -1 || llListFindList(alcoholicbuyers,[avatar]) != -1 || llListFindList(snacksbuyers,[avatar]) != -1 || llListFindList(mealsbuyers,[avatar]) != -1) { list buttons; if (llListFindList(drinkbuyers,[avatar]) != -1) { buttons += "Drinks"; } if (llListFindList(alcoholicbuyers,[avatar]) != -1) { buttons += "Alcoholic Drinks"; } if (llListFindList(snacksbuyers,[avatar]) != -1) { buttons += "Snacks"; } if (llListFindList(mealsbuyers,[avatar]) != -1) { buttons += "Meals"; } llOwnerSay((string)llGetListLength(buttons)); if (llGetListLength(buttons) > 1) { buttons += "Cancel"; llDialog(avatar, "Hello " + llGetDisplayName(avatar) + ", You already paid me, which menu would you like to reopen?",order_buttons(buttons), chan); } else { string singleitem = llList2String(buttons,0); if (singleitem == "Drinks") { ordermenu(avatar,drinks); } else if (singleitem == "Alcoholic Drinks") { ordermenu(avatar,alcoholic); } else if (singleitem == "Snacks") { ordermenu(avatar,snack); } else if (singleitem == "Meals") { ordermenu(avatar,meal); } } } else { llDialog(avatar, "Hello " + llGetDisplayName(avatar) + ", I am Billy a robot the serves you food and drinks. My Menu is: \n\nL$1: Drinks \nL$2: Alcoholic Drinks \nL$3: Snacks \nL$4 Meals \n\nYou can pay me the price of the menu item you want, then pick a item. If you don't see anything you like, don't worry as i can refund you.",["Okay"], chan); } } else { if (llDetectedKey(0) == llGetOwner()) { llRequestPermissions(avatar,PERMISSION_DEBIT); } else { llDialog(avatar, "Hello " + llGetDisplayName(avatar) + ", I am Billy a robot the serves you food and drinks. I'm sorry to inform you that i can not take orders right now as my owner has not enabled me. I hope you can try me later as i look forward to serving you.",["Okay"], chan); } } }[/code]
In part 2 we will finish this up in the listen event.