diff --git a/system/compat/config.php b/system/compat/config.php
index 4fc3004a..5476c52e 100644
--- a/system/compat/config.php
+++ b/system/compat/config.php
@@ -5,8 +5,6 @@ $deprecatedConfig = [
'genders',
'template',
'template_allow_change',
- 'vocations_amount',
- 'vocations',
'client',
'session_prefix',
'friendly_urls',
diff --git a/system/init.php b/system/init.php
index 862b5370..d5767eb8 100644
--- a/system/init.php
+++ b/system/init.php
@@ -14,6 +14,7 @@ use MyAAC\CsrfToken;
use MyAAC\Hooks;
use MyAAC\Plugins;
use MyAAC\Models\Town;
+use MyAAC\Server\XML\Vocations;
use MyAAC\Settings;
defined('MYAAC') or die('Direct access not allowed!');
@@ -214,3 +215,5 @@ if (count($towns) <= 0) {
config(['towns', $towns]);
unset($towns);
+
+new Vocations();
diff --git a/system/libs/pot/OTS_Player.php b/system/libs/pot/OTS_Player.php
index 099f5db1..fbd77aac 100644
--- a/system/libs/pot/OTS_Player.php
+++ b/system/libs/pot/OTS_Player.php
@@ -852,13 +852,7 @@ class OTS_Player extends OTS_Row_DAO
throw new E_OTS_NotLoaded();
}
- if(isset($this->data['promotion'])) {
- global $config;
- if((int)$this->data['promotion'] > 0)
- return ($this->data['vocation'] + ($this->data['promotion'] * $config['vocations_amount']));
- }
-
- return $this->data['vocation'];
+ return \OTS_Toolbox::getVocationFromPromotion($this->data['vocation'], $this->data['promotion'] ?? 0);
}
diff --git a/system/libs/pot/OTS_Toolbox.php b/system/libs/pot/OTS_Toolbox.php
index 575dba6f..2b587ca1 100644
--- a/system/libs/pot/OTS_Toolbox.php
+++ b/system/libs/pot/OTS_Toolbox.php
@@ -13,6 +13,8 @@
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU Lesser General Public License, Version 3
*/
+use MyAAC\Server\XML\Vocations;
+
/**
* Toolbox for common operations.
*
@@ -110,14 +112,21 @@ class OTS_Toolbox
$list->setFilter($filter);
return $list;
}
-
- public static function getVocationName($id, $promotion = 0): string
+ public static function getVocationFromPromotion($id, $promotion = 0): int
{
if($promotion > 0) {
- $id = ($id + ($promotion * config('vocations_amount')));
+ for ($i = 0; $i < $promotion; $i++) {
+ if ($_id = Vocations::getPromoted($id)) {
+ $id = $_id;
+ }
+ }
}
- return config('vocations')[$id] ?? 'Unknown';
+ return $id;
+ }
+
+ public static function getVocationName($id, $promotion = 0): string {
+ return config('vocations')[self::getVocationFromPromotion($id, $promotion)] ?? 'Unknown';
}
}
diff --git a/system/pages/characters.php b/system/pages/characters.php
index b88368ff..2f03884b 100644
--- a/system/pages/characters.php
+++ b/system/pages/characters.php
@@ -452,10 +452,8 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
if($query->rowCount() > 0) {
echo 'Did you mean:
';
foreach($query as $player) {
- if(isset($player['promotion'])) {
- if((int)$player['promotion'] > 0)
- $player['vocation'] += ($player['promotion'] * $config['vocations_amount']);
- }
+ $player['vocation'] = OTS_Toolbox::getVocationFromPromotion($player['vocation'], $player['promotion'] ?? 0);
+
echo '- ' . getPlayerLink($player['name']) . ' (level ' . $player['level'] . ', ' . $config['vocations'][$player['vocation']] . ')
';
}
echo '
';
diff --git a/system/pages/highscores.php b/system/pages/highscores.php
index 79d4feee..cf8e6cb7 100644
--- a/system/pages/highscores.php
+++ b/system/pages/highscores.php
@@ -13,6 +13,7 @@ use MyAAC\Cache\Cache;
use MyAAC\Models\Player;
use MyAAC\Models\PlayerDeath;
use MyAAC\Models\PlayerKillers;
+use MyAAC\Server\XML\Vocations;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Highscores';
@@ -35,24 +36,20 @@ if(!is_numeric($page) || $page < 1 || $page > PHP_INT_MAX) {
$query = Player::query();
$configVocations = config('vocations');
-$configVocationsAmount = config('vocations_amount');
$vocationId = null;
if($vocation !== 'all') {
foreach($configVocations as $id => $name) {
if(strtolower($name) == $vocation) {
$vocationId = $id;
- $add_vocs = [$id];
+ $filterVocations = [$id];
- if ($id !== 0) {
- $i = $id + $configVocationsAmount;
- while (isset($configVocations[$i])) {
- $add_vocs[] = $i;
- $i += $configVocationsAmount;
- }
+ while($tmpVoc = Vocations::getPromoted($id)) {
+ $id = $tmpVoc;
+ $filterVocations[] = $tmpVoc;
}
- $query->whereIn('players.vocation', $add_vocs);
+ $query->whereIn('players.vocation', $filterVocations);
break;
}
}
@@ -325,4 +322,5 @@ $twig->display('highscores.html.twig', [
'page' => $page,
'baseLink' => $baseLink,
'updatedAt' => $updatedAt,
+ 'baseVocations' => Vocations::getBase(true),
]);
diff --git a/system/pages/online.php b/system/pages/online.php
index 21f2ee0d..c68fd619 100644
--- a/system/pages/online.php
+++ b/system/pages/online.php
@@ -12,6 +12,7 @@
use MyAAC\Cache\Cache;
use MyAAC\Models\ServerConfig;
use MyAAC\Models\ServerRecord;
+use MyAAC\Server\XML\Vocations;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Who is online?';
@@ -56,15 +57,14 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60
$vocations = array_map(function ($name) {
return 0;
- }, setting('core.vocations'));
+ }, config('vocations'));
if($db->hasTable('players_online')) // tfs 1.0
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql);
else
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql);
- $settingVocations = setting('core.vocations');
- $settingVocationsAmount = setting('core.vocations_amount');
+ $configVocations = config('vocations');
$players = [];
foreach($playersOnline as $player) {
@@ -81,22 +81,19 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60
}
}
- if(isset($player['promotion'])) {
- if((int)$player['promotion'] > 0)
- $player['vocation'] += ($player['promotion'] * $settingVocationsAmount);
- }
+ $player['vocation'] = OTS_Toolbox::getVocationFromPromotion($player['vocation'], $player['promotion'] ?? 0);
$players[] = array(
'name' => getPlayerLink($player['name']),
'player' => $player,
'level' => $player['level'],
- 'vocation' => $settingVocations[$player['vocation']],
+ 'vocation' => $configVocations[$player['vocation']],
'skull' => $skull,
'country_image' => getFlagImage($player['country']),
'outfit' => setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'],
);
- $vocations[($player['vocation'] > $settingVocationsAmount ? $player['vocation'] - $settingVocationsAmount : $player['vocation'])]++;
+ $vocations[Vocations::getOriginal($player['vocation'])]++;
}
$record = '';
@@ -142,6 +139,7 @@ $twig->display('online.html.twig', array(
'vocations' => $cached['vocations'],
'vocs' => $cached['vocations'], // deprecated, to be removed
'order' => $order,
+ 'baseVocations' => Vocations::getBase(false),
));
// search bar
diff --git a/system/settings.php b/system/settings.php
index 6de908ce..614b07ac 100644
--- a/system/settings.php
+++ b/system/settings.php
@@ -319,23 +319,6 @@ return [
},
],
],
- 'vocations_amount' => [
- 'name' => 'Vocations Amount',
- 'type' => 'number',
- 'desc' => 'How much basic vocations your server got (without promotion)',
- 'default' => 4,
- ],
- 'vocations' => [
- 'name' => 'Vocation Names',
- 'type' => 'textarea',
- 'desc' => 'Separated by comma. Must be in the same order as in vocations.xml, starting with id: 0.',
- 'default' => 'None, Sorcerer, Druid, Paladin, Knight, Master Sorcerer, Elder Druid,Royal Paladin, Elite Knight',
- 'callbacks' => [
- 'get' => function ($value) {
- return array_map('trim', explode(',', $value));
- },
- ],
- ],
[
'type' => 'category',
'title' => 'Database',
diff --git a/system/src/Models/Player.php b/system/src/Models/Player.php
index 77fe4504..479967c8 100644
--- a/system/src/Models/Player.php
+++ b/system/src/Models/Player.php
@@ -46,14 +46,8 @@ class Player extends Model {
});
}
- public function getVocationNameAttribute()
- {
- $vocation = $this->vocation;
- if (isset($this->promotion) && $this->promotion > 0) {
- $vocation += ($this->promotion * setting('core.vocations_amount'));
- }
-
- return config('vocations')[$vocation] ?? 'Unknown';
+ public function getVocationNameAttribute() {
+ return \OTS_Toolbox::getVocationName($this->vocation, $this->promotion ?? 0);
}
public function getIsDeletedAttribute()
diff --git a/system/src/Server/XML/Vocations.php b/system/src/Server/XML/Vocations.php
new file mode 100644
index 00000000..6bd8f357
--- /dev/null
+++ b/system/src/Server/XML/Vocations.php
@@ -0,0 +1,93 @@
+load();
+ $from = $this->getFrom();
+
+ $amount = 0;
+ foreach ($from as $vocId => $fromVocation) {
+ if ($vocId != 0 && $vocId == $fromVocation) {
+ $amount++;
+ }
+ }
+
+ return ['vocations' => $this->get(), 'vocationsFrom' => $from, 'amount' => $amount];
+ });
+
+ self::$vocations = $cached['vocations'];
+ self::$vocationsFrom = $cached['vocationsFrom'];
+
+ config(['vocations', self::$vocations]);
+ config(['vocations_amount', $cached['amount']]);
+ }
+
+ public function load(): void
+ {
+ if(!class_exists('DOMDocument')) {
+ throw new \RuntimeException('Please install PHP xml extension. MyAAC will not work without it.');
+ }
+
+ $vocationsXML = new \DOMDocument();
+ $file = config('data_path') . 'XML/vocations.xml';
+ if(!@file_exists($file)) {
+ $file = config('data_path') . 'vocations.xml';
+ }
+
+ if(!$vocationsXML->load($file)) {
+ throw new \RuntimeException('ERROR: Cannot load vocations.xml - the file is malformed. Check the file with xml syntax validator.');
+ }
+
+ foreach($vocationsXML->getElementsByTagName('vocation') as $vocation) {
+ $id = $vocation->getAttribute('id');
+
+ self::$vocations[$id] = $vocation->getAttribute('name');
+
+ $fromVocation = (int) $vocation->getAttribute('fromvoc');
+ self::$vocationsFrom[$id] = $fromVocation;
+ }
+ }
+
+ public static function get(): array {
+ return self::$vocations;
+ }
+
+ public static function getFrom(): array {
+ return self::$vocationsFrom;
+ }
+
+ public static function getPromoted(int $id): ?int {
+ foreach (self::$vocationsFrom as $vocId => $fromVocation) {
+ if ($id == $fromVocation && $vocId != $id) {
+ return $vocId;
+ }
+ }
+
+ return null;
+ }
+
+ public static function getOriginal(int $id): ?int {
+ return self::$vocationsFrom[$id] ?? null;
+ }
+
+ public static function getBase($includingRook = true): array {
+ $vocations = [];
+ foreach (self::$vocationsFrom as $vocId => $fromVoc) {
+ if ($vocId == $fromVoc && ($vocId != 0 || $includingRook)) {
+ $vocations[] = $vocId;
+ }
+ }
+
+ return $vocations;
+ }
+}
diff --git a/system/templates/highscores.html.twig b/system/templates/highscores.html.twig
index 88bf579b..a22cacb0 100644
--- a/system/templates/highscores.html.twig
+++ b/system/templates/highscores.html.twig
@@ -18,7 +18,7 @@
@@ -120,7 +120,7 @@
[ALL]
- {% for i in 0..config.vocations_amount %}
+ {% for i in baseVocations %}
{{ config.vocations[i]}}
{% endfor %}
|
diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig
index 6f798740..71dfa4f2 100644
--- a/system/templates/online.html.twig
+++ b/system/templates/online.html.twig
@@ -10,22 +10,19 @@
{% if setting('core.online_vocations_images') %}
-  |
-  |
-  |
-  |
+ {% for vocationId in baseVocations %}
+ [vocationId]|lower }}.png) |
+ {% endfor %}
- | Sorcerers |
- Druids |
- Paladins |
- Knights |
+ {% for vocationId in baseVocations %}
+ {{ config('vocations')[vocationId] }}s |
+ {% endfor %}
- | {{ vocs[1] }} |
- {{ vocs[2] }} |
- {{ vocs[3] }} |
- {{ vocs[4] }} |
+ {% for vocationId in baseVocations %}
+ {{ vocs[vocationId] }} |
+ {% endfor %}
@@ -35,11 +32,14 @@
Vocation statistics |
- {% for i in 1..config.vocations_amount %}
-
- | {{ config.vocations[i] }} |
- {{ vocs[i] }} |
-
+ {% set i = 0 %}
+ {% for vocationId in baseVocations %}
+
+ | {{ config.vocations[vocationId] }} |
+ {{ vocs[vocationId] }} |
+
+
+ {% set i = i + 1 %}
{% endfor %}