form('/inn', 'Towns\inn'); $r->get('/shop', 'Towns\shop'); $r->form('/buy/:id', 'Towns\buy'); // $r->get('/sell', 'Towns\sell'); $r->get('/maps', 'Towns\maps'); $r->get('/maps2/:id', 'Towns\maps2'); $r->post('/maps3/:id', 'Towns\maps3'); $r->get('/gotown/:id', 'Towns\travelto'); return $r; } /** * Spit out the main town page. */ function town() { global $controlrow; $town = get_town_by_xy(user()->longitude, user()->latitude); if ($town === false) exit('There is an error with your user account, or with the town data. Please try again.'); $page = ['news' => '', 'whos_online' => '']; // News box. Grab latest news entry and display it. Something a little more graceful coming soon maybe. if ($controlrow['shownews'] === 1) { $news = db()->query('SELECT * FROM news ORDER BY id DESC LIMIT 1;')->fetchArray(SQLITE3_ASSOC); $news_date = pretty_date($news["postdate"]); $news_content = nl2br($news["content"]); $page['news'] = <<Latest News $news_date
$news_content HTML; } // Who's Online. Currently just members. Guests maybe later. if ($controlrow['showonline'] === 1) { $onlinequery = db()->query(<<= datetime('now', '-600 seconds') ORDER BY username; SQL); $online_count = 0; $online_rows = []; while ($onlinerow = $onlinequery->fetchArray(SQLITE3_ASSOC)) { $online_count++; $online_rows[] = "".$onlinerow["username"].""; } $online_rows = implode(', ', $online_rows); $page['whos_online'] = <<Who's Online There are $online_count user(s) online within the last 10 minutes: $online_rows HTML; } page_title($town['name']); return render('towns', ['town' => $town, 'news' => $page['news'], 'whos_online' => $page['whos_online']]); } /** * Staying at the inn resets all expendable stats to their max values. * GET/POST /inn */ function inn() { $town = get_town_by_xy(user()->longitude, user()->latitude); if ($town === false) { exit('Cheat attempt detected.

Get a life, loser.'); } $htmx = is_htmx(); page_title($town['name'] . ' Inn'); if (user()->gold < $town['innprice']) { $page = <<
You may return to town, or use the direction buttons on the left to start exploring. HTML; } elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && $_POST['rest']) { user()->gold -= $town['innprice']; user()->restore_points()->save(); $page = <<
You may return to town, or use the direction buttons on the left to start exploring. HTML; } elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && !$_POST['rest']) { redirect('/'); } else { $page = <<
A night's sleep at this Inn will cost you {$town['innprice']} gold. Is that ok?

HTML; } return $htmx ? $page : display($page, $town['name'] . ' Inn'); } /** * Displays a list of available items for purchase from the town the user is currently in. If the user is not in a town, * redirects to home. * GET /shop */ function shop() { $town = get_town_by_xy(user()->longitude, user()->latitude); if ($town === false) exit('Cheat attempt detected.

Get a life, loser.'); $htmx = is_htmx(); page_title($town['name'] . ' Shop'); $page = <<
Click an item name to purchase it.

The following items are available at this town:

HTML; $items = db()->query('SELECT * FROM items WHERE id IN (' . $town["itemslist"] . ');'); while ($item = $items->fetchArray(SQLITE3_ASSOC)) { $attrib = ($item["type"] == 1) ? "Attack Power:" : "Defense Power:"; $page .= ''; if (user()->weaponid === $item["id"] || user()->armorid === $item["id"] || user()->shieldid === $item["id"]) { $page .= <<{$item["name"]} HTML; } else { $specialdot = $item['special'] !== 'X' ? '*' : ''; $page .= <<{$item['name']}$specialdot HTML; } $page .= ''; } $page .= <<
If you've changed your mind, you may also return back to town. HTML; return $htmx ? $page : display($page, $town['name'] . ' Shop'); } /** * Confirm user's intent to purchase item. */ function buy(int $id) { $town = get_town_by_xy(user()->longitude, user()->latitude); if ($town === false) redirect('/'); if (!in_array($id, explode(',', $town['itemslist']))) redirect('/shop'); $item = get_item($id); $can_afford = user()->gold >= $item['buycost']; if (!$can_afford) { $page = <<{$item['name']}.

You may return to town, shop, or use the direction buttons on the left to start exploring. HTML; } elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && !$_POST['buy']) { redirect('/shop'); } elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && $_POST['buy']) { $type_mapping = [ 1 => ['id' => 'weaponid', 'name' => 'weaponname', 'power' => 'attackpower'], 2 => ['id' => 'armorid', 'name' => 'armorname', 'power' => 'defensepower'], 3 => ['id' => 'shieldid', 'name' => 'shieldname', 'power' => 'defensepower'] ]; if (!isset($type_mapping[$item["type"]])) { // should never happen $page = 'Error! Invalid item type...
'.var_dump($item); return is_htmx() ? $page : display($page, ''); } // Retrieve current equipped item or create a default $current_equip_id = user()->{$type_mapping[$item["type"]]['id']}; if ($current_equip_id != 0) { $item2 = get_item($current_equip_id); } else { $item2 = ["attribute" => 0, "buycost" => 0, "special" => "X"]; } // Process special item effects $specialFields = []; $specialValues = []; $powerAdjustments = 0; foreach ([$item, $item2] as $index => $process_item) { if ($process_item["special"] != "X") { $special = explode(",", $process_item["special"]); $toChange = $special[0]; $changeAmount = $index === 0 ? $special[1] : -$special[1]; user()[$toChange] += $changeAmount; $specialFields[] = "$toChange = ?"; $specialValues[] = user()[$toChange]; // Adjust attack or defense power if ($toChange == "strength" || $toChange == "dexterity") { $powerType = $toChange == "strength" ? "attackpower" : "defensepower"; $powerAdjustments += $changeAmount; } } } // Determine power and type-specific updates $currentType = $type_mapping[$item['type']]; $powerField = $currentType['power']; user()->$powerField += $item['attribute'] - $item2['attribute']; // Calculate new gold with trade-in value user()->gold += ceil($item2['buycost'] / 2) - $item['buycost']; // Ensure current HP/MP/TP don't exceed max values user()->currenthp = min(user()->currenthp, user()->maxhp); user()->currentmp = min(user()->currentmp, user()->maxmp); user()->currenttp = min(user()->currenttp, user()->maxtp); // Update item info in user user()->{$type_mapping[$item['type']]['id']} = $item['id']; user()->{$type_mapping[$item['type']]['name']} = $item['name']; user()->save(); $page = <<{$item['name']}.

You may return to town, shop, or use the direction buttons on the left to start exploring. HTML; } else { $type_to_row_mapping = [1 => 'weaponid', 2 => 'armorid', 3 => 'shieldid']; $current_equipped_id = user()->{$type_to_row_mapping[$item['type']]} ?? 0; if ($current_equipped_id != 0) { $item2 = get_item($current_equipped_id); $sell_price = ceil($item2['buycost'] / 2); $page = <<
HTML; } else { $page = <<
HTML; } } page_title('Buying '.$item['name']); return is_htmx() ? $page : display($page, 'Buying '.$item['name']); } /** * List maps the user can buy. */ function maps() { $mappedtowns = explode(",", user()->towns); $page = "Buying maps will put the town in your Travel To box, and it won't cost you as many TP to get there.

\n"; $page .= "Click a town name to purchase its map.

\n"; $page .= "
'; $page .= match ($item["type"]) { 1 => 'weapon', 2 => 'armor', 3 => 'shield' }; $page .= ' $attrib {$item['attribute']} Already purchased $attrib {$item['attribute']} Price: {$item['buycost']} gold
\n"; $towns = db()->query('SELECT * FROM towns ORDER BY id;'); while ($townrow = $towns->fetchArray(SQLITE3_ASSOC)) { $latitude = ($townrow["latitude"] >= 0) ? $townrow["latitude"] . "N," : ($townrow["latitude"] * -1) . "S,"; $longitude = ($townrow["longitude"] >= 0) ? $townrow["longitude"] . "E" : ($townrow["longitude"] * -1) . "W"; $mapped = false; foreach($mappedtowns as $b) if ($b == $townrow["id"]) $mapped = true; if ($mapped == false) { $page .= "\n"; } else { $page .= "\n"; } } $page .= "
".$townrow["name"]."Price: ".$townrow["mapprice"]." goldBuy map to reveal details.
".$townrow["name"]."Already mapped.Location: $latitude $longitudeTP: ".$townrow["travelpoints"]."

\n"; $page .= "If you've changed your mind, you may also return back to town.\n"; display($page, "Buy Maps"); } /** * Confirm user's intent to purchase map. */ function maps2($id) { $townrow = get_town_by_id($id); if (user()->gold < $townrow["mapprice"]) { display("You do not have enough gold to buy this map.

You may return to town, store, or use the direction buttons on the left to start exploring.", "Buy Maps"); } $page = "You are buying the ".$townrow["name"]." map. Is that ok?

"; display($page, "Buy Maps"); } /** * Add new map to user's profile. */ function maps3($id) { if (isset($_POST["cancel"])) redirect('/'); $townrow = get_town_by_id($id); if (user()->gold < $townrow["mapprice"]) { display("You do not have enough gold to buy this map.

You may return to town, store, or use the direction buttons on the left to start exploring.", "Buy Maps"); } $mappedtowns = user()->towns.",$id"; $newgold = user()->gold - $townrow["mapprice"]; db()->query('UPDATE users SET towns=?, gold=? WHERE id=?;', [$mappedtowns, $newgold, user()->id]); display("Thank you for purchasing this map.

You may return to town, store, or use the direction buttons on the left to start exploring.", "Buy Maps"); } /** * Send a user to a town from the Travel To menu. */ function travelto($id, bool $usepoints = true) { if (user()->currentaction == "Fighting") redirect('/fight'); $townrow = get_town_by_id($id); if ($usepoints) { if (user()->currenttp < $townrow["travelpoints"]) { return display("You do not have enough TP to travel here. Please go back and try again when you get more TP.", "Travel To"); } $mapped = explode(",",user()->towns); if (!in_array($id, $mapped)) { display("Cheat attempt detected.

Get a life, loser.", "Error"); } } if ((user()->latitude == $townrow["latitude"]) && (user()->longitude == $townrow["longitude"])) { return display("You are already in this town. Click here to return to the main town screen.", "Travel To"); } $newtp = ($usepoints) ? user()->currenttp - $townrow["travelpoints"] : user()->currenttp; $newlat = $townrow["latitude"]; $newlon = $townrow["longitude"]; // If they got here by exploring, add this town to their map. $mapped = explode(",",user()->towns); $town = false; foreach($mapped as $b) if ($b == $id) $town = true; $mapped = implode(",", $mapped); if ($town == false) $mapped .= ",$id"; user()->currentaction = 'In Town'; user()->towns = $mapped; user()->currenttp = $newtp; user()->longitude = $newlon; user()->latitude = $newlat; user()->save(); $page = "You have travelled to ".$townrow["name"].". You may now enter this town."; return display($page, "Travel To"); }