Compare commits

..

No commits in common. "27f38f7ebcf284f2d8182774d18c1a7c5ebc3c02" and "faefbb37d42fd81ff5336b855cf5784684d0ab09" have entirely different histories.

18 changed files with 514 additions and 439 deletions

View File

@ -40,7 +40,7 @@ main {
} }
main > section { main > section {
padding: 0.75rem; padding: 4px;
} }
main > section > section { main > section > section {
@ -49,7 +49,6 @@ main > section > section {
main section#left { main section#left {
width: 180px; width: 180px;
flex-shrink: 0;
border-right: solid 2px black; border-right: solid 2px black;
} }
@ -59,7 +58,6 @@ main section#middle {
main section#right { main section#right {
width: 180px; width: 180px;
flex-shrink: 0;
border-left: solid 2px black; border-left: solid 2px black;
} }
@ -84,6 +82,20 @@ td {
vertical-align: top; vertical-align: top;
} }
td.top {
border-bottom: solid 2px black;
}
td.left {
width: 180px;
border-right: solid 2px black;
}
td.right {
width: 180px;
border-left: solid 2px black;
}
a { a {
color: #663300; color: #663300;
text-decoration: none; text-decoration: none;
@ -114,7 +126,6 @@ a:hover {
padding: 5px; padding: 5px;
font-size: 1.2rem; font-size: 1.2rem;
font-family: serif; font-family: serif;
margin-bottom: 0.5rem;
} }
.copyright { .copyright {

View File

@ -8,7 +8,7 @@ html {
} }
body { body {
background-image: url('/img/backgrounds/classic.jpg'); background-image: url('/img/backgrounds/background.jpg');
padding: 2rem; padding: 2rem;
} }
table { table {

View File

@ -15,13 +15,15 @@ $r = new Router;
$r->get('/', function() { $r->get('/', function() {
if (user()->currentaction === "In Town") { if (user()->currentaction === "In Town") {
$page = Towns\town(); $page = Towns\town();
$title = "In Town";
} elseif (user()->currentaction === "Exploring") { } elseif (user()->currentaction === "Exploring") {
$page = explore(); $page = doexplore();
$title = "Exploring";
} elseif (user()->currentaction === "Fighting") { } elseif (user()->currentaction === "Fighting") {
redirect('/fight'); redirect('/fight');
} }
return is_htmx() ? $page : display($page, ''); return is_htmx() ? $page : display($page, $title);
}); });
$r->get('/ninja', function() { $r->get('/ninja', function() {
@ -51,14 +53,9 @@ $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 .= Render\debug_db_info(); $content .= Render\debug_db_info();
if (env('debug', false)) $content .= Render\debug_query_log();
if ($GLOBALS['state']['user-state-changed'] ?? false) { if ($GLOBALS['state']['user-state-changed'] ?? false) {
$content .= Render\right_nav(); $content .= Render\right_nav();
$content .= Render\left_nav();
} }
} }
echo $content; echo $content;
@ -68,9 +65,8 @@ exit;
* Just spit out a blank exploring page. Exploring without a GET string is normally when they first log in, or when * Just spit out a blank exploring page. Exploring without a GET string is normally when they first log in, or when
* they've just finished fighting. * they've just finished fighting.
*/ */
function explore() function doexplore()
{ {
page_title('Exploring');
return <<<HTML return <<<HTML
<div class="title"><img src="/img/title_exploring.gif" alt="Exploring"></div> <div class="title"><img src="/img/title_exploring.gif" alt="Exploring"></div>
You are exploring the map, and nothing has happened. Continue exploring using the direction buttons or the Travel To menus. You are exploring the map, and nothing has happened. Continue exploring using the direction buttons or the Travel To menus.

View File

@ -10,12 +10,12 @@ function move() {
// Validate direction // Validate direction
$form = validate($_POST, ['direction' => ['in:north,west,east,south']]); $form = validate($_POST, ['direction' => ['in:north,west,east,south']]);
if (!$form['valid']) return display(ul_from_validate_errors($form['errors']), 'Move Error'); if (!$form['valid']) display(ul_from_validate_errors($form['errors']), 'Move Error');
// Current game state // Current game state
$game_size = $controlrow['gamesize']; $game_size = $controlrow['gamesize'];
$latitude = user()->latitude; $latitude = user('latitude');
$longitude = user()->longitude; $longitude = user('longitude');
$direction = $form['data']['direction']; $direction = $form['data']['direction'];
// Calculate new coordinates with boundary checks // Calculate new coordinates with boundary checks
@ -37,20 +37,20 @@ function move() {
// Check for town // Check for town
$town = get_town_by_xy($longitude, $latitude); $town = get_town_by_xy($longitude, $latitude);
if ($town !== false) { if ($town !== false) {
return Towns\travelto($town['id'], false); Towns\travelto($town['id'], false);
return;
} }
// Determine action (1 in 5 chance of fighting) // Determine action (1 in 5 chance of fighting)
if (rand(1, 5) === 1) { $action = (rand(1, 5) === 1)
user()->currentaction = 'Fighting'; ? "currentaction='Fighting', currentfight='1',"
user()->currentfight = 1; : "currentaction='Exploring',";
} else {
user()->currentaction = 'Exploring';
}
user()->latitude = $latitude; // Update user's position
user()->longitude = $longitude; db()->query(
user()->save(); "UPDATE users SET $action latitude = ?, longitude = ?, dropcode = 0 WHERE id = ?;",
[$latitude, $longitude, user()->id]
);
redirect('/'); redirect('/');
} }

View File

@ -20,55 +20,56 @@ function register_routes(Router $r): Router
*/ */
function fight() function fight()
{ {
if (user()->currentaction !== 'Fighting') exit('Cheat attempt detected.<br><br>Get a life, loser.'); global $userrow;
if ($userrow["currentaction"] != "Fighting") display("Cheat attempt detected.<br><br>Get a life, loser.", "Error");
$page = ["magiclist" => "", "yourturn" => "", "monsterturn" => "", "monsterhp" => "", "command" => ""]; $pagearray = ["magiclist" => "", "yourturn" => "", "monsterturn" => "", "monsterhp" => "", "command" => ""];
$playerisdead = 0; $playerisdead = 0;
// Generate spell list // Populate magic list
$user_spells = user()->spells(); $userspells = explode(",", $userrow["spells"]);
if (!empty($user_spells)) { $spellquery = db()->query('SELECT id, name FROM spells ORDER BY id;');
$page['magiclist'] = '<select name="userspell">'; while ($spellrow = $spellquery->fetchArray(SQLITE3_ASSOC)) {
foreach ($user_spells as $spell) { if (in_array($spellrow["id"], $userspells)) {
$page['magiclist'] .= "<option value=\"{$spell['id']}\">{$spell['name']}</option>\n"; $pagearray["magiclist"] .= "<option value=\"{$spellrow["id"]}\">{$spellrow["name"]}</option>\n";
} }
$page['magiclist'] .= '</select> <input type="submit" name="spell" value="Spell"><br><br>'; }
} $pagearray["magiclist"] = $pagearray["magiclist"] ?: "<option value=\"0\">None</option>\n";
$magiclist = $pagearray["magiclist"];
// Determine initial combat parameters // Determine initial combat parameters
$chancetoswingfirst = rand(1, 10) + (int)ceil(sqrt(user()->dexterity)); $chancetoswingfirst = rand(1, 10) + (int)ceil(sqrt($userrow["dexterity"]));
if (user()->currentfight === 1) { if ($userrow["currentfight"] == 1) {
$maxlevel = (int)floor(max(abs(user()->latitude) + 5, abs(user()->longitude) + 5) / 5); $maxlevel = (int)floor(max(abs($userrow["latitude"]) + 5, abs($userrow["longitude"]) + 5) / 5);
$minlevel = max(1, $maxlevel - 2); $minlevel = max(1, $maxlevel - 2);
$monster = db()->query('SELECT * FROM monsters WHERE level >= ? AND level <= ? ORDER BY RANDOM() LIMIT 1;', [ $monsterrow = db()->query('SELECT * FROM monsters WHERE level >= ? AND level <= ? ORDER BY RANDOM() LIMIT 1;', [
$minlevel, $maxlevel $minlevel, $maxlevel
])->fetchArray(SQLITE3_ASSOC); ])->fetchArray(SQLITE3_ASSOC);
user()->currentmonster = $monster["id"]; $userrow["currentmonster"] = $monsterrow["id"];
user()->currentmonsterhp = rand((int)(($monster["maxhp"]/5)*4), $monster["maxhp"]); $userrow["currentmonsterhp"] = rand((int)(($monsterrow["maxhp"]/5)*4), $monsterrow["maxhp"]);
user()->currentmonstersleep = 0; $userrow["currentmonstersleep"] = 0;
user()->currentmonsterimmune = $monster["immune"]; $userrow["currentmonsterimmune"] = $monsterrow["immune"];
$chancetoswingfirst = ($chancetoswingfirst > (rand(1,7) + (int)ceil(sqrt($monster["maxdam"])))) ? 1 : 0; $chancetoswingfirst = ($chancetoswingfirst > (rand(1,7) + (int)ceil(sqrt($monsterrow["maxdam"])))) ? 1 : 0;
} }
// Get monster statistics // Get monster statistics
$monster = get_monster(user()->currentmonster); $monsterrow = get_monster($userrow['currentmonster']);
$page['monstername'] = $monster['name']; $pagearray["monstername"] = $monsterrow["name"];
// Run action // Run action
if (isset($_POST["run"])) { if (isset($_POST["run"])) {
$chancetorun = rand(4,10) + (int)ceil(sqrt(user()->dexterity)); $chancetorun = rand(4,10) + (int)ceil(sqrt($userrow["dexterity"]));
if ($chancetorun <= (rand(1,5) + (int)ceil(sqrt($monster["maxdam"])))) { if ($chancetorun <= (rand(1,5) + (int)ceil(sqrt($monsterrow["maxdam"])))) {
$page["yourturn"] = "You tried to run away, but were blocked in front!<br><br>"; $pagearray["yourturn"] = "You tried to run away, but were blocked in front!<br><br>";
$page["monsterhp"] = "Monster's HP: " . user()->currentmonsterhp . "<br><br>"; $pagearray["monsterhp"] = "Monster's HP: " . $userrow["currentmonsterhp"] . "<br><br>";
// Monster turn logic (similar to original function) // Monster turn logic (similar to original function)
$page["monsterturn"] = handleMonsterTurn($userrow, $monster); $pagearray["monsterturn"] = handleMonsterTurn($userrow, $monsterrow);
user()->currentaction = 'Exploring'; db()->query("UPDATE users SET currentaction='Exploring' WHERE id=?;", [$userrow['id']]);
user()->save();
redirect('/'); redirect('/');
} }
} }
@ -76,125 +77,147 @@ function fight()
// Fight action // Fight action
if (isset($_POST["fight"])) { if (isset($_POST["fight"])) {
// Player's attack // Player's attack
$min = (int)(user()->attackpower * 0.75); $min = (int)($userrow["attackpower"] * 0.75);
$max = (int)(user()->attackpower / 3); $max = (int)($userrow["attackpower"] / 3);
$tohit = (int)ceil(mt_rand(min($min, $max), max($min, $max))); $tohit = (int)ceil(mt_rand(min($min, $max), max($min, $max)));
$toexcellent = rand(1,150); $toexcellent = rand(1,150);
if ($toexcellent <= sqrt(user()->strength)) { if ($toexcellent <= sqrt($userrow["strength"])) {
$tohit *= 2; $tohit *= 2;
$page["yourturn"] .= "Excellent hit!<br>"; $pagearray["yourturn"] .= "Excellent hit!<br>";
} }
$min = (int)($monster["armor"] * 0.75); $min = (int)($monsterrow["armor"] * 0.75);
$max = (int)$monster["armor"]; $max = (int)$monsterrow["armor"];
$toblock = (int)ceil(rand(min($min, $max), max($min, $max)) / 3); $toblock = (int)ceil(rand(min($min, $max), max($min, $max)) / 3);
$tododge = rand(1, 100); $tododge = rand(1,200);
$monsterdamage = max(1, $tohit - $toblock); $monsterdamage = max(1, $tohit - $toblock);
if ($tododge <= sqrt($monster["armor"])) { if ($tododge <= sqrt($monsterrow["armor"])) {
$monsterdamage = 0; $monsterdamage = 0;
$page["yourturn"] .= "The monster is dodging. No damage has been scored.<br>"; $pagearray["yourturn"] .= "The monster is dodging. No damage has been scored.<br>";
} }
if (user()->currentuberdamage != 0) { if ($userrow["currentuberdamage"] != 0) {
$monsterdamage += (int)ceil($monsterdamage * (user()->currentuberdamage / 100)); $monsterdamage += (int)ceil($monsterdamage * ($userrow["currentuberdamage"]/100));
} }
user()->currentmonsterhp -= $monsterdamage; $userrow["currentmonsterhp"] -= $monsterdamage;
$page["yourturn"] .= "You attack the monster for $monsterdamage damage.<br><br>"; $pagearray["yourturn"] .= "You attack the monster for $monsterdamage damage.<br><br>";
$page["monsterhp"] = "Monster's HP: " . user()->currentmonsterhp . "<br><br>"; $pagearray["monsterhp"] = "Monster's HP: " . $userrow["currentmonsterhp"] . "<br><br>";
// Check for monster defeat // Check for monster defeat
if (user()->currentmonsterhp <= 0) { if ($userrow["currentmonsterhp"] <= 0) {
user()->currentmonsterhp = 0; db()->query('UPDATE users SET currentmonsterhp=0 WHERE id=?;', [$userrow['id']]);
user()->save();
redirect('/victory'); redirect('/victory');
} }
// Monster's turn // Monster's turn
$page["monsterturn"] = handleMonsterTurn($userrow, $monster); $pagearray["monsterturn"] = handleMonsterTurn($userrow, $monsterrow);
} }
// Spell action // Spell action
if (isset($_POST["spell"])) { if (isset($_POST["spell"])) {
$pickedspell = $_POST["userspell"]; $pickedspell = $_POST["userspell"];
if ($pickedspell == 0) { if ($pickedspell == 0) {
return display("You must select a spell first. Please go back and try again.", "Error"); display("You must select a spell first. Please go back and try again.", "Error");
die(); die();
} }
$newspellrow = get_spell($pickedspell); $newspellrow = get_spell($pickedspell);
$spell = in_array($pickedspell, explode(',', user()->spells)); $spell = in_array($pickedspell, $userspells);
if (!$spell) { if (!$spell) {
return display("You have not yet learned this spell. Please go back and try again.", "Error"); display("You have not yet learned this spell. Please go back and try again.", "Error");
die(); die();
} }
if (user()->currentmp < $newspellrow["mp"]) { if ($userrow["currentmp"] < $newspellrow["mp"]) {
return display("You do not have enough Magic Points to cast this spell. Please go back and try again.", "Error"); display("You do not have enough Magic Points to cast this spell. Please go back and try again.", "Error");
die(); die();
} }
// Spell type handling (similar to original function) // Spell type handling (similar to original function)
$page["yourturn"] = handleSpellCast($userrow, $newspellrow); $pagearray["yourturn"] = handleSpellCast($userrow, $newspellrow);
$page["monsterhp"] = "Monster's HP: " . user()->currentmonsterhp . "<br><br>"; $pagearray["monsterhp"] = "Monster's HP: " . $userrow["currentmonsterhp"] . "<br><br>";
// Check for monster defeat // Check for monster defeat
if (user()->currentmonsterhp <= 0) { if ($userrow["currentmonsterhp"] <= 0) {
user()->currentmonsterhp = 0; db()->query('UPDATE users SET currentmonsterhp=0, currenthp=?, currentmp=? WHERE id=?;', [
user()->save(); $userrow['currenthp'], $userrow['currentmp'], $userrow['id']
]);
redirect('/victory'); redirect('/victory');
} }
// Monster's turn // Monster's turn
$page["monsterturn"] = handleMonsterTurn($userrow, $monster); $pagearray["monsterturn"] = handleMonsterTurn($userrow, $monsterrow);
} }
// Monster's turn if player lost first swing // Monster's turn if player lost first swing
if (!isset($_POST["run"]) && !isset($_POST["fight"]) && !isset($_POST["spell"]) && $chancetoswingfirst == 0) { if (!isset($_POST["run"]) && !isset($_POST["fight"]) && !isset($_POST["spell"]) && $chancetoswingfirst == 0) {
$page["yourturn"] = "The monster attacks before you are ready!<br><br>"; $pagearray["yourturn"] = "The monster attacks before you are ready!<br><br>";
$page["monsterhp"] = "Monster's HP: " . user()->currentmonsterhp . "<br><br>"; $pagearray["monsterhp"] = "Monster's HP: " . $userrow["currentmonsterhp"] . "<br><br>";
$page["monsterturn"] = handleMonsterTurn($userrow, $monster); $pagearray["monsterturn"] = handleMonsterTurn($userrow, $monsterrow);
} }
// Prepare command or death message // Prepare command or death message
if ($playerisdead != 1) { if ($playerisdead != 1) {
$page["command"] = <<<HTML $pagearray["command"] = <<<HTML
Command?<br><br> Command?<br><br>
<form action="/fight" method="post"> <form action="/fight" method="post">
<input type="submit" name="fight" value="Fight"><br><br> <input type="submit" name="fight" value="Fight" /><br><br>
{$page['magiclist']} <select name="userspell"><option value="0">Choose One</option>$magiclist</select> <input type="submit" name="spell" value="Spell" /><br><br>
<input type="submit" name="run" value="Run"><br><br> <input type="submit" name="run" value="Run" /><br><br>
</form> </form>
HTML; HTML;
user()->currentfight += 1; db()->query("UPDATE users SET
currentaction='Fighting',
currenthp=?,
currentmp=?,
currentfight=?,
currentmonster=?,
currentmonsterhp=?,
currentmonstersleep=?,
currentmonsterimmune=?,
currentuberdamage=?,
currentuberdefense=?
WHERE id=?;", [
$userrow['currenthp'],
$userrow['currentmp'],
$userrow['currentfight'] + 1,
$userrow['currentmonster'],
$userrow['currentmonsterhp'],
$userrow['currentmonstersleep'],
$userrow['currentmonsterimmune'],
$userrow['currentuberdamage'],
$userrow['currentuberdefense'],
$userrow['id']
]);
} else { } else {
$pagearray["command"] = "<b>You have died.</b><br><br>As a consequence, you've lost half of your gold. However, you have been given back a portion of your hit points to continue your journey.<br><br>You may now continue back to <a href=\"/\">town</a>, and we hope you fair better next time."; $pagearray["command"] = "<b>You have died.</b><br><br>As a consequence, you've lost half of your gold. However, you have been given back a portion of your hit points to continue your journey.<br><br>You may now continue back to <a href=\"/\">town</a>, and we hope you fair better next time.";
} }
user()->save();
// Finalize page and display it // Finalize page and display it
return display(render('fight', ['page' => $page]), "Fighting"); display(render('fight', ['page' => $pagearray]), "Fighting");
} }
function victory() function victory()
{ {
if (user()->currentmonsterhp != 0) redirect('/fight'); global $userrow;
if (user()->currentfight == 0) redirect('/');
$monsterrow = get_monster(user()->currentmonster); if ($userrow["currentmonsterhp"] != 0) redirect('/fight');
if ($userrow["currentfight"] == 0) redirect('/');
$monsterrow = get_monster($userrow['currentmonster']);
$min = (int)(($monsterrow["maxexp"] / 6) * 5); $min = (int)(($monsterrow["maxexp"] / 6) * 5);
$max = (int)$monsterrow["maxexp"]; $max = (int)$monsterrow["maxexp"];
$exp = mt_rand(min($min, $max), max($min, $max)); $exp = mt_rand(min($min, $max), max($min, $max));
if ($exp < 1) { $exp = 1; } if ($exp < 1) { $exp = 1; }
if (user()->expbonus != 0) { $exp += ceil((user()->expbonus/100)*$exp); } if ($userrow["expbonus"] != 0) { $exp += ceil(($userrow["expbonus"]/100)*$exp); }
$min = (int)(($monsterrow["maxgold"] / 6) * 5); $min = (int)(($monsterrow["maxgold"] / 6) * 5);
$max = (int)$monsterrow["maxgold"]; $max = (int)$monsterrow["maxgold"];
@ -202,33 +225,42 @@ function victory()
$gold = mt_rand(min($min, $max), max($min, $max)); $gold = mt_rand(min($min, $max), max($min, $max));
if ($gold < 1) { $gold = 1; } if ($gold < 1) { $gold = 1; }
if (user()->goldbonus != 0) { $gold += ceil((user()->goldbonus/100)*$exp); } if ($userrow["goldbonus"] != 0) { $gold += ceil(($userrow["goldbonus"]/100)*$exp); }
if (user()->experience + $exp < 16777215) { $newexp = user()->experience += $exp; $warnexp = ""; } else { $newexp = user()->experience; $exp = 0; $warnexp = "You have maxed out your experience points."; } if ($userrow["experience"] + $exp < 16777215) { $newexp = $userrow["experience"] + $exp; $warnexp = ""; } else { $newexp = $userrow["experience"]; $exp = 0; $warnexp = "You have maxed out your experience points."; }
if (user()->gold + $gold < 16777215) { $newgold = user()->gold += $gold; $warngold = ""; } else { $newgold = user()->gold; $gold = 0; $warngold = "You have maxed out your gold."; } if ($userrow["gold"] + $gold < 16777215) { $newgold = $userrow["gold"] + $gold; $warngold = ""; } else { $newgold = $userrow["gold"]; $gold = 0; $warngold = "You have maxed out your experience points."; }
$levelrow = db()->query('SELECT * FROM levels WHERE id=? LIMIT 1;', [user()->level + 1])->fetchArray(SQLITE3_ASSOC); $levelrow = db()->query('SELECT * FROM levels WHERE id=? LIMIT 1;', [$userrow['level'] + 1])->fetchArray(SQLITE3_ASSOC);
if (user()->level < 100) { if ($userrow["level"] < 100) {
if ($newexp >= $levelrow[user()->charclass."_exp"]) { if ($newexp >= $levelrow[$userrow["charclass"]."_exp"]) {
user()->maxhp += $levelrow[user()->charclass."_hp"]; $newhp = $userrow["maxhp"] + $levelrow[$userrow["charclass"]."_hp"];
user()->maxmp += $levelrow[user()->charclass."_mp"]; $newmp = $userrow["maxmp"] + $levelrow[$userrow["charclass"]."_mp"];
user()->maxtp += $levelrow[user()->charclass."_tp"]; $newtp = $userrow["maxtp"] + $levelrow[$userrow["charclass"]."_tp"];
user()->strength += $levelrow[user()->charclass."_strength"]; $newstrength = $userrow["strength"] + $levelrow[$userrow["charclass"]."_strength"];
user()->dexterity += $levelrow[user()->charclass."_dexterity"]; $newdexterity = $userrow["dexterity"] + $levelrow[$userrow["charclass"]."_dexterity"];
user()->attackpower += $levelrow[user()->charclass."_strength"]; $newattack = $userrow["attackpower"] + $levelrow[$userrow["charclass"]."_strength"];
user()->defensepower += $levelrow[user()->charclass."_dexterity"]; $newdefense = $userrow["defensepower"] + $levelrow[$userrow["charclass"]."_dexterity"];
user()->level += 1;
$newlevel = $levelrow["id"]; $newlevel = $levelrow["id"];
if ($levelrow[user()->charclass."_spells"] != 0) { if ($levelrow[$userrow["charclass"]."_spells"] != 0) {
user()->spells .= ",".$levelrow[user()->charclass."_spells"]; $userspells = $userrow["spells"] . ",".$levelrow[$userrow["charclass"]."_spells"];
$newspell = "spells='$userspells',";
$spelltext = "You have learned a new spell.<br>"; $spelltext = "You have learned a new spell.<br>";
} else { $spelltext = ""; $newspell=""; } } else { $spelltext = ""; $newspell=""; }
$page = "Congratulations. You have defeated the ".$monsterrow["name"].".<br>You gain $exp experience. $warnexp <br>You gain $gold gold. $warngold <br><br><b>You have gained a level!</b><br><br>You gain ".$levelrow[user()->charclass."_hp"]." hit points.<br>You gain ".$levelrow[user()->charclass."_mp"]." magic points.<br>You gain ".$levelrow[user()->charclass."_tp"]." travel points.<br>You gain ".$levelrow[user()->charclass."_strength"]." strength.<br>You gain ".$levelrow[user()->charclass."_dexterity"]." dexterity.<br>$spelltext<br>You can now continue <a href=\"/\">exploring</a>."; $page = "Congratulations. You have defeated the ".$monsterrow["name"].".<br>You gain $exp experience. $warnexp <br>You gain $gold gold. $warngold <br><br><b>You have gained a level!</b><br><br>You gain ".$levelrow[$userrow["charclass"]."_hp"]." hit points.<br>You gain ".$levelrow[$userrow["charclass"]."_mp"]." magic points.<br>You gain ".$levelrow[$userrow["charclass"]."_tp"]." travel points.<br>You gain ".$levelrow[$userrow["charclass"]."_strength"]." strength.<br>You gain ".$levelrow[$userrow["charclass"]."_dexterity"]." dexterity.<br>$spelltext<br>You can now continue <a href=\"/\">exploring</a>.";
$title = "Courage and Wit have served thee well!"; $title = "Courage and Wit have served thee well!";
$dropcode = ""; $dropcode = "";
} else { } else {
$newhp = $userrow["maxhp"];
$newmp = $userrow["maxmp"];
$newtp = $userrow["maxtp"];
$newstrength = $userrow["strength"];
$newdexterity = $userrow["dexterity"];
$newattack = $userrow["attackpower"];
$newdefense = $userrow["defensepower"];
$newlevel = $userrow["level"];
$newspell = "";
$page = "Congratulations. You have defeated the ".$monsterrow["name"].".<br>You gain $exp experience. $warnexp <br>You gain $gold gold. $warngold <br><br>"; $page = "Congratulations. You have defeated the ".$monsterrow["name"].".<br>You gain $exp experience. $warnexp <br>You gain $gold gold. $warngold <br><br>";
if (rand(1, 30) === 1) { if (rand(1, 30) === 1) {
@ -244,82 +276,74 @@ function victory()
} }
} }
user()->currentaction = 'Exploring'; db()->query("UPDATE users SET currentaction='Exploring', level=?, maxhp=?, maxmp=?, maxtp=?, strength=?, dexterity=?, attackpower=?, defensepower=?, $newspell currentfight=0, currentmonster=0, currentmonsterhp=0, currentmonstersleep=0, currentmonsterimmune=0, currentuberdamage=0, currentuberdefense=0,$dropcode experience=?, gold=? WHERE id=?;", [
user()->currentfight = 0; $newlevel, $newhp, $newmp, $newtp, $newstrength, $newdexterity, $newattack, $newdefense, $newexp, $newgold, $userrow['id']
user()->currentuberdamage = 0; ]);
user()->currentuberdefense = 0;
user()->currentmonstersleep = 0;
user()->currentmonsterimmune = 0;
user()->save();
return display($page, $title); display($page, $title);
} }
function drop() function drop()
{ {
if (user()->dropcode == 0) redirect('/'); global $userrow;
$droprow = get_drop(user()->dropcode); if ($userrow["dropcode"] == 0) redirect('/');
$droprow = get_drop($userrow['dropcode']);
if (isset($_POST["submit"])) { if (isset($_POST["submit"])) {
$slot = $_POST["slot"]; $slot = $_POST["slot"];
if ($slot == 0) { return display("Please go back and select an inventory slot to continue.","Error"); } if ($slot == 0) { display("Please go back and select an inventory slot to continue.","Error"); }
$slotstr = 'slot'.$slot.'id'; if ($userrow["slot{$slot}id"] != 0) {
if (user()->$slotstr != 0) { $slotrow = get_drop($userrow["slot{$slot}id"]);
$slotrow = get_drop(user()->$slotstr);
$old1 = explode(",",$slotrow["attribute1"]); $old1 = explode(",",$slotrow["attribute1"]);
if ($slotrow["attribute2"] != "X") { $old2 = explode(",",$slotrow["attribute2"]); } else { $old2 = array(0=>"maxhp",1=>0); } if ($slotrow["attribute2"] != "X") { $old2 = explode(",",$slotrow["attribute2"]); } else { $old2 = array(0=>"maxhp",1=>0); }
$new1 = explode(",",$droprow["attribute1"]); $new1 = explode(",",$droprow["attribute1"]);
if ($droprow["attribute2"] != "X") { $new2 = explode(",",$droprow["attribute2"]); } else { $new2 = array(0=>"maxhp",1=>0); } if ($droprow["attribute2"] != "X") { $new2 = explode(",",$droprow["attribute2"]); } else { $new2 = array(0=>"maxhp",1=>0); }
user()->$old1[0] -= $old1[1]; $userrow[$old1[0]] -= $old1[1];
user()->$old2[0] -= $old2[1]; $userrow[$old2[0]] -= $old2[1];
if ($old1[0] == "strength") { user()->attackpower -= $old1[1]; } if ($old1[0] == "strength") { $userrow["attackpower"] -= $old1[1]; }
if ($old1[0] == "dexterity") { user()->defensepower -= $old1[1]; } if ($old1[0] == "dexterity") { $userrow["defensepower"] -= $old1[1]; }
if ($old2[0] == "strength") { user()->attackpower -= $old2[1]; } if ($old2[0] == "strength") { $userrow["attackpower"] -= $old2[1]; }
if ($old2[0] == "dexterity") { user()->defensepower -= $old2[1]; } if ($old2[0] == "dexterity") { $userrow["defensepower"] -= $old2[1]; }
user()->$new1[0] += $new1[1]; $userrow[$new1[0]] += $new1[1];
user()->$new2[0] += $new2[1]; $userrow[$new2[0]] += $new2[1];
if ($new1[0] == "strength") { user()->attackpower += $new1[1]; } if ($new1[0] == "strength") { $userrow["attackpower"] += $new1[1]; }
if ($new1[0] == "dexterity") { user()->defensepower += $new1[1]; } if ($new1[0] == "dexterity") { $userrow["defensepower"] += $new1[1]; }
if ($new2[0] == "strength") { user()->attackpower += $new2[1]; } if ($new2[0] == "strength") { $userrow["attackpower"] += $new2[1]; }
if ($new2[0] == "dexterity") { user()->defensepower += $new2[1]; } if ($new2[0] == "dexterity") { $userrow["defensepower"] += $new2[1]; }
if (user()->currenthp > user()->maxhp) { user()->currenthp = user()->maxhp; } if ($userrow["currenthp"] > $userrow["maxhp"]) { $userrow["currenthp"] = $userrow["maxhp"]; }
if (user()->currentmp > user()->maxmp) { user()->currentmp = user()->maxmp; } if ($userrow["currentmp"] > $userrow["maxmp"]) { $userrow["currentmp"] = $userrow["maxmp"]; }
if (user()->currenttp > user()->maxtp) { user()->currenttp = user()->maxtp; } if ($userrow["currenttp"] > $userrow["maxtp"]) { $userrow["currenttp"] = $userrow["maxtp"]; }
$slot_s = 'slot'.$_POST["slot"]; $slot_s = 'slot'.$_POST["slot"];
$slot_name = "{$slot_s}name"; db()->query("UPDATE users SET {$slot_s}name=?, {$slot_s}id=?, {$old1[0]}=?, {$old2[0]}=?, {$new1[0]}=?, {$new2[0]}=?, attackpower=?, defensepower=?, currenthp=?, currentmp=?, currenttp=?, dropcode=0 WHERE id=?;", [
$slot_id = "{$slot_s}id"; $droprow["name"], $droprow["id"], $userrow[$old1[0]], $userrow[$old2[0]], $userrow[$new1[0]], $userrow[$new2[0]], $userrow["attackpower"], $userrow["defensepower"], $userrow["currenthp"], $userrow["currentmp"], $userrow["currenttp"], $userrow['id']
]);
user()->$slot_name = $droprow['name'];
user()->$slot_id = $droprow['id'];
} else { } else {
$new1 = explode(",",$droprow["attribute1"]); $new1 = explode(",",$droprow["attribute1"]);
if ($droprow["attribute2"] != "X") { $new2 = explode(",",$droprow["attribute2"]); } else { $new2 = array(0=>"maxhp",1=>0); } if ($droprow["attribute2"] != "X") { $new2 = explode(",",$droprow["attribute2"]); } else { $new2 = array(0=>"maxhp",1=>0); }
user()->$new1[0] += $new1[1]; $userrow[$new1[0]] += $new1[1];
user()->$new2[0] += $new2[1]; $userrow[$new2[0]] += $new2[1];
if ($new1[0] == "strength") { user()->attackpower += $new1[1]; } if ($new1[0] == "strength") { $userrow["attackpower"] += $new1[1]; }
if ($new1[0] == "dexterity") { user()->defensepower += $new1[1]; } if ($new1[0] == "dexterity") { $userrow["defensepower"] += $new1[1]; }
if ($new2[0] == "strength") { user()->attackpower += $new2[1]; } if ($new2[0] == "strength") { $userrow["attackpower"] += $new2[1]; }
if ($new2[0] == "dexterity") { user()->defensepower += $new2[1]; } if ($new2[0] == "dexterity") { $userrow["defensepower"] += $new2[1]; }
$slot_s = 'slot'.$_POST["slot"]; $slot_s = 'slot'.$_POST["slot"];
$slot_name = "{$slot_s}name"; db()->query("UPDATE users SET {$slot_s}name=?, {$slot_s}id=?, {$new1[0]}=?, {$new2[0]}=?, attackpower=?, defensepower=?, currenthp=?, currentmp=?, currenttp=?, dropcode=0 WHERE id=?;", [
$slot_id = "{$slot_s}id"; $droprow["name"], $droprow["id"], $userrow[$new1[0]], $userrow[$new2[0]], $userrow["attackpower"], $userrow["defensepower"], $userrow["currenthp"], $userrow["currentmp"], $userrow["currenttp"], $userrow['id']
]);
user()->$slot_name = $droprow['name'];
user()->$slot_id = $droprow['id'];
} }
user()->save(); display("The item has been equipped. You can now continue <a href=\"/\">exploring</a>.", "Item Drop");
return display("The item has been equipped. You can now continue <a href=\"/\">exploring</a>.", "Item Drop");
} }
$attributearray = array("maxhp"=>"Max HP", $attributearray = array("maxhp"=>"Max HP",
@ -346,10 +370,10 @@ function drop()
} }
$page .= "<br>Select an inventory slot from the list below to equip this item. If the inventory slot is already full, the old item will be discarded."; $page .= "<br>Select an inventory slot from the list below to equip this item. If the inventory slot is already full, the old item will be discarded.";
$page .= "<form action=\"/drop\" method=\"post\"><select name=\"slot\"><option value=\"0\">Choose One</option><option value=\"1\">Slot 1: ".user()->slot1name."</option><option value=\"2\">Slot 2: ".user()->slot2name."</option><option value=\"3\">Slot 3: ".user()->slot3name."</option></select> <input type=\"submit\" name=\"submit\" value=\"Submit\" /></form>"; $page .= "<form action=\"/drop\" method=\"post\"><select name=\"slot\"><option value=\"0\">Choose One</option><option value=\"1\">Slot 1: ".$userrow["slot1name"]."</option><option value=\"2\">Slot 2: ".$userrow["slot2name"]."</option><option value=\"3\">Slot 3: ".$userrow["slot3name"]."</option></select> <input type=\"submit\" name=\"submit\" value=\"Submit\" /></form>";
$page .= "You may also choose to just continue <a href=\"/\">exploring</a> and give up this item."; $page .= "You may also choose to just continue <a href=\"/\">exploring</a> and give up this item.";
return display($page, "Item Drop"); display($page, "Item Drop");
} }
@ -361,45 +385,45 @@ function dead()
to continue your journey.<br><br> to continue your journey.<br><br>
You may now continue back to <a href="/">town</a>, and we hope you fair better next time. You may now continue back to <a href="/">town</a>, and we hope you fair better next time.
HTML; HTML;
return display($page, 'You Died'); display($page, 'You Died');
} }
function handleMonsterTurn(&$userrow, $monsterrow) function handleMonsterTurn(&$userrow, $monsterrow)
{ {
$pagearray = ""; $pagearray = "";
if (user()->currentmonstersleep != 0) { if ($userrow["currentmonstersleep"] != 0) {
$chancetowake = rand(1,15); $chancetowake = rand(1,15);
if ($chancetowake > user()->currentmonstersleep) { if ($chancetowake > $userrow["currentmonstersleep"]) {
user()->currentmonstersleep = 0; $userrow["currentmonstersleep"] = 0;
$pagearray .= "The monster has woken up.<br>"; $pagearray .= "The monster has woken up.<br>";
} else { } else {
$pagearray .= "The monster is still asleep.<br>"; $pagearray .= "The monster is still asleep.<br>";
} }
} }
if (user()->currentmonstersleep == 0) { if ($userrow["currentmonstersleep"] == 0) {
$tohit = (int)ceil(mt_rand((int)($monsterrow["maxdam"] * 0.5), (int)$monsterrow["maxdam"])); $tohit = (int)ceil(mt_rand((int)($monsterrow["maxdam"] * 0.5), (int)$monsterrow["maxdam"]));
$toblock = (int)ceil(mt_rand((int)(user()->defensepower * 0.75), (int)user()->defensepower) / 4); $toblock = (int)ceil(mt_rand((int)($userrow["defensepower"] * 0.75), (int)$userrow["defensepower"]) / 4);
$tododge = rand(1, 150); $tododge = rand(1, 150);
if ($tododge <= sqrt(user()->dexterity)) { if ($tododge <= sqrt($userrow["dexterity"])) {
$tohit = 0; $tohit = 0;
$pagearray .= "You dodge the monster's attack. No damage has been scored.<br>"; $pagearray .= "You dodge the monster's attack. No damage has been scored.<br>";
$persondamage = 0; $persondamage = 0;
} else { } else {
$persondamage = max(1, $tohit - $toblock); $persondamage = max(1, $tohit - $toblock);
if (user()->currentuberdefense != 0) { if ($userrow["currentuberdefense"] != 0) {
$persondamage -= (int)ceil($persondamage * (user()->currentuberdefense/100)); $persondamage -= (int)ceil($persondamage * ($userrow["currentuberdefense"]/100));
} }
$persondamage = max(1, $persondamage); $persondamage = max(1, $persondamage);
} }
$pagearray .= "The monster attacks you for $persondamage damage.<br><br>"; $pagearray .= "The monster attacks you for $persondamage damage.<br><br>";
user()->currenthp -= $persondamage; $userrow["currenthp"] -= $persondamage;
if (user()->currenthp <= 0) { if ($userrow["currenthp"] <= 0) {
$newgold = (int)ceil(user()->gold/2); $newgold = (int)ceil($userrow["gold"]/2);
$newhp = (int)ceil(user()->maxhp/4); $newhp = (int)ceil($userrow["maxhp"]/4);
db()->query("UPDATE users SET currenthp=?, currentaction='In Town', currentmonster=0, currentmonsterhp=0, currentmonstersleep=0, currentmonsterimmune=0, currentfight=0, latitude=0, longitude=0, gold=? WHERE id=?;", [ db()->query("UPDATE users SET currenthp=?, currentaction='In Town', currentmonster=0, currentmonsterhp=0, currentmonstersleep=0, currentmonsterimmune=0, currentfight=0, latitude=0, longitude=0, gold=? WHERE id=?;", [
$newhp, $newgold, $userrow['id'] $newhp, $newgold, $userrow['id']
]); ]);
@ -414,38 +438,38 @@ function handleSpellCast(&$userrow, $newspellrow)
$pagearray = ""; $pagearray = "";
switch ($newspellrow["type"]) { switch ($newspellrow["type"]) {
case 1: // Heal spell case 1: // Heal spell
$newhp = min(user()->currenthp + $newspellrow["attribute"], user()->maxhp); $newhp = min($userrow["currenthp"] + $newspellrow["attribute"], $userrow["maxhp"]);
user()->currenthp = $newhp; $userrow["currenthp"] = $newhp;
user()->currentmp -= $newspellrow["mp"]; $userrow["currentmp"] -= $newspellrow["mp"];
$pagearray = "You have cast the {$newspellrow["name"]} spell, and gained {$newspellrow["attribute"]} Hit Points.<br><br>"; $pagearray = "You have cast the {$newspellrow["name"]} spell, and gained {$newspellrow["attribute"]} Hit Points.<br><br>";
break; break;
case 2: // Hurt spell case 2: // Hurt spell
if (user()->currentmonsterimmune == 0) { if ($userrow["currentmonsterimmune"] == 0) {
$monsterdamage = mt_rand((int)(($newspellrow["attribute"]/6)*5), $newspellrow["attribute"]); $monsterdamage = mt_rand((int)(($newspellrow["attribute"]/6)*5), $newspellrow["attribute"]);
user()->currentmonsterhp -= $monsterdamage; $userrow["currentmonsterhp"] -= $monsterdamage;
$pagearray = "You have cast the {$newspellrow["name"]} spell for $monsterdamage damage.<br><br>"; $pagearray = "You have cast the {$newspellrow["name"]} spell for $monsterdamage damage.<br><br>";
} else { } else {
$pagearray = "You have cast the {$newspellrow["name"]} spell, but the monster is immune to it.<br><br>"; $pagearray = "You have cast the {$newspellrow["name"]} spell, but the monster is immune to it.<br><br>";
} }
user()->currentmp -= $newspellrow["mp"]; $userrow["currentmp"] -= $newspellrow["mp"];
break; break;
case 3: // Sleep spell case 3: // Sleep spell
if (user()->currentmonsterimmune != 2) { if ($userrow["currentmonsterimmune"] != 2) {
user()->currentmonstersleep = $newspellrow["attribute"]; $userrow["currentmonstersleep"] = $newspellrow["attribute"];
$pagearray = "You have cast the {$newspellrow["name"]} spell. The monster is asleep.<br><br>"; $pagearray = "You have cast the {$newspellrow["name"]} spell. The monster is asleep.<br><br>";
} else { } else {
$pagearray = "You have cast the {$newspellrow["name"]} spell, but the monster is immune to it.<br><br>"; $pagearray = "You have cast the {$newspellrow["name"]} spell, but the monster is immune to it.<br><br>";
} }
user()->currentmp -= $newspellrow["mp"]; $userrow["currentmp"] -= $newspellrow["mp"];
break; break;
case 4: // +Damage spell case 4: // +Damage spell
user()->currentuberdamage = $newspellrow["attribute"]; $userrow["currentuberdamage"] = $newspellrow["attribute"];
user()->currentmp -= $newspellrow["mp"]; $userrow["currentmp"] -= $newspellrow["mp"];
$pagearray = "You have cast the {$newspellrow["name"]} spell, and will gain {$newspellrow["attribute"]}% damage until the end of this fight.<br><br>"; $pagearray = "You have cast the {$newspellrow["name"]} spell, and will gain {$newspellrow["attribute"]}% damage until the end of this fight.<br><br>";
break; break;
case 5: // +Defense spell case 5: // +Defense spell
user()->currentuberdefense = $newspellrow["attribute"]; $userrow["currentuberdefense"] = $newspellrow["attribute"];
user()->currentmp -= $newspellrow["mp"]; $userrow["currentmp"] -= $newspellrow["mp"];
$pagearray = "You have cast the {$newspellrow["name"]} spell, and will gain {$newspellrow["attribute"]}% defense until the end of this fight.<br><br>"; $pagearray = "You have cast the {$newspellrow["name"]} spell, and will gain {$newspellrow["attribute"]}% defense until the end of this fight.<br><br>";
break; break;
} }

View File

@ -34,7 +34,7 @@ function donothing($start = 0)
$page .= "</table></td></tr></table>"; $page .= "</table></td></tr></table>";
return display($page, "Forum"); display($page, "Forum");
} }
function showthread($id, $start) function showthread($id, $start)
@ -49,7 +49,7 @@ function showthread($id, $start)
$page .= "</table></td></tr></table><br>"; $page .= "</table></td></tr></table><br>";
$page .= "<table width=\"100%\"><tr><td><b>Reply To This Thread:</b><br><form action=\"/forum/reply\" method=\"post\"><input type=\"hidden\" name=\"parent\" value=\"$id\" /><input type=\"hidden\" name=\"title\" value=\"Re: ".$title["title"]."\" /><textarea name=\"content\" rows=\"7\" cols=\"40\"></textarea><br><input type=\"submit\" name=\"submit\" value=\"Submit\" /> <input type=\"reset\" name=\"reset\" value=\"Reset\" /></form></td></tr></table>"; $page .= "<table width=\"100%\"><tr><td><b>Reply To This Thread:</b><br><form action=\"/forum/reply\" method=\"post\"><input type=\"hidden\" name=\"parent\" value=\"$id\" /><input type=\"hidden\" name=\"title\" value=\"Re: ".$title["title"]."\" /><textarea name=\"content\" rows=\"7\" cols=\"40\"></textarea><br><input type=\"submit\" name=\"submit\" value=\"Submit\" /> <input type=\"reset\" name=\"reset\" value=\"Reset\" /></form></td></tr></table>";
return display($page, "Forum"); display($page, "Forum");
} }
function reply() function reply()
@ -68,7 +68,7 @@ function reply()
$form = $form['data']; $form = $form['data'];
db()->query('INSERT INTO forum (author, title, content, parent) VALUES (?, ?, ?, ?);', [ db()->query('INSERT INTO forum (author, title, content, parent) VALUES (?, ?, ?, ?);', [
user()->username, $form['title'], $form['content'], $form['parent'] $userrow['username'], $form['title'], $form['content'], $form['parent']
]); ]);
db()->query('UPDATE forum SET newpostdate=CURRENT_TIMESTAMP, replies=replies + 1 WHERE id=?;', [$form['parent']]); db()->query('UPDATE forum SET newpostdate=CURRENT_TIMESTAMP, replies=replies + 1 WHERE id=?;', [$form['parent']]);
redirect("/forum/thread/{$form['parent']}/0"); redirect("/forum/thread/{$form['parent']}/0");
@ -76,6 +76,8 @@ function reply()
function newthread() function newthread()
{ {
global $userrow;
if (isset($_POST["submit"])) { if (isset($_POST["submit"])) {
$form = validate($_POST, [ $form = validate($_POST, [
'title' => ['length:2-30'], 'title' => ['length:2-30'],
@ -88,11 +90,11 @@ function newthread()
$form = $form['data']; $form = $form['data'];
db()->query('INSERT INTO forum (author, title, content) VALUES (?, ?, ?);', [ db()->query('INSERT INTO forum (author, title, content) VALUES (?, ?, ?);', [
user()->username, $form['title'], $form['content'] $userrow['username'], $form['title'], $form['content']
]); ]);
redirect('/forum'); redirect('/forum');
} }
$page = "<table width=\"100%\"><tr><td><b>Make A New Post:</b><br><br/ ><form action=\"/forum/new\" method=\"post\">Title:<br><input type=\"text\" name=\"title\" size=\"50\" maxlength=\"50\" /><br><br>Message:<br><textarea name=\"content\" rows=\"7\" cols=\"40\"></textarea><br><br><input type=\"submit\" name=\"submit\" value=\"Submit\" /> <input type=\"reset\" name=\"reset\" value=\"Reset\" /></form></td></tr></table>"; $page = "<table width=\"100%\"><tr><td><b>Make A New Post:</b><br><br/ ><form action=\"/forum/new\" method=\"post\">Title:<br><input type=\"text\" name=\"title\" size=\"50\" maxlength=\"50\" /><br><br>Message:<br><textarea name=\"content\" rows=\"7\" cols=\"40\"></textarea><br><br><input type=\"submit\" name=\"submit\" value=\"Submit\" /> <input type=\"reset\" name=\"reset\" value=\"Reset\" /></form></td></tr></table>";
return display($page, "Forum"); display($page, "Forum");
} }

View File

@ -12,11 +12,11 @@ function healspells($id)
// All the various ways to error out. // All the various ways to error out.
$spell = false; $spell = false;
foreach ($userspells as $b) if ($b == $id) $spell = true; foreach ($userspells as $b) if ($b == $id) $spell = true;
if ($spell !== true) return display("You have not yet learned this spell. Please go back and try again.", "Error"); if ($spell !== true) display("You have not yet learned this spell. Please go back and try again.", "Error");
if ($spellrow["type"] != 1) return display("This is not a healing spell. Please go back and try again.", "Error"); if ($spellrow["type"] != 1) display("This is not a healing spell. Please go back and try again.", "Error");
if ($userrow["currentmp"] < $spellrow["mp"]) return display("You do not have enough Magic Points to cast this spell. Please go back and try again.", "Error"); if ($userrow["currentmp"] < $spellrow["mp"]) display("You do not have enough Magic Points to cast this spell. Please go back and try again.", "Error");
if ($userrow["currentaction"] == "Fighting") return display("You cannot use the Quick Spells list during a fight. Please go back and select the Healing Spell you wish to use from the Spells box on the main fighting screen to continue.", "Error"); if ($userrow["currentaction"] == "Fighting") display("You cannot use the Quick Spells list during a fight. Please go back and select the Healing Spell you wish to use from the Spells box on the main fighting screen to continue.", "Error");
if ($userrow["currenthp"] == $userrow["maxhp"]) return display("Your Hit Points are already full. You don't need to use a Healing spell now.", "Error"); if ($userrow["currenthp"] == $userrow["maxhp"]) display("Your Hit Points are already full. You don't need to use a Healing spell now.", "Error");
$newhp = $userrow["currenthp"] + $spellrow["attribute"]; $newhp = $userrow["currenthp"] + $spellrow["attribute"];
if ($userrow["maxhp"] < $newhp) { $spellrow["attribute"] = $userrow["maxhp"] - $userrow["currenthp"]; $newhp = $userrow["currenthp"] + $spellrow["attribute"]; } if ($userrow["maxhp"] < $newhp) { $spellrow["attribute"] = $userrow["maxhp"] - $userrow["currenthp"]; $newhp = $userrow["currenthp"] + $spellrow["attribute"]; }
@ -24,5 +24,5 @@ function healspells($id)
db()->query('UPDATE users SET currenthp=?, currentmp=? WHERE id=?;', [$newhp, $newmp, $userrow['id']]); db()->query('UPDATE users SET currenthp=?, currentmp=? WHERE id=?;', [$newhp, $newmp, $userrow['id']]);
return display("You have cast the ".$spellrow["name"]." spell, and gained ".$spellrow["attribute"]." Hit Points. You can now continue <a href=\"/\">exploring</a>.", "Healing Spell"); display("You have cast the ".$spellrow["name"]." spell, and gained ".$spellrow["attribute"]." Hit Points. You can now continue <a href=\"/\">exploring</a>.", "Healing Spell");
} }

View File

@ -246,7 +246,7 @@ function main()
[ <a href="#top">Top</a> ] [ <a href="#top">Top</a> ]
HTML; HTML;
return display_help(parse($page, $controlrow)); display_help(parse($page, $controlrow));
} }
function items() function items()
@ -313,7 +313,7 @@ function items()
} }
$page .= '</table>'; $page .= '</table>';
return display_help($page); display_help($page);
} }
@ -349,7 +349,7 @@ function spells()
</ul> </ul>
HTML; HTML;
return display_help($page); display_help($page);
} }
function monsters() function monsters()
@ -368,7 +368,7 @@ function monsters()
$page .= "<tr><td width=\"30%\">".$m["name"]."</td><td width=\"10%\">".$m["maxhp"]."</td><td width=\"10%\">".$m["maxdam"]."</td><td width=\"10%\">".$m["armor"]."</td><td width=\"10%\">".$m["level"]."</td><td width=\"10%\">".$m["maxexp"]."</td><td width=\"10%\">".$m["maxgold"]."</td><td width=\"20%\">$immune</td></tr>\n"; $page .= "<tr><td width=\"30%\">".$m["name"]."</td><td width=\"10%\">".$m["maxhp"]."</td><td width=\"10%\">".$m["maxdam"]."</td><td width=\"10%\">".$m["armor"]."</td><td width=\"10%\">".$m["level"]."</td><td width=\"10%\">".$m["maxexp"]."</td><td width=\"10%\">".$m["maxgold"]."</td><td width=\"20%\">$immune</td></tr>\n";
} }
return display_help($page.'</table>'); display_help($page.'</table>');
} }
function levels() function levels()
@ -489,13 +489,13 @@ function levels()
Experience points listed are total values up until that point. All other values are just the new amount that you gain for each level. Experience points listed are total values up until that point. All other values are just the new amount that you gain for each level.
HTML; HTML;
return display_help(parse($page, $controlrow)); display_help(parse($page, $controlrow));
} }
function display_help(string $content) function display_help(string $content)
{ {
global $controlrow; global $controlrow;
return render('layouts/help', [ echo render('layouts/help', [
'control' => $controlrow, 'control' => $controlrow,
'content' => $content, 'content' => $content,
'version' => VERSION, 'version' => VERSION,

View File

@ -9,8 +9,9 @@ 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('/shop', 'Towns\shop'); $r->get('/buy', 'Towns\buy');
$r->form('/buy/:id', 'Towns\buy'); $r->get('/buy2/:id', 'Towns\buy2');
$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');
@ -26,31 +27,28 @@ function town()
{ {
global $controlrow; global $controlrow;
$town = get_town_by_xy(user()->longitude, user()->latitude); $townrow = 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.'); if ($townrow === false) display("There is an error with your user account, or with the town data. Please try again.","Error");
$page = ['news' => '', 'whos_online' => '']; $townrow["news"] = "";
$townrow["whosonline"] = "";
$townrow["babblebox"] = "";
// News box. Grab latest news entry and display it. Something a little more graceful coming soon maybe. // News box. Grab latest news entry and display it. Something a little more graceful coming soon maybe.
if ($controlrow['shownews'] === 1) { if ($controlrow["shownews"] == 1) {
$news = db()->query('SELECT * FROM news ORDER BY id DESC LIMIT 1;')->fetchArray(SQLITE3_ASSOC); $newsrow = db()->query('SELECT * FROM news ORDER BY id DESC LIMIT 1;')->fetchArray(SQLITE3_ASSOC);
$news_date = pretty_date($news["postdate"]); $townrow["news"] = '<div class="title">Latest News</div>';
$news_content = nl2br($news["content"]); $townrow["news"] .= "<span class=\"light\">[".pretty_date($newsrow["postdate"])."]</span><br>".nl2br($newsrow["content"]);
$page['news'] = <<<HTML
<div class="title">Latest News</div>
<span class="light">$news_date</span><br>
$news_content
HTML;
} }
// Who's Online. Currently just members. Guests maybe later. // Who's Online. Currently just members. Guests maybe later.
if ($controlrow['showonline'] === 1) { if ($controlrow["showonline"] == 1) {
$onlinequery = db()->query(<<<SQL $onlinequery = db()->query(<<<SQL
SELECT id, username SELECT id, username
FROM users FROM users
WHERE onlinetime >= datetime('now', '-600 seconds') WHERE onlinetime >= datetime('now', '-600 seconds')
ORDER BY username; ORDER BY username;
SQL); SQL);
$online_count = 0; $online_count = 0;
$online_rows = []; $online_rows = [];
@ -60,20 +58,27 @@ function town()
$online_rows[] = "<a href=\"javascript:opencharpopup({$onlinerow['id']})\">".$onlinerow["username"]."</a>"; $online_rows[] = "<a href=\"javascript:opencharpopup({$onlinerow['id']})\">".$onlinerow["username"]."</a>";
} }
$online_rows = implode(', ', $online_rows); $townrow["whosonline"] = '<div class="title">Who\'s Online</div>';
$page['whos_online'] = <<<HTML $townrow["whosonline"] .= "There are <b>$online_count</b> user(s) online within the last 10 minutes: ";
<div class="title">Who's Online</div> $townrow["whosonline"] .= rtrim(implode(', ', $online_rows), ', ');
There are <b>$online_count</b> user(s) online within the last 10 minutes: $online_rows }
if ($controlrow["showbabble"] == 1) {
$townrow["babblebox"] = <<<HTML
<div class="title">Babble Box</div>
<iframe src="/babblebox" name="sbox" width="100%" height="250" frameborder="0" id="bbox">
Your browser does not support inline frames! The Babble Box will not be available until you upgrade to
a newer <a href="http://www.mozilla.org" target="_new">browser</a>.
</iframe>
HTML; HTML;
} }
page_title($town['name']); if (is_htmx()) htmx_update_page_title($townrow['name']);
return render('towns', ['town' => $town, 'news' => $page['news'], 'whos_online' => $page['whos_online']]); return render('towns', ['town' => $townrow]);
} }
/** /**
* 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()
{ {
@ -81,29 +86,28 @@ function inn()
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'] . ' Inn'); if ($htmx) htmx_update_page_title($town['name'] . ' Inn');
if (user()->gold < $town['innprice']) { if (user()->gold < $town['innprice']) {
$page = <<<HTML $page = <<<HTML
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 ($_SERVER['REQUEST_METHOD'] === 'POST' && $_POST['rest']) { } elseif (isset($_POST['submit'])) {
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 ($_SERVER['REQUEST_METHOD'] === 'POST' && !$_POST['rest']) { } elseif (isset($_POST['cancel'])) {
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">
<button name="rest" value="1">Yes</button> <input type="submit" name="submit" value="Yes"> <input type="submit" name="cancel" value="No">
<button name="rest" value="0">No</button>
</form> </form>
HTML; HTML;
} }
@ -112,17 +116,15 @@ function 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, * Displays a list of available items for purchase.
* redirects to home.
* GET /shop
*/ */
function shop() function buy()
{ {
$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'); if ($htmx) htmx_update_page_title($town['name'] . ' Shop');
$page = <<<HTML $page = <<<HTML
Buying weapons will increase your Attack Power. Buying armor and shields will increase your Defense Power.<br><br> Buying weapons will increase your Attack Power. Buying armor and shields will increase your Defense Power.<br><br>
@ -150,7 +152,7 @@ function shop()
} else { } else {
$specialdot = $item['special'] !== 'X' ? '<span class="highlight">&#42;</span>' : ''; $specialdot = $item['special'] !== 'X' ? '<span class="highlight">&#42;</span>' : '';
$page .= <<<HTML $page .= <<<HTML
<td width="32%"><b><a hx-get="/buy/{$item['id']}" hx-target="#middle">{$item['name']}</a>$specialdot</b></td> <td width="32%"><b><a href="/buy2/{$item['id']}">{$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;
@ -168,116 +170,137 @@ function shop()
/** /**
* Confirm user's intent to purchase item. * Confirm user's intent to purchase item.
*/ */
function buy(int $id) function buy2($id)
{ {
$town = get_town_by_xy(user()->longitude, user()->latitude); $townrow = get_town_by_xy(user()->longitude, user()->latitude);
if ($town === false) redirect('/'); if ($townrow === false) display("Cheat attempt detected.<br><br>Get a life, loser.", "Error");
if (!in_array($id, explode(',', $town['itemslist']))) redirect('/shop'); $townitems = explode(",", $townrow["itemslist"]);
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 (!$can_afford) { if (user()->gold < $item["buycost"]) {
$page = <<<HTML 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");
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']
];
if (!isset($type_mapping[$item["type"]])) { // should never happen $type_to_row_mapping = [1 => 'weaponid', 2 => 'armorid', 3 => 'shieldid'];
$page = 'Error! Invalid item type...<br>'.var_dump($item); $current_equipped_id = user()[$type_to_row_mapping[$item['type']] ?? 0];
return is_htmx() ? $page : display($page, '');
}
// Retrieve current equipped item or create a default if ($current_equipped_id != 0) {
$current_equip_id = user()->{$type_mapping[$item["type"]]['id']}; $item2 = get_item($current_equipped_id);
if ($current_equip_id != 0) { $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>";
$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 { } else {
$type_to_row_mapping = [1 => 'weaponid', 2 => 'armorid', 3 => 'shieldid']; $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>";
$current_equipped_id = user()->{$type_to_row_mapping[$item['type']]} ?? 0; }
if ($current_equipped_id != 0) { display($page, "Buy Items");
$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> * Update user profile with new item & stats.
<form hx-post="/buy/$id" hx-target="#middle"> */
<button name="buy" value="1">Yes</button> function buy3($id)
<button name="buy" value="0">No</button> {
</form>
HTML; if (isset($_POST["cancel"])) redirect('/');
} else {
$page = <<<HTML $townrow = get_town_by_xy(user()->longitude, user()->latitude);
You are buying {$item['name']} for {$item['buycost']} gold, is that ok?<br><br> if ($townrow === false) display("Cheat attempt detected.<br><br>Get a life, loser.", "Error");
<form hx-post="/buy/$id" hx-target="#middle"> $townitems = explode(",", $townrow["itemslist"]);
<button name="buy" value="1">Yes</button> if (!in_array($id, $townitems)) display("Cheat attempt detected.<br><br>Get a life, loser.", "Error");
<button name="buy" value="0">No</button>
</form> $item = get_item($id);
HTML;
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;
}
} }
} }
page_title('Buying '.$item['name']); // Determine power and type-specific updates
return is_htmx() ? $page : display($page, 'Buying '.$item['name']); $currentType = $type_mapping[$item["type"]];
$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");
} }
/** /**
@ -360,20 +383,21 @@ function travelto($id, bool $usepoints = true)
if ($usepoints) { if ($usepoints) {
if (user()->currenttp < $townrow["travelpoints"]) { 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"); 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); $mapped = explode(",",user()->towns);
if (!in_array($id, $mapped)) { display("Cheat attempt detected.<br><br>Get a life, loser.", "Error"); } if (!in_array($id, $mapped)) { display("Cheat attempt detected.<br><br>Get a life, loser.", "Error"); }
} }
if ((user()->latitude == $townrow["latitude"]) && (user()->longitude == $townrow["longitude"])) { if ((user()->latitude == $townrow["latitude"]) && (user()->longitude == $townrow["longitude"])) {
return display("You are already in this town. <a href=\"/\">Click here</a> to return to the main town screen.", "Travel To"); display("You are already in this town. <a href=\"/\">Click here</a> to return to the main town screen.", "Travel To");
} }
$newtp = ($usepoints) ? user()->currenttp - $townrow["travelpoints"] : user()->currenttp; $newtp = ($usepoints) ? user()->currenttp - $townrow["travelpoints"] : user()->currenttp;
$newlat = $townrow["latitude"]; $newlat = $townrow["latitude"];
$newlon = $townrow["longitude"]; $newlon = $townrow["longitude"];
$newid = user()->id;
// If they got here by exploring, add this town to their map. // If they got here by exploring, add this town to their map.
$mapped = explode(",",user()->towns); $mapped = explode(",",user()->towns);
@ -382,13 +406,12 @@ function travelto($id, bool $usepoints = true)
$mapped = implode(",", $mapped); $mapped = implode(",", $mapped);
if ($town == false) $mapped .= ",$id"; if ($town == false) $mapped .= ",$id";
user()->currentaction = 'In Town'; $mapped = "towns='".$mapped."',";
user()->towns = $mapped;
user()->currenttp = $newtp; db()->query("UPDATE users SET currentaction='In Town',$mapped currenttp=?, latitude=?, longitude=? WHERE id=?;", [
user()->longitude = $newlon; $newtp, $newlat, $newlon, $newid
user()->latitude = $newlat; ]);
user()->save();
$page = "You have travelled to ".$townrow["name"].". You may now <a href=\"/\">enter this town</a>."; $page = "You have travelled to ".$townrow["name"].". You may now <a href=\"/\">enter this town</a>.";
return display($page, "Travel To"); display($page, "Travel To");
} }

View File

@ -47,7 +47,7 @@ function login()
redirect('/'); redirect('/');
} }
return display(render('login'), 'Log In', true, false, false); display(render('login'), 'Log In', true, false, false);
} }
/** /**
@ -109,7 +109,7 @@ function register()
$page = render('register', ['controlrow' => $controlrow]); $page = render('register', ['controlrow' => $controlrow]);
} }
return display($page, 'Register', true, false, false); display($page, 'Register', true, false, false);
} }
function verify() function verify()
@ -124,10 +124,10 @@ function verify()
db()->query("UPDATE users SET verify='g2g' WHERE username=?;", [$u]); db()->query("UPDATE users SET verify='g2g' WHERE username=?;", [$u]);
return display("Your account was verified successfully.<br><br>You may now continue to the <a href=\"/login\">Login Page</a> and start playing the game.<br><br>Thanks for playing!","Verify Email",false,false,false); display("Your account was verified successfully.<br><br>You may now continue to the <a href=\"/login\">Login Page</a> and start playing the game.<br><br>Thanks for playing!","Verify Email",false,false,false);
} }
return display(render('verify'), "Verify Email", true, false, false); display(render('verify'), "Verify Email", true, false, false);
} }
function lostpassword() function lostpassword()
@ -143,13 +143,13 @@ function lostpassword()
db()->query('UPDATE users SET password=? WHERE email=?;', [$hashed, $e]); db()->query('UPDATE users SET password=? WHERE email=?;', [$hashed, $e]);
if (sendpassemail($e, $newpass)) { if (sendpassemail($e, $newpass)) {
return display("Your new password was emailed to the address you provided.<br><br>Once you receive it, you may <a href=\"/login\">Log In</a> and continue playing.<br><br>Thank you.","Lost Password",false,false,false); display("Your new password was emailed to the address you provided.<br><br>Once you receive it, you may <a href=\"/login\">Log In</a> and continue playing.<br><br>Thank you.","Lost Password",false,false,false);
} else { } else {
return display("There was an error sending your new password.<br><br>Please check with the game administrator for more information.<br><br>We apologize for the inconvience.","Lost Password",false,false,false); display("There was an error sending your new password.<br><br>Please check with the game administrator for more information.<br><br>We apologize for the inconvience.","Lost Password",false,false,false);
} }
} }
return display(render('lostpassword'), "Lost Password", true, false, false); display(render('lostpassword'), "Lost Password", true, false, false);
} }
function changepassword() function changepassword()
@ -179,10 +179,10 @@ function changepassword()
set_cookie('dkgame', '', -3600); set_cookie('dkgame', '', -3600);
return display("Your password was changed successfully.<br><br>You have been logged out of the game to avoid errors.<br><br>Please <a href=\"/login\">log back in</a> to continue playing.","Change Password",false,false,false); display("Your password was changed successfully.<br><br>You have been logged out of the game to avoid errors.<br><br>Please <a href=\"/login\">log back in</a> to continue playing.","Change Password",false,false,false);
} }
return display(render('changepassword'), "Change Password", true, false, false); display(render('changepassword'), "Change Password", true, false, false);
} }
function settings() function settings()
@ -198,10 +198,10 @@ function settings()
user()->save(); user()->save();
$alert = '<div class="alert">Settings updated</div>'; $alert = '<div class="alert">Settings updated</div>';
return display($alert . render('settings'), "Account Settings"); display($alert . render('settings'), "Account Settings");
} }
return display(render('settings'), "Account Settings"); display(render('settings'), "Account Settings");
} }
function sendpassemail($emailaddress, $password) function sendpassemail($emailaddress, $password)

View File

@ -19,7 +19,7 @@ require_once 'models/user.php';
env_load('../.env'); env_load('../.env');
$uri = explode('/', trim($_SERVER['REQUEST_URI'], '/')); $uri = uri();
$GLOBALS['cache'] = []; $GLOBALS['cache'] = [];
$GLOBALS['state'] = []; $GLOBALS['state'] = [];
@ -27,7 +27,7 @@ if (!file_exists('../.installed') && $uri[0] !== 'install') {
redirect('/install'); redirect('/install');
} elseif (file_exists(('../.installed')) && $uri[0] === 'install') { } elseif (file_exists(('../.installed')) && $uri[0] === 'install') {
redirect('/'); redirect('/');
} elseif (file_exists(('../.installed')) && $uri[0] !== 'install') { } else {
$controlrow = get_control_row(); $controlrow = get_control_row();
if (!$controlrow["gameopen"]) { if (!$controlrow["gameopen"]) {

View File

@ -20,8 +20,8 @@ function db(): Database
function redirect(string $location): void function redirect(string $location): void
{ {
if (is_htmx()) { if (is_htmx()) {
$json = json_encode(['path' => $location, 'target' => '#'.$_SERVER['HTTP_HX_TARGET'] ?? '#middle']); header("HX-Redirect: $location");
header("HX-Location: $json"); header("HX-Replace-Url: $location");
} else { } else {
header("Location: $location"); header("Location: $location");
} }
@ -107,13 +107,46 @@ function display($content, $title, bool $topnav = true, bool $leftnav = true, bo
{ {
global $controlrow; global $controlrow;
$game_skin = user() !== false ? user()->game_skin : 0; $game_skin = 0;
$topnav = $topnav ? Render\header_links() : '';
if (user() !== false) {
$game_skin = user()->game_skin;
if (user()->currentaction == 'In Town') {
$town = get_town_by_xy(user()->latitude, user()->longitude);
$current_town = "Welcome to <b>{$town['name']}</b>.<br><br>";
} else {
$current_town = '';
}
// Format various userrow stuffs...
if (user()->latitude < 0) { user()->latitude = user()->latitude * -1 . "S"; } else { user()->latitude .= "N"; }
if (user()->longitude < 0) { user()->longitude = user()->longitude * -1 . "W"; } else { user()->longitude .= "E"; }
// Travel To list.
$townslist = explode(",",user()->towns);
$townquery2 = db()->query('SELECT * FROM towns ORDER BY id;');
$town_list_html = '';
while ($townrow2 = $townquery2->fetchArray(SQLITE3_ASSOC)) {
$town = false;
foreach($townslist as $id) {
if ($id == $townrow2["id"]) { $town = true; }
}
if ($town == true) {
$town_list_html .= "<a href=\"/gotown/{$townrow2["id"]}\">".$townrow2["name"]."</a><br>\n";
}
}
}
return render('layouts/primary', [ return render('layouts/primary', [
"dkgamename" => $controlrow["gamename"], "dkgamename" => $controlrow["gamename"],
"title" => $title,
"content" => $content, "content" => $content,
"game_skin" => $game_skin, "game_skin" => $game_skin,
"topnav" => $topnav ? Render\header_links() : '' "leftnav" => $leftnav ? render('leftnav', ['town_list' => $town_list_html, 'current_town' => $current_town]) : '',
"topnav" => $topnav,
]); ]);
} }
@ -452,6 +485,14 @@ 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.
*/ */
@ -515,8 +556,6 @@ function get_spells_from_list(array|string $spell_ids): array|false
function generate_stat_bar(int $current, int $max): string function generate_stat_bar(int $current, int $max): string
{ {
$percent = $max > 0 ? round(max(0, $current) / $max * 100, 4) : 0; $percent = $max > 0 ? round(max(0, $current) / $max * 100, 4) : 0;
if ($percent < 0) $percent = 0;
if ($percent > 100) $percent = 100;
$color = $percent >= 66 ? 'green' : ($percent >= 33 ? 'yellow' : 'red'); $color = $percent >= 66 ? 'green' : ($percent >= 33 ? 'yellow' : 'red');
return <<<HTML return <<<HTML
@ -559,11 +598,8 @@ function is_htmx(): bool
} }
/** /**
* Get the current page title per updates. Optionally set a new title. * Update the page title using HTMX.
*/ */
function page_title(string $new_title = ''): string function htmx_update_page_title(string $new_title) {
{ header('HX-Trigger: ' . json_encode(['updateTitle' => ['title' => $new_title]]));
global $controlrow;
if ($new_title) return $GLOBALS['state']['new-page-title'] = $new_title;
return $GLOBALS['state']['new-page-title'] ?? $controlrow['gamename'];
} }

View File

@ -39,27 +39,7 @@ function right_nav(): string
return $template; return $template;
} }
function left_nav(): string
{
if (user() === false) return '';
$template = render('left_nav');
if (is_htmx()) $template = '<section id="left" hx-swap-oob="true">'.$template."</section>";
return $template;
}
function babblebox(): string function babblebox(): string
{ {
return render('babblebox', ['messages' => babblebox_messages()]); return render('babblebox', ['messages' => babblebox_messages()]);
} }
function debug_query_log(): string
{
$html = '<pre id="debug-query-log" hx-swap-oob="true">';
foreach (db()->log as $record) {
$query_string = str_replace(["\r\n", "\n", "\r"], ' ', $record[0]);
$error_string = !empty($record[2]) ? '// '.$record[2] : '';
$html .= '<div>['.round($record[1], 2)."s] {$query_string}{$error_string}</div>";
}
return $html . '</pre>';
}

View File

@ -10,7 +10,7 @@
</form> </form>
<script> <script>
let chatBox = document.querySelector('#babblebox > .messages') const 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;

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= page_title() ?></title> <title><?= $title ?></title>
<link rel="stylesheet" href="/css/dk.css"> <link rel="stylesheet" href="/css/dk.css">
<script src="/js/htmx.js"></script> <script src="/js/htmx.js"></script>
@ -23,12 +23,12 @@
<body class="skin-<?= $game_skin ?>"> <body class="skin-<?= $game_skin ?>">
<div id="game-container"> <div id="game-container">
<header> <header>
<a href="/"><img id="logo" src="/img/logo.gif" alt="<?= $dkgamename ?>" title="<?= $dkgamename ?>"></a> <img id="logo" src="/img/logo.gif" alt="<?= $dkgamename ?>" title="<?= $dkgamename ?>">
<nav><?= $topnav ?></nav> <nav><?= $topnav ?></nav>
</header> </header>
<main> <main>
<section id="left"><?= Render\left_nav() ?></section> <section id="left"><?= $leftnav ?></section>
<section id="middle"><?= $content ?></section> <section id="middle"><?= $content ?></section>
<section id="right"><?= Render\right_nav() ?></section> <section id="right"><?= Render\right_nav() ?></section>
</main> </main>
@ -40,7 +40,27 @@
<div>Version <?= VERSION ?> <?= BUILD ?></div> <div>Version <?= VERSION ?> <?= BUILD ?></div>
</footer> </footer>
<?php if (env('debug', false)) echo Render\debug_query_log(); ?> <?php
if (env('debug', false)) {
echo '<pre>';
foreach (db()->log as $record) {
$query_string = str_replace(["\r\n", "\n", "\r"], ' ', $record[0]);
$error_string = !empty($record[2]) ? '// '.$record[2] : '';
echo '<div>['.round($record[1], 2)."s] {$query_string}{$error_string}</div>";
}
echo '</pre>';
}
?>
</div> </div>
<script>
document.addEventListener("updateTitle", (event) => {
const title = event.detail?.title
if (title) {
console.log('New title:', title);
document.title = title;
}
})
</script>
</body> </body>
</html> </html>

View File

@ -1,14 +1,8 @@
<section> <section>
<div class="title"><img src="/img/button_location.gif" alt="Location" title="Location"></div> <div class="title"><img src="/img/button_location.gif" alt="Location" title="Location"></div>
Currently: <?= user()->currentaction ?><br> Currently: <?= user()->currentaction ?><br>
<?php Latitude: <?= user()->latitude ?><br>
$lat = user()->latitude; Longitude: <?= user()->longitude ?><br>
$lon = user()->longitude;
if ($lat < 0) { $lat = ($lat * -1) . "S"; } else { $lat .= "N"; }
if ($lon < 0) { $lon = ($lon * -1) . "W"; } else { $lon .= "E"; }
?>
Latitude: <?= $lat ?><br>
Longitude: <?= $lon ?><br>
<a href="javascript:openmappopup()">View Map</a><br> <a href="javascript:openmappopup()">View Map</a><br>
<form action="/move" method="post" class="move-compass"> <form action="/move" method="post" class="move-compass">
<button type="submit" name="direction" value="north" class="north">North</button> <button type="submit" name="direction" value="north" class="north">North</button>
@ -23,24 +17,13 @@
<section> <section>
<div class="title"><img src="/img/button_towns.gif" alt="Towns" title="Towns"></div> <div class="title"><img src="/img/button_towns.gif" alt="Towns" title="Towns"></div>
<?php <?php
if (user()->currentaction == 'In Town') { if (user()->currentaction == 'In Town') {
$town = get_town_by_xy((int) user()->latitude, (int) user()->longitude); $town = get_town_by_xy((int) user()->latitude, (int) user()->longitude);
echo "Welcome to <b>{$town['name']}</b>.<br><br>"; echo "Welcome to <b>{$town['name']}</b>.<br><br>";
} }
?> ?>
Travel To:<br> Travel To:<br>
<?php <?= $town_list ?>
$town_list = explode(",", user()->towns);
$towns = db()->query('SELECT * FROM towns ORDER BY id;');
$mapped = false;
while ($row = $towns->fetchArray(SQLITE3_ASSOC)) {
$mapped = true;
if (in_array($row['id'], $town_list)) {
echo "<a href=\"/gotown/{$row["id"]}\">".$row["name"]."</a><br>";
}
}
if (!$mapped) echo 'You have no towns mapped.';
?>
</section> </section>
<section> <section>

View File

@ -13,9 +13,9 @@
<section> <section>
<div class="title"><img src="/img/button_inventory.gif" alt="Inventory" title="Inventory"></div> <div class="title"><img src="/img/button_inventory.gif" alt="Inventory" title="Inventory"></div>
<img src="/img/icon_weapon.gif" alt="Weapon" title="Weapon"> <?= user()->weaponname ?><br> <img src="/img/icon_weapon.gif" alt="Weapon" title="Weapon"> Weapon: <?= user()->weaponname ?><br>
<img src="/img/icon_armor.gif" alt="Armor" title="Armor"> <?= user()->armorname ?><br> <img src="/img/icon_armor.gif" alt="Armor" title="Armor"> Armor: <?= user()->armorname ?><br>
<img src="/img/icon_shield.gif" alt="Shield" title="Shield"> <?= user()->shieldname ?><br> <img src="/img/icon_shield.gif" alt="Shield" title="Shield"> Shield: <?= user()->shieldname ?><br>
Slot 1: <?= user()->slot1name ?><br> Slot 1: <?= user()->slot1name ?><br>
Slot 2: <?= user()->slot2name ?><br> Slot 2: <?= user()->slot2name ?><br>
Slot 3: <?= user()->slot3name ?> Slot 3: <?= user()->slot3name ?>

View File

@ -2,19 +2,19 @@
<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 hx-boost="true" hx-target="#middle"> <ul>
<li><a href="/inn">Rest at the Inn</a></li> <li><a hx-get="/inn" hx-target="#middle">Rest at the Inn</a></li>
<li><a href="/shop">Browse the Shop</a></li> <li><a hx-get="/buy" hx-target="#middle">Buy Weapons/Armor</a></li>
<li><a href="/maps">Buy Maps</a></li> <li><a href="/maps">Buy Maps</a></li>
</ul> </ul>
</div> </div>
<div class="news"> <div class="news">
<?= $news ?> <?= $town['news'] ?>
</div> </div>
<div class="whos-online"> <div class="whos-online">
<?= $whos_online ?> <?= $town['whosonline'] ?>
</div> </div>
<div class="babblebox"> <div class="babblebox">