// ==UserScript==
// @name TolyanHammerKombat
// @namespace http://tampermonkey.net/
// @version 1.3
// @description Игра поймай неудаленного Толяна Хамстеркомбата
// @author Marina Khamsterkombat
// @match https://vk.com/*
// @icon https://em-content.zobj.net/source/apple/391/hamster_1f439.png
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// Конфигурация скрипта
const CONFIG = {
targetName: 'Толян Хамстеркомбат', // Имя целевого автора
message: '🎉🐹🔨 Попался, крысеныш! 🎉🐹🔨', // Текст уведомления
colors: {
background: '#5252CC', // Фон уведомления
text: '#FFDDCC' // Цвет текста
},
assets: {
hammerImage: 'https://i.imgur.com/9hJJv6a.png', // Изображение молотка
hammerSound: 'https://myinstants.com/media/sounds/fnaf-12-3-freddys-nose-sound.mp3' // Звук удара
},
animation: {
hammerSize: 50, // Размер молотка в пикселях
hitAnimation: {
duration: 200, // Длительность анимации
rotations: {
initial: 0, // Начальный угол
hit: -30, // Угол при ударе
reset: 0 // Угол после удара
}
},
}
};
// Переключатель работы скрипта
let isActive = true;
// Создание уведомления
const createNotice = (postElement) => {
const notice = document.createElement('div');
Object.assign(notice.style, {
position: 'relative',
textAlign: 'center',
padding: '16px',
backgroundColor: CONFIG.colors.background,
borderRadius: '8px',
marginTop: '8px',
opacity: '0',
transform: 'translateY(-20px)',
transition: 'opacity 0.5s ease, transform 0.5s ease'
});
// Создание и добавление элемента
notice.innerHTML = `<h2 style="color: ${CONFIG.colors.text}; font-weight: 600;">
${CONFIG.message}
</h2>`;
postElement.prepend(notice);
// Запуск анимации когда элемент виден на 100%
const noticeObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
observer.disconnect();
setTimeout(() => {
notice.style.opacity = '1';
notice.style.transform = 'translateY(0)';
}, 200);
}
});
}, { threshold: 1.0 });
noticeObserver.observe(notice);
};
// Создание и управление молотком
const createHammer = (event) => {
const hammer = document.createElement('img');
Object.assign(hammer.style, {
position: 'fixed',
width: `${CONFIG.animation.hammerSize}px`,
height: `${CONFIG.animation.hammerSize}px`,
pointerEvents: 'none',
transformOrigin: 'bottom right',
transition: 'transform 0.1s ease',
left: `${event.clientX - 8}px`,
top: `${event.clientY - 40}px`
});
// Создание и добавление элемента
hammer.src = CONFIG.assets.hammerImage;
document.body.appendChild(hammer);
// Анимация удара молотком
function animateHammer(hammer, rotation) {
hammer.style.transform = `rotate(${rotation}deg)`;
}
// Последовательность анимации
setTimeout(() => animateHammer(hammer, CONFIG.animation.hitAnimation.rotations.hit), 10);
setTimeout(() => animateHammer(hammer, CONFIG.animation.hitAnimation.rotations.reset), 100);
setTimeout(() => hammer.remove(), CONFIG.animation.hitAnimation.duration);
};
// Воспроизведение звукового эффекта
const playSound = () => new Audio(CONFIG.assets.hammerSound).play();
// Обработчик клика по аватарке
const setupHammerInteraction = (postElement) => {
const avatar = postElement.querySelector('.PostHeader__avatar a');
if (!avatar) return;
Object.assign(avatar.style, {
cursor: 'crosshair',
userSelect: 'none'
});
avatar.removeAttribute('href');
avatar.addEventListener('click', event => {
createHammer(event);
playSound();
});
};
// Проверка удаления профиля по аватарке
const isProfileDeleted = (postElement) => !postElement.querySelector('.PostHeader__avatar img')?.src.includes('ava=1');
// Основная логика проверки постов
const checkPosts = () => {
if (!isActive) {
observer.disconnect();
return;
}
// Проверка всех постов на странице
document.querySelectorAll('.post').forEach(post => {
const authorElement = post.querySelector('.PostHeaderTitle__authorName');
const authorName = authorElement?.textContent.trim();
// Если имя автора совпадает с целью и профиль не удален
if (authorName === CONFIG.targetName && !isProfileDeleted(post)) {
isActive = false;
createNotice(post);
setupHammerInteraction(post);
}
});
};
// Инициализация наблюдателя
const observer = new MutationObserver(checkPosts);
window.addEventListener('load', checkPosts);
observer.observe(document.body, { childList: true, subtree: true });
})();