Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - Basil Beard

Pages: [1]
1
Modifications / SMFPets Version 0.2
« on: April 30, 2007, 07:30:43 am »
This is the thread for asking me questions and/or discussing my pet mod for SMFShop.

The pet mod is currently in BETA so please only use it at your own risk.

The current release of the pet mod is version 0.2. Anyone will 0.1 or 0.0 must uninstall and then reinstall to get this update. Sorry.
If you do uninstall, BACK UP YOUR PET DATA FIRST. Because it will be zapped if you do not.

If you asked a question on the old thread and it was never addressed, please ask again here because I probably didn't see it.

You can download version 0.2 here:

http://dev.dansoftaustralia.net/frs/shownotes.php?release_id=13

2
General SMFShop Discussion / SMFPets is Finally Here (0.1 out)
« on: February 27, 2007, 12:24:31 pm »
Thats right. The much awaited release of SMFPets is here. You can download it at:

http://dev.dansoftaustralia.net/frs/?group_id=10

Please direct any questions about the mod here. I'll try to answer/fix them as best as I can.

Please also try to break this mod now(on a test board or something) so that such bugs can be fixed before I release an updated version.

Please also suggest any improvements you want to make.

Please note that you must have Shop 3.0(and thus SMF 1.1 or higher to use this mod).

Finally, please have fun. I know you guys have waited a *long* time for this.  O0

3
Coding / Making Packages?
« on: February 23, 2007, 11:45:18 am »
Is there a guide on how to make packages somewhere? I am almost done with my pets mod, and wanted to package it up for everyone to be happy with.  :coolsmiley: But yeah. I donno how and I am sure you all don't want to install it by hand. (Even though only three files actually get edited, the rest is new stuff and database stuff).

But yeah. I still need to iron out a few kinks, but everybody should have pets... early next week  :angel:

4
General SMFShop Discussion / Multiple Shops! A brute-force guide.
« on: September 11, 2006, 05:14:45 am »
Only follow this if you feel like manually editing alot of code and also editing your database by hand.. I don't feel like actually making adding shops nice and easy.  :P.
Also BACK UP ALL FILES BEFORE YOU START! incase I messed up.  :coolsmiley:. Also when I sya "line 201" that means 201 of the unedited file. If you have made other changes, including the ones you make while editing the file, these line numbers may change. Sorry about that.

Your first task it to edit the Shop-Buy.php file.

After line 24 add
Code: [Select]
if (!isset($_GET['store'])) {
die("Please select a store!");
}

if ($_GET['store'] < 1 || $_GET['store'] > 5) {
die("Please select a valid store");
}

At line 117 find this part of the code:

Code: [Select]
$result = db_query("SELECT name, `desc`, price, stock, id, image, shop
FROM {$db_prefix}shop_items
ORDER BY {$sortQuery} {$sortDirQuery}", __FILE__, __LINE__);

and replace it with

Code: [Select]
$result = db_query("SELECT name, `desc`, price, stock, id, image
FROM {$db_prefix}shop_items
WHERE shopid = {$_GET['store']}
ORDER BY {$sortQuery} {$sortDirQuery}",
__FILE__, __LINE__);

Next, line 149

Code: [Select]
$context['shop_items_list'] .= "<a href='$scripturl?action=shop;do=buy2;id={$itemRows[$x]['id']}'>{$txt['shop_buynow']}</a>";

Make that
Code: [Select]
$context['shop_items_list'] .= "<a href='$scripturl?action=shop;do=buy2;store={$_GET['store']};id={$itemRows[$x]['id']};'>{$txt['shop_buynow']}</a>";

Line 169:
Code: [Select]
$context['shop_page_link'] = $scripturl."?action=shop;do=buy;sort=".$_GET['sort'].";sortDir=".$_GET['sortDir'];
replace it with
Code: [Select]
$context['shop_page_link'] = $scripturl."?action=shop;do=buy;store=".$_GET['store'].";sort=".$_GET['sort'].";sortDir=".$_GET['sortDir'];

after line 177 add:
Code: [Select]
if (!isset($_GET['store'])) {
die("Please select a store!");
}

if ($_GET['store'] < 1 || $_GET['store'] > 5) {
die("Please select a valid store");
}

Line 190. Find
Code: [Select]
$result = db_query("SELECT price, stock, name
FROM {$db_prefix}shop_items
WHERE id = {$_GET['id']}
LIMIT 1", __FILE__, __LINE__);
$row = mysql_fetch_array($result, MYSQL_ASSOC);
replace it with
Code: [Select]
$result = db_query("SELECT price, stock, name, shopid
FROM {$db_prefix}shop_items
WHERE id = {$_GET['id']}
LIMIT 1", __FILE__, __LINE__);
$row = mysql_fetch_array($result, MYSQL_ASSOC);

if ($row['shopid'] != $_GET['store']) {
die ("That item cannot be purchased in this store");
}

And yay! That file is done!

While you are at it; lets make our shops restock themselves as well. No more annoying by hand stuff.


add this after line 42.

Code: [Select]
    $time = date("zH");
$result = db_query("UPDATE {$db_prefix}shop_items
        SET stock = stock + restock
        WHERE laststock <= $time - timer AND stock <= maxrestock", __FILE__, __LINE__);
$result = db_query("UPDATE {$db_prefix}shop_items
        SET laststock = $time
        WHERE laststock <= $time - timer", __FILE__, __LINE__);
$times = date("z");
if ($modSettings['rateday'] != $times) {
$newrate = mt_rand(100,300);
$newrate= $newrate / 100;
$result = db_query("UPDATE {$db_prefix}settings
SET value = {$newrate}
WHERE variable = 'rate'", __FILE__, __LINE__);
$result = db_query("UPDATE {$db_prefix}settings
SET value = {$times}
WHERE variable = 'rateday'", __FILE__, __LINE__);
}

Ok. So those two files are done! Time to play with the templetes!

Line 29 of Shop.templete.php

Code: [Select]
<a href="$scripturl?action=shop;do=buy">{$txt['shop_buy']}</a><br />

replace that with

Code: [Select]
<a href="$scripturl?action=shop;do=buy;store=1">[i]Store 1 desp.[/i]</a><br />
<a href="$scripturl?action=shop;do=buy;store=2">[i]Store 2 desp.[/i]</a><br />
<a href="$scripturl?action=shop;do=buy;store=3">[i]Store 3 desp.[/i]</a><br />
.
.
.
<a href="$scripturl?action=shop;do=buy;store=n">[i]Store n desp.[/i]</a><br />


Where n is the number of stores. Rename "store 1 desp" whatever you want to call that store.

Ok. Now we get to play with the admin part of the store!
in shopAdmin.templete.php instert after line  179

Code: [Select]
Amount to stock per restock: <input name="restock" type="text" value="{$context['shop_items_item']['restock']}" size="5"<br />
Time between restocks: <input name="timer" type="text" value="{$context['shop_items_item']['timer']}" size="5"<br />
Max amount to stock: <input name="maxstock" type="text" value="{$context['shop_items_item']['maxstock']}" size="5"<br />
ID of shop to stock in: <input name="shopid" type="text" value="{$context['shop_items_item']['shopid']}" size="5"<br />

and then do the SAME THING after line 220.

Ok, last file. ShopAdmin.php

line 201. Instert this after it

Code: [Select]
                                            'restock' => 1,
                                            'timer' => 6,
                                            'maxstock' => 10,
                                            'shopid' => 1

line 225. Fine and replace
Code: [Select]
        $sql = "INSERT
                INTO {$db_prefix}shop_items
                (name, `desc`, price, module, stock, input_needed, can_use_item, info1, info2, info3, info4, image)
                VALUES (
                        '{$_POST['itemname']}',
                        '{$_POST['itemdesc']}',
                        {$_POST['itemprice']},
                        '{$_POST['item']}',
                        {$_POST['itemstock']},
                        {$_POST['require_input']},
                        {$_POST['can_use_item']},
                        '{$_POST['info1']}',
                        '{$_POST['info2']}',
                        '{$_POST['info3']}',
                        '{$_POST['info4']}',
                        '{$_POST['icon']}'
                        )";
replace with

Code: [Select]
        $sql = "INSERT
                INTO {$db_prefix}shop_items
                (name, `desc`, price, module, stock, input_needed, can_use_item, info1, info2, info3, info4, image, restock, timer, maxrestock, shopid)
                VALUES (
                        '{$_POST['itemname']}',
                        '{$_POST['itemdesc']}',
                        {$_POST['itemprice']},
                        '{$_POST['item']}',
                        {$_POST['itemstock']},
                        {$_POST['require_input']},
                        {$_POST['can_use_item']},
                        '{$_POST['info1']}',
                        '{$_POST['info2']}',
                        '{$_POST['info3']}',
                        '{$_POST['info4']}',
                        '{$_POST['icon']}',
                        '{$_POST['restock']}',
                        '{$_POST['timer']}',
                        '{$_POST['maxstock']}',
                        '{$_POST['shopid']}'
                        )";

line 262. Find and replace

Code: [Select]
        $result = db_query("SELECT name, `desc`, price, stock, image
                            FROM {$db_prefix}shop_items
                            WHERE id = {$_GET['id']}"
                            , __FILE__, __LINE__);
        $row = mysql_fetch_array($result, MYSQL_ASSOC);
        $context['shop_edit'] = array(
                                      'id' => $_GET['id'],
                                      'name' => $row['name'],
                                      'desc' => $row['desc'],
                                      'price' => $row['price'],
                                      'stock' => $row['stock'],
                                      'image' => $row['image'],
                                       );
    } elseif ($_GET['do'] == "edit2") {
        $context['shop_items_edit'] = 2;
        $result = db_query("UPDATE {$db_prefix}shop_items
                            SET name = '{$_POST['itemname']}',
                                `desc` = '{$_POST['itemdesc']}',
                                price = {$_POST['itemprice']},
                                stock = {$_POST['itemstock']},
                                image = '{$_POST['icon']}'
                            WHERE id = {$_POST['id']}
                            LIMIT 1"
                            , __FILE__, __LINE__);
with 
Code: [Select]
       $result = db_query("SELECT name, `desc`, price, stock, image, restock, timer, maxrestock, shopid
                            FROM {$db_prefix}shop_items
                            WHERE id = {$_GET['id']}"
                            , __FILE__, __LINE__);
        $row = mysql_fetch_array($result, MYSQL_ASSOC);
        $context['shop_edit'] = array(
                                      'id' => $_GET['id'],
                                      'name' => $row['name'],
                                      'desc' => $row['desc'],
                                      'price' => $row['price'],
                                      'stock' => $row['stock'],
                                      'image' => $row['image'],
                                      'restock' => $row['restock'],
                                      'timer' => $row['timer'],
                                      'maxstock' => $row['maxrestock'],
                                      'shopid' => $row['shopid']
                                       );
    } elseif ($_GET['do'] == "edit2") {
        $context['shop_items_edit'] = 2;
        $result = db_query("UPDATE {$db_prefix}shop_items
                            SET name = '{$_POST['itemname']}',
                                `desc` = '{$_POST['itemdesc']}',
                                price = {$_POST['itemprice']},
                                stock = {$_POST['itemstock']},
                                image = '{$_POST['icon']}',
                                restock = {$_POST['restock']},
                                timer = {$_POST['timer']},
                                maxrestock = {$_POST['maxstock']},
                                shopid = {$_POST['shopid']}
                            WHERE id = {$_POST['id']}
                            LIMIT 1", __FILE__, __LINE__);

And there you go. You have a shop.

But wait, there is still the database to edit! Silly us  :D

Anyways, you need to add these four cols to the shop_shop_items database:

        Field      Type     Attributes     Null     Default
      timer      int(10)     UNSIGNED     No      6
    laststock     int(10)    UNSIGNED    No     0
    used     int(10)    UNSIGNED    No     0
    maxrestock     int(10)    UNSIGNED    No     15     

And after you do that, upload everything, cross your fingers, and hope it works. It probably won't, but you can post whatever error you get here and I can try to help you fix it.  :police:

5
Items / Item Transfers.
« on: April 26, 2006, 09:13:38 am »
I was board again. And so using my newfound knowledge of what $context does.... 3 easy steps to get item transfers working on your forum  :)

1) Open shop.php and insert:

Code: [Select]
elseif($_GET['do'] == "senditems") {
        $context['linktree'][] = array(
            'url' => "$scripturl?action=shop;do=senditems",
            'name' => $txt['shop_send_money'],
        );
       
        $result = db_query("SELECT it.name, inv.id AS ivid, inv.trading
                            FROM {$db_prefix}shop_inventory AS inv, {$db_prefix}shop_items AS it
                            WHERE inv.ownerid = {$ID_MEMBER} AND inv.itemid = it.id AND inv.trading = 0
                            GROUP BY it.id
                            ORDER BY it.name ASC ", __FILE__, __LINE__);
        while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
        $context['shop_trade_items'] .= "
        <option value ={$row['ivid']}>{$row['name']}</option>";
        }
        $context['sub_template'] = "sendItems";
loadTemplate('Shop');

    } elseif($_GET['do'] == "senditems2") {
        $context['linktree'][] = array(
            'url' => "$scripturl?action=shop;do=senditems2",
            'name' => $txt['shop_send_money'],
        );
$result = db_query("SELECT ID_MEMBER
FROM {$db_prefix}members
WHERE memberName = '{$_POST['membername']}'", __FILE__, __LINE__);
        $row = mysql_fetch_array($result, MYSQL_ASSOC);
        $newowner = $row['ID_MEMBER'];
$result = db_query("SELECT ownerid, itemid
FROM {$db_prefix}shop_inventory
WHERE id = '{$_POST['giftid']}'", __FILE__, __LINE__);
        $row = mysql_fetch_array($result, MYSQL_ASSOC);
        $itemid = $row['itemid'];
        if ($row['ownerid'] !== $ID_MEMBER) {
       die($txt['shop_use_others_item']);
       }
       else {
        $result = db_query("UPDATE {$db_prefix}shop_inventory
SET ownerid = $newowner
WHERE id = '{$_POST['giftid']}'", __FILE__, __LINE__);
$context['shop_buy_message'] = "Item succesfully transfered!";
$result = db_query("SELECT name
FROM {$db_prefix}shop_items
WHERE id = {$itemid}", __FILE__, __LINE__);
      $row = mysql_fetch_array($result, MYSQL_ASSOC);
      $name = $row['name'];
$result = db_query("SELECT memberName
FROM {$db_prefix}members
WHERE ID_MEMBER = {$ID_MEMBER}", __FILE__, __LINE__);
        $row = mysql_fetch_array($result, MYSQL_ASSOC);
        $target = $row['memberName'];
$pmfrom = array(
'id' => '1',
'name' => 'Clucky',
'username' => 'Clucky'
);
$pmto = array(
'to' => array($newowner),
'bcc' => array()
);
sendpm($pmto, 'You have been sent an item!', "{$target} has sent you an {$name}. Isn't that nice of them? [i]You do not need to reply to this automated message[/i]", 0, $pmfrom);
}
        $context['sub_template'] = "message";
loadTemplate('Shop');

    }

this should go right before the
Code: [Select]
     else {
        die("What do I do with {$_GET['do']}? HUH????");
    }
}


function formatMoney($money) {
    global $modSettings;

    $money = (int) $money;
    return $modSettings['shopCurrencyPrefix'].$money.$modSettings['shopCurrencySuffix'];
}
?>
Which ends the file.

Next, open shop.tempelate.php and insert
Code: [Select]
function template_sendItems() {
global $txt, $context, $modSettings, $scripturl, $settings;

shop_header();
echo <<<EOT
<table width="100%" cellpadding="5" cellspacing="0" border="0" class="tborder" style="margin-top: 1.5ex;">
<tr valign='top' class='windowbg2'>
<td style='padding-bottom: 2ex;' width='20%'>
<center><b>{$txt['shop_send_items']}</b></center><br />{$txt['shop_send_items_message']}
<form action="$scripturl?action=shop;do=senditems2" method="POST">
{$txt['shop_member_name']}: <input type="text" name="membername" size="25">
<a href="{$scripturl}?action=findmember;input=membername;quote=1;sesc={$context['session_id']}" onclick="return reqWin(this.href, 350, 400);"><img src="{$settings['images_url']}/icons/assist.gif" border="0" alt="{$txt['find_members']}" /> Find Members</a><br />
{$txt['shop_item_to_send']}:
<select name="giftid">
{$context['shop_trade_items']}
</select>
{$txt['shop_send_message_to_give']}: <textarea name="message" cols="50" rows="5"></textarea><br />
<input type="submit" value="{$txt['shop_send_items']}">
</form>
</td>
</tr>
</table>
EOT;
shop_footer();
}
Right before the ?> that ends the file.

You also need to find this line of code:
Code: [Select]
<a href='$scripturl?action=shop;do=invother'>{$txt['shop_invother']}</a><br />
and insert
Code: [Select]
<a href='$scripturl?action=shop;do=senditems'>{$txt['shop_senditems']}</a><br />

After it.

Lastly, open shop.english.php and insert these four lines pretty much anywhere in the file.
Code: [Select]
$txt['shop_send_items'] = "Send a item to someone";
$txt['shop_send_items_message'] = "You can use this to give an item to someone. This can also be used for item - item trades. If you wish to sell an item, please use the trade center. You cannot sell an item that you are currently trading";
$txt['shop_item_to_send'] = "Item to send:";
$txt['shop_senditems'] = "Items transfer center";

Save/upload everything, and you should be able to transfer items from account to account without using the trade center.

 

6
General SMFShop Discussion / Question about shop.php
« on: April 25, 2006, 12:48:52 am »
All through out shop.php there are these $context lines.

Code: [Select]
$context['shop_bank_link']

I have determined that the $context lines provoide certain amounts of text formatting and all that, but I can't figgure out where they are defined? Is in one of the subs files in the sources folder? Or is it someplace else?

Thanks  :D

7
After reading tazpot's post Here I decided to take him up on it.  :P. After all, item creation is pretty easy(I have coded several fine items with only a begginers knowlege of php and my_sql when I started) and there isn't any reason why Daniel needs to code all the items you have ideas for.  :D. So cause I had some free time, I was like "Lets write a guide"  O0. And so, without futhur ado...   :)

Item Creation 101
By Basilbeard

So we want to create an item for SMF shop. To do this, first figure what item you want to create. For this lesson, we will be creating a “Magic Die”. Upon using the die, it will target another player, and then either give them a random amount of points or destroy a random amount of points.

Note: This guide assumes a basic knowledge of php. Thought not much is required.

Start by opening the testitem.php file.

Code: [Select]
<?php

/**********************************************\
| SMFSHOP (Shop MOD for Simple Machines Forum) |
|         (c) 2005 DanSoft Australia           |
|      http://www.dansoftaustralia.com/        |
\**********************************************/

//File: testitem.php
//      Test Item (gets some inputs, most likely you will base your items on this)

//VERSION: 1.1 (Build 4)
//DATE: 10th April 2005

//your class should always be called item_filename, eg. if your file is 
//myCoolItem.php then the class should be called 'item_myCoolItem'. This 
//class should always extend itemTemplate.

class item_testitem2 extends itemTemplate {
    
    
//when this function is called, you should set all the item's
    //variables (see inside this example)
    
function getItemDetails() {

        
//VALUES CHANGABLE FROM WITHIN ADMIN PANEL:
          //the name of the item
          
$this->name "A Test Item 2";
          
//the item's description
          
$this->desc "Just a test item! The second time!";
          
//the item's price
          
$this->price 5;

        
//UNCHANGABLE VALUES:
          //whether inputs are required by this item. In this case, we get some inputs,
          //so set this to 'true'.
          
$this->require_input true;
          
//set this to 'false' if the item is unusable. This is good for display
          //items.
          
$this->can_use_item true;
    }

    
//this function is called when the user tries to use the item.
    //if your item needs any further user input then you can get that 
    //input here (eg. if it's a "Change username" item then you have
    //to ask the user what they'd like to change their username to).
    //Any text you return will get shown to the user (DON'T ECHO STUFF).
    
function getUseInput() {
        return 
"A Test: <input type='text' name='test123'>";
    }

    
//the is where all the fun begins. This function is called when 
    //the user actually uses the item. Return stuff, DON'T ECHO!
    
function onUse() {
        return 
"Hello, I am a test!<br>In the text box, you entered '{$_POST['test123']}'";
    }
}

?>

Anything after a // is a comment and doesn’t actually appear in the code, so the real file looks like

Code: [Select]
<?php
class item_testitem2 extends itemTemplate {
    function 
getItemDetails() {
          
$this->name "A Test Item 2";
          
$this->desc "Just a test item! The second time!";
          
$this->price 5;

          
$this->require_input true;
          
$this->can_use_item true;
    }

    function 
getUseInput() {
        return 
"A Test: <input type='text' name='test123'>";
    }

    function 
onUse() {
        return 
"Hello, I am a test!<br>In the text box, you entered '{$_POST['test123']}'";
    }
}

?>
First lets try and see what this item does. The function getUseInput() prompts the user for input upon using the item. This is where they will often type in the member name of the target. The type=’text’ tells them to be a text box while the name=’test123’ defines its value for the onUse() function. In this case, name=’test123’ and so whatever the user inputs here can be called up using ($_POST[‘test123’]} in the onUse() function.

Note that if you wanted two inputs, say, an item that lets you pick a target and also an amount to steal, you would not have.
Code: [Select]
    function getUseInput() {
        return "Target: <input type='text' name='target'>";
        return "Amount to steal: <input type='text' name='steal'>";
    }

Because the return line causes that part of the function to end. Instead, you would need to have.

Code: [Select]
    function getUseInput() {
        return "Target: <input type='text' name='target'> <br>
                Amount to steal: <input type='text' name='steal'>";
    }

Here, the target name could later be called up using {$_POST[‘target’]} and the amount to steal could later be called up using {$_POST[‘steal’]}.

Now lets examine the second half of the code.

Code: [Select]
    function onUse() {
        return "Hello, I am a test!<br>In the text box, you entered '{$_POST['test123']}'";
    }

This is very simple. ‘return’ tells it print the follow text in the quotes. Thus, upon using the item it will display

Hello, I am a test!
In the text box, you entered ‘Arrrrrrrr!’

(this assumes that I did infact enter Arrrrrrr! In the textbox.

So now that we understand the basics behind how this item works, lets start coding out item.

We start by copying this to a new file, which we call MagicDie.php

Code: [Select]
  <?php
class item_testitem2 extends itemTemplate {
    function 
getItemDetails() {
          
$this->name "A Test Item 2";
          
$this->desc "Just a test item! The second time!";
          
$this->price 5;

          
$this->require_input true;
          
$this->can_use_item true;
    }

    function 
getUseInput() {
        return 
"A Test: <input type='text' name='test123'>";
    }

    function 
onUse() {
        return 
"Hello, I am a test!<br>In the text box, you entered '{$_POST['test123']}'";
    }
}

?>


The most important change is in the second line. We need to change class item_testitem2 extends itemTemplate { to class item_MagicDie extends itemTemplate {
We then need to change the name and desc and price. This item requires input and it can be used, so the other two values stay as true. Lets make this item cost 20 points.

Code: [Select]
  <?php
class item_MagicDie extends itemTemplate {
    function 
getItemDetails() {
          
$this->name "Magic Die";
          
$this->desc "Why risk your own points when you can gamble with someone elses?";
          
$this->price 20;

          
$this->require_input true;
          
$this->can_use_item true;
    }

For this item, we also need to include the getAddInput() function. This will allow us, upon the creation of the item, to send bounds on how rewarding or damaging this item can be.
Code: [Select]
    function getAddInput() {
        return "Max amount to give: <input type='text' name='info1' value='100'><br>
               Max amount to take: <input type='text' name='info2' value='-100'>";
    }

Unlike with the getUseInput() function, you cannot change the value of the ‘name’ in these two lines. If you were to add a third, it would have to be called ‘info3’ and a fourth would be ‘info4’. You can’t add anymore after that due to database constraints.

Now that we have that part coded, lets again code our getUseInput() function. This is best served by copying the same function from another item, say the steal item we already have.

Code: [Select]
    function getUseInput() {
global $context, $scripturl, $settings, $txt;
        return "Steal From: <input type='text' name='stealfrom' size='50'>
         <a href='{$scripturl}?action=findmember;input=stealfrom;quote=0;sesc={$context['session_id']}' onclick='return reqWin(this.href, 350, 400);'><img src='{$settings['images_url']}/icons/assist.gif' border='0' alt='{$txt['find_members']}' /> Find Member</a>";
    }

We of course need to make some changes. Namely, the “Steal From” line needs to be changed and the name should be more like ‘dicetarget’ rather than ‘stealfrom’. So we make out changes.

Code: [Select]
    function getUseInput() {
global $context, $scripturl, $settings, $txt;
        return “Choose a target for your die: <input type='text' name='dicetarget' size='50'>
         <a href='{$scripturl}?action=findmember;input=dicetarget;quote=0;sesc={$context['session_id']}' onclick='return reqWin(this.href, 350, 400);'><img src='{$settings['images_url']}/icons/assist.gif' border='0' alt='{$txt['find_members']}' /> Find Member</a>";
    }

Don’t worry about all that funky code. That adds the button that lets you search for member’s names. Now we just need to code the fun part. The onUse() function. The part that actually tells the item what to do.
Code: [Select]
    function onUse() {
        global $db_prefix, $ID_MEMBER, $item_info;

The first task is to make sure they are not targeting themselves with the item. They should use random money if they want to do that. So we do a database query.
Code: [Select]
$result = db_query("SELECT memberName
                                FROM {$db_prefix}members
                                WHERE ID_MEMBER = {$ID_MEMBER}", __FILE__, __LINE__);

I personally hate these queries. The syntax needs to be perfect or else the item will not work, and I often find I need keep fixing the syntax on my items several times after I add them before they actually work. But they are needed for any good item. They are what you use for almost everything, from changing someone’s money count to modifying their title or post count.

We then need to add a few more lines of code. I am not a PHP know-it-all, so can’t really explain why it works I just know it does.

Code: [Select]
$row = mysql_fetch_array($result, MYSQL_ASSOC);
$user = $row[‘memberName’]

This creates an array called row(I think) which contains the previously selected memberName. We can now call that value using $row[‘memberName’]; our next part needs to be an if statement which gets to see if $row[‘memberName’] is the same name as the name the user inputted. If this is true, we need to return an error message instead of executing the random part.

Code: [Select]
if ($user == $_POST[‘dicetarget’]) {
return “Use some random money instead. Use the die on someone else”;
die();
}

According to Daniel, the die() function should stop the item from deleting itself. I have worked around this differently and thus cannot test this, but if it gives you any errors, just remove it from the code.

Now we need to code the other part of the code, what happens when the target is someone different. To do this, we just use an else.
Code: [Select]
else {
$amount = mt_rand($item_info[2], $item_info[1]);

The mt_rand function creates a random integer(inclusive) between the two given bounds. Exactly what we want. We now need to update the other guys point count. Guess what? We need another database query to do this.
Code: [Select]
$result = db_query("UPDATE {$db_prefix}members
                                SET money = money + {$ammount}
                                WHERE memberName = '{$_POST[‘dicetarget’]}'", __FILE__, __LINE__);

So we have updated the database with the random amount. There are two things left to do. The first is to send a friendly PM to the unlucky or lucky target. They should know their points have been changed. To do this, we actually need to add a couple of lines into the top of the code. There again might be a better way to do this, but this is how I’ve figured out how to do it. So until Daniel tells me a better way to do it, add

Code: [Select]
global $sourcedir;
require_once($sourcedir . '/Subs-Post.php');

below the <?php line that starts your code.

Now let’s send the PM. We first need to select the targets ID_MEMBER number so that the PM can be sent.

Code: [Select]
$result = db_query("SELECT ID_MEMBER
       FROM {$db_prefix}members
                           WHERE memberName = '{$_POST[‘dicetarget’]}'", __FILE__, __LINE__);
$row = mysql_fetch_array($result, MYSQL_ASSOC);
$pmfrom = array(
'id' => 1,
'name' => 'Basilbeard',
'username' => 'Basilbeard'
);
$pmto = array(
to' => array($row['ID_MEMBER']),
'bcc' => array()
);
sendpm($pmto, 'Care for a game of chance?', “{$user} uses a Magic Die on you. You check your inventory, and find that your point total has been changed by ".formatMoney($amount).”! [i] You do not need to reply to this automated message”, 0, $pmfrom);                                           

Lastly, we need to return a statement to the user of the item and then make sure we end all our brackets and such.

Code: [Select]
Return “You use your Magic Die on {$_POST[‘dicetarget’}. It spins around for a few minutes, before landing on {$amount} and thus changing their point count by “.formatMoney{$amount}.”!”;
} // This ends the else bracket.
} // This ends the onUse function
} // This items the item function itself.
?> // this ends the PHP code, and thus out file.

So in the end, our whole file looks like:

Code: [Select]
<?php
/**********************************************\
| SMFSHOP (Shop MOD for Simple Machines Forum) |
|         (c) 2005 DanSoft Australia           |
|      http://www.dansoftaustralia.com/        |
\**********************************************/

//File: MagicDie.php
//      Magic Die

//VERSION: 1.0
//DATE: 16th April 2006
//AUTHOR: Basilbeard
global $sourcedir;
require_once(
$sourcedir '/Subs-Post.php');
class 
item_MagicDie extends itemTemplate {
    function 
getItemDetails() {
          
$this->name "Magic Die";
          
$this->desc "Why risk your own points when you can gamble with someone elses?";
          
$this->price 20;

          
$this->require_input true;
          
$this->can_use_item true;
    }

    function 
getAddInput() {
 
   return "Max amount to give: <input type='text' name='info1' value='100'><br>
               Max amount to take: <input type='text' name='info2' value='-100'>"
;
    }

    function 
getUseInput() {
global $context$scripturl$settings$txt;
        return 
"Choose a target for your die: <input type='text' name='dicetarget' size='50'>
         <a href='
{$scripturl}?action=findmember;input=dicetarget;quote=0;sesc={$context['session_id']}' onclick='return reqWin(this.href, 350, 400);'><img src='{$settings['images_url']}/icons/assist.gif' border='0' alt='{$txt['find_members']}' /> Find Member</a>";
    }

    function 
onUse() {
    global $db_prefix$ID_MEMBER$item_info;
$result db_query("SELECT memberName
                                FROM 
{$db_prefix}members
                                WHERE ID_MEMBER = 
{$ID_MEMBER}"__FILE____LINE__);
$row mysql_fetch_array($resultMYSQL_ASSOC);
$user $row['memberName'];
if ($user == $_POST['dicetarget']) {
return "Use some random money instead. Use the die on someone else"
die();
}
else {
$amount mt_rand($item_info[2], $item_info[1]);
$result db_query("UPDATE {$db_prefix}members
                                SET money = money + 
{$ammount}
                                WHERE memberName = '
{$_POST['dicetarget']}'"__FILE____LINE__);
$result db_query("SELECT ID_MEMBER
        FROM 
{$db_prefix}members
                         WHERE memberName = '
{$_POST['dicetarget']}'"__FILE____LINE__);
$row mysql_fetch_array($resultMYSQL_ASSOC);
$pmfrom = array(
'id' => 1,
'name' => 'Basilbeard',
'username' => 'Basilbeard'
);
$pmto = array(
to' => array($row['ID_MEMBER']),
'
bcc' => array()
);
sendpm($pmto, '
Care for a game of chance?', "{$user} uses a Magic Die on you. You check your inventory, and find that your point total has been changed by ".formatMoney($amount)."! [i] You do not need to reply to this automated message[/i]", 0, $pmfrom);                                           
return "You use your Magic Die on {$_POST['
dicetarget']}. It spins around for a few minutes, before landing on {$amount} and thus changing their point count by {$amount} points!";;
}
}
}
?>


Now of course, if I am coding my own items I don’t worry too much about commenting. But if I am doing some coding for others and that, its nice to add some recognition both to myself and to Daniel. So that’s why I put that block of code up at the very top.

The only thing remaining is to upload the item, install it and test it out. For me this never seems to work the first time, or the second time, or even the nth time. I personally prefer to just code the item in something like Crimson Editor, which shows any really dumb mistakes, and then to just upload and let it tell me what I did wrong instead of spending time looking for it myself. For example, the first time I coded this item I forgot the ; on the $user = $row['memberName']; line, causing the whole function not to work.

Once all the errors in the code are sorted out. We need to see if the item works. I start by using it on myself.

Quote
Use some random money instead. Use the die on someone else

Yay! It worked!.

I then try on someone else. And get a mysql error. As I said, I hate those errors. Luckily, this one wasn’t bad. I had {$ammount} instead of {$amount}.

I use it again and get
Quote
You use your Magic Die on Bunny. It spins around for a few minutes, before landing on 52 and thus changing their point count by 52 points!

Yay! The last thing to do is log into Bunny and see the PM. It works! So I assume the item is working just fine and release it on my forum. Or, in this place, remove it from my forum and post this guide.



I'm open to any questions you might have about the guide. Questions about SMF_SHOP itself would probably be better suited for Daniel cause he was the one that acutally wrote it  :P

Update: 4/23: Scroll down for part 2! Learn how to code items which use custom database fields!

Pages: [1]