-
Posts
2,123 -
Joined
-
Last visited
-
Days Won
143
Content Type
Profiles
Forums
Events
Everything posted by Magictallguy
-
Maria
-
Based almost entirely on this query INSERT INTO `loan_shark` (ls_id, `ls_userid`, `ls_amount`, `ls_interest`, ls_daily, `ls_remaining`, `ls_time`) VALUES ('', {$ir['userid']}, {$amount}, {$interest}, {$dailyPayment}, {$remaining}, {$time}) and a cursory glance at the rest of the code, I'm throwing a guess at this: CREATE TABLE loan_shark ( ls_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, ls_userid INT NOT NULL, ls_amount INT NOT NULL DEFAULT 0, ls_daily INT NOT NULL DEFAULT 0, ls_remaining INT NOT NULL DEFAULT 0, ls_time INT NOT NULL DEFAULT 0, FOREIGN KEY (ls_userid) REFERENCES users(userid) );
-
I'm certainly curious - please feel free to share your experiences. I'd like to learn ^.^
-
If running on PHP 8.2 and above, you can use null coalescence $userid = $_SESSION['switch_to'] ?? $_SESSION['userid'];
-
Welcome (back) to MWG! There's definitely still a love for the various styles of games found here on this site, along with programmers of varying degrees itching to get into projects. We will never die! 😄
-
Quick tip for ya; if you need to dynamically resize an image on output, but want to keep its aspect ratio, avoid using the deprecated height and width attributes. Instead, a little CSS goes a long way. .panel-image { max-width: 150px; max-height: 100px; } <img src="{pic}" alt="A basic image title" class="panel-image"> Alternatively, you can inline the styling <img src="{pic}" alt="A basic title" style="max-width: 150px; max-height: 100px;">
-
Ooh, I'm in!
-
Inventory / Item Options (MCCodes V2)
Magictallguy replied to Rooster's topic in Requests & In Production
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> </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"> </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(); -
You're too kind 🙂 So, to get us back on topic, here's an update to MCCv2. I turned the rewards into a config array at the top of the file. Be sure to update the bonus_items to the id=>quantity you want to give! You're no longer limited to 2 items either. Set as many or as few as you wish - at least 1 required. PHP 7.4-friendly <?php declare(strict_types=1); global $db, $ir, $h, $set; include __DIR__ . '/globals.php'; // bonus_items = [item id => quantity, ...] $rewards = [ 'money' => 500, 'crystals' => 500, 'donatordays' => 10, 'bonus_items' => [ 2 => 100, 4 => 100, ] ]; // If the bonus item id is not set if (empty($rewards['bonus_items'])) { basic_error('The welcome pack hasn\'t been set up. Please notify an administrator.'); } // If the bonus item is set, but doesn't exist $getItems = $db->query( 'SELECT itmid, itmname FROM items WHERE itmid IN (' . implode(', ', array_keys($rewards['bonus_items'])) . ')' ); // If there's no result at all if (!$db->num_rows($getItems)) { basic_error('The items set in the Bonus Pack don\'t exist. Please notify an administrator'); } // Get the items into an array. [item id => name, ...] $items = []; while ($row = $db->fetch_row($getItems)) { $items[$row['itmid']] = $row['itmname']; } // If the amount of items in our array doesn't match the number of items set in the Bonus Pack if (count($items) !== count($rewards['bonus_items'])) { basic_error('Some of the items set in the Bonus Pack don\'t exist. Please notify an administrator'); } // If the user has already claimed their Bonus Pack if ($ir['bonus'] > 1) { basic_error('You\'ve already claimed your Bonus Pack.'); } // Ok! Looks like we're clear. Grant the Bonus Pack! // Update the user $db->query( 'UPDATE users SET money = money + ' . $rewards['money'] . ', crystals = crystals + ' . $rewards['crystals'] . ', donatordays = donatordays + ' . $rewards['donatordays'] . ', bonus = 2 WHERE userid = ' . $ir['userid'] ); // Give 'em the items foreach ($rewards['bonus_items'] as $id => $quantity) { item_add($ir['userid'], $id, $quantity); } ?> Your welcome pack has been credited successfully.<br><br> You have gained 500 game money.<br> You have gained 500 crystals.<br> You have gained 10 days donators status.<br> <?php // Dynamically output the items, meaning we can change them at any time without having to update this foreach ($items as $id => $name) { echo 'x' . $rewards['bonus_items'][$id] . ' <a href="iteminfo.php?ID=' . $id . '">' . $name . '</a><br>'; } ?> The donator status given here will give you the following benefits:<br><br> <ul> <li> Red name + cross next to your name.</li> <li> Friends and Enemies List.</li> <li> 17% Energy every 5 minutes instead of 8%.</li> <li> 25% Stats gain in the donator gym.</li> <li> Unlocking of enhanced features.</li> <li> 25 street steps instead of 10 per day.</li> </ul> This is a complementary welcome pack.<br> Just a way to say thank you for joining <?php echo $set['game_name']; ?>. <?php // End $h->endpage(); /** * A simple "error and exit" function, which keeps the output styling Dragon Blade originally wrote for this script. * @param string $msg * @return void */ function basic_error(string $msg) { global $h; ?> <hr style="width: 50%;"> <h3>ERROR</h3> <?php echo $msg; ?><br><br> <hr style="width: 50%;"> <a href="index.php">> Go Back</a> <hr style="width: 50%;"> <?php $h->endpage(); exit; } And here's the same script, updated to PHP 8.2 - which, in all honesty, merely adds the return typehinting for the basic_error() function. <?php declare(strict_types=1); global $db, $ir, $h, $set; include __DIR__ . '/globals.php'; // bonus_items = [item id => quantity, ...] $rewards = [ 'money' => 500, 'crystals' => 500, 'donatordays' => 10, 'bonus_items' => [ 2 => 100, 4 => 100, ] ]; // If the bonus item id is not set if (empty($rewards['bonus_items'])) { basic_error('The welcome pack hasn\'t been set up. Please notify an administrator.'); } // If the bonus item is set, but doesn't exist $getItems = $db->query( 'SELECT itmid, itmname FROM items WHERE itmid IN (' . implode(', ', array_keys($rewards['bonus_items'])) . ')' ); // If there's no result at all if (!$db->num_rows($getItems)) { basic_error('The items set in the Bonus Pack don\'t exist. Please notify an administrator'); } // Get the items into an array. [item id => name, ...] $items = []; while ($row = $db->fetch_row($getItems)) { $items[$row['itmid']] = $row['itmname']; } // If the amount of items in our array doesn't match the number of items set in the Bonus Pack if (count($items) !== count($rewards['bonus_items'])) { basic_error('Some of the items set in the Bonus Pack don\'t exist. Please notify an administrator'); } // If the user has already claimed their Bonus Pack if ($ir['bonus'] > 1) { basic_error('You\'ve already claimed your Bonus Pack.'); } // Ok! Looks like we're clear. Grant the Bonus Pack! // Update the user $db->query( 'UPDATE users SET money = money + ' . $rewards['money'] . ', crystals = crystals + ' . $rewards['crystals'] . ', donatordays = donatordays + ' . $rewards['donatordays'] . ', bonus = 2 WHERE userid = ' . $ir['userid'] ); // Give 'em the items foreach ($rewards['bonus_items'] as $id => $quantity) { item_add($ir['userid'], $id, $quantity); } ?> Your welcome pack has been credited successfully.<br><br> You have gained 500 game money.<br> You have gained 500 crystals.<br> You have gained 10 days donators status.<br> <?php // Dynamically output the items, meaning we can change them at any time without having to update this foreach ($items as $id => $name) { echo 'x' . $rewards['bonus_items'][$id] . ' <a href="iteminfo.php?ID=' . $id . '">' . $name . '</a><br>'; } ?> The donator status given here will give you the following benefits:<br><br> <ul> <li> Red name + cross next to your name.</li> <li> Friends and Enemies List.</li> <li> 17% Energy every 5 minutes instead of 8%.</li> <li> 25% Stats gain in the donator gym.</li> <li> Unlocking of enhanced features.</li> <li> 25 street steps instead of 10 per day.</li> </ul> This is a complementary welcome pack.<br> Just a way to say thank you for joining <?php echo $set['game_name']; ?>. <?php // End $h->endpage(); /** * A simple "error and exit" function, which keeps the output styling Dragon Blade originally wrote for this script. * @param string $msg * @return void */ function basic_error(string $msg): void { global $h; ?> <hr style="width: 50%;"> <h3>ERROR</h3> <?php echo $msg; ?><br><br> <hr style="width: 50%;"> <a href="index.php">> Go Back</a> <hr style="width: 50%;"> <?php $h->endpage(); exit; }
-
Keep the flaming out of this topic please. A blow-up over genuine support is not how we do things here.
-
Here's SRB's PHP-flavoured generator as pure HTML/CSS/JS. <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Kitten Generator</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/1.1.4/tailwind.min.css"> </head> <body> <div class="antialiased w-screen min-h-screen bg-gray-900 pb-12"> <form action="" method="post" id="kitten-form"> <div> <div class="max-w-6xl mx-auto flex pt-12"> <div class="w-1/2 p-4"> <h1 class="text-white text-3xl">Mother</h1> </div> <div class="w-1/2 p-4"> <h1 class="text-white text-3xl">Father</h1> </div> </div> <div class="max-w-6xl mx-auto flex"> <div class="w-1/2 p-4 border-r border-gray-500"> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Body Size</span> <input type="text" name="mother-body-size" id="mother-body-size" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded px-2" tabindex="1" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Build</span> <input type="text" name="mother-build" id="mother-build" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="3" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Ears</span> <input type="text" name="mother-ears" id="mother-ears" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="5" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Eye Color</span> <input type="text" name="mother-eye-color" id="mother-eye-color" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="7" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Nose / Paw Pads</span> <input type="text" name="mother-nose-paw-pads" id="mother-nose-paw-pads" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="9" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Pelt Length</span> <input type="text" name="mother-pelt-length" id="mother-pelt-length" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="11" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Pelt Color</span> <input type="text" name="mother-pelt-color" id="mother-pelt-color" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="13" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Pelt Markings</span> <input type="text" name="mother-pelt-markings" id="mother-pelt-markings" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="15" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Mutation</span> <input type="text" name="mother-mutation" id="mother-mutation" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="17" /> </label> </div> </div> <div class="w-1/2 p-4"> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Body Size</span> <input type="text" name="father-body-size" id="father-body-size" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="2" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Build</span> <input type="text" name="father-build" id="father-build" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="4" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Ears</span> <input type="text" name="father-ears" id="father-ears" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="6" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Eye Color</span> <input type="text" name="father-eye-color" id="father-eye-color" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="8" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Nose / Paw Pads</span> <input type="text" name="father-nose-paw-pads" id="father-nose-paw-pads" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="10" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Pelt Length</span> <input type="text" name="father-pelt-length" id="father-pelt-length" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="12" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Pelt Color</span> <input type="text" name="father-pelt-color" id="father-pelt-color" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="14" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Pelt Markings</span> <input type="text" name="father-pelt-markings" id="father-pelt-markings" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="16" /> </label> </div> <div class="block mb-4"> <label> <span class="block text-gray-300 text-sm">Mutation</span> <input type="text" name="father-mutation" id="father-mutation" value="" class="mt-1 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md px-2" tabindex="18" /> </label> </div> </div> </div> <div class="max-w-4xl mx-auto flex justify-center mt-8"> <button type="submit" class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-gray-600 hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500">Randomize</button> </div> </div> </form> <div class="max-w-6xl mx-auto flex justify-center flex-wrap mt-6 border-t pt-6" id="kitten-result"></div> </div> <script> let kittenCount = 0; const getOpts = () => { return ['body-size', 'build', 'ears', 'eye-color', 'nose-paw-pads', 'pelt-length', 'pelt-color', 'pelt-markings', 'mutation']; }; const generateKittens = () => { const opts = getOpts(); let output = []; for (let opt of opts) { const fatherOpt = `father-${opt}`; const motherOpt = `mother-${opt}`; let motherInput = document.getElementById(motherOpt).value ?? ''; let fatherInput = document.getElementById(fatherOpt).value ?? ''; console.log(`${opt}: ${motherInput} :: ${fatherInput}`); const items = [motherInput, fatherInput]; let selectedOpt = items[Math.floor(Math.random() * 2)]; let color = "#838383"; if (selectedOpt === '') { selectedOpt = (motherInput ?? fatherInput) ?? 'none'; } if (motherInput === fatherInput) { color = "#5bf132"; } else if (selectedOpt === motherInput) { color = "#ee6acb"; } else if (selectedOpt === fatherInput) { color = "#32aef1"; } output[opt] = `<span style="color: ${color};">${selectedOpt}</span>`; } const kittenCard = ` <div class="inline text-left box-border p-3 w-1/4"> <div class="border box-border p-2"> <h3 class="text-gray-300 font-bold border-b pb-1 mb-1"> Random Kitten #${++kittenCount} </h3> <div class="text-gray-300 body-size"> <span class="font-semibold">Body Size : </span> <span class="float-right">${output['body-size']}</span> </div> <div class="text-gray-300 build"> <span class="font-semibold">Build : </span> <span class="float-right">${output['build']}</span> </div> <div class="text-gray-300 ears"> <span class="font-semibold">Ears : </span> <span class="float-right">${output['ears']}</span> </div> <div class="text-gray-300 eye-color"> <span class="font-semibold">Eye Color : </span> <span class="float-right">${output['eye-color']}</span> </div> <div class="text-gray-300 nose-paw-color"> <span class="font-semibold">Nose / Paw Color : </span> <span class="float-right">${output['nose-paw-pads']}</span> </div> <div class="text-gray-300 pelt-length"> <span class="font-semibold">Pelt Length : </span> <span class="float-right">${output['pelt-length']}</span> </div> <div class="text-gray-300 pelt-color"> <span class="font-semibold">Pelt Color : </span> <span class="float-right">${output['pelt-color']}</span> </div> <div class="text-gray-300 pelt-markings"> <span class="font-semibold">Pelt Markings : </span> <span class="float-right">${output['pelt-markings']}</span> </div> <div class="text-gray-300 mutation"> <span class="font-semibold">Mutation : </span> <span class="float-right">${output['mutation']}</span> </div> </div> </div>`; document.getElementById('kitten-result').innerHTML += kittenCard; }; let formElem = document.getElementById('kitten-form'); formElem.addEventListener("submit", (e) => { e.preventDefault(); e.stopPropagation(); generateKittens(); }); </script> </body> </html> Fair note that this has never heard of "security". Blue: trait from father Pink: trait from mother Green: trait from both (matching trait) Grey: no trait 2023-08-23 15-44-43.mp4
-
Here's a PHP 8 version, because why not? <?php declare(strict_types=1); global $db, $h, $set, $userid; include 'globals.php'; $question = strtolower($_POST['question']); ?> <h2 class="fontface"><span class="green">T</span>utorial</h2> <hr /><br /><br /> <table style="border:none;width:650px;"> <tr> <td> <p>Welcome to the Tutorial, we hope that this guide will help you to better understand the game. <p><br /> <p> You are free to choose your own path. You can protect the weak, or exploit their weakness. Spend your money to help your friends, or horde it, they can take care of themselves. Buy a gang and become the most respected group of players in the land. Declare war on an enemy, or an innocent bystander, the choice is yours. </p><br /> <h3 class="fontface"> <?php echo $set['game_name']; ?> Help Bot </h3> <small>(Ask the Bot a question below and let's see if we can get you going.)</small><br /><br /> <form action="help.php" method="POST"> Question: <input type="text" name="question" size="70" placeholder="What would you like to know? why not try typing in training, gangs or rules"> <input type="submit" value="Ask"> </form> <?php if (empty($question)) { $h->endpage(); exit; } $answer = match ($question) { 'x' => 'x', 'help' => 'What do you need help with?', 'hello', 'helo', 'hi', 'hey' => 'Hello how are you?', 'gym', 'the gym' => 'The gym is where you use energy,gold and some will potions to train your stats up.<Br />Stats help you beat up players and protect yourself as well from attacks.', 'good' => 'Im glad to hear your good.', 'strength' => 'This stat is used to calculate how much damage a weapon does.', 'agility' => 'This stat is used for dodging attacks.', 'labour' => 'This stat is used for getting promoted in jobs.', 'IQ' => 'This stat is stat is gained from courses and used for promotions.', 'crystal', 'crystals' => 'Crystals are used for various things under <a href="crystaltemple.php">Crystal Temple</a>', 'cash' => 'Cash is used to buy stuff all over the game', 'energy' => 'This is used mainly for training and attacking', 'brave' => 'This is used for doing crimes', 'health' => 'How much health you have in a fight', 'mine', 'mines' => 'Mining a great way to earn gold', 'job' => 'Nice way to earn cash and stats', 'education' => 'Used for gaining IQ', 'mail' => 'Your own personal mail system', 'events' => 'What happens to you is recorded here', 'logout' => 'Used to logout of the game, duh.', 'explore' => 'Where the main links are listed', 'search' => 'Search for other players!', 'friend list' => 'Record your friends', 'black list' => 'Record your enemies', 'missions' => 'This is where you can use some of your brave to earn some cash.', 'preferences' => 'Used to change your account around', 'donate' => 'Donate to the game and be awarded donator features', 'vote' => 'Voting earns you rewards and it helps the game grow', 'item', 'items' => 'Items are a main part of the game and used for doing lots of things', 'church' => 'Used for getting married', 'stats' => 'Stats are what determines your account and how good you are', 'travel' => 'Travel around the game', 'casino' => 'Casino, play various games earning you some cash', 'quests' => 'Quests do various tasks to earn rewards', 'banned' => 'Users banned are listed in dungeon', 'war' => 'War is when 2 gangs fight each other', 'staff' => 'Main staff can be listed under Staff, ID 1 is the overall owner', 'prison' => 'Sent here when failing crimes', 'hospital', 'hosp' => 'Sent here when attacked', 'noob', 'n00b' => 'Who you calling a noob?', 'fuck', 'shit', 'prick', 'cunt', 'bitch' => 'Please do not swear', 'robot', 'bot' => 'Who you calling a bot!', 'who are you' => 'I am the ' . $set['game_name'] . ' Bot', 'weather' => 'The weather effects your training at the gym and your mining rates when at the mines.<br />You can also visit the weather page and ask the gods for better weather.', 'money' => 'Please Explain? e.g: how to get money or what should i save for', 'how to get money' => 'The best way to get money is by going into the mines and mine for gold and sell it. You could also take a risk and put it into the stock exchange.', 'what should i save for' => 'Well that\'s upto you but personally I would save up for a better house as that will help improve your stats and player.', 'users online' => 'This is where you see who is online', 'attacking' => 'Attacking is a good way to get experience, and exert your superiority over those weaker than you. In order to attack you need 1 energy, and should have a weapon. When you win a fight you will get a percentage of experience depending on how much stronger you are compared to the person you are attacking. Make sure that you really want to fight the person, because once you start you can\'t stop until one of you loses. When you start a fight, you will have the option of using any weapon that you currently have in your items page.', 'gang', 'gangs' => 'Gangs are a group of players that band together to work for a common purpose, granted this may be robbing a bank, or taking down the losers in a rival gang.<br /> Gangs cost $500K to create, and once you buy it, you are the president of your gang.<br /> Your gang will initially be able to hold 5 members, but will be able to upgrade to more as time goes on.<br /> The President will be able to assign a Vice-President to the gang. Gangs are able to do Organised Crimes for money and respect.<br /> The president can also select to go to war with another gang. One should be careful about doing this though, as it may come back to haunt you.', 'training' => '<b>Gym: </b>To use the gym, type in the number of times you want to train, select the stat to train and click ok.<br /> The next screen will tell you how much of that stat you gained, and what your total in that stat is.<br /><br /> <b>Missions: </b>Go to the mission screen and select the mission you want to do. <br />Remember that trying a mission that is to hard may land you in jail, and lose the experience you\'ve worked so hard to get.<br /><br /> <b>School: </b>School offers courses that will raise your stats over a certain period of time<br /><br /> <b>Your Job: </b>A job will provide you with money at 5:00PM every day, as well as raising your job stats every day. <br />Some jobs have requirements before you can do them, so make sure to keep an eye out for that.<br /><br /> <b>Attacking: </b>Attacking will gain you experience when you win, but you lose experience if you lose.<br /> The amount of experience depends on the comparative strength of your enemy, if they are much weaker, you won\'t get much experience.', 'rules' => 'Rules are important, They make sure that everyone gets a chance and the games is fair and fun for all. For all the rules please check out the game rules section.', 'profile', 'profiles' => 'This is where you can look at yours and other players profiles. Very informative ', 'rucksack' => 'this is where you find your items to use within the game, you also find your weapons and armour here.<br />', 'referrals', 'referral' => 'This is where you give friends a link to the game to earn rewards.', 'lucky', 'box', 'lucky box' => 'This is your reward for logging in every hour.', default => 'Sorry, I don\'t know the answer. <br />I\'ve logged it and should have an answer for you soon.', }; ?> <br /> <span class="blue"><b>You asked the Bot:</b></span> <?php echo $question; ?><br /> <span class="gold"><b>The Bot replied:</b></span> <?php echo $answer; if (empty($answer)) { $db->query('INSERT INTO `bot` (`submitted` ,`question` )VALUES (' . $userid . ', \'' . $db->escape($question) . '\')'); ?> Sorry, I don't know the answer. <br />It has been submitted to the database. <?php $h->endpage(); exit; } ?> </td> </tr> </table> <?php $h->endpage();
-
No worries! And no, I don't believe so. Updating it, I imagine, wouldn't be such a massive undertaking - it's a pretty small engine, and good practice! 😄
-
It will not run on PHP 8 without minor edits (primarily removals of magic_quotes calls in a couple of core files and a removal/tweak of the gethostbyaddr() calls in viewuser.php). After those minor fixes, it seems to run ok on my localhost and a public-facing webserver, though it will fill up the error log depending on your error reporting setting. PHP 7 seems to be a little more forgiving, it's less-restrictive rulesets allow MCCv2.0.5b to run. Again, however, it will generate a few notices/warnings for the error log. PHP 5.6 doesn't seems to give a rats butt - it runs fine. MySQL, all major versions since (and including) version 5 seem to take it fine. I'd advise a number of optimisations - both to the code and the database - but that'd be another topic for another time.
-
Aye, they're not bad at all. Well reputed, long-standing, experienced. Do you already have a domain? (example.com, example.net, example.tld) If so, contact wherever you bought it for that code. If not, consider creating a new one for your project. Edit; responded to DM. This isn't the correct context for the desire
-
Your second attempt is much closer! 😄 I've edited your post to wrap your code in code tags, with PHP selected as the language. Not only does this make the post look a little cleaner, it's less abuse on my scrollwheel 😛 Now it has "syntax highlighting", which changes the colour of the text, visually breaking things up a little in an attempt to make it easier to follow. Lets take the first line after the opening PHP tag -- this bit: require_once('globals.php'); It uses 3 colours: White to denote a function (or variable (see further down your code)), off-yellow to show special characters, and green to show a string. Syntactically, this is correct. Assuming there is a file named "globals.php" in the same directory (folder) as whatever file's running this, it will parse (see this StackOverflow answer for multiple explanations on what "parsing" is). So, strings are green. Noted. See the example snippet @corruptcity || skalman just posted? Notice how variables are green and some of the strings are white? Eek! Something's wrong here! The colours have flipped - perhaps a string has been closed before it should've been. It's easy to mix up " (quotation mark) and '' (double apostrophe) 😉 Example snippets from your code: That's absolutely correct! The function (I use the term loosely as echo is not a function but a language construct.) is white and the string is green. That should run fine. It starts fine, but wait! The string becomes white, yellow and blue. Somewhere here's one of your problems. 😉 You're also going to run into an additional "gotcha!" too with this one; variables within strings encased in ' (apostrophe) won't parse and will print as plain text. You'll need to break it out of the string and concatenate it instead. At the risk of a temporary topic change; I strongly recommend using an IDE, preferably tailored the languages you intend to write. Personally, I use solutions from the JetBrains Toolbox as I have full access to everything the toolbox provides at (thankfully) no cost to me. However, it is payware under the usual circumstances. Notepad++ (albeit not actually an IDE, but can become one) is great for quick 30-second edits and VSCode is a highly-extensive free alternative to the JetBrains products I use. Final note: Keep at it. You're getting there 🙂
-
Chromebook's Developer Mode is for allowing the user to install apps not found in the Play Store, amongst other things. However; these ones are! Here's VSCode Mobile, and here's CodeSandbox which even supports importing directly from GitHub and has its own version of VSCode interface - all in-browser! Also, here's KSWEB: web developer kit, which allows you to turn your Android/Chromium device into an Apache webserver with MySQL database for localhost testing
-
Free coding courses in various language available here: CodeCademy, FreeCodeCamp, The Odin Project Free courses available on Udacity: Tech Requirements, Intro to HTML and CSS, JavaScript Basics, Intro to jQuery Intro to AJAX, Object-Oriented JavaScript, Intro to Relational Databases (such as MySQL), Web Development, Full Stack Foundations, Responsive Web Design Fundamentals, Mobile Web Development, HTML5 Game Development, Intro to Computer Science, Programming Foundations with Python, Programming Languages, HTML5 Canvas, Responsive Images. If you need to pay for it, you're probably doing it wrong 😉
-
[SPADE] SPADE Engine is Officially Released!
Magictallguy replied to gamble's topic in Other Game Engines
The installer hook did not want to fire for me - though that could be due to running on localhost in a subdirectory. After extracting the db structure from the code and generating a .sql for it, I was able to create an account and log in. I quite like your approach to this. That cron management system is niiiice! Overall, I'd say this is a great basis for a game. Pretty easy to extend too. I'll continue exploring the code and see if I can come up with some mods for it. 🙂 -
If you wish to continue your dispute, please take it to DMs. We're not resuming the flaming threads of old if we can help it 😉
-
Seeing as this was tagged as v2, suggest making use of MCCv2's `database` class. At the very least, it offers a MySQLi wrapper. Here's the snippet, converted to use v2: function mass_give_item() { global $db, $ir, $c, $h; if ($ir['user_level'] != 2) { print "<hr width='50%'>Please read the error message.<hr width='50%'><h3>! ERROR</h3>Admin Only<br/><br/> <hr width='50%'><a href='../index.php'>> Go Home</a><hr width='50%'><br />"; $h->endpage(); exit; } print "<h3>Giving Item To All Users</h3> <form action='staff_users.php?action=massitemgivesub' method='post'> Item: " . item_dropdown($c, 'item') . " Quantity: <input type='text' name='qty' value='1' /> Event: <input type='text' name='event' value='Event Words Here' /> <input type='submit' value='Mass Send' /></form>"; } function mass_give_item_sub() { global $db, $ir, $c; $q = $db->query("SELECT * FROM users WHERE fedjail=0"); while ($r = $db->fetch_row($q)) { $qty = abs(intval($_POST['qty'])); $item = abs(intval($_POST['item'])); $event = ($_POST['event']); item_add($r['userid'], $item, $qty); event_add($r['userid'], "$event", $c); print "Item Sent To {$r['username']}</br>"; } print "Mass item sending complete!</br>"; stafflog_add("Gave {$_POST['qty']} of item ID {$_POST['item']} to all users"); }