Update town behavior to HTMX, fix some redirect issues
This commit is contained in:
parent
5fa648ab7b
commit
27f38f7ebc
|
@ -51,6 +51,7 @@ $l = $r->lookup($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
|
||||||
if (is_int($l)) exit("Error: $l");
|
if (is_int($l)) exit("Error: $l");
|
||||||
$content = $l['handler'](...$l['params'] ?? []);
|
$content = $l['handler'](...$l['params'] ?? []);
|
||||||
if (is_htmx() && $uri[0] !== 'babblebox') {
|
if (is_htmx() && $uri[0] !== 'babblebox') {
|
||||||
|
header('HX-Push-Url: '.$_SERVER['REQUEST_URI']);
|
||||||
$content .= '<title>'.page_title().'</title>';
|
$content .= '<title>'.page_title().'</title>';
|
||||||
$content .= Render\debug_db_info();
|
$content .= Render\debug_db_info();
|
||||||
if (env('debug', false)) $content .= Render\debug_query_log();
|
if (env('debug', false)) $content .= Render\debug_query_log();
|
||||||
|
|
|
@ -9,9 +9,8 @@ use Router;
|
||||||
function register_routes(Router $r): Router
|
function register_routes(Router $r): Router
|
||||||
{
|
{
|
||||||
$r->form('/inn', 'Towns\inn');
|
$r->form('/inn', 'Towns\inn');
|
||||||
$r->get('/buy', 'Towns\buy');
|
$r->get('/shop', 'Towns\shop');
|
||||||
$r->get('/buy2/:id', 'Towns\buy2');
|
$r->form('/buy/:id', 'Towns\buy');
|
||||||
$r->post('/buy3/:id', 'Towns\buy3');
|
|
||||||
// $r->get('/sell', 'Towns\sell');
|
// $r->get('/sell', 'Towns\sell');
|
||||||
$r->get('/maps', 'Towns\maps');
|
$r->get('/maps', 'Towns\maps');
|
||||||
$r->get('/maps2/:id', 'Towns\maps2');
|
$r->get('/maps2/:id', 'Towns\maps2');
|
||||||
|
@ -74,6 +73,7 @@ function town()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Staying at the inn resets all expendable stats to their max values.
|
* Staying at the inn resets all expendable stats to their max values.
|
||||||
|
* GET/POST /inn
|
||||||
*/
|
*/
|
||||||
function inn()
|
function inn()
|
||||||
{
|
{
|
||||||
|
@ -88,21 +88,22 @@ function inn()
|
||||||
You do not have enough gold to stay at this Inn tonight. <br><br>
|
You do not have enough gold to stay at this Inn tonight. <br><br>
|
||||||
You may return to <a hx-get="/" hx-target="#middle">town</a>, or use the direction buttons on the left to start exploring.
|
You may return to <a hx-get="/" hx-target="#middle">town</a>, or use the direction buttons on the left to start exploring.
|
||||||
HTML;
|
HTML;
|
||||||
} elseif (isset($_POST['submit'])) {
|
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && $_POST['rest']) {
|
||||||
user()->gold -= $town['innprice'];
|
user()->gold -= $town['innprice'];
|
||||||
user()->restore_points()->save();
|
user()->restore_points()->save();
|
||||||
$page = <<<HTML
|
$page = <<<HTML
|
||||||
You wake up feeling refreshed and ready for action. <br><br>
|
You wake up feeling refreshed and ready for action. <br><br>
|
||||||
You may return to <a hx-get="/" hx-target="#middle">town</a>, or use the direction buttons on the left to start exploring.
|
You may return to <a hx-get="/" hx-target="#middle">town</a>, or use the direction buttons on the left to start exploring.
|
||||||
HTML;
|
HTML;
|
||||||
} elseif (isset($_POST['cancel'])) {
|
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && !$_POST['rest']) {
|
||||||
redirect('/');
|
redirect('/');
|
||||||
} else {
|
} else {
|
||||||
$page = <<<HTML
|
$page = <<<HTML
|
||||||
Resting at the inn will refill your current HP, MP, and TP to their maximum levels.<br><br>
|
Resting at the inn will refill your current HP, MP, and TP to their maximum levels.<br><br>
|
||||||
A night's sleep at this Inn will cost you <b>{$town['innprice']} gold</b>. Is that ok?<br><br>
|
A night's sleep at this Inn will cost you <b>{$town['innprice']} gold</b>. Is that ok?<br><br>
|
||||||
<form hx-post="/inn" hx-target="#middle">
|
<form hx-post="/inn" hx-target="#middle">
|
||||||
<input type="submit" name="submit" value="Yes"> <input type="submit" name="cancel" value="No">
|
<button name="rest" value="1">Yes</button>
|
||||||
|
<button name="rest" value="0">No</button>
|
||||||
</form>
|
</form>
|
||||||
HTML;
|
HTML;
|
||||||
}
|
}
|
||||||
|
@ -111,12 +112,14 @@ function inn()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays a list of available items for purchase.
|
* 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 buy()
|
function shop()
|
||||||
{
|
{
|
||||||
$town = get_town_by_xy(user()->longitude, user()->latitude);
|
$town = get_town_by_xy(user()->longitude, user()->latitude);
|
||||||
if ($town === false) { exit('Cheat attempt detected.<br><br>Get a life, loser.'); }
|
if ($town === false) exit('Cheat attempt detected.<br><br>Get a life, loser.');
|
||||||
|
|
||||||
$htmx = is_htmx();
|
$htmx = is_htmx();
|
||||||
page_title($town['name'] . ' Shop');
|
page_title($town['name'] . ' Shop');
|
||||||
|
@ -147,7 +150,7 @@ function buy()
|
||||||
} else {
|
} else {
|
||||||
$specialdot = $item['special'] !== 'X' ? '<span class="highlight">*</span>' : '';
|
$specialdot = $item['special'] !== 'X' ? '<span class="highlight">*</span>' : '';
|
||||||
$page .= <<<HTML
|
$page .= <<<HTML
|
||||||
<td width="32%"><b><a href="/buy2/{$item['id']}">{$item['name']}</a>$specialdot</b></td>
|
<td width="32%"><b><a hx-get="/buy/{$item['id']}" hx-target="#middle">{$item['name']}</a>$specialdot</b></td>
|
||||||
<td width="32%">$attrib <b>{$item['attribute']}</b></td>
|
<td width="32%">$attrib <b>{$item['attribute']}</b></td>
|
||||||
<td width="32%">Price: <b>{$item['buycost']} gold</b></td>
|
<td width="32%">Price: <b>{$item['buycost']} gold</b></td>
|
||||||
HTML;
|
HTML;
|
||||||
|
@ -165,137 +168,116 @@ function buy()
|
||||||
/**
|
/**
|
||||||
* Confirm user's intent to purchase item.
|
* Confirm user's intent to purchase item.
|
||||||
*/
|
*/
|
||||||
function buy2($id)
|
function buy(int $id)
|
||||||
{
|
{
|
||||||
$townrow = get_town_by_xy(user()->longitude, user()->latitude);
|
$town = get_town_by_xy(user()->longitude, user()->latitude);
|
||||||
if ($townrow === false) display("Cheat attempt detected.<br><br>Get a life, loser.", "Error");
|
if ($town === false) redirect('/');
|
||||||
$townitems = explode(",", $townrow["itemslist"]);
|
if (!in_array($id, explode(',', $town['itemslist']))) redirect('/shop');
|
||||||
if (!in_array($id, $townitems)) display("Cheat attempt detected.<br><br>Get a life, loser.", "Error");
|
|
||||||
|
|
||||||
$item = get_item($id);
|
$item = get_item($id);
|
||||||
|
$can_afford = user()->gold >= $item['buycost'];
|
||||||
|
|
||||||
if (user()->gold < $item["buycost"]) {
|
if (!$can_afford) {
|
||||||
display("You do not have enough gold to buy this item.<br><br>You may return to <a href=\"/\">town</a>, <a href=\"/buy\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Items");
|
$page = <<<HTML
|
||||||
}
|
You do not have enough gold to buy <b>{$item['name']}</b>.<br><br>
|
||||||
|
You may return to <a hx-get="/" hx-target="#middle">town</a>, <a hx-get="/shop" hx-target="#middle">shop</a>,
|
||||||
|
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']
|
||||||
|
];
|
||||||
|
|
||||||
$type_to_row_mapping = [1 => 'weaponid', 2 => 'armorid', 3 => 'shieldid'];
|
if (!isset($type_mapping[$item["type"]])) { // should never happen
|
||||||
$current_equipped_id = user()[$type_to_row_mapping[$item['type']] ?? 0];
|
$page = 'Error! Invalid item type...<br>'.var_dump($item);
|
||||||
|
return is_htmx() ? $page : display($page, '');
|
||||||
|
}
|
||||||
|
|
||||||
if ($current_equipped_id != 0) {
|
// Retrieve current equipped item or create a default
|
||||||
$item2 = get_item($current_equipped_id);
|
$current_equip_id = user()->{$type_mapping[$item["type"]]['id']};
|
||||||
$page = "If you are buying the ".$item["name"].", then I will buy your ".$item2["name"]." for ".ceil($item2["buycost"] / 2)." gold. Is that ok?<br><br><form action=\"/buy3/$id\" method=\"post\"><input type=\"submit\" name=\"submit\" value=\"Yes\" /> <input type=\"submit\" name=\"cancel\" value=\"No\" /></form>";
|
if ($current_equip_id != 0) {
|
||||||
} else {
|
$item2 = get_item($current_equip_id);
|
||||||
$page = "You are buying the ".$item["name"].", is that ok?<br><br><form action=\"/buy3/$id\" method=\"post\"><input type=\"submit\" name=\"submit\" value=\"Yes\" /> <input type=\"submit\" name=\"cancel\" value=\"No\" /></form>";
|
} else {
|
||||||
}
|
$item2 = ["attribute" => 0, "buycost" => 0, "special" => "X"];
|
||||||
|
}
|
||||||
|
|
||||||
display($page, "Buy Items");
|
// Process special item effects
|
||||||
}
|
$specialFields = [];
|
||||||
|
$specialValues = [];
|
||||||
|
$powerAdjustments = 0;
|
||||||
|
|
||||||
/**
|
foreach ([$item, $item2] as $index => $process_item) {
|
||||||
* Update user profile with new item & stats.
|
if ($process_item["special"] != "X") {
|
||||||
*/
|
$special = explode(",", $process_item["special"]);
|
||||||
function buy3($id)
|
$toChange = $special[0];
|
||||||
{
|
$changeAmount = $index === 0 ? $special[1] : -$special[1];
|
||||||
|
|
||||||
if (isset($_POST["cancel"])) redirect('/');
|
user()[$toChange] += $changeAmount;
|
||||||
|
$specialFields[] = "$toChange = ?";
|
||||||
|
$specialValues[] = user()[$toChange];
|
||||||
|
|
||||||
$townrow = get_town_by_xy(user()->longitude, user()->latitude);
|
// Adjust attack or defense power
|
||||||
if ($townrow === false) display("Cheat attempt detected.<br><br>Get a life, loser.", "Error");
|
if ($toChange == "strength" || $toChange == "dexterity") {
|
||||||
$townitems = explode(",", $townrow["itemslist"]);
|
$powerType = $toChange == "strength" ? "attackpower" : "defensepower";
|
||||||
if (!in_array($id, $townitems)) display("Cheat attempt detected.<br><br>Get a life, loser.", "Error");
|
$powerAdjustments += $changeAmount;
|
||||||
|
}
|
||||||
$item = get_item($id);
|
|
||||||
|
|
||||||
if (user()->gold < $item["buycost"]) {
|
|
||||||
display("You do not have enough gold to buy this item.<br><br>You may return to <a href=\"/\">town</a>, <a href=\"/buy\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Items");
|
|
||||||
}
|
|
||||||
|
|
||||||
$type_mapping = [
|
|
||||||
1 => ['id' => 'weaponid', 'name' => 'weaponname', 'power' => 'attackpower'],
|
|
||||||
2 => ['id' => 'armorid', 'name' => 'armorname', 'power' => 'defensepower'],
|
|
||||||
3 => ['id' => 'shieldid', 'name' => 'shieldname', 'power' => 'defensepower']
|
|
||||||
];
|
|
||||||
|
|
||||||
// Validate item type
|
|
||||||
if (!isset($type_mapping[$item["type"]])) {
|
|
||||||
display("Invalid item type.", "Error");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 = <<<HTML
|
||||||
|
Thank you for purchasing <b>{$item['name']}</b>.<br><br>
|
||||||
|
You may return to <a hx-get="/" hx-target="#middle">town</a>, <a hx-get="/shop" hx-target="#middle">shop</a>, 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
|
||||||
|
If you are buying the {$item['name']}, then I will buy your {$item2['name']} for $sell_price gold. Is that ok?<br><br>
|
||||||
|
<form hx-post="/buy/$id" hx-target="#middle">
|
||||||
|
<button name="buy" value="1">Yes</button>
|
||||||
|
<button name="buy" value="0">No</button>
|
||||||
|
</form>
|
||||||
|
HTML;
|
||||||
|
} else {
|
||||||
|
$page = <<<HTML
|
||||||
|
You are buying {$item['name']} for {$item['buycost']} gold, is that ok?<br><br>
|
||||||
|
<form hx-post="/buy/$id" hx-target="#middle">
|
||||||
|
<button name="buy" value="1">Yes</button>
|
||||||
|
<button name="buy" value="0">No</button>
|
||||||
|
</form>
|
||||||
|
HTML;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine power and type-specific updates
|
page_title('Buying '.$item['name']);
|
||||||
$currentType = $type_mapping[$item["type"]];
|
return is_htmx() ? $page : display($page, 'Buying '.$item['name']);
|
||||||
$powerField = $currentType['power'];
|
|
||||||
$newPower = user()[$powerField] + $item["attribute"] - $item2["attribute"];
|
|
||||||
|
|
||||||
// Calculate new gold with trade-in value
|
|
||||||
$newGold = user()->gold + ceil($item2["buycost"]/2) - $item["buycost"];
|
|
||||||
|
|
||||||
// Ensure current HP/MP/TP don't exceed max values
|
|
||||||
$newhp = min(user()->currenthp, user()->maxhp);
|
|
||||||
$newmp = min(user()->currentmp, user()->maxmp);
|
|
||||||
$newtp = min(user()->currenttp, user()->maxtp);
|
|
||||||
|
|
||||||
$updateFields = array_merge(
|
|
||||||
$specialFields,
|
|
||||||
[
|
|
||||||
"gold = ?",
|
|
||||||
"{$powerField} = ?",
|
|
||||||
"{$currentType['id']} = ?",
|
|
||||||
"{$currentType['name']} = ?",
|
|
||||||
"currenthp = ?",
|
|
||||||
"currentmp = ?",
|
|
||||||
"currenttp = ?"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$updateValues = array_merge(
|
|
||||||
$specialValues,
|
|
||||||
[
|
|
||||||
$newGold,
|
|
||||||
$newPower,
|
|
||||||
$item["id"],
|
|
||||||
$item["name"],
|
|
||||||
$newhp,
|
|
||||||
$newmp,
|
|
||||||
$newtp,
|
|
||||||
user()->id
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$stmt = db()->query("UPDATE users SET " . implode(", ", $updateFields) . " WHERE id = ?;", $updateValues);
|
|
||||||
if ($stmt === false) exit("Failed to purchase and equip $id. Go back and try again.");
|
|
||||||
|
|
||||||
display("Thank you for purchasing this item.<br><br>You may return to <a href=\"/\">town</a>, <a href=\"/buy\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Items");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,7 +19,7 @@ require_once 'models/user.php';
|
||||||
|
|
||||||
env_load('../.env');
|
env_load('../.env');
|
||||||
|
|
||||||
$uri = uri();
|
$uri = explode('/', trim($_SERVER['REQUEST_URI'], '/'));
|
||||||
$GLOBALS['cache'] = [];
|
$GLOBALS['cache'] = [];
|
||||||
$GLOBALS['state'] = [];
|
$GLOBALS['state'] = [];
|
||||||
|
|
||||||
|
|
12
src/lib.php
12
src/lib.php
|
@ -20,8 +20,8 @@ function db(): Database
|
||||||
function redirect(string $location): void
|
function redirect(string $location): void
|
||||||
{
|
{
|
||||||
if (is_htmx()) {
|
if (is_htmx()) {
|
||||||
header("HX-Redirect: $location");
|
$json = json_encode(['path' => $location, 'target' => '#'.$_SERVER['HTTP_HX_TARGET'] ?? '#middle']);
|
||||||
header("HX-Replace-Url: $location");
|
header("HX-Location: $json");
|
||||||
} else {
|
} else {
|
||||||
header("Location: $location");
|
header("Location: $location");
|
||||||
}
|
}
|
||||||
|
@ -452,14 +452,6 @@ function ul_from_validate_errors(array $errors): string
|
||||||
return $string . '</ul>';
|
return $string . '</ul>';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the URI, broken up into chunks.
|
|
||||||
*/
|
|
||||||
function uri(): array
|
|
||||||
{
|
|
||||||
return explode('/', trim($_SERVER['REQUEST_URI'], '/'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the environment variables from the .env file.
|
* Load the environment variables from the .env file.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const chatBox = document.querySelector('#babblebox > .messages')
|
let chatBox = document.querySelector('#babblebox > .messages')
|
||||||
let isUserAtBottom = true
|
let isUserAtBottom = true
|
||||||
if (chatBox !== null) {
|
if (chatBox !== null) {
|
||||||
chatBox.scrollTop = chatBox.scrollHeight;
|
chatBox.scrollTop = chatBox.scrollHeight;
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
<div class="options">
|
<div class="options">
|
||||||
<div class="title"><img src="/img/town_<?= $town['id'] ?>.gif" alt="Welcome to <?= $town['name'] ?>" title="Welcome to <?= $town['name'] ?>"></div>
|
<div class="title"><img src="/img/town_<?= $town['id'] ?>.gif" alt="Welcome to <?= $town['name'] ?>" title="Welcome to <?= $town['name'] ?>"></div>
|
||||||
<b>Town Options:</b><br>
|
<b>Town Options:</b><br>
|
||||||
<ul>
|
<ul hx-boost="true" hx-target="#middle">
|
||||||
<li><a hx-get="/inn" hx-target="#middle">Rest at the Inn</a></li>
|
<li><a href="/inn">Rest at the Inn</a></li>
|
||||||
<li><a hx-get="/buy" hx-target="#middle">Buy Weapons/Armor</a></li>
|
<li><a href="/shop">Browse the Shop</a></li>
|
||||||
<li><a href="/maps">Buy Maps</a></li>
|
<li><a href="/maps">Buy Maps</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user