Graal Forums  

Go Back   Graal Forums > Development Forums > NPC Scripting > Code Gallery
FAQ Members List Calendar Today's Posts

 
 
Thread Tools Search this Thread Display Modes
Prev Previous Post   Next Post Next
  #1  
Old 08-21-2006, 11:11 PM
Skyld Skyld is offline
Script-fu
Skyld's Avatar
Join Date: Jan 2002
Location: United Kingdom
Posts: 3,914
Skyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud ofSkyld has much to be proud of
Send a message via AIM to Skyld
Script: Shop system

Once again in the interest of education, here's my shop system. It's broken into several parts, so make sure to read the instructions carefully!

Now, of course you can modify the script to make it match your own setup, however, here's how it works in my configuration. It also works using gralats by default; you'll have to change it in order to use custom money.

You'll need to update the shop weapon so that it adds the item to the player matching your own system. Also, you'll want to make sure that the seteffect fade doesn't interfere with your daynight, and finally, note that the weapon has a "Debit" option. This was for my setup on Rudora so that you could pay straight from your bank account. Either match it to your own bank system or just rip it out.

The system will depend upon three database NPCs, two classes and one weapon. Start by making the Database NPCs;
  • DB_Items; this is where we will store information about the items which you will sell
  • DB_Shops; this is where we will store the names of the shops, funds received from shop sales, etc
  • DB_Prices; this is where we will store the prices of items

You'll need to populate the NPCs with some data. Let's start with DB_Items; put the following script in DB_Items:
PHP Code:
function onCreated()
{
  
/*
    Format:
    this.item_id = {Name, Internalname, Image, ActionWeapon, Canbedropped};
   */
 
  
this.item_100 = {"Block", "block", "block.png", "-No Item", 1};
} 
Next, in DB_Prices, put the following:
PHP Code:
function onCreated()
{
  
// Format:
  // this.item_id = price
  
  
this.item_100 = 3; // 3 gralats in this case
} 
Next, you'll need to set up the levels with the classes. It shouldn't really matter what you name the classes, but for this example, we'll use 'shopcontrol' and 'shopitem'.

Each shop level requires one shopcontrol class. This puts the level's base name into a level variable, and displays the shop's funds and name. Put this somewhere nice-looking. Just do something like this:
PHP Code:
this.join("shopcontrol"); 
Now, for each item that you want to sell in the shop, place a shopitem. You must specify additional data for shopitem classes, such as the item you want to sell. Here's an example:
PHP Code:
this.item = 100; // this is item ID 100 from DB_Items
this.customimage = false; // use the image set in DB_Items
this.join("shopitem"); 
Finally, add the shop interface weapon into a weapon called "-Shop", and make sure that it is added to any players using the shop. Hell, you could just add it to all players on logon.

That's about it, really. Once you upload the shop, it should work. You should also be able to specify a name for the shop inside DB_Shops' flag list once it's uploaded.

Enjoy.

Shop item class:
PHP Code:
function onCreated()
{
  
onTimeout();
}

function 
onTimeout()
{
  
this.okay = 0;
  
  if (
this.item == NULL)
  {
    
temp.data = "-unavailable-";
  }
  
  if (
DB_Items.("item_" @ this.item) == NULL)
  {
    
temp.data = "-unavailable-";
  }
  
  if (
DB_Prices.("item_" @ this.item) == NULL)
  {
    
temp.data = "-unavailable-";
  }
  
  
this.itemdata = DB_Items.("item_" @ this.item);
  
this.price = DB_Prices.("item_" @ this.item);

  
this.setShape(1, 32, 32);

  if (
temp.data == "-unavailable-")
  {
    
this.setimg(""); // <- image for unavailable item here
  
}
    else
  {
    if (
this.customimage != TRUE ||
        
this.customimage == 0)
    {
      
this.setimg(this.itemdata[2]);
    }
  }

  if (
temp.data == NULL)
  {
    
temp.data = this.itemdata[0];
    
this.okay = 1;
  }
  
  
showimg(1, "@Tahoma@bc@" @ temp.data, this.x + 1, this.y - 0.5);
  
changeimgzoom(1, 0.5);
  
  
setTimer(2);
}

function 
onActionleftmouse()
{
  if (
this.okay == 1)
  {
    
player.triggerclient("-Shop", "purchaseItem", this.item, this.itemdata, this.price);
  }
} 
Shop control class:
PHP Code:
function onCreated()
{
  
level.creditor = extractfilebase(this.level.name);
  
  
onTimeout();
}

function 
onTimeout()
{
  
level.shopname = (!(DB_Shops.(level.creditor @ "_name")) ? 
                    
"Unnamed Shop" : DB_Shops.(level.creditor @ "_name"));
  
  
showimg(1, format("@Tahoma@bc@%s", level.shopname), x - 1.5, y - 1);
  
changeimgvis(1, 2);
  
changeimgzoom(1, 0.8);
  
  
showimg(2, format("@Tahoma@bc@Shop Funds: %ig", DB_Shops.(level.creditor @ "_funds")), x - 1.5, y);
  
changeimgvis(2, 2);
  
changeimgzoom(2, 0.5);

  
setTimer(2);
} 
-Shop weapon:
PHP Code:
function onActionserverside()
{
  if (
params[0] == "purchaseItem")
  {
    if (
params[1] == NULL)
    {
      
player.say2("An error occured. 1" @ params[1]);
      return;
    }
    
    if (
DB_Prices.("item_" @ params[1]) == NULL)
    {
      
player.say2("An error occured. 2");
      return;
    }
    
    
temp.price = DB_Prices.("item_" @ params[1]);
    
temp.item = params[1];
    
temp.creditor = (!level.creditor ? "unknown" : level.creditor);
    
    if (
params[2] == false)
    {
      if (
player.rupees >= temp.price)
      {
        
player.rupees -= temp.price; 
        
// ADD THE ITEM TO THE PLAYER HERE
        
DB_Shops.(temp.creditor @ "_funds") += temp.price;
      
        
player.say2("Thank you.");
      }
        else
      {
        
player.say2("You do not have enough money!");
      }
    }
      else
    {
      if (
player.bankBalance() >= temp.price)
      {     
        
temp.res = player.bankDebit(temp.price, temp.creditor);   
        if (
temp.res == 0)
        { 
          
// ADD THE ITEM TO THE PLAYER HERE
          
DB_Shops.(temp.creditor @ "_funds") += temp.price;
      
          
player.say2(format("Thank you.\nDebited: %dg.\nNew bank balance: %dg.", temp.price, player.bankBalance()));
        }
          else
        {
          
player.say2(format("Bank debit failed!\n%s.", temp.res));
        }
      }
        else
      {
        
player.say2("You do not have enough money!");
      }
    }
  }
}

//#CLIENTSIDE

function onPlayerEnters()
{
  
client.menus.remove("shop");
  
hideimgs(200, 201);
  
  
Shop_Purchase.visible = false;
  
Shop_Cancel.visible = false;
  
Shop_Debit.visible = false;
}

function 
onActionclientside(temp.actionname, temp.itemid, temp.itemdata, temp.itemprice)
{
  switch (
temp.actionname)
  {
    case 
"purchaseItem":
    {
      if (
"shop" in client.menus)
      {
        return;
      }
    
      
client.menus.add("shop");
      
this.sellitem = temp.itemid;
      
      for (
temp.i = 0; temp.i <= 0.7; temp.i += 0.1)
      {
        
seteffect(0, 0, 0, temp.i);
        
sleep(0.05);
      }
      
      
showimg(200, "@Tahoma@cb@Purchase " @ temp.itemdata[0], screenwidth / 2, (screenheight / 2) - 150);
      
changeimgvis(200, 5);
      
      
showimg(201, "@Tahoma@cb@Price: " @ temp.itemprice @ "g", screenwidth / 2, (screenheight / 2) - 120);
      
changeimgzoom(201, 0.6);
      
changeimgvis(201, 5);
      
      new 
GuiCheckBoxCtrl(Shop_Debit)
      {
        
profile = "GuiBlueCheckBoxProfile";
        
        
position = {(screenwidth / 2) - 64, (screenheight / 2) - 110};
        
extent = {136, 16};
        
        
visible = true;
        
        
text = "Debit from bank account";
      }
      
      new 
GuiButtonCtrl(Shop_Purchase)
      {
        
profile = "GuiGreenButtonProfile";
      
        
position = {(screenwidth / 2) - 72, (screenheight / 2) - 90};
        
extent = {64, 24};
        
        
visible = true;
      
        
text = "Purchase";
        
        
thiso.catchEvent(this, "onAction", "onPurchase");
      }
      
      new 
GuiButtonCtrl(Shop_Cancel)
      {
        
profile = "GuiBlueButtonProfile";
      
        
position = {(screenwidth / 2) + 12, (screenheight / 2) - 90};
        
extent = {64, 24};
        
        
visible = true;
      
        
text = "Cancel";
        
        
thiso.catchEvent(this, "onAction", "onCancelPurchase");
      }
      
      break;
    }
  
    default:
    {
      echo(
"Invalid shop data received!");
    }
  }
}

function 
onPurchase()
{
  
triggeraction(0, 0, "serverside", "-Rudora-Shop", "purchaseItem", this.sellitem, Shop_Debit.checked);
  
onCancelPurchase();
}

function 
onCancelPurchase()
{
  if (!(
"shop" in client.menus))
  {
    return;
  }
  
  
hideimgs(200, 201);
  
  
Shop_Purchase.destroy();
  
Shop_Cancel.destroy();
  
Shop_Debit.destroy();
  
  for (
temp.i = 0.7; temp.i >= 0; temp.i -= 0.1)
  {
    
seteffect(0, 0, 0, temp.i);
    
sleep(0.05);
  }
 
  
client.menus.remove("shop");
} 
Reply With Quote
 


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 02:03 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2026, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.