function getModFolder() {
return window.location.pathname
.split('/')
.pop()
.replace('.html', '');
}
function loadDescription(lang){
const file = `${getModFolder()}/description.txt`;
fetch(file)
.then(res => res.text())
.then(text => {
document.getElementById('aboutText').innerHTML = parseText(text, lang);
})
.catch(() => {
document.getElementById('aboutText').innerText = '[ERROR]Failed to load description';
});
}
function parseText(text, lang) {
text = text.replace(/\r\n/g, '\n');
const lines = text.split('\n');
let currentColor = null;
let inList = false;
const colorMap = {
red: 'red',
orange: 'orange',
yellow: 'yellow',
lightgreen: 'lightgreen',
green: 'green',
blue: 'lightblue',
purple: 'purple',
pink: 'pink',
normal: 'yellow',
gray: 'gray',
black: 'black'
};
// Список тегов, строки с которыми нужно пропускать целиком
const skipTags = ['green']; // можно добавить другие, например: 'red', 'blue' и т.д.
let html = '';
lines.forEach((line, index) => {
if (index === 0 || index === 1 || index === 2 || index === 3) return;
if ((index === 4 || index === 5) && lang !== 'ru') return;
if ((index === 6 || index === 7) && lang !== 'en') return;
if (line.trim() === '') {
html += '
';
return;
}
line = line.trim();
const tags = line.match(/^(\[[^\]]+\])+/);
// ПРОВЕРКА НА ПРОПУСК СТРОКИ
let shouldSkip = false;
if (tags) {
const tagList = tags[0].match(/\[([^\]]+)\]/g) || [];
tagList.forEach(tag => {
const clean = tag.replace(/[\[\]]/g, '');
if (skipTags.includes(clean)) {
shouldSkip = true;
}
});
}
// Если строка начинается с пропускаемого тега - пропускаем её
if (shouldSkip) {
return;
}
if (tags) {
const tagList = tags[0].match(/\[([^\]]+)\]/g) || [];
tagList.forEach(tag => {
const clean = tag.replace(/[\[\]]/g, '');
if (colorMap[clean]) {
currentColor = colorMap[clean];
line = line.replace(tag, '');
}
});
}
if (line.toLowerCase().includes('load order')) {
const title = lang === 'ru' ? 'Порядок Загрузки:' : line;
html += `
${title}
`;
html += ``;
inList = true;
return;
}
if (inList) {
html += `- ${line}
`;
return;
}
html += `${line}
`;
});
if (inList) html += '
';
return html;
}
// animations.js
// Анимации плавного появления элементов при загрузке страницы
(function() {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initAnimations);
} else {
initAnimations();
}
function initAnimations() {
const style = document.createElement('style');
style.textContent = `
.fade-animate-init {
opacity: 0 !important;
transform: translateY(20px) !important;
}
.fade-left-init {
opacity: 0 !important;
transform: translateX(-15px) !important;
}
.fade-scale-init {
opacity: 0 !important;
transform: scale(0.95) !important;
}
`;
document.head.appendChild(style);
// Функция для временной анимации (transition удаляется после показа)
function animateWithCleanup(element, className, delay, duration = 0.3) {
if (!element) return;
element.classList.add(className);
element.style.transition = `opacity ${duration}s ease, transform ${duration}s ease`;
setTimeout(() => {
element.classList.remove(className);
element.style.opacity = '1';
element.style.transform = '';
// Удаляем transition через небольшую задержку
setTimeout(() => {
element.style.transition = '';
}, duration * 1000 + 50);
}, delay);
}
// Навигация и шапка (быстро)
animateWithCleanup(document.querySelector('#backBtn'), 'fade-animate-init', 30, 0.2);
animateWithCleanup(document.querySelector('.nav'), 'fade-animate-init', 50, 0.25);
animateWithCleanup(document.querySelector('.dwlbtn'), 'fade-animate-init', 70, 0.25);
animateWithCleanup(document.querySelector('.lang'), 'fade-animate-init', 90, 0.25);
// Заголовки и описание
animateWithCleanup(document.querySelector('.title'), 'fade-animate-init', 120, 0.3);
animateWithCleanup(document.querySelector('.desc'), 'fade-animate-init', 150, 0.3);
animateWithCleanup(document.querySelector('.banner'), 'fade-scale-init', 180, 0.35);
// Изображения
const images = document.querySelectorAll('.banner img');
images.forEach((img, idx) => {
img.style.opacity = '0';
img.style.transition = 'opacity 1s ease';
setTimeout(() => {
img.style.opacity = '1';
setTimeout(() => img.style.transition = '', 1000);
}, 200 + idx * 60);
});
// Секции и info-box
const sections = document.querySelectorAll('.section');
sections.forEach((el, i) => animateWithCleanup(el, 'fade-animate-init', 220 + i * 80, 0.3));
const infoBoxes = document.querySelectorAll('.info-box');
infoBoxes.forEach((box, i) => {
animateWithCleanup(box, 'fade-animate-init', 280 + i * 100, 0.3);
const headers = box.querySelectorAll('h2');
headers.forEach((h, hi) => animateWithCleanup(h, 'fade-left-init', 300 + i * 100 + hi * 40, 0.25));
const texts = box.querySelectorAll('p, .info-text');
texts.forEach((t, ti) => animateWithCleanup(t, 'fade-left-init', 320 + i * 100 + ti * 50, 0.25));
});
// Блок загрузки
const downloadBlock = document.querySelector('.download-block');
animateWithCleanup(downloadBlock, 'fade-animate-init', 520, 0.3);
const dlBtns = document.querySelectorAll('.download-block .btn');
dlBtns.forEach((btn, i) => animateWithCleanup(btn, 'fade-scale-init', 560 + i * 60, 0.25));
// Нижние кнопки
const bottomDiv = document.querySelector('.bottom-buttons');
animateWithCleanup(bottomDiv, 'fade-animate-init', 620, 0.3);
const bottomBtns = document.querySelectorAll('.bottom-buttons .btn');
bottomBtns.forEach((btn, i) => animateWithCleanup(btn, 'fade-scale-init', 650 + i * 60, 0.25));
// Версия
const versionDiv = document.querySelector('.version');
animateWithCleanup(versionDiv, 'fade-animate-init', 700, 0.3);
animateWithCleanup(document.querySelector('.version-title'), 'fade-left-init', 730, 0.25);
animateWithCleanup(document.querySelector('.changelog'), 'fade-left-init', 760, 0.3);
animateWithCleanup(document.querySelector('.version .btn'), 'fade-scale-init', 800, 0.25);
// Кнопка аддонов
animateWithCleanup(document.querySelector('#addonBtn'), 'fade-scale-init', 680, 0.25);
// Остальные тексты и заголовки (без накопления transition)
const extraTexts = document.querySelectorAll('p:not(.info-box p), .changelog, #creditsText, #infoText, #aboutText');
extraTexts.forEach((txt, i) => {
if (txt && !txt.closest('.info-box') && !txt.closest('.version')) {
txt.style.opacity = '0';
txt.style.transform = 'translateY(8px)';
txt.style.transition = 'opacity 1s ease, transform 1s ease';
setTimeout(() => {
txt.style.opacity = '1';
txt.style.transform = 'translateY(0)';
setTimeout(() => txt.style.transition = '', 400);
}, 340 + i * 30);
}
});
// Удаляем временные стили через 2 секунды
setTimeout(() => style.remove(), 2000);
}
})();
// Синхронизация всех select с выбором языка
function syncLangSelects() {
const selects = document.querySelectorAll('#langSelect');
const currentLang = localStorage.getItem('lang') || 'ru';
selects.forEach(select => {
if (select.value !== currentLang) {
select.value = currentLang;
}
});
}
// Вызываем синхронизацию при загрузке страницы
document.addEventListener('DOMContentLoaded', function() {
syncLangSelects();
});
// Также синхронизируем при изменении языка любым из select'ов
function setupLangSync() {
const selects = document.querySelectorAll('#langSelect');
selects.forEach(select => {
select.addEventListener('change', function(e) {
const newLang = e.target.value;
localStorage.setItem('lang', newLang);
// Обновляем все остальные select'ы
selects.forEach(otherSelect => {
if (otherSelect !== select) {
otherSelect.value = newLang;
}
});
// Вызываем функцию смены языка
if (typeof setLang === 'function') {
setLang(newLang);
}
});
});
}
// Запускаем синхронизацию после загрузки DOM
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
syncLangSelects();
setupLangSync();
});
} else {
syncLangSelects();
setupLangSync();
}
(function() {
const SCROLL_HIDE_POINT = 60;
const SCROLL_SHOW_POINT = 60;
const header = document.querySelector("header");
const leftPanel = document.querySelector(".left-panel");
const rightPanel = document.querySelector(".right-panel");
window.addEventListener("scroll", () => {
const scrollY = window.pageYOffset;
// При скролле вниз
if (scrollY > SCROLL_HIDE_POINT) {
if (header) header.classList.add("hide");
if (leftPanel) leftPanel.classList.add("show");
if (rightPanel) rightPanel.classList.add("show");
}
// При скролле вверх (в начало страницы)
if (scrollY < SCROLL_SHOW_POINT) {
if (header) header.classList.remove("hide");
if (leftPanel) leftPanel.classList.remove("show");
if (rightPanel) rightPanel.classList.remove("show");
}
});
})();
// Анимация при смене языка (минимальная, без сохранения transition)
function animateLanguageChange() {
const els = document.querySelectorAll('.info-box, .version, .download-block, .title, .desc, .section');
els.forEach(el => {
if (!el) return;
const oldTrans = el.style.transition;
el.style.transition = 'opacity 1s ease';
el.style.opacity = '0.7';
setTimeout(() => {
el.style.opacity = '';
setTimeout(() => {
if (el.style.transition === 'opacity 1s ease') el.style.transition = oldTrans;
}, 200);
}, 100);
});
}
// Плавное обновление текста
function smoothTextUpdate(el, newText) {
if (!el) return;
const oldTrans = el.style.transition;
el.style.transition = 'opacity 1s ease';
el.style.opacity = '0';
setTimeout(() => {
if (typeof newText === 'string') el.innerHTML = newText;
el.style.opacity = '1';
setTimeout(() => el.style.transition = oldTrans, 150);
}, 100);
}
// Перехват setLang
const originalSetLang = window.setLang;
if (originalSetLang) {
window.setLang = function(lang) {
animateLanguageChange();
setTimeout(() => originalSetLang(lang), 50);
};
}
function goBack(){
const last = localStorage.getItem('lastPage');
if(last){
window.location.href = "../mods.html";
window.close();
} else {
window.location.href = "../mods.html";
}
}