Jump to content
MakeWebGames

Inventory / Item Options (MCCodes V2)


Rooster

Recommended Posts

Willing to pay*

I have a request for someone to take the standard inventory.php and merge the iteminfo/itemsend/itemsell/imadd/itemuse.php all into the inventory.php.

So basically it reduces 6 files into the 1 inventory.php file.

I figured functions would be the easiest way.

Inventory.php?action=info&ItemID=1
Inventory.php?action=sell&ItemID=1

something like that?


Thank you.

 

I am not running PHP 8 - I'm using 7.4.26

Edited by Rooster
Link to comment
Share on other sites

As Adam said, Its a odd thing to do. But hey, I'm Down. This is Untested.
 

<?php
require_once('globals.php');
if (!isset($_GET['action'])) {
    $_GET['action'] = '';
}
switch ($_GET['action']) {
case 'iteminfo': iteminfo(); break;
case 'itemsend': itemsend(); break;
case 'itemsell': itemsell(); break;
case 'imadd': imadd(); break;
case 'itemuse': itemuse(); break;
default: index(); break;
}



function itemuse(){
	global $db, $ir, $c, $userid, $h;
	$_GET['ID'] =
        (isset($_GET['ID']) && is_numeric($_GET['ID']))
                ? abs(intval($_GET['ID'])) : '';
if (!$_GET['ID'])
{
    echo 'Invalid use of file';
}
else
{
    $i =
            $db->query(
                    "SELECT `effect1`, `effect2`, `effect3`,
                     `effect1_on`, `effect2_on`, `effect3_on`,
                     `itmname`, `inv_itemid`
                     FROM `inventory` AS `iv`
                     INNER JOIN `items` AS `i`
                     ON `iv`.`inv_itemid` = `i`.`itmid`
                     WHERE `iv`.`inv_id` = {$_GET['ID']}
                     AND `iv`.`inv_userid` = $userid");
    if ($db->num_rows($i) == 0)
    {
        $db->free_result($i);
        echo 'Invalid item ID';
    }
    else
    {
        $r = $db->fetch_row($i);
        $db->free_result($i);
        if (!$r['effect1_on'] && !$r['effect2_on'] && !$r['effect3_on'])
        {
            echo 'Sorry, this item cannot be used as it has no effect.';
            die($h->endpage());
        }
        for ($enum = 1; $enum <= 3; $enum++)
        {
            if ($r["effect{$enum}_on"])
            {
                $einfo = unserialize($r["effect{$enum}"]);
                if ($einfo['inc_type'] == "percent")
                {
                    if (in_array($einfo['stat'],
                            array('energy', 'will', 'brave', 'hp')))
                    {
                        $inc =
                                round(
                                        $ir['max' . $einfo['stat']] / 100
                                                * $einfo['inc_amount']);
                    }
                    else
                    {
                        $inc =
                                round(
                                        $ir[$einfo['stat']] / 100
                                                * $einfo['inc_amount']);
                    }
                }
                else
                {
                    $inc = $einfo['inc_amount'];
                }
                if ($einfo['dir'] == "pos")
                {
                    if (in_array($einfo['stat'],
                            array('energy', 'will', 'brave', 'hp')))
                    {
                        $ir[$einfo['stat']] =
                                min($ir[$einfo['stat']] + $inc,
                                        $ir['max' . $einfo['stat']]);
                    }
                    else
                    {
                        $ir[$einfo['stat']] += $inc;
                    }
                }
                else
                {
                    $ir[$einfo['stat']] = max($ir[$einfo['stat']] - $inc, 0);
                }
                $upd = $ir[$einfo['stat']];
                if (in_array($einfo['stat'],
                        array('strength', 'agility', 'guard', 'labour', 'IQ')))
                {
                    $db->query(
                            "UPDATE `userstats`
                             SET `{$einfo['stat']}` = '{$upd}'
                             WHERE `userid` = {$userid}");
                }
                else
                {
                    $db->query(
                            "UPDATE `users`
                             SET `{$einfo['stat']}` = '{$upd}'
                             WHERE `userid` = {$userid}");
                }
            }
        }
        echo $r['itmname'] . ' used successfully!';
        item_remove($userid, $r['inv_itemid'], 1);
    }
}
}


function imadd() {
    global $db, $ir, $c, $userid, $h;
	$_GET['ID'] =
        (isset($_GET['ID']) && is_numeric($_GET['ID']))
                ? abs(intval($_GET['ID'])) : '';
$_POST['price'] =
        (isset($_POST['price']) && is_numeric($_POST['price']))
                ? abs(intval($_POST['price'])) : '';
$_POST['QTY'] =
        (isset($_POST['QTY']) && is_numeric($_POST['QTY']))
                ? abs(intval($_POST['QTY'])) : '';
$_POST['currency'] =
        (isset($_POST['currency'])
                && in_array($_POST['currency'], array('money', 'crystals')))
                ? $_POST['currency'] : 'money';
if ($_POST['price'] && $_POST['QTY'] && $_GET['ID'])
{
    if (!isset($_POST['verf'])
            || !verify_csrf_code("imadd_{$_GET['ID']}",
                    stripslashes($_POST['verf'])))
    {
        echo "Your request to add this item to the market has expired.
        Please try again.<br />
		&gt; <a href='?action=imadd&ID={$_GET['ID']}'>Back</a>";
        die($h->endpage());
    }
    $q =
            $db->query(
                    "SELECT `inv_qty`, `inv_itemid`, `inv_id`, `itmname`
                     FROM `inventory` AS `iv`
                     INNER JOIN `items` AS `i`
                     ON `iv`.`inv_itemid` = `i`.`itmid`
                     WHERE `inv_id` = {$_GET['ID']}
                     AND `inv_userid` = $userid");
    if ($db->num_rows($q) == 0)
    {
        $db->free_result($q);
        echo "Invalid Item ID";
    }
    else
    {
        $r = $db->fetch_row($q);
        $db->free_result($q);
        if ($r['inv_qty'] < $_POST['QTY'])
        {
            echo 'You do not have enough of this item.';
            $h->endpage();
            exit;
        }
        $checkq =
                sprintf(
                        'SELECT `imID`
                         FROM `itemmarket`
                         WHERE `imITEM` = %u AND `imPRICE` = %u
                         AND `imADDER` = %u AND `imCURRENCY` = "%s"',
                        $r['inv_itemid'], $_POST['price'], $userid,
                        $_POST['currency']);
        $checkq = $db->query($checkq);
        if ($db->num_rows($checkq) > 0)
        {
            $cqty = $db->fetch_row($checkq);
            $query =
                    sprintf(
                            'UPDATE `itemmarket`
                             SET imQTY = imQTY + %u
                             WHERE imID = %u', $_POST['QTY'], $cqty['imID']);
            $db->query($query);
        }
        else
        {
            $db->query(
                    "INSERT INTO `itemmarket`
                     VALUES (NULL, '{$r['inv_itemid']}', {$userid},
                     {$_POST['price']}, '{$_POST['currency']}',
                     {$_POST['QTY']})");
        }
        $db->free_result($checkq);
        item_remove($userid, $r['inv_itemid'], $_POST['QTY']);
        $imadd_log =
                $db->escape(
                        "{$ir['username']} added {$r['itmname']} "
                                . "x{$_POST['QTY']} to the item market for "
                                . "{$_POST['price']} {$_POST['currency']}");
        $db->query(
                "INSERT INTO `imarketaddlogs`
                VALUES (NULL, {$r['inv_itemid']}, {$_POST['price']},
                {$r['inv_id']}, $userid, " . time() . ", '{$imadd_log}')");
        echo "Item added to market.";
    }
}
else
{
    $q =
            $db->query(
                    "SELECT COUNT(`inv_id`)
                     FROM `inventory`
                     WHERE `inv_id` = {$_GET['ID']}
                     AND `inv_userid` = $userid");
    if ($db->fetch_single($q) == 0)
    {
        echo 'Invalid Item ID';
    }
    else
    {
        $imadd_csrf = request_csrf_code("imadd_{$_GET['ID']}");
        echo "
Adding an item to the item market...<br />
	<form action='?action=imadd&ID={$_GET['ID']}' method='post'>
	<input type='hidden' name='verf' value='{$imadd_csrf}' />
		Quantity: <input type='text' name='QTY' value=''><br />
		Price: <input type='text' name='price' value='0' /><br />
	<select name='currency' type='dropdown'>
		<option value='money'>Money</option>
		<option value='crystals'>Crystals</option>
	</select><br />
		<input type='submit' value='Add' />
	</form>
   ";
    }
    $db->free_result($q);
}
}


function itemsell() {
    global $db, $ir, $c, $userid, $h;
	$_GET['ID'] =
        (isset($_GET['ID']) && is_numeric($_GET['ID']))
                ? abs(intval($_GET['ID'])) : '';
$_POST['qty'] =
        (isset($_POST['qty']) && is_numeric($_POST['qty']))
                ? abs(intval($_POST['qty'])) : '';
if (!empty($_POST['qty']) && !empty($_GET['ID']))
{
    $id =
            $db->query(
                    "SELECT `inv_qty`, `itmsellprice`, `itmid`, `itmname`
                     FROM `inventory` AS `iv`
                     INNER JOIN `items` AS `it`
                     ON `iv`.`inv_itemid` = `it`.`itmid`
                     WHERE `iv`.`inv_id` = {$_GET['ID']}
                     AND `iv`.`inv_userid` = {$userid}
                     LIMIT 1");
    if ($db->num_rows($id) == 0)
    {
        echo 'Invalid item ID';
    }
    else
    {
        $r = $db->fetch_row($id);
        if (!isset($_POST['verf'])
                || !verify_csrf_code("sellitem_{$_GET['ID']}",
                        stripslashes($_POST['verf'])))
        {
            echo '<h3>Error</h3><hr />
    		This transaction has been blocked for your security.<br />
    		Please sell items quickly after you open the form - do not leave it open in tabs.<br />
    		&gt; <a href="itemsell.php?ID=' . $_GET['ID'] . '">Try Again</a>';
            die($h->endpage());
        }
        if ($_POST['qty'] > $r['inv_qty'])
        {
            echo 'You are trying to sell more than you have!';
        }
        else
        {
            $price = $r['itmsellprice'] * $_POST['qty'];
            item_remove($userid, $r['itmid'], $_POST['qty']);
            $db->query(
                    "UPDATE `users`
                     SET `money` = `money` + {$price}
                     WHERE `userid` = $userid");
            $priceh = money_formatter($price);
            echo 'You sold ' . $_POST['qty'] . ' ' . $r['itmname']
                    . '(s) for ' . $priceh;
            $is_log =
                    $db->escape(
                            "{$ir['username']} sold {$_POST['qty']} {$r['itmname']}(s) for {$priceh}");
            $db->query(
                    "INSERT INTO `itemselllogs`
                    VALUES (NULL, $userid, {$r['itmid']}, $price,
                    {$_POST['qty']}, " . time() . ", '{$is_log}')");
        }
    }
    $db->free_result($id);
}
else if (!empty($_GET['ID']) && empty($_POST['qty']))
{
    $id =
            $db->query(
                    "SELECT `inv_qty`, `itmname`
                     FROM `inventory` AS `iv`
                     INNER JOIN `items` AS `it`
                     ON `iv`.`inv_itemid` = `it`.`itmid`
                     WHERE `iv`.`inv_id` = {$_GET['ID']}
                     AND `iv`.`inv_userid` = {$userid}
                     LIMIT 1");
    if ($db->num_rows($id) == 0)
    {
        echo 'Invalid item ID';
    }
    else
    {
        $r = $db->fetch_row($id);
        $code = request_csrf_code("sellitem_{$_GET['ID']}");
        echo "
		<b>Enter how many {$r['itmname']} you want to sell. You have {$r['inv_qty']} to sell.</b>
		<br />
		<form action='?action=itemsell&ID={$_GET['ID']}' method='post'>
			<input type='hidden' name='verf' value='{$code}' />
			Quantity: <input type='text' name='qty' value='' />
			<br />
			<input type='submit' value='Sell Items (no prompt so be sure!' />
		</form>
   		";
    }
    $db->free_result($id);
}
else
{
    echo 'Invalid use of file.';
}
}


function itemsend() {
    global $db, $ir, $c, $userid, $h;
	$_GET['ID'] =
        (isset($_GET['ID']) && is_numeric($_GET['ID']))
                ? abs(intval($_GET['ID'])) : '';
$_POST['user'] =
        (isset($_POST['user']) && is_numeric($_POST['user']))
                ? abs(intval($_POST['user'])) : '';
$_POST['qty'] =
        (isset($_POST['qty']) && is_numeric($_POST['qty']))
                ? abs(intval($_POST['qty'])) : '';
if (!empty($_POST['qty']) && !empty($_POST['user']))
{
    $id =
            $db->query(
                    "SELECT `inv_qty`, `inv_itemid`, `itmname`, `itmid`
                     FROM `inventory` AS `iv`
                     INNER JOIN `items` AS `it`
                     ON `iv`.`inv_itemid` = `it`.`itmid`
                     WHERE `iv`.`inv_id` = {$_GET['ID']}
                     AND iv.`inv_userid` = {$userid}
                     LIMIT 1");
    if ($db->num_rows($id) == 0)
    {
        echo 'Invalid item ID';
    }
    else
    {
        $r = $db->fetch_row($id);
        $m =
                $db->query(
                        "SELECT `lastip`,`username`
                         FROM `users`
                         WHERE `userid` = {$_POST['user']}
                         LIMIT 1");
        if (!isset($_POST['verf'])
                || !verify_csrf_code("senditem_{$_GET['ID']}",
                        stripslashes($_POST['verf'])))
        {
            echo '<h3>Error</h3><hr />
   			This transaction has been blocked for your security.<br />
    		Please send items quickly after you open the form - do not leave it open in tabs.<br />
    		&gt; <a href="?action=itemsend&ID=' . $_GET['ID'] . '">Try Again</a>';
            die($h->endpage());
        }
        else if ($_POST['qty'] > $r['inv_qty'])
        {
            echo 'You are trying to send more than you have!';
        }
        else if ($db->num_rows($m) == 0)
        {
            echo 'You are trying to send to an invalid user!';
        }
        else
        {
            $rm = $db->fetch_row($m);
            item_remove($userid, $r['inv_itemid'], $_POST['qty']);
            item_add($_POST['user'], $r['inv_itemid'], $_POST['qty']);
            echo 'You sent ' . $_POST['qty'] . ' ' . $r['itmname'] . '(s) to '
                    . $rm['username'];
            event_add($_POST['user'],
                    "You received {$_POST['qty']} {$r['itmname']}(s) from <a href='viewuser.php?u=$userid'>{$ir['username']}</a>",
                    $c);
            $db->query(
                    "INSERT INTO `itemxferlogs`
                     VALUES(NULL, $userid, {$_POST['user']}, {$r['itmid']},
                     {$_POST['qty']}, " . time()
                            . ", '{$ir['lastip']}', '{$rm['lastip']}')");
        }
        $db->free_result($m);
    }
    $db->free_result($id);
}
else if (!empty($_GET['ID']))
{
    $id =
            $db->query(
                    "SELECT `inv_qty`, `itmname`
                     FROM `inventory` iv
                     INNER JOIN `items` AS `it`
                     ON `iv`.`inv_itemid` = `it`.`itmid`
                     WHERE `iv`.`inv_id` = {$_GET['ID']}
                     AND `iv`.`inv_userid` = $userid
                     LIMIT 1");
    if ($db->num_rows($id) == 0)
    {
        echo 'Invalid item ID';
    }
    else
    {
        $r = $db->fetch_row($id);
        $code = request_csrf_code("senditem_{$_GET['ID']}");
        echo "
		<b>Enter who you want to send {$r['itmname']} to and how many you want to send.
			You have {$r['inv_qty']} to send.</b>
		<br />
		<form action='?action=itemsend&ID={$_GET['ID']}' method='post'>
			User ID: <input type='text' name='user' value='' />
			<br />
			Quantity: <input type='text' name='qty' value='' />
			<br />
			<input type='hidden' name='verf' value='{$code}' />
			<input type='submit' value='Send Items (no prompt so be sure!' />
		</form>
   		";
    }
    $db->free_result($id);
}
else
{
    echo 'Invalid use of file.';
}
}


function iteminfo() {
    global $db, $ir, $c, $userid, $h;
$_GET['ID'] =
        (isset($_GET['ID']) && is_numeric($_GET['ID']))
                ? abs(intval($_GET['ID'])) : '';
$itmid = $_GET['ID'];
if (!$itmid)
{
    echo 'Invalid item ID';
}
else
{
    $q =
            $db->query(
                    "SELECT `itmname`, `itmdesc`, `itmbuyprice`,
                     `itmsellprice`, `itmtypename`
                     FROM `items` AS `i`
                     INNER JOIN `itemtypes` AS `it`
                     ON `i`.`itmtype` = `it`.`itmtypeid`
                     WHERE `i`.`itmid` = {$itmid}
                     LIMIT 1");
    if ($db->num_rows($q) == 0)
    {
        echo 'Invalid item ID';
    }
    else
    {
        $id = $db->fetch_row($q);
        echo "
<table width=75% class='table' cellspacing='1'>
		<tr style='background: gray;'>
	<th colspan=2><b>Looking up info on {$id['itmname']}</b></th>
		</tr>
		<tr style='background: #dfdfdf;'>
	<td colspan=2>The <b>{$id['itmname']}</b> is a/an {$id['itmtypename']} Item - <b>{$id['itmdesc']}</b></th>
		</tr>
	<tr style='background: gray;'>
	<th colspan=2>Item Info</th>
		</tr>
		<tr style='background:gray'>
	<th>Item Buy Price</th>
	<th>Item Sell Price</th>
		</tr>
		<tr>
	<td>
   ";
        if ($id['itmbuyprice'])
        {
            echo money_formatter($id['itmbuyprice']);
        }
        else
        {
            echo 'N/A';
        }
        echo '
	</td>
	<td>
   ';
        if ($id['itmsellprice'])
        {
            echo money_formatter($id['itmsellprice'])
                    . '
	</td>
		</tr>
</table>
   ';
        }
        else
        {
            echo '
N/A</td>
		</tr>
</table>
   ';
        }
    }
    $db->free_result($q);
}
}


function index() {
    global $db, $ir, $c, $userid, $h;
	$q =
        $db->query(
                "SELECT `itmid`, `itmname`
                 FROM `items`
                 WHERE `itmid`
                  IN({$ir['equip_primary']}, {$ir['equip_secondary']},
                     {$ir['equip_armor']})");
echo "<h3>Equipped Items</h3><hr />";
$equip = array();
while ($r = $db->fetch_row($q))
{
    $equip[$r['itmid']] = $r;
}
$db->free_result($q);
echo "<table width='75%' cellspacing='1' class='table'>
<tr>
<th>Primary Weapon</th>
<td>";
if (isset($equip[$ir['equip_primary']]))
{
    print
            $equip[$ir['equip_primary']]['itmname']
                    . "</td><td><a href='unequip.php?type=equip_primary'>Unequip Item</a></td>";
}
else
{
    echo "None equipped.</td><td>&nbsp;</td>";
}
echo "</tr>
<tr>
<th>Secondary Weapon</th>
<td>";
if (isset($equip[$ir['equip_secondary']]))
{
    print
            $equip[$ir['equip_secondary']]['itmname']
                    . "</td><td><a href='unequip.php?type=equip_secondary'>Unequip Item</a></td>";
}
else
{
    echo "None equipped.</td><td>&nbsp;</td>";
}
echo "</tr>
<tr>
<th>Armor</th>
<td>";
if (isset($equip[$ir['equip_armor']]))
{
    print
            $equip[$ir['equip_armor']]['itmname']
                    . "</td><td><a href='unequip.php?type=equip_armor'>Unequip Item</a></td>";
}
else
{
    echo "None equipped.</td><td>&nbsp;</td>";
}
echo "</tr>
</table><hr />
<h3>Inventory</h3><hr />";
$inv =
        $db->query(
                "SELECT `inv_qty`, `itmsellprice`, `itmid`, `inv_id`,
                 `effect1_on`, `effect2_on`, `effect3_on`, `itmname`,
                 `weapon`, `armor`, `itmtypename`
                 FROM `inventory` AS `iv`
                 INNER JOIN `items` AS `i`
                 ON `iv`.`inv_itemid` = `i`.`itmid`
                 INNER JOIN `itemtypes` AS `it`
                 ON `i`.`itmtype` = `it`.`itmtypeid`
                 WHERE `iv`.`inv_userid` = {$userid}
                 ORDER BY `i`.`itmtype` ASC, `i`.`itmname` ASC");
if ($db->num_rows($inv) == 0)
{
    echo "<b>You have no items!</b>";
}
else
{
    echo "<b>Your items are listed below.</b><br />
<table width=100% class=\"table\" border=\"0\" cellspacing=\"1\">
	<tr>
		<td class=\"h\">Item</td>
		<td class=\"h\">Sell Value</td>
		<td class=\"h\">Total Sell Value</td>
		<td class=\"h\">Links</td>
	</tr>";
    $lt = "";
    while ($i = $db->fetch_row($inv))
    {
        if ($lt != $i['itmtypename'])
        {
            $lt = $i['itmtypename'];
            echo "\n<tr>
            			<td colspan='4'>
            				<b>{$lt}</b>
            			</td>
            		</tr>";
        }
        if ($i['weapon'])
        {
            $i['itmname'] =
                    "<span style='color: red;'>*</span>" . $i['itmname'];
        }
        if ($i['armor'])
        {
            $i['itmname'] =
                    "<span style='color: green;'>*</span>" . $i['itmname'];
        }
        echo "<tr>
        		<td>{$i['itmname']}";
        if ($i['inv_qty'] > 1)
        {
            echo "&nbsp;x{$i['inv_qty']}";
        }
        echo "</td>
        	  <td>" . money_formatter($i['itmsellprice'])
                . "</td>
        	  <td>";
        echo money_formatter($i['itmsellprice'] * $i['inv_qty']);
        echo "</td>
        	  <td>
        	  	[<a href='?action=iteminfo&ID={$i['itmid']}'>Info</a>]
        	  	[<a href='?action=itemsend&ID={$i['inv_id']}'>Send</a>]
        	  	[<a href='?action=itemsell&ID={$i['inv_id']}'>Sell</a>]
        	  	[<a href='?action=imadd.php&ID={$i['inv_id']}'>Add To Market</a>]";
        if ($i['effect1_on'] || $i['effect2_on'] || $i['effect3_on'])
        {
            echo " [<a href='?action=itemuse&ID={$i['inv_id']}'>Use</a>]";
        }
        if ($i['weapon'] > 0)
        {
            echo " [<a href='equip_weapon.php?ID={$i['inv_id']}'>Equip as Weapon</a>]";
        }
        if ($i['armor'] > 0)
        {
            echo " [<a href='equip_armor.php?ID={$i['inv_id']}'>Equip as Armor</a>]";
        }
        echo "</td>
        </tr>";
    }
    echo "</table>";
    $db->free_result($inv);
    echo "<small><b>NB:</b> Items with a small red </small><span style='color: red;'>*</span><small> next to their name can be used as weapons in combat.<br />
Items with a small green </small><span style='color: green;'>*</span><small> next to their name can be used as armor in combat.</small>";
}
}


$h->endpage();

As Said, Untested, Using Default Mccodes from V2.0.6

  • Like 1
Link to comment
Share on other sites

1 hour ago, peterisgb said:

As Adam said, Its a odd thing to do. But hey, I'm Down. This is Untested.
 

<?php require_once('globals.php'); if (!isset($_GET['action'])) { $_GET['action'] = ''; } switch ($_GET['action']) { case 'iteminfo': iteminfo(); break; case 'itemsend': itemsend(); break; case 'itemsell': itemsell(); break; case 'imadd': imadd(); break; case 'itemuse': itemuse(); break; default: index(); break; } function itemuse(){ global $db, $ir, $c, $userid, $h; $_GET['ID'] = (isset($_GET['ID']) && is_numeric($_GET['ID'])) ? abs(intval($_GET['ID'])) : ''; if (!$_GET['ID']) { echo 'Invalid use of file'; } else { $i = $db->query( "SELECT `effect1`, `effect2`, `effect3`, `effect1_on`, `effect2_on`, `effect3_on`, `itmname`, `inv_itemid` FROM `inventory` AS `iv` INNER JOIN `items` AS `i` ON `iv`.`inv_itemid` = `i`.`itmid` WHERE `iv`.`inv_id` = {$_GET['ID']} AND `iv`.`inv_userid` = $userid"); if ($db->num_rows($i) == 0) { $db->free_result($i); echo 'Invalid item ID'; } else { $r = $db->fetch_row($i); $db->free_result($i); if (!$r['effect1_on'] && !$r['effect2_on'] && !$r['effect3_on']) { echo 'Sorry, this item cannot be used as it has no effect.'; die($h->endpage()); } for ($enum = 1; $enum <= 3; $enum++) { if ($r["effect{$enum}_on"]) { $einfo = unserialize($r["effect{$enum}"]); if ($einfo['inc_type'] == "percent") { if (in_array($einfo['stat'], array('energy', 'will', 'brave', 'hp'))) { $inc = round( $ir['max' . $einfo['stat']] / 100 * $einfo['inc_amount']); } else { $inc = round( $ir[$einfo['stat']] / 100 * $einfo['inc_amount']); } } else { $inc = $einfo['inc_amount']; } if ($einfo['dir'] == "pos") { if (in_array($einfo['stat'], array('energy', 'will', 'brave', 'hp'))) { $ir[$einfo['stat']] = min($ir[$einfo['stat']] + $inc, $ir['max' . $einfo['stat']]); } else { $ir[$einfo['stat']] += $inc; } } else { $ir[$einfo['stat']] = max($ir[$einfo['stat']] - $inc, 0); } $upd = $ir[$einfo['stat']]; if (in_array($einfo['stat'], array('strength', 'agility', 'guard', 'labour', 'IQ'))) { $db->query( "UPDATE `userstats` SET `{$einfo['stat']}` = '{$upd}' WHERE `userid` = {$userid}"); } else { $db->query( "UPDATE `users` SET `{$einfo['stat']}` = '{$upd}' WHERE `userid` = {$userid}"); } } } echo $r['itmname'] . ' used successfully!'; item_remove($userid, $r['inv_itemid'], 1); } } } function imadd() { global $db, $ir, $c, $userid, $h; $_GET['ID'] = (isset($_GET['ID']) && is_numeric($_GET['ID'])) ? abs(intval($_GET['ID'])) : ''; $_POST['price'] = (isset($_POST['price']) && is_numeric($_POST['price'])) ? abs(intval($_POST['price'])) : ''; $_POST['QTY'] = (isset($_POST['QTY']) && is_numeric($_POST['QTY'])) ? abs(intval($_POST['QTY'])) : ''; $_POST['currency'] = (isset($_POST['currency']) && in_array($_POST['currency'], array('money', 'crystals'))) ? $_POST['currency'] : 'money'; if ($_POST['price'] && $_POST['QTY'] && $_GET['ID']) { if (!isset($_POST['verf']) || !verify_csrf_code("imadd_{$_GET['ID']}", stripslashes($_POST['verf']))) { echo "Your request to add this item to the market has expired. Please try again.<br /> &gt; <a href='?action=imadd&ID={$_GET['ID']}'>Back</a>"; die($h->endpage()); } $q = $db->query( "SELECT `inv_qty`, `inv_itemid`, `inv_id`, `itmname` FROM `inventory` AS `iv` INNER JOIN `items` AS `i` ON `iv`.`inv_itemid` = `i`.`itmid` WHERE `inv_id` = {$_GET['ID']} AND `inv_userid` = $userid"); if ($db->num_rows($q) == 0) { $db->free_result($q); echo "Invalid Item ID"; } else { $r = $db->fetch_row($q); $db->free_result($q); if ($r['inv_qty'] < $_POST['QTY']) { echo 'You do not have enough of this item.'; $h->endpage(); exit; } $checkq = sprintf( 'SELECT `imID` FROM `itemmarket` WHERE `imITEM` = %u AND `imPRICE` = %u AND `imADDER` = %u AND `imCURRENCY` = "%s"', $r['inv_itemid'], $_POST['price'], $userid, $_POST['currency']); $checkq = $db->query($checkq); if ($db->num_rows($checkq) > 0) { $cqty = $db->fetch_row($checkq); $query = sprintf( 'UPDATE `itemmarket` SET imQTY = imQTY + %u WHERE imID = %u', $_POST['QTY'], $cqty['imID']); $db->query($query); } else { $db->query( "INSERT INTO `itemmarket` VALUES (NULL, '{$r['inv_itemid']}', {$userid}, {$_POST['price']}, '{$_POST['currency']}', {$_POST['QTY']})"); } $db->free_result($checkq); item_remove($userid, $r['inv_itemid'], $_POST['QTY']); $imadd_log = $db->escape( "{$ir['username']} added {$r['itmname']} " . "x{$_POST['QTY']} to the item market for " . "{$_POST['price']} {$_POST['currency']}"); $db->query( "INSERT INTO `imarketaddlogs` VALUES (NULL, {$r['inv_itemid']}, {$_POST['price']}, {$r['inv_id']}, $userid, " . time() . ", '{$imadd_log}')"); echo "Item added to market."; } } else { $q = $db->query( "SELECT COUNT(`inv_id`) FROM `inventory` WHERE `inv_id` = {$_GET['ID']} AND `inv_userid` = $userid"); if ($db->fetch_single($q) == 0) { echo 'Invalid Item ID'; } else { $imadd_csrf = request_csrf_code("imadd_{$_GET['ID']}"); echo " Adding an item to the item market...<br /> <form action='?action=imadd&ID={$_GET['ID']}' method='post'> <input type='hidden' name='verf' value='{$imadd_csrf}' /> Quantity: <input type='text' name='QTY' value=''><br /> Price: <input type='text' name='price' value='0' /><br /> <select name='currency' type='dropdown'> <option value='money'>Money</option> <option value='crystals'>Crystals</option> </select><br /> <input type='submit' value='Add' /> </form> "; } $db->free_result($q); } } function itemsell() { global $db, $ir, $c, $userid, $h; $_GET['ID'] = (isset($_GET['ID']) && is_numeric($_GET['ID'])) ? abs(intval($_GET['ID'])) : ''; $_POST['qty'] = (isset($_POST['qty']) && is_numeric($_POST['qty'])) ? abs(intval($_POST['qty'])) : ''; if (!empty($_POST['qty']) && !empty($_GET['ID'])) { $id = $db->query( "SELECT `inv_qty`, `itmsellprice`, `itmid`, `itmname` FROM `inventory` AS `iv` INNER JOIN `items` AS `it` ON `iv`.`inv_itemid` = `it`.`itmid` WHERE `iv`.`inv_id` = {$_GET['ID']} AND `iv`.`inv_userid` = {$userid} LIMIT 1"); if ($db->num_rows($id) == 0) { echo 'Invalid item ID'; } else { $r = $db->fetch_row($id); if (!isset($_POST['verf']) || !verify_csrf_code("sellitem_{$_GET['ID']}", stripslashes($_POST['verf']))) { echo '<h3>Error</h3><hr /> This transaction has been blocked for your security.<br /> Please sell items quickly after you open the form - do not leave it open in tabs.<br /> &gt; <a href="itemsell.php?ID=' . $_GET['ID'] . '">Try Again</a>'; die($h->endpage()); } if ($_POST['qty'] > $r['inv_qty']) { echo 'You are trying to sell more than you have!'; } else { $price = $r['itmsellprice'] * $_POST['qty']; item_remove($userid, $r['itmid'], $_POST['qty']); $db->query( "UPDATE `users` SET `money` = `money` + {$price} WHERE `userid` = $userid"); $priceh = money_formatter($price); echo 'You sold ' . $_POST['qty'] . ' ' . $r['itmname'] . '(s) for ' . $priceh; $is_log = $db->escape( "{$ir['username']} sold {$_POST['qty']} {$r['itmname']}(s) for {$priceh}"); $db->query( "INSERT INTO `itemselllogs` VALUES (NULL, $userid, {$r['itmid']}, $price, {$_POST['qty']}, " . time() . ", '{$is_log}')"); } } $db->free_result($id); } else if (!empty($_GET['ID']) && empty($_POST['qty'])) { $id = $db->query( "SELECT `inv_qty`, `itmname` FROM `inventory` AS `iv` INNER JOIN `items` AS `it` ON `iv`.`inv_itemid` = `it`.`itmid` WHERE `iv`.`inv_id` = {$_GET['ID']} AND `iv`.`inv_userid` = {$userid} LIMIT 1"); if ($db->num_rows($id) == 0) { echo 'Invalid item ID'; } else { $r = $db->fetch_row($id); $code = request_csrf_code("sellitem_{$_GET['ID']}"); echo " <b>Enter how many {$r['itmname']} you want to sell. You have {$r['inv_qty']} to sell.</b> <br /> <form action='?action=itemsell&ID={$_GET['ID']}' method='post'> <input type='hidden' name='verf' value='{$code}' /> Quantity: <input type='text' name='qty' value='' /> <br /> <input type='submit' value='Sell Items (no prompt so be sure!' /> </form> "; } $db->free_result($id); } else { echo 'Invalid use of file.'; } } function itemsend() { global $db, $ir, $c, $userid, $h; $_GET['ID'] = (isset($_GET['ID']) && is_numeric($_GET['ID'])) ? abs(intval($_GET['ID'])) : ''; $_POST['user'] = (isset($_POST['user']) && is_numeric($_POST['user'])) ? abs(intval($_POST['user'])) : ''; $_POST['qty'] = (isset($_POST['qty']) && is_numeric($_POST['qty'])) ? abs(intval($_POST['qty'])) : ''; if (!empty($_POST['qty']) && !empty($_POST['user'])) { $id = $db->query( "SELECT `inv_qty`, `inv_itemid`, `itmname`, `itmid` FROM `inventory` AS `iv` INNER JOIN `items` AS `it` ON `iv`.`inv_itemid` = `it`.`itmid` WHERE `iv`.`inv_id` = {$_GET['ID']} AND iv.`inv_userid` = {$userid} LIMIT 1"); if ($db->num_rows($id) == 0) { echo 'Invalid item ID'; } else { $r = $db->fetch_row($id); $m = $db->query( "SELECT `lastip`,`username` FROM `users` WHERE `userid` = {$_POST['user']} LIMIT 1"); if (!isset($_POST['verf']) || !verify_csrf_code("senditem_{$_GET['ID']}", stripslashes($_POST['verf']))) { echo '<h3>Error</h3><hr /> This transaction has been blocked for your security.<br /> Please send items quickly after you open the form - do not leave it open in tabs.<br /> &gt; <a href="?action=itemsend&ID=' . $_GET['ID'] . '">Try Again</a>'; die($h->endpage()); } else if ($_POST['qty'] > $r['inv_qty']) { echo 'You are trying to send more than you have!'; } else if ($db->num_rows($m) == 0) { echo 'You are trying to send to an invalid user!'; } else { $rm = $db->fetch_row($m); item_remove($userid, $r['inv_itemid'], $_POST['qty']); item_add($_POST['user'], $r['inv_itemid'], $_POST['qty']); echo 'You sent ' . $_POST['qty'] . ' ' . $r['itmname'] . '(s) to ' . $rm['username']; event_add($_POST['user'], "You received {$_POST['qty']} {$r['itmname']}(s) from <a href='viewuser.php?u=$userid'>{$ir['username']}</a>", $c); $db->query( "INSERT INTO `itemxferlogs` VALUES(NULL, $userid, {$_POST['user']}, {$r['itmid']}, {$_POST['qty']}, " . time() . ", '{$ir['lastip']}', '{$rm['lastip']}')"); } $db->free_result($m); } $db->free_result($id); } else if (!empty($_GET['ID'])) { $id = $db->query( "SELECT `inv_qty`, `itmname` FROM `inventory` iv INNER JOIN `items` AS `it` ON `iv`.`inv_itemid` = `it`.`itmid` WHERE `iv`.`inv_id` = {$_GET['ID']} AND `iv`.`inv_userid` = $userid LIMIT 1"); if ($db->num_rows($id) == 0) { echo 'Invalid item ID'; } else { $r = $db->fetch_row($id); $code = request_csrf_code("senditem_{$_GET['ID']}"); echo " <b>Enter who you want to send {$r['itmname']} to and how many you want to send. You have {$r['inv_qty']} to send.</b> <br /> <form action='?action=itemsend&ID={$_GET['ID']}' method='post'> User ID: <input type='text' name='user' value='' /> <br /> Quantity: <input type='text' name='qty' value='' /> <br /> <input type='hidden' name='verf' value='{$code}' /> <input type='submit' value='Send Items (no prompt so be sure!' /> </form> "; } $db->free_result($id); } else { echo 'Invalid use of file.'; } } function iteminfo() { global $db, $ir, $c, $userid, $h; $_GET['ID'] = (isset($_GET['ID']) && is_numeric($_GET['ID'])) ? abs(intval($_GET['ID'])) : ''; $itmid = $_GET['ID']; if (!$itmid) { echo 'Invalid item ID'; } else { $q = $db->query( "SELECT `itmname`, `itmdesc`, `itmbuyprice`, `itmsellprice`, `itmtypename` FROM `items` AS `i` INNER JOIN `itemtypes` AS `it` ON `i`.`itmtype` = `it`.`itmtypeid` WHERE `i`.`itmid` = {$itmid} LIMIT 1"); if ($db->num_rows($q) == 0) { echo 'Invalid item ID'; } else { $id = $db->fetch_row($q); echo " <table width=75% class='table' cellspacing='1'> <tr style='background: gray;'> <th colspan=2><b>Looking up info on {$id['itmname']}</b></th> </tr> <tr style='background: #dfdfdf;'> <td colspan=2>The <b>{$id['itmname']}</b> is a/an {$id['itmtypename']} Item - <b>{$id['itmdesc']}</b></th> </tr> <tr style='background: gray;'> <th colspan=2>Item Info</th> </tr> <tr style='background:gray'> <th>Item Buy Price</th> <th>Item Sell Price</th> </tr> <tr> <td> "; if ($id['itmbuyprice']) { echo money_formatter($id['itmbuyprice']); } else { echo 'N/A'; } echo ' </td> <td> '; if ($id['itmsellprice']) { echo money_formatter($id['itmsellprice']) . ' </td> </tr> </table> '; } else { echo ' N/A</td> </tr> </table> '; } } $db->free_result($q); } } function index() { global $db, $ir, $c, $userid, $h; $q = $db->query( "SELECT `itmid`, `itmname` FROM `items` WHERE `itmid` IN({$ir['equip_primary']}, {$ir['equip_secondary']}, {$ir['equip_armor']})"); echo "<h3>Equipped Items</h3><hr />"; $equip = array(); while ($r = $db->fetch_row($q)) { $equip[$r['itmid']] = $r; } $db->free_result($q); echo "<table width='75%' cellspacing='1' class='table'> <tr> <th>Primary Weapon</th> <td>"; if (isset($equip[$ir['equip_primary']])) { print $equip[$ir['equip_primary']]['itmname'] . "</td><td><a href='unequip.php?type=equip_primary'>Unequip Item</a></td>"; } else { echo "None equipped.</td><td>&nbsp;</td>"; } echo "</tr> <tr> <th>Secondary Weapon</th> <td>"; if (isset($equip[$ir['equip_secondary']])) { print $equip[$ir['equip_secondary']]['itmname'] . "</td><td><a href='unequip.php?type=equip_secondary'>Unequip Item</a></td>"; } else { echo "None equipped.</td><td>&nbsp;</td>"; } echo "</tr> <tr> <th>Armor</th> <td>"; if (isset($equip[$ir['equip_armor']])) { print $equip[$ir['equip_armor']]['itmname'] . "</td><td><a href='unequip.php?type=equip_armor'>Unequip Item</a></td>"; } else { echo "None equipped.</td><td>&nbsp;</td>"; } echo "</tr> </table><hr /> <h3>Inventory</h3><hr />"; $inv = $db->query( "SELECT `inv_qty`, `itmsellprice`, `itmid`, `inv_id`, `effect1_on`, `effect2_on`, `effect3_on`, `itmname`, `weapon`, `armor`, `itmtypename` FROM `inventory` AS `iv` INNER JOIN `items` AS `i` ON `iv`.`inv_itemid` = `i`.`itmid` INNER JOIN `itemtypes` AS `it` ON `i`.`itmtype` = `it`.`itmtypeid` WHERE `iv`.`inv_userid` = {$userid} ORDER BY `i`.`itmtype` ASC, `i`.`itmname` ASC"); if ($db->num_rows($inv) == 0) { echo "<b>You have no items!</b>"; } else { echo "<b>Your items are listed below.</b><br /> <table width=100% class=\"table\" border=\"0\" cellspacing=\"1\"> <tr> <td class=\"h\">Item</td> <td class=\"h\">Sell Value</td> <td class=\"h\">Total Sell Value</td> <td class=\"h\">Links</td> </tr>"; $lt = ""; while ($i = $db->fetch_row($inv)) { if ($lt != $i['itmtypename']) { $lt = $i['itmtypename']; echo "\n<tr> <td colspan='4'> <b>{$lt}</b> </td> </tr>"; } if ($i['weapon']) { $i['itmname'] = "<span style='color: red;'>*</span>" . $i['itmname']; } if ($i['armor']) { $i['itmname'] = "<span style='color: green;'>*</span>" . $i['itmname']; } echo "<tr> <td>{$i['itmname']}"; if ($i['inv_qty'] > 1) { echo "&nbsp;x{$i['inv_qty']}"; } echo "</td> <td>" . money_formatter($i['itmsellprice']) . "</td> <td>"; echo money_formatter($i['itmsellprice'] * $i['inv_qty']); echo "</td> <td> [<a href='?action=iteminfo&ID={$i['itmid']}'>Info</a>] [<a href='?action=itemsend&ID={$i['inv_id']}'>Send</a>] [<a href='?action=itemsell&ID={$i['inv_id']}'>Sell</a>] [<a href='?action=imadd.php&ID={$i['inv_id']}'>Add To Market</a>]"; if ($i['effect1_on'] || $i['effect2_on'] || $i['effect3_on']) { echo " [<a href='?action=itemuse&ID={$i['inv_id']}'>Use</a>]"; } if ($i['weapon'] > 0) { echo " [<a href='equip_weapon.php?ID={$i['inv_id']}'>Equip as Weapon</a>]"; } if ($i['armor'] > 0) { echo " [<a href='equip_armor.php?ID={$i['inv_id']}'>Equip as Armor</a>]"; } echo "</td> </tr>"; } echo "</table>"; $db->free_result($inv); echo "<small><b>NB:</b> Items with a small red </small><span style='color: red;'>*</span><small> next to their name can be used as weapons in combat.<br /> Items with a small green </small><span style='color: green;'>*</span><small> next to their name can be used as armor in combat.</small>"; } } $h->endpage();

<?php
require_once('globals.php');
if (!isset($_GET['action'])) {
    $_GET['action'] = '';
}
switch ($_GET['action']) {
case 'iteminfo': iteminfo(); break;
case 'itemsend': itemsend(); break;
case 'itemsell': itemsell(); break;
case 'imadd': imadd(); break;
case 'itemuse': itemuse(); break;
default: index(); break;
}



function itemuse(){
	global $db, $ir, $c, $userid, $h;
	$_GET['ID'] =
        (isset($_GET['ID']) && is_numeric($_GET['ID']))
                ? abs(intval($_GET['ID'])) : '';
if (!$_GET['ID'])
{
    echo 'Invalid use of file';
}
else
{
    $i =
            $db->query(
                    "SELECT `effect1`, `effect2`, `effect3`,
                     `effect1_on`, `effect2_on`, `effect3_on`,
                     `itmname`, `inv_itemid`
                     FROM `inventory` AS `iv`
                     INNER JOIN `items` AS `i`
                     ON `iv`.`inv_itemid` = `i`.`itmid`
                     WHERE `iv`.`inv_id` = {$_GET['ID']}
                     AND `iv`.`inv_userid` = $userid");
    if ($db->num_rows($i) == 0)
    {
        $db->free_result($i);
        echo 'Invalid item ID';
    }
    else
    {
        $r = $db->fetch_row($i);
        $db->free_result($i);
        if (!$r['effect1_on'] && !$r['effect2_on'] && !$r['effect3_on'])
        {
            echo 'Sorry, this item cannot be used as it has no effect.';
            die($h->endpage());
        }
        for ($enum = 1; $enum <= 3; $enum++)
        {
            if ($r["effect{$enum}_on"])
            {
                $einfo = unserialize($r["effect{$enum}"]);
                if ($einfo['inc_type'] == "percent")
                {
                    if (in_array($einfo['stat'],
                            array('energy', 'will', 'brave', 'hp')))
                    {
                        $inc =
                                round(
                                        $ir['max' . $einfo['stat']] / 100
                                                * $einfo['inc_amount']);
                    }
                    else
                    {
                        $inc =
                                round(
                                        $ir[$einfo['stat']] / 100
                                                * $einfo['inc_amount']);
                    }
                }
                else
                {
                    $inc = $einfo['inc_amount'];
                }
                if ($einfo['dir'] == "pos")
                {
                    if (in_array($einfo['stat'],
                            array('energy', 'will', 'brave', 'hp')))
                    {
                        $ir[$einfo['stat']] =
                                min($ir[$einfo['stat']] + $inc,
                                        $ir['max' . $einfo['stat']]);
                    }
                    else
                    {
                        $ir[$einfo['stat']] += $inc;
                    }
                }
                else
                {
                    $ir[$einfo['stat']] = max($ir[$einfo['stat']] - $inc, 0);
                }
                $upd = $ir[$einfo['stat']];
                if (in_array($einfo['stat'],
                        array('strength', 'agility', 'guard', 'labour', 'IQ')))
                {
                    $db->query(
                            "UPDATE `userstats`
                             SET `{$einfo['stat']}` = '{$upd}'
                             WHERE `userid` = {$userid}");
                }
                else
                {
                    $db->query(
                            "UPDATE `users`
                             SET `{$einfo['stat']}` = '{$upd}'
                             WHERE `userid` = {$userid}");
                }
            }
        }
        echo $r['itmname'] . ' used successfully!';
        item_remove($userid, $r['inv_itemid'], 1);
    }
}
}


function imadd() {
    global $db, $ir, $c, $userid, $h;
	$_GET['ID'] =
        (isset($_GET['ID']) && is_numeric($_GET['ID']))
                ? abs(intval($_GET['ID'])) : '';
$_POST['price'] =
        (isset($_POST['price']) && is_numeric($_POST['price']))
                ? abs(intval($_POST['price'])) : '';
$_POST['QTY'] =
        (isset($_POST['QTY']) && is_numeric($_POST['QTY']))
                ? abs(intval($_POST['QTY'])) : '';
$_POST['currency'] =
        (isset($_POST['currency'])
                && in_array($_POST['currency'], array('money', 'crystals')))
                ? $_POST['currency'] : 'money';
if ($_POST['price'] && $_POST['QTY'] && $_GET['ID'])
{
    if (!isset($_POST['verf'])
            || !verify_csrf_code("imadd_{$_GET['ID']}",
                    stripslashes($_POST['verf'])))
    {
        echo "Your request to add this item to the market has expired.
        Please try again.<br />
		&gt; <a href='?action=imadd&ID={$_GET['ID']}'>Back</a>";
        die($h->endpage());
    }
    $q =
            $db->query(
                    "SELECT `inv_qty`, `inv_itemid`, `inv_id`, `itmname`
                     FROM `inventory` AS `iv`
                     INNER JOIN `items` AS `i`
                     ON `iv`.`inv_itemid` = `i`.`itmid`
                     WHERE `inv_id` = {$_GET['ID']}
                     AND `inv_userid` = $userid");
    if ($db->num_rows($q) == 0)
    {
        $db->free_result($q);
        echo "Invalid Item ID";
    }
    else
    {
        $r = $db->fetch_row($q);
        $db->free_result($q);
        if ($r['inv_qty'] < $_POST['QTY'])
        {
            echo 'You do not have enough of this item.';
            $h->endpage();
            exit;
        }
        $checkq =
                sprintf(
                        'SELECT `imID`
                         FROM `itemmarket`
                         WHERE `imITEM` = %u AND `imPRICE` = %u
                         AND `imADDER` = %u AND `imCURRENCY` = "%s"',
                        $r['inv_itemid'], $_POST['price'], $userid,
                        $_POST['currency']);
        $checkq = $db->query($checkq);
        if ($db->num_rows($checkq) > 0)
        {
            $cqty = $db->fetch_row($checkq);
            $query =
                    sprintf(
                            'UPDATE `itemmarket`
                             SET imQTY = imQTY + %u
                             WHERE imID = %u', $_POST['QTY'], $cqty['imID']);
            $db->query($query);
        }
        else
        {
            $db->query(
                    "INSERT INTO `itemmarket`
                     VALUES (NULL, '{$r['inv_itemid']}', {$userid},
                     {$_POST['price']}, '{$_POST['currency']}',
                     {$_POST['QTY']})");
        }
        $db->free_result($checkq);
        item_remove($userid, $r['inv_itemid'], $_POST['QTY']);
        $imadd_log =
                $db->escape(
                        "{$ir['username']} added {$r['itmname']} "
                                . "x{$_POST['QTY']} to the item market for "
                                . "{$_POST['price']} {$_POST['currency']}");
        $db->query(
                "INSERT INTO `imarketaddlogs`
                VALUES (NULL, {$r['inv_itemid']}, {$_POST['price']},
                {$r['inv_id']}, $userid, " . time() . ", '{$imadd_log}')");
        echo "Item added to market.";
    }
}
else
{
    $q =
            $db->query(
                    "SELECT COUNT(`inv_id`)
                     FROM `inventory`
                     WHERE `inv_id` = {$_GET['ID']}
                     AND `inv_userid` = $userid");
    if ($db->fetch_single($q) == 0)
    {
        echo 'Invalid Item ID';
    }
    else
    {
        $imadd_csrf = request_csrf_code("imadd_{$_GET['ID']}");
        echo "
Adding an item to the item market...<br />
	<form action='?action=imadd&ID={$_GET['ID']}' method='post'>
	<input type='hidden' name='verf' value='{$imadd_csrf}' />
		Quantity: <input type='text' name='QTY' value=''><br />
		Price: <input type='text' name='price' value='0' /><br />
	<select name='currency' type='dropdown'>
		<option value='money'>Money</option>
		<option value='crystals'>Crystals</option>
	</select><br />
		<input type='submit' value='Add' />
	</form>
   ";
    }
    $db->free_result($q);
}
}


function itemsell() {
    global $db, $ir, $c, $userid, $h;
	$_GET['ID'] =
        (isset($_GET['ID']) && is_numeric($_GET['ID']))
                ? abs(intval($_GET['ID'])) : '';
$_POST['qty'] =
        (isset($_POST['qty']) && is_numeric($_POST['qty']))
                ? abs(intval($_POST['qty'])) : '';
if (!empty($_POST['qty']) && !empty($_GET['ID']))
{
    $id =
            $db->query(
                    "SELECT `inv_qty`, `itmsellprice`, `itmid`, `itmname`
                     FROM `inventory` AS `iv`
                     INNER JOIN `items` AS `it`
                     ON `iv`.`inv_itemid` = `it`.`itmid`
                     WHERE `iv`.`inv_id` = {$_GET['ID']}
                     AND `iv`.`inv_userid` = {$userid}
                     LIMIT 1");
    if ($db->num_rows($id) == 0)
    {
        echo 'Invalid item ID';
    }
    else
    {
        $r = $db->fetch_row($id);
        if (!isset($_POST['verf'])
                || !verify_csrf_code("sellitem_{$_GET['ID']}",
                        stripslashes($_POST['verf'])))
        {
            echo '<h3>Error</h3><hr />
    		This transaction has been blocked for your security.<br />
    		Please sell items quickly after you open the form - do not leave it open in tabs.<br />
    		&gt; <a href="itemsell.php?ID=' . $_GET['ID'] . '">Try Again</a>';
            die($h->endpage());
        }
        if ($_POST['qty'] > $r['inv_qty'])
        {
            echo 'You are trying to sell more than you have!';
        }
        else
        {
            $price = $r['itmsellprice'] * $_POST['qty'];
            item_remove($userid, $r['itmid'], $_POST['qty']);
            $db->query(
                    "UPDATE `users`
                     SET `money` = `money` + {$price}
                     WHERE `userid` = $userid");
            $priceh = money_formatter($price);
            echo 'You sold ' . $_POST['qty'] . ' ' . $r['itmname']
                    . '(s) for ' . $priceh;
            $is_log =
                    $db->escape(
                            "{$ir['username']} sold {$_POST['qty']} {$r['itmname']}(s) for {$priceh}");
            $db->query(
                    "INSERT INTO `itemselllogs`
                    VALUES (NULL, $userid, {$r['itmid']}, $price,
                    {$_POST['qty']}, " . time() . ", '{$is_log}')");
        }
    }
    $db->free_result($id);
}
else if (!empty($_GET['ID']) && empty($_POST['qty']))
{
    $id =
            $db->query(
                    "SELECT `inv_qty`, `itmname`
                     FROM `inventory` AS `iv`
                     INNER JOIN `items` AS `it`
                     ON `iv`.`inv_itemid` = `it`.`itmid`
                     WHERE `iv`.`inv_id` = {$_GET['ID']}
                     AND `iv`.`inv_userid` = {$userid}
                     LIMIT 1");
    if ($db->num_rows($id) == 0)
    {
        echo 'Invalid item ID';
    }
    else
    {
        $r = $db->fetch_row($id);
        $code = request_csrf_code("sellitem_{$_GET['ID']}");
        echo "
		<b>Enter how many {$r['itmname']} you want to sell. You have {$r['inv_qty']} to sell.</b>
		<br />
		<form action='?action=itemsell&ID={$_GET['ID']}' method='post'>
			<input type='hidden' name='verf' value='{$code}' />
			Quantity: <input type='text' name='qty' value='' />
			<br />
			<input type='submit' value='Sell Items (no prompt so be sure!' />
		</form>
   		";
    }
    $db->free_result($id);
}
else
{
    echo 'Invalid use of file.';
}
}


function itemsend() {
    global $db, $ir, $c, $userid, $h;
	$_GET['ID'] =
        (isset($_GET['ID']) && is_numeric($_GET['ID']))
                ? abs(intval($_GET['ID'])) : '';
$_POST['user'] =
        (isset($_POST['user']) && is_numeric($_POST['user']))
                ? abs(intval($_POST['user'])) : '';
$_POST['qty'] =
        (isset($_POST['qty']) && is_numeric($_POST['qty']))
                ? abs(intval($_POST['qty'])) : '';
if (!empty($_POST['qty']) && !empty($_POST['user']))
{
    $id =
            $db->query(
                    "SELECT `inv_qty`, `inv_itemid`, `itmname`, `itmid`
                     FROM `inventory` AS `iv`
                     INNER JOIN `items` AS `it`
                     ON `iv`.`inv_itemid` = `it`.`itmid`
                     WHERE `iv`.`inv_id` = {$_GET['ID']}
                     AND iv.`inv_userid` = {$userid}
                     LIMIT 1");
    if ($db->num_rows($id) == 0)
    {
        echo 'Invalid item ID';
    }
    else
    {
        $r = $db->fetch_row($id);
        $m =
                $db->query(
                        "SELECT `lastip`,`username`
                         FROM `users`
                         WHERE `userid` = {$_POST['user']}
                         LIMIT 1");
        if (!isset($_POST['verf'])
                || !verify_csrf_code("senditem_{$_GET['ID']}",
                        stripslashes($_POST['verf'])))
        {
            echo '<h3>Error</h3><hr />
   			This transaction has been blocked for your security.<br />
    		Please send items quickly after you open the form - do not leave it open in tabs.<br />
    		&gt; <a href="?action=itemsend&ID=' . $_GET['ID'] . '">Try Again</a>';
            die($h->endpage());
        }
        else if ($_POST['qty'] > $r['inv_qty'])
        {
            echo 'You are trying to send more than you have!';
        }
        else if ($db->num_rows($m) == 0)
        {
            echo 'You are trying to send to an invalid user!';
        }
        else
        {
            $rm = $db->fetch_row($m);
            item_remove($userid, $r['inv_itemid'], $_POST['qty']);
            item_add($_POST['user'], $r['inv_itemid'], $_POST['qty']);
            echo 'You sent ' . $_POST['qty'] . ' ' . $r['itmname'] . '(s) to '
                    . $rm['username'];
            event_add($_POST['user'],
                    "You received {$_POST['qty']} {$r['itmname']}(s) from <a href='viewuser.php?u=$userid'>{$ir['username']}</a>",
                    $c);
            $db->query(
                    "INSERT INTO `itemxferlogs`
                     VALUES(NULL, $userid, {$_POST['user']}, {$r['itmid']},
                     {$_POST['qty']}, " . time()
                            . ", '{$ir['lastip']}', '{$rm['lastip']}')");
        }
        $db->free_result($m);
    }
    $db->free_result($id);
}
else if (!empty($_GET['ID']))
{
    $id =
            $db->query(
                    "SELECT `inv_qty`, `itmname`
                     FROM `inventory` iv
                     INNER JOIN `items` AS `it`
                     ON `iv`.`inv_itemid` = `it`.`itmid`
                     WHERE `iv`.`inv_id` = {$_GET['ID']}
                     AND `iv`.`inv_userid` = $userid
                     LIMIT 1");
    if ($db->num_rows($id) == 0)
    {
        echo 'Invalid item ID';
    }
    else
    {
        $r = $db->fetch_row($id);
        $code = request_csrf_code("senditem_{$_GET['ID']}");
        echo "
		<b>Enter who you want to send {$r['itmname']} to and how many you want to send.
			You have {$r['inv_qty']} to send.</b>
		<br />
		<form action='?action=itemsend&ID={$_GET['ID']}' method='post'>
			User ID: <input type='text' name='user' value='' />
			<br />
			Quantity: <input type='text' name='qty' value='' />
			<br />
			<input type='hidden' name='verf' value='{$code}' />
			<input type='submit' value='Send Items (no prompt so be sure!' />
		</form>
   		";
    }
    $db->free_result($id);
}
else
{
    echo 'Invalid use of file.';
}
}


function iteminfo() {
    global $db, $ir, $c, $userid, $h;
$_GET['ID'] =
        (isset($_GET['ID']) && is_numeric($_GET['ID']))
                ? abs(intval($_GET['ID'])) : '';
$itmid = $_GET['ID'];
if (!$itmid)
{
    echo 'Invalid item ID';
}
else
{
    $q =
            $db->query(
                    "SELECT `itmname`, `itmdesc`, `itmbuyprice`,
                     `itmsellprice`, `itmtypename`
                     FROM `items` AS `i`
                     INNER JOIN `itemtypes` AS `it`
                     ON `i`.`itmtype` = `it`.`itmtypeid`
                     WHERE `i`.`itmid` = {$itmid}
                     LIMIT 1");
    if ($db->num_rows($q) == 0)
    {
        echo 'Invalid item ID';
    }
    else
    {
        $id = $db->fetch_row($q);
        echo "
<table width=75% class='table' cellspacing='1'>
		<tr style='background: gray;'>
	<th colspan=2><b>Looking up info on {$id['itmname']}</b></th>
		</tr>
		<tr style='background: #dfdfdf;'>
	<td colspan=2>The <b>{$id['itmname']}</b> is a/an {$id['itmtypename']} Item - <b>{$id['itmdesc']}</b></th>
		</tr>
	<tr style='background: gray;'>
	<th colspan=2>Item Info</th>
		</tr>
		<tr style='background:gray'>
	<th>Item Buy Price</th>
	<th>Item Sell Price</th>
		</tr>
		<tr>
	<td>
   ";
        if ($id['itmbuyprice'])
        {
            echo money_formatter($id['itmbuyprice']);
        }
        else
        {
            echo 'N/A';
        }
        echo '
	</td>
	<td>
   ';
        if ($id['itmsellprice'])
        {
            echo money_formatter($id['itmsellprice'])
                    . '
	</td>
		</tr>
</table>
   ';
        }
        else
        {
            echo '
N/A</td>
		</tr>
</table>
   ';
        }
    }
    $db->free_result($q);
}
}


function index() {
    global $db, $ir, $c, $userid, $h;
	$q =
        $db->query(
                "SELECT `itmid`, `itmname`
                 FROM `items`
                 WHERE `itmid`
                  IN({$ir['equip_primary']}, {$ir['equip_secondary']},
                     {$ir['equip_armor']})");
echo "<h3>Equipped Items</h3><hr />";
$equip = array();
while ($r = $db->fetch_row($q))
{
    $equip[$r['itmid']] = $r;
}
$db->free_result($q);
echo "<table width='75%' cellspacing='1' class='table'>
<tr>
<th>Primary Weapon</th>
<td>";
if (isset($equip[$ir['equip_primary']]))
{
    print
            $equip[$ir['equip_primary']]['itmname']
                    . "</td><td><a href='unequip.php?type=equip_primary'>Unequip Item</a></td>";
}
else
{
    echo "None equipped.</td><td>&nbsp;</td>";
}
echo "</tr>
<tr>
<th>Secondary Weapon</th>
<td>";
if (isset($equip[$ir['equip_secondary']]))
{
    print
            $equip[$ir['equip_secondary']]['itmname']
                    . "</td><td><a href='unequip.php?type=equip_secondary'>Unequip Item</a></td>";
}
else
{
    echo "None equipped.</td><td>&nbsp;</td>";
}
echo "</tr>
<tr>
<th>Armor</th>
<td>";
if (isset($equip[$ir['equip_armor']]))
{
    print
            $equip[$ir['equip_armor']]['itmname']
                    . "</td><td><a href='unequip.php?type=equip_armor'>Unequip Item</a></td>";
}
else
{
    echo "None equipped.</td><td>&nbsp;</td>";
}
echo "</tr>
</table><hr />
<h3>Inventory</h3><hr />";
$inv =
        $db->query(
                "SELECT `inv_qty`, `itmsellprice`, `itmid`, `inv_id`,
                 `effect1_on`, `effect2_on`, `effect3_on`, `itmname`,
                 `weapon`, `armor`, `itmtypename`
                 FROM `inventory` AS `iv`
                 INNER JOIN `items` AS `i`
                 ON `iv`.`inv_itemid` = `i`.`itmid`
                 INNER JOIN `itemtypes` AS `it`
                 ON `i`.`itmtype` = `it`.`itmtypeid`
                 WHERE `iv`.`inv_userid` = {$userid}
                 ORDER BY `i`.`itmtype` ASC, `i`.`itmname` ASC");
if ($db->num_rows($inv) == 0)
{
    echo "<b>You have no items!</b>";
}
else
{
    echo "<b>Your items are listed below.</b><br />
<table width=100% class=\"table\" border=\"0\" cellspacing=\"1\">
	<tr>
		<td class=\"h\">Item</td>
		<td class=\"h\">Sell Value</td>
		<td class=\"h\">Total Sell Value</td>
		<td class=\"h\">Links</td>
	</tr>";
    $lt = "";
    while ($i = $db->fetch_row($inv))
    {
        if ($lt != $i['itmtypename'])
        {
            $lt = $i['itmtypename'];
            echo "\n<tr>
            			<td colspan='4'>
            				<b>{$lt}</b>
            			</td>
            		</tr>";
        }
        if ($i['weapon'])
        {
            $i['itmname'] =
                    "<span style='color: red;'>*</span>" . $i['itmname'];
        }
        if ($i['armor'])
        {
            $i['itmname'] =
                    "<span style='color: green;'>*</span>" . $i['itmname'];
        }
        echo "<tr>
        		<td>{$i['itmname']}";
        if ($i['inv_qty'] > 1)
        {
            echo "&nbsp;x{$i['inv_qty']}";
        }
        echo "</td>
        	  <td>" . money_formatter($i['itmsellprice'])
                . "</td>
        	  <td>";
        echo money_formatter($i['itmsellprice'] * $i['inv_qty']);
        echo "</td>
        	  <td>
        	  	[<a href='?action=iteminfo&ID={$i['itmid']}'>Info</a>]
        	  	[<a href='?action=itemsend&ID={$i['inv_id']}'>Send</a>]
        	  	[<a href='?action=itemsell&ID={$i['inv_id']}'>Sell</a>]
        	  	[<a href='?action=imadd.php&ID={$i['inv_id']}'>Add To Market</a>]";
        if ($i['effect1_on'] || $i['effect2_on'] || $i['effect3_on'])
        {
            echo " [<a href='?action=itemuse&ID={$i['inv_id']}'>Use</a>]";
        }
        if ($i['weapon'] > 0)
        {
            echo " [<a href='equip_weapon.php?ID={$i['inv_id']}'>Equip as Weapon</a>]";
        }
        if ($i['armor'] > 0)
        {
            echo " [<a href='equip_armor.php?ID={$i['inv_id']}'>Equip as Armor</a>]";
        }
        echo "</td>
        </tr>";
    }
    echo "</table>";
    $db->free_result($inv);
    echo "<small><b>NB:</b> Items with a small red </small><span style='color: red;'>*</span><small> next to their name can be used as weapons in combat.<br />
Items with a small green </small><span style='color: green;'>*</span><small> next to their name can be used as armor in combat.</small>";
}
}


$h->endpage();

As Said, Untested, Using Default Mccodes from V2.0.6

Well thank you very much kind sir!

It works perfectly, only issue teeny tiny was the link for imadd which was a 2 second fix.

I thank you greatly.

I'm working on Mccodes on a localhost and I'm trying to condense the amount of files so I'm compressing multiples into 1.

The above being an example.

I'm currently making attack.php all in one - I guess it's personal preference I just don't like seeing 182 files.

But again, thank you for this, it's perfect.

Edited by Rooster
Link to comment
Share on other sites

57 minutes ago, Rooster said:

Well thank you very much kind sir!

It works perfectly, only issue teeny tiny was the link for imadd which was a 2 second fix.

I thank you greatly.

I'm working on Mccodes on a localhost and I'm trying to condense the amount of files so I'm compressing multiples into 1.

The above being an example.

I'm currently making attack.php all in one - I guess it's personal preference I just don't like seeing 182 files.

But again, thank you for this, it's perfect.

oh ok, i've been doing the oppsite, my last site the header was massive, I've split it up into sections on different pages.

Opera Snapshot_2023-09-01_182324_makeweb.games.png

Header.php being only 140ish lines.

Edited by peterisgb
Link to comment
Share on other sites

27 minutes ago, peterisgb said:

oh ok, i've been doing the oppsite, my last site the header was massive, I've split it up into sections on different pages.

Opera Snapshot_2023-09-01_182324_makeweb.games.png

Header.php being only 140ish lines.

Interesting - Yeah quite the opposite!

Although, I have done away with the mainmenu.php file and only have a header file.
My header has a horizontal nav menu that's very small.

My header is currently at 136 lines.
I do have to add about 8/10 lines for some display data code.

Link to comment
Share on other sites

Soooo, I had some free time and wrote this. It clocks in at 1,149 lines, and combines 9 files (imadd, inventory, itembuy, iteminfo, itemsell, itemsend, itemuse, equip, unequip) into 1.
It's PHP 7.4-compatible.

<?php
declare(strict_types=1);
/**
 * For use on MCCodes Version 2.0.5b
 * We shouldn't just redistribute licensed software, so here's a rewrite ;)
 * I do *not* claim this to be efficient or better than the original, it's just a different take on things
 * The length and calculable complexity of this class is ugly. I would recommend splitting this into extendable classes and consider autoloading
 *
 * See the ItemHandler constants for configurable text outputs
 */
global $db, $ir, $h;
require_once __DIR__ . '/globals.php'; ?>
    <!-- Remove this if you're using Bootstrap. I just like the naming scheme -->
    <!--suppress CssUnusedSymbol -->
    <style>
        .text-end {
            text-align: end;
        }

        .form-group {
            display: block;
            padding: 5px 0;
        }

        .text-danger {
            color: #f00;
        }

        .text-success {
            color: #050;
        }

        .table-responsive {
            min-height: 20vh;
            max-height: 99.9vh;
            min-width: 20vh;
            max-width: 99.9vh;
            overflow: auto;
        }

        .btn {
            margin: 0.75vh 1vw;
            padding: 0.5vh 1vw;
        }

        .btn-primary {
            color: #fff;
            background-color: #337ab7;
            border-color: #2e6da4;
            border-radius: 5%;
        }

        .alert {
            display: block;
            height: auto;
            line-height: 1em;
            max-width: 50%;
            padding: 0.6vh 3vw;
            margin: 0.5vh 1vw;
            border-radius: 5%;
        }

        .alert-danger {
            color: #a94442;
            background-color: #f2dede;
            border-color: #ebccd1;
        }

        .alert-success {
            color: #3c763d;
            background-color: #dff0d8;
            border-color: #d6e9c6;
        }

        .alert-info {
            color: #31708f;
            background-color: #d9edf7;
            border-color: #bce8f1;
        }

        .alert .alert-links {
            margin-top: 1.1em;
        }

        .alert .alert-title {
            display: block;
            font-weight: 700;
            font-size: 1.125em;
            line-height: 1em;
            margin-bottom: 0.2vh;
        }
    </style>
<?php

/**
 * ItemHandler
 * all-in-one class for imadd, inventory, itembuy, iteminfo, itemsell, itemsend, itemuse, equip, unequip
 */
class ItemHandler
{
    // Don't touch these
    private database $db;
    private array $ir;
    private headers $headers;
    private ?string $action;
    private ?int $id;

    // Do touch these!
    private const SECURITY_TIMEOUT = 'Your request has timed out for security reasons';
    private const NO_INVENTORY = 'You don\'t have any items in your inventory';
    private const INVALID_ITEM = 'You didn\'t select a valid item';
    private const INVALID_QUANTITY = 'You didn\'t enter a valid quantity';
    private const INVALID_EQUIP_SLOT = 'You didn\'t provide a valid equipment slot';
    private const INVALID_PRICE = 'You didn\'t enter a valid price';
    private const INVALID_CURRENCY = 'You didn\'t selected a valid currency';
    private const INVALID_USER = 'You didn\'t select a valid user';
    private const USER_NOT_EXISTS = 'Your intended recipient doesn\'t exist';
    private const ITEM_NOT_EXISTS = 'The item you selected doesn\'t exist';
    private const EQUIP_NOT_EXISTS = 'You don\'t have that item equipped';
    private const ITEM_NOT_BUYABLE = 'You can\'t buy that item';
    private const ITEM_NOT_EQUIPPABLE = 'You can\'t equip that item';
    private const ITEM_NOT_USABLE = 'You can\'t use that item';
    private const INSUFFICIENT_FUNDS = 'You don\'t have enough money';
    private const NOT_ENOUGH_ITEMS = 'You don\'t have enough of those';
    private const WORTHLESS_ITEMS = 'You can\'t sell worthless items';
    private const TRANSFER_NOT_PERMITTED = 'You can\'t transfer items to that player';
    private const SELF_TRANSFER_NOT_PERMITTED = 'You can\'t transfer items to yourself';
    private const ITEM_PLAYER_LOCATION_MISMATCH = 'You can\'t buy items from other locations';
    private const ITEM_ADDED_TO_MARKET = 'You\'ve added %sx %s to the item market for %s';
    private const ITEM_PURCHASED = 'You bought %sx %s for %s';
    private const ITEM_SOLD = 'You sold %sx %s for %s';
    private const ITEM_TRANSFERRED = 'You sent %sx %s to %s';
    private const ITEM_USED = 'You used %s';
    /**
     * true: prevents the player from selling items if the sell value is 0
     * false: allows the player to use the sell items as a trashing function; permitting sales of items regardless of sell value
     * @var bool preventWorthlessSales
     */
    private bool $preventWorthlessSales = false;
    private string $table_users_stats = 'userstats';
    private string $table_users = 'users';
    private array $bar_cols = ['energy', 'will', 'brave', 'hp'];
    private array $stat_cols = ['strength', 'agility', 'guard', 'labour', 'IQ'];
    private array $currencies = ['money', 'crystals'];
    private array $equipSlots = ['equip_primary', 'equip_secondary', 'equip_armor'];

    /**
     * @param database $db
     * @param array $ir
     * @param headers $h
     * @param string|null $action
     * @param int|null $id
     */
    public function __construct(database $db, array $ir, headers $h, ?string $action = null, ?int $id = null)
    {
        $this->db = $db;
        $this->ir = $ir;
        $this->headers = $h;
        $this->action = $action;
        $this->id = $id;
    }

    /**
     * @return void
     */
    public function run()
    {
        switch ($this->action) {
            case 'buy':
                $this->itemPurchase();
                break;
            case 'info':
                $this->itemInfo();
                break;
            case 'sell':
                $this->itemSell();
                break;
            case 'send':
                $this->itemSend();
                break;
            case 'use':
                $this->itemUse();
                break;
            case 'market-add':
                $this->itemMarketAdd();
                break;
            case 'unequip':
                $this->doItemUnequip();
                break;
            case 'equip':
                $this->itemEquip();
                break;
            default:
                $this->inventory();
                break;
        }
    }

    /**
     * @return array
     */
    private function getEquippedItems(): array
    {
        $items = [];
        // Maps the equipSlots to the user's equipped items, removes 0 values and duplicates
        $equipped_ids = array_unique(array_filter(array_map(function ($slot) {
            return $this->ir[$slot];
        }, $this->equipSlots)));
        if (!empty($equipped_ids)) {
            $get_items = $this->db->query(
                'SELECT itmid, itmname FROM items WHERE itmid IN (' . implode(', ', $equipped_ids) . ')',
            );
            while ($row = $this->db->fetch_row($get_items)) {
                $items[$row['itmid']] = $row['itmname'];
            }
            $this->db->free_result($get_items);
        }
        return $items;
    }

    /**
     * @param array $row
     * @return bool
     */
    private function hasEffect(array $row): bool
    {
        return $row['effect1_on'] || $row['effect2_on'] || $row['effect3_on'];
    }
    // -----------------------------------------

    /**
     * @param array $equip
     * @return void
     */
    private function renderEquips(array $equip): void
    {
        $slots = [
            'primary'   => $equip[$this->ir['equip_primary']] ?? '',
            'secondary' => $equip[$this->ir['equip_secondary']] ?? '',
            'armor'     => $equip[$this->ir['equip_armor']] ?? '',
        ];
        $code = request_csrf_code('verf'); ?>
        <div class="table-responsive">
            <table class="table">
                <?php
                foreach ($slots as $slot => $item) {
                    ?>
                    <tr>
                        <th scope="row"><?php echo $slot === 'armor' ? 'Armor' : ucfirst($slot) . ' Weapon'; ?></th>
                        <?php
                        if (!empty($item)) {
                            $slot_col = 'equip_' . $slot; ?>
                            <td><?php echo $item; ?></td>
                            <td><a href="/inventory.php?action=unequip&type=<?php echo $slot_col; ?>&id=<?php echo $this->ir[$slot_col]; ?>&verf=<?php echo $code; ?>">Unequip Item</a></td>
                            <?php
                        } else {
                            ?>
                            <td>None equipped.</td>
                            <td>&nbsp;</td>
                            <?php
                        } ?>
                    </tr>
                    <?php
                } ?>
            </table>
        </div>
        <hr>
        <?php
    }

    /**
     * @return void
     */
    private function renderInventory(): void
    {
        $get_inventory = $this->db->query(
            'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname, i.itmsellprice, i.effect1_on, i.effect2_on, i.effect3_on, i.weapon, i.armor, it.itmtypename
            FROM inventory AS inv
            INNER JOIN items AS i ON inv.inv_itemid = i.itmid
            INNER JOIN itemtypes AS it ON it.itmtypeid = i.itmtype
            WHERE inv.inv_userid = ' . $this->ir['userid'] . '
            ORDER BY i.itmtype, i.itmname'
        );
        if (!$this->db->num_rows($get_inventory)) {
            $this->alert('info', self::NO_INVENTORY);
        }
        $code = request_csrf_code('verf'); ?>
        <h3>Inventory</h3>
        <div class="table-responsive">
            <table class="table">
                <thead>
                <tr>
                    <th scope="col">Item</th>
                    <th scope="col">Sell Value</th>
                    <th scope="col">Total Sell Value</th>
                    <th scope="col">Links</th>
                </tr>
                </thead>
                <tbody>
                <?php $last_type = '';
                $total_inventory_value = 0;
                while ($row = $this->db->fetch_row($get_inventory)) {
                    $total_inventory_value += $row['itmsellprice'] * $row['inv_qty'];
                    if ($last_type !== $row['itmtypename']) {
                        $last_type = $row['itmtypename']; ?>
                        <tr>
                            <td colspan="4">
                                <strong><?php echo $last_type; ?></strong>
                            </td>
                        </tr>
                        <?php
                    }
                    $prefix = '';
                    if ($row['weapon'] > 0) {
                        $prefix .= '<span class="text-danger">*</span>';
                    }
                    if ($row['armor'] > 0) {
                        $prefix .= '<span class="text-success">*</span>';
                    } ?>
                    <tr>
                        <td><?php echo $prefix . $row['itmname'] . ($row['inv_qty'] > 1 ? ' x' . number_format((int)$row['inv_qty']) : ''); ?></td>
                        <td><?php echo money_formatter($row['itmsellprice']); ?></td>
                        <td><?php echo money_formatter($row['itmsellprice'] * $row['inv_qty']); ?></td>
                        <td>
                            [<a href="inventory.php?action=info&id=<?php echo $row['itmid']; ?>">Info</a>]
                            [<a href="inventory.php?action=send&id=<?php echo $row['inv_id']; ?>">Send</a>]
                            [<a href="inventory.php?action=sell&id=<?php echo $row['inv_id']; ?>">Sell</a>]
                            [<a href="inventory.php?action=market-add&id=<?php echo $row['inv_id']; ?>">Add To Market</a>]
                            <?php
                            if ($this->hasEffect($row)) {
                                ?>
                                [<a href="inventory.php?action=use&id=<?php echo $row['inv_id']; ?>">Use</a>]
                                <?php
                            }
                            if ($row['weapon'] > 0) {
                                ?>
                                [<a href="inventory.php?action=equip&id=<?php echo $row['inv_id']; ?>&verf=<?php echo $code; ?>&type=weapon">Equip as Weapon</a>]
                                <?php
                            }
                            if ($row['armor'] > 0) {
                                ?>
                                [<a href="inventory.php?action=equip&id=<?php echo $row['inv_id']; ?>&verf=<?php echo $code; ?>&type=armor">Equip as Armor</a>]
                                <?php
                            } ?>
                        </td>
                    </tr>
                    <?php
                } ?>
                <tr>
                    <td colspan="4">&nbsp;</td>
                </tr>
                <tr>
                    <td colspan="4" class="text-end">
                        <strong>Total Inventory Value:</strong> <?php echo money_formatter($total_inventory_value); ?>
                    </td>
                </tr>
                </tbody>
            </table>
        </div>
        <p>
            <small><strong>NB:</strong> Items with a small red </small><span class="text-danger">*</span><small> next to their name can be used as weapons in combat.</small><br>
            <small>Items with a small green </small><span class="text-success">*</span><small> next to their name can be used as armor in combat.</small>
        </p>
        <?php $this->db->free_result($get_inventory);


    }

    /**
     * @return void
     */
    private function inventory()
    {
        $this->renderEquips($this->getEquippedItems());
        $this->renderInventory();
    }
    // -----------------------------------------

    /**
     * @param array $row
     * @return void
     */
    private function renderItemInfo(array $row): void
    {
        ?>
        <h3>Item Information</h3>
        <table class="table" style="width: 75%;">
            <thead>
            <tr>
                <th colspan="2" style="font-weight: 700;">
                    Looking up info on <?php echo $row['itmname']; ?>
                </th>
            </tr>
            </thead>
            <tbody>
            <tr>
                <td colspan="2">
                    The <?php echo $row['itmname']; ?> is <?php echo $this->aAn($row['itmtypename']); ?> Item<br>
                    <p>
                        <?php echo $row['itmdesc']; ?>
                    </p>
                </td>
            </tr>
            </tbody>
            <thead>
            <tr>
                <th colspan="2">Item Info</th>
            </tr>
            <tr>
                <th scope="col">Item Buy Price</th>
                <th scope="col">Item Sell Price</th>
            </tr>
            </thead>
            <tbody>
            <tr>
                <td><?php echo $row['itmbuyprice'] > 0 ? money_formatter($row['itmbuyprice']) : 'N/A'; ?></td>
                <td><?php echo $row['itmsellprice'] > 0 ? money_formatter($row['itmsellprice']) : 'N/A'; ?></td>
            </tr>
            </tbody>
        </table>
        <p>
            <a href="inventory.php">Back to Inventory</a>
        </p>
        <?php
    }

    /**
     * @return void
     */
    private function itemInfo(): void
    {
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT i.itmid, i.itmname, i.itmdesc, i.itmbuyprice, i.itmsellprice, it.itmtypename
            FROM items AS i
            INNER JOIN itemtypes AS it ON it.itmtypeid = i.itmtype
            WHERE i.itmid = ' . $this->id . '
            LIMIT 1'
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        $this->renderItemInfo($row);
    }

    // -----------------------------------------

    /**
     * @param array $row
     * @return void
     */
    private function renderItemSell(array $row): void
    {
        $code = request_csrf_code('sell_item_' . $row['inv_id']); ?>
        <h3>Sell Item</h3>
        <p>
            Enter the amount of <?php echo $this->pluralize($row['itmname'], 0); ?> you want to sell. You have <strong><?php echo $row['inv_qty']; ?></strong>.<br>
            <?php
            if ($row['inv_qty'] > 1) {
                ?>
                Altogether, they are worth <?php echo money_formatter($row['inv_qty'] * $row['itmsellprice']); ?>.<br>
                <?php
            } ?>
            <span class="text-italic">Note: There is no confirmation. Be sure you've entered the amount you want to sell.</span>
        </p>
        <form action="inventory.php?action=sell&id=<?php echo $row['inv_id']; ?>" method="post">
            <input type="hidden" name="verf" value="<?php echo $code; ?>" />
            <div class="form-group">
                <label for="qty">Quantity</label>
                <input type="number" name="qty" id="qty" class="form-control" placeholder="0" required>
            </div>
            <button type="submit" class="btn btn-primary">
                Sell Items
            </button>
        </form>
        <?php
    }

    /**
     * @param array $row
     * @return array
     */
    private function doItemSell(array $row): array
    {
        $qty = array_key_exists('qty', $_POST) && is_numeric($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : null;
        if (empty($_POST['qty'])) {
            return [
                'type'    => 'error',
                'content' => self::INVALID_QUANTITY,
            ];
        }
        if ($qty > $row['inv_qty']) {
            return [
                'type'    => 'error',
                'content' => self::NOT_ENOUGH_ITEMS,
            ];
        }
        $value = $qty * $row['itmsellprice'];
        if ($this->preventWorthlessSales && !$value) {
            return [
                'type'    => 'error',
                'content' => self::WORTHLESS_ITEMS,
            ];
        }
        $formatted_value = money_formatter($value);
        item_remove($this->ir['userid'], $row['itmid'], $qty);
        $this->db->query(
            'UPDATE users SET money = money + ' . $value . ' WHERE userid = ' . $this->ir['userid']
        );
        // At this point, consider parameterised queries.
        $this->db->query(
            sprintf(
                'INSERT INTO itemselllogs (isUSER, isITEM, isTOTALPRICE, isQTY, isTIME, isCONTENT)
                VALUES (%u, %u, %u, %u, %u, \'%s\')',
                $this->ir['userid'],
                $row['itmid'],
                $value,
                $qty,
                time(),
                $this->db->escape($this->ir['username'] . ' sold ' . $qty . ' ' . $this->pluralize($row['itmname'], $qty) . ' for ' . $formatted_value)
            )
        );
        return [
            'type'    => 'success',
            'content' => sprintf(self::ITEM_SOLD, number_format($qty), $this->pluralize($row['itmname'], $qty), $formatted_value),
        ];
    }

    /**
     * @return void
     */
    private function itemSell(): void
    {
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname, i.itmsellprice
            FROM inventory AS inv
            INNER JOIN items AS i ON i.itmid = inv.inv_itemid
            WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . '
            LIMIT 1'
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        $response = array_key_exists('verf', $_POST) && verify_csrf_code('sell_item_' . $row['inv_id'], stripslashes($_POST['verf'])) ? $this->doItemSell($row) : null;
        if (!empty($response)) {
            $this->alert($response['type'], $response['content']);
        }
        $this->renderItemSell($row);
    }
    // -----------------------------------------

    /**
     * @return void
     */
    private function itemPurchase(): void
    {
        $qty = array_key_exists('qty', $_POST) && is_numeric($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : null;
        if (empty($qty)) {
            $this->alert('error', self::INVALID_QUANTITY);
        }
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT s.shopLOCATION, i.itmid, i.itmname, i.itmbuyable, i.itmbuyprice
            FROM shopitems AS si
            INNER JOIN shops AS s ON s.shopID = si.sitemSHOP
            INNER JOIN items AS i ON i.itmid = si.sitemITEMID
            WHERE si.sitemITEMID = ' . $this->id
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        if (!$row['itmbuyable']) {
            $this->alert('error', self::ITEM_NOT_BUYABLE);
        }
        if ($row['shopLOCATION'] !== $this->ir['location']) {
            $this->alert('error', self::ITEM_PLAYER_LOCATION_MISMATCH);
        }
        $total_value = $qty * (int)$row['itmbuyprice'];
        if ($total_value > $this->ir['money']) {
            $this->alert('error', self::INSUFFICIENT_FUNDS);
        }
        item_add($this->ir['userid'], $row['itmid'], $qty);
        $this->db->query(
            'UPDATE users SET money = money - ' . $total_value . ' WHERE userid = ' . $this->ir['userid']
        );
        $this->db->query(
            sprintf(
                'INSERT INTO itembuylogs (ibUSER, ibITEM, ibTOTALPRICE, ibQTY, ibTIME, ibCONTENT)
                VALUES (%u, %u, %u, %u, %u, \'%s\')',
                $this->ir['userid'],
                $row['itmid'],
                $total_value,
                $qty,
                time(),
                $this->db->escape($this->ir['username'] . ' purchased ' . $qty . ' ' . $this->pluralize($row['itmname'], $qty) . ' for ' . money_formatter($total_value))
            )
        );
        $this->alert('success', sprintf(self::ITEM_PURCHASED, number_format($qty), $this->pluralize($row['itmname'], $qty), money_formatter($total_value)));
    }
    // -----------------------------------------

    /**
     * @param array $row
     * @return string[]
     */
    private function doItemSend(array $row): array
    {
        $target_id = array_key_exists('user', $_POST) && is_numeric($_POST['user']) && (int)$_POST['user'] > 0 ? (int)$_POST['user'] : null;
        $qty = array_key_exists('qty', $_POST) && is_numeric($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : null;
        if ($qty > $row['inv_qty']) {
            return [
                'type'    => 'error',
                'content' => self::NOT_ENOUGH_ITEMS
            ];
        }
        if (empty($target_id)) {
            return [
                'type'    => 'error',
                'content' => self::INVALID_USER
            ];
        }
        if ($target_id === $this->ir['userid']) {
            return [
                'type'    => 'error',
                'content' => self::SELF_TRANSFER_NOT_PERMITTED
            ];
        }
        $get_target = $this->db->query(
            'SELECT userid, username, lastip FROM users WHERE userid = ' . $target_id
        );
        if (!$this->db->num_rows($get_target)) {
            return [
                'type'    => 'error',
                'content' => self::USER_NOT_EXISTS
            ];
        }
        $target = $this->db->fetch_row($get_target);
        $this->db->free_result($get_target);
        if ($target['lastip'] === $this->ir['lastip']) {
            return [
                'type'    => 'error',
                'content' => self::TRANSFER_NOT_PERMITTED
            ];
        }
        item_remove($this->ir['userid'], $row['itmid'], $qty);
        item_add($target['userid'], $row['itmid'], $qty);
        event_add($target['userid'], 'You received ' . number_format($qty) . ' ' . $this->pluralize($row['itmname'], $qty) . ' from ' . $this->ir['username']);
        $this->db->query(
            sprintf(
                'INSERT INTO itemxferlogs (ixFROM, ixTO, ixITEM, ixQTY, ixTIME, ixFROMIP, ixTOIP)
                VALUES (%u, %u, %u, %u, %u, \'%s\', \'%s\')',
                $this->ir['userid'],
                $target['userid'],
                $row['itmid'],
                $qty,
                time(),
                $this->ir['lastip'],
                $target['lastip']
            )
        );
        return [
            'type'    => 'success',
            'content' => sprintf(self::ITEM_TRANSFERRED, number_format($qty), $this->pluralize($row['itmname'], $qty), $target['username'])
        ];
    }

    /**
     * @param array $row
     * @param int|null $get_target_id
     * @return void
     */
    private function renderItemSend(array $row, ?int $get_target_id = null): void
    {
        $code = request_csrf_code('send_item_' . $row['inv_id']); ?>
        <h3>Send Item</h3>
        <p>
            Enter the amount of <?php echo $this->pluralize($row['itmname'], 0); ?> you want to send. You have <strong><?php echo $row['inv_qty']; ?></strong>.<br>
            <span class="text-italic">Note: There is no confirmation. Be sure you've entered the amount you want to send.</span>
        </p>
        <form action="inventory.php?action=send&id=<?php echo $row['inv_id']; ?>" method="post">
            <input type="hidden" name="verf" value="<?php echo $code; ?>" />
            <div class="form-group">
                <label for="user">User ID:</label>
                <input type="number" name="user" id="user" class="form-control" placeholder="0" value="<?php echo $get_target_id; ?>" required>
            </div>
            <div class="form-group">
                <label for="qty">Quantity</label>
                <input type="number" name="qty" id="qty" class="form-control" placeholder="0" required>
            </div>
            <button type="submit" class="btn btn-primary">
                Send Items
            </button>
        </form>
        <?php
    }

    /**
     * @return void
     */
    private function itemSend(): void
    {
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT inv.inv_id, inv.inv_qty, inv.inv_itemid, i.itmid, i.itmname
            FROM inventory AS inv
            INNER JOIN items AS i ON inv.inv_itemid = i.itmid
            WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . '
            LIMIT 1'
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        $response = array_key_exists('verf', $_POST) && verify_csrf_code('send_item_' . $this->id, stripslashes($_POST['verf'])) ? $this->doItemSend($row) : null;

        if (!empty($response)) {
            $this->alert($response['type'], $response['content']);
        }
        $get_target_id = array_key_exists('user', $_GET) && is_numeric($_GET['user']) && (int)$_GET['user'] > 0 ? (int)$_GET['user'] : null;
        $this->renderItemSend($row, $get_target_id);
    }

    // -----------------------------------------

    /**
     * @return void
     */
    private function itemUse(): void
    {
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname, i.effect1_on, i.effect2_on, i.effect3_on, i.effect1, i.effect2, i.effect3
            FROM inventory AS inv
            INNER JOIN items AS i ON i.itmid = inv.inv_itemid
            WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . '
            LIMIT 1'
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        if (!$this->hasEffect($row)) {
            $this->alert('error', self::ITEM_NOT_USABLE);
        }
        for ($i = 1; $i <= 3; ++$i) {
            if (!$row['effect' . $i . '_on']) {
                continue;
            }
            $effect = unserialize($row['effect' . $i]);
            $max_stat = 'max' . $effect['stat'];
            $inc_amount = $effect['inc_type'] === 'percent'
                ? (in_array($effect['stat'], $this->bar_cols)
                    ? round($this->ir[$max_stat] / 100 * $effect['inc_amount'])
                    : round($this->ir[$effect['stat']] / 100 * $effect['inc_amount']))
                : $effect['inc_amount'];
            if ($effect['dir'] === 'pos') {
                if (in_array($effect['stat'], $this->bar_cols)) {
                    $this->ir[$effect['stat']] = min($this->ir[$effect['stat']] + $inc_amount, $this->ir[$max_stat]);
                } else {
                    $this->ir[$effect['stat']] += $inc_amount;
                }
            } else {
                $this->ir[$effect['stat']] = max($this->ir[$effect['stat']] - $inc_amount, 0);
            }
            $table = in_array($effect['stat'], $this->stat_cols) ? $this->table_users_stats : $this->table_users;
            $this->db->query(
                'UPDATE ' . $table . ' SET ' . $effect['stat'] . ' = ' . $this->ir[$effect['stat']] . ' WHERE userid = ' . $this->ir['userid']
            );
        }
        item_remove($this->ir['userid'], $row['itmid'], 1);
        $this->alert('success', sprintf(self::ITEM_USED, $this->aAn($row['itmname'])));
    }
    // -----------------------------------------

    /**
     * @param array $row
     * @return array
     */
    private function doItemMarketAdd(array $row): array
    {
        $price = array_key_exists('price', $_POST) && is_numeric($_POST['price']) && (int)$_POST['price'] > 0 ? (int)$_POST['price'] : null;
        $qty = array_key_exists('qty', $_POST) && is_numeric($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : null;
        $currency = array_key_exists('currency', $_POST) && in_array($_POST['currency'], $this->currencies) ? $_POST['currency'] : null;
        if (empty($qty)) {
            return [
                'type'    => 'error',
                'content' => self::INVALID_QUANTITY
            ];
        }
        if (empty($price)) {
            return [
                'type'    => 'error',
                'content' => self::INVALID_PRICE
            ];
        }
        if (empty($currency)) {
            return [
                'type'    => 'error',
                'content' => self::INVALID_CURRENCY
            ];
        }
        if ($qty > $row['inv_qty']) {
            return [
                'type'    => 'error',
                'content' => self::NOT_ENOUGH_ITEMS
            ];
        }
        $get_dupe = $this->db->query(
            sprintf(
                'SELECT imID FROM itemmarket WHERE imITEM = %u AND imPRICE = %u AND imADDER = %u AND imCURRENCY = \'%s\'',
                $row['itmid'],
                $price,
                $this->ir['userid'],
                $currency
            )
        );
        $dupe = $this->db->num_rows($get_dupe) ? $this->db->fetch_single($get_dupe) : null;
        $this->db->free_result($get_dupe);
        if ($dupe) {
            $this->db->query(
                'UPDATE itemmarket SET imQTY = imQTY + ' . $qty . ' WHERE imID = ' . $dupe
            );
        } else {
            $this->db->query(
                sprintf(
                    'INSERT INTO itemmarket (imITEM, imADDER, imPRICE, imCURRENCY, imQTY)
                    VALUES (%u, %u, %u, \'%s\', %u)',
                    $row['itmid'],
                    $this->ir['userid'],
                    $price,
                    $currency,
                    $qty
                )
            );
        }
        item_remove($this->ir['userid'], $row['itmid'], $qty);
        $this->db->query(
            sprintf(
                'INSERT INTO imarketaddlogs (imaITEM, imaPRICE, imaINVID, imaADDER, imaTIME, imaCONTENT)
                VALUES (%u, %u, %u, %u, %u, \'%s\')',
                $row['itmid'],
                $price,
                $row['inv_id'],
                $this->ir['userid'],
                time(),
                $this->db->escape($this->ir['username'] . ' added ' . $qty . ' ' . $this->pluralize($row['itmname'], $qty) . ' to the item market for ' . money_formatter($price))
            )
        );
        return [
            'type'    => 'success',
            'content' => sprintf(self::ITEM_ADDED_TO_MARKET, $qty, $this->pluralize($row['itmname'], $qty), money_formatter($price))
        ];
    }

    /**
     * @param array $row
     * @return void
     */
    private function renderItemMarketAdd(array $row): void
    {
        $code = request_csrf_code('market_item_' . $this->id); ?>
        <h3>Add Item to Market</h3>
        <p>
            Enter the amount of <?php echo $this->pluralize($row['itmname'], 0); ?> you want to list on the item market. You have <strong><?php echo $row['inv_qty']; ?></strong>.<br>
            Set the currency you want to receive and the price for <em>each</em> item.
        </p>
        <form action="inventory.php?action=market-add&id=<?php echo $this->id; ?>" method="post">
            <input type="hidden" name="verf" value="<?php echo $code; ?>" />
            <div class="form-group">
                <label for="qty">Quantity</label>
                <input type="number" name="qty" id="qty" class="form-control" placeholder="0" required>
            </div>
            <div class="form-group">
                <label for="price">Price</label>
                <input type="number" name="price" id="price" class="form-control" placeholder="0" required>
            </div>
            <div class="form-group">
                <label for="currency">Currency</label>
                <select name="currency" id="currency" class="form-control">
                    <?php
                    foreach ($this->currencies as $currency) {
                        printf('<option value="%s">%s</option>', $currency, ucfirst($currency));
                    } ?>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">
                Add Item To Market
            </button>
        </form>
        <?php
    }

    /**
     * @return void
     */
    private function itemMarketAdd(): void
    {
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname
            FROM inventory AS inv
            INNER JOIN items AS i ON inv.inv_itemid = i.itmid
            WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . '
            LIMIT 1'
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        $response = array_key_exists('verf', $_POST) && verify_csrf_code('market_item_' . $this->id, stripslashes($_POST['verf'])) ? $this->doItemMarketAdd($row) : null;
        if (!empty($response)) {
            $this->alert($response['type'], $response['content']);
        }
        $this->renderItemMarketAdd($row);
    }

    // -----------------------------------------

    /**
     * @return void
     */
    private function doItemUnequip(): void
    {
        $type = array_key_exists('type', $_GET) && in_array($_GET['type'], $this->equipSlots) ? $_GET['type'] : null;
        if (empty($type)) {
            $this->alert('error', self::INVALID_EQUIP_SLOT);
        }
        if (empty($this->ir[$type])) {
            $this->alert('error', self::EQUIP_NOT_EXISTS);
        }
        item_add($this->ir['userid'], $this->ir[$type], 1);
        $this->db->query(
            'UPDATE users SET ' . $type . ' = 0 WHERE userid = ' . $this->ir['userid']
        );
        $names = array_map(function ($slot) {
            $slot = str_replace('equip_', '', $slot);
            return ucfirst($slot) . ($slot !== 'armor' ? ' Weapon' : '');
        }, $this->equipSlots);
        $this->alert('success', 'The item in your ' . $names[$type] . ' slot has been unequipped.');
    }

    // -----------------------------------------

    /**
     * @param array $row
     * @return array
     */
    private function doEquipArmor(array $row): array
    {
        if (!array_key_exists('verf', $_GET) || !verify_csrf_code('verf', $_GET['verf'])) {
            return [
                'type'    => 'error',
                'content' => self::SECURITY_TIMEOUT,
            ];
        }
        if ($this->ir['equip_armor'] > 0) {
            item_add($this->ir['userid'], $this->ir['equip_armor'], 1);
        }
        item_remove($this->ir['userid'], $row['itmid'], 1);
        $this->db->query(
            'UPDATE users SET equip_armor = ' . $row['itmid'] . ' WHERE userid = ' . $this->ir['userid']
        );
        return [
            'type'    => 'success',
            'content' => 'Your armor has been equipped.'
        ];
    }

    /**
     * @param array $row
     * @return string[]
     */
    private function doEquipWeapon(array $row): array
    {
        $slots = [...array_slice($this->equipSlots, 0, 2)];
        $type = array_key_exists('type', $_POST) && in_array($_POST['type'], $slots) ? $_POST['type'] : null;
        if (empty($type)) {
            return [
                'type'    => 'error',
                'content' => self::INVALID_EQUIP_SLOT
            ];
        }
        if ($this->ir[$type] > 0) {
            item_add($this->ir['userid'], $this->ir[$type], 1);
        }
        item_remove($this->ir['userid'], $row['itmid'], 1);
        $this->db->query(
            'UPDATE users SET ' . $type . ' = ' . $row['itmid'] . ' WHERE userid = ' . $this->ir['userid']
        );
        return [
            'type'    => 'success',
            'content' => 'Your weapon has been equipped.'
        ];
    }

    /**
     * @param array $row
     * @param bool $multi
     * @return void
     */
    private function renderEquipSelect(array $row, bool $multi = false): void
    {
        $response = array_key_exists('equip_' . $row['inv_id'], $_POST) && verify_csrf_code('equip_' . $row['inv_id'], $_POST['equip_' . $row['inv_id']])
            ? (array_key_exists('type', $_POST) && $_POST['type'] === 'equip_armor' ? $this->doEquipArmor($row) : $this->doEquipWeapon($row)
            ) : null;
        if (!empty($response)) {
            $this->alert($response['type'], $response['content']);
        }
        $code = request_csrf_code('equip_' . $row['inv_id']); ?>
        <h3>Equip Item</h3>
        <p>
            Please choose the slot to equip your <?php echo $row['itmname']; ?>.
            If you already have an item equipped in that slot, it will be unequipped and returned to your inventory.
        </p>
        <form action="inventory.php?action=equip&id=<?php echo $this->id; ?>" method="post">
            <input type="hidden" name="equip_<?php echo $row['inv_id']; ?>" value="<?php echo $code; ?>" />
            <?php
            $cnt = 0;
            foreach ($this->equipSlots as $slot) {
                if ($slot === 'equip_armor' && !$multi) {
                    continue;
                } ?>
                <div class="form-group">
                    <label for="<?php echo $slot; ?>">
                        <input type="radio" name="type" id="<?php echo $slot; ?>" value="<?php echo $slot; ?>" <?php echo !$cnt ? 'checked' : ''; ?> />
                        <?php echo ucfirst(str_replace('equip_', '', $slot)) . ($slot !== 'equip_armor' ? ' Weapon' : ''); ?>
                    </label>
                </div>
                <?php
                ++$cnt;
            } ?>
            <button type="submit" class="btn btn-primary">
                Equip Item
            </button>
        </form>
        <?php
    }

    /**
     * @return void
     */
    private function itemEquip(): void
    {
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname, i.weapon, i.armor
            FROM inventory AS inv
            INNER JOIN items AS i ON inv.inv_itemid = i.itmid
            WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . '
            LIMIT 1'
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        if (!$row['weapon'] && !$row['armor']) {
            $this->alert('error', self::ITEM_NOT_EQUIPPABLE);
        }
        if ($row['armor'] && !$row['weapon']) {
            $response = $this->doEquipArmor($row);
            $this->alert($response['type'], $response['content']);
        } elseif ($row['weapon'] && !$row['armor']) {
            $this->renderEquipSelect($row);
        } else {
            $type = array_key_exists('type', $_GET) && in_array($_GET['type'], ['weapon', 'armor']) ? $_GET['type'] : null;
            if ($type === 'armor') {
                $response = $this->doEquipArmor($row);
                $this->alert($response['type'], $response['content']);
            }
            $this->renderEquipSelect($row, true);
        }
    }
    // -----------------------------------------

    /**
     * @param string $type
     * @param string $content
     * @return void
     */
    private function alert(string $type, string $content): void
    {
        $alert = $type === 'error' ? 'danger' : $type; ?>
        <div class="alert alert-<?php echo $alert; ?>" role="alert">
            <span class="alert-title"><?php echo ucfirst($type); ?></span>
            <?php echo $content; ?>
            <div class="alert-links">
                <a href="inventory.php">Back to Inventory</a>
            </div>
        </div>
        <?php
        $this->headers->endpage();
        exit;
    }

    /**
     * @param string $word
     * @return string
     */
    private function aAn(string $word): string
    {
        $first_letter = substr($word, 0, 1);
        return in_array($first_letter, ['a', 'e', 'i', 'o', 'u'])
            ? 'an ' . $word
            : 'a ' . $word;
    }

    /**
     * Note: This does not respect irregular plurals in the slightest. It's just a quick and dirty way to whack an s on the end if $amount <> 1 and the word doesn't already end in s.
     * @param string $word
     * @param int $amount
     * @return string
     */
    private function pluralize(string $word, int $amount = 1): string
    {
        $last_letter = substr($word, -1);
        return strtolower($last_letter) === 's' || $amount === 1 ? $word : $word . 's';
    }
}

// basic int validation
$_GET['id'] = array_key_exists('id', $_GET) && is_numeric($_GET['id']) && (int)$_GET['id'] > 0 ? (int)$_GET['id'] : null;
$_GET['action'] ??= null;
(new ItemHandler($db, $ir, $h, $_GET['action'], $_GET['id']))->run();

 

  • Like 2
Link to comment
Share on other sites

3 hours ago, Magictallguy said:

Soooo, I had some free time and wrote this. It clocks in at 1,149 lines, and combines 9 files (imadd, inventory, itembuy, iteminfo, itemsell, itemsend, itemuse, equip, unequip) into 1.
It's PHP 7.4-compatible.

<?php declare(strict_types=1); /** * For use on MCCodes Version 2.0.5b * We shouldn't just redistribute licensed software, so here's a rewrite ;) * I do *not* claim this to be efficient or better than the original, it's just a different take on things * The length and calculable complexity of this class is ugly. I would recommend splitting this into extendable classes and consider autoloading * * See the ItemHandler constants for configurable text outputs */ global $db, $ir, $h; require_once __DIR__ . '/globals.php'; ?> <!-- Remove this if you're using Bootstrap. I just like the naming scheme --> <!--suppress CssUnusedSymbol --> <style> .text-end { text-align: end; } .form-group { display: block; padding: 5px 0; } .text-danger { color: #f00; } .text-success { color: #050; } .table-responsive { min-height: 20vh; max-height: 99.9vh; min-width: 20vh; max-width: 99.9vh; overflow: auto; } .btn { margin: 0.75vh 1vw; padding: 0.5vh 1vw; } .btn-primary { color: #fff; background-color: #337ab7; border-color: #2e6da4; border-radius: 5%; } .alert { display: block; height: auto; line-height: 1em; max-width: 50%; padding: 0.6vh 3vw; margin: 0.5vh 1vw; border-radius: 5%; } .alert-danger { color: #a94442; background-color: #f2dede; border-color: #ebccd1; } .alert-success { color: #3c763d; background-color: #dff0d8; border-color: #d6e9c6; } .alert-info { color: #31708f; background-color: #d9edf7; border-color: #bce8f1; } .alert .alert-links { margin-top: 1.1em; } .alert .alert-title { display: block; font-weight: 700; font-size: 1.125em; line-height: 1em; margin-bottom: 0.2vh; } </style> <?php /** * ItemHandler * all-in-one class for imadd, inventory, itembuy, iteminfo, itemsell, itemsend, itemuse, equip, unequip */ class ItemHandler { // Don't touch these private database $db; private array $ir; private headers $headers; private ?string $action; private ?int $id; // Do touch these! private const SECURITY_TIMEOUT = 'Your request has timed out for security reasons'; private const NO_INVENTORY = 'You don\'t have any items in your inventory'; private const INVALID_ITEM = 'You didn\'t select a valid item'; private const INVALID_QUANTITY = 'You didn\'t enter a valid quantity'; private const INVALID_EQUIP_SLOT = 'You didn\'t provide a valid equipment slot'; private const INVALID_PRICE = 'You didn\'t enter a valid price'; private const INVALID_CURRENCY = 'You didn\'t selected a valid currency'; private const INVALID_USER = 'You didn\'t select a valid user'; private const USER_NOT_EXISTS = 'Your intended recipient doesn\'t exist'; private const ITEM_NOT_EXISTS = 'The item you selected doesn\'t exist'; private const EQUIP_NOT_EXISTS = 'You don\'t have that item equipped'; private const ITEM_NOT_BUYABLE = 'You can\'t buy that item'; private const ITEM_NOT_EQUIPPABLE = 'You can\'t equip that item'; private const ITEM_NOT_USABLE = 'You can\'t use that item'; private const INSUFFICIENT_FUNDS = 'You don\'t have enough money'; private const NOT_ENOUGH_ITEMS = 'You don\'t have enough of those'; private const WORTHLESS_ITEMS = 'You can\'t sell worthless items'; private const TRANSFER_NOT_PERMITTED = 'You can\'t transfer items to that player'; private const SELF_TRANSFER_NOT_PERMITTED = 'You can\'t transfer items to yourself'; private const ITEM_PLAYER_LOCATION_MISMATCH = 'You can\'t buy items from other locations'; private const ITEM_ADDED_TO_MARKET = 'You\'ve added %sx %s to the item market for %s'; private const ITEM_PURCHASED = 'You bought %sx %s for %s'; private const ITEM_SOLD = 'You sold %sx %s for %s'; private const ITEM_TRANSFERRED = 'You sent %sx %s to %s'; private const ITEM_USED = 'You used %s'; /** * true: prevents the player from selling items if the sell value is 0 * false: allows the player to use the sell items as a trashing function; permitting sales of items regardless of sell value * @var bool preventWorthlessSales */ private bool $preventWorthlessSales = false; private string $table_users_stats = 'userstats'; private string $table_users = 'users'; private array $bar_cols = ['energy', 'will', 'brave', 'hp']; private array $stat_cols = ['strength', 'agility', 'guard', 'labour', 'IQ']; private array $currencies = ['money', 'crystals']; private array $equipSlots = ['equip_primary', 'equip_secondary', 'equip_armor']; /** * @param database $db * @param array $ir * @param headers $h * @param string|null $action * @param int|null $id */ public function __construct(database $db, array $ir, headers $h, ?string $action = null, ?int $id = null) { $this->db = $db; $this->ir = $ir; $this->headers = $h; $this->action = $action; $this->id = $id; } /** * @return void */ public function run() { switch ($this->action) { case 'buy': $this->itemPurchase(); break; case 'info': $this->itemInfo(); break; case 'sell': $this->itemSell(); break; case 'send': $this->itemSend(); break; case 'use': $this->itemUse(); break; case 'market-add': $this->itemMarketAdd(); break; case 'unequip': $this->doItemUnequip(); break; case 'equip': $this->itemEquip(); break; default: $this->inventory(); break; } } /** * @return array */ private function getEquippedItems(): array { $items = []; // Maps the equipSlots to the user's equipped items, removes 0 values and duplicates $equipped_ids = array_unique(array_filter(array_map(function ($slot) { return $this->ir[$slot]; }, $this->equipSlots))); if (!empty($equipped_ids)) { $get_items = $this->db->query( 'SELECT itmid, itmname FROM items WHERE itmid IN (' . implode(', ', $equipped_ids) . ')', ); while ($row = $this->db->fetch_row($get_items)) { $items[$row['itmid']] = $row['itmname']; } $this->db->free_result($get_items); } return $items; } /** * @param array $row * @return bool */ private function hasEffect(array $row): bool { return $row['effect1_on'] || $row['effect2_on'] || $row['effect3_on']; } // ----------------------------------------- /** * @param array $equip * @return void */ private function renderEquips(array $equip): void { $slots = [ 'primary' => $equip[$this->ir['equip_primary']] ?? '', 'secondary' => $equip[$this->ir['equip_secondary']] ?? '', 'armor' => $equip[$this->ir['equip_armor']] ?? '', ]; $code = request_csrf_code('verf'); ?> <div class="table-responsive"> <table class="table"> <?php foreach ($slots as $slot => $item) { ?> <tr> <th scope="row"><?php echo $slot === 'armor' ? 'Armor' : ucfirst($slot) . ' Weapon'; ?></th> <?php if (!empty($item)) { $slot_col = 'equip_' . $slot; ?> <td><?php echo $item; ?></td> <td><a href="/inventory.php?action=unequip&type=<?php echo $slot_col; ?>&id=<?php echo $this->ir[$slot_col]; ?>&verf=<?php echo $code; ?>">Unequip Item</a></td> <?php } else { ?> <td>None equipped.</td> <td>&nbsp;</td> <?php } ?> </tr> <?php } ?> </table> </div> <hr> <?php } /** * @return void */ private function renderInventory(): void { $get_inventory = $this->db->query( 'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname, i.itmsellprice, i.effect1_on, i.effect2_on, i.effect3_on, i.weapon, i.armor, it.itmtypename FROM inventory AS inv INNER JOIN items AS i ON inv.inv_itemid = i.itmid INNER JOIN itemtypes AS it ON it.itmtypeid = i.itmtype WHERE inv.inv_userid = ' . $this->ir['userid'] . ' ORDER BY i.itmtype, i.itmname' ); if (!$this->db->num_rows($get_inventory)) { $this->alert('info', self::NO_INVENTORY); } $code = request_csrf_code('verf'); ?> <h3>Inventory</h3> <div class="table-responsive"> <table class="table"> <thead> <tr> <th scope="col">Item</th> <th scope="col">Sell Value</th> <th scope="col">Total Sell Value</th> <th scope="col">Links</th> </tr> </thead> <tbody> <?php $last_type = ''; $total_inventory_value = 0; while ($row = $this->db->fetch_row($get_inventory)) { $total_inventory_value += $row['itmsellprice'] * $row['inv_qty']; if ($last_type !== $row['itmtypename']) { $last_type = $row['itmtypename']; ?> <tr> <td colspan="4"> <strong><?php echo $last_type; ?></strong> </td> </tr> <?php } $prefix = ''; if ($row['weapon'] > 0) { $prefix .= '<span class="text-danger">*</span>'; } if ($row['armor'] > 0) { $prefix .= '<span class="text-success">*</span>'; } ?> <tr> <td><?php echo $prefix . $row['itmname'] . ($row['inv_qty'] > 1 ? ' x' . number_format((int)$row['inv_qty']) : ''); ?></td> <td><?php echo money_formatter($row['itmsellprice']); ?></td> <td><?php echo money_formatter($row['itmsellprice'] * $row['inv_qty']); ?></td> <td> [<a href="inventory.php?action=info&id=<?php echo $row['itmid']; ?>">Info</a>] [<a href="inventory.php?action=send&id=<?php echo $row['inv_id']; ?>">Send</a>] [<a href="inventory.php?action=sell&id=<?php echo $row['inv_id']; ?>">Sell</a>] [<a href="inventory.php?action=market-add&id=<?php echo $row['inv_id']; ?>">Add To Market</a>] <?php if ($this->hasEffect($row)) { ?> [<a href="inventory.php?action=use&id=<?php echo $row['inv_id']; ?>">Use</a>] <?php } if ($row['weapon'] > 0) { ?> [<a href="inventory.php?action=equip&id=<?php echo $row['inv_id']; ?>&verf=<?php echo $code; ?>&type=weapon">Equip as Weapon</a>] <?php } if ($row['armor'] > 0) { ?> [<a href="inventory.php?action=equip&id=<?php echo $row['inv_id']; ?>&verf=<?php echo $code; ?>&type=armor">Equip as Armor</a>] <?php } ?> </td> </tr> <?php } ?> <tr> <td colspan="4">&nbsp;</td> </tr> <tr> <td colspan="4" class="text-end"> <strong>Total Inventory Value:</strong> <?php echo money_formatter($total_inventory_value); ?> </td> </tr> </tbody> </table> </div> <p> <small><strong>NB:</strong> Items with a small red </small><span class="text-danger">*</span><small> next to their name can be used as weapons in combat.</small><br> <small>Items with a small green </small><span class="text-success">*</span><small> next to their name can be used as armor in combat.</small> </p> <?php $this->db->free_result($get_inventory); } /** * @return void */ private function inventory() { $this->renderEquips($this->getEquippedItems()); $this->renderInventory(); } // ----------------------------------------- /** * @param array $row * @return void */ private function renderItemInfo(array $row): void { ?> <h3>Item Information</h3> <table class="table" style="width: 75%;"> <thead> <tr> <th colspan="2" style="font-weight: 700;"> Looking up info on <?php echo $row['itmname']; ?> </th> </tr> </thead> <tbody> <tr> <td colspan="2"> The <?php echo $row['itmname']; ?> is <?php echo $this->aAn($row['itmtypename']); ?> Item<br> <p> <?php echo $row['itmdesc']; ?> </p> </td> </tr> </tbody> <thead> <tr> <th colspan="2">Item Info</th> </tr> <tr> <th scope="col">Item Buy Price</th> <th scope="col">Item Sell Price</th> </tr> </thead> <tbody> <tr> <td><?php echo $row['itmbuyprice'] > 0 ? money_formatter($row['itmbuyprice']) : 'N/A'; ?></td> <td><?php echo $row['itmsellprice'] > 0 ? money_formatter($row['itmsellprice']) : 'N/A'; ?></td> </tr> </tbody> </table> <p> <a href="inventory.php">Back to Inventory</a> </p> <?php } /** * @return void */ private function itemInfo(): void { if (!$this->id) { $this->alert('error', self::INVALID_ITEM); } $get_item = $this->db->query( 'SELECT i.itmid, i.itmname, i.itmdesc, i.itmbuyprice, i.itmsellprice, it.itmtypename FROM items AS i INNER JOIN itemtypes AS it ON it.itmtypeid = i.itmtype WHERE i.itmid = ' . $this->id . ' LIMIT 1' ); if (!$this->db->num_rows($get_item)) { $this->alert('error', self::ITEM_NOT_EXISTS); } $row = $this->db->fetch_row($get_item); $this->db->free_result($get_item); $this->renderItemInfo($row); } // ----------------------------------------- /** * @param array $row * @return void */ private function renderItemSell(array $row): void { $code = request_csrf_code('sell_item_' . $row['inv_id']); ?> <h3>Sell Item</h3> <p> Enter the amount of <?php echo $this->pluralize($row['itmname'], 0); ?> you want to sell. You have <strong><?php echo $row['inv_qty']; ?></strong>.<br> <?php if ($row['inv_qty'] > 1) { ?> Altogether, they are worth <?php echo money_formatter($row['inv_qty'] * $row['itmsellprice']); ?>.<br> <?php } ?> <span class="text-italic">Note: There is no confirmation. Be sure you've entered the amount you want to sell.</span> </p> <form action="inventory.php?action=sell&id=<?php echo $row['inv_id']; ?>" method="post"> <input type="hidden" name="verf" value="<?php echo $code; ?>" /> <div class="form-group"> <label for="qty">Quantity</label> <input type="number" name="qty" id="qty" class="form-control" placeholder="0" required> </div> <button type="submit" class="btn btn-primary"> Sell Items </button> </form> <?php } /** * @param array $row * @return array */ private function doItemSell(array $row): array { $qty = array_key_exists('qty', $_POST) && is_numeric($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : null; if (empty($_POST['qty'])) { return [ 'type' => 'error', 'content' => self::INVALID_QUANTITY, ]; } if ($qty > $row['inv_qty']) { return [ 'type' => 'error', 'content' => self::NOT_ENOUGH_ITEMS, ]; } $value = $qty * $row['itmsellprice']; if ($this->preventWorthlessSales && !$value) { return [ 'type' => 'error', 'content' => self::WORTHLESS_ITEMS, ]; } $formatted_value = money_formatter($value); item_remove($this->ir['userid'], $row['itmid'], $qty); $this->db->query( 'UPDATE users SET money = money + ' . $value . ' WHERE userid = ' . $this->ir['userid'] ); // At this point, consider parameterised queries. $this->db->query( sprintf( 'INSERT INTO itemselllogs (isUSER, isITEM, isTOTALPRICE, isQTY, isTIME, isCONTENT) VALUES (%u, %u, %u, %u, %u, \'%s\')', $this->ir['userid'], $row['itmid'], $value, $qty, time(), $this->db->escape($this->ir['username'] . ' sold ' . $qty . ' ' . $this->pluralize($row['itmname'], $qty) . ' for ' . $formatted_value) ) ); return [ 'type' => 'success', 'content' => sprintf(self::ITEM_SOLD, number_format($qty), $this->pluralize($row['itmname'], $qty), $formatted_value), ]; } /** * @return void */ private function itemSell(): void { if (!$this->id) { $this->alert('error', self::INVALID_ITEM); } $get_item = $this->db->query( 'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname, i.itmsellprice FROM inventory AS inv INNER JOIN items AS i ON i.itmid = inv.inv_itemid WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . ' LIMIT 1' ); if (!$this->db->num_rows($get_item)) { $this->alert('error', self::ITEM_NOT_EXISTS); } $row = $this->db->fetch_row($get_item); $this->db->free_result($get_item); $response = array_key_exists('verf', $_POST) && verify_csrf_code('sell_item_' . $row['inv_id'], stripslashes($_POST['verf'])) ? $this->doItemSell($row) : null; if (!empty($response)) { $this->alert($response['type'], $response['content']); } $this->renderItemSell($row); } // ----------------------------------------- /** * @return void */ private function itemPurchase(): void { $qty = array_key_exists('qty', $_POST) && is_numeric($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : null; if (empty($qty)) { $this->alert('error', self::INVALID_QUANTITY); } if (!$this->id) { $this->alert('error', self::INVALID_ITEM); } $get_item = $this->db->query( 'SELECT s.shopLOCATION, i.itmid, i.itmname, i.itmbuyable, i.itmbuyprice FROM shopitems AS si INNER JOIN shops AS s ON s.shopID = si.sitemSHOP INNER JOIN items AS i ON i.itmid = si.sitemITEMID WHERE si.sitemITEMID = ' . $this->id ); if (!$this->db->num_rows($get_item)) { $this->alert('error', self::ITEM_NOT_EXISTS); } $row = $this->db->fetch_row($get_item); $this->db->free_result($get_item); if (!$row['itmbuyable']) { $this->alert('error', self::ITEM_NOT_BUYABLE); } if ($row['shopLOCATION'] !== $this->ir['location']) { $this->alert('error', self::ITEM_PLAYER_LOCATION_MISMATCH); } $total_value = $qty * (int)$row['itmbuyprice']; if ($total_value > $this->ir['money']) { $this->alert('error', self::INSUFFICIENT_FUNDS); } item_add($this->ir['userid'], $row['itmid'], $qty); $this->db->query( 'UPDATE users SET money = money - ' . $total_value . ' WHERE userid = ' . $this->ir['userid'] ); $this->db->query( sprintf( 'INSERT INTO itembuylogs (ibUSER, ibITEM, ibTOTALPRICE, ibQTY, ibTIME, ibCONTENT) VALUES (%u, %u, %u, %u, %u, \'%s\')', $this->ir['userid'], $row['itmid'], $total_value, $qty, time(), $this->db->escape($this->ir['username'] . ' purchased ' . $qty . ' ' . $this->pluralize($row['itmname'], $qty) . ' for ' . money_formatter($total_value)) ) ); $this->alert('success', sprintf(self::ITEM_PURCHASED, number_format($qty), $this->pluralize($row['itmname'], $qty), money_formatter($total_value))); } // ----------------------------------------- /** * @param array $row * @return string[] */ private function doItemSend(array $row): array { $target_id = array_key_exists('user', $_POST) && is_numeric($_POST['user']) && (int)$_POST['user'] > 0 ? (int)$_POST['user'] : null; $qty = array_key_exists('qty', $_POST) && is_numeric($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : null; if ($qty > $row['inv_qty']) { return [ 'type' => 'error', 'content' => self::NOT_ENOUGH_ITEMS ]; } if (empty($target_id)) { return [ 'type' => 'error', 'content' => self::INVALID_USER ]; } if ($target_id === $this->ir['userid']) { return [ 'type' => 'error', 'content' => self::SELF_TRANSFER_NOT_PERMITTED ]; } $get_target = $this->db->query( 'SELECT userid, username, lastip FROM users WHERE userid = ' . $target_id ); if (!$this->db->num_rows($get_target)) { return [ 'type' => 'error', 'content' => self::USER_NOT_EXISTS ]; } $target = $this->db->fetch_row($get_target); $this->db->free_result($get_target); if ($target['lastip'] === $this->ir['lastip']) { return [ 'type' => 'error', 'content' => self::TRANSFER_NOT_PERMITTED ]; } item_remove($this->ir['userid'], $row['itmid'], $qty); item_add($target['userid'], $row['itmid'], $qty); event_add($target['userid'], 'You received ' . number_format($qty) . ' ' . $this->pluralize($row['itmname'], $qty) . ' from ' . $this->ir['username']); $this->db->query( sprintf( 'INSERT INTO itemxferlogs (ixFROM, ixTO, ixITEM, ixQTY, ixTIME, ixFROMIP, ixTOIP) VALUES (%u, %u, %u, %u, %u, \'%s\', \'%s\')', $this->ir['userid'], $target['userid'], $row['itmid'], $qty, time(), $this->ir['lastip'], $target['lastip'] ) ); return [ 'type' => 'success', 'content' => sprintf(self::ITEM_TRANSFERRED, number_format($qty), $this->pluralize($row['itmname'], $qty), $target['username']) ]; } /** * @param array $row * @param int|null $get_target_id * @return void */ private function renderItemSend(array $row, ?int $get_target_id = null): void { $code = request_csrf_code('send_item_' . $row['inv_id']); ?> <h3>Send Item</h3> <p> Enter the amount of <?php echo $this->pluralize($row['itmname'], 0); ?> you want to send. You have <strong><?php echo $row['inv_qty']; ?></strong>.<br> <span class="text-italic">Note: There is no confirmation. Be sure you've entered the amount you want to send.</span> </p> <form action="inventory.php?action=send&id=<?php echo $row['inv_id']; ?>" method="post"> <input type="hidden" name="verf" value="<?php echo $code; ?>" /> <div class="form-group"> <label for="user">User ID:</label> <input type="number" name="user" id="user" class="form-control" placeholder="0" value="<?php echo $get_target_id; ?>" required> </div> <div class="form-group"> <label for="qty">Quantity</label> <input type="number" name="qty" id="qty" class="form-control" placeholder="0" required> </div> <button type="submit" class="btn btn-primary"> Send Items </button> </form> <?php } /** * @return void */ private function itemSend(): void { if (!$this->id) { $this->alert('error', self::INVALID_ITEM); } $get_item = $this->db->query( 'SELECT inv.inv_id, inv.inv_qty, inv.inv_itemid, i.itmid, i.itmname FROM inventory AS inv INNER JOIN items AS i ON inv.inv_itemid = i.itmid WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . ' LIMIT 1' ); if (!$this->db->num_rows($get_item)) { $this->alert('error', self::ITEM_NOT_EXISTS); } $row = $this->db->fetch_row($get_item); $this->db->free_result($get_item); $response = array_key_exists('verf', $_POST) && verify_csrf_code('send_item_' . $this->id, stripslashes($_POST['verf'])) ? $this->doItemSend($row) : null; if (!empty($response)) { $this->alert($response['type'], $response['content']); } $get_target_id = array_key_exists('user', $_GET) && is_numeric($_GET['user']) && (int)$_GET['user'] > 0 ? (int)$_GET['user'] : null; $this->renderItemSend($row, $get_target_id); } // ----------------------------------------- /** * @return void */ private function itemUse(): void { if (!$this->id) { $this->alert('error', self::INVALID_ITEM); } $get_item = $this->db->query( 'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname, i.effect1_on, i.effect2_on, i.effect3_on, i.effect1, i.effect2, i.effect3 FROM inventory AS inv INNER JOIN items AS i ON i.itmid = inv.inv_itemid WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . ' LIMIT 1' ); if (!$this->db->num_rows($get_item)) { $this->alert('error', self::ITEM_NOT_EXISTS); } $row = $this->db->fetch_row($get_item); $this->db->free_result($get_item); if (!$this->hasEffect($row)) { $this->alert('error', self::ITEM_NOT_USABLE); } for ($i = 1; $i <= 3; ++$i) { if (!$row['effect' . $i . '_on']) { continue; } $effect = unserialize($row['effect' . $i]); $max_stat = 'max' . $effect['stat']; $inc_amount = $effect['inc_type'] === 'percent' ? (in_array($effect['stat'], $this->bar_cols) ? round($this->ir[$max_stat] / 100 * $effect['inc_amount']) : round($this->ir[$effect['stat']] / 100 * $effect['inc_amount'])) : $effect['inc_amount']; if ($effect['dir'] === 'pos') { if (in_array($effect['stat'], $this->bar_cols)) { $this->ir[$effect['stat']] = min($this->ir[$effect['stat']] + $inc_amount, $this->ir[$max_stat]); } else { $this->ir[$effect['stat']] += $inc_amount; } } else { $this->ir[$effect['stat']] = max($this->ir[$effect['stat']] - $inc_amount, 0); } $table = in_array($effect['stat'], $this->stat_cols) ? $this->table_users_stats : $this->table_users; $this->db->query( 'UPDATE ' . $table . ' SET ' . $effect['stat'] . ' = ' . $this->ir[$effect['stat']] . ' WHERE userid = ' . $this->ir['userid'] ); } item_remove($this->ir['userid'], $row['itmid'], 1); $this->alert('success', sprintf(self::ITEM_USED, $this->aAn($row['itmname']))); } // ----------------------------------------- /** * @param array $row * @return array */ private function doItemMarketAdd(array $row): array { $price = array_key_exists('price', $_POST) && is_numeric($_POST['price']) && (int)$_POST['price'] > 0 ? (int)$_POST['price'] : null; $qty = array_key_exists('qty', $_POST) && is_numeric($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : null; $currency = array_key_exists('currency', $_POST) && in_array($_POST['currency'], $this->currencies) ? $_POST['currency'] : null; if (empty($qty)) { return [ 'type' => 'error', 'content' => self::INVALID_QUANTITY ]; } if (empty($price)) { return [ 'type' => 'error', 'content' => self::INVALID_PRICE ]; } if (empty($currency)) { return [ 'type' => 'error', 'content' => self::INVALID_CURRENCY ]; } if ($qty > $row['inv_qty']) { return [ 'type' => 'error', 'content' => self::NOT_ENOUGH_ITEMS ]; } $get_dupe = $this->db->query( sprintf( 'SELECT imID FROM itemmarket WHERE imITEM = %u AND imPRICE = %u AND imADDER = %u AND imCURRENCY = \'%s\'', $row['itmid'], $price, $this->ir['userid'], $currency ) ); $dupe = $this->db->num_rows($get_dupe) ? $this->db->fetch_single($get_dupe) : null; $this->db->free_result($get_dupe); if ($dupe) { $this->db->query( 'UPDATE itemmarket SET imQTY = imQTY + ' . $qty . ' WHERE imID = ' . $dupe ); } else { $this->db->query( sprintf( 'INSERT INTO itemmarket (imITEM, imADDER, imPRICE, imCURRENCY, imQTY) VALUES (%u, %u, %u, \'%s\', %u)', $row['itmid'], $this->ir['userid'], $price, $currency, $qty ) ); } item_remove($this->ir['userid'], $row['itmid'], $qty); $this->db->query( sprintf( 'INSERT INTO imarketaddlogs (imaITEM, imaPRICE, imaINVID, imaADDER, imaTIME, imaCONTENT) VALUES (%u, %u, %u, %u, %u, \'%s\')', $row['itmid'], $price, $row['inv_id'], $this->ir['userid'], time(), $this->db->escape($this->ir['username'] . ' added ' . $qty . ' ' . $this->pluralize($row['itmname'], $qty) . ' to the item market for ' . money_formatter($price)) ) ); return [ 'type' => 'success', 'content' => sprintf(self::ITEM_ADDED_TO_MARKET, $qty, $this->pluralize($row['itmname'], $qty), money_formatter($price)) ]; } /** * @param array $row * @return void */ private function renderItemMarketAdd(array $row): void { $code = request_csrf_code('market_item_' . $this->id); ?> <h3>Add Item to Market</h3> <p> Enter the amount of <?php echo $this->pluralize($row['itmname'], 0); ?> you want to list on the item market. You have <strong><?php echo $row['inv_qty']; ?></strong>.<br> Set the currency you want to receive and the price for <em>each</em> item. </p> <form action="inventory.php?action=market-add&id=<?php echo $this->id; ?>" method="post"> <input type="hidden" name="verf" value="<?php echo $code; ?>" /> <div class="form-group"> <label for="qty">Quantity</label> <input type="number" name="qty" id="qty" class="form-control" placeholder="0" required> </div> <div class="form-group"> <label for="price">Price</label> <input type="number" name="price" id="price" class="form-control" placeholder="0" required> </div> <div class="form-group"> <label for="currency">Currency</label> <select name="currency" id="currency" class="form-control"> <?php foreach ($this->currencies as $currency) { printf('<option value="%s">%s</option>', $currency, ucfirst($currency)); } ?> </select> </div> <button type="submit" class="btn btn-primary"> Add Item To Market </button> </form> <?php } /** * @return void */ private function itemMarketAdd(): void { if (!$this->id) { $this->alert('error', self::INVALID_ITEM); } $get_item = $this->db->query( 'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname FROM inventory AS inv INNER JOIN items AS i ON inv.inv_itemid = i.itmid WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . ' LIMIT 1' ); if (!$this->db->num_rows($get_item)) { $this->alert('error', self::ITEM_NOT_EXISTS); } $row = $this->db->fetch_row($get_item); $this->db->free_result($get_item); $response = array_key_exists('verf', $_POST) && verify_csrf_code('market_item_' . $this->id, stripslashes($_POST['verf'])) ? $this->doItemMarketAdd($row) : null; if (!empty($response)) { $this->alert($response['type'], $response['content']); } $this->renderItemMarketAdd($row); } // ----------------------------------------- /** * @return void */ private function doItemUnequip(): void { $type = array_key_exists('type', $_GET) && in_array($_GET['type'], $this->equipSlots) ? $_GET['type'] : null; if (empty($type)) { $this->alert('error', self::INVALID_EQUIP_SLOT); } if (empty($this->ir[$type])) { $this->alert('error', self::EQUIP_NOT_EXISTS); } item_add($this->ir['userid'], $this->ir[$type], 1); $this->db->query( 'UPDATE users SET ' . $type . ' = 0 WHERE userid = ' . $this->ir['userid'] ); $names = array_map(function ($slot) { $slot = str_replace('equip_', '', $slot); return ucfirst($slot) . ($slot !== 'armor' ? ' Weapon' : ''); }, $this->equipSlots); $this->alert('success', 'The item in your ' . $names[$type] . ' slot has been unequipped.'); } // ----------------------------------------- /** * @param array $row * @return array */ private function doEquipArmor(array $row): array { if (!array_key_exists('verf', $_GET) || !verify_csrf_code('verf', $_GET['verf'])) { return [ 'type' => 'error', 'content' => self::SECURITY_TIMEOUT, ]; } if ($this->ir['equip_armor'] > 0) { item_add($this->ir['userid'], $this->ir['equip_armor'], 1); } item_remove($this->ir['userid'], $row['itmid'], 1); $this->db->query( 'UPDATE users SET equip_armor = ' . $row['itmid'] . ' WHERE userid = ' . $this->ir['userid'] ); return [ 'type' => 'success', 'content' => 'Your armor has been equipped.' ]; } /** * @param array $row * @return string[] */ private function doEquipWeapon(array $row): array { $slots = [...array_slice($this->equipSlots, 0, 2)]; $type = array_key_exists('type', $_POST) && in_array($_POST['type'], $slots) ? $_POST['type'] : null; if (empty($type)) { return [ 'type' => 'error', 'content' => self::INVALID_EQUIP_SLOT ]; } if ($this->ir[$type] > 0) { item_add($this->ir['userid'], $this->ir[$type], 1); } item_remove($this->ir['userid'], $row['itmid'], 1); $this->db->query( 'UPDATE users SET ' . $type . ' = ' . $row['itmid'] . ' WHERE userid = ' . $this->ir['userid'] ); return [ 'type' => 'success', 'content' => 'Your weapon has been equipped.' ]; } /** * @param array $row * @param bool $multi * @return void */ private function renderEquipSelect(array $row, bool $multi = false): void { $response = array_key_exists('equip_' . $row['inv_id'], $_POST) && verify_csrf_code('equip_' . $row['inv_id'], $_POST['equip_' . $row['inv_id']]) ? (array_key_exists('type', $_POST) && $_POST['type'] === 'equip_armor' ? $this->doEquipArmor($row) : $this->doEquipWeapon($row) ) : null; if (!empty($response)) { $this->alert($response['type'], $response['content']); } $code = request_csrf_code('equip_' . $row['inv_id']); ?> <h3>Equip Item</h3> <p> Please choose the slot to equip your <?php echo $row['itmname']; ?>. If you already have an item equipped in that slot, it will be unequipped and returned to your inventory. </p> <form action="inventory.php?action=equip&id=<?php echo $this->id; ?>" method="post"> <input type="hidden" name="equip_<?php echo $row['inv_id']; ?>" value="<?php echo $code; ?>" /> <?php $cnt = 0; foreach ($this->equipSlots as $slot) { if ($slot === 'equip_armor' && !$multi) { continue; } ?> <div class="form-group"> <label for="<?php echo $slot; ?>"> <input type="radio" name="type" id="<?php echo $slot; ?>" value="<?php echo $slot; ?>" <?php echo !$cnt ? 'checked' : ''; ?> /> <?php echo ucfirst(str_replace('equip_', '', $slot)) . ($slot !== 'equip_armor' ? ' Weapon' : ''); ?> </label> </div> <?php ++$cnt; } ?> <button type="submit" class="btn btn-primary"> Equip Item </button> </form> <?php } /** * @return void */ private function itemEquip(): void { if (!$this->id) { $this->alert('error', self::INVALID_ITEM); } $get_item = $this->db->query( 'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname, i.weapon, i.armor FROM inventory AS inv INNER JOIN items AS i ON inv.inv_itemid = i.itmid WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . ' LIMIT 1' ); if (!$this->db->num_rows($get_item)) { $this->alert('error', self::ITEM_NOT_EXISTS); } $row = $this->db->fetch_row($get_item); $this->db->free_result($get_item); if (!$row['weapon'] && !$row['armor']) { $this->alert('error', self::ITEM_NOT_EQUIPPABLE); } if ($row['armor'] && !$row['weapon']) { $response = $this->doEquipArmor($row); $this->alert($response['type'], $response['content']); } elseif ($row['weapon'] && !$row['armor']) { $this->renderEquipSelect($row); } else { $type = array_key_exists('type', $_GET) && in_array($_GET['type'], ['weapon', 'armor']) ? $_GET['type'] : null; if ($type === 'armor') { $response = $this->doEquipArmor($row); $this->alert($response['type'], $response['content']); } $this->renderEquipSelect($row, true); } } // ----------------------------------------- /** * @param string $type * @param string $content * @return void */ private function alert(string $type, string $content): void { $alert = $type === 'error' ? 'danger' : $type; ?> <div class="alert alert-<?php echo $alert; ?>" role="alert"> <span class="alert-title"><?php echo ucfirst($type); ?></span> <?php echo $content; ?> <div class="alert-links"> <a href="inventory.php">Back to Inventory</a> </div> </div> <?php $this->headers->endpage(); exit; } /** * @param string $word * @return string */ private function aAn(string $word): string { $first_letter = substr($word, 0, 1); return in_array($first_letter, ['a', 'e', 'i', 'o', 'u']) ? 'an ' . $word : 'a ' . $word; } /** * Note: This does not respect irregular plurals in the slightest. It's just a quick and dirty way to whack an s on the end if $amount <> 1 and the word doesn't already end in s. * @param string $word * @param int $amount * @return string */ private function pluralize(string $word, int $amount = 1): string { $last_letter = substr($word, -1); return strtolower($last_letter) === 's' || $amount === 1 ? $word : $word . 's'; } } // basic int validation $_GET['id'] = array_key_exists('id', $_GET) && is_numeric($_GET['id']) && (int)$_GET['id'] > 0 ? (int)$_GET['id'] : null; $_GET['action'] ??= null; (new ItemHandler($db, $ir, $h, $_GET['action'], $_GET['id']))->run();

<?php
declare(strict_types=1);
/**
 * For use on MCCodes Version 2.0.5b
 * We shouldn't just redistribute licensed software, so here's a rewrite ;)
 * I do *not* claim this to be efficient or better than the original, it's just a different take on things
 * The length and calculable complexity of this class is ugly. I would recommend splitting this into extendable classes and consider autoloading
 *
 * See the ItemHandler constants for configurable text outputs
 */
global $db, $ir, $h;
require_once __DIR__ . '/globals.php'; ?>
    <!-- Remove this if you're using Bootstrap. I just like the naming scheme -->
    <!--suppress CssUnusedSymbol -->
    <style>
        .text-end {
            text-align: end;
        }

        .form-group {
            display: block;
            padding: 5px 0;
        }

        .text-danger {
            color: #f00;
        }

        .text-success {
            color: #050;
        }

        .table-responsive {
            min-height: 20vh;
            max-height: 99.9vh;
            min-width: 20vh;
            max-width: 99.9vh;
            overflow: auto;
        }

        .btn {
            margin: 0.75vh 1vw;
            padding: 0.5vh 1vw;
        }

        .btn-primary {
            color: #fff;
            background-color: #337ab7;
            border-color: #2e6da4;
            border-radius: 5%;
        }

        .alert {
            display: block;
            height: auto;
            line-height: 1em;
            max-width: 50%;
            padding: 0.6vh 3vw;
            margin: 0.5vh 1vw;
            border-radius: 5%;
        }

        .alert-danger {
            color: #a94442;
            background-color: #f2dede;
            border-color: #ebccd1;
        }

        .alert-success {
            color: #3c763d;
            background-color: #dff0d8;
            border-color: #d6e9c6;
        }

        .alert-info {
            color: #31708f;
            background-color: #d9edf7;
            border-color: #bce8f1;
        }

        .alert .alert-links {
            margin-top: 1.1em;
        }

        .alert .alert-title {
            display: block;
            font-weight: 700;
            font-size: 1.125em;
            line-height: 1em;
            margin-bottom: 0.2vh;
        }
    </style>
<?php

/**
 * ItemHandler
 * all-in-one class for imadd, inventory, itembuy, iteminfo, itemsell, itemsend, itemuse, equip, unequip
 */
class ItemHandler
{
    // Don't touch these
    private database $db;
    private array $ir;
    private headers $headers;
    private ?string $action;
    private ?int $id;

    // Do touch these!
    private const SECURITY_TIMEOUT = 'Your request has timed out for security reasons';
    private const NO_INVENTORY = 'You don\'t have any items in your inventory';
    private const INVALID_ITEM = 'You didn\'t select a valid item';
    private const INVALID_QUANTITY = 'You didn\'t enter a valid quantity';
    private const INVALID_EQUIP_SLOT = 'You didn\'t provide a valid equipment slot';
    private const INVALID_PRICE = 'You didn\'t enter a valid price';
    private const INVALID_CURRENCY = 'You didn\'t selected a valid currency';
    private const INVALID_USER = 'You didn\'t select a valid user';
    private const USER_NOT_EXISTS = 'Your intended recipient doesn\'t exist';
    private const ITEM_NOT_EXISTS = 'The item you selected doesn\'t exist';
    private const EQUIP_NOT_EXISTS = 'You don\'t have that item equipped';
    private const ITEM_NOT_BUYABLE = 'You can\'t buy that item';
    private const ITEM_NOT_EQUIPPABLE = 'You can\'t equip that item';
    private const ITEM_NOT_USABLE = 'You can\'t use that item';
    private const INSUFFICIENT_FUNDS = 'You don\'t have enough money';
    private const NOT_ENOUGH_ITEMS = 'You don\'t have enough of those';
    private const WORTHLESS_ITEMS = 'You can\'t sell worthless items';
    private const TRANSFER_NOT_PERMITTED = 'You can\'t transfer items to that player';
    private const SELF_TRANSFER_NOT_PERMITTED = 'You can\'t transfer items to yourself';
    private const ITEM_PLAYER_LOCATION_MISMATCH = 'You can\'t buy items from other locations';
    private const ITEM_ADDED_TO_MARKET = 'You\'ve added %sx %s to the item market for %s';
    private const ITEM_PURCHASED = 'You bought %sx %s for %s';
    private const ITEM_SOLD = 'You sold %sx %s for %s';
    private const ITEM_TRANSFERRED = 'You sent %sx %s to %s';
    private const ITEM_USED = 'You used %s';
    /**
     * true: prevents the player from selling items if the sell value is 0
     * false: allows the player to use the sell items as a trashing function; permitting sales of items regardless of sell value
     * @var bool preventWorthlessSales
     */
    private bool $preventWorthlessSales = false;
    private string $table_users_stats = 'userstats';
    private string $table_users = 'users';
    private array $bar_cols = ['energy', 'will', 'brave', 'hp'];
    private array $stat_cols = ['strength', 'agility', 'guard', 'labour', 'IQ'];
    private array $currencies = ['money', 'crystals'];
    private array $equipSlots = ['equip_primary', 'equip_secondary', 'equip_armor'];

    /**
     * @param database $db
     * @param array $ir
     * @param headers $h
     * @param string|null $action
     * @param int|null $id
     */
    public function __construct(database $db, array $ir, headers $h, ?string $action = null, ?int $id = null)
    {
        $this->db = $db;
        $this->ir = $ir;
        $this->headers = $h;
        $this->action = $action;
        $this->id = $id;
    }

    /**
     * @return void
     */
    public function run()
    {
        switch ($this->action) {
            case 'buy':
                $this->itemPurchase();
                break;
            case 'info':
                $this->itemInfo();
                break;
            case 'sell':
                $this->itemSell();
                break;
            case 'send':
                $this->itemSend();
                break;
            case 'use':
                $this->itemUse();
                break;
            case 'market-add':
                $this->itemMarketAdd();
                break;
            case 'unequip':
                $this->doItemUnequip();
                break;
            case 'equip':
                $this->itemEquip();
                break;
            default:
                $this->inventory();
                break;
        }
    }

    /**
     * @return array
     */
    private function getEquippedItems(): array
    {
        $items = [];
        // Maps the equipSlots to the user's equipped items, removes 0 values and duplicates
        $equipped_ids = array_unique(array_filter(array_map(function ($slot) {
            return $this->ir[$slot];
        }, $this->equipSlots)));
        if (!empty($equipped_ids)) {
            $get_items = $this->db->query(
                'SELECT itmid, itmname FROM items WHERE itmid IN (' . implode(', ', $equipped_ids) . ')',
            );
            while ($row = $this->db->fetch_row($get_items)) {
                $items[$row['itmid']] = $row['itmname'];
            }
            $this->db->free_result($get_items);
        }
        return $items;
    }

    /**
     * @param array $row
     * @return bool
     */
    private function hasEffect(array $row): bool
    {
        return $row['effect1_on'] || $row['effect2_on'] || $row['effect3_on'];
    }
    // -----------------------------------------

    /**
     * @param array $equip
     * @return void
     */
    private function renderEquips(array $equip): void
    {
        $slots = [
            'primary'   => $equip[$this->ir['equip_primary']] ?? '',
            'secondary' => $equip[$this->ir['equip_secondary']] ?? '',
            'armor'     => $equip[$this->ir['equip_armor']] ?? '',
        ];
        $code = request_csrf_code('verf'); ?>
        <div class="table-responsive">
            <table class="table">
                <?php
                foreach ($slots as $slot => $item) {
                    ?>
                    <tr>
                        <th scope="row"><?php echo $slot === 'armor' ? 'Armor' : ucfirst($slot) . ' Weapon'; ?></th>
                        <?php
                        if (!empty($item)) {
                            $slot_col = 'equip_' . $slot; ?>
                            <td><?php echo $item; ?></td>
                            <td><a href="/inventory.php?action=unequip&type=<?php echo $slot_col; ?>&id=<?php echo $this->ir[$slot_col]; ?>&verf=<?php echo $code; ?>">Unequip Item</a></td>
                            <?php
                        } else {
                            ?>
                            <td>None equipped.</td>
                            <td>&nbsp;</td>
                            <?php
                        } ?>
                    </tr>
                    <?php
                } ?>
            </table>
        </div>
        <hr>
        <?php
    }

    /**
     * @return void
     */
    private function renderInventory(): void
    {
        $get_inventory = $this->db->query(
            'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname, i.itmsellprice, i.effect1_on, i.effect2_on, i.effect3_on, i.weapon, i.armor, it.itmtypename
            FROM inventory AS inv
            INNER JOIN items AS i ON inv.inv_itemid = i.itmid
            INNER JOIN itemtypes AS it ON it.itmtypeid = i.itmtype
            WHERE inv.inv_userid = ' . $this->ir['userid'] . '
            ORDER BY i.itmtype, i.itmname'
        );
        if (!$this->db->num_rows($get_inventory)) {
            $this->alert('info', self::NO_INVENTORY);
        }
        $code = request_csrf_code('verf'); ?>
        <h3>Inventory</h3>
        <div class="table-responsive">
            <table class="table">
                <thead>
                <tr>
                    <th scope="col">Item</th>
                    <th scope="col">Sell Value</th>
                    <th scope="col">Total Sell Value</th>
                    <th scope="col">Links</th>
                </tr>
                </thead>
                <tbody>
                <?php $last_type = '';
                $total_inventory_value = 0;
                while ($row = $this->db->fetch_row($get_inventory)) {
                    $total_inventory_value += $row['itmsellprice'] * $row['inv_qty'];
                    if ($last_type !== $row['itmtypename']) {
                        $last_type = $row['itmtypename']; ?>
                        <tr>
                            <td colspan="4">
                                <strong><?php echo $last_type; ?></strong>
                            </td>
                        </tr>
                        <?php
                    }
                    $prefix = '';
                    if ($row['weapon'] > 0) {
                        $prefix .= '<span class="text-danger">*</span>';
                    }
                    if ($row['armor'] > 0) {
                        $prefix .= '<span class="text-success">*</span>';
                    } ?>
                    <tr>
                        <td><?php echo $prefix . $row['itmname'] . ($row['inv_qty'] > 1 ? ' x' . number_format((int)$row['inv_qty']) : ''); ?></td>
                        <td><?php echo money_formatter($row['itmsellprice']); ?></td>
                        <td><?php echo money_formatter($row['itmsellprice'] * $row['inv_qty']); ?></td>
                        <td>
                            [<a href="inventory.php?action=info&id=<?php echo $row['itmid']; ?>">Info</a>]
                            [<a href="inventory.php?action=send&id=<?php echo $row['inv_id']; ?>">Send</a>]
                            [<a href="inventory.php?action=sell&id=<?php echo $row['inv_id']; ?>">Sell</a>]
                            [<a href="inventory.php?action=market-add&id=<?php echo $row['inv_id']; ?>">Add To Market</a>]
                            <?php
                            if ($this->hasEffect($row)) {
                                ?>
                                [<a href="inventory.php?action=use&id=<?php echo $row['inv_id']; ?>">Use</a>]
                                <?php
                            }
                            if ($row['weapon'] > 0) {
                                ?>
                                [<a href="inventory.php?action=equip&id=<?php echo $row['inv_id']; ?>&verf=<?php echo $code; ?>&type=weapon">Equip as Weapon</a>]
                                <?php
                            }
                            if ($row['armor'] > 0) {
                                ?>
                                [<a href="inventory.php?action=equip&id=<?php echo $row['inv_id']; ?>&verf=<?php echo $code; ?>&type=armor">Equip as Armor</a>]
                                <?php
                            } ?>
                        </td>
                    </tr>
                    <?php
                } ?>
                <tr>
                    <td colspan="4">&nbsp;</td>
                </tr>
                <tr>
                    <td colspan="4" class="text-end">
                        <strong>Total Inventory Value:</strong> <?php echo money_formatter($total_inventory_value); ?>
                    </td>
                </tr>
                </tbody>
            </table>
        </div>
        <p>
            <small><strong>NB:</strong> Items with a small red </small><span class="text-danger">*</span><small> next to their name can be used as weapons in combat.</small><br>
            <small>Items with a small green </small><span class="text-success">*</span><small> next to their name can be used as armor in combat.</small>
        </p>
        <?php $this->db->free_result($get_inventory);


    }

    /**
     * @return void
     */
    private function inventory()
    {
        $this->renderEquips($this->getEquippedItems());
        $this->renderInventory();
    }
    // -----------------------------------------

    /**
     * @param array $row
     * @return void
     */
    private function renderItemInfo(array $row): void
    {
        ?>
        <h3>Item Information</h3>
        <table class="table" style="width: 75%;">
            <thead>
            <tr>
                <th colspan="2" style="font-weight: 700;">
                    Looking up info on <?php echo $row['itmname']; ?>
                </th>
            </tr>
            </thead>
            <tbody>
            <tr>
                <td colspan="2">
                    The <?php echo $row['itmname']; ?> is <?php echo $this->aAn($row['itmtypename']); ?> Item<br>
                    <p>
                        <?php echo $row['itmdesc']; ?>
                    </p>
                </td>
            </tr>
            </tbody>
            <thead>
            <tr>
                <th colspan="2">Item Info</th>
            </tr>
            <tr>
                <th scope="col">Item Buy Price</th>
                <th scope="col">Item Sell Price</th>
            </tr>
            </thead>
            <tbody>
            <tr>
                <td><?php echo $row['itmbuyprice'] > 0 ? money_formatter($row['itmbuyprice']) : 'N/A'; ?></td>
                <td><?php echo $row['itmsellprice'] > 0 ? money_formatter($row['itmsellprice']) : 'N/A'; ?></td>
            </tr>
            </tbody>
        </table>
        <p>
            <a href="inventory.php">Back to Inventory</a>
        </p>
        <?php
    }

    /**
     * @return void
     */
    private function itemInfo(): void
    {
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT i.itmid, i.itmname, i.itmdesc, i.itmbuyprice, i.itmsellprice, it.itmtypename
            FROM items AS i
            INNER JOIN itemtypes AS it ON it.itmtypeid = i.itmtype
            WHERE i.itmid = ' . $this->id . '
            LIMIT 1'
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        $this->renderItemInfo($row);
    }

    // -----------------------------------------

    /**
     * @param array $row
     * @return void
     */
    private function renderItemSell(array $row): void
    {
        $code = request_csrf_code('sell_item_' . $row['inv_id']); ?>
        <h3>Sell Item</h3>
        <p>
            Enter the amount of <?php echo $this->pluralize($row['itmname'], 0); ?> you want to sell. You have <strong><?php echo $row['inv_qty']; ?></strong>.<br>
            <?php
            if ($row['inv_qty'] > 1) {
                ?>
                Altogether, they are worth <?php echo money_formatter($row['inv_qty'] * $row['itmsellprice']); ?>.<br>
                <?php
            } ?>
            <span class="text-italic">Note: There is no confirmation. Be sure you've entered the amount you want to sell.</span>
        </p>
        <form action="inventory.php?action=sell&id=<?php echo $row['inv_id']; ?>" method="post">
            <input type="hidden" name="verf" value="<?php echo $code; ?>" />
            <div class="form-group">
                <label for="qty">Quantity</label>
                <input type="number" name="qty" id="qty" class="form-control" placeholder="0" required>
            </div>
            <button type="submit" class="btn btn-primary">
                Sell Items
            </button>
        </form>
        <?php
    }

    /**
     * @param array $row
     * @return array
     */
    private function doItemSell(array $row): array
    {
        $qty = array_key_exists('qty', $_POST) && is_numeric($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : null;
        if (empty($_POST['qty'])) {
            return [
                'type'    => 'error',
                'content' => self::INVALID_QUANTITY,
            ];
        }
        if ($qty > $row['inv_qty']) {
            return [
                'type'    => 'error',
                'content' => self::NOT_ENOUGH_ITEMS,
            ];
        }
        $value = $qty * $row['itmsellprice'];
        if ($this->preventWorthlessSales && !$value) {
            return [
                'type'    => 'error',
                'content' => self::WORTHLESS_ITEMS,
            ];
        }
        $formatted_value = money_formatter($value);
        item_remove($this->ir['userid'], $row['itmid'], $qty);
        $this->db->query(
            'UPDATE users SET money = money + ' . $value . ' WHERE userid = ' . $this->ir['userid']
        );
        // At this point, consider parameterised queries.
        $this->db->query(
            sprintf(
                'INSERT INTO itemselllogs (isUSER, isITEM, isTOTALPRICE, isQTY, isTIME, isCONTENT)
                VALUES (%u, %u, %u, %u, %u, \'%s\')',
                $this->ir['userid'],
                $row['itmid'],
                $value,
                $qty,
                time(),
                $this->db->escape($this->ir['username'] . ' sold ' . $qty . ' ' . $this->pluralize($row['itmname'], $qty) . ' for ' . $formatted_value)
            )
        );
        return [
            'type'    => 'success',
            'content' => sprintf(self::ITEM_SOLD, number_format($qty), $this->pluralize($row['itmname'], $qty), $formatted_value),
        ];
    }

    /**
     * @return void
     */
    private function itemSell(): void
    {
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname, i.itmsellprice
            FROM inventory AS inv
            INNER JOIN items AS i ON i.itmid = inv.inv_itemid
            WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . '
            LIMIT 1'
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        $response = array_key_exists('verf', $_POST) && verify_csrf_code('sell_item_' . $row['inv_id'], stripslashes($_POST['verf'])) ? $this->doItemSell($row) : null;
        if (!empty($response)) {
            $this->alert($response['type'], $response['content']);
        }
        $this->renderItemSell($row);
    }
    // -----------------------------------------

    /**
     * @return void
     */
    private function itemPurchase(): void
    {
        $qty = array_key_exists('qty', $_POST) && is_numeric($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : null;
        if (empty($qty)) {
            $this->alert('error', self::INVALID_QUANTITY);
        }
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT s.shopLOCATION, i.itmid, i.itmname, i.itmbuyable, i.itmbuyprice
            FROM shopitems AS si
            INNER JOIN shops AS s ON s.shopID = si.sitemSHOP
            INNER JOIN items AS i ON i.itmid = si.sitemITEMID
            WHERE si.sitemITEMID = ' . $this->id
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        if (!$row['itmbuyable']) {
            $this->alert('error', self::ITEM_NOT_BUYABLE);
        }
        if ($row['shopLOCATION'] !== $this->ir['location']) {
            $this->alert('error', self::ITEM_PLAYER_LOCATION_MISMATCH);
        }
        $total_value = $qty * (int)$row['itmbuyprice'];
        if ($total_value > $this->ir['money']) {
            $this->alert('error', self::INSUFFICIENT_FUNDS);
        }
        item_add($this->ir['userid'], $row['itmid'], $qty);
        $this->db->query(
            'UPDATE users SET money = money - ' . $total_value . ' WHERE userid = ' . $this->ir['userid']
        );
        $this->db->query(
            sprintf(
                'INSERT INTO itembuylogs (ibUSER, ibITEM, ibTOTALPRICE, ibQTY, ibTIME, ibCONTENT)
                VALUES (%u, %u, %u, %u, %u, \'%s\')',
                $this->ir['userid'],
                $row['itmid'],
                $total_value,
                $qty,
                time(),
                $this->db->escape($this->ir['username'] . ' purchased ' . $qty . ' ' . $this->pluralize($row['itmname'], $qty) . ' for ' . money_formatter($total_value))
            )
        );
        $this->alert('success', sprintf(self::ITEM_PURCHASED, number_format($qty), $this->pluralize($row['itmname'], $qty), money_formatter($total_value)));
    }
    // -----------------------------------------

    /**
     * @param array $row
     * @return string[]
     */
    private function doItemSend(array $row): array
    {
        $target_id = array_key_exists('user', $_POST) && is_numeric($_POST['user']) && (int)$_POST['user'] > 0 ? (int)$_POST['user'] : null;
        $qty = array_key_exists('qty', $_POST) && is_numeric($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : null;
        if ($qty > $row['inv_qty']) {
            return [
                'type'    => 'error',
                'content' => self::NOT_ENOUGH_ITEMS
            ];
        }
        if (empty($target_id)) {
            return [
                'type'    => 'error',
                'content' => self::INVALID_USER
            ];
        }
        if ($target_id === $this->ir['userid']) {
            return [
                'type'    => 'error',
                'content' => self::SELF_TRANSFER_NOT_PERMITTED
            ];
        }
        $get_target = $this->db->query(
            'SELECT userid, username, lastip FROM users WHERE userid = ' . $target_id
        );
        if (!$this->db->num_rows($get_target)) {
            return [
                'type'    => 'error',
                'content' => self::USER_NOT_EXISTS
            ];
        }
        $target = $this->db->fetch_row($get_target);
        $this->db->free_result($get_target);
        if ($target['lastip'] === $this->ir['lastip']) {
            return [
                'type'    => 'error',
                'content' => self::TRANSFER_NOT_PERMITTED
            ];
        }
        item_remove($this->ir['userid'], $row['itmid'], $qty);
        item_add($target['userid'], $row['itmid'], $qty);
        event_add($target['userid'], 'You received ' . number_format($qty) . ' ' . $this->pluralize($row['itmname'], $qty) . ' from ' . $this->ir['username']);
        $this->db->query(
            sprintf(
                'INSERT INTO itemxferlogs (ixFROM, ixTO, ixITEM, ixQTY, ixTIME, ixFROMIP, ixTOIP)
                VALUES (%u, %u, %u, %u, %u, \'%s\', \'%s\')',
                $this->ir['userid'],
                $target['userid'],
                $row['itmid'],
                $qty,
                time(),
                $this->ir['lastip'],
                $target['lastip']
            )
        );
        return [
            'type'    => 'success',
            'content' => sprintf(self::ITEM_TRANSFERRED, number_format($qty), $this->pluralize($row['itmname'], $qty), $target['username'])
        ];
    }

    /**
     * @param array $row
     * @param int|null $get_target_id
     * @return void
     */
    private function renderItemSend(array $row, ?int $get_target_id = null): void
    {
        $code = request_csrf_code('send_item_' . $row['inv_id']); ?>
        <h3>Send Item</h3>
        <p>
            Enter the amount of <?php echo $this->pluralize($row['itmname'], 0); ?> you want to send. You have <strong><?php echo $row['inv_qty']; ?></strong>.<br>
            <span class="text-italic">Note: There is no confirmation. Be sure you've entered the amount you want to send.</span>
        </p>
        <form action="inventory.php?action=send&id=<?php echo $row['inv_id']; ?>" method="post">
            <input type="hidden" name="verf" value="<?php echo $code; ?>" />
            <div class="form-group">
                <label for="user">User ID:</label>
                <input type="number" name="user" id="user" class="form-control" placeholder="0" value="<?php echo $get_target_id; ?>" required>
            </div>
            <div class="form-group">
                <label for="qty">Quantity</label>
                <input type="number" name="qty" id="qty" class="form-control" placeholder="0" required>
            </div>
            <button type="submit" class="btn btn-primary">
                Send Items
            </button>
        </form>
        <?php
    }

    /**
     * @return void
     */
    private function itemSend(): void
    {
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT inv.inv_id, inv.inv_qty, inv.inv_itemid, i.itmid, i.itmname
            FROM inventory AS inv
            INNER JOIN items AS i ON inv.inv_itemid = i.itmid
            WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . '
            LIMIT 1'
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        $response = array_key_exists('verf', $_POST) && verify_csrf_code('send_item_' . $this->id, stripslashes($_POST['verf'])) ? $this->doItemSend($row) : null;

        if (!empty($response)) {
            $this->alert($response['type'], $response['content']);
        }
        $get_target_id = array_key_exists('user', $_GET) && is_numeric($_GET['user']) && (int)$_GET['user'] > 0 ? (int)$_GET['user'] : null;
        $this->renderItemSend($row, $get_target_id);
    }

    // -----------------------------------------

    /**
     * @return void
     */
    private function itemUse(): void
    {
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname, i.effect1_on, i.effect2_on, i.effect3_on, i.effect1, i.effect2, i.effect3
            FROM inventory AS inv
            INNER JOIN items AS i ON i.itmid = inv.inv_itemid
            WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . '
            LIMIT 1'
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        if (!$this->hasEffect($row)) {
            $this->alert('error', self::ITEM_NOT_USABLE);
        }
        for ($i = 1; $i <= 3; ++$i) {
            if (!$row['effect' . $i . '_on']) {
                continue;
            }
            $effect = unserialize($row['effect' . $i]);
            $max_stat = 'max' . $effect['stat'];
            $inc_amount = $effect['inc_type'] === 'percent'
                ? (in_array($effect['stat'], $this->bar_cols)
                    ? round($this->ir[$max_stat] / 100 * $effect['inc_amount'])
                    : round($this->ir[$effect['stat']] / 100 * $effect['inc_amount']))
                : $effect['inc_amount'];
            if ($effect['dir'] === 'pos') {
                if (in_array($effect['stat'], $this->bar_cols)) {
                    $this->ir[$effect['stat']] = min($this->ir[$effect['stat']] + $inc_amount, $this->ir[$max_stat]);
                } else {
                    $this->ir[$effect['stat']] += $inc_amount;
                }
            } else {
                $this->ir[$effect['stat']] = max($this->ir[$effect['stat']] - $inc_amount, 0);
            }
            $table = in_array($effect['stat'], $this->stat_cols) ? $this->table_users_stats : $this->table_users;
            $this->db->query(
                'UPDATE ' . $table . ' SET ' . $effect['stat'] . ' = ' . $this->ir[$effect['stat']] . ' WHERE userid = ' . $this->ir['userid']
            );
        }
        item_remove($this->ir['userid'], $row['itmid'], 1);
        $this->alert('success', sprintf(self::ITEM_USED, $this->aAn($row['itmname'])));
    }
    // -----------------------------------------

    /**
     * @param array $row
     * @return array
     */
    private function doItemMarketAdd(array $row): array
    {
        $price = array_key_exists('price', $_POST) && is_numeric($_POST['price']) && (int)$_POST['price'] > 0 ? (int)$_POST['price'] : null;
        $qty = array_key_exists('qty', $_POST) && is_numeric($_POST['qty']) && (int)$_POST['qty'] > 0 ? (int)$_POST['qty'] : null;
        $currency = array_key_exists('currency', $_POST) && in_array($_POST['currency'], $this->currencies) ? $_POST['currency'] : null;
        if (empty($qty)) {
            return [
                'type'    => 'error',
                'content' => self::INVALID_QUANTITY
            ];
        }
        if (empty($price)) {
            return [
                'type'    => 'error',
                'content' => self::INVALID_PRICE
            ];
        }
        if (empty($currency)) {
            return [
                'type'    => 'error',
                'content' => self::INVALID_CURRENCY
            ];
        }
        if ($qty > $row['inv_qty']) {
            return [
                'type'    => 'error',
                'content' => self::NOT_ENOUGH_ITEMS
            ];
        }
        $get_dupe = $this->db->query(
            sprintf(
                'SELECT imID FROM itemmarket WHERE imITEM = %u AND imPRICE = %u AND imADDER = %u AND imCURRENCY = \'%s\'',
                $row['itmid'],
                $price,
                $this->ir['userid'],
                $currency
            )
        );
        $dupe = $this->db->num_rows($get_dupe) ? $this->db->fetch_single($get_dupe) : null;
        $this->db->free_result($get_dupe);
        if ($dupe) {
            $this->db->query(
                'UPDATE itemmarket SET imQTY = imQTY + ' . $qty . ' WHERE imID = ' . $dupe
            );
        } else {
            $this->db->query(
                sprintf(
                    'INSERT INTO itemmarket (imITEM, imADDER, imPRICE, imCURRENCY, imQTY)
                    VALUES (%u, %u, %u, \'%s\', %u)',
                    $row['itmid'],
                    $this->ir['userid'],
                    $price,
                    $currency,
                    $qty
                )
            );
        }
        item_remove($this->ir['userid'], $row['itmid'], $qty);
        $this->db->query(
            sprintf(
                'INSERT INTO imarketaddlogs (imaITEM, imaPRICE, imaINVID, imaADDER, imaTIME, imaCONTENT)
                VALUES (%u, %u, %u, %u, %u, \'%s\')',
                $row['itmid'],
                $price,
                $row['inv_id'],
                $this->ir['userid'],
                time(),
                $this->db->escape($this->ir['username'] . ' added ' . $qty . ' ' . $this->pluralize($row['itmname'], $qty) . ' to the item market for ' . money_formatter($price))
            )
        );
        return [
            'type'    => 'success',
            'content' => sprintf(self::ITEM_ADDED_TO_MARKET, $qty, $this->pluralize($row['itmname'], $qty), money_formatter($price))
        ];
    }

    /**
     * @param array $row
     * @return void
     */
    private function renderItemMarketAdd(array $row): void
    {
        $code = request_csrf_code('market_item_' . $this->id); ?>
        <h3>Add Item to Market</h3>
        <p>
            Enter the amount of <?php echo $this->pluralize($row['itmname'], 0); ?> you want to list on the item market. You have <strong><?php echo $row['inv_qty']; ?></strong>.<br>
            Set the currency you want to receive and the price for <em>each</em> item.
        </p>
        <form action="inventory.php?action=market-add&id=<?php echo $this->id; ?>" method="post">
            <input type="hidden" name="verf" value="<?php echo $code; ?>" />
            <div class="form-group">
                <label for="qty">Quantity</label>
                <input type="number" name="qty" id="qty" class="form-control" placeholder="0" required>
            </div>
            <div class="form-group">
                <label for="price">Price</label>
                <input type="number" name="price" id="price" class="form-control" placeholder="0" required>
            </div>
            <div class="form-group">
                <label for="currency">Currency</label>
                <select name="currency" id="currency" class="form-control">
                    <?php
                    foreach ($this->currencies as $currency) {
                        printf('<option value="%s">%s</option>', $currency, ucfirst($currency));
                    } ?>
                </select>
            </div>
            <button type="submit" class="btn btn-primary">
                Add Item To Market
            </button>
        </form>
        <?php
    }

    /**
     * @return void
     */
    private function itemMarketAdd(): void
    {
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname
            FROM inventory AS inv
            INNER JOIN items AS i ON inv.inv_itemid = i.itmid
            WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . '
            LIMIT 1'
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        $response = array_key_exists('verf', $_POST) && verify_csrf_code('market_item_' . $this->id, stripslashes($_POST['verf'])) ? $this->doItemMarketAdd($row) : null;
        if (!empty($response)) {
            $this->alert($response['type'], $response['content']);
        }
        $this->renderItemMarketAdd($row);
    }

    // -----------------------------------------

    /**
     * @return void
     */
    private function doItemUnequip(): void
    {
        $type = array_key_exists('type', $_GET) && in_array($_GET['type'], $this->equipSlots) ? $_GET['type'] : null;
        if (empty($type)) {
            $this->alert('error', self::INVALID_EQUIP_SLOT);
        }
        if (empty($this->ir[$type])) {
            $this->alert('error', self::EQUIP_NOT_EXISTS);
        }
        item_add($this->ir['userid'], $this->ir[$type], 1);
        $this->db->query(
            'UPDATE users SET ' . $type . ' = 0 WHERE userid = ' . $this->ir['userid']
        );
        $names = array_map(function ($slot) {
            $slot = str_replace('equip_', '', $slot);
            return ucfirst($slot) . ($slot !== 'armor' ? ' Weapon' : '');
        }, $this->equipSlots);
        $this->alert('success', 'The item in your ' . $names[$type] . ' slot has been unequipped.');
    }

    // -----------------------------------------

    /**
     * @param array $row
     * @return array
     */
    private function doEquipArmor(array $row): array
    {
        if (!array_key_exists('verf', $_GET) || !verify_csrf_code('verf', $_GET['verf'])) {
            return [
                'type'    => 'error',
                'content' => self::SECURITY_TIMEOUT,
            ];
        }
        if ($this->ir['equip_armor'] > 0) {
            item_add($this->ir['userid'], $this->ir['equip_armor'], 1);
        }
        item_remove($this->ir['userid'], $row['itmid'], 1);
        $this->db->query(
            'UPDATE users SET equip_armor = ' . $row['itmid'] . ' WHERE userid = ' . $this->ir['userid']
        );
        return [
            'type'    => 'success',
            'content' => 'Your armor has been equipped.'
        ];
    }

    /**
     * @param array $row
     * @return string[]
     */
    private function doEquipWeapon(array $row): array
    {
        $slots = [...array_slice($this->equipSlots, 0, 2)];
        $type = array_key_exists('type', $_POST) && in_array($_POST['type'], $slots) ? $_POST['type'] : null;
        if (empty($type)) {
            return [
                'type'    => 'error',
                'content' => self::INVALID_EQUIP_SLOT
            ];
        }
        if ($this->ir[$type] > 0) {
            item_add($this->ir['userid'], $this->ir[$type], 1);
        }
        item_remove($this->ir['userid'], $row['itmid'], 1);
        $this->db->query(
            'UPDATE users SET ' . $type . ' = ' . $row['itmid'] . ' WHERE userid = ' . $this->ir['userid']
        );
        return [
            'type'    => 'success',
            'content' => 'Your weapon has been equipped.'
        ];
    }

    /**
     * @param array $row
     * @param bool $multi
     * @return void
     */
    private function renderEquipSelect(array $row, bool $multi = false): void
    {
        $response = array_key_exists('equip_' . $row['inv_id'], $_POST) && verify_csrf_code('equip_' . $row['inv_id'], $_POST['equip_' . $row['inv_id']])
            ? (array_key_exists('type', $_POST) && $_POST['type'] === 'equip_armor' ? $this->doEquipArmor($row) : $this->doEquipWeapon($row)
            ) : null;
        if (!empty($response)) {
            $this->alert($response['type'], $response['content']);
        }
        $code = request_csrf_code('equip_' . $row['inv_id']); ?>
        <h3>Equip Item</h3>
        <p>
            Please choose the slot to equip your <?php echo $row['itmname']; ?>.
            If you already have an item equipped in that slot, it will be unequipped and returned to your inventory.
        </p>
        <form action="inventory.php?action=equip&id=<?php echo $this->id; ?>" method="post">
            <input type="hidden" name="equip_<?php echo $row['inv_id']; ?>" value="<?php echo $code; ?>" />
            <?php
            $cnt = 0;
            foreach ($this->equipSlots as $slot) {
                if ($slot === 'equip_armor' && !$multi) {
                    continue;
                } ?>
                <div class="form-group">
                    <label for="<?php echo $slot; ?>">
                        <input type="radio" name="type" id="<?php echo $slot; ?>" value="<?php echo $slot; ?>" <?php echo !$cnt ? 'checked' : ''; ?> />
                        <?php echo ucfirst(str_replace('equip_', '', $slot)) . ($slot !== 'equip_armor' ? ' Weapon' : ''); ?>
                    </label>
                </div>
                <?php
                ++$cnt;
            } ?>
            <button type="submit" class="btn btn-primary">
                Equip Item
            </button>
        </form>
        <?php
    }

    /**
     * @return void
     */
    private function itemEquip(): void
    {
        if (!$this->id) {
            $this->alert('error', self::INVALID_ITEM);
        }
        $get_item = $this->db->query(
            'SELECT inv.inv_id, inv.inv_qty, i.itmid, i.itmname, i.weapon, i.armor
            FROM inventory AS inv
            INNER JOIN items AS i ON inv.inv_itemid = i.itmid
            WHERE inv.inv_id = ' . $this->id . ' AND inv.inv_userid = ' . $this->ir['userid'] . '
            LIMIT 1'
        );
        if (!$this->db->num_rows($get_item)) {
            $this->alert('error', self::ITEM_NOT_EXISTS);
        }
        $row = $this->db->fetch_row($get_item);
        $this->db->free_result($get_item);
        if (!$row['weapon'] && !$row['armor']) {
            $this->alert('error', self::ITEM_NOT_EQUIPPABLE);
        }
        if ($row['armor'] && !$row['weapon']) {
            $response = $this->doEquipArmor($row);
            $this->alert($response['type'], $response['content']);
        } elseif ($row['weapon'] && !$row['armor']) {
            $this->renderEquipSelect($row);
        } else {
            $type = array_key_exists('type', $_GET) && in_array($_GET['type'], ['weapon', 'armor']) ? $_GET['type'] : null;
            if ($type === 'armor') {
                $response = $this->doEquipArmor($row);
                $this->alert($response['type'], $response['content']);
            }
            $this->renderEquipSelect($row, true);
        }
    }
    // -----------------------------------------

    /**
     * @param string $type
     * @param string $content
     * @return void
     */
    private function alert(string $type, string $content): void
    {
        $alert = $type === 'error' ? 'danger' : $type; ?>
        <div class="alert alert-<?php echo $alert; ?>" role="alert">
            <span class="alert-title"><?php echo ucfirst($type); ?></span>
            <?php echo $content; ?>
            <div class="alert-links">
                <a href="inventory.php">Back to Inventory</a>
            </div>
        </div>
        <?php
        $this->headers->endpage();
        exit;
    }

    /**
     * @param string $word
     * @return string
     */
    private function aAn(string $word): string
    {
        $first_letter = substr($word, 0, 1);
        return in_array($first_letter, ['a', 'e', 'i', 'o', 'u'])
            ? 'an ' . $word
            : 'a ' . $word;
    }

    /**
     * Note: This does not respect irregular plurals in the slightest. It's just a quick and dirty way to whack an s on the end if $amount <> 1 and the word doesn't already end in s.
     * @param string $word
     * @param int $amount
     * @return string
     */
    private function pluralize(string $word, int $amount = 1): string
    {
        $last_letter = substr($word, -1);
        return strtolower($last_letter) === 's' || $amount === 1 ? $word : $word . 's';
    }
}

// basic int validation
$_GET['id'] = array_key_exists('id', $_GET) && is_numeric($_GET['id']) && (int)$_GET['id'] > 0 ? (int)$_GET['id'] : null;
$_GET['action'] ??= null;
(new ItemHandler($db, $ir, $h, $_GET['action'], $_GET['id']))->run();

 

Whoa.

That is absolutely awesome the way it's structured.
I honestly didn't even think to combine the equip/unequip/itmbuy in with it.

I love features compressed into 1 file - I know people frown upon it but structured correctly it's really not that hard to de-bug when/if an issue arises.

Thank you, @Magictallguy

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...