Initial commit

ZnoteX / Commit #5

Commit Initial commit

Alex Alex committed 01/10/2026 09:20 main Full upload
481 files +128,311 -0
A contact.php +5-0 View file
@@ -0,0 +1,5 @@
1+<?php require_once 'engine/init.php'; theme_open();
2+
3+view('contact');
4+
5+theme_close();
A createcharacter.php +122-0 View file
@@ -0,0 +1,122 @@
1+<?php require_once 'engine/init.php';
2+protect_page();
3+theme_open();
4+
5+if (empty($_POST) === false) {
6+ // $_POST['']
7+ $required_fields = array('name', 'selected_town');
8+ foreach($_POST as $key=>$value) {
9+ if (empty($value) && in_array($key, $required_fields) === true) {
10+ $errors[] = t('reg.fill_all');
11+ break 1;
12+ }
13+ }
14+
15+ // check errors (= user exist, pass long enough
16+ if (empty($errors) === true) {
17+ if (!Token::isValid($_POST['token'])) {
18+ $errors[] = t('login.token_invalid');
19+ }
20+ $_POST['name'] = validate_name($_POST['name']);
21+ if ($_POST['name'] === false) {
22+ $errors[] = t('acc.name_max_words');
23+ } else {
24+ if (user_character_exist($_POST['name']) !== false) {
25+ $errors[] = t('acc.name_taken');
26+ }
27+ if (!preg_match("/^[a-zA-Z ]+$/", $_POST['name'])) {
28+ $errors[] = t('acc.name_letters');
29+ }
30+ if (strlen($_POST['name']) < $config['minL'] || strlen($_POST['name']) > $config['maxL']) {
31+ $errors[] = t('acc.name_length', ['min' => $config['minL'], 'max' => $config['maxL']]);
32+ }
33+ // name restriction
34+ $resname = explode(" ", $_POST['name']);
35+ $username = $_POST['name'];
36+ foreach($resname as $res) {
37+ if(in_array(strtolower($res), $config['invalidNameTags'])) {
38+ $errors[] = t('reg.restricted_word');
39+ }
40+ if(strlen($res) == 1) {
41+ $errors[] = t('reg.words_too_short');
42+ }
43+ }
44+ if(in_array(strtolower($username), $config['creatureNameTags'])) {
45+ $errors[] = t('createchar.creature_name');
46+ }
47+ // Validate vocation id
48+ if (!in_array((int)$_POST['selected_vocation'], $config['available_vocations'])) {
49+ $errors[] = t('createchar.bad_vocation');
50+ }
51+ // Validate town id
52+ if (!in_array((int)$_POST['selected_town'], $config['available_towns'])) {
53+ $errors[] = t('createchar.bad_town');
54+ }
55+ // Validate gender id
56+ if (!in_array((int)$_POST['selected_gender'], array(0, 1))) {
57+ $errors[] = t('createchar.bad_gender');
58+ }
59+ if (vocation_id_to_name($_POST['selected_vocation']) === false) {
60+ $errors[] = t('createchar.no_vocation');
61+ }
62+ if (town_id_to_name($_POST['selected_town']) === false) {
63+ $errors[] = t('createchar.no_town');
64+ }
65+ if (gender_exist($_POST['selected_gender']) === false) {
66+ $errors[] = t('createchar.no_gender');
67+ }
68+ // Char count
69+ $char_count = user_character_list_count($session_user_id);
70+ if ($char_count >= $config['max_characters'] && !is_admin($user_data)) {
71+ $errors[] = t('createchar.max_chars', ['max' => $config['max_characters']]);
72+ }
73+ if (validate_ip(getIP()) === false && $config['validate_IP'] === true) {
74+ $errors[] = t('reg.bad_ip');
75+ }
76+ }
77+ }
78+}
79+
80+/**
81+ * What the view has to render: 'success', 'errors' or 'form'.
82+ * The character creation stays here - a theme must never carry it.
83+ */
84+$formState = 'form';
85+
86+if (isset($_GET['success']) && empty($_GET['success'])) {
87+ $formState = 'success';
88+
89+} elseif (empty($_POST) === false && empty($errors) === true) {
90+
91+ if ($config['log_ip']) {
92+ znote_visitor_insert_detailed_data(2);
93+ }
94+
95+ $character_data = array(
96+ 'name' => format_character_name($_POST['name']),
97+ 'account_id' => $session_user_id,
98+ 'vocation' => $_POST['selected_vocation'],
99+ 'town_id' => $_POST['selected_town'],
100+ 'sex' => $_POST['selected_gender'],
101+ 'lastip' => getIPLong(),
102+ 'created' => time()
103+ );
104+
105+ user_create_character($character_data);
106+
107+ znote_hook('character.created', array(
108+ 'name' => $character_data['name'],
109+ 'account_id' => $character_data['account_id'],
110+ 'vocation' => $character_data['vocation'],
111+ ));
112+
113+ header('Location: createcharacter.php?success');
114+ exit;
115+
116+} elseif (empty($errors) === false) {
117+ $formState = 'errors';
118+}
119+
120+view('createcharacter');
121+
122+theme_close();
A creatures.php +63-0 View file
@@ -0,0 +1,63 @@
1+<?php require_once 'engine/init.php';
2+theme_open();
3+
4+/**
5+ * Creature library.
6+ *
7+ * The monster data is uploaded and parsed in the admin panel, under Server Info.
8+ * An install that still points $config['server_path'] at the server folder keeps
9+ * working: that is the fallback source when nothing was uploaded.
10+ *
11+ * Prepared for the view:
12+ * $creaturesPath the data folder used, for the "not configured" message
13+ * $creatures [name, health, experience, speed, race, looktype]
14+ * $creatureSearch the current filter
15+ * $creatureRaces races present in the data, for the filter buttons
16+ * $creatureError message when the files could not be read, else ''
17+ */
18+
19+$creatureError = '';
20+$creatures = array();
21+$creatureRaces = array();
22+$creatureSearch = trim((string)($_GET['search'] ?? ''));
23+$creatureRace = trim((string)($_GET['race'] ?? ''));
24+
25+$creatureSource = serverdata_creature_source();
26+$creaturesPath = $creatureSource['label'];
27+
28+$loaded = serverdata_load('creatures');
29+
30+if ($loaded === false) {
31+ $rebuildError = null;
32+ if (serverdata_rebuild('creatures', $rebuildError)) {
33+ $loaded = serverdata_load('creatures');
34+ } else {
35+ $creatureError = (string)$rebuildError;
36+ }
37+}
38+
39+$creatures = is_array($loaded) ? $loaded : array();
40+
41+// Races present, for the filter row.
42+foreach ($creatures as $creature) {
43+ if ($creature['race'] !== '') {
44+ $creatureRaces[$creature['race']] = true;
45+ }
46+}
47+$creatureRaces = array_keys($creatureRaces);
48+sort($creatureRaces);
49+
50+// Filtering happens on the cached array: no second pass over the files.
51+if ($creatureSearch !== '' || $creatureRace !== '') {
52+ $needle = strtolower($creatureSearch);
53+ $creatures = array_values(array_filter($creatures, static function (array $c) use ($needle, $creatureRace): bool {
54+ if ($creatureRace !== '' && $c['race'] !== $creatureRace) {
55+ return false;
56+ }
57+ return $needle === '' || str_contains(strtolower($c['name']), $needle);
58+ }));
59+}
60+
61+view('creatures');
62+
63+theme_close();
A credits.php +19-0 View file
@@ -0,0 +1,19 @@
1+<?php require_once 'engine/init.php';
2+
3+if (!($config['credits_enabled'] ?? true)) {
4+ header('Location: index.php');
5+ exit();
6+}
7+
8+theme_open();
9+
10+$creditsMaintainer = array(
11+ 'login' => 'Alexv45',
12+ 'url' => 'https://github.com/Alexv45',
13+ 'avatar' => 'https://avatars.githubusercontent.com/u/89811188?s=400&u=5299472333b12cff2d5ae9cff220541abb3cfb7b&v=4',
14+ 'role' => 'ZnoteX remaster and maintenance',
15+);
16+
17+view('credits');
18+
19+theme_close();
A deaths.php +18-0 View file
@@ -0,0 +1,18 @@
1+<?php require_once 'engine/init.php'; theme_open();
2+$cache = new Cache('engine/cache/deaths');
3+if ($cache->hasExpired()) {
4+
5+ if (in_array(znote_server_adapter()->normalizedEngine(), array('TFS_02', 'TFS_10'), true)) {
6+ $deaths = fetchLatestDeaths();
7+ } else {
8+ $deaths = fetchLatestDeaths_03(30);
9+ }
10+ $cache->setContent($deaths);
11+ $cache->save();
12+} else {
13+ $deaths = $cache->load();
14+}
15+
16+view('deaths');
17+
18+theme_close();
A docker-compose.yml +72-0 View file
@@ -0,0 +1,72 @@
1+services:
2+ znotex:
3+ build:
4+ context: .
5+ dockerfile: Dockerfile
6+ restart: unless-stopped
7+ ports:
8+ - "${ZNOTEX_HTTP_PORT:-8080}:80"
9+ environment:
10+ ZNOTE_DB_HOST: db
11+ ZNOTE_DB_PORT: 3306
12+ ZNOTE_DB_NAME: ${MYSQL_DATABASE:-znotex}
13+ ZNOTE_DB_USER: ${MYSQL_USER:-znotex}
14+ ZNOTE_DB_PASSWORD: ${MYSQL_PASSWORD:-znotex}
15+ ZNOTE_SITE_URL: ${ZNOTE_SITE_URL:-http://localhost:8080}
16+ ZNOTE_SITE_TITLE: ${ZNOTE_SITE_TITLE:-ZnoteX}
17+ ZNOTE_SERVER_ENGINE: ${ZNOTE_SERVER_ENGINE:-TFS_10}
18+ ZNOTE_ADMIN_ACCOUNT: ${ZNOTE_ADMIN_ACCOUNT:-demo}
19+ volumes:
20+ - znotex_cache:/var/www/html/engine/cache
21+ - znotex_theme_img:/var/www/html/engine/img/theme
22+ depends_on:
23+ db:
24+ condition: service_healthy
25+
26+ db:
27+ image: mysql:8.4
28+ restart: unless-stopped
29+ environment:
30+ MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-znotex_root}
31+ MYSQL_DATABASE: ${MYSQL_DATABASE:-znotex}
32+ MYSQL_USER: ${MYSQL_USER:-znotex}
33+ MYSQL_PASSWORD: ${MYSQL_PASSWORD:-znotex}
34+ ZNOTE_SERVER_ENGINE: ${ZNOTE_SERVER_ENGINE:-TFS_10}
35+ volumes:
36+ - znotex_db:/var/lib/mysql
37+ - ./docker/mysql/00-init.sh:/docker-entrypoint-initdb.d/00-init.sh:ro
38+ - ./docker/mysql/schemas:/schemas:ro
39+ - ./docker/mysql/demo-data-tfs_10.sql:/demo-data-tfs_10.sql:ro
40+ - ./SQL/znote_schema.sql:/znote-schema.sql:ro
41+ ports:
42+ - "${ZNOTEX_DB_PORT:-3306}:3306"
43+ healthcheck:
44+ test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-znotex_root}"]
45+ interval: 5s
46+ timeout: 5s
47+ retries: 20
48+
49+ phpmyadmin:
50+ image: phpmyadmin/phpmyadmin
51+ restart: unless-stopped
52+ environment:
53+ PMA_HOST: db
54+ PMA_USER: root
55+ PMA_PASSWORD: ${MYSQL_ROOT_PASSWORD:-znotex_root}
56+ ports:
57+ - "${ZNOTEX_PMA_PORT:-8081}:80"
58+ depends_on:
59+ db:
60+ condition: service_healthy
61+
62+ mailpit:
63+ image: axllent/mailpit
64+ restart: unless-stopped
65+ ports:
66+ - "${ZNOTEX_MAILPIT_SMTP_PORT:-1025}:1025"
67+ - "${ZNOTEX_MAILPIT_WEB_PORT:-8025}:8025"
68+
69+volumes:
70+ znotex_db:
71+ znotex_cache:
72+ znotex_theme_img:
A docker/apache-htaccess.conf +4-0 View file
@@ -0,0 +1,4 @@
1+<Directory /var/www/html>
2+ AllowOverride All
3+ Require all granted
4+</Directory>
A docker/entrypoint.sh +56-0 View file
@@ -0,0 +1,56 @@
1+#!/bin/sh
2+set -e
3+
4+ROOT=/var/www/html
5+
6+quote() {
7+ printf "%s" "$1" | sed "s/\\\\/\\\\\\\\/g; s/'/\\\\'/g"
8+}
9+
10+cat > "$ROOT/config.local.php" <<PHP
11+<?php
12+/**
13+ * Written by the ZnoteX Docker entrypoint on every container start.
14+ * Edit docker-compose.yml environment values, not this file - it is
15+ * regenerated each time the container boots.
16+ */
17+
18+\$config['sqlHost'] = '$(quote "${ZNOTE_DB_HOST:-db}")';
19+\$config['sqlUser'] = '$(quote "${ZNOTE_DB_USER:-znotex}")';
20+\$config['sqlPassword'] = '$(quote "${ZNOTE_DB_PASSWORD:-znotex}")';
21+\$config['sqlDatabase'] = '$(quote "${ZNOTE_DB_NAME:-znotex}")';
22+
23+\$config['ServerEngine'] = '$(quote "${ZNOTE_SERVER_ENGINE:-TFS_10}")';
24+\$config['site_title'] = '$(quote "${ZNOTE_SITE_TITLE:-ZnoteX}")';
25+\$config['site_url'] = '$(quote "${ZNOTE_SITE_URL:-http://localhost:8080}")';
26+
27+\$config['mailserver'] = array(
28+ 'register' => true,
29+ 'accountRecovery' => true,
30+ 'myaccount_verify_email' => true,
31+ 'verify_email_points' => 0,
32+ 'host' => 'mailpit',
33+ 'securityType' => '',
34+ 'port' => 1025,
35+ 'email' => 'noreply@znotex.local',
36+ 'username' => '',
37+ 'password' => '',
38+ 'debug' => false,
39+ 'fromName' => \$config['site_title'],
40+);
41+
42+// Admin access is granted by account name (not character name).
43+\$config['page_admin_access'] = array(
44+ '$(quote "${ZNOTE_ADMIN_ACCOUNT:-demo}")',
45+);
46+PHP
47+
48+mkdir -p "$ROOT/install"
49+if [ ! -f "$ROOT/install/installed.lock" ]; then
50+ printf "Installed by the ZnoteX Docker entrypoint on %s\nDelete this file only if you mean to run the installer again.\n" "$(date '+%Y-%m-%d %H:%M:%S')" > "$ROOT/install/installed.lock"
51+fi
52+
53+mkdir -p "$ROOT/engine/cache" "$ROOT/engine/img/theme"
54+chown -R www-data:www-data "$ROOT/engine/cache" "$ROOT/engine/img/theme" "$ROOT/config.local.php" 2>/dev/null || true
55+
56+exec "$@"
A docker/mysql/00-init.sh +37-0 View file
@@ -0,0 +1,37 @@
1+#!/bin/sh
2+set -e
3+
4+engine=$(printf "%s" "${ZNOTE_SERVER_ENGINE:-TFS_10}" | tr '[:upper:]' '[:lower:]')
5+schema="/schemas/${engine}.sql"
6+
7+if [ ! -f "$schema" ]; then
8+ case "$engine" in
9+ tfs_02)
10+ echo "[znotex] No dedicated TFS 0.2.13+ schema is bundled; falling back to the TFS_03 schema (TFS 0.3.6+/0.4/OTX). Ultra-legacy tables some TFS_02-only pages use may be missing." >&2
11+ schema="/schemas/tfs_03.sql"
12+ ;;
13+ *)
14+ echo "[znotex] Unknown ZNOTE_SERVER_ENGINE '${ZNOTE_SERVER_ENGINE}', falling back to TFS_10." >&2
15+ schema="/schemas/tfs_10.sql"
16+ ;;
17+ esac
18+fi
19+
20+echo "[znotex] Importing game schema: $schema"
21+mysql --user=root --password="$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE" < "$schema"
22+
23+if [ "$engine" = "tfs_10" ] && [ -f /demo-data-tfs_10.sql ]; then
24+ echo "[znotex] Importing TFS_10 demo accounts/players/guild."
25+ mysql --user=root --password="$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE" < /demo-data-tfs_10.sql
26+else
27+ echo "[znotex] No demo game data for engine '$engine' - the database will have ZnoteX's own tables only, no demo accounts/characters."
28+fi
29+
30+echo "[znotex] Importing ZnoteX's own schema."
31+mysql --user=root --password="$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE" < /znote-schema.sql
32+
33+if [ "$engine" = "tfs_10" ]; then
34+ echo "[znotex] Activating the demo account."
35+ mysql --user=root --password="$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE" \
36+ -e "UPDATE znote_accounts SET active = 1, active_email = 1 WHERE account_id = 1;"
37+fi
A docker/mysql/demo-data-tfs_10.sql +19-0 View file
@@ -0,0 +1,19 @@
1+-- Demo game data for the ZnoteX Docker environment.
2+-- Login: account "demo", password "demo123". The character "Admin" is
3+-- granted admin panel access by docker/entrypoint.sh (page_admin_access).
4+
5+INSERT INTO `accounts` (`id`, `name`, `password`, `type`, `premdays`, `email`, `creation`) VALUES
6+ (1, 'demo', SHA1('demo123'), 1, 90, 'demo@znotex.local', UNIX_TIMESTAMP());
7+
8+INSERT INTO `players` (`id`, `name`, `group_id`, `account_id`, `level`, `vocation`, `health`, `healthmax`, `mana`, `manamax`, `experience`, `looktype`, `lookhead`, `lookbody`, `looklegs`, `lookfeet`, `town_id`, `conditions`, `sex`, `lastlogin`, `onlinetime`) VALUES
9+ (1, 'Admin', 3, 1, 200, 4, 4585, 4585, 3155, 3155, 698737485, 268, 78, 68, 58, 76, 1, '', 1, UNIX_TIMESTAMP(), 3600),
10+ (2, 'Rookgaard', 1, 1, 15, 1, 185, 185, 35, 35, 4200, 128, 78, 68, 58, 76, 1, '', 1, UNIX_TIMESTAMP(), 1200),
11+ (3, 'Thais Mage', 2, 1, 80, 2, 1240, 1240, 920, 920, 1520000, 138, 78, 68, 58, 76, 1, '', 0, UNIX_TIMESTAMP(), 900);
12+
13+-- The oncreate_guilds trigger auto-creates 3 guild_ranks rows for this guild,
14+-- so they are not inserted here.
15+INSERT INTO `guilds` (`id`, `name`, `ownerid`, `creationdata`, `motd`) VALUES
16+ (1, 'ZnoteX Guardians', 1, UNIX_TIMESTAMP(), 'Welcome to the demo guild.');
17+
18+INSERT INTO `guild_membership` (`player_id`, `guild_id`, `rank_id`, `nick`) VALUES
19+ (1, 1, (SELECT `id` FROM `guild_ranks` WHERE `guild_id` = 1 AND `level` = 3 LIMIT 1), '');
A docker/mysql/schemas/othire.sql +432-0 View file
@@ -0,0 +1,432 @@
1+-- OTHire database schema.
2+-- Source: https://github.com/Ezzz-dev/OTHire/blob/master/source/schema.mysql
3+-- License: GPL-2.0. Covers ZnoteX's OTHIRE engine choice.
4+
5+CREATE TABLE `groups` (
6+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
7+ `name` VARCHAR(255) NOT NULL COMMENT 'group name',
8+
9+ `flags` BIGINT UNSIGNED NOT NULL DEFAULT 0,
10+ `access` INT NOT NULL DEFAULT 0,
11+ `violation` INT NOT NULL DEFAULT 0,
12+ `maxdepotitems` INT NOT NULL,
13+ `maxviplist` INT NOT NULL,
14+
15+ PRIMARY KEY (`id`)
16+) ENGINE = InnoDB;
17+INSERT INTO `groups` VALUES (1, 'Player', 0, 0, 0, 2000, 100),(2, 'Tutor', 16777216, 0, 0, 2000, 100),(3, 'Sennior Tutor', 274894684160, 0, 0, 2000, 100),(4, 'Community Manager', 69681547968463, 2, 0, 1000, 100),(5, 'Game Master', 69681547968463, 2, 0, 1000, 100),(6, 'GOD/OWNER', 57171953819640, 3, 0, 2000, 100);
18+
19+CREATE TABLE `accounts` (
20+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
21+ `name` VARCHAR(32) NOT NULL,
22+
23+ `password` VARCHAR(255) NOT NULL/* VARCHAR(32) NOT NULL COMMENT 'MD5'*//* VARCHAR(40) NOT NULL COMMENT 'SHA1'*/,
24+ `email` VARCHAR(255) NOT NULL DEFAULT '',
25+ `premend` INT UNSIGNED NOT NULL DEFAULT 0,
26+ `blocked` TINYINT(1) NOT NULL DEFAULT FALSE,
27+ `warnings` INT NOT NULL DEFAULT 0,
28+
29+ PRIMARY KEY (`id`),
30+ UNIQUE (`name`)
31+) ENGINE = InnoDB;
32+INSERT INTO `accounts` VALUES (1, 'tibia', 'tibia', '', 0, 0, 0);
33+
34+CREATE TABLE `players` (
35+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
36+ `name` VARCHAR(255) NOT NULL,
37+ `account_id` INT UNSIGNED NOT NULL,
38+ `group_id` INT UNSIGNED NOT NULL COMMENT 'users group',
39+
40+ `sex` INT UNSIGNED NOT NULL DEFAULT 0,
41+ `vocation` INT UNSIGNED NOT NULL DEFAULT 0,
42+ `experience` BIGINT UNSIGNED NOT NULL DEFAULT 0,
43+ `level` INT UNSIGNED NOT NULL DEFAULT 1,
44+ `maglevel` INT UNSIGNED NOT NULL DEFAULT 0,
45+ `health` INT NOT NULL DEFAULT 100,
46+ `healthmax` INT NOT NULL DEFAULT 100,
47+ `mana` INT NOT NULL DEFAULT 100,
48+ `manamax` INT NOT NULL DEFAULT 100,
49+ `manaspent` INT UNSIGNED NOT NULL DEFAULT 0,
50+ `soul` INT UNSIGNED NOT NULL DEFAULT 0,
51+ `direction` INT UNSIGNED NOT NULL DEFAULT 0,
52+ `lookbody` INT UNSIGNED NOT NULL DEFAULT 10,
53+ `lookfeet` INT UNSIGNED NOT NULL DEFAULT 10,
54+ `lookhead` INT UNSIGNED NOT NULL DEFAULT 10,
55+ `looklegs` INT UNSIGNED NOT NULL DEFAULT 10,
56+ `looktype` INT UNSIGNED NOT NULL DEFAULT 136,
57+ `lookaddons` INT UNSIGNED NOT NULL DEFAULT 0,
58+ `posx` INT NOT NULL DEFAULT 0,
59+ `posy` INT NOT NULL DEFAULT 0,
60+ `posz` INT NOT NULL DEFAULT 0,
61+ `cap` INT NOT NULL DEFAULT 0,
62+ `lastlogin` INT UNSIGNED NOT NULL DEFAULT 0,
63+ `lastlogout` INT UNSIGNED NOT NULL DEFAULT 0,
64+ `lastip` INT UNSIGNED NOT NULL DEFAULT 0,
65+ `save` TINYINT(1) NOT NULL DEFAULT TRUE,
66+ `conditions` BLOB NOT NULL COMMENT 'drunk, poisoned etc',
67+ `skull_type` INT NOT NULL DEFAULT 0,
68+ `skull_time` INT UNSIGNED NOT NULL DEFAULT 0,
69+ `loss_experience` INT NOT NULL DEFAULT 100,
70+ `loss_mana` INT NOT NULL DEFAULT 100,
71+ `loss_skills` INT NOT NULL DEFAULT 100,
72+ `loss_items` INT NOT NULL DEFAULT 10,
73+ `loss_containers` INT NOT NULL DEFAULT 100,
74+ `town_id` INT NOT NULL COMMENT 'old masterpos, temple spawn point position',
75+ `balance` INT NOT NULL DEFAULT 0 COMMENT 'money balance of the player for houses paying',
76+ `stamina` INT NOT NULL DEFAULT 151200000 COMMENT 'player stamina in milliseconds',
77+ `online` TINYINT(1) NOT NULL DEFAULT 0,
78+ `rank_id` INT NOT NULL COMMENT 'only if you use __OLD_GUILD_SYSTEM__',
79+ `guildnick` VARCHAR(255) NOT NULL COMMENT 'only if you use __OLD_GUILD_SYSTEM__',
80+
81+ PRIMARY KEY (`id`),
82+ UNIQUE (`name`),
83+ KEY (`online`),
84+ FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE,
85+ FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`)
86+) ENGINE = InnoDB;
87+
88+CREATE TABLE `guilds` (
89+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
90+
91+ `name` VARCHAR(255) NOT NULL,
92+ `owner_id` INT UNSIGNED NOT NULL,
93+ `creationdate` INT NOT NULL,
94+
95+ PRIMARY KEY (`id`),
96+ UNIQUE (`name`),
97+ FOREIGN KEY (`owner_id`) REFERENCES `players` (`id`) ON DELETE CASCADE
98+) ENGINE = InnoDB;
99+
100+CREATE TABLE `guild_ranks` (
101+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
102+ `guild_id` INT UNSIGNED NOT NULL COMMENT 'guild',
103+
104+ `name` VARCHAR(255) NOT NULL COMMENT 'rank name',
105+ `level` INT NOT NULL COMMENT 'rank level - leader, vice leader, member, maybe something else',
106+
107+ PRIMARY KEY (`id`),
108+ FOREIGN KEY (`guild_id`) REFERENCES `guilds` (`id`) ON DELETE CASCADE
109+) ENGINE = InnoDB;
110+
111+CREATE TABLE `guild_members` (
112+ `player_id` INT UNSIGNED NOT NULL COMMENT 'if you doesnt use new guild system you are free to delete this table',
113+ `rank_id` INT UNSIGNED NOT NULL COMMENT 'a rank which belongs to certain guild',
114+
115+ `nick` VARCHAR(255) NOT NULL DEFAULT '',
116+
117+ UNIQUE (`player_id`),
118+ FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE,
119+ FOREIGN KEY (`rank_id`) REFERENCES `guild_ranks` (`id`) ON DELETE CASCADE
120+) ENGINE = InnoDB;
121+
122+CREATE TABLE `guild_invites` (
123+ `player_id` INT UNSIGNED NOT NULL,
124+ `guild_id` INT UNSIGNED NOT NULL COMMENT 'guild',
125+
126+ UNIQUE (`player_id`),
127+ FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE,
128+ FOREIGN KEY (`guild_id`) REFERENCES `guilds` (`id`) ON DELETE CASCADE
129+) ENGINE = InnoDB;
130+
131+CREATE TABLE `guild_wars` (
132+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
133+ `guild_id` INT UNSIGNED NOT NULL COMMENT 'the guild which declared the war',
134+ `opponent_id` INT UNSIGNED NOT NULL COMMENT 'the enemy guild at war',
135+
136+ `frag_limit` INT UNSIGNED NOT NULL DEFAULT 10 COMMENT 'kills needed to win the war',
137+ `declaration_date` INT UNSIGNED NOT NULL,
138+ `end_date` INT UNSIGNED NOT NULL,
139+ `guild_fee` INT UNSIGNED NOT NULL DEFAULT 1000 COMMENT 'amount of money the guild has to pay if loses the war',
140+ `opponent_fee` INT UNSIGNED NOT NULL DEFAULT 1000 COMMENT 'amount of money the enemy guild has to pay if loses the war',
141+ `guild_frags` INT UNSIGNED NOT NULL DEFAULT 0,
142+ `opponent_frags` INT UNSIGNED NOT NULL DEFAULT 0,
143+ `comment` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'the guild leader can leave a message for the other guild',
144+ `status` INT NOT NULL DEFAULT 0 COMMENT '-1 -> will be ignored (finished or unaccepted) 0 -> to be started 1 -> started/not finished',
145+
146+ PRIMARY KEY (`id`),
147+ FOREIGN KEY (`guild_id`) REFERENCES `guilds` (`id`) ON DELETE CASCADE,
148+ FOREIGN KEY (`opponent_id`) REFERENCES `guilds` (`id`) ON DELETE CASCADE
149+) ENGINE = InnoDB;
150+
151+CREATE TABLE `player_viplist` (
152+ `player_id` INT UNSIGNED NOT NULL COMMENT 'id of player whose viplist entry it is',
153+ `vip_id` INT UNSIGNED NOT NULL COMMENT 'id of target player of viplist entry',
154+
155+ FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE,
156+ FOREIGN KEY (`vip_id`) REFERENCES `players` (`id`) ON DELETE CASCADE
157+) ENGINE = InnoDB;
158+
159+CREATE TABLE `player_spells` (
160+ `player_id` INT UNSIGNED NOT NULL,
161+ `name` VARCHAR(255) NOT NULL,
162+
163+ FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE
164+) ENGINE = InnoDB;
165+
166+CREATE TABLE `player_storage` (
167+ `player_id` INT UNSIGNED NOT NULL,
168+ `key` INT NOT NULL,
169+ `value` INT NOT NULL,
170+
171+ FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE
172+) ENGINE = InnoDB;
173+
174+CREATE TABLE `player_skills` (
175+ `player_id` INT UNSIGNED NOT NULL,
176+
177+ `skillid` INT UNSIGNED NOT NULL,
178+ `value` INT UNSIGNED NOT NULL DEFAULT 0,
179+ `count` INT UNSIGNED NOT NULL DEFAULT 0,
180+
181+ FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE
182+) ENGINE = InnoDB;
183+
184+CREATE TABLE `player_items` (
185+ `player_id` INT UNSIGNED NOT NULL,
186+ `sid` INT NOT NULL,
187+ `pid` INT NOT NULL DEFAULT 0,
188+ `itemtype` INT NOT NULL,
189+ `count` INT NOT NULL DEFAULT 0,
190+ `attributes` BLOB COMMENT 'replaces unique_id, action_id, text, special_desc',
191+
192+ FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE,
193+ UNIQUE (`player_id`, `sid`)
194+) ENGINE = InnoDB;
195+
196+CREATE TABLE `houses` (
197+ `id` INT UNSIGNED NOT NULL,
198+ `townid` INT UNSIGNED NOT NULL DEFAULT 0,
199+
200+ `name` VARCHAR(100) NOT NULL,
201+ `rent` INT UNSIGNED NOT NULL DEFAULT 0,
202+ `guildhall` TINYINT(1) NOT NULL DEFAULT 0,
203+ `tiles` INT UNSIGNED NOT NULL DEFAULT 0,
204+ `doors` INT UNSIGNED NOT NULL DEFAULT 0,
205+ `beds` INT UNSIGNED NOT NULL DEFAULT 0,
206+ `owner` INT NOT NULL DEFAULT 0,
207+ `paid` INT UNSIGNED NOT NULL DEFAULT 0,
208+ `clear` TINYINT(1) NOT NULL DEFAULT 0,
209+ `warnings` INT NOT NULL DEFAULT 0,
210+ `lastwarning` INT UNSIGNED NOT NULL DEFAULT 0,
211+
212+ PRIMARY KEY (`id`)
213+) ENGINE = InnoDB;
214+
215+CREATE TABLE `house_auctions` (
216+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
217+ `house_id` INT UNSIGNED NOT NULL,
218+ `player_id` INT UNSIGNED NOT NULL,
219+
220+ `bid` INT UNSIGNED NOT NULL DEFAULT 0,
221+ `limit` INT UNSIGNED NOT NULL DEFAULT 0,
222+ `endtime` INT UNSIGNED NOT NULL DEFAULT 0,
223+
224+ FOREIGN KEY (`house_id`) REFERENCES `houses` (`id`) ON DELETE CASCADE,
225+ FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE,
226+ PRIMARY KEY (`id`)
227+) ENGINE = InnoDB;
228+
229+CREATE TABLE `house_lists` (
230+ `house_id` INT UNSIGNED NOT NULL,
231+ `listid` INT NOT NULL,
232+ `list` TEXT NOT NULL,
233+
234+ FOREIGN KEY (`house_id`) REFERENCES `houses` (`id`) ON DELETE CASCADE
235+) ENGINE = InnoDB;
236+
237+CREATE TABLE `bans` (
238+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
239+ `type` INT NOT NULL COMMENT 'this field defines if its ip, account, player, or any else ban',
240+ `value` INT UNSIGNED NOT NULL COMMENT 'ip, player guid, account number',
241+ `param` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'mask',
242+ `active` TINYINT(1) NOT NULL DEFAULT TRUE,
243+ `expires` INT NOT NULL,
244+ `added` INT UNSIGNED NOT NULL,
245+ `admin_id` INT UNSIGNED,
246+ `comment` VARCHAR(1024) NOT NULL DEFAULT '',
247+ `reason` INT UNSIGNED NOT NULL DEFAULT 0,
248+ `action` INT UNSIGNED NOT NULL DEFAULT 0,
249+ `statement` VARCHAR(255) NOT NULL DEFAULT '',
250+
251+ PRIMARY KEY (`id`),
252+ KEY (`type`, `value`),
253+ KEY (`expires`),
254+ FOREIGN KEY (`admin_id`) REFERENCES `players` (`id`) ON DELETE SET NULL
255+) ENGINE = InnoDB;
256+
257+CREATE TABLE `tiles` (
258+ `id` INT UNSIGNED NOT NULL,
259+ `house_id` INT UNSIGNED NOT NULL DEFAULT 0,
260+ `x` INT(5) UNSIGNED NOT NULL,
261+ `y` INT(5) UNSIGNED NOT NULL,
262+ `z` INT(2) UNSIGNED NOT NULL,
263+
264+ PRIMARY KEY(`id`),
265+ KEY(`x`, `y`, `z`),
266+ FOREIGN KEY (`house_id`) REFERENCES `houses` (`id`) ON DELETE NO ACTION
267+) ENGINE = InnoDB;
268+
269+CREATE TABLE `tile_items` (
270+ `tile_id` INT UNSIGNED NOT NULL,
271+ `sid` INT NOT NULL,
272+ `pid` INT NOT NULL DEFAULT 0,
273+ `itemtype` INT NOT NULL,
274+ `count` INT NOT NULL DEFAULT 0,
275+ `attributes` BLOB NOT NULL,
276+
277+ INDEX (`sid`),
278+ FOREIGN KEY (`tile_id`) REFERENCES `tiles` (`id`) ON DELETE CASCADE
279+) ENGINE = InnoDB;
280+
281+CREATE TABLE `map_store` (
282+ `house_id` INT UNSIGNED NOT NULL,
283+ `data` LONGBLOB NOT NULL,
284+
285+ KEY(`house_id`)
286+) ENGINE = InnoDB;
287+
288+CREATE TABLE `player_deaths` (
289+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
290+ `player_id` INT UNSIGNED NOT NULL,
291+ `date` INT UNSIGNED NOT NULL,
292+ `level` INT NOT NULL,
293+
294+ FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE,
295+ PRIMARY KEY(`id`),
296+ INDEX(`date`)
297+) ENGINE = InnoDB;
298+
299+CREATE TABLE `killers` (
300+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
301+ `death_id` INT UNSIGNED NOT NULL,
302+ `final_hit` TINYINT(1) NOT NULL DEFAULT 1,
303+
304+ PRIMARY KEY(`id`),
305+ FOREIGN KEY (`death_id`) REFERENCES `player_deaths` (`id`) ON DELETE CASCADE
306+) ENGINE = InnoDB;
307+
308+CREATE TABLE `environment_killers` (
309+ `kill_id` INT UNSIGNED NOT NULL,
310+ `name` VARCHAR(255) NOT NULL,
311+
312+ PRIMARY KEY (`kill_id`, `name`),
313+ FOREIGN KEY (`kill_id`) REFERENCES `killers` (`id`) ON DELETE CASCADE
314+) ENGINE = InnoDB;
315+
316+CREATE TABLE `player_killers` (
317+ `kill_id` INT UNSIGNED NOT NULL,
318+ `player_id` INT UNSIGNED NOT NULL,
319+ `unjustified` TINYINT(1) NOT NULL DEFAULT 0,
320+
321+ PRIMARY KEY (`kill_id`, `player_id`),
322+ FOREIGN KEY (`kill_id`) REFERENCES `killers` (`id`) ON DELETE CASCADE,
323+ FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE
324+) ENGINE = InnoDB;
325+
326+CREATE TABLE `player_depotitems` (
327+ `player_id` INT UNSIGNED NOT NULL,
328+ `sid` INT NOT NULL COMMENT 'any given range eg 0-100 will be reserved for depot lockers and all > 100 will be then normal items inside depots',
329+ `pid` INT NOT NULL DEFAULT 0,
330+ `itemtype` INT NOT NULL,
331+ `count` INT NOT NULL DEFAULT 0,
332+ `attributes` BLOB NOT NULL,
333+
334+ FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE,
335+ UNIQUE (`player_id`, `sid`)
336+) ENGINE = InnoDB;
337+
338+CREATE TABLE `market_offers` (
339+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
340+ `player_id` INT UNSIGNED NOT NULL,
341+
342+ `sale` TINYINT(1) NOT NULL DEFAULT 0,
343+ `itemtype` INT NOT NULL,
344+ `amount` INT NOT NULL,
345+
346+ `created` INT NOT NULL,
347+ `anonymous` TINYINT(1) DEFAULT 0,
348+ `price` INT NOT NULL DEFAULT 0,
349+
350+ PRIMARY KEY (`id`),
351+ KEY (`sale`, `itemtype`),
352+ KEY (`created`),
353+ FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE
354+) ENGINE = InnoDB;
355+
356+CREATE TABLE `market_statistics` (
357+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
358+
359+ `sale` TINYINT(1) NOT NULL,
360+ `itemtype` INT NOT NULL,
361+ `price` INT NOT NULL,
362+ `amount` INT NOT NULL,
363+ `when` INT NOT NULL,
364+
365+ PRIMARY KEY(`id`),
366+ KEY(`sale`, `itemtype`, `when`)
367+) ENGINE = InnoDB;
368+
369+CREATE TABLE `global_storage` (
370+ `key` INT UNSIGNED NOT NULL,
371+ `value` INT NOT NULL,
372+
373+ PRIMARY KEY(`key`)
374+) ENGINE = InnoDB;
375+
376+CREATE TABLE `schema_info` (
377+ `name` VARCHAR(255) NOT NULL,
378+ `value` VARCHAR(255) NOT NULL,
379+
380+ PRIMARY KEY (`name`)
381+) ENGINE = InnoDB;
382+
383+INSERT INTO `schema_info` (`name`, `value`) VALUES ('version', 24);
384+
385+DELIMITER |
386+
387+CREATE TRIGGER `ondelete_accounts`
388+BEFORE DELETE
389+ON `accounts`
390+FOR EACH ROW
391+BEGIN
392+ DELETE FROM `bans` WHERE `type` = 3 AND `value` = OLD.`id`;
393+END|
394+
395+CREATE TRIGGER `ondelete_players`
396+BEFORE DELETE
397+ON `players`
398+FOR EACH ROW
399+BEGIN
400+ DELETE FROM `bans` WHERE `type` = 2 AND `value` = OLD.`id`;
401+ UPDATE `houses` SET `owner` = 0 WHERE `owner` = OLD.`id`;
402+END|
403+
404+CREATE TRIGGER `oncreate_guilds`
405+AFTER INSERT
406+ON `guilds`
407+FOR EACH ROW
408+BEGIN
409+ INSERT INTO `guild_ranks` (`name`, `level`, `guild_id`) VALUES ('Leader', 3, NEW.`id`);
410+ INSERT INTO `guild_ranks` (`name`, `level`, `guild_id`) VALUES ('Vice-Leader', 2, NEW.`id`);
411+ INSERT INTO `guild_ranks` (`name`, `level`, `guild_id`) VALUES ('Member', 1, NEW.`id`);
412+END|
413+
414+CREATE TRIGGER `oncreate_players`
415+AFTER INSERT
416+ON `players`
417+FOR EACH ROW
418+BEGIN
419+ INSERT INTO `player_skills` (`player_id`, `skillid`, `value`) VALUES (NEW.`id`, 0, 10);
420+ INSERT INTO `player_skills` (`player_id`, `skillid`, `value`) VALUES (NEW.`id`, 1, 10);
421+ INSERT INTO `player_skills` (`player_id`, `skillid`, `value`) VALUES (NEW.`id`, 2, 10);
422+ INSERT INTO `player_skills` (`player_id`, `skillid`, `value`) VALUES (NEW.`id`, 3, 10);
423+ INSERT INTO `player_skills` (`player_id`, `skillid`, `value`) VALUES (NEW.`id`, 4, 10);
424+ INSERT INTO `player_skills` (`player_id`, `skillid`, `value`) VALUES (NEW.`id`, 5, 10);
425+ INSERT INTO `player_skills` (`player_id`, `skillid`, `value`) VALUES (NEW.`id`, 6, 10);
426+END|
427+
428+DELIMITER ;
429+INSERT INTO `players` VALUES (1, 'Administrator', 1, 6, 2, 1, 0, 1, 0, 185, 185, 35, 35, 0, 100, 2, 10, 10, 10, 10, 75, 0, 200, 200, 6, 435, 0, 0, 1, 1, '', 0, 0, 100, 100, 100, 10, 100, 1, 0, 151200000, 0, 0, '');
430+INSERT INTO `players` VALUES (2, 'Player', 1, 1, 1, 1, 0, 1, 0, 185, 185, 35, 35, 0, 100, 2, 10, 10, 10, 10, 75, 0, 200, 200, 6, 435, 0, 0, 1, 1, '', 0, 0, 100, 100, 100, 10, 100, 1, 0, 151200000, 0, 0, '');
431+
432+# to add your own privileges for players/gms please use this flag generator http://hem.bredband.net/johannesrosen/playerflags.html
Top