forked from Sky/Dragon-Knight
457 lines
20 KiB
PHP
457 lines
20 KiB
PHP
<?php
|
|
|
|
// fight.php :: Handles all fighting action.
|
|
|
|
namespace Fights;
|
|
|
|
use Router;
|
|
|
|
function register_routes(Router $r): Router
|
|
{
|
|
$r->form('/fight', 'Fights\fight');
|
|
$r->get('/victory', 'Fights\victory');
|
|
$r->form('/drop', 'Fights\drop');
|
|
$r->get('/dead', 'Fights\dead');
|
|
return $r;
|
|
}
|
|
|
|
/**
|
|
* One big long function that determines the outcome of the fight.
|
|
*/
|
|
function fight()
|
|
{
|
|
if (user()->currentaction !== 'Fighting') exit('Cheat attempt detected.<br><br>Get a life, loser.');
|
|
|
|
$page = ["magiclist" => "", "yourturn" => "", "monsterturn" => "", "monsterhp" => "", "command" => ""];
|
|
$playerisdead = 0;
|
|
|
|
// Generate spell list
|
|
$user_spells = user()->spells();
|
|
if (!empty($user_spells)) {
|
|
$page['magiclist'] = '<select name="userspell">';
|
|
foreach ($user_spells as $spell) {
|
|
$page['magiclist'] .= "<option value=\"{$spell['id']}\">{$spell['name']}</option>\n";
|
|
}
|
|
$page['magiclist'] .= '</select> <input type="submit" name="spell" value="Spell"><br><br>';
|
|
}
|
|
|
|
// Determine initial combat parameters
|
|
$chancetoswingfirst = rand(1, 10) + (int)ceil(sqrt(user()->dexterity));
|
|
if (user()->currentfight === 1) {
|
|
$maxlevel = (int)floor(max(abs(user()->latitude) + 5, abs(user()->longitude) + 5) / 5);
|
|
$minlevel = max(1, $maxlevel - 2);
|
|
|
|
$monster = db()->query('SELECT * FROM monsters WHERE level >= ? AND level <= ? ORDER BY RANDOM() LIMIT 1;', [
|
|
$minlevel, $maxlevel
|
|
])->fetchArray(SQLITE3_ASSOC);
|
|
|
|
user()->currentmonster = $monster["id"];
|
|
user()->currentmonsterhp = rand((int)(($monster["maxhp"]/5)*4), $monster["maxhp"]);
|
|
user()->currentmonstersleep = 0;
|
|
user()->currentmonsterimmune = $monster["immune"];
|
|
|
|
$chancetoswingfirst = ($chancetoswingfirst > (rand(1,7) + (int)ceil(sqrt($monster["maxdam"])))) ? 1 : 0;
|
|
}
|
|
|
|
// Get monster statistics
|
|
$monster = get_monster(user()->currentmonster);
|
|
$page['monstername'] = $monster['name'];
|
|
|
|
// Run action
|
|
if (isset($_POST["run"])) {
|
|
$chancetorun = rand(4,10) + (int)ceil(sqrt(user()->dexterity));
|
|
if ($chancetorun <= (rand(1,5) + (int)ceil(sqrt($monster["maxdam"])))) {
|
|
$page["yourturn"] = "You tried to run away, but were blocked in front!<br><br>";
|
|
$page["monsterhp"] = "Monster's HP: " . user()->currentmonsterhp . "<br><br>";
|
|
|
|
// Monster turn logic (similar to original function)
|
|
$page["monsterturn"] = handleMonsterTurn($userrow, $monster);
|
|
|
|
user()->currentaction = 'Exploring';
|
|
user()->save();
|
|
redirect('/');
|
|
}
|
|
}
|
|
|
|
// Fight action
|
|
if (isset($_POST["fight"])) {
|
|
// Player's attack
|
|
$min = (int)(user()->attackpower * 0.75);
|
|
$max = (int)(user()->attackpower / 3);
|
|
$tohit = (int)ceil(mt_rand(min($min, $max), max($min, $max)));
|
|
|
|
$toexcellent = rand(1,150);
|
|
if ($toexcellent <= sqrt(user()->strength)) {
|
|
$tohit *= 2;
|
|
$page["yourturn"] .= "Excellent hit!<br>";
|
|
}
|
|
|
|
$min = (int)($monster["armor"] * 0.75);
|
|
$max = (int)$monster["armor"];
|
|
$toblock = (int)ceil(rand(min($min, $max), max($min, $max)) / 3);
|
|
|
|
$tododge = rand(1, 100);
|
|
|
|
$monsterdamage = max(1, $tohit - $toblock);
|
|
if ($tododge <= sqrt($monster["armor"])) {
|
|
$monsterdamage = 0;
|
|
$page["yourturn"] .= "The monster is dodging. No damage has been scored.<br>";
|
|
}
|
|
|
|
if (user()->currentuberdamage != 0) {
|
|
$monsterdamage += (int)ceil($monsterdamage * (user()->currentuberdamage / 100));
|
|
}
|
|
|
|
user()->currentmonsterhp -= $monsterdamage;
|
|
$page["yourturn"] .= "You attack the monster for $monsterdamage damage.<br><br>";
|
|
$page["monsterhp"] = "Monster's HP: " . user()->currentmonsterhp . "<br><br>";
|
|
|
|
// Check for monster defeat
|
|
if (user()->currentmonsterhp <= 0) {
|
|
user()->currentmonsterhp = 0;
|
|
user()->save();
|
|
redirect('/victory');
|
|
}
|
|
|
|
// Monster's turn
|
|
$page["monsterturn"] = handleMonsterTurn($userrow, $monster);
|
|
}
|
|
|
|
// Spell action
|
|
if (isset($_POST["spell"])) {
|
|
$pickedspell = $_POST["userspell"];
|
|
if ($pickedspell == 0) return \Render\content('You must select a spell first. Please go back and try again.');
|
|
|
|
$newspellrow = get_spell($pickedspell);
|
|
$spell = in_array($pickedspell, explode(',', user()->spells));
|
|
|
|
if (!$spell) return \Render\content('You have not yet learned this spell. Please go back and try again.');
|
|
|
|
if (user()->currentmp < $newspellrow["mp"]) {
|
|
return \Render\content('You do not have enough Magic Points to cast this spell. Please go back and try again.');
|
|
}
|
|
|
|
// Spell type handling (similar to original function)
|
|
$page["yourturn"] = handleSpellCast($userrow, $newspellrow);
|
|
$page["monsterhp"] = "Monster's HP: " . user()->currentmonsterhp . "<br><br>";
|
|
|
|
// Check for monster defeat
|
|
if (user()->currentmonsterhp <= 0) {
|
|
user()->currentmonsterhp = 0;
|
|
user()->save();
|
|
redirect('/victory');
|
|
}
|
|
|
|
// Monster's turn
|
|
$page["monsterturn"] = handleMonsterTurn($userrow, $monster);
|
|
}
|
|
|
|
// Monster's turn if player lost first swing
|
|
if (!isset($_POST["run"]) && !isset($_POST["fight"]) && !isset($_POST["spell"]) && $chancetoswingfirst == 0) {
|
|
$page["yourturn"] = "The monster attacks before you are ready!<br><br>";
|
|
$page["monsterhp"] = "Monster's HP: " . user()->currentmonsterhp . "<br><br>";
|
|
$page["monsterturn"] = handleMonsterTurn($userrow, $monster);
|
|
}
|
|
|
|
// Prepare command or death message
|
|
if ($playerisdead != 1) {
|
|
$page["command"] = <<<HTML
|
|
Command?<br><br>
|
|
<form action="/fight" method="post" hx-post="/fight" hx-target="#middle">
|
|
<input type="submit" name="fight" value="Fight"><br><br>
|
|
{$page['magiclist']}
|
|
<input type="submit" name="run" value="Run"><br><br>
|
|
</form>
|
|
HTML;
|
|
|
|
user()->currentfight += 1;
|
|
} else {
|
|
$page["command"] = <<<HTML
|
|
<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="/" hx-get="/" hx-target="#middle">town</a>, and we hope you fair better next time.
|
|
HTML;
|
|
}
|
|
|
|
user()->save();
|
|
|
|
// Finalize page and display it
|
|
$page = render('fight', ['page' => $page]);
|
|
return \Render\content($page);
|
|
}
|
|
|
|
function victory()
|
|
{
|
|
if (user()->currentmonsterhp != 0) redirect('/fight');
|
|
if (user()->currentfight == 0) redirect('/');
|
|
|
|
$monsterrow = get_monster(user()->currentmonster);
|
|
|
|
$min = (int)(($monsterrow["maxexp"] / 6) * 5);
|
|
$max = (int)$monsterrow["maxexp"];
|
|
$exp = mt_rand(min($min, $max), max($min, $max));
|
|
if ($exp < 1) { $exp = 1; }
|
|
|
|
if (user()->expbonus != 0) { $exp += ceil((user()->expbonus/100)*$exp); }
|
|
|
|
$min = (int)(($monsterrow["maxgold"] / 6) * 5);
|
|
$max = (int)$monsterrow["maxgold"];
|
|
|
|
$gold = mt_rand(min($min, $max), max($min, $max));
|
|
if ($gold < 1) { $gold = 1; }
|
|
|
|
if (user()->goldbonus != 0) { $gold += ceil((user()->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 (user()->gold + $gold < 16777215) { $newgold = user()->gold += $gold; $warngold = ""; } else { $newgold = user()->gold; $gold = 0; $warngold = "You have maxed out your gold."; }
|
|
|
|
$levelrow = db()->query('SELECT * FROM levels WHERE id=? LIMIT 1;', [user()->level + 1])->fetchArray(SQLITE3_ASSOC);
|
|
|
|
if (user()->level < 100) {
|
|
if ($newexp >= $levelrow[user()->charclass."_exp"]) {
|
|
user()->maxhp += $levelrow[user()->charclass."_hp"];
|
|
user()->maxmp += $levelrow[user()->charclass."_mp"];
|
|
user()->maxtp += $levelrow[user()->charclass."_tp"];
|
|
user()->strength += $levelrow[user()->charclass."_strength"];
|
|
user()->dexterity += $levelrow[user()->charclass."_dexterity"];
|
|
user()->attackpower += $levelrow[user()->charclass."_strength"];
|
|
user()->defensepower += $levelrow[user()->charclass."_dexterity"];
|
|
user()->level += 1;
|
|
$newlevel = $levelrow["id"];
|
|
|
|
if ($levelrow[user()->charclass."_spells"] != 0) {
|
|
user()->spells .= ",".$levelrow[user()->charclass."_spells"];
|
|
$spelltext = "You have learned a new spell.<br>";
|
|
} 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=\"/\" hx-get=\"/\" hx-target=\"#middle\">exploring</a>.";
|
|
$title = "Courage and Wit have served thee well!";
|
|
$dropcode = "";
|
|
} else {
|
|
$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) {
|
|
$droprow = db()->query('SELECT * FROM drops WHERE mlevel <= ? ORDER BY RANDOM() LIMIT 1;', [$monsterrow['level']])->fetchArray(SQLITE3_ASSOC);
|
|
$dropcode = "dropcode='".$droprow["id"]."',";
|
|
$page .= "This monster has dropped an item. <a href=\"/drop\" hx-get=\"/drop\" hx-target=\"#middle\">Click here</a> to reveal and equip the item, or you may also move on and continue <a href=\"/\" hx-get=\"/\" hx-target=\"#middle\">exploring</a>.";
|
|
} else {
|
|
$dropcode = "";
|
|
$page .= 'You can now continue <a href="/" hx-get="/" hx-target="#middle">exploring</a>.';
|
|
}
|
|
|
|
$title = "Victory!";
|
|
}
|
|
}
|
|
|
|
user()->currentaction = 'Exploring';
|
|
user()->currentfight = 0;
|
|
user()->currentuberdamage = 0;
|
|
user()->currentuberdefense = 0;
|
|
user()->currentmonstersleep = 0;
|
|
user()->currentmonsterimmune = 0;
|
|
user()->save();
|
|
|
|
page_title($title);
|
|
return \Render\content($page);
|
|
}
|
|
|
|
function drop()
|
|
{
|
|
if (user()->dropcode == 0) redirect('/');
|
|
|
|
$droprow = get_drop(user()->dropcode);
|
|
|
|
if (isset($_POST["submit"])) {
|
|
$slot = $_POST["slot"];
|
|
|
|
if ($slot == 0) {
|
|
$page = 'Please go back and select an inventory slot to continue.';
|
|
return \Render\content($page);
|
|
}
|
|
|
|
$slotstr = 'slot'.$slot.'id';
|
|
if (user()->$slotstr != 0) {
|
|
$slotrow = get_drop(user()->$slotstr);
|
|
|
|
$old1 = explode(",",$slotrow["attribute1"]);
|
|
if ($slotrow["attribute2"] != "X") { $old2 = explode(",",$slotrow["attribute2"]); } else { $old2 = array(0=>"maxhp",1=>0); }
|
|
$new1 = explode(",",$droprow["attribute1"]);
|
|
if ($droprow["attribute2"] != "X") { $new2 = explode(",",$droprow["attribute2"]); } else { $new2 = array(0=>"maxhp",1=>0); }
|
|
|
|
user()->$old1[0] -= $old1[1];
|
|
user()->$old2[0] -= $old2[1];
|
|
if ($old1[0] == "strength") { user()->attackpower -= $old1[1]; }
|
|
if ($old1[0] == "dexterity") { user()->defensepower -= $old1[1]; }
|
|
if ($old2[0] == "strength") { user()->attackpower -= $old2[1]; }
|
|
if ($old2[0] == "dexterity") { user()->defensepower -= $old2[1]; }
|
|
|
|
user()->$new1[0] += $new1[1];
|
|
user()->$new2[0] += $new2[1];
|
|
if ($new1[0] == "strength") { user()->attackpower += $new1[1]; }
|
|
if ($new1[0] == "dexterity") { user()->defensepower += $new1[1]; }
|
|
if ($new2[0] == "strength") { user()->attackpower += $new2[1]; }
|
|
if ($new2[0] == "dexterity") { user()->defensepower += $new2[1]; }
|
|
|
|
if (user()->currenthp > user()->maxhp) { user()->currenthp = user()->maxhp; }
|
|
if (user()->currentmp > user()->maxmp) { user()->currentmp = user()->maxmp; }
|
|
if (user()->currenttp > user()->maxtp) { user()->currenttp = user()->maxtp; }
|
|
|
|
$slot_s = 'slot'.$_POST["slot"];
|
|
$slot_name = "{$slot_s}name";
|
|
$slot_id = "{$slot_s}id";
|
|
|
|
user()->$slot_name = $droprow['name'];
|
|
user()->$slot_id = $droprow['id'];
|
|
} else {
|
|
$new1 = explode(",",$droprow["attribute1"]);
|
|
if ($droprow["attribute2"] != "X") { $new2 = explode(",",$droprow["attribute2"]); } else { $new2 = array(0=>"maxhp",1=>0); }
|
|
|
|
user()->$new1[0] += $new1[1];
|
|
user()->$new2[0] += $new2[1];
|
|
if ($new1[0] == "strength") { user()->attackpower += $new1[1]; }
|
|
if ($new1[0] == "dexterity") { user()->defensepower += $new1[1]; }
|
|
if ($new2[0] == "strength") { user()->attackpower += $new2[1]; }
|
|
if ($new2[0] == "dexterity") { user()->defensepower += $new2[1]; }
|
|
|
|
$slot_s = 'slot'.$_POST["slot"];
|
|
$slot_name = "{$slot_s}name";
|
|
$slot_id = "{$slot_s}id";
|
|
|
|
user()->$slot_name = $droprow['name'];
|
|
user()->$slot_id = $droprow['id'];
|
|
}
|
|
|
|
user()->save();
|
|
$page = 'The item has been equipped. You can now continue <a href="/" hx-get="/" hx-target="#middle">exploring</a>.';
|
|
return \Render\content($page);
|
|
}
|
|
|
|
$attributearray = array("maxhp"=>"Max HP",
|
|
"maxmp"=>"Max MP",
|
|
"maxtp"=>"Max TP",
|
|
"defensepower"=>"Defense Power",
|
|
"attackpower"=>"Attack Power",
|
|
"strength"=>"Strength",
|
|
"dexterity"=>"Dexterity",
|
|
"expbonus"=>"Experience Bonus",
|
|
"goldbonus"=>"Gold Bonus");
|
|
|
|
$page = "The monster dropped the following item: <b>".$droprow["name"]."</b><br><br>";
|
|
$page .= "This item has the following attribute(s):<br>";
|
|
|
|
$attribute1 = explode(",",$droprow["attribute1"]);
|
|
$page .= $attributearray[$attribute1[0]];
|
|
if ($attribute1[1] > 0) { $page .= " +" . $attribute1[1] . "<br>"; } else { $page .= $attribute1[1] . "<br>"; }
|
|
|
|
if ($droprow["attribute2"] != "X") {
|
|
$attribute2 = explode(",",$droprow["attribute2"]);
|
|
$page .= $attributearray[$attribute2[0]];
|
|
if ($attribute2[1] > 0) { $page .= " +" . $attribute2[1] . "<br>"; } else { $page .= $attribute2[1] . "<br>"; }
|
|
}
|
|
|
|
$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 .= "You may also choose to just continue <a href=\"/\" hx-get=\"/\" hx-target=\"#middle\">exploring</a> and give up this item.";
|
|
|
|
return \Render\content($page);
|
|
}
|
|
|
|
|
|
function dead()
|
|
{
|
|
$page = <<<HTML
|
|
<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="/" hx-get="/" hx-target="#middle">town</a>, and we hope you fair better next time.
|
|
HTML;
|
|
return \Render\content($page);
|
|
}
|
|
|
|
function handleMonsterTurn(&$userrow, $monsterrow)
|
|
{
|
|
$pagearray = "";
|
|
if (user()->currentmonstersleep != 0) {
|
|
$chancetowake = rand(1,15);
|
|
if ($chancetowake > user()->currentmonstersleep) {
|
|
user()->currentmonstersleep = 0;
|
|
$pagearray .= "The monster has woken up.<br>";
|
|
} else {
|
|
$pagearray .= "The monster is still asleep.<br>";
|
|
}
|
|
}
|
|
|
|
if (user()->currentmonstersleep == 0) {
|
|
$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);
|
|
$tododge = rand(1, 150);
|
|
|
|
if ($tododge <= sqrt(user()->dexterity)) {
|
|
$tohit = 0;
|
|
$pagearray .= "You dodge the monster's attack. No damage has been scored.<br>";
|
|
$persondamage = 0;
|
|
} else {
|
|
$persondamage = max(1, $tohit - $toblock);
|
|
if (user()->currentuberdefense != 0) {
|
|
$persondamage -= (int)ceil($persondamage * (user()->currentuberdefense/100));
|
|
}
|
|
$persondamage = max(1, $persondamage);
|
|
}
|
|
|
|
$pagearray .= "The monster attacks you for $persondamage damage.<br><br>";
|
|
user()->currenthp -= $persondamage;
|
|
|
|
if (user()->currenthp <= 0) {
|
|
$newgold = (int)ceil(user()->gold/2);
|
|
$newhp = (int)ceil(user()->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=?;", [
|
|
$newhp, $newgold, $userrow['id']
|
|
]);
|
|
dead();
|
|
}
|
|
}
|
|
return $pagearray;
|
|
}
|
|
|
|
function handleSpellCast(&$userrow, $newspellrow)
|
|
{
|
|
$pagearray = "";
|
|
switch ($newspellrow["type"]) {
|
|
case 1: // Heal spell
|
|
$newhp = min(user()->currenthp + $newspellrow["attribute"], user()->maxhp);
|
|
user()->currenthp = $newhp;
|
|
user()->currentmp -= $newspellrow["mp"];
|
|
$pagearray = "You have cast the {$newspellrow["name"]} spell, and gained {$newspellrow["attribute"]} Hit Points.<br><br>";
|
|
break;
|
|
case 2: // Hurt spell
|
|
if (user()->currentmonsterimmune == 0) {
|
|
$monsterdamage = mt_rand((int)(($newspellrow["attribute"]/6)*5), $newspellrow["attribute"]);
|
|
user()->currentmonsterhp -= $monsterdamage;
|
|
$pagearray = "You have cast the {$newspellrow["name"]} spell for $monsterdamage damage.<br><br>";
|
|
} else {
|
|
$pagearray = "You have cast the {$newspellrow["name"]} spell, but the monster is immune to it.<br><br>";
|
|
}
|
|
user()->currentmp -= $newspellrow["mp"];
|
|
break;
|
|
case 3: // Sleep spell
|
|
if (user()->currentmonsterimmune != 2) {
|
|
user()->currentmonstersleep = $newspellrow["attribute"];
|
|
$pagearray = "You have cast the {$newspellrow["name"]} spell. The monster is asleep.<br><br>";
|
|
} else {
|
|
$pagearray = "You have cast the {$newspellrow["name"]} spell, but the monster is immune to it.<br><br>";
|
|
}
|
|
user()->currentmp -= $newspellrow["mp"];
|
|
break;
|
|
case 4: // +Damage spell
|
|
user()->currentuberdamage = $newspellrow["attribute"];
|
|
user()->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>";
|
|
break;
|
|
case 5: // +Defense spell
|
|
user()->currentuberdefense = $newspellrow["attribute"];
|
|
user()->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>";
|
|
break;
|
|
}
|
|
return $pagearray;
|
|
}
|