Reorganize, update install to step two

This commit is contained in:
Sky Johnson 2024-07-01 20:53:23 -05:00
parent 6bad6a1816
commit 7659cbed52
68 changed files with 1031 additions and 70 deletions

View File

@ -1,11 +0,0 @@
<?php // config.php :: Low-level app/database variables.
$dbsettings = Array(
"server" => "localhost", // MySQL server name. (Default: localhost)
"user" => "", // MySQL username.
"pass" => "", // MySQL password.
"name" => "", // MySQL database name.
"prefix" => "dk", // Prefix for table names. (Default: dk)
"secretword" => ""); // Secret word used when hashing information for cookies.
?>

21
public/css/dragon.css Normal file
View File

@ -0,0 +1,21 @@
* {
box-sizing: border-box;
}
body {
background-image: url(/img/bg/bg.webp);
background-repeat: repeat;
}
#container {
max-width: 996px;
margin: 0 auto;
}
.mb-1 {
margin-bottom: 1rem;
}
.mb-2 {
margin-bottom: 2rem;
}

View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

BIN
public/img/bg/bg.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View File

Before

Width:  |  Height:  |  Size: 527 B

After

Width:  |  Height:  |  Size: 527 B

View File

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 575 B

View File

Before

Width:  |  Height:  |  Size: 561 B

After

Width:  |  Height:  |  Size: 561 B

View File

Before

Width:  |  Height:  |  Size: 402 B

After

Width:  |  Height:  |  Size: 402 B

View File

Before

Width:  |  Height:  |  Size: 551 B

After

Width:  |  Height:  |  Size: 551 B

View File

Before

Width:  |  Height:  |  Size: 486 B

After

Width:  |  Height:  |  Size: 486 B

View File

Before

Width:  |  Height:  |  Size: 474 B

After

Width:  |  Height:  |  Size: 474 B

View File

Before

Width:  |  Height:  |  Size: 500 B

After

Width:  |  Height:  |  Size: 500 B

View File

Before

Width:  |  Height:  |  Size: 523 B

After

Width:  |  Height:  |  Size: 523 B

View File

Before

Width:  |  Height:  |  Size: 565 B

After

Width:  |  Height:  |  Size: 565 B

View File

Before

Width:  |  Height:  |  Size: 469 B

After

Width:  |  Height:  |  Size: 469 B

View File

Before

Width:  |  Height:  |  Size: 469 B

After

Width:  |  Height:  |  Size: 469 B

View File

Before

Width:  |  Height:  |  Size: 461 B

After

Width:  |  Height:  |  Size: 461 B

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 147 B

After

Width:  |  Height:  |  Size: 147 B

View File

Before

Width:  |  Height:  |  Size: 121 B

After

Width:  |  Height:  |  Size: 121 B

View File

Before

Width:  |  Height:  |  Size: 112 B

After

Width:  |  Height:  |  Size: 112 B

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1005 B

After

Width:  |  Height:  |  Size: 1005 B

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

5
public/index.php Normal file
View File

@ -0,0 +1,5 @@
<?php // index.php :: Primary program script, evil alien overlord, you decide.
require_once '../server/bootstrap.php';
if (!installed()) redirect('/install');

489
public/install/index.php Normal file
View File

@ -0,0 +1,489 @@
<?php // install.php :: creates/populates database tables on a new installation.
const SERVER = '../../server';
require_once SERVER.'/bootstrap.php';
if (installed()) redirect('/');
$db = new Database(DB);
const STEPS = ['first', 'second', 'third', 'fourth', 'fifth'];
$step = isset($_GET['step']) && in_array($_GET['step'], STEPS) ? $_GET['step'] : 'first';
// Introduction; offer the user two options for installation;
// Complete: all default data
// Partial: no default data
if ($step == 'first') {
echo render('install/layout', ['title' => 'Intro', 'step' => 'first']);
exit;
}
// Database setup; create tables and default data (if requested)
if ($step == 'second') {
$istart = microtime(true); // time the database setup
if (!isset($_POST['mode'])) redirect('/install/'); // dont run install if a button wasnt clicked
$complete = $_POST['mode'] == 'complete'; // complete or partial setup
// Create Control table
$db->table('control')->create([
'id INTEGER PRIMARY KEY',
"game_name TEXT DEFAULT 'Dragon Knight'",
'game_size INTEGER DEFAULT 250',
'game_open INTEGER DEFAULT 1',
"admin_email TEXT DEFAULT ''",
'forum_type INTEGER DEFAULT 1',
"forum_addr TEXT DEFAULT ''",
"class_1_name TEXT DEFAULT 'Mage'",
"class_2_name TEXT DEFAULT 'Warrior'",
"class_3_name TEXT DEFAULT 'Paladin'",
'verify_email INTEGER DEFAULT 1',
'show_news INTEGER DEFAULT 1',
'show_online INTEGER DEFAULT 1',
'show_babble INTEGER DEFAULT 1'
]);
// Insert default control row
$db->insertDefaultValues();
// Create Babble table
$db->table('babble')->create([
'id INTEGER PRIMARY KEY',
'posted DATETIME DEFAULT CURRENT_TIMESTAMP',
'author INTEGER DEFAULT 1',
'babble TEXT NOT NULL'
]);
// Create Drops table
$db->table('drops')->create([
'id INTEGER PRIMARY KEY',
'name TEXT NOT NULL',
'level INTEGER DEFAULT 1',
'type INTEGER DEFAULT 1',
"attr1 TEXT DEFAULT ''",
"attr2 TEXT DEFAULT ''"
]);
// Add default drops if complete install
if ($complete) {
$db->insert([
['name' => 'Life Pebble', 'level' => 1, 'type' => 1, 'attr1' => 'hp,10', 'attr2' => '' ],
['name' => 'Life Stone', 'level' => 10, 'type' => 1, 'attr1' => 'hp,25', 'attr2' => '' ],
['name' => 'Life Rock', 'level' => 25, 'type' => 1, 'attr1' => 'hp,50', 'attr2' => '' ],
['name' => 'Life Ore', 'level' => 50, 'type' => 1, 'attr1' => 'hp,100', 'attr2' => '' ],
['name' => 'Life Gem', 'level' => 75, 'type' => 1, 'attr1' => 'hp,150', 'attr2' => '' ],
['name' => 'Magic Pebble', 'level' => 1, 'type' => 1, 'attr1' => 'mp,10', 'attr2' => '' ],
['name' => 'Magic Stone', 'level' => 10, 'type' => 1, 'attr1' => 'mp,25', 'attr2' => '' ],
['name' => 'Magic Rock', 'level' => 25, 'type' => 1, 'attr1' => 'mp,50', 'attr2' => '' ],
['name' => 'Magic Ore', 'level' => 50, 'type' => 1, 'attr1' => 'mp,100', 'attr2' => '' ],
['name' => 'Magic Gem', 'level' => 75, 'type' => 1, 'attr1' => 'mp,150', 'attr2' => '' ],
['name' => "Dragon's Scale", 'level' => 10, 'type' => 1, 'attr1' => 'def,25', 'attr2' => '' ],
['name' => "Dragon's Plate", 'level' => 30, 'type' => 1, 'attr1' => 'def,50', 'attr2' => '' ],
['name' => "Dragon's Claw", 'level' => 10, 'type' => 1, 'attr1' => 'atk,25', 'attr2' => '' ],
['name' => "Dragon's Fang", 'level' => 30, 'type' => 1, 'attr1' => 'atk,50', 'attr2' => '' ],
['name' => "Dragon's Tear", 'level' => 35, 'type' => 1, 'attr1' => 'str,75', 'attr2' => '' ],
['name' => "Dragon's Wing", 'level' => 35, 'type' => 1, 'attr1' => 'dex,75', 'attr2' => '' ],
['name' => "Demon's Sin", 'level' => 35, 'type' => 1, 'attr1' => 'hp,-50', 'attr2' => 'str,50' ],
['name' => "Demon's Fall", 'level' => 35, 'type' => 1, 'attr1' => 'mp,-50', 'attr2' => 'str,50' ],
['name' => "Demon's Lie", 'level' => 45, 'type' => 1, 'attr1' => 'hp,-100', 'attr2' => 'str,100' ],
['name' => "Demon's Hate", 'level' => 45, 'type' => 1, 'attr1' => 'mp,-100', 'attr2' => 'str,100' ],
['name' => "Angel's Joy", 'level' => 25, 'type' => 1, 'attr1' => 'hp,25', 'attr2' => 'str,25' ],
['name' => "Angel's Rise", 'level' => 30, 'type' => 1, 'attr1' => 'hp,50', 'attr2' => 'str,50' ],
['name' => "Angel's Truth", 'level' => 35, 'type' => 1, 'attr1' => 'hp,75', 'attr2' => 'str,75' ],
['name' => "Angel's Grace", 'level' => 40, 'type' => 1, 'attr1' => 'hp,100', 'attr2' => 'str,100' ],
['name' => "Seraph's Strength", 'level' => 25, 'type' => 1, 'attr1' => 'mp,25', 'attr2' => 'dex,25' ],
['name' => "Seraph's Power", 'level' => 30, 'type' => 1, 'attr1' => 'mp,50', 'attr2' => 'dex,50' ],
['name' => "Seraph's Justice", 'level' => 35, 'type' => 1, 'attr1' => 'mp,75', 'attr2' => 'dex,75' ],
['name' => "Seraph's Judgement", 'level' => 40, 'type' => 1, 'attr1' => 'mp,100', 'attr2' => 'dex,100' ],
['name' => 'Ruby', 'level' => 50, 'type' => 1, 'attr1' => 'hp,150', 'attr2' => '' ],
['name' => 'Sapphire', 'level' => 50, 'type' => 1, 'attr1' => 'mp,150', 'attr2' => '' ],
['name' => 'Emerald', 'level' => 50, 'type' => 1, 'attr1' => 'str,150', 'attr2' => '' ],
['name' => 'Amethyst', 'level' => 50, 'type' => 1, 'attr1' => 'dex,150', 'attr2' => '' ],
['name' => 'Topaz', 'level' => 50, 'type' => 1, 'attr1' => 'atk,150', 'attr2' => '' ],
['name' => 'Diamond', 'level' => 50, 'type' => 1, 'attr1' => 'def,150', 'attr2' => '' ],
['name' => "Ocean Blessing", 'level' => 77, 'type' => 1, 'attr1' => 'str,7007', 'attr2' => 'dex,7007'],
['name' => 'Memory Tonic', 'level' => 5, 'type' => 1, 'attr1' => 'exp,10', 'attr2' => '' ],
['name' => 'Memory Potion', 'level' => 30, 'type' => 1, 'attr1' => 'exp,20', 'attr2' => '' ],
['name' => 'Memory Elixir', 'level' => 50, 'type' => 1, 'attr1' => 'exp,30', 'attr2' => '' ],
['name' => 'Gold Tonic', 'level' => 5, 'type' => 1, 'attr1' => 'gold,10', 'attr2' => '' ],
['name' => 'Gold Potion', 'level' => 30, 'type' => 1, 'attr1' => 'gold,20', 'attr2' => '' ],
['name' => 'Gold Elixir', 'level' => 50, 'type' => 1, 'attr1' => 'gold,30', 'attr2' => '' ],
]);
}
// Create Forum table
$db->table('forum')->create([
'id INTEGER PRIMARY KEY',
'posted DATETIME DEFAULT CURRENT_TIMESTAMP',
'new_post DATETIME DEFAULT CURRENT_TIMESTAMP',
'author INTEGER DEFAULT 1',
"subject TEXT DEFAULT ''",
"message TEXT DEFAULT ''",
'locked INTEGER DEFAULT 0',
'sticky INTEGER DEFAULT 0',
'parent INTEGER DEFAULT 0'
]);
// Create Items table
$db->table('items')->create([
'id INTEGER PRIMARY KEY',
'type INTEGER DEFAULT 1',
'name TEXT NOT NULL',
'cost INTEGER DEFAULT 0',
"attr1 TEXT DEFAULT ''",
"attr2 TEXT DEFAULT ''",
"icon TEXT DEFAULT ''"
]);
// Create default items, if complete install
if ($complete) {
$db->insert([
// Type 1 - weapons
['type' => 1, 'name' => 'Stick', 'cost' => 10, 'attr1' => 'atk,2', 'attr2' => '', 'icon' => 'stick.png' ],
['type' => 1, 'name' => 'Branch', 'cost' => 30, 'attr1' => 'atk,4', 'attr2' => '', 'icon' => 'branch.png' ],
['type' => 1, 'name' => 'Club', 'cost' => 40, 'attr1' => 'atk,6', 'attr2' => '', 'icon' => 'club.png' ],
['type' => 1, 'name' => 'Dagger', 'cost' => 80, 'attr1' => 'atk,8', 'attr2' => '', 'icon' => 'dagger.png' ],
['type' => 1, 'name' => 'Hatchet', 'cost' => 120, 'attr1' => 'atk,12', 'attr2' => '', 'icon' => 'hatchet.png' ],
['type' => 1, 'name' => 'Axe', 'cost' => 200, 'attr1' => 'atk,18', 'attr2' => '', 'icon' => 'axe.png' ],
['type' => 1, 'name' => 'Spear', 'cost' => 300, 'attr1' => 'atk,25', 'attr2' => '', 'icon' => 'spear.png' ],
['type' => 1, 'name' => 'Poleaxe', 'cost' => 500, 'attr1' => 'atk,35', 'attr2' => '', 'icon' => 'poleaxe.png' ],
['type' => 1, 'name' => 'Warhammer', 'cost' => 800, 'attr1' => 'atk,50', 'attr2' => '', 'icon' => 'warhammer.png' ],
['type' => 1, 'name' => 'Longsword', 'cost' => 1200, 'attr1' => 'atk,65', 'attr2' => '', 'icon' => 'longsword.png' ],
['type' => 1, 'name' => 'Claymore', 'cost' => 1800, 'attr1' => 'atk,85', 'attr2' => '', 'icon' => 'claymore.png' ],
['type' => 1, 'name' => 'Demon Axe', 'cost' => 2800, 'attr1' => 'atk,125', 'attr2' => 'exp,-5', 'icon' => 'demonaxe.png' ],
['type' => 1, 'name' => 'Dark Sword', 'cost' => 4500, 'attr1' => 'atk,225', 'attr2' => 'exp,-10', 'icon' => 'darksword.png' ],
['type' => 1, 'name' => 'Magic Axe', 'cost' => 2800, 'attr1' => 'atk,95', 'attr2' => 'exp,5', 'icon' => 'magicaxe.png' ],
['type' => 1, 'name' => 'Bright Sword', 'cost' => 4500, 'attr1' => 'atk,185', 'attr2' => 'exp,10', 'icon' => 'brightsword.png'],
['type' => 1, 'name' => 'Dragonbane', 'cost' => 10000, 'attr1' => 'atk,300', 'attr2' => 'str,50', 'icon' => 'dragonbane.png' ],
// Type 2 - armors
['type' => 2, 'name' => 'Underwear', 'cost' => 25, 'attr1' => 'def,2', 'attr2' => 'gold,10', 'icon' => 'underwear.png' ],
['type' => 2, 'name' => 'Clothes', 'cost' => 50, 'attr1' => 'def,5', 'attr2' => '', 'icon' => 'clothes.png' ],
['type' => 2, 'name' => 'Leather', 'cost' => 75, 'attr1' => 'def,10', 'attr2' => '', 'icon' => 'leather.png' ],
['type' => 2, 'name' => 'Hard Leather', 'cost' => 150, 'attr1' => 'def,25', 'attr2' => '', 'icon' => 'hardleather.png' ],
['type' => 2, 'name' => 'Chainmail', 'cost' => 300, 'attr1' => 'def,35', 'attr2' => '', 'icon' => 'chainmail.png' ],
['type' => 2, 'name' => 'Scale Armor', 'cost' => 900, 'attr1' => 'def,50', 'attr2' => '', 'icon' => 'scalearmor.png' ],
['type' => 2, 'name' => 'Platemail', 'cost' => 1800, 'attr1' => 'def,100', 'attr2' => '', 'icon' => 'platemail.png' ],
['type' => 2, 'name' => 'Magic Plate', 'cost' => 3000, 'attr1' => 'def,125', 'attr2' => 'mp,50', 'icon' => 'magicplate.png' ],
['type' => 2, 'name' => 'Darkmail', 'cost' => 5000, 'attr1' => 'def,200', 'attr2' => 'exp,-10', 'icon' => 'darkmail.png' ],
['type' => 2, 'name' => 'Dragon Plate', 'cost' => 10000, 'attr1' => 'def,165', 'attr2' => 'exp,10', 'icon' => 'dragonplate.png' ],
['type' => 2, 'name' => 'Destiny Raiment', 'cost' => 50000, 'attr1' => 'def,200', 'attr2' => 'dex,50', 'icon' => 'destinyraiment.png'],
// Type 3 - shields
['type' => 3, 'name' => 'Reed Shield', 'cost' => 50, 'attr1' => 'def,5', 'attr2' => '', 'icon' => 'reedshield.png' ],
['type' => 3, 'name' => 'Buckler', 'cost' => 100, 'attr1' => 'def,10', 'attr2' => '', 'icon' => 'nuckler.png' ],
['type' => 3, 'name' => 'Round Shield', 'cost' => 500, 'attr1' => 'def,25', 'attr2' => '', 'icon' => 'roundshield.png' ],
['type' => 3, 'name' => 'Tower Shield', 'cost' => 2500, 'attr1' => 'def,50', 'attr2' => '', 'icon' => 'towershield.png' ],
['type' => 3, 'name' => 'Silver Shield', 'cost' => 10000, 'attr1' => 'def,100', 'attr2' => '', 'icon' => 'silvershield.png'],
['type' => 3, 'name' => 'Dragon Shield', 'cost' => 25000, 'attr1' => 'def,125', 'attr2' => 'mp,100', 'icon' => 'dragonshield.png'],
['type' => 3, 'name' => 'Aegis', 'cost' => 50000, 'attr1' => 'def,225', 'attr2' => 'exp,10', 'icon' => 'aegis.png' ]
]);
}
// Create Monsters table
$db->table('monsters')->create([
'id INTEGER PRIMARY KEY',
'name TEXT NOT NULL',
'level INTEGER DEFAULT 1',
'hp INTEGER DEFAULT 1',
'atk INTEGER DEFAULT 1',
'def INTEGER DEFAULT 1',
'exp INTEGER DEFAULT 1',
'gold INTEGER DEFAULT 1',
'immune INTEGER DEFAULT 0',
"image TEXT DEFAULT ''"
]);
// Fill monsters table if complete install
if ($complete) {
$db->insert([
['name' => 'Blue Slime', 'level' => 1, 'hp' => 4, 'atk' => 3, 'def' => 1, 'exp' => 1, 'gold' => 1, 'immune' => 0],
['name' => 'Red Slime', 'level' => 1, 'hp' => 6, 'atk' => 5, 'def' => 1, 'exp' => 2, 'gold' => 1, 'immune' => 0],
['name' => 'Critter', 'level' => 1, 'hp' => 6, 'atk' => 5, 'def' => 2, 'exp' => 4, 'gold' => 2, 'immune' => 0],
['name' => 'Creature', 'level' => 2, 'hp' => 10, 'atk' => 8, 'def' => 2, 'exp' => 4, 'gold' => 2, 'immune' => 0],
['name' => 'Shadow', 'level' => 2, 'hp' => 10, 'atk' => 9, 'def' => 3, 'exp' => 6, 'gold' => 2, 'immune' => 1],
['name' => 'Drake', 'level' => 2, 'hp' => 11, 'atk' => 10, 'def' => 3, 'exp' => 8, 'gold' => 3, 'immune' => 0],
['name' => 'Shade', 'level' => 3, 'hp' => 12, 'atk' => 10, 'def' => 3, 'exp' => 10, 'gold' => 3, 'immune' => 1],
['name' => 'Drakelor', 'level' => 3, 'hp' => 14, 'atk' => 12, 'def' => 4, 'exp' => 10, 'gold' => 3, 'immune' => 0],
['name' => 'Silver Slime', 'level' => 30, 'hp' => 15, 'atk' => 100, 'def' => 200, 'exp' => 15, 'gold' => 1000, 'immune' => 2],
['name' => 'Scamp', 'level' => 4, 'hp' => 16, 'atk' => 13, 'def' => 5, 'exp' => 15, 'gold' => 5, 'immune' => 0],
['name' => 'Raven', 'level' => 4, 'hp' => 16, 'atk' => 13, 'def' => 5, 'exp' => 18, 'gold' => 6, 'immune' => 0],
['name' => 'Scorpion', 'level' => 5, 'hp' => 18, 'atk' => 14, 'def' => 6, 'exp' => 20, 'gold' => 7, 'immune' => 0],
['name' => 'Illusion', 'level' => 5, 'hp' => 20, 'atk' => 15, 'def' => 6, 'exp' => 20, 'gold' => 7, 'immune' => 1],
['name' => 'Nightshade', 'level' => 6, 'hp' => 22, 'atk' => 16, 'def' => 6, 'exp' => 24, 'gold' => 8, 'immune' => 0],
['name' => 'Drakemal', 'level' => 6, 'hp' => 22, 'atk' => 18, 'def' => 7, 'exp' => 24, 'gold' => 8, 'immune' => 0],
['name' => 'Shadow Raven', 'level' => 6, 'hp' => 24, 'atk' => 18, 'def' => 7, 'exp' => 26, 'gold' => 9, 'immune' => 1],
['name' => 'Ghost', 'level' => 6, 'hp' => 24, 'atk' => 20, 'def' => 8, 'exp' => 28, 'gold' => 9, 'immune' => 0],
['name' => 'Frost Raven', 'level' => 7, 'hp' => 26, 'atk' => 20, 'def' => 8, 'exp' => 30, 'gold' => 10, 'immune' => 0],
['name' => 'Rogue Scorpion', 'level' => 7, 'hp' => 28, 'atk' => 22, 'def' => 9, 'exp' => 32, 'gold' => 11, 'immune' => 0],
['name' => 'Ghoul', 'level' => 7, 'hp' => 29, 'atk' => 24, 'def' => 9, 'exp' => 34, 'gold' => 11, 'immune' => 0],
['name' => 'Magician', 'level' => 8, 'hp' => 30, 'atk' => 24, 'def' => 10, 'exp' => 36, 'gold' => 12, 'immune' => 0],
['name' => 'Rogue', 'level' => 8, 'hp' => 30, 'atk' => 25, 'def' => 12, 'exp' => 40, 'gold' => 13, 'immune' => 0],
['name' => 'Drakefin', 'level' => 8, 'hp' => 32, 'atk' => 26, 'def' => 12, 'exp' => 40, 'gold' => 13, 'immune' => 0],
['name' => 'Shimmer', 'level' => 8, 'hp' => 32, 'atk' => 26, 'def' => 14, 'exp' => 45, 'gold' => 15, 'immune' => 1],
['name' => 'Fire Raven', 'level' => 9, 'hp' => 34, 'atk' => 28, 'def' => 14, 'exp' => 45, 'gold' => 15, 'immune' => 0],
['name' => 'Dybbuk', 'level' => 9, 'hp' => 34, 'atk' => 28, 'def' => 14, 'exp' => 50, 'gold' => 17, 'immune' => 0],
['name' => 'Knave', 'level' => 9, 'hp' => 36, 'atk' => 30, 'def' => 15, 'exp' => 52, 'gold' => 17, 'immune' => 0],
['name' => 'Goblin', 'level' => 10, 'hp' => 36, 'atk' => 30, 'def' => 15, 'exp' => 54, 'gold' => 18, 'immune' => 0],
['name' => 'Skeleton', 'level' => 10, 'hp' => 38, 'atk' => 30, 'def' => 18, 'exp' => 58, 'gold' => 19, 'immune' => 0],
['name' => 'Dark Slime', 'level' => 10, 'hp' => 38, 'atk' => 32, 'def' => 18, 'exp' => 62, 'gold' => 21, 'immune' => 0],
['name' => 'Silver Scorpion', 'level' => 40, 'hp' => 30, 'atk' => 160, 'def' => 350, 'exp' => 63, 'gold' => 2000, 'immune' => 2],
['name' => 'Mirage', 'level' => 11, 'hp' => 40, 'atk' => 32, 'def' => 20, 'exp' => 64, 'gold' => 21, 'immune' => 1],
['name' => 'Sorceror', 'level' => 11, 'hp' => 41, 'atk' => 33, 'def' => 22, 'exp' => 68, 'gold' => 23, 'immune' => 0],
['name' => 'Imp', 'level' => 12, 'hp' => 42, 'atk' => 34, 'def' => 22, 'exp' => 70, 'gold' => 23, 'immune' => 0],
['name' => 'Nymph', 'level' => 12, 'hp' => 43, 'atk' => 35, 'def' => 22, 'exp' => 70, 'gold' => 23, 'immune' => 0],
['name' => 'Scoundrel', 'level' => 12, 'hp' => 43, 'atk' => 35, 'def' => 22, 'exp' => 75, 'gold' => 25, 'immune' => 0],
['name' => 'Megaskeleton', 'level' => 13, 'hp' => 44, 'atk' => 36, 'def' => 24, 'exp' => 78, 'gold' => 26, 'immune' => 0],
['name' => 'Grey Wolf', 'level' => 13, 'hp' => 44, 'atk' => 36, 'def' => 24, 'exp' => 82, 'gold' => 27, 'immune' => 0],
['name' => 'Phantom', 'level' => 14, 'hp' => 46, 'atk' => 38, 'def' => 24, 'exp' => 85, 'gold' => 28, 'immune' => 1],
['name' => 'Specter', 'level' => 14, 'hp' => 46, 'atk' => 38, 'def' => 24, 'exp' => 90, 'gold' => 30, 'immune' => 0],
['name' => 'Dark Scorpion', 'level' => 15, 'hp' => 48, 'atk' => 40, 'def' => 26, 'exp' => 95, 'gold' => 32, 'immune' => 1],
['name' => 'Warlock', 'level' => 15, 'hp' => 48, 'atk' => 40, 'def' => 26, 'exp' => 100, 'gold' => 33, 'immune' => 1],
['name' => 'Orc', 'level' => 15, 'hp' => 49, 'atk' => 42, 'def' => 28, 'exp' => 104, 'gold' => 35, 'immune' => 0],
['name' => 'Sylph', 'level' => 15, 'hp' => 49, 'atk' => 42, 'def' => 28, 'exp' => 106, 'gold' => 35, 'immune' => 0],
['name' => 'Wraith', 'level' => 16, 'hp' => 50, 'atk' => 45, 'def' => 30, 'exp' => 108, 'gold' => 36, 'immune' => 0],
['name' => 'Hellion', 'level' => 16, 'hp' => 50, 'atk' => 45, 'def' => 30, 'exp' => 110, 'gold' => 37, 'immune' => 0],
['name' => 'Bandit', 'level' => 16, 'hp' => 52, 'atk' => 45, 'def' => 30, 'exp' => 114, 'gold' => 38, 'immune' => 0],
['name' => 'Ultraskeleton', 'level' => 16, 'hp' => 52, 'atk' => 46, 'def' => 32, 'exp' => 116, 'gold' => 39, 'immune' => 0],
['name' => 'Dark Wolf', 'level' => 17, 'hp' => 54, 'atk' => 47, 'def' => 36, 'exp' => 120, 'gold' => 40, 'immune' => 1],
['name' => 'Troll', 'level' => 17, 'hp' => 56, 'atk' => 48, 'def' => 36, 'exp' => 120, 'gold' => 40, 'immune' => 0],
['name' => 'Werewolf', 'level' => 17, 'hp' => 56, 'atk' => 48, 'def' => 38, 'exp' => 124, 'gold' => 41, 'immune' => 0],
['name' => 'Hellcat', 'level' => 18, 'hp' => 58, 'atk' => 50, 'def' => 38, 'exp' => 128, 'gold' => 43, 'immune' => 0],
['name' => 'Spirit', 'level' => 18, 'hp' => 58, 'atk' => 50, 'def' => 38, 'exp' => 132, 'gold' => 44, 'immune' => 0],
['name' => 'Nisse', 'level' => 19, 'hp' => 60, 'atk' => 52, 'def' => 40, 'exp' => 132, 'gold' => 44, 'immune' => 0],
['name' => 'Dawk', 'level' => 19, 'hp' => 60, 'atk' => 54, 'def' => 40, 'exp' => 136, 'gold' => 45, 'immune' => 0],
['name' => 'Figment', 'level' => 19, 'hp' => 64, 'atk' => 55, 'def' => 42, 'exp' => 140, 'gold' => 47, 'immune' => 1],
['name' => 'Hellhound', 'level' => 20, 'hp' => 66, 'atk' => 56, 'def' => 44, 'exp' => 140, 'gold' => 47, 'immune' => 0],
['name' => 'Wizard', 'level' => 20, 'hp' => 66, 'atk' => 56, 'def' => 44, 'exp' => 144, 'gold' => 48, 'immune' => 0],
['name' => 'Uruk', 'level' => 20, 'hp' => 68, 'atk' => 58, 'def' => 44, 'exp' => 146, 'gold' => 49, 'immune' => 0],
['name' => 'Siren', 'level' => 50, 'hp' => 68, 'atk' => 400, 'def' => 800, 'exp' => 10000, 'gold' => 50, 'immune' => 2],
['name' => 'Megawraith', 'level' => 21, 'hp' => 70, 'atk' => 60, 'def' => 46, 'exp' => 155, 'gold' => 52, 'immune' => 0],
['name' => 'Dawkin', 'level' => 21, 'hp' => 70, 'atk' => 60, 'def' => 46, 'exp' => 155, 'gold' => 52, 'immune' => 0],
['name' => 'Grey Bear', 'level' => 21, 'hp' => 70, 'atk' => 62, 'def' => 48, 'exp' => 160, 'gold' => 53, 'immune' => 0],
['name' => 'Haunt', 'level' => 22, 'hp' => 72, 'atk' => 62, 'def' => 48, 'exp' => 160, 'gold' => 53, 'immune' => 0],
['name' => 'Hellbeast', 'level' => 22, 'hp' => 74, 'atk' => 64, 'def' => 50, 'exp' => 165, 'gold' => 55, 'immune' => 0],
['name' => 'Fear', 'level' => 23, 'hp' => 76, 'atk' => 66, 'def' => 52, 'exp' => 165, 'gold' => 55, 'immune' => 0],
['name' => 'Beast', 'level' => 23, 'hp' => 76, 'atk' => 66, 'def' => 52, 'exp' => 170, 'gold' => 57, 'immune' => 0],
['name' => 'Ogre', 'level' => 23, 'hp' => 78, 'atk' => 68, 'def' => 54, 'exp' => 170, 'gold' => 57, 'immune' => 0],
['name' => 'Dark Bear', 'level' => 24, 'hp' => 80, 'atk' => 70, 'def' => 56, 'exp' => 175, 'gold' => 58, 'immune' => 1],
['name' => 'Fire', 'level' => 24, 'hp' => 80, 'atk' => 72, 'def' => 56, 'exp' => 175, 'gold' => 58, 'immune' => 0],
['name' => 'Polgergeist', 'level' => 25, 'hp' => 84, 'atk' => 74, 'def' => 58, 'exp' => 180, 'gold' => 60, 'immune' => 0],
['name' => 'Fright', 'level' => 25, 'hp' => 86, 'atk' => 76, 'def' => 58, 'exp' => 180, 'gold' => 60, 'immune' => 0],
['name' => 'Lycan', 'level' => 25, 'hp' => 88, 'atk' => 78, 'def' => 60, 'exp' => 185, 'gold' => 62, 'immune' => 0],
['name' => 'Terra Elemental', 'level' => 25, 'hp' => 88, 'atk' => 80, 'def' => 62, 'exp' => 185, 'gold' => 62, 'immune' => 1],
['name' => 'Necromancer', 'level' => 26, 'hp' => 90, 'atk' => 80, 'def' => 62, 'exp' => 190, 'gold' => 63, 'immune' => 0],
['name' => 'Ultrawraith', 'level' => 26, 'hp' => 90, 'atk' => 82, 'def' => 64, 'exp' => 190, 'gold' => 63, 'immune' => 0],
['name' => 'Dawkor', 'level' => 26, 'hp' => 92, 'atk' => 82, 'def' => 64, 'exp' => 195, 'gold' => 65, 'immune' => 0],
['name' => 'Werebear', 'level' => 26, 'hp' => 92, 'atk' => 84, 'def' => 65, 'exp' => 195, 'gold' => 65, 'immune' => 0],
['name' => 'Brute', 'level' => 27, 'hp' => 94, 'atk' => 84, 'def' => 65, 'exp' => 200, 'gold' => 67, 'immune' => 0],
['name' => 'Large Beast', 'level' => 27, 'hp' => 96, 'atk' => 88, 'def' => 66, 'exp' => 200, 'gold' => 67, 'immune' => 0],
['name' => 'Horror', 'level' => 27, 'hp' => 96, 'atk' => 88, 'def' => 68, 'exp' => 210, 'gold' => 70, 'immune' => 0],
['name' => 'Flame', 'level' => 28, 'hp' => 100, 'atk' => 90, 'def' => 70, 'exp' => 210, 'gold' => 70, 'immune' => 0],
['name' => 'Lycanthor', 'level' => 28, 'hp' => 100, 'atk' => 90, 'def' => 70, 'exp' => 210, 'gold' => 70, 'immune' => 0],
['name' => 'Wyrm', 'level' => 28, 'hp' => 100, 'atk' => 92, 'def' => 72, 'exp' => 220, 'gold' => 73, 'immune' => 0],
['name' => 'Aero Elemental', 'level' => 29, 'hp' => 104, 'atk' => 94, 'def' => 74, 'exp' => 220, 'gold' => 73, 'immune' => 1],
['name' => 'Dawkare', 'level' => 29, 'hp' => 106, 'atk' => 96, 'def' => 76, 'exp' => 220, 'gold' => 73, 'immune' => 0],
['name' => 'Large Brute', 'level' => 29, 'hp' => 108, 'atk' => 98, 'def' => 78, 'exp' => 230, 'gold' => 77, 'immune' => 0],
['name' => 'Frost Wyrm', 'level' => 30, 'hp' => 110, 'atk' => 100, 'def' => 80, 'exp' => 230, 'gold' => 77, 'immune' => 0],
['name' => 'Knight', 'level' => 30, 'hp' => 110, 'atk' => 102, 'def' => 80, 'exp' => 240, 'gold' => 80, 'immune' => 0],
['name' => 'Lycanthra', 'level' => 30, 'hp' => 112, 'atk' => 104, 'def' => 82, 'exp' => 240, 'gold' => 80, 'immune' => 0],
['name' => 'Terror', 'level' => 31, 'hp' => 115, 'atk' => 108, 'def' => 84, 'exp' => 250, 'gold' => 83, 'immune' => 0],
['name' => 'Blaze', 'level' => 31, 'hp' => 118, 'atk' => 108, 'def' => 84, 'exp' => 250, 'gold' => 83, 'immune' => 0],
['name' => 'Aqua Elemental', 'level' => 31, 'hp' => 120, 'atk' => 110, 'def' => 90, 'exp' => 260, 'gold' => 87, 'immune' => 1],
['name' => 'Fire Wyrm', 'level' => 32, 'hp' => 120, 'atk' => 110, 'def' => 90, 'exp' => 260, 'gold' => 87, 'immune' => 0],
['name' => 'Lesser Wyvern', 'level' => 32, 'hp' => 122, 'atk' => 110, 'def' => 92, 'exp' => 270, 'gold' => 90, 'immune' => 0],
['name' => 'Doomer', 'level' => 32, 'hp' => 124, 'atk' => 112, 'def' => 92, 'exp' => 270, 'gold' => 90, 'immune' => 0],
['name' => 'Armor Knight', 'level' => 33, 'hp' => 130, 'atk' => 115, 'def' => 95, 'exp' => 280, 'gold' => 93, 'immune' => 0],
['name' => 'Wyvern', 'level' => 33, 'hp' => 134, 'atk' => 120, 'def' => 95, 'exp' => 290, 'gold' => 97, 'immune' => 0],
['name' => 'Nightmare', 'level' => 33, 'hp' => 138, 'atk' => 125, 'def' => 100, 'exp' => 300, 'gold' => 100, 'immune' => 0],
['name' => 'Fira Elemental', 'level' => 34, 'hp' => 140, 'atk' => 125, 'def' => 100, 'exp' => 310, 'gold' => 103, 'immune' => 1],
['name' => 'Megadoomer', 'level' => 34, 'hp' => 140, 'atk' => 128, 'def' => 105, 'exp' => 320, 'gold' => 107, 'immune' => 0],
['name' => 'Greater Wyvern', 'level' => 34, 'hp' => 145, 'atk' => 130, 'def' => 105, 'exp' => 335, 'gold' => 112, 'immune' => 0],
['name' => 'Advocate', 'level' => 35, 'hp' => 148, 'atk' => 132, 'def' => 108, 'exp' => 350, 'gold' => 117, 'immune' => 0],
['name' => 'Strong Knight', 'level' => 35, 'hp' => 150, 'atk' => 135, 'def' => 110, 'exp' => 365, 'gold' => 122, 'immune' => 0],
['name' => 'Liche', 'level' => 35, 'hp' => 150, 'atk' => 135, 'def' => 110, 'exp' => 380, 'gold' => 127, 'immune' => 0],
['name' => 'Ultradoomer', 'level' => 36, 'hp' => 155, 'atk' => 140, 'def' => 115, 'exp' => 395, 'gold' => 132, 'immune' => 0],
['name' => 'Fanatic', 'level' => 36, 'hp' => 160, 'atk' => 140, 'def' => 115, 'exp' => 410, 'gold' => 137, 'immune' => 0],
['name' => 'Green Dragon', 'level' => 36, 'hp' => 160, 'atk' => 140, 'def' => 115, 'exp' => 425, 'gold' => 142, 'immune' => 0],
['name' => 'Fiend', 'level' => 37, 'hp' => 160, 'atk' => 145, 'def' => 120, 'exp' => 445, 'gold' => 148, 'immune' => 0],
['name' => 'Greatest Wyvern', 'level' => 37, 'hp' => 162, 'atk' => 150, 'def' => 120, 'exp' => 465, 'gold' => 155, 'immune' => 0],
['name' => 'Lesser Devil', 'level' => 37, 'hp' => 164, 'atk' => 150, 'def' => 120, 'exp' => 485, 'gold' => 162, 'immune' => 0],
['name' => 'Liche Master', 'level' => 38, 'hp' => 168, 'atk' => 155, 'def' => 125, 'exp' => 505, 'gold' => 168, 'immune' => 0],
['name' => 'Zealot', 'level' => 38, 'hp' => 168, 'atk' => 155, 'def' => 125, 'exp' => 530, 'gold' => 177, 'immune' => 0],
['name' => 'Serafiend', 'level' => 38, 'hp' => 170, 'atk' => 155, 'def' => 125, 'exp' => 555, 'gold' => 185, 'immune' => 0],
['name' => 'Pale Knight', 'level' => 39, 'hp' => 175, 'atk' => 160, 'def' => 130, 'exp' => 580, 'gold' => 193, 'immune' => 0],
['name' => 'Blue Dragon', 'level' => 39, 'hp' => 180, 'atk' => 160, 'def' => 130, 'exp' => 605, 'gold' => 202, 'immune' => 0],
['name' => 'Obsessive', 'level' => 40, 'hp' => 180, 'atk' => 160, 'def' => 135, 'exp' => 630, 'gold' => 210, 'immune' => 0],
['name' => 'Devil', 'level' => 40, 'hp' => 184, 'atk' => 164, 'def' => 135, 'exp' => 666, 'gold' => 222, 'immune' => 0],
['name' => 'Liche Prince', 'level' => 40, 'hp' => 190, 'atk' => 168, 'def' => 138, 'exp' => 660, 'gold' => 220, 'immune' => 0],
['name' => 'Cherufiend', 'level' => 41, 'hp' => 195, 'atk' => 170, 'def' => 140, 'exp' => 690, 'gold' => 230, 'immune' => 0],
['name' => 'Red Dragon', 'level' => 41, 'hp' => 200, 'atk' => 180, 'def' => 145, 'exp' => 720, 'gold' => 240, 'immune' => 0],
['name' => 'Greater Devil', 'level' => 41, 'hp' => 200, 'atk' => 180, 'def' => 145, 'exp' => 750, 'gold' => 250, 'immune' => 0],
['name' => 'Renegade', 'level' => 42, 'hp' => 205, 'atk' => 185, 'def' => 150, 'exp' => 780, 'gold' => 260, 'immune' => 0],
['name' => 'Archfiend', 'level' => 42, 'hp' => 210, 'atk' => 190, 'def' => 150, 'exp' => 810, 'gold' => 270, 'immune' => 0],
['name' => 'Liche Lord', 'level' => 42, 'hp' => 210, 'atk' => 190, 'def' => 155, 'exp' => 850, 'gold' => 283, 'immune' => 0],
['name' => 'Greatest Devil', 'level' => 43, 'hp' => 215, 'atk' => 195, 'def' => 160, 'exp' => 890, 'gold' => 297, 'immune' => 0],
['name' => 'Dark Knight', 'level' => 43, 'hp' => 220, 'atk' => 200, 'def' => 160, 'exp' => 930, 'gold' => 310, 'immune' => 0],
['name' => 'Giant', 'level' => 43, 'hp' => 220, 'atk' => 200, 'def' => 165, 'exp' => 970, 'gold' => 323, 'immune' => 0],
['name' => 'Shadow Dragon', 'level' => 44, 'hp' => 225, 'atk' => 200, 'def' => 170, 'exp' => 1010, 'gold' => 337, 'immune' => 0],
['name' => 'Liche King', 'level' => 44, 'hp' => 225, 'atk' => 205, 'def' => 170, 'exp' => 1050, 'gold' => 350, 'immune' => 0],
['name' => 'Incubus', 'level' => 44, 'hp' => 230, 'atk' => 205, 'def' => 175, 'exp' => 1100, 'gold' => 367, 'immune' => 1],
['name' => 'Traitor', 'level' => 45, 'hp' => 230, 'atk' => 205, 'def' => 175, 'exp' => 1150, 'gold' => 383, 'immune' => 0],
['name' => 'Demon', 'level' => 45, 'hp' => 240, 'atk' => 210, 'def' => 180, 'exp' => 1200, 'gold' => 400, 'immune' => 0],
['name' => 'Dark Dragon', 'level' => 45, 'hp' => 245, 'atk' => 215, 'def' => 180, 'exp' => 1250, 'gold' => 417, 'immune' => 1],
['name' => 'Insurgent', 'level' => 46, 'hp' => 250, 'atk' => 220, 'def' => 190, 'exp' => 1300, 'gold' => 433, 'immune' => 0],
['name' => 'Leviathan', 'level' => 46, 'hp' => 255, 'atk' => 225, 'def' => 190, 'exp' => 1350, 'gold' => 450, 'immune' => 0],
['name' => 'Grey Daemon', 'level' => 46, 'hp' => 260, 'atk' => 230, 'def' => 190, 'exp' => 1400, 'gold' => 467, 'immune' => 0],
['name' => 'Succubus', 'level' => 47, 'hp' => 265, 'atk' => 240, 'def' => 200, 'exp' => 1460, 'gold' => 487, 'immune' => 1],
['name' => 'Demon Prince', 'level' => 47, 'hp' => 270, 'atk' => 240, 'def' => 200, 'exp' => 1520, 'gold' => 507, 'immune' => 0],
['name' => 'Black Dragon', 'level' => 47, 'hp' => 275, 'atk' => 250, 'def' => 205, 'exp' => 1580, 'gold' => 527, 'immune' => 1],
['name' => 'Nihilist', 'level' => 47, 'hp' => 280, 'atk' => 250, 'def' => 205, 'exp' => 1640, 'gold' => 547, 'immune' => 0],
['name' => 'Behemoth', 'level' => 48, 'hp' => 285, 'atk' => 260, 'def' => 210, 'exp' => 1700, 'gold' => 567, 'immune' => 0],
['name' => 'Demagogue', 'level' => 48, 'hp' => 290, 'atk' => 260, 'def' => 210, 'exp' => 1760, 'gold' => 587, 'immune' => 0],
['name' => 'Demon Lord', 'level' => 48, 'hp' => 300, 'atk' => 270, 'def' => 220, 'exp' => 1820, 'gold' => 607, 'immune' => 0],
['name' => 'Red Daemon', 'level' => 48, 'hp' => 310, 'atk' => 280, 'def' => 230, 'exp' => 1880, 'gold' => 627, 'immune' => 0],
['name' => 'Colossus', 'level' => 49, 'hp' => 320, 'atk' => 300, 'def' => 240, 'exp' => 1940, 'gold' => 647, 'immune' => 0],
['name' => 'Demon King', 'level' => 49, 'hp' => 330, 'atk' => 300, 'def' => 250, 'exp' => 2000, 'gold' => 667, 'immune' => 0],
['name' => 'Dark Daemon', 'level' => 49, 'hp' => 340, 'atk' => 320, 'def' => 260, 'exp' => 2200, 'gold' => 733, 'immune' => 1],
['name' => 'Titan', 'level' => 50, 'hp' => 360, 'atk' => 340, 'def' => 270, 'exp' => 2400, 'gold' => 800, 'immune' => 0],
['name' => 'Black Daemon', 'level' => 50, 'hp' => 400, 'atk' => 400, 'def' => 280, 'exp' => 3000, 'gold' => 1000, 'immune' => 1],
['name' => 'Lucifuge', 'level' => 50, 'hp' => 600, 'atk' => 600, 'def' => 400, 'exp' => 10000, 'gold' => 10000, 'immune' => 2],
]);
}
// Create News table
$db->table('news')->create([
'id INTEGER PRIMARY KEY',
'posted DATETIME DEFAULT CURRENT_TIMESTAMP',
'author INTEGER DEFAULT 1',
"title TEXT DEFAULT ''",
"content TEXT DEFAULT ''"
]);
// Create Spells table
$db->table('spells')->create([
'id INTEGER PRIMARY KEY',
'name TEXT NOT NULL',
'type INTEGER DEFAULT 1',
'mp INTEGER DEFAULT 0',
"effect TEXT DEFAULT ''",
"icon TEXT DEFAULT ''"
]);
// Fill spells if complete install
if ($complete) {
$db->table('spells')->insert([
// Type 1 = healing
['name' => 'Heal', 'type' => 1, 'mp' => 5, 'effect' => 'heal:self,10', 'icon' => 'heal.png' ],
['name' => 'Cure', 'type' => 1, 'mp' => 10, 'effect' => 'heal:self,25', 'icon' => 'cure.png' ],
['name' => 'Breath', 'type' => 1, 'mp' => 25, 'effect' => 'heal:self,50', 'icon' => 'breath.png'],
['name' => 'Revive', 'type' => 1, 'mp' => 50, 'effect' => 'heal:self,100', 'icon' => 'revive.png'],
['name' => 'Gaia', 'type' => 1, 'mp' => 75, 'effect' => 'heal:self,150', 'icon' => 'gaia.png' ],
// Type 2 = damage
['name' => 'Slash', 'type' => 2, 'mp' => 5, 'effect' => 'damage:opp,10', 'icon' => 'slash.png' ],
['name' => 'Magic Missile', 'type' => 2, 'mp' => 12, 'effect' => 'damage:opp,35', 'icon' => 'missile.png' ],
['name' => 'Fireball', 'type' => 2, 'mp' => 25, 'effect' => 'damage:opp,70', 'icon' => 'fireball.png' ],
['name' => 'Pain', 'type' => 2, 'mp' => 40, 'effect' => 'damage:opp,100', 'icon' => 'pain.png' ],
['name' => 'Lightning', 'type' => 2, 'mp' => 50, 'effect' => 'damage:opp,130', 'icon' => 'lightning.png'],
['name' => 'Chaos', 'type' => 2, 'mp' => 75, 'effect' => 'damage:opp,200', 'icon' => 'chaos.png' ],
// Type 3 = sleep
['name' => 'Sleep', 'type' => 3, 'mp' => 10, 'effect' => 'sleep:opp,3', 'icon' => 'sleep.png' ],
['name' => 'Dream', 'type' => 3, 'mp' => 30, 'effect' => 'sleep:opp,6', 'icon' => 'dream.png' ],
['name' => 'Nightmare', 'type' => 3, 'mp' => 60, 'effect' => 'sleep:opp,13', 'icon' => 'nightmare.png'],
// Type 4 = rage
['name' => 'Craze', 'type' => 4, 'mp' => 10, 'effect' => 'rage:self,3', 'icon' => 'craze.png'],
['name' => 'Rage', 'type' => 4, 'mp' => 30, 'effect' => 'rage:self,6', 'icon' => 'rage.png' ],
['name' => 'Fury', 'type' => 4, 'mp' => 60, 'effect' => 'rage:self,13', 'icon' => 'fury.png' ],
// Type 5 = protect
['name' => 'Ward', 'type' => 5, 'mp' => 10, 'effect' => 'protect:self,3', 'icon' => 'ward.png' ],
['name' => 'Guard', 'type' => 5, 'mp' => 30, 'effect' => 'protect:self,6', 'icon' => 'guard.png' ],
['name' => 'Barrier', 'type' => 5, 'mp' => 60, 'effect' => 'protect:self,13', 'icon' => 'barrier.png'],
]);
}
// Create Towns table
$db->table('towns')->create([
'id INTEGER PRIMARY KEY',
'name TEXT NOT NULL',
'x INTEGER DEFAULT 0',
'y INTEGER DEFAULT 0',
'inn_cost INTEGER DEFAULT 0',
'map_cost INTEGER DEFAULT 5',
'tp_cost INTEGER DEFAULT 0',
"shop_list TEXT DEFAULT ''",
"image TEXT DEFAULT ''",
]);
// Fill towns table if complete install
if ($complete) {
$db->insert([
['name' => 'Midworld', 'x' => 0, 'y' => 0, 'inn_cost' => 5, 'map_cost' => 5, 'tp_cost' => 0, 'shop_list' => '1,2,3,17,18,19,28,29', 'image' => 'midworld.png'],
['name' => 'Roma', 'x' => 30, 'y' => 30, 'inn_cost' => 10, 'map_cost' => 25, 'tp_cost' => 5, 'shop_list' => '2,3,4,18,19,29', 'image' => 'roma.png' ],
['name' => 'Bris', 'x' => 70, 'y' => -70, 'inn_cost' => 25, 'map_cost' => 50, 'tp_cost' => 15, 'shop_list' => '2,3,4,5,18,19,20,29,30', 'image' => 'bris.png' ],
['name' => 'Kalle', 'x' => -100, 'y' => 100, 'inn_cost' => 40, 'map_cost' => 100, 'tp_cost' => 30, 'shop_list' => '5,6,8,10,12,21,22,23,29,30', 'image' => 'kalle.png' ],
['name' => 'Narcissa', 'x' => -130, 'y' => -130, 'inn_cost' => 60, 'map_cost' => 500, 'tp_cost' => 50, 'shop_list' => '4,7,9,11,13,21,22,23,29,30,31', 'image' => 'narcissa.png'],
['name' => 'Hambry', 'x' => 170, 'y' => 170, 'inn_cost' => 90, 'map_cost' => 1000, 'tp_cost' => 80, 'shop_list' => '10,11,12,13,14,23,24,30,31', 'image' => 'hambry.png' ],
['name' => 'Gilead', 'x' => 200, 'y' => -200, 'inn_cost' => 100, 'map_cost' => 3000, 'tp_cost' => 110,'shop_list' => '12,13,14,15,24,25,26,32', 'image' => 'gilead.png' ],
['name' => 'Endworld', 'x' => -250, 'y' => -250, 'inn_cost' => 150, 'map_cost' => 9000, 'tp_cost' => 160,'shop_list' => '16,27,33', 'image' => 'endworld.png'],
]);
}
// Create Users table
$db->table('users')->create([
'id INTEGER PRIMARY KEY',
'username TEXT NOT NULL',
'password TEXT NOT NULL',
"email TEXT DEFAULT ''",
'verified INTEGER DEFAULT 1',
'registered DATETIME DEFAULT CURRENT_TIMESTAMP',
'last_online DATETIME DEFAULT CURRENT_TIMESTAMP',
'currently INTEGER DEFAULT 0',
'role INTEGER DEFAULT 1',
'class INTEGER DEFAULT 1',
'level INTEGER DEFAULT 1',
'exp INTEGER DEFAULT 0',
'gold INTEGER DEFAULT 0',
'hp INTEGER DEFAULT 0',
'max_hp INTEGER DEFAULT 0',
'mp INTEGER DEFAULT 0',
'max_mp INTEGER DEFAULT 0',
'tp INTEGER DEFAULT 0',
'max_tp INTEGER DEFAULT 0',
'str INTEGER DEFAULT 0',
'atk INTEGER DEFAULT 0',
'dex INTEGER DEFAULT 0',
'def INTEGER DEFAULT 0',
'weapon_id INTEGER DEFAULT 0',
'armor_id INTEGER DEFAULT 0',
'shield_id INTEGER DEFAULT 0',
'slot_1_id INTEGER DEFAULT 0',
'slot_2_id INTEGER DEFAULT 0',
'slot_3_id INTEGER DEFAULT 0',
"spells TEXT DEFAULT ''",
"maps TEXT DEFAULT ''",
]);
// Create Fights table
$db->table('fights')->create([
'id INTEGER PRIMARY KEY',
'user_id INTEGER DEFAULT 1',
'monster_id INTEGER DEFAULT 1',
'turn INTEGER DEFAULT 1',
'user_hp INTEGER DEFAULT 0',
'user_mp INTEGER DEFAULT 0',
'monster_hp INTEGER DEFAULT 0',
'monster_mp INTEGER DEFAULT 0',
'user_uber_dmg INTEGER DEFAULT 0',
'monster_uber_dmg INTEGER DEFAULT 0',
'user_uber_def INTEGER DEFAULT 0',
'monster_uber_def INTEGER DEFAULT 0',
'monster_immune INTEGER DEFAULT 0',
'monster_sleep INTEGER DEFAULT 0',
]);
echo render('install/layout', ['title' => 'Database', 'step' => 'second', 'complete' => $complete]);
exit;
}

15
server/bootstrap.php Normal file
View File

@ -0,0 +1,15 @@
<?php // bootstrap.php :: Initialize all our boring stuff
ini_set('display_errors', 'on');
error_reporting(E_ALL | E_STRICT);
$start = microtime(true);
session_start();
const VERSION = '1.1.11';
const BUILD = '';
const DB = SERVER.'/database/dragon.db';
require_once SERVER.'/lib.php';
require_once SERVER.'/database.php';

374
server/database.php Normal file
View File

@ -0,0 +1,374 @@
<?php
/**
* SQLite database wrapper class. Provides a non-static interface to interact with a
* SQLite database in as simple a way as possible.
*
* The wrapper provides a simple-to-use database API using PDO's SQLite driver.
* It was designed to have method signatures very close to Laravel's Eloquent ORM. There
* are not, however, any ORM features in the wrapper. These must be handled at
* the model level.
*
* By default, foreign keys are enabled and the database is in WAL mode. In general
* these defaults should be perfect for most use cases.
*/
class Database
{
/**
* The PDO handle.
*/
private PDO $c;
/**
* The current working table.
*/
private string $table = '';
/**
* The number of queries executed.
*/
private int $queries = 0;
/**
* The log of executed queries.
*/
private array $log = [];
/**
* The last error.
*/
private string $error = '';
/**
* The array for the query builder.
*/
private array $builder = [
'where' => [],
'order' => [],
'limit' => 0,
'values' => [],
];
/**
* Open a connection to the database.
*/
public function __construct(string $path, array $opts = [])
{
$opts = !empty($opts) ? $opts : [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
try {
$this->c = new PDO("sqlite:$path", null, null, $opts);
$this->c->exec('PRAGMA foreign_keys = ON;'); // Enable foreign keys
$this->c->exec('PRAGMA journal_mode = WAL;'); // Enable WAL
} catch (PDOException $e) {
$this->error = "Failed to open database: " . $e->getMessage();
throw $e;
}
}
/**
* Change the current working table.
*/
public function table(string $name): Database
{
$this->table = $name;
return $this;
}
/**
* Create a table with the name of the current working table. Will drop
* the table if it already exists.
*/
public function create(array $columns): PDOStatement|false
{
$query = "CREATE TABLE IF NOT EXISTS $this->table (" . implode(', ', $columns) . ');';
$this->addToLog($query);
return $this->c->query($query);
}
/**
* Drop the current working table if it exists.
*/
public function drop(): PDOStatement|false
{
$query = "DROP TABLE IF EXISTS $this->table;";
$this->addToLog($query);
return $this->c->query($query);
}
/**
* Return the current working table's schema.
*/
public function schema(): array
{
$query = "PRAGMA table_info($this->table);";
$this->addToLog($query);
return $this->c->query($query)->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Insert data into the current working table. Pass an array of key/value
* pairs to insert one record, or an array of arrays to insert multiple. Returns
* the number of rows inserted, or false on failure.
*/
public function insert(array $data): int|false
{
// If the first element is not an array we can assume we're doing a single insert.
if (!isset($data[0])) {
$query = "INSERT INTO $this->table (" . implode(', ', array_keys($data)) . ')'
. ' VALUES (' . implode(', ', array_fill(0, count($data), '?')) . ');';
$this->addToLog($query);
return $this->c->prepare($query)->execute(array_values($data));
}
// Otherwise we will build a multi-insert query.
$query = "INSERT INTO $this->table (" . implode(', ', array_keys($data[0])) . ') VALUES ';
$placeholders = [];
$values = [];
foreach ($data as $row) {
$placeholders[] = '(' . implode(', ', array_fill(0, count($row), '?')) . ')';
foreach ($row as $value) $values[] = $value;
}
$query .= implode(', ', $placeholders) . ';';
$this->addToLog($query);
return $this->c->prepare($query)->execute($values);
}
/**
* Insert a default record into the current working table.
*/
public function insertDefaultValues(): int|false
{
$query = "INSERT INTO $this->table DEFAULT VALUES;";
$this->addToLog($query);
return $this->c->prepare($query)->execute();
}
/**
* Add a where clause to the builder. All values are paramaterized.
*/
public function where(string $column, string $operator, mixed $value): Database
{
$this->builder['where'][] = "$column $operator ?";
$this->builder['values'][] = $value;
return $this;
}
/**
* Add an order clause to the builder.
*/
public function order(string $column, string $direction = 'ASC'): Database
{
$this->builder['order'] = "$column $direction";
return $this;
}
/**
* Set a limit in the builder.
*/
public function limit(int $limit): Database
{
$this->builder['limit'] = $limit;
return $this;
}
/**
* Build a select query and return the result. By default selects the entire
* row. Optionally use fetchAll, but there is also the selectAll() alias method
* for this.
*/
public function select(string $what = '*', bool $fetchAll = false): array|false
{
$query = "SELECT $what FROM $this->table";
if (!empty($this->builder['where'])) $query .= " WHERE " . implode(' AND ', $this->builder['where']);
if (!empty($this->builder['order'])) $query .= " ORDER BY " . $this->builder['order'];
if (!empty($this->builder['limit'])) $query .= " LIMIT " . $this->builder['limit'];
$this->addToLog($query);
try {
$stmt = $this->c->prepare($query);
$stmt->execute($this->builder['values']);
} catch (PDOException $e) {
$this->error = "Failed to execute query: " . $e->getMessage();
return false;
}
$this->resetBuilder();
return $fetchAll ? $stmt->fetchAll() : $stmt->fetch();
}
/**
* Delete records from the current working table. Returns the number of rows
* deleted, or false on failure. Uses where clauses if set.
*/
public function delete(): int|false
{
$query = "DELETE FROM $this->table";
if (!empty($this->builder['where'])) $query .= " WHERE " . implode(' AND ', $this->builder['where']);
$this->addToLog($query);
$this->resetBuilder();
return $this->c->exec($query);
}
/**
* Update records in the current working table. Returns the number of rows
* updated, or false on failure. Uses where clauses if set.
*/
public function update(array $data): int|false
{
$query = "UPDATE $this->table SET " . implode(', ', array_keys($data)) . ' = ?';
if (!empty($this->builder['where'])) $query .= " WHERE " . implode(' AND ', $this->builder['where']);
$this->addToLog($query);
$values = array_merge(array_values($data), $this->builder['values']);
$this->resetBuilder();
return $this->c->prepare($query)->execute($values);
}
/**
* Get the number of rows in the current working table. Can use where clauses.
*/
public function count(): int|false
{
return $this->select('COUNT(*)', true)[0]['COUNT(*)'];
}
/**
* Alias for $db->select(true)
*/
public function selectAll(string $what = '*'): array|false
{
return $this->select($what, true);
}
/**
* Return whether the given table exists.
*/
public function tableExists(string $name): bool
{
$query = "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='$name';";
$this->addToLog($query);
return $this->c->query($query)->fetchColumn() > 0;
}
/**
* Return the PDO instance; for when more complex operations are needed.
*/
public function c(): PDO
{
return $this->c;
}
/**
* Alias for PDO::prepare
*/
public function prepare(string $query): PDOStatement
{
return $this->c->prepare($query);
}
/**
* Alias for PDO::lastInsertId
*/
public function lastInsertId(): int
{
return $this->c->lastInsertId();
}
/**
* Alias for PDO::exec
*/
public function exec(string $query): int
{
$this->addToLog($query);
return $this->c->exec($query);
}
/**
* Alias for PDO::beginTransaction
*/
public function begin(): bool
{
return $this->c->beginTransaction();
}
/**
* Alias for PDO::commit
*/
public function commit(): bool
{
return $this->c->commit();
}
/**
* Alias for PDO::rollBack
*/
public function rollBack(): bool
{
return $this->c->rollBack();
}
/**
* Alias for PDO::query
*/
public function query(string $query): PDOStatement|false
{
$this->addToLog($query);
return $this->c->query($query);
}
/**
* Add the query to the log and increment the number of queries executed.
*/
private function addToLog(string $query): void
{
$this->log[] = $query;
$this->queries++;
}
/**
* Reset the builder to it's default structure.
*/
public function resetBuilder(): void
{
$this->builder = [
'where' => [],
'order' => [],
'limit' => 0,
'values' => [],
];
}
/**
* Return the log of executed queries.
*/
public function log(): array
{
return $this->log;
}
/**
* Return the number of queries executed.
*/
public function queries(): int
{
return $this->queries;
}
/**
* Return the last error message.
*/
public function error(): string
{
return $this->error;
}
}

View File

@ -0,0 +1,4 @@
## /server/database
This README is here to allow git to keep this folder present in the repo.
The SQLite database for the game is generated into this folder, and PDO
will not create the path TO the SQLite database.

BIN
server/database/dragon.db Normal file

Binary file not shown.

View File

@ -1,72 +1,35 @@
<?php // lib.php :: Common functions used throughout the program. <?php // lib.php :: Common functions used throughout the program.
$starttime = getmicrotime(); // Redirect to another page.
$numqueries = 0; function redirect(string $url): void
$version = "1.1.11"; {
$build = ""; header("Location: $url");
exit;
// Handling for servers with magic_quotes turned on.
// Example from php.net.
if (get_magic_quotes_gpc()) {
$_POST = array_map('stripslashes_deep', $_POST);
$_GET = array_map('stripslashes_deep', $_GET);
$_COOKIE = array_map('stripslashes_deep', $_COOKIE);
}
$_POST = array_map('addslashes_deep', $_POST);
$_POST = array_map('html_deep', $_POST);
$_GET = array_map('addslashes_deep', $_GET);
$_GET = array_map('html_deep', $_GET);
$_COOKIE = array_map('addslashes_deep', $_COOKIE);
$_COOKIE = array_map('html_deep', $_COOKIE);
function stripslashes_deep($value) {
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
return $value;
} }
function addslashes_deep($value) { // Check if the server is installed.
function installed(): bool
$value = is_array($value) ? {
array_map('addslashes_deep', $value) : return file_exists(SERVER.'/.installed');
addslashes($value);
return $value;
} }
function html_deep($value) { // Get a template path.
function template(string $name): string
$value = is_array($value) ? {
array_map('html_deep', $value) : return SERVER."/templates/$name.php";
htmlspecialchars($value);
return $value;
} }
function opendb() { // Open database connection. // Render a template. Pass data to it - uses an output buffer to have PHP process the template instead of using
// a template engine. If you're including partials in the page, call render('partial', $data), as $data will still
include('config.php'); // be available.
extract($dbsettings); function render(string $baseView, array $data = []): string
$link = mysql_connect($server, $user, $pass) or die(mysql_error()); {
mysql_select_db($name) or die(mysql_error()); ob_start();
return $link; extract($data);
include template($baseView);
return ob_get_clean();
} }
function doquery($query, $table) { // Something of a tiny little database abstraction layer.
include('config.php');
global $numqueries;
$sqlquery = mysql_query(str_replace("{{table}}", $dbsettings["prefix"] . "_" . $table, $query)) or die(mysql_error());
$numqueries++;
return $sqlquery;
}
function gettemplate($templatename) { // SQL query for the template. function gettemplate($templatename) { // SQL query for the template.

View File

@ -0,0 +1,33 @@
<p class="mb-1">
Installation for Dragon Knight is a simple two-step process:
set up the database tables, then create the admin user. After
that, you're done.
</p>
<p class="mb-1">
You have two options for database setup: complete or partial.
<ul>
<li>
<b>Complete Setup</b> includes table structure and all
default data (items, drops, monsters, levels, spells,
towns) - after complete setup, the game is totally
ready to run.
</li>
<li>
<b>Partial Setup</b> only creates the table structure,
it does not populate the tables - use this if you are
going to be creating and importing your own customized
game data later.
</li>
</ul>
</p>
<p>
Click the appropriate button below for your preferred installation method.
<form action="/install/?step=second" method="post">
<button type="submit" name="mode" value="complete">Complete Setup</button>
- OR - <br>
<button type="submit" name="mode" value="partial">Partial Setup</button>
</form>
</p>

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= $title ?> | Installer</title>
<link rel="stylesheet" href="/css/dragon.css">
</head>
<body>
<div id="container">
<h1>Dragon Knight Installation</h1>
<h2><?= $title ?></h2>
<?= render("install/$step", $data) ?>
</div>
</body>
</html>

View File

@ -0,0 +1,52 @@
<p class="mb-1">
If you're seeing this page with no errors, then database setup is complete!
</p>
<?php if ($complete): ?>
<p class="mb-1">
You chose a complete install, so the database has been filled with all sorts of
cool starting data! Items, drops, monsters, towns, weapons, armor, et cetera.
</p>
<?php else: ?>
<p class="mb-1">
You chose a partial install, so the database has been left empty. The onus is now
on you to fill it up with all your awesome ideas!
</p>
<?php endif; ?>
<p class="mb-1">
The next step is to create the admin account you'll run the game from. Do so
below. <?php if (!$complete): ?>Since your install was partial, you can't choose
a class here. Once you make some classes, you can assign yourself one in the admin
panel.<?php endif; ?>
</p>
<form action="/install/?step=third" method="post">
<div class="mb-1">
<label for="username">Username</label>
<input type="text" name="username" id="username" required>
</div>
<div class="mb-1">
<label for="password">Password</label>
<input type="password" name="password" id="password" required>
</div class="mb-1">
<div class="mb-1">
<label for="email">Email</label>
<input type="email" name="email" id="email" required>
</div>
<?php if ($complete): ?>
<div class="mb-1">
<label for="class">Class</label>
<select name="class" id="class">
<option value="1">Mage</option>
<option value="2">Paladin</option>
<option value="3">Warrior</option>
</select>
</div>
<?php endif; ?>
<button type="submit" name="submit">Submit</button>
</form>