Merge branch 'develop' into feature/refactor-account-lost

This commit is contained in:
slawkens
2026-01-04 13:14:33 +01:00
46 changed files with 420 additions and 205 deletions

View File

@@ -5,8 +5,6 @@ $deprecatedConfig = [
'genders',
'template',
'template_allow_change',
'vocations_amount',
'vocations',
'client',
'session_prefix',
'friendly_urls',

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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';
}
}

View File

@@ -22,7 +22,7 @@ csrfProtect();
$new_password = $_POST['new_password'] ?? null;
$new_password_confirm = $_POST['new_password_confirm'] ?? null;
$old_password = $_POST['old_password'] ?? null;
if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) {
if(is_null($new_password) && is_null($new_password_confirm) && is_null($old_password)) {
$twig->display('account.change-password.html.twig');
}
else {

View File

@@ -48,7 +48,7 @@ else
$account_logged->setCustomField('key', $new_rec_key);
$account_logged->setCustomField(setting('core.donate_column'), $account_logged->getCustomField(setting('core.donate_column')) - setting('core.account_generate_new_reckey_price'));
$account_logged->logAction('Generated new recovery key for ' . setting('core.account_generate_new_reckey_price') . ' premium points.');
$message = '<br />Your recovery key were send on email address <b>'.$account_logged->getEMail().'</b> for '.setting('core.account_generate_new_reckey_price').' premium points.';
$message = '<br />Your recovery key was sent on email address <b>'.$account_logged->getEMail().'</b> for '.setting('core.account_generate_new_reckey_price').' premium points.';
}
else
$message = '<br /><p class="error">An error occurred while sending email ( <b>'.$account_logged->getEMail().'</b> ) with recovery key! Recovery key not changed. Try again later. For Admin: More info can be found in system/logs/mailer-error.log</p>';

View File

@@ -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:<ul>';
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 '<li>' . getPlayerLink($player['name']) . ' (<small><strong>level ' . $player['level'] . ', ' . $config['vocations'][$player['vocation']] . '</strong></small>)</li>';
}
echo '</ul>';

View File

@@ -42,35 +42,12 @@ for($i = 0; $i < $threads_count['threads_count'] / setting('core.forum_threads_p
$links_to_pages .= '<b>'.($i + 1).' </b>';
}
echo '<a href="' . getLink('forum') . '">Boards</a> >> <b>'.$sections[$section_id]['name'].'</b>';
if($logged && (!$sections[$section_id]['closed'] || Forum::isModerator())) {
echo '<br /><br />
<a href="' . getLink('forum') . '?action=new_thread&section_id='.$section_id.'"><img src="images/forum/topic.gif" border="0" /></a>';
}
echo '<br /><br />Page: '.$links_to_pages.'<br />';
$last_threads = $db->query("SELECT `players`.`id` as `player_id`, `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`first_post`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`id`, `" . FORUM_TABLE_PREFIX . "forum`.`last_post`, `" . FORUM_TABLE_PREFIX . "forum`.`replies`, `" . FORUM_TABLE_PREFIX . "forum`.`views`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`section` = ".$section_id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = `" . FORUM_TABLE_PREFIX . "forum`.`id` ORDER BY `" . FORUM_TABLE_PREFIX . "forum`.`last_post` DESC LIMIT ".setting('core.forum_threads_per_page')." OFFSET ".($_page * setting('core.forum_threads_per_page')))->fetchAll(PDO::FETCH_ASSOC);
if(isset($last_threads[0])) {
echo '<table width="100%">
<tr bgcolor="'.$config['vdarkborder'].'" align="center">
<td class="white">
<span style="font-size: 10px"><b>Thread</b></span></td>
<td><span style="font-size: 10px"><b>Thread Starter</b></span></td>
<td><span style="font-size: 10px"><b>Replies</b></span></td>
<td><span style="font-size: 10px"><b>Views</b></span></td>
<td><span style="font-size: 10px"><b>Last Post</b></span></td>
</tr>';
$threads = [];
if(count($last_threads) > 0) {
$player = new OTS_Player();
foreach($last_threads as $thread) {
echo '<tr bgcolor="' . getStyle($number_of_rows++) . '"><td>';
if(Forum::isModerator()) {
echo '<a href="' . getLink('forum') . '?action=move_thread&id=' . $thread['id'] . '" title="Move Thread"><img src="images/icons/arrow_right.gif"/></a>';
$twig->display('forum.remove_post.html.twig', ['post' => $thread]);
}
$player->load($thread['player_id']);
if(!$player->isLoaded()) {
throw new RuntimeException('Forum error: Player not loaded.');
@@ -79,28 +56,29 @@ if(isset($last_threads[0])) {
$player_account = $player->getAccount();
$canEditForum = $player_account->hasFlag(FLAG_CONTENT_FORUM) || $player_account->isAdmin();
echo '<a href="' . getForumThreadLink($thread['id']) . '">'.htmlspecialchars($thread['post_topic']). '</a><br /><small>'.($canEditForum ? substr(strip_tags($thread['post_text']), 0, 50) : htmlspecialchars(substr($thread['post_text'], 0, 50))).'...</small></td><td>' . getPlayerLink($thread['name']) . '</td><td>'.(int) $thread['replies'].'</td><td>'.(int) $thread['views'].'</td><td>';
$thread['link'] = getForumThreadLink($thread['id']);
$thread['post_shortened'] = ($canEditForum ? substr(strip_tags($thread['post_text']), 0, 50) : htmlspecialchars(substr($thread['post_text'], 0, 50)));
$thread['player'] = $player;
$thread['player_link'] = getPlayerLink($thread['name']);
if($thread['last_post'] > 0) {
$last_post = $db->query("SELECT `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $thread['id']." AND `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` ORDER BY `post_date` DESC LIMIT 1")->fetch();
if(isset($last_post['name'])) {
echo date('d.m.y H:i:s', $last_post['post_date']) . '<br />by ' . getPlayerLink($last_post['name']);
}
else {
echo 'No posts.';
}
$last_post['player_link'] = getPlayerLink($last_post['name']);
$thread['latest_post'] = $last_post;
}
else {
echo date('d.m.y H:i:s', $thread['post_date']) . '<br />by ' . getPlayerLink($thread['name']);
}
echo '</td></tr>';
}
echo '</table>';
if($logged && (!$sections[$section_id]['closed'] || Forum::isModerator())) {
echo '<br /><a href="' . getLink('forum') . '?action=new_thread&section_id=' . $section_id . '"><img src="images/forum/topic.gif" border="0" /></a>';
$threads[] = $thread;
}
}
else {
echo '<h3>No threads in this board.</h3>';
}
$twig->display('forum.show_board.html.twig', [
'threads' => $threads,
'section_id' => $section_id,
'section_name' => $sections[$section_id]['name'],
'links_to_pages' => $links_to_pages,
'is_moderator' => Forum::isModerator(),
'closed' => $sections[$section_id]['closed'],
]);

View File

@@ -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),
]);

View File

@@ -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

View File

@@ -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',

View File

@@ -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()

View File

@@ -0,0 +1,93 @@
<?php
namespace MyAAC\Server\XML;
use MyAAC\Cache\Cache;
class Vocations
{
private static array $vocations;
private static array $vocationsFrom;
public function __construct()
{
$cached = Cache::remember('vocations', 10 * 60, function () {
$this->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 <i>vocations.xml</i> - 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;
}
}

View File

@@ -184,11 +184,11 @@ class Settings implements \ArrayAccess
}
?>
<h3 id="row_<?= $key ?>" style="text-align: center"><strong><?= $setting['title']; ?></strong></h3>
<table class="table table-bordered table-striped">
<table class="table table-bordered table-striped table-responsive d-md-table">
<thead>
<tr>
<th style="width: 13%">Name</th>
<th style="width: 30%">Value</th>
<th style="width: 30%; min-width: 200px">Value</th>
<th>Description</th>
</tr>
</thead>

View File

@@ -5,18 +5,18 @@ Please enter your password and the new email address. Make sure that you enter a
<table style="width:100%;">
<tr>
<td class="LabelV" >
<span>New Email Address:</span>
<label for="new_email">New Email Address:</label>
</td>
<td style="width:90%;">
<input form="form" name="new_email" value="{% if new_email is defined %}{{ new_email }}{% endif %}" size="30" maxlength="50" autofocus/>
<input form="form" id="new_email" name="new_email" value="{% if new_email is defined %}{{ new_email }}{% endif %}" size="30" maxlength="50" autofocus/>
</td>
</tr>
<tr>
<td class="LabelV">
<span >Password:</span>
<label for="password">Password:</label>
</td>
<td>
<input form="form" type="password" name="password" size="30" maxlength="29">
<input form="form" type="password" id="password" name="password" size="30" maxlength="29">
</td>
</tr>
</table>

View File

@@ -4,20 +4,26 @@ Here you can tell other players about yourself. This information will be display
{% set content %}
<table style="width: 100%;" >
<tr>
<td class="LabelV">Real Name:</td>
<td class="LabelV">
<label for="info_rlname">Real Name:</label>
</td>
<td style="width:90%;" >
<input form="form" name="info_rlname" value="{{ account_rlname }}" size="30" maxlength="50" >
<input form="form" id="info_rlname" name="info_rlname" value="{{ account_rlname }}" size="30" maxlength="50" >
</td>
</tr>
<tr>
<td class="LabelV" >Location:</td>
<td class="LabelV">
<label for="info_location">Location:</label>
</td>
<td>
<input form="form" name="info_location" value="{{ account_location }}" size="30" maxlength="50" >
<input form="form" id="info_location" name="info_location" value="{{ account_location }}" size="30" maxlength="50" >
</td>
</tr>
{% if setting('core.account_country') %}
<tr>
<td class="LabelV">Country:</td>
<td class="LabelV">
<label for="account_country">Country:</label>
</td>
<td>
<select form="form" name="info_country" id="account_country">
{% for code, country in countries %}

View File

@@ -6,7 +6,7 @@ Please enter your current password and a new password. For your security, please
<table style="width:100%;">
<tr>
<td class="LabelV">
<span>Current Password:</span>
<label for="old_password">Current Password:</label>
</td>
<td>
<input form="form" type="password" id="old_password" name="old_password" size="30" maxlength="29">
@@ -17,7 +17,7 @@ Please enter your current password and a new password. For your security, please
<tr>
<td class="LabelV">
<span>New Password:</span>
<label for="new_password">New Password:</label>
</td>
<td style="width:90%;">
<input form="form" type="password" id="new_password" name="new_password" size="30" maxlength="29">
@@ -28,7 +28,7 @@ Please enter your current password and a new password. For your security, please
<tr>
<td class="LabelV">
<span>New Password Again:</span>
<label for="new_password_confirm">New Password Again:</label>
</td>
<td>
<input form="form" type="password" id="new_password_confirm" name="new_password_confirm" size="30" maxlength="29">

View File

@@ -1,4 +1,4 @@
To change a name of character select player and choose a new name.<br/>
To change the name of a character, select a player and choose a new name.<br/>
<span style="color: red">Change name cost {{ setting('core.account_change_character_name_price') }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}. You have {{ points }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}.</span><br/><br/>
{% set title = 'Change Name' %}
@@ -6,9 +6,11 @@ To change a name of character select player and choose a new name.<br/>
{% set content %}
<table style="width:100%;" >
<tr>
<td class="LabelV" ><span>Character:</span></td>
<td class="LabelV">
<label for="player_id">Character:</label>
</td>
<td style="width:90%;" >
<select form="form" name="player_id">
<select form="form" id="player_id" name="player_id">
{% for player in account_logged.getPlayersList(false) %}
<option value="{{ player.getId() }}">{{ player.getName() }}</option>
{% endfor %}
@@ -16,7 +18,9 @@ To change a name of character select player and choose a new name.<br/>
</td>
</tr>
<tr>
<td class="LabelV" ><span>New Name:</span></td>
<td class="LabelV">
<label for="character_name">New Name:</label>
</td>
<td>
<input form="form" type="text" name="name" id="character_name" size="25" maxlength="25" >
<img id="character_indicator" src="images/global/general/{% if not save or errors|length > 0 %}n{% endif %}ok.gif" />

View File

@@ -6,9 +6,11 @@ To change a sex of character select player and choose a new sex.<br/>
{% set content %}
<table style="width:100%;" >
<tr>
<td class="LabelV" ><span>Character:</span></td>
<td class="LabelV">
<label for="player_id">Character:</label>
</td>
<td style="width:90%;" >
<select form="form" name="player_id">
<select form="form" id="player_id" name="player_id">
{% for player in players %}
<option value="{{ player.getId() }}">{{ player.getName() }}</option>
{% endfor %}
@@ -16,9 +18,11 @@ To change a sex of character select player and choose a new sex.<br/>
</td>
</tr>
<tr>
<td class="LabelV" ><span>New Sex:</span></td>
<td class="LabelV">
<label for="new_sex">New Sex:</label>
</td>
<td>
<select form="form" name="new_sex">
<select form="form" id="new_sex" name="new_sex">
{% for id, gender in config.genders %}
<option value="{{ id }}"{% if player_sex == id %} selected{% endif %}>{{ gender }}</option>
{% endfor %}

View File

@@ -4,15 +4,19 @@ To delete a character enter the name of the character and your password.<br/><br
{% set content %}
<table style="width:100%;">
<tr>
<td class="LabelV" ><span>Character Name:</span></td>
<td class="LabelV">
<label for="delete_name">Character Name:</label>
</td>
<td style="width:90%;">
<input form="form" name="delete_name" value="" size="30" maxlength="29"/>
<input form="form" id="delete_name" name="delete_name" value="" size="30" maxlength="29"/>
</td>
</tr>
<tr>
<td class="LabelV" ><span>Password:</span></td>
<td class="LabelV">
<label for="delete_password">Password:</label>
</td>
<td>
<input form="form" type="password" name="delete_password" size="30" maxlength="29"/>
<input form="form" type="password" id="delete_password" name="delete_password" size="30" maxlength="29"/>
</td>
</tr>
</table>

View File

@@ -48,7 +48,7 @@
</tr>
{% if setting('core.mail_enabled') and setting('core.account_mail_verify') %}
<tr><td></td><td><span><strong>Please use real address!<br/>We will send a link to validate your Email.</strong></span></td></tr>
<tr><td></td><td><span><strong>Please use a real address!<br/>We will send a link to validate your Email.</strong></span></td></tr>
{% endif %}
{{ hook('HOOK_ACCOUNT_CREATE_AFTER_EMAIL') }}

View File

@@ -1,13 +1,15 @@
To generate new recovery key for your account please enter your password.<br/>
<span style="color: red"><b>New recovery key cost {{ setting('core.account_generate_new_reckey_price') }} Premium Points</b>.</span> You have {{ points }} premium points. You will receive e-mail with this recovery key.
To generate a new recovery key for your account, please enter your password.<br/>
<span style="color: red"><b>New recovery key cost {{ setting('core.account_change_character_name_price') }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}. You have {{ points }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}. You will receive an e-mail with this recovery key.
<br/>
{% set title = 'Generate recovery key' %}
{% set background = config('darkborder') %}
{% set content %}
<table style="width:100%;">
<tr>
<td class="LabelV"><span>Password:</span></td>
<td><input form="form" type="password" name="reg_password" size="30" maxlength="29" ></td>
<td class="LabelV">
<label for="reg_password">Password:</label>
</td>
<td><input form="form" type="password" id="reg_password" name="reg_password" size="30" maxlength="29" ></td>
</tr>
</table>
{% endset %}
@@ -18,7 +20,7 @@ To generate new recovery key for your account please enter your password.<br/>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td style="border:0px;">
<td style="border:0;">
<form id="form" action="{{ getLink('account/register-new') }}" method="post">
{{ csrf() }}
<input type="hidden" name="registeraccountsave" value="1">
@@ -31,7 +33,7 @@ To generate new recovery key for your account please enter your password.<br/>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td style="border:0px;">
<td style="border:0;">
<form action="{{ getLink('account/manage') }}" method="post">
{{ csrf() }}
{{ include('buttons.back.html.twig') }}

View File

@@ -5,10 +5,10 @@ To generate recovery key for your account please enter your password.<br/><br/>
<table style="width:100%;" >
<tr>
<td class="LabelV">
<span>Password:</span>
<label for="reg_password">Password:</label>
</td>
<td>
<input form="form" type="password" name="reg_password" size="30" maxlength="29" autofocus/>
<input form="form" type="password" id="reg_password" name="reg_password" size="30" maxlength="29" autofocus/>
</td>
</tr>
</table>
@@ -20,7 +20,7 @@ To generate recovery key for your account please enter your password.<br/><br/>
<td>
<table border="0" cellspacing="0" cellpadding="0" >
<tr>
<td style="border:0px;">
<td style="border:0;">
<form id="form" action="{{ getLink('account/register') }}" method="post">
{{ csrf() }}
<input type="hidden" name="registeraccountsave" value="1"/>

View File

@@ -179,7 +179,7 @@
{% set i = i + 1 %}
<tr bgcolor="{{ getStyle(i) }}">
<td>
<a href="{{ getLink('characters/' ~ player.getName()|urlencode) }}">{{ player.getName() }}</a>
<a href="{{ getLink('characters/' ~ player.getName()|urlencode) }}">{{ player.getName() }}</a>{% if player.isDeleted() %}<span style="color: red"><b> [ DELETED ] </b></span>{% endif %}
</td>
<td>{{ player.getLevel() }}</td>
<td>{{ player.getVocationName() }}</td>

View File

@@ -1,6 +1,6 @@
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0">News:
<h5 class="m-0">Changelogs:
<form method="post" class="float-right">
{{ csrf() }}
<input type="hidden" name="action" value="new" />

View File

@@ -0,0 +1,33 @@
<link rel="stylesheet" type="text/css" href="{{ constant('BASE_URL') }}tools/css/toastify.min.css">
<script type="text/javascript" src="{{ constant('BASE_URL') }}tools/js/toastify.min.js"></script>
{{ include('script.ajax-setup.html.twig') }}
<script>
$(function () {
/* Store sidebar state */
$('.sidebar-toggle').on('click',function(event) {
event.preventDefault();
const isCollapsed = $('body').hasClass('sidebar-collapse');
$.ajax({
type: 'POST',
url: '{{ constant('ADMIN_URL') }}tools/menu_collapse.php',
data : { collapse: !isCollapsed},
success : function(response) {
},
error : function(response) {
Toastify({
position: 'center',
text: response.responseText,
duration: 3000,
style: {
background: 'red',
},
escapeMarkup: false,
}).showToast();
}
});
});
});
</script>

View File

@@ -73,13 +73,9 @@
<!-- jQuery Form Submit No Refresh + Toastify -->
<link rel="stylesheet" type="text/css" href="{{ constant('BASE_URL') }}tools/css/toastify.min.css">
<script type="text/javascript" src="{{ constant('BASE_URL') }}tools/js/toastify.min.js"></script>
<script>
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
{{ include('script.ajax-setup.html.twig') }}
<script>
const noChangesText = "No changes has been made";
$('form')

View File

@@ -1,7 +1,7 @@
<form action="?" method="post">
{{ csrf() }}
<input type="hidden" name="action" value="new_post" />
<input type="hidden" name="thread_id" value=" {{ thread_id }}" />
<input type="hidden" name="thread_id" value="{{ thread_id }}" />
<input type="hidden" name="subtopic" value="forum" />
<input type="hidden" name="save" value="save" />
<table width="100%">
@@ -43,7 +43,8 @@
</tr>
</table>
<div style="text-align:center">
<input type="submit" value="Post Reply" />
{% set button_name = 'Post Reply' %}
{{ include('buttons.base.html.twig') }}
</div>
</form>

View File

@@ -44,6 +44,7 @@
</tr>
</table>
<div style="text-align:center">
<input type="submit" value="Post Thread" />
{% set button_name = 'Post Thread' %}
{{ include('buttons.base.html.twig') }}
</div>
</form>

View File

@@ -0,0 +1,57 @@
<a href="{{ getLink('forum') }}">Boards</a> >> <b>{{ section_name }}</b>
{% if (logged and (not closed or is_moderator)) %}
<br/><br/>
<a href="{{ getLink('forum') }}?action=new_thread&section_id={{ section_id }}"><img src="images/forum/topic.gif" border="0" /></a>
{% endif %}
{% if threads|length > 0 %}
<br/><br/>Page: {{ links_to_pages|raw }}<br/>
<table width="100%">
<tr bgcolor=" {{ config.vdarkborder }}" align="center">
<td class="white"><span style="font-size: 10px"><b>Thread</b></span></td>
<td class="white"><span style="font-size: 10px"><b>Thread Starter</b></span></td>
<td class="white"><span style="font-size: 10px"><b>Replies</b></span></td>
<td class="white"><span style="font-size: 10px"><b>Views</b></span></td>
<td class="white"><span style="font-size: 10px"><b>Last Post</b></span></td>
</tr>
{% set i = 0 %}
{% for thread in threads %}
<tr bgcolor="{{ getStyle(i) }}">
<td>
{% if is_moderator %}
<a href="{{ getLink('forum') }}?action=move_thread&id={{ thread.id }}" title="Move Thread"><img src="images/icons/arrow_right.gif"/></a>
{{ include('forum.remove_post.html.twig', {post: thread}) }}
{% endif %}
<a href="{{ thread.link }}">{{ thread.post_topic }}</a><br />
<small>{{ thread.post_shortened|raw }}...</small>
</td>
<td>{{ thread.player_link|raw }}</td>
<td>{{ thread.replies }}</td>
<td>{{ thread.views }}</td>
<td>
{% if thread.last_post > 0 %}
{% if thread.latest_post.name is defined %}
{{ thread.latest_post.post_date|date('d.m.y H:i:s') }}<br />by {{ thread.latest_post.player_link|raw }}
{% else %}
No posts.
{% endif %}
{% else %}
{{ thread.post_date|date('d.m.y H:i:s') }}<br />by {{ thread.player_link|raw }}
{% endif %}
</td>
</tr>
{% set i = i + 1 %}
{% endfor %}
</table>
{% else %}
<h3>No threads in this board.</h3>
{% endif %}
{% if(logged and (not closed or is_moderator)) %}
<br /><a href="{{ getLink('forum') }}?action=new_thread&section_id={{ section_id }}"><img src="images/forum/topic.gif" border="0" /></a>
{% endif %}

View File

@@ -6,7 +6,7 @@
<td class="white"><b>Leave guild</b></td></tr>
{% if players|length > 0 %}
<tr bgcolor="{{ config.lightborder }}">
<td width="100%">Select character to leave guild:</td>
<td width="100%">Select a character to leave the guild:</td>
</tr>
<tr bgcolor="{{ config.darkborder }}">
<td>

View File

@@ -105,7 +105,8 @@ Here you can change names of ranks, delete and add ranks, pass leadership to oth
<form action="{{ getLink('guilds') }}?guild={{ guild.getName() }}&action=delete_rank" method="post" style="display: inline;">
{{ csrf() }}
<input type="hidden" name="rankid" value="{{ rank.getId() }}" />
<input type="image" src="/images/news/delete.png" border="0" alt="Delete" />
<input type="submit" value="Delete" />
</form>
</td>
<td>

View File

@@ -18,7 +18,7 @@
<label for="vocationFilter">Choose a vocation</label>
<select onchange="location = this.value;" id="vocationFilter">
<option value="{{ getLink('highscores') }}/{{ list|urlencode }}" class="size_xs">[ALL]</option>
{% for i in 0..config.vocations_amount %}
{% for i in baseVocations %}
<option value="{{ getLink('highscores') }}/{{ list|urlencode }}/{{ config.vocations[i]|lower|urlencode }}" class="size_xs" {% if vocationId is not null and vocationId == i %}selected{% endif %}>{{ config.vocations[i]}}</option>
{% endfor %}
</select>
@@ -120,7 +120,7 @@
<tr bgcolor="{{ config.lightborder }}">
<td>
<a href="{{ getLink('highscores') }}/{{ list|urlencode }}" class="size_xs">[ALL]</a><br/>
{% for i in 0..config.vocations_amount %}
{% for i in baseVocations %}
<a href="{{ getLink('highscores') }}/{{ list|urlencode }}/{{ config.vocations[i]|lower|urlencode }}" class="size_xs">{{ config.vocations[i]}}</a><br/>
{% endfor %}
</td>

View File

@@ -4,55 +4,66 @@
<br/>
{% endif %}
<br/>
{# vocation statistics #}
{% if setting('core.online_vocations') %}
<br/>
{% set title = 'Vocation statistics' %}
{% set tableClass = 'Table3' %}
{% set background = config('darkborder') %}
{% set content %}
{% if setting('core.online_vocations_images') %}
<table width="200" cellspacing="1" cellpadding="0" border="0" align="center">
<tr bgcolor="{{ config.darkborder }}">
<td><img src="images/sorcerer.png" /></td>
<td><img src="images/druid.png" /></td>
<td><img src="images/paladin.png" /></td>
<td><img src="images/knight.png" /></td>
<table width="200" cellspacing="1" cellpadding="0" border="0" align="center" class="myaac-table">
<thead>
<tr>
{% for vocationId in baseVocations %}
<td style="text-align: center;"><strong>{{ config('vocations')[vocationId] }}s</strong></td>
{% endfor %}
</tr>
<tr bgcolor="{{ config.vdarkborder }}">
<td class="white" style="text-align: center;"><strong>Sorcerers</strong></td>
<td class="white" style="text-align: center;"><strong>Druids</strong></td>
<td class="white" style="text-align: center;"><strong>Paladins</strong></td>
<td class="white" style="text-align: center;"><strong>Knights</strong></td>
</thead>
<tr>
{% for vocationId in baseVocations %}
<td><img src="images/{{ config('vocations')[vocationId]|lower }}.png" width="150" height="200"/></td>
{% endfor %}
</tr>
<tr bgcolor="{{ config.lightborder }}">
<td style="text-align: center;">{{ vocs[1] }}</td>
<td style="text-align: center;">{{ vocs[2] }}</td>
<td style="text-align: center;">{{ vocs[3] }}</td>
<td style="text-align: center;">{{ vocs[4] }}</td>
<tr>
{% for vocationId in baseVocations %}
<td style="text-align: center;">{{ vocs[vocationId] }}</td>
{% endfor %}
</tr>
</table>
<div style="text-align: center;">&nbsp;</div>
{% else %}
<table border="0" cellspacing="1" cellpadding="4" width="100%">
<tr bgcolor="{{ config.vdarkborder }}">
<td class="white" colspan="2"><b>Vocation statistics</b></td>
</tr>
{% else %}
<table border="0" cellspacing="1" cellpadding="4" width="100%" class="myaac-table">
{% set i = 0 %}
{% for vocationId in baseVocations %}
<tr>
<td width="25%">{{ config.vocations[vocationId] }}</td>
<td width="75%">{{ vocs[vocationId] }}</td>
</tr>
{% for i in 1..config.vocations_amount %}
<tr bgcolor="{{ getStyle(i) }}">
<td width="25%">{{ config.vocations[i] }}</td>
<td width="75%">{{ vocs[i] }}</td>
</tr>
{% set i = i + 1 %}
{% endfor %}
</table>
<br/>
<br/>
{% endif %}
{% endset %}
{% include 'tables.headline.html.twig' %}
{% endif %}
<br/>
{# show skulls #}
{% if setting('core.online_skulls') %}
<table width="100%" cellspacing="1">
<table width="100%" cellspacing="1" class="myaac-table">
<tr>
<td style="background: {{ config.darkborder }};" align="center">
<td align="center">
<img src="images/white_skull.gif"/> - 1 - 6 Frags<br/>
<img src="images/red_skull.gif"/> - 6+ Frags or Red Skull<br/>
<img src="images/black_skull.gif"/> - 10+ Frags or Black Skull
@@ -125,23 +136,24 @@
{% set title = 'Players Online' %}
{% set tableClass = 'Table2' %}
{% set content %}
<table width="100%">
<tr class="LabelH" style="position: relative; z-index: 20;">
<table width="100%" class="myaac-table">
<tr class="LabelH" style="z-index: 20;">
{% if setting('core.account_country') %}
<td width="11px"><a href="{{ getLink('online')}}?order=country_{{ order == 'country_asc' ? 'desc' : 'asc' }}">#&#160;&#160;</a>
<td style="width: 6px;"><a href="{{ getLink('online')}}?order=country_{{ order == 'country_asc' ? 'desc' : 'asc' }}">#&#160;&#160;</a>
</td>
{% endif %}
{% if setting('core.online_outfit') %}
<td><b>Outfit</b></td>
<td style="width: 32px;"><b>Outfit</b></td>
{% endif %}
<td style="text-align:left; width:50%">Name&#160;&#160;
<td style="text-align:left;">Name&#160;&#160;
<small style="font-weight:normal">[<a href="{{ getLink('online')}}?order=name_{{ order == 'name_asc' ? 'desc' : 'asc' }}">sort</a>]</small>
<img class="sortarrow" src="images/{{ order == 'name_asc' ? 'order_desc' : (order == 'name_desc' ? 'order_asc' : 'news/blank') }}.gif"/></td>
<td style="text-align:left;width:30%">Level&#160;&#160;
<td style="text-align:left;width:10%">Level&#160;&#160;
<small style="font-weight:normal">[<a href="{{ getLink('online')}}?order=level_{{ order == 'level_asc' ? 'desc' : 'asc' }}">sort</a>]</small>
<img class="sortarrow" src="images/{{ order == 'level_asc' ? 'order_desc' : (order == 'level_desc' ? 'order_asc' : 'news/blank') }}.gif"/>
</td>
<td style="text-align:left;width:50%">Vocation&#160;&#160;
<td style="text-align:left;width:20%">Vocation&#160;&#160;
<small style="font-weight:normal">[<a href="{{ getLink('online')}}?order=vocation_{{ order == 'vocation_asc' ? 'desc' : 'asc' }}">sort</a>]</small>
<img class="sortarrow" src="images/{{ order == 'vocation_asc' ? 'order_desc' : (order == 'vocation_desc' ? 'order_asc' : 'news/blank') }}.gif"/>
</td>
@@ -151,20 +163,20 @@
{% for player in players %}
{% set i = i + 1 %}
<tr style="background: {{ getStyle(i) }}; text-align: right; height: 40px;">
<tr style="text-align: right; height: 40px;">
{% if setting('core.account_country') %}
<td>{{ player.country_image|raw }}</td>
{% endif %}
{% if setting('core.online_outfit') %}
<td width="5%"><img style="position:absolute;margin-top:-48px;margin-left:-70px;" src="{{ player.outfit }}" alt="player outfit"/></td>
<td><img style="position:absolute;margin-top:-48px;margin-left:-70px;" src="{{ player.outfit }}" alt="player outfit"/></td>
{% endif %}
<td style="width:70%; text-align:left">
<td style="text-align:left">
{{ player.name|raw }}{{ player.skull|raw }}
</td>
<td style="width:10%">{{ player.level }}</td>
<td style="width:20%">{{ player.vocation }}</td>
<td>{{ player.level }}</td>
<td>{{ player.vocation }}</td>
</tr>
{% endfor %}
</table>

View File

@@ -0,0 +1,7 @@
<script>
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
</script>