Good Working bots system
// ==UserScript==
// @name Glotus Client fixed
// @author Murka / Seldoom
// @description Good Working bots system
// @icon https://imagizer.imageshack.com/img924/3497/SedB2D.png
// @version 5.3 fixed by seldoom
// @match *://moomoo.io/
// @match *://moomoo.io/?server*
// @match *://*.moomoo.io/
// @match *://*.moomoo.io/?server*
// @run-at document-start
// @grant none
// @license MIT
// @namespace https://github.com/Murka007/Glotus-client
// ==/UserScript==
/* jshint esversion:6 */
/*
Author: Murka
Github: https://github.com/Murka007/Glotus-client
Greasyfork: https://greasyfork.org/users/919633
Discord: https://discord.gg/cPRFdcZkeD
Version: 5.3
Build Time: 23/01/2026 | 12:47:35
Works On: index-eb87bff7.js
*/
(function() {
function easeOutQuad(x) {
return 1 - (1 - x) * (1 - x);
}
function shortAngle(a, b) {
let PI22 = 2 * Math.PI;
a = (a % PI22 + PI22) % PI22, b = (b % PI22 + PI22) % PI22;
let diff = b - a;
if (diff > PI22 / 2) {
diff -= PI22;
} else if (diff < -PI22 / 2) {
diff += PI22;
}
return diff;
}
class Altcha {
coreCount=Math.min(16, navigator.hardwareConcurrency || 8);
workers=[];
blobUrl=null;
initPool(challenge, salt) {
if (this.workers.length > 0) {
return;
}
let workerCode = `\n ${atob("IWZ1bmN0aW9uKCl7InVzZSBzdHJpY3QiO2Z1bmN0aW9uIHQodCxpKXtpPyhkWzBdPWRbMTZdPWRbMV09ZFsyXT1kWzNdPWRbNF09ZFs1XT1kWzZdPWRbN109ZFs4XT1kWzldPWRbMTBdPWRbMTFdPWRbMTJdPWRbMTNdPWRbMTRdPWRbMTVdPTAsdGhpcy5ibG9ja3M9ZCk6dGhpcy5ibG9ja3M9WzAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sdD8odGhpcy5oMD0zMjM4MzcxMDMyLHRoaXMuaDE9OTE0MTUwNjYzLHRoaXMuaDI9ODEyNzAyOTk5LHRoaXMuaDM9NDE0NDkxMjY5Nyx0aGlzLmg0PTQyOTA3NzU4NTcsdGhpcy5oNT0xNzUwNjAzMDI1LHRoaXMuaDY9MTY5NDA3NjgzOSx0aGlzLmg3PTMyMDQwNzU0MjgpOih0aGlzLmgwPTE3NzkwMzM3MDMsdGhpcy5oMT0zMTQ0MTM0Mjc3LHRoaXMuaDI9MTAxMzkwNDI0Mix0aGlzLmgzPTI3NzM0ODA3NjIsdGhpcy5oND0xMzU5ODkzMTE5LHRoaXMuaDU9MjYwMDgyMjkyNCx0aGlzLmg2PTUyODczNDYzNSx0aGlzLmg3PTE1NDE0NTkyMjUpLHRoaXMuYmxvY2s9dGhpcy5zdGFydD10aGlzLmJ5dGVzPXRoaXMuaEJ5dGVzPTAsdGhpcy5maW5hbGl6ZWQ9dGhpcy5oYXNoZWQ9ITEsdGhpcy5maXJzdD0hMCx0aGlzLmlzMjI0PXR9ZnVuY3Rpb24gaShpLHIscyl7dmFyIGUsbj10eXBlb2YgaTtpZigic3RyaW5nIj09PW4pe3ZhciBvLGE9W10sdT1pLmxlbmd0aCxjPTA7Zm9yKGU9MDtlPHU7KytlKShvPWkuY2hhckNvZGVBdChlKSk8MTI4P2FbYysrXT1vOm88MjA0OD8oYVtjKytdPTE5MnxvPj42LGFbYysrXT0xMjh8NjMmbyk6bzw1NTI5Nnx8bz49NTczNDQ/KGFbYysrXT0yMjR8bz4+MTIsYVtjKytdPTEyOHxvPj42JjYzLGFbYysrXT0xMjh8NjMmbyk6KG89NjU1MzYrKCgxMDIzJm8pPDwxMHwxMDIzJmkuY2hhckNvZGVBdCgrK2UpKSxhW2MrK109MjQwfG8+PjE4LGFbYysrXT0xMjh8bz4+MTImNjMsYVtjKytdPTEyOHxvPj42JjYzLGFbYysrXT0xMjh8NjMmbyk7aT1hfWVsc2V7aWYoIm9iamVjdCIhPT1uKXRocm93IG5ldyBFcnJvcihoKTtpZihudWxsPT09aSl0aHJvdyBuZXcgRXJyb3IoaCk7aWYoZiYmaS5jb25zdHJ1Y3Rvcj09PUFycmF5QnVmZmVyKWk9bmV3IFVpbnQ4QXJyYXkoaSk7ZWxzZSBpZighKEFycmF5LmlzQXJyYXkoaSl8fGYmJkFycmF5QnVmZmVyLmlzVmlldyhpKSkpdGhyb3cgbmV3IEVycm9yKGgpfWkubGVuZ3RoPjY0JiYoaT1uZXcgdChyLCEwKS51cGRhdGUoaSkuYXJyYXkoKSk7dmFyIHk9W10scD1bXTtmb3IoZT0wO2U8NjQ7KytlKXt2YXIgbD1pW2VdfHwwO3lbZV09OTJebCxwW2VdPTU0Xmx9dC5jYWxsKHRoaXMscixzKSx0aGlzLnVwZGF0ZShwKSx0aGlzLm9LZXlQYWQ9eSx0aGlzLmlubmVyPSEwLHRoaXMuc2hhcmVkTWVtb3J5PXN9dmFyIGg9ImlucHV0IGlzIGludmFsaWQgdHlwZSIscj0ib2JqZWN0Ij09dHlwZW9mIHdpbmRvdyxzPXI/d2luZG93Ont9O3MuSlNfU0hBMjU2X05PX1dJTkRPVyYmKHI9ITEpO3ZhciBlPSFyJiYib2JqZWN0Ij09dHlwZW9mIHNlbGYsbj0hcy5KU19TSEEyNTZfTk9fTk9ERV9KUyYmIm9iamVjdCI9PXR5cGVvZiBwcm9jZXNzJiZwcm9jZXNzLnZlcnNpb25zJiZwcm9jZXNzLnZlcnNpb25zLm5vZGU7bj9zPWdsb2JhbDplJiYocz1zZWxmKTt2YXIgbz0hcy5KU19TSEEyNTZfTk9fQ09NTU9OX0pTJiYib2JqZWN0Ij09dHlwZW9mIG1vZHVsZSYmbW9kdWxlLmV4cG9ydHMsYT0iZnVuY3Rpb24iPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kLGY9IXMuSlNfU0hBMjU2X05PX0FSUkFZX0JVRkZFUiYmInVuZGVmaW5lZCIhPXR5cGVvZiBBcnJheUJ1ZmZlcix1PSIwMTIzNDU2Nzg5YWJjZGVmIi5zcGxpdCgiIiksYz1bLTIxNDc0ODM2NDgsODM4ODYwOCwzMjc2OCwxMjhdLHk9WzI0LDE2LDgsMF0scD1bMTExNjM1MjQwOCwxODk5NDQ3NDQxLDMwNDkzMjM0NzEsMzkyMTAwOTU3Myw5NjE5ODcxNjMsMTUwODk3MDk5MywyNDUzNjM1NzQ4LDI4NzA3NjMyMjEsMzYyNDM4MTA4MCwzMTA1OTg0MDEsNjA3MjI1Mjc4LDE0MjY4ODE5ODcsMTkyNTA3ODM4OCwyMTYyMDc4MjA2LDI2MTQ4ODgxMDMsMzI0ODIyMjU4MCwzODM1MzkwNDAxLDQwMjIyMjQ3NzQsMjY0MzQ3MDc4LDYwNDgwNzYyOCw3NzAyNTU5ODMsMTI0OTE1MDEyMiwxNTU1MDgxNjkyLDE5OTYwNjQ5ODYsMjU1NDIyMDg4MiwyODIxODM0MzQ5LDI5NTI5OTY4MDgsMzIxMDMxMzY3MSwzMzM2NTcxODkxLDM1ODQ1Mjg3MTEsMTEzOTI2OTkzLDMzODI0MTg5NSw2NjYzMDcyMDUsNzczNTI5OTEyLDEyOTQ3NTczNzIsMTM5NjE4MjI5MSwxNjk1MTgzNzAwLDE5ODY2NjEwNTEsMjE3NzAyNjM1MCwyNDU2OTU2MDM3LDI3MzA0ODU5MjEsMjgyMDMwMjQxMSwzMjU5NzMwODAwLDMzNDU3NjQ3NzEsMzUxNjA2NTgxNywzNjAwMzUyODA0LDQwOTQ1NzE5MDksMjc1NDIzMzQ0LDQzMDIyNzczNCw1MDY5NDg2MTYsNjU5MDYwNTU2LDg4Mzk5Nzg3Nyw5NTgxMzk1NzEsMTMyMjgyMjIxOCwxNTM3MDAyMDYzLDE3NDc4NzM3NzksMTk1NTU2MjIyMiwyMDI0MTA0ODE1LDIyMjc3MzA0NTIsMjM2MTg1MjQyNCwyNDI4NDM2NDc0LDI3NTY3MzQxODcsMzIwNDAzMTQ3OSwzMzI5MzI1Mjk4XSxsPVsiaGV4IiwiYXJyYXkiLCJkaWdlc3QiLCJhcnJheUJ1ZmZlciJdLGQ9W107IXMuSlNfU0hBMjU2X05PX05PREVfSlMmJkFycmF5LmlzQXJyYXl8fChBcnJheS5pc0FycmF5PWZ1bmN0aW9uKHQpe3JldHVybiJbb2JqZWN0IEFycmF5XSI9PT1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodCl9KSwhZnx8IXMuSlNfU0hBMjU2X05PX0FSUkFZX0JVRkZFUl9JU19WSUVXJiZBcnJheUJ1ZmZlci5pc1ZpZXd8fChBcnJheUJ1ZmZlci5pc1ZpZXc9ZnVuY3Rpb24odCl7cmV0dXJuIm9iamVjdCI9PXR5cGVvZiB0JiZ0LmJ1ZmZlciYmdC5idWZmZXIuY29uc3RydWN0b3I9PT1BcnJheUJ1ZmZlcn0pO3ZhciBBPWZ1bmN0aW9uKGksaCl7cmV0dXJuIGZ1bmN0aW9uKHIpe3JldHVybiBuZXcgdChoLCEwKS51cGRhdGUocilbaV0oKX19LHc9ZnVuY3Rpb24oaSl7dmFyIGg9QSgiaGV4IixpKTtuJiYoaD1iKGgsaSkpLGguY3JlYXRlPWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyB0KGkpfSxoLnVwZGF0ZT1mdW5jdGlvbih0KXtyZXR1cm4gaC5jcmVhdGUoKS51cGRhdGUodCl9O2Zvcih2YXIgcj0wO3I8bC5sZW5ndGg7KytyKXt2YXIgcz1sW3JdO2hbc109QShzLGkpfXJldHVybiBofSxiPWZ1bmN0aW9uKHQsaSl7dmFyIHI9ZXZhbCgicmVxdWlyZSgnY3J5cHRvJykiKSxzPWV2YWwoInJlcXVpcmUoJ2J1ZmZlcicpLkJ1ZmZlciIpLGU9aT8ic2hhMjI0Ijoic2hhMjU2IixuPWZ1bmN0aW9uKGkpe2lmKCJzdHJpbmciPT10eXBlb2YgaSlyZXR1cm4gci5jcmVhdGVIYXNoKGUpLnVwZGF0ZShpLCJ1dGY4IikuZGlnZXN0KCJoZXgiKTtpZihudWxsPT09aXx8dm9pZCAwPT09aSl0aHJvdyBuZXcgRXJyb3IoaCk7cmV0dXJuIGkuY29uc3RydWN0b3I9PT1BcnJheUJ1ZmZlciYmKGk9bmV3IFVpbnQ4QXJyYXkoaSkpLEFycmF5LmlzQXJyYXkoaSl8fEFycmF5QnVmZmVyLmlzVmlldyhpKXx8aS5jb25zdHJ1Y3Rvcj09PXM/ci5jcmVhdGVIYXNoKGUpLnVwZGF0ZShuZXcgcyhpKSkuZGlnZXN0KCJoZXgiKTp0KGkpfTtyZXR1cm4gbn0sdj1mdW5jdGlvbih0LGgpe3JldHVybiBmdW5jdGlvbihyLHMpe3JldHVybiBuZXcgaShyLGgsITApLnVwZGF0ZShzKVt0XSgpfX0sXz1mdW5jdGlvbih0KXt2YXIgaD12KCJoZXgiLHQpO2guY3JlYXRlPWZ1bmN0aW9uKGgpe3JldHVybiBuZXcgaShoLHQpfSxoLnVwZGF0ZT1mdW5jdGlvbih0LGkpe3JldHVybiBoLmNyZWF0ZSh0KS51cGRhdGUoaSl9O2Zvcih2YXIgcj0wO3I8bC5sZW5ndGg7KytyKXt2YXIgcz1sW3JdO2hbc109dihzLHQpfXJldHVybiBofTt0LnByb3RvdHlwZS51cGRhdGU9ZnVuY3Rpb24odCl7aWYoIXRoaXMuZmluYWxpemVkKXt2YXIgaSxyPXR5cGVvZiB0O2lmKCJzdHJpbmciIT09cil7aWYoIm9iamVjdCIhPT1yKXRocm93IG5ldyBFcnJvcihoKTtpZihudWxsPT09dCl0aHJvdyBuZXcgRXJyb3IoaCk7aWYoZiYmdC5jb25zdHJ1Y3Rvcj09PUFycmF5QnVmZmVyKXQ9bmV3IFVpbnQ4QXJyYXkodCk7ZWxzZSBpZighKEFycmF5LmlzQXJyYXkodCl8fGYmJkFycmF5QnVmZmVyLmlzVmlldyh0KSkpdGhyb3cgbmV3IEVycm9yKGgpO2k9ITB9Zm9yKHZhciBzLGUsbj0wLG89dC5sZW5ndGgsYT10aGlzLmJsb2NrcztuPG87KXtpZih0aGlzLmhhc2hlZCYmKHRoaXMuaGFzaGVkPSExLGFbMF09dGhpcy5ibG9jayxhWzE2XT1hWzFdPWFbMl09YVszXT1hWzRdPWFbNV09YVs2XT1hWzddPWFbOF09YVs5XT1hWzEwXT1hWzExXT1hWzEyXT1hWzEzXT1hWzE0XT1hWzE1XT0wKSxpKWZvcihlPXRoaXMuc3RhcnQ7bjxvJiZlPDY0OysrbilhW2U+PjJdfD10W25dPDx5WzMmZSsrXTtlbHNlIGZvcihlPXRoaXMuc3RhcnQ7bjxvJiZlPDY0Oysrbikocz10LmNoYXJDb2RlQXQobikpPDEyOD9hW2U+PjJdfD1zPDx5WzMmZSsrXTpzPDIwNDg/KGFbZT4+Ml18PSgxOTJ8cz4+Nik8PHlbMyZlKytdLGFbZT4+Ml18PSgxMjh8NjMmcyk8PHlbMyZlKytdKTpzPDU1Mjk2fHxzPj01NzM0ND8oYVtlPj4yXXw9KDIyNHxzPj4xMik8PHlbMyZlKytdLGFbZT4+Ml18PSgxMjh8cz4+NiY2Myk8PHlbMyZlKytdLGFbZT4+Ml18PSgxMjh8NjMmcyk8PHlbMyZlKytdKToocz02NTUzNisoKDEwMjMmcyk8PDEwfDEwMjMmdC5jaGFyQ29kZUF0KCsrbikpLGFbZT4+Ml18PSgyNDB8cz4+MTgpPDx5WzMmZSsrXSxhW2U+PjJdfD0oMTI4fHM+PjEyJjYzKTw8eVszJmUrK10sYVtlPj4yXXw9KDEyOHxzPj42JjYzKTw8eVszJmUrK10sYVtlPj4yXXw9KDEyOHw2MyZzKTw8eVszJmUrK10pO3RoaXMubGFzdEJ5dGVJbmRleD1lLHRoaXMuYnl0ZXMrPWUtdGhpcy5zdGFydCxlPj02ND8odGhpcy5ibG9jaz1hWzE2XSx0aGlzLnN0YXJ0PWUtNjQsdGhpcy5oYXNoKCksdGhpcy5oYXNoZWQ9ITApOnRoaXMuc3RhcnQ9ZX1yZXR1cm4gdGhpcy5ieXRlcz40Mjk0OTY3Mjk1JiYodGhpcy5oQnl0ZXMrPXRoaXMuYnl0ZXMvNDI5NDk2NzI5Njw8MCx0aGlzLmJ5dGVzPXRoaXMuYnl0ZXMlNDI5NDk2NzI5NiksdGhpc319LHQucHJvdG90eXBlLmZpbmFsaXplPWZ1bmN0aW9uKCl7aWYoIXRoaXMuZmluYWxpemVkKXt0aGlzLmZpbmFsaXplZD0hMDt2YXIgdD10aGlzLmJsb2NrcyxpPXRoaXMubGFzdEJ5dGVJbmRleDt0WzE2XT10aGlzLmJsb2NrLHRbaT4+Ml18PWNbMyZpXSx0aGlzLmJsb2NrPXRbMTZdLGk+PTU2JiYodGhpcy5oYXNoZWR8fHRoaXMuaGFzaCgpLHRbMF09dGhpcy5ibG9jayx0WzE2XT10WzFdPXRbMl09dFszXT10WzRdPXRbNV09dFs2XT10WzddPXRbOF09dFs5XT10WzEwXT10WzExXT10WzEyXT10WzEzXT10WzE0XT10WzE1XT0wKSx0WzE0XT10aGlzLmhCeXRlczw8M3x0aGlzLmJ5dGVzPj4+MjksdFsxNV09dGhpcy5ieXRlczw8Myx0aGlzLmhhc2goKX19LHQucHJvdG90eXBlLmhhc2g9ZnVuY3Rpb24oKXt2YXIgdCxpLGgscixzLGUsbixvLGEsZj10aGlzLmgwLHU9dGhpcy5oMSxjPXRoaXMuaDIseT10aGlzLmgzLGw9dGhpcy5oNCxkPXRoaXMuaDUsQT10aGlzLmg2LHc9dGhpcy5oNyxiPXRoaXMuYmxvY2tzO2Zvcih0PTE2O3Q8NjQ7Kyt0KWk9KChzPWJbdC0xNV0pPj4+N3xzPDwyNSleKHM+Pj4xOHxzPDwxNClecz4+PjMsaD0oKHM9Ylt0LTJdKT4+PjE3fHM8PDE1KV4ocz4+PjE5fHM8PDEzKV5zPj4+MTAsYlt0XT1iW3QtMTZdK2krYlt0LTddK2g8PDA7Zm9yKGE9dSZjLHQ9MDt0PDY0O3QrPTQpdGhpcy5maXJzdD8odGhpcy5pczIyND8oZT0zMDAwMzIsdz0ocz1iWzBdLTE0MTMyNTc4MTkpLTE1MDA1NDU5OTw8MCx5PXMrMjQxNzcwNzc8PDApOihlPTcwNDc1MTEwOSx3PShzPWJbMF0tMjEwMjQ0MjQ4KS0xNTIxNDg2NTM0PDwwLHk9cysxNDM2OTQ1NjU8PDApLHRoaXMuZmlyc3Q9ITEpOihpPShmPj4+MnxmPDwzMCleKGY+Pj4xM3xmPDwxOSleKGY+Pj4yMnxmPDwxMCkscj0oZT1mJnUpXmYmY15hLHc9eSsocz13KyhoPShsPj4+NnxsPDwyNileKGw+Pj4xMXxsPDwyMSleKGw+Pj4yNXxsPDw3KSkrKGwmZF5+bCZBKStwW3RdK2JbdF0pPDwwLHk9cysoaStyKTw8MCksaT0oeT4+PjJ8eTw8MzApXih5Pj4+MTN8eTw8MTkpXih5Pj4+MjJ8eTw8MTApLHI9KG49eSZmKV55JnVeZSxBPWMrKHM9QSsoaD0odz4+PjZ8dzw8MjYpXih3Pj4+MTF8dzw8MjEpXih3Pj4+MjV8dzw8NykpKyh3JmxefncmZCkrcFt0KzFdK2JbdCsxXSk8PDAsaT0oKGM9cysoaStyKTw8MCk+Pj4yfGM8PDMwKV4oYz4+PjEzfGM8PDE5KV4oYz4+PjIyfGM8PDEwKSxyPShvPWMmeSleYyZmXm4sZD11KyhzPWQrKGg9KEE+Pj42fEE8PDI2KV4oQT4+PjExfEE8PDIxKV4oQT4+PjI1fEE8PDcpKSsoQSZ3Xn5BJmwpK3BbdCsyXStiW3QrMl0pPDwwLGk9KCh1PXMrKGkrcik8PDApPj4+Mnx1PDwzMCleKHU+Pj4xM3x1PDwxOSleKHU+Pj4yMnx1PDwxMCkscj0oYT11JmMpXnUmeV5vLGw9Zisocz1sKyhoPShkPj4+NnxkPDwyNileKGQ+Pj4xMXxkPDwyMSleKGQ+Pj4yNXxkPDw3KSkrKGQmQV5+ZCZ3KStwW3QrM10rYlt0KzNdKTw8MCxmPXMrKGkrcik8PDA7dGhpcy5oMD10aGlzLmgwK2Y8PDAsdGhpcy5oMT10aGlzLmgxK3U8PDAsdGhpcy5oMj10aGlzLmgyK2M8PDAsdGhpcy5oMz10aGlzLmgzK3k8PDAsdGhpcy5oND10aGlzLmg0K2w8PDAsdGhpcy5oNT10aGlzLmg1K2Q8PDAsdGhpcy5oNj10aGlzLmg2K0E8PDAsdGhpcy5oNz10aGlzLmg3K3c8PDB9LHQucHJvdG90eXBlLmhleD1mdW5jdGlvbigpe3RoaXMuZmluYWxpemUoKTt2YXIgdD10aGlzLmgwLGk9dGhpcy5oMSxoPXRoaXMuaDIscj10aGlzLmgzLHM9dGhpcy5oNCxlPXRoaXMuaDUsbj10aGlzLmg2LG89dGhpcy5oNyxhPXVbdD4+MjgmMTVdK3VbdD4+MjQmMTVdK3VbdD4+MjAmMTVdK3VbdD4+MTYmMTVdK3VbdD4+MTImMTVdK3VbdD4+OCYxNV0rdVt0Pj40JjE1XSt1WzE1JnRdK3VbaT4+MjgmMTVdK3VbaT4+MjQmMTVdK3VbaT4+MjAmMTVdK3VbaT4+MTYmMTVdK3VbaT4+MTImMTVdK3VbaT4+OCYxNV0rdVtpPj40JjE1XSt1WzE1JmldK3VbaD4+MjgmMTVdK3VbaD4+MjQmMTVdK3VbaD4+MjAmMTVdK3VbaD4+MTYmMTVdK3VbaD4+MTImMTVdK3VbaD4+OCYxNV0rdVtoPj40JjE1XSt1WzE1JmhdK3Vbcj4+MjgmMTVdK3Vbcj4+MjQmMTVdK3Vbcj4+MjAmMTVdK3Vbcj4+MTYmMTVdK3Vbcj4+MTImMTVdK3Vbcj4+OCYxNV0rdVtyPj40JjE1XSt1WzE1JnJdK3Vbcz4+MjgmMTVdK3Vbcz4+MjQmMTVdK3Vbcz4+MjAmMTVdK3Vbcz4+MTYmMTVdK3Vbcz4+MTImMTVdK3Vbcz4+OCYxNV0rdVtzPj40JjE1XSt1WzE1JnNdK3VbZT4+MjgmMTVdK3VbZT4+MjQmMTVdK3VbZT4+MjAmMTVdK3VbZT4+MTYmMTVdK3VbZT4+MTImMTVdK3VbZT4+OCYxNV0rdVtlPj40JjE1XSt1WzE1JmVdK3Vbbj4+MjgmMTVdK3Vbbj4+MjQmMTVdK3Vbbj4+MjAmMTVdK3Vbbj4+MTYmMTVdK3Vbbj4+MTImMTVdK3Vbbj4+OCYxNV0rdVtuPj40JjE1XSt1WzE1Jm5dO3JldHVybiB0aGlzLmlzMjI0fHwoYSs9dVtvPj4yOCYxNV0rdVtvPj4yNCYxNV0rdVtvPj4yMCYxNV0rdVtvPj4xNiYxNV0rdVtvPj4xMiYxNV0rdVtvPj44JjE1XSt1W28+PjQmMTVdK3VbMTUmb10pLGF9LHQucHJvdG90eXBlLnRvU3RyaW5nPXQucHJvdG90eXBlLmhleCx0LnByb3RvdHlwZS5kaWdlc3Q9ZnVuY3Rpb24oKXt0aGlzLmZpbmFsaXplKCk7dmFyIHQ9dGhpcy5oMCxpPXRoaXMuaDEsaD10aGlzLmgyLHI9dGhpcy5oMyxzPXRoaXMuaDQsZT10aGlzLmg1LG49dGhpcy5oNixvPXRoaXMuaDcsYT1bdD4+MjQmMjU1LHQ+PjE2JjI1NSx0Pj44JjI1NSwyNTUmdCxpPj4yNCYyNTUsaT4+MTYmMjU1LGk+PjgmMjU1LDI1NSZpLGg+PjI0JjI1NSxoPj4xNiYyNTUsaD4+OCYyNTUsMjU1Jmgscj4+MjQmMjU1LHI+PjE2JjI1NSxyPj44JjI1NSwyNTUmcixzPj4yNCYyNTUscz4+MTYmMjU1LHM+PjgmMjU1LDI1NSZzLGU+PjI0JjI1NSxlPj4xNiYyNTUsZT4+OCYyNTUsMjU1JmUsbj4+MjQmMjU1LG4+PjE2JjI1NSxuPj44JjI1NSwyNTUmbl07cmV0dXJuIHRoaXMuaXMyMjR8fGEucHVzaChvPj4yNCYyNTUsbz4+MTYmMjU1LG8+PjgmMjU1LDI1NSZvKSxhfSx0LnByb3RvdHlwZS5hcnJheT10LnByb3RvdHlwZS5kaWdlc3QsdC5wcm90b3R5cGUuYXJyYXlCdWZmZXI9ZnVuY3Rpb24oKXt0aGlzLmZpbmFsaXplKCk7dmFyIHQ9bmV3IEFycmF5QnVmZmVyKHRoaXMuaXMyMjQ/Mjg6MzIpLGk9bmV3IERhdGFWaWV3KHQpO3JldHVybiBpLnNldFVpbnQzMigwLHRoaXMuaDApLGkuc2V0VWludDMyKDQsdGhpcy5oMSksaS5zZXRVaW50MzIoOCx0aGlzLmgyKSxpLnNldFVpbnQzMigxMix0aGlzLmgzKSxpLnNldFVpbnQzMigxNix0aGlzLmg0KSxpLnNldFVpbnQzMigyMCx0aGlzLmg1KSxpLnNldFVpbnQzMigyNCx0aGlzLmg2KSx0aGlzLmlzMjI0fHxpLnNldFVpbnQzMigyOCx0aGlzLmg3KSx0fSxpLnByb3RvdHlwZT1uZXcgdCxpLnByb3RvdHlwZS5maW5hbGl6ZT1mdW5jdGlvbigpe2lmKHQucHJvdG90eXBlLmZpbmFsaXplLmNhbGwodGhpcyksdGhpcy5pbm5lcil7dGhpcy5pbm5lcj0hMTt2YXIgaT10aGlzLmFycmF5KCk7dC5jYWxsKHRoaXMsdGhpcy5pczIyNCx0aGlzLnNoYXJlZE1lbW9yeSksdGhpcy51cGRhdGUodGhpcy5vS2V5UGFkKSx0aGlzLnVwZGF0ZShpKSx0LnByb3RvdHlwZS5maW5hbGl6ZS5jYWxsKHRoaXMpfX07dmFyIEI9dygpO0Iuc2hhMjU2PUIsQi5zaGEyMjQ9dyghMCksQi5zaGEyNTYuaG1hYz1fKCksQi5zaGEyMjQuaG1hYz1fKCEwKSxvP21vZHVsZS5leHBvcnRzPUI6KHMuc2hhMjU2PUIuc2hhMjU2LHMuc2hhMjI0PUIuc2hhMjI0LGEmJmRlZmluZShmdW5jdGlvbigpe3JldHVybiBCfSkpfSgpOw==")}\n // let challenge = null, salt = null;\n self.onmessage = e => {\n const d = e.data;\n if (d.init) { challenge = d.challenge; salt = d.salt; return; }\n const { start, end } = d;\n for (let i = start; i <= end; i++) {\n if (sha256(salt + i) === challenge) {\n postMessage(i);\n return;\n }\n }\n postMessage(null);\n };\n `;
this.blobUrl = URL.createObjectURL(new Blob([ workerCode ], {
type: "application/javascript"
}));
for (let i = 0; i < this.coreCount; i++) {
this.workers.push(new Worker(this.blobUrl)), this.workers[i].postMessage({
init: !0,
challenge: challenge,
salt: salt
});
}
}
async getChallenge() {
return (await fetch("https://api.moomoo.io/verify")).json();
}
async solve(chal) {
let {challenge: challenge, salt: salt, maxnumber: maxnumber} = chal;
this.initPool(challenge, salt);
let segSize = Math.ceil(maxnumber / this.coreCount);
return new Promise((resolve, reject) => {
let solved = !1, done = 0, startTime = performance.now();
this.workers.forEach((worker, idx) => {
let s = idx * segSize, e = Math.min(maxnumber, (idx + 1) * segSize - 1);
worker.onmessage = msg => {
if (solved) {
return;
}
let number = msg.data;
if (number !== null) {
solved = !0;
let took = ((performance.now() - startTime) / 1e3).toFixed(2);
resolve({
number: number,
took: took
}), this.cleanup();
} else if (done++, !solved && done === this.coreCount) {
reject(Error("Not solved")), this.cleanup();
}
}, worker.onerror = err => {
if (!solved) {
reject(err);
}
this.cleanup();
}, worker.postMessage({
start: s,
end: e
});
});
});
}
cleanup() {
if (this.workers.forEach(w => w.terminate()), this.workers.length = 0, this.blobUrl) {
URL.revokeObjectURL(this.blobUrl);
}
this.blobUrl = null;
}
static makePayload(chal, result) {
return btoa(JSON.stringify({
algorithm: "SHA-256",
challenge: chal.challenge,
salt: chal.salt,
signature: chal.signature || null,
number: result.number,
took: result.took
}));
}
async generate() {
let chal = await this.getChallenge(), sol = await this.solve(chal);
return "alt:" + Altcha.makePayload(chal, sol);
}
}
// ==================================================================
// HLM - ALTCHA REMPLACE PAR CLOUDFLARE TURNSTILE
// moomoo.io ne sert plus de defi altcha : api.moomoo.io/verify a
// disparu et le prefixe de jeton "alt:" n'est plus reconnu. La
// connexion principale est ouverte par le jeu lui-meme, qui gere
// Turnstile de son cote - elle n'a besoin de rien ici.
// Cette fonction ne sert qu'aux bots : on reutilise donc l'adresse
// du socket principal, jeton compris, au lieu d'en fabriquer un.
// ==================================================================
// ==================================================================
// HLM - UN JETON TURNSTILE FRAIS PAR BOT
//
// Un jeton Cloudflare ne sert qu'une fois : celui du menu a ete
// consomme par la connexion principale. On rend donc notre propre
// widget, avec la cle publique du jeu, et on le reinitialise pour
// obtenir un jeton par bot. C'est la seule facon d'ouvrir une
// connexion supplementaire acceptee par le serveur.
// ==================================================================
// ==================================================================
// HLM - JETON POUR LES BOTS : WIDGET DEDIE ET VISIBLE
//
// Historique des tentatives, pour ne pas y revenir :
// 1. widget cache -> Turnstile ne resout pas un widget non rendu
// 2. reset du widget du jeu -> son iframe reste "about:blank", d'ou
// "postMessage ... target origin challenges.cloudflare.com does not
// match ... sandbox.moomoo.io" : Turnstile parle a un cadre qui n'a
// jamais charge. Un reset ne le ressuscite pas.
//
// On rend donc un widget NEUF, reellement visible, dans un coin, et on
// le retire des que le jeton est arrive. Un rendu neuf par bot : pas de
// reset, pas d'etat a recycler.
// ==================================================================
// Cles publiques lues dans le bundle du jeu :
// La = We ? "1x00000000000000000000AA" : "0x4AAAAAAAMYHI96GFiJzMmp"
// We designe le developpement local, donc sandbox utilise la seconde.
const HLM_SITEKEY = /^(localhost|127\.)/.test(window.location.hostname)
? "1x00000000000000000000AA"
: "0x4AAAAAAAMYHI96GFiJzMmp";
let hlmTokenWaiter = null, hlmTokenTimer = null, hlmBox = null, hlmWidgetId = null;
function hlmCleanupWidget() {
try {
if (hlmWidgetId !== null && window.turnstile && window.turnstile.remove) {
window.turnstile.remove(hlmWidgetId);
}
} catch (err) { /* rien a faire */ }
hlmWidgetId = null;
if (hlmBox !== null) {
hlmBox.remove(), hlmBox = null;
}
}
function hlmTokenSettle(token) {
let done = hlmTokenWaiter;
hlmTokenWaiter = null;
if (hlmTokenTimer !== null) {
clearTimeout(hlmTokenTimer), hlmTokenTimer = null;
}
hlmCleanupWidget();
console.log("[HLM] jeton pour le bot :", token ? "obtenu" : "ABSENT");
if (done !== null) done(token || null);
}
window.__hlmTokenDelivery = function() { /* plus utilise : widget dedie */ };
// Les demandes doivent etre SERIALISEES : il n'y a qu'un widget a la
// fois. Avant, une demande simultanee etait refusee - "une demande de
// jeton est deja en cours" - et le bot concerne partait sans jeton,
// donc se faisait fermer en 4001. On les met desormais en file.
let hlmTokenQueue = Promise.resolve();
function hlmRenderOnce() {
return new Promise(resolve => {
let ts = window.turnstile;
if (!ts || typeof ts.render !== "function") {
console.warn("[HLM] turnstile indisponible : le bot partira sans jeton");
return resolve(null);
}
hlmTokenWaiter = resolve;
hlmTokenTimer = setTimeout(() => {
console.warn("[HLM] jeton turnstile non obtenu (delai depasse)");
hlmTokenSettle(null);
}, 3e4);
hlmCleanupWidget();
hlmBox = document.createElement("div");
hlmBox.id = "hlmTurnstileBox";
// Volontairement VISIBLE : c'est la condition pour que Cloudflare
// accepte de resoudre. Il disparait des que le jeton arrive.
hlmBox.style.cssText = "position:fixed;right:10px;bottom:10px;width:300px;"
+ "height:65px;z-index:2147483647;background:#fff;border-radius:4px;";
document.body.appendChild(hlmBox);
try {
hlmWidgetId = ts.render(hlmBox, {
sitekey: HLM_SITEKEY,
theme: "light",
callback: t => hlmTokenSettle(t || null),
"error-callback": () => {
console.warn("[HLM] turnstile a signale une erreur");
hlmTokenSettle(null);
},
"expired-callback": () => hlmTokenSettle(null)
});
console.log("[HLM] widget dedie rendu, identifiant :", hlmWidgetId,
" | cle :", HLM_SITEKEY);
if (hlmWidgetId === null || hlmWidgetId === undefined) {
hlmTokenSettle(null);
}
} catch (err) {
console.error("[HLM] rendu du widget dedie impossible", err);
hlmTokenSettle(null);
}
});
}
function hlmFreshToken() {
// Un seul rendu a la fois, chacun son tour. Une seconde tentative
// si la premiere revient a vide : un echec isole ne doit pas
// condamner le bot.
let run = async () => {
let token = await hlmRenderOnce();
if (token === null) {
console.warn("[HLM] premiere tentative sans jeton, nouvel essai");
await new Promise(r => setTimeout(r, 800));
token = await hlmRenderOnce();
}
return token;
};
let p = hlmTokenQueue.then(run, run);
hlmTokenQueue = p.then(() => undefined, () => undefined);
return p;
}
const altcha = new Altcha, createSocket = async href => {
let url = href;
try {
let token = await hlmFreshToken();
if (token !== null) {
let u = new URL(href);
u.search = "";
url = u.href + "?token=" + encodeURIComponent("cf:" + token);
} else {
console.error("[HLM] ce bot part SANS jeton : le serveur le fermera"
+ " en 4001. Ajoute-le a nouveau dans quelques secondes.");
}
} catch (err) {
console.error("[HLM] jeton du bot indisponible", err);
}
let ws = new WebSocket(url);
return ws.binaryType = "arraybuffer", ws;
}, createSocket_default = createSocket;
const Hooker = new class {
createRecursiveHook(target, prop, callback) {
let newValue = target[prop];
(function recursiveHook() {
Object.defineProperty(target, prop, {
set(value) {
if (delete target[prop], this[prop] = value, newValue = value, callback(this, value)) {
return;
}
recursiveHook();
},
get() {
return newValue;
},
configurable: !0
});
})();
}
createHook(target, prop, callback) {
let symbol = Symbol(prop);
Object.defineProperty(target, prop, {
get() {
return this[symbol];
},
set(value) {
callback(this, value, symbol);
},
configurable: !0
});
}
linker(value) {
let hook = [ value ];
return hook.valueOf = () => hook[0], hook;
}
}, blockProperty = (target, key) => {
let value = target[key];
Object.defineProperty(target, key, {
set() {},
get() {
return value;
},
configurable: !0
});
}, Hooker_default = Hooker;
const Config = {
maxScreenWidth: 1920,
maxScreenHeight: 1080,
serverUpdateRate: 9,
collisionDepth: 6,
minimapRate: 3e3,
colGrid: 10,
clientSendRate: 5,
barWidth: 50,
barHeight: 17,
barPad: 4.5,
iconPadding: 15,
iconPad: .9,
deathFadeout: 3e3,
crownIconScale: 60,
crownPad: 35,
chatCountdown: 3e3,
chatCooldown: 500,
maxAge: 100,
gatherAngle: Math.PI / 2.6,
gatherWiggle: 10,
hitReturnRatio: .25,
hitAngle: Math.PI / 2,
playerScale: 35,
playerSpeed: .0016,
playerDecel: .993,
nameY: 34,
animalCount: 7,
aiTurnRandom: .06,
shieldAngle: Math.PI / 3,
resourceTypes: [ "wood", "food", "stone", "points" ],
areaCount: 7,
treesPerArea: 9,
bushesPerArea: 3,
totalRocks: 32,
goldOres: 7,
riverWidth: 724,
riverPadding: 114,
waterCurrent: .0011,
waveSpeed: 1e-4,
waveMax: 1.3,
treeScales: [ 150, 160, 165, 175 ],
bushScales: [ 80, 85, 95 ],
rockScales: [ 80, 85, 90 ],
snowBiomeTop: 2400,
desertBiomeTop: 2400,
snowSpeed: .75,
maxNameLength: 15,
mapScale: 14400,
mapPingScale: 40,
mapPingTime: 2200,
skinColors: [ "#bf8f54", "#cbb091", "#896c4b", "#fadadc", "#ececec", "#c37373", "#4c4c4c", "#ecaff7", "#738cc3", "#8bc373", "#91B2DB" ]
}, Config_default = Config;
const WeaponTypeString = [ "primary", "secondary" ];
const Weapons = [ {
id: 0,
itemType: 0,
upgradeType: 0,
type: 0,
age: 0,
name: "tool hammer",
description: "tool for gathering all resources",
src: "hammer_1",
length: 140,
width: 140,
xOffset: -3,
yOffset: 18,
spdMult: 1,
damage: 25,
range: 65,
gather: 1,
speed: 300,
knockback: 60
}, {
id: 1,
itemType: 0,
upgradeType: 1,
type: 0,
age: 2,
name: "hand axe",
description: "gathers resources at a higher rate",
src: "axe_1",
length: 140,
width: 140,
xOffset: 3,
yOffset: 24,
damage: 30,
spdMult: 1,
range: 70,
gather: 2,
speed: 400,
knockback: 60
}, {
id: 2,
itemType: 0,
upgradeOf: 1,
upgradeType: 1,
type: 0,
age: 8,
pre: 1,
name: "great axe",
description: "deal more damage and gather more resources",
src: "great_axe_1",
length: 140,
width: 140,
xOffset: -8,
yOffset: 25,
damage: 35,
spdMult: 1,
range: 75,
gather: 4,
speed: 400,
knockback: 60
}, {
id: 3,
itemType: 0,
upgradeType: 2,
type: 0,
age: 2,
name: "short sword",
description: "increased attack power but slower move speed",
src: "sword_1",
iPad: 1.3,
length: 130,
width: 210,
xOffset: -8,
yOffset: 46,
damage: 35,
spdMult: .85,
range: 110,
gather: 1,
speed: 300,
knockback: 60
}, {
id: 4,
itemType: 0,
upgradeOf: 3,
upgradeType: 2,
type: 0,
age: 8,
pre: 3,
name: "katana",
description: "greater range and damage",
src: "samurai_1",
iPad: 1.3,
length: 130,
width: 210,
xOffset: -8,
yOffset: 59,
damage: 40,
spdMult: .8,
range: 118,
gather: 1,
speed: 300,
knockback: 60
}, {
id: 5,
itemType: 0,
upgradeType: 3,
isUpgrade: !1,
type: 0,
age: 2,
name: "polearm",
description: "long range melee weapon",
src: "spear_1",
iPad: 1.3,
length: 130,
width: 210,
xOffset: -8,
yOffset: 53,
damage: 45,
knock: .2,
spdMult: .82,
range: 142,
gather: 1,
speed: 700,
knockback: 100
}, {
id: 6,
itemType: 0,
upgradeType: 4,
isUpgrade: !1,
type: 0,
age: 2,
name: "bat",
description: "fast long range melee weapon",
src: "bat_1",
iPad: 1.3,
length: 110,
width: 180,
xOffset: -8,
yOffset: 53,
damage: 20,
knock: .7,
spdMult: 1,
range: 110,
gather: 1,
speed: 300,
knockback: 204
}, {
id: 7,
itemType: 0,
upgradeType: 5,
isUpgrade: !1,
type: 0,
age: 2,
name: "daggers",
description: "really fast short range weapon",
src: "dagger_1",
iPad: .8,
length: 110,
width: 110,
xOffset: 18,
yOffset: 0,
damage: 20,
knock: .1,
range: 65,
gather: 1,
hitSlow: .1,
spdMult: 1.13,
speed: 100,
knockback: 80
}, {
id: 8,
itemType: 0,
upgradeType: 6,
isUpgrade: !1,
type: 0,
age: 2,
name: "stick",
description: "great for gathering but very weak",
src: "stick_1",
length: 140,
width: 140,
xOffset: 3,
yOffset: 24,
damage: 1,
spdMult: 1,
range: 70,
gather: 7,
speed: 400,
knockback: 60
}, {
id: 9,
itemType: 1,
upgradeType: 7,
projectile: 0,
type: 1,
age: 6,
name: "hunting bow",
description: "bow used for ranged combat and hunting",
src: "bow_1",
cost: {
food: 0,
wood: 4,
stone: 0,
gold: 0
},
length: 120,
width: 120,
xOffset: -6,
yOffset: 0,
spdMult: .75,
speed: 600,
range: 1e3,
knockback: 60
}, {
id: 10,
itemType: 1,
upgradeType: 8,
isUpgrade: !1,
type: 1,
age: 6,
name: "great hammer",
description: "hammer used for destroying structures",
src: "great_hammer_1",
length: 140,
width: 140,
xOffset: -9,
yOffset: 25,
damage: 10,
spdMult: .88,
range: 75,
sDmg: 7.5,
gather: 1,
speed: 400,
knockback: 60
}, {
id: 11,
itemType: 1,
upgradeType: 9,
isUpgrade: !1,
type: 1,
age: 6,
name: "wooden shield",
description: "blocks projectiles and reduces melee damage",
src: "shield_1",
length: 120,
width: 120,
shield: .2,
xOffset: 6,
yOffset: 0,
spdMult: .7,
speed: 1,
range: 0,
knockback: 0
}, {
id: 12,
itemType: 1,
upgradeType: 7,
projectile: 2,
upgradeOf: 9,
type: 1,
age: 8,
pre: 9,
name: "crossbow",
description: "deals more damage and has greater range",
src: "crossbow_1",
cost: {
food: 0,
wood: 5,
stone: 0,
gold: 0
},
aboveHand: !0,
armS: .75,
length: 120,
width: 120,
xOffset: -4,
yOffset: 0,
spdMult: .7,
speed: 700,
range: 1200,
knockback: 60
}, {
id: 13,
itemType: 1,
upgradeType: 7,
projectile: 3,
upgradeOf: 12,
type: 1,
age: 9,
pre: 12,
name: "repeater crossbow",
description: "high firerate crossbow with reduced damage",
src: "crossbow_2",
cost: {
food: 0,
wood: 10,
stone: 0,
gold: 0
},
aboveHand: !0,
armS: .75,
length: 120,
width: 120,
xOffset: -4,
yOffset: 0,
spdMult: .7,
speed: 230,
range: 1200,
knockback: 60
}, {
id: 14,
itemType: 1,
upgradeType: 10,
isUpgrade: !1,
type: 1,
age: 6,
name: "mc grabby",
description: "steals resources from enemies",
src: "grab_1",
length: 130,
width: 210,
xOffset: -8,
yOffset: 53,
damage: 0,
steal: 250,
knock: .2,
spdMult: 1.05,
range: 125,
gather: 0,
speed: 700,
knockback: 100
}, {
id: 15,
itemType: 1,
upgradeType: 7,
projectile: 5,
upgradeOf: 12,
type: 1,
age: 9,
pre: 12,
name: "musket",
description: "slow firerate but high damage and range",
src: "musket_1",
cost: {
food: 0,
wood: 0,
stone: 10,
gold: 0
},
aboveHand: !0,
rec: .35,
armS: .6,
hndS: .3,
hndD: 1.6,
length: 205,
width: 205,
xOffset: 25,
yOffset: 0,
hideProjectile: !0,
spdMult: .6,
speed: 1500,
range: 1400,
knockback: 60
} ], ItemGroups = {
1: {
name: "Wall",
limit: 30,
layer: 0
},
2: {
name: "Spike",
limit: 15,
layer: 0
},
3: {
name: "Windmill",
limit: 7,
sandboxLimit: 299,
layer: 1
},
4: {
name: "Mine",
limit: 1,
layer: 0
},
5: {
name: "Trap",
limit: 6,
layer: -1
},
6: {
name: "Boost",
limit: 12,
sandboxLimit: 299,
layer: -1
},
7: {
name: "Turret",
limit: 2,
layer: 1
},
8: {
name: "Plaftorm",
limit: 12,
layer: -1
},
9: {
name: "Healing pad",
limit: 4,
layer: -1
},
10: {
name: "Spawn",
limit: 1,
layer: -1
},
11: {
name: "Sapling",
limit: 2,
layer: 0
},
12: {
name: "Blocker",
limit: 3,
layer: -1
},
13: {
name: "Teleporter",
limit: 2,
sandboxLimit: 299,
layer: -1
}
}, Items = [ {
id: 0,
itemType: 2,
name: "apple",
description: "restores 20 health when consumed",
age: 0,
cost: {
food: 10,
wood: 0,
stone: 0,
gold: 0
},
restore: 20,
scale: 22,
holdOffset: 15
}, {
id: 1,
itemType: 2,
upgradeOf: 0,
name: "cookie",
description: "restores 40 health when consumed",
age: 3,
cost: {
food: 15,
wood: 0,
stone: 0,
gold: 0
},
restore: 40,
scale: 27,
holdOffset: 15
}, {
id: 2,
itemType: 2,
upgradeOf: 1,
name: "cheese",
description: "restores 30 health and another 50 over 5 seconds",
age: 7,
cost: {
food: 25,
wood: 0,
stone: 0,
gold: 0
},
restore: 30,
scale: 27,
holdOffset: 15
}, {
id: 3,
itemType: 3,
itemGroup: 1,
name: "wood wall",
description: "provides protection for your village",
age: 0,
cost: {
food: 0,
wood: 10,
stone: 0,
gold: 0
},
projDmg: !0,
health: 380,
scale: 50,
holdOffset: 20,
placeOffset: -5
}, {
id: 4,
itemType: 3,
itemGroup: 1,
upgradeOf: 3,
name: "stone wall",
description: "provides improved protection for your village",
age: 3,
cost: {
food: 0,
wood: 0,
stone: 25,
gold: 0
},
health: 900,
scale: 50,
holdOffset: 20,
placeOffset: -5
}, {
pre: 1,
id: 5,
itemType: 3,
itemGroup: 1,
upgradeOf: 4,
name: "castle wall",
description: "provides powerful protection for your village",
age: 7,
cost: {
food: 0,
wood: 0,
stone: 35,
gold: 0
},
health: 1500,
scale: 52,
holdOffset: 20,
placeOffset: -5
}, {
id: 6,
itemType: 4,
itemGroup: 2,
name: "spikes",
description: "damages enemies when they touch them",
age: 0,
cost: {
food: 0,
wood: 20,
stone: 5,
gold: 0
},
health: 400,
damage: 20,
scale: 49,
spritePadding: -23,
holdOffset: 8,
placeOffset: -5
}, {
id: 7,
itemType: 4,
itemGroup: 2,
upgradeOf: 6,
name: "greater spikes",
description: "damages enemies when they touch them",
age: 5,
cost: {
food: 0,
wood: 30,
stone: 10,
gold: 0
},
health: 500,
damage: 35,
scale: 52,
spritePadding: -23,
holdOffset: 8,
placeOffset: -5
}, {
id: 8,
itemType: 4,
itemGroup: 2,
upgradeOf: 7,
name: "poison spikes",
description: "poisons enemies when they touch them",
age: 9,
pre: 1,
cost: {
food: 0,
wood: 35,
stone: 15,
gold: 0
},
health: 600,
damage: 30,
poisonDamage: 5,
scale: 52,
spritePadding: -23,
holdOffset: 8,
placeOffset: -5
}, {
id: 9,
itemType: 4,
itemGroup: 2,
upgradeOf: 7,
name: "spinning spikes",
description: "damages enemies when they touch them",
age: 9,
pre: 2,
cost: {
food: 0,
wood: 30,
stone: 20,
gold: 0
},
health: 500,
damage: 45,
turnSpeed: .003,
scale: 52,
spritePadding: -23,
holdOffset: 8,
placeOffset: -5
}, {
id: 10,
itemType: 5,
itemGroup: 3,
name: "windmill",
description: "generates gold over time",
age: 0,
cost: {
food: 0,
wood: 50,
stone: 10,
gold: 0
},
health: 400,
pps: 1,
turnSpeed: .0016,
spritePadding: 25,
iconLineMult: 12,
scale: 45,
holdOffset: 20,
placeOffset: 5
}, {
id: 11,
itemType: 5,
itemGroup: 3,
upgradeOf: 10,
name: "faster windmill",
description: "generates more gold over time",
age: 5,
pre: 1,
cost: {
food: 0,
wood: 60,
stone: 20,
gold: 0
},
health: 500,
pps: 1.5,
turnSpeed: .0025,
spritePadding: 25,
iconLineMult: 12,
scale: 47,
holdOffset: 20,
placeOffset: 5
}, {
id: 12,
itemType: 5,
itemGroup: 3,
upgradeOf: 11,
name: "power mill",
description: "generates more gold over time",
age: 8,
pre: 1,
cost: {
food: 0,
wood: 100,
stone: 50,
gold: 0
},
health: 800,
pps: 2,
turnSpeed: .005,
spritePadding: 25,
iconLineMult: 12,
scale: 47,
holdOffset: 20,
placeOffset: 5
}, {
id: 13,
itemType: 6,
itemGroup: 4,
name: "mine",
description: "allows you to mine stone",
age: 5,
type: 2,
cost: {
food: 0,
wood: 20,
stone: 100,
gold: 0
},
iconLineMult: 12,
scale: 65,
holdOffset: 20,
placeOffset: 0
}, {
id: 14,
itemType: 6,
itemGroup: 11,
name: "sapling",
description: "allows you to farm wood",
age: 5,
type: 0,
cost: {
food: 0,
wood: 150,
stone: 0,
gold: 0
},
iconLineMult: 12,
colDiv: .5,
scale: 110,
holdOffset: 50,
placeOffset: -15
}, {
id: 15,
itemType: 7,
itemGroup: 5,
name: "pit trap",
description: "pit that traps enemies if they walk over it",
age: 4,
cost: {
food: 0,
wood: 30,
stone: 30,
gold: 0
},
trap: !0,
ignoreCollision: !0,
hideFromEnemy: !0,
health: 500,
colDiv: .2,
scale: 50,
holdOffset: 20,
placeOffset: -5
}, {
id: 16,
itemType: 7,
itemGroup: 6,
name: "boost pad",
description: "provides boost when stepped on",
age: 4,
cost: {
food: 0,
wood: 5,
stone: 20,
gold: 0
},
boostSpeed: 1.5,
health: 150,
colDiv: .7,
scale: 45,
holdOffset: 20,
placeOffset: -5
}, {
id: 17,
itemType: 8,
itemGroup: 7,
name: "turret",
description: "defensive structure that shoots at enemies",
age: 7,
doUpdate: !0,
cost: {
food: 0,
wood: 200,
stone: 150,
gold: 0
},
health: 800,
projectile: 1,
shootRange: 700,
shootRate: 2200,
scale: 43,
holdOffset: 20,
placeOffset: -5
}, {
id: 18,
itemType: 8,
itemGroup: 8,
name: "platform",
description: "platform to shoot over walls and cross over water",
age: 7,
cost: {
food: 0,
wood: 20,
stone: 0,
gold: 0
},
ignoreCollision: !0,
zIndex: 1,
health: 300,
scale: 43,
holdOffset: 20,
placeOffset: -5
}, {
id: 19,
itemType: 8,
itemGroup: 9,
name: "healing pad",
description: "standing on it will slowly heal you",
age: 7,
cost: {
food: 10,
wood: 30,
stone: 0,
gold: 0
},
ignoreCollision: !0,
healCol: 15,
health: 400,
colDiv: .7,
scale: 45,
holdOffset: 20,
placeOffset: -5
}, {
id: 20,
itemType: 9,
itemGroup: 10,
name: "spawn pad",
description: "you will spawn here when you die but it will dissapear",
age: 9,
cost: {
food: 0,
wood: 100,
stone: 100,
gold: 0
},
health: 400,
ignoreCollision: !0,
spawnPoint: !0,
scale: 45,
holdOffset: 20,
placeOffset: -5
}, {
id: 21,
itemType: 8,
itemGroup: 12,
name: "blocker",
description: "blocks building in radius",
age: 7,
cost: {
food: 0,
wood: 30,
stone: 25,
gold: 0
},
ignoreCollision: !0,
blocker: 300,
health: 400,
colDiv: .7,
scale: 45,
holdOffset: 20,
placeOffset: -5
}, {
id: 22,
itemType: 8,
itemGroup: 13,
name: "teleporter",
description: "teleports you to a random point on the map",
age: 7,
cost: {
food: 0,
wood: 60,
stone: 60,
gold: 0
},
teleport: !0,
health: 200,
colDiv: .7,
scale: 45,
holdOffset: 20,
placeOffset: -5
} ], WeaponVariants = [ {
id: 0,
src: "",
xp: 1,
needXP: 0,
val: 1,
color: "#7e7e90"
}, {
id: 1,
src: "_g",
xp: 3e3,
needXP: 3e3,
val: 1.1,
color: "#f7cf45"
}, {
id: 2,
src: "_d",
xp: 7e3,
needXP: 4e3,
val: 1.18,
color: "#6d91cb"
}, {
id: 3,
src: "_r",
poison: !0,
xp: 12e3,
needXP: 5e3,
val: 1.18,
color: "#be5454"
} ], Projectiles = [ {
id: 0,
name: "Hunting bow",
index: 0,
layer: 0,
src: "arrow_1",
damage: 25,
scale: 103,
range: 1e3,
speed: 1.6
}, {
id: 1,
name: "Turret",
index: 1,
layer: 1,
damage: 25,
scale: 20,
speed: 1.5,
range: 700
}, {
id: 2,
name: "Crossbow",
index: 0,
layer: 0,
src: "arrow_1",
damage: 35,
scale: 103,
range: 1200,
speed: 2.5
}, {
id: 3,
name: "Repeater crossbow",
index: 0,
layer: 0,
src: "arrow_1",
damage: 30,
scale: 103,
range: 1200,
speed: 2
}, {
id: 4,
index: 1,
layer: 1,
damage: 16,
scale: 20,
range: 0,
speed: 0
}, {
id: 5,
name: "Musket",
index: 0,
layer: 0,
src: "bullet_1",
damage: 50,
scale: 160,
range: 1400,
speed: 3.6
} ];
class Vector {
x;
y;
constructor(x = 0, y = 0) {
this.x = x, this.y = y;
}
static fromAngle(angle, length = 1) {
return new Vector(Math.cos(angle) * length, Math.sin(angle) * length);
}
add(vec) {
if (vec instanceof Vector) {
this.x += vec.x, this.y += vec.y;
} else {
this.x += vec, this.y += vec;
}
return this;
}
sub(vec) {
if (vec instanceof Vector) {
this.x -= vec.x, this.y -= vec.y;
} else {
this.x -= vec, this.y -= vec;
}
return this;
}
mult(scalar) {
return this.x *= scalar, this.y *= scalar, this;
}
div(scalar) {
let inv = 1 / scalar;
return this.x *= inv, this.y *= inv, this;
}
get length() {
return Math.hypot(this.x, this.y);
}
normalizeVec() {
let len = this.length;
if (len > 0) {
let inv = 1 / len;
this.x *= inv, this.y *= inv;
}
return this;
}
dot(vec) {
return this.x * vec.x + this.y * vec.y;
}
setXY(x, y) {
return this.x = x, this.y = y, this;
}
setVec(vec) {
return this.setXY(vec.x, vec.y);
}
setLength(value) {
return this.normalizeVec().mult(value);
}
copy() {
return new Vector(this.x, this.y);
}
distanceDefault(vec) {
let dx = this.x - vec.x, dy = this.y - vec.y;
return dx * dx + dy * dy;
}
distance(vec) {
let dx = this.x - vec.x, dy = this.y - vec.y;
return Math.hypot(dx, dy);
}
angle(vec) {
return Math.atan2(vec.y - this.y, vec.x - this.x);
}
addDirection(angle, length) {
let x = this.x + Math.cos(angle) * length, y = this.y + Math.sin(angle) * length;
return new Vector(x, y);
}
isEqual(vec) {
return this.x === vec.x && this.y === vec.y;
}
makeString() {
return this.x + ":" + this.y;
}
}
const Vector_default = Vector;
const getAngle = (x1, y1, x2, y2) => Math.atan2(y2 - y1, x2 - x1);
const clamp = (value, min, max) => Math.min(Math.max(value, min), max), fixTo = (value, fraction) => parseFloat(value.toFixed(fraction)), PI = Math.PI, PI2 = PI * 2, getAngleDist = (a, b) => {
let p = Math.abs(b - a) % (PI * 2);
return p > PI ? PI * 2 - p : p;
}, findMiddleAngle = (a, b) => {
let x = Math.cos(a) + Math.cos(b), y = Math.sin(a) + Math.sin(b);
return Math.atan2(y, x);
}, toRadians = degrees => degrees * (PI / 180), removeFast = (array, index) => {
if (index < 0 || index >= array.length) {
throw RangeError("removeFast: Index out of range");
}
if (index === array.length - 1) {
array.pop();
} else {
array[index] = array.pop();
}
};
const lerp = (start, end, factor) => (1 - factor) * start + factor * end;
const reverseAngle = angle => Math.atan2(-Math.sin(angle), -Math.cos(angle)), getTargetValue = (target, prop) => target[prop], setTargetValue = (target, prop, value) => {
target[prop] = value;
}, formatDate = date => {
if (date == null) {
date = new Date;
}
let hours = (date.getHours() + "").padStart(2, "0"), minutes = (date.getMinutes() + "").padStart(2, "0"), seconds = (date.getSeconds() + "").padStart(2, "0");
return `${hours}:${minutes}:${seconds}`;
}, incrementor = () => {
let value = 0;
return function() {
return value++;
};
}, getUniqueID = incrementor(), pointInsideRect = (point, rectStart, rectEnd) => point.x >= rectStart.x && point.x <= rectEnd.x && point.y >= rectStart.y && point.y <= rectEnd.y;
const isActiveInput = () => {
let active = document.activeElement || document.body;
return active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement;
}, getAngleFromBitmask = (bitmask, rotate) => {
let vec = {
x: 0,
y: 0
};
if (bitmask & 1) {
vec.y--;
}
if (bitmask & 2) {
vec.y++;
}
if (bitmask & 4) {
vec.x--;
}
if (bitmask & 8) {
vec.x++;
}
if (rotate) {
vec.x *= -1, vec.y *= -1;
}
return vec.x === 0 && vec.y === 0 ? null : Math.atan2(vec.y, vec.x);
}, formatCode = code => {
if (code += "", code === "Backspace") {
return code;
}
if (code === "Escape") {
return "ESC";
}
if (code === "Delete") {
return "DEL";
}
if (code === "Minus") {
return "-";
}
if (code === "Equal") {
return "=";
}
if (code === "BracketLeft") {
return "[";
}
if (code === "BracketRight") {
return "]";
}
if (code === "Slash") {
return "/";
}
if (code === "Backslash") {
return "\\";
}
if (code === "Quote") {
return "'";
}
if (code === "Backquote") {
return "`";
}
if (code === "Semicolon") {
return ";";
}
if (code === "Comma") {
return ",";
}
if (code === "Period") {
return ".";
}
if (code === "CapsLock") {
return "CAPS";
}
if (code === "ContextMenu") {
return "CTXMENU";
}
if (code === "NumLock") {
return "LOCK";
}
return code.replace(/^Page/, "PG").replace(/^Digit/, "").replace(/Button$/, "BTN").replace(/^Key/, "").replace(/^(Shift|Control|Alt)(L|R).*$/, "$2$1").replace(/Control/, "CTRL").replace(/^Arrow/, "").replace(/^Numpad/, "NUM").replace(/Decimal/, "DEC").replace(/Subtract/, "SUB").replace(/Divide/, "DIV").replace(/Multiply/, "MULT").toUpperCase();
}, formatButton = button => {
if (button === 0) {
return "LBTN";
}
if (button === 1) {
return "MBTN";
}
if (button === 2) {
return "RBTN";
}
if (button === 3) {
return "BBTN";
}
if (button === 4) {
return "FBTN";
}
throw Error(`formatButton Error: "${button}" is not valid button`);
}, removeClass = (target, name) => {
if (target instanceof HTMLElement) {
target.classList.remove(name);
return;
}
for (let element of target) {
element.classList.remove(name);
}
};
const pointInRiver = position => {
let y = position.y, below = y >= Config_default.mapScale / 2 - Config_default.riverWidth / 2, above = y <= Config_default.mapScale / 2 + Config_default.riverWidth / 2;
return below && above;
}, pointInDesert = position => position.y >= Config_default.mapScale - Config_default.snowBiomeTop, inRange = (value, min, max) => value >= min && value <= max, targetInsideRect = (target, rectPos, radius) => {
let screen = new Vector_default(1920, 1080).div(2).add(radius), rectStart = rectPos.copy().sub(screen), rectEnd = rectPos.copy().add(screen);
return pointInsideRect(target, rectStart, rectEnd);
}, findPlacementAngles = angles => {
let output = new Set;
for (let i = 0; i < angles.length; i++) {
let [angle, offset] = angles[i], start = angle - offset, end = angle + offset, startIntersects = !1, endIntersects = !1;
for (let j = 0; j < angles.length; j++) {
if (startIntersects && endIntersects) {
break;
}
if (i === j) {
continue;
}
let [angle2, offset2] = angles[j];
if (getAngleDist(start, angle2) <= offset2) {
startIntersects = !0;
}
if (getAngleDist(end, angle2) <= offset2) {
endIntersects = !0;
}
}
if (!startIntersects) {
output.add(start);
}
if (!endIntersects) {
output.add(end);
}
}
return [ ...output ];
}, createAction = (callback, time = 0) => {
let state = !1, timeoutID = setTimeout(() => {
if (state) {
return;
}
state = !0, callback();
}, time);
return () => {
if (state) {
return;
}
state = !0, clearTimeout(timeoutID), callback();
};
};
class CustomStorage {
static get(key) {
let value = window.localStorage.getItem(key);
return value === null ? null : JSON.parse(value);
}
static set(key, value, stringify = !0) {
let data = stringify ? JSON.stringify(value) : value;
window.localStorage.setItem(key, data);
}
static delete(key) {
let has = window.localStorage.hasOwnProperty(key) && key in window.localStorage;
return window.localStorage.removeItem(key), has;
}
}
const Header_default = '<header>\n <div id="credits">\n <svg version="1.1" id="logo" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">\n <path transform="translate(868.08 108.59)" d="m0 0c0.70463-0.0067323 1.4093-0.013465 2.1352-0.020401 6.4762 0.12104 11.035 2.1066 15.783 6.4267 6.7355 7.1685 7.4975 15.175 7.2769 24.712-0.32818 6.7315-1.9685 13.117-3.7144 19.6-0.39653 1.5245-0.79241 3.0492-1.1877 4.574-15.141 57.747-33.221 114.75-51.15 171.68-0.77339 2.4566-1.5457 4.9135-2.3178 7.3705-4.8024 15.273-9.6359 30.535-14.809 45.687-0.51513 1.5277-0.51513 1.5277-1.0407 3.0862-5.8617 16.918-5.8617 16.918-12.244 22.918-0.67418 0.65227-1.3484 1.3045-2.043 1.9766-1.7695 1.3984-1.7695 1.3984-3.7695 1.3984v2c-2.0273 1.7234-4.0653 3.3381-6.1875 4.9375-4.8734 3.7442-9.6517 7.5565-14.312 11.562-4.471 3.8341-9.032 7.5173-13.688 11.125-4.9944 3.8756-9.7402 7.9242-14.398 12.203-3.3976 3.0568-6.9447 5.9139-10.496 8.7891-3.7343 3.0494-7.405 6.1702-11.077 9.2942-3.4521 2.9308-6.943 5.8055-10.466 8.6511-4.7271 3.842-9.2068 7.9069-13.688 12.031-3.2993 2.954-6.7453 5.6796-10.227 8.4141-3.423 2.771-6.6461 5.7432-9.8984 8.7109-2.6078 2.3215-5.2829 4.5266-8 6.7188-4.7768 3.8631-9.302 7.9416-13.82 12.102-2.6423 2.3713-5.3491 4.6135-8.1172 6.8359-4.2031 3.3889-8.1871 6.9374-12.125 10.625-4.7712 4.4679-9.6791 8.6676-14.785 12.754-3.9854 3.2972-7.737 6.8279-11.5 10.375-2.2148 1.8711-2.2148 1.8711-4.2148 1.8711v2c-1.2227 1.2695-1.2227 1.2695-3.0625 2.8125-0.72574 0.61746-1.4515 1.2349-2.1992 1.8711-0.90363 0.76441-1.8073 1.5288-2.7383 2.3164-2.4635 2.119-4.9193 4.2469-7.375 6.375-0.6546 0.56598-1.3092 1.132-1.9836 1.7151-3.6698 3.1784-7.3014 6.3911-10.891 9.6599-3.2287 2.9318-6.5326 5.7126-9.9375 8.4375-5.3248 4.3005-10.273 8.933-15.238 13.637-4.625 4.3579-9.3867 8.402-14.403 12.308-2.0969 1.8028-3.6149 3.5924-5.1719 5.8672 5.208 2.3208 10.456 4.2336 15.875 6 4.5547 1.5 4.5547 1.5 6.8157 2.2454 1.6015 0.52332 3.2057 1.0382 4.812 1.5464 0.80478 0.25822 1.6096 0.51643 2.4387 0.78247 0.72905 0.23034 1.4581 0.46068 2.2092 0.698 2.6191 1.0307 3.9951 2.6343 5.8494 4.7278 1.2792 0.95451 2.5725 1.8902 3.875 2.8125 7.5329 5.5831 11.921 11.63 13.938 20.938 1.1447 13.632-5.9612 26.77-14.188 37.188-15.306 17.463-37.523 33.314-58.625 43.062h-2l-1 2c-9.832 3.3392-20.457 3.193-30-1-9.0874-4.8402-17.029-11.545-25-18-1.0018-0.81042-1.0018-0.81042-2.0239-1.6372-3.4276-2.7755-6.85-5.5573-10.269-8.3433-4.5453-3.7035-9.0945-7.3997-13.707-11.02-0.64324-0.51434-1.2865-1.0287-1.9492-1.5586-3.6186-2.7709-6.4181-4.8196-11.051-4.4414-3.0465 1.9411-5.465 4.4432-8 7-0.89461 0.87012-1.7892 1.7402-2.7109 2.6367-4.6551 4.5722-9.1144 9.2354-13.348 14.203-2.5425 2.829-5.236 5.4878-7.9414 8.1602-3.2221 3.1829-6.3905 6.3469-9.3125 9.8125-4.0741 4.7984-8.604 9.1542-13.095 13.558-3.1238 3.0815-6.1309 6.1991-8.991 9.5281-4.0078 4.6483-8.3527 8.9253-12.727 13.227-2.9835 2.9345-5.9455 5.8865-8.875 8.875-0.54793 0.5431-1.0959 1.0862-1.6604 1.6458-2.4213 2.5837-3.3138 4.1479-3.7576 7.6941 0.076055 1.1872 0.15211 2.3745 0.23047 3.5977 0.047874 1.3357 0.088031 2.6717 0.12109 4.0078 0.017886 0.67579 0.035771 1.3516 0.054199 2.0479 0.13648 22.438-9.8287 42.623-25.238 58.386-16.639 15.859-38.194 21.12-60.574 20.77-32.474-0.91475-58.907-15.915-81.383-38.352-17.614-18.76-26.234-43.914-27.043-69.359 0.81801-25.407 10.042-46.905 28.438-64.625 12.128-10.629 27.322-17.522 43.197-20.087 8.9085-1.4767 13.784-3.2843 19.51-10.745 0.6948-0.98355 1.3896-1.9671 2.1055-2.9805 1.4259-1.7595 2.8634-3.5096 4.3125-5.25 0.72832-0.90105 1.4566-1.8021 2.207-2.7305 7.2516-8.8275 14.851-17.375 22.516-25.844 3.9882-4.4163 7.8855-8.9089 11.75-13.434 1.0299-1.2058 2.0599-2.4115 3.0898-3.6172 0.51965-0.60852 1.0393-1.217 1.5747-1.844 3.0292-3.5372 6.1018-7.0249 9.2378-10.469 4.6378-5.11 8.9914-10.434 13.312-15.812 1.0886-1.3052 1.0886-1.3052 2.1992-2.6367 2.6966-3.539 3.2616-6.8067 3.1938-11.236-0.74301-4.0206-3.4519-6.5065-6.2056-9.377-0.58878-0.6455-1.1776-1.291-1.7842-1.9561-1.7834-1.9486-3.5909-3.8723-5.4033-5.7939-1.4678-1.5866-2.93-3.178-4.3914-4.7705-1.3503-1.4704-2.706-2.9359-4.0618-4.4014-3.2209-3.5765-6.2239-7.3042-9.2383-11.055-2.4819-2.9817-5.0951-5.8187-7.7461-8.6484-11.792-12.676-21.99-24.809-21.48-43.066 3.407-27.518 27.039-66.699 47.918-84.559 5.9718-4.5112 12.209-7.1966 19.84-6.8477 17.094 2.7511 34.034 17.486 44.098 30.938 4.2859 6.4381 7.3285 13.191 10.062 20.41 7.824-9.5531 15.526-19.17 23-29 2.0817-2.7304 4.1656-5.4591 6.25-8.1875 0.81356-1.0657 0.81356-1.0657 1.6436-2.1528 4.0884-5.348 8.2159-10.664 12.356-15.972 4.6005-5.8986 9.1409-11.833 13.609-17.832 2.3536-3.1396 4.7426-6.2498 7.1406-9.3555 3.8824-5.0298 7.7073-10.099 11.508-15.191 1.8918-2.5232 3.809-5.0258 5.7344-7.5234 7.5051-9.6188 7.5051-9.6188 14.316-19.73 1.3298-1.8955 2.7369-3.5894 4.2539-5.3359 3.1005-3.572 5.9408-7.2908 8.75-11.094 1.0579-1.4211 2.1165-2.8416 3.1758-4.2617 0.53963-0.72365 1.0793-1.4473 1.6353-2.1929 2.6013-3.4712 5.2376-6.9153 7.8765-10.358 0.52964-0.69182 1.0593-1.3836 1.605-2.0964 2.371-3.0966 4.7431-6.1922 7.1172-9.2864 6.9922-9.117 13.973-18.224 20.592-27.617 3.0266-4.2821 6.1935-8.4387 9.4126-12.577 3.6953-4.7679 7.2699-9.6201 10.836-14.485 5.1531-7.0285 10.394-13.981 15.708-20.889 2.9437-3.8331 5.8403-7.6907 8.6675-11.611 2.947-4.0834 5.9477-8.12 9-12.125 0.79793-1.0493 1.5959-2.0986 2.418-3.1797 7.3745-9.0707 16.159-14.641 27.277-18.121 2.2951-0.62073 2.2951-0.62073 3.1172-2.8242 1.8452-0.2245 3.6914-0.44251 5.5404-0.63281 4.8219-0.71986 9.4052-2.3736 14.034-3.8672 1.11-0.35194 2.2199-0.70389 3.3635-1.0665 3.5853-1.1382 7.1675-2.2859 10.75-3.4335 2.4571-0.78153 4.9145-1.5623 7.3721-2.3423 4.8141-1.5283 9.6274-3.0592 14.44-4.5923 7.9059-2.5156 15.825-4.9889 23.75-7.4404 1.0889-0.33773 2.1777-0.67547 3.2996-1.0234 1.9287-0.59704 3.8581-1.192 5.7883-1.7842 1.8337-0.56302 3.6656-1.1317 5.4961-1.7051 0.89525-0.27683 1.7905-0.55365 2.7129-0.83887 0.78729-0.24573 1.5746-0.49146 2.3857-0.74463 2.0674-0.52881 2.0674-0.52881 5.0674-0.52881l1-2c2.0635-0.65381 2.0635-0.65381 4.8906-1.2734 5.3022-1.2515 10.508-2.6858 15.719-4.2656 0.791-0.2396 1.582-0.4792 2.397-0.72606 1.6915-0.51395 3.3826-1.029 5.0735-1.545 2.7544-0.84057 5.51-1.6773 8.2659-2.5133 8.5257-2.5879 17.048-5.1863 25.57-7.7864 13.103-3.9975 26.21-7.9851 39.326-11.94 6.004-1.8112 12.003-3.6372 17.996-5.485 3.178-0.97486 6.3616-1.9305 9.5474-2.8797 1.3959-0.41997 2.7895-0.84771 4.1802-1.2846 7.4197-2.3263 14.365-3.6465 22.117-3.7067z" fill="#353C35"/>\n <path transform="translate(843,160)" d="m0 0c0.87909 3.1738 0.98903 4.9646 0.066406 8.1484-0.34938 1.2387-0.34938 1.2387-0.70581 2.5024-0.39506 1.3484-0.39506 1.3484-0.7981 2.7241-0.55849 1.9736-1.1157 3.9476-1.6719 5.9219-0.30357 1.0693-0.60715 2.1386-0.91992 3.2402-1.5967 5.6962-3.1174 11.413-4.6372 17.13-0.50784 1.9089-1.0182 3.8171-1.5285 5.7253-1.4648 5.4908-2.907 10.983-4.262 16.502-1.8468 7.4363-3.9359 14.802-6.043 22.168-0.21587 0.75494-0.43174 1.5099-0.65414 2.2877-8.0126 27.951-17.064 55.512-26.559 82.99-2.8479 8.2577-5.5966 16.548-8.3086 24.851-1.7657 5.3597-3.6081 10.69-5.5405 15.992-0.39316 1.0872-0.78633 2.1745-1.1914 3.2947-0.41121 0.83217-0.82242 1.6643-1.2461 2.5217-3.6956 1.2319-4.5849 0.62215-8.1133-0.83594-1.001-0.40477-2.0019-0.80953-3.0332-1.2266-1.0448-0.43312-2.0896-0.86625-3.166-1.3125-2.0563-0.84665-4.1149-1.688-6.1758-2.5234-0.91306-0.37818-1.8261-0.75636-2.7668-1.146-2.9074-1.0121-5.7004-1.5329-8.7449-1.9556 1.3335 1.3335 2.8308 2.2957 4.3867 3.3633 0.69158 0.47502 1.3832 0.95004 2.0957 1.4395 0.72768 0.49822 1.4554 0.99645 2.2051 1.5098 0.70834 0.48662 1.4167 0.97324 2.1465 1.4746 4.0353 2.7685 8.0873 5.5087 12.166 8.2129-1.5022 3.7389-3.6017 5.5409-6.75 8-4.4989 3.5802-8.9008 7.2395-13.25 11-4.9886 4.3006-10.042 8.5049-15.156 12.656-3.9325 3.2411-7.787 6.5698-11.646 9.8979-3.5828 3.0831-7.2074 6.1011-10.885 9.0708-3.7169 3.0149-7.2893 6.1358-10.812 9.375-4.3903 4.0363-8.9118 7.8403-13.551 11.586-3.3629 2.7527-6.6585 5.5758-9.9492 8.4141-4.1022 3.5362-8.228 7.0286-12.438 10.438-5.0518 4.1023-9.9656 8.3495-14.873 12.623-4.0583 3.5322-8.1393 7.0343-12.252 10.502-12.951 10.904-12.951 10.904-25.625 22.125-3.2492 2.9538-6.5712 5.757-10 8.5-6.0657 4.9025-11.694 10.235-17.367 15.582-3.1257 2.9433-6.314 5.7988-9.5664 8.6016-4.0147 3.4805-7.935 7.0686-11.879 10.629-1.6664 1.5003-3.3331 3.0003-5 4.5-0.82887 0.74637-1.6577 1.4927-2.5117 2.2617-1.626 1.4627-3.2536 2.9237-4.8828 4.3828-8.3305 7.4692-16.56 15.047-24.711 22.711-0.69916 0.65726-1.3983 1.3145-2.1187 1.9917-1.3493 1.2698-2.6973 2.5409-4.0439 3.8135-4.4852 4.2235-9.0804 8.3005-13.732 12.339-1.6688 1.4768-3.3359 2.9554-5 4.4375-0.76312 0.67934-1.5262 1.3587-2.3125 2.0586-0.83531 0.74443-0.83531 0.74443-1.6875 1.5039-3.5083-1.5208-5.9527-3.5996-8.75-6.1875-2.9494-2.7054-5.8997-5.3943-8.9375-8-4.6095-4.0135-9.0492-8.2078-13.509-12.386-5.8936-5.5207-11.839-10.983-17.804-16.427 5.0137-5.9623 10.266-11.693 15.544-17.419 2.3231-2.5226 4.639-5.0519 6.9556-7.5806 0.92056-1.0039 1.8411-2.0078 2.7617-3.0117 1.7961-1.9592 3.59-3.9205 5.3828-5.8828 5.1673-5.6515 10.371-11.266 15.605-16.855 4.0531-4.3292 8.0554-8.6815 11.926-13.176 2.4978-2.8401 5.0669-5.6118 7.6367-8.3867 9.9004-10.674 9.9004-10.674 19.562-21.562 3.6073-4.1544 7.3481-8.1822 11.099-12.207 2.6949-2.8999 5.3367-5.8352 7.9321-8.8247 4.1992-4.8221 8.5917-9.4524 12.988-14.094 3.7604-3.9861 7.4233-8.034 10.996-12.189 1.6392-1.844 3.3487-3.5828 5.1094-5.3105 2.2933-2.258 4.4643-4.56 6.5625-7 5.1684-5.9857 10.626-11.708 16.036-17.474 1.8617-1.9841 3.7216-3.9698 5.5811-5.9561 3.1132-3.3247 6.2293-6.6466 9.3467-9.9673 1.3605-1.4497 2.7205-2.9 4.0801-4.3506 2.1301-2.2727 4.2617-4.5439 6.3936-6.8149 0.6463-0.69013 1.2926-1.3803 1.9585-2.0913 3.0535-3.2496 6.1349-6.4582 9.2993-9.6001 2.3124-2.2965 4.5196-4.6239 6.6172-7.1211 2.5913-3.0097 5.2975-5.8359 8.125-8.625 2.7862-2.7486 5.4531-5.5286 8-8.5 3.18-3.7101 6.5876-7.1298 10.094-10.531 1.9594-2.0103 3.7888-4.0495 5.6172-6.1758 4.0901-4.7132 8.4794-9.0936 12.914-13.48 0.78504-0.78053 1.5701-1.5611 2.3789-2.3652 5.9292-5.8942 5.9292-5.8942 8.1169-8.0286 3.2839-3.2186 5.2875-5.6724 5.4463-10.431-0.0079761-0.71132-0.015952-1.4226-0.02417-2.1555-0.01418-1.2646-0.028359-2.5291-0.042969-3.832-0.8826 0.38333-1.7652 0.76667-2.6746 1.1616-3.2891 1.4283-6.5786 2.8556-9.8682 4.2827-1.421 0.61661-2.8419 1.2335-4.2627 1.8506-2.0476 0.88934-4.0957 1.7778-6.1438 2.666-0.63041 0.27404-1.2608 0.54807-1.9103 0.83041-2.654 1.1501-5.3006 2.2683-8.0116 3.2785-2.707 1.1828-2.9946 2.2719-4.1289 4.9302-1.4805 1.6406-1.4805 1.6406-3.1875 3.25-3.2018 3.0294-6.0544 6.2979-8.9412 9.6226-2.9422 3.3449-5.9993 6.5777-9.0588 9.8149-1.3233 1.4059-2.6462 2.8121-3.9688 4.2188-0.64969 0.69094-1.2994 1.3819-1.9688 2.0938-2.7022 2.8823-5.3852 5.782-8.0625 8.6875-0.4859 0.52715-0.97179 1.0543-1.4724 1.5974-1.922 2.0864-3.8427 4.174-5.7625 6.2625-8.118 8.8299-16.324 17.574-24.552 26.302-5.6877 6.0386-11.357 12.095-17.026 18.151-0.60618 0.64743-1.2124 1.2949-1.8369 1.9619-6.8593 7.3286-13.69 14.682-20.464 22.089-7.7804 8.5011-15.62 16.946-23.49 25.365-3.7309 3.9935-7.4455 8.0013-11.147 12.022-5.716 6.2062-11.487 12.36-17.262 18.512-7.9458 8.4654-15.873 16.948-23.738 25.488-7.6097 8.261-15.309 16.438-22.999 24.624-1.9174 2.0416-3.8344 4.0836-5.751 6.126-0.62117 0.66169-1.2423 1.3234-1.8823 2.0051-3.9812 4.2462-7.9315 8.5194-11.868 12.807-4.4004 4.7913-8.9009 9.4618-13.562 14-5.8423-4.1181-11.1-8.7281-16.355-13.566-4.6205-4.252-9.3708-8.3474-14.145-12.426-0.62673-0.53577-1.2535-1.0715-1.8992-1.6235-1.2542-1.0713-2.5096-2.1413-3.7661-3.21-0.58096-0.49581-1.1619-0.99161-1.7605-1.5024-0.5199-0.44247-1.0398-0.88494-1.5754-1.3408-1.5624-1.3875-3.0357-2.8398-4.4988-4.3311 1.6268-3.6539 3.8669-6.596 6.3125-9.75 0.43441-0.56074 0.86883-1.1215 1.3164-1.6992 4.1028-5.2668 8.3245-10.436 12.55-15.604 3.3615-4.1209 6.6595-8.28 9.8838-12.509 3.5663-4.6743 7.1936-9.2908 10.875-13.875 5.7387-7.148 11.418-14.34 17.062-21.562 0.52288-0.66838 1.0458-1.3368 1.5845-2.0254 8.3281-10.652 16.554-21.378 24.736-32.143 2.9156-3.8344 5.8538-7.6498 8.8047-11.457 4.5205-5.8616 8.8975-11.824 13.273-17.794 4.5458-6.1869 9.1826-12.299 13.852-18.393 4.7428-6.1924 9.4013-12.419 13.884-18.802 3.8186-5.3996 7.843-10.637 11.866-15.885 4.8482-6.3256 9.6231-12.679 14.212-19.195 3.5844-5.0695 7.304-10.033 11.038-14.993 13.008-17.283 25.755-34.749 38.348-52.336 0.59031-0.82234 1.1806-1.6447 1.7888-2.4919 1.1321-1.5772 2.2619-3.1561 3.3892-4.7368 0.50974-0.70955 1.0195-1.4191 1.5447-2.1501 0.44618-0.62383 0.89235-1.2477 1.3521-1.8904 2.4758-3.1838 4.393-4.9888 8.2991-6.1675 0.81133-0.24997 1.6227-0.49994 2.4586-0.75749 0.89321-0.26461 1.7864-0.52921 2.7067-0.80183 0.95336-0.29083 1.9067-0.58166 2.889-0.8813 3.218-0.97942 6.4399-1.9453 9.6618-2.9117 2.2999-0.69745 4.5996-1.3959 6.8989-2.0952 4.3839-1.3323 8.7687-2.6616 13.155-3.9868 9.3777-2.8337 18.747-5.6947 28.114-8.5625 1.5308-0.46858 3.0615-0.93715 4.5923-1.4057 0.76137-0.23306 1.5227-0.46611 2.3072-0.70623 0.76342-0.23368 1.5268-0.46736 2.3134-0.70812 0.76499-0.23418 1.53-0.46836 2.3182-0.70964 8.5298-2.6108 17.062-5.2145 25.594-7.8179 8.9283-2.7244 17.856-5.45 26.781-8.1852 32.342-9.9105 64.783-19.48 97.238-29.01z" fill="#747C77"/>\n <path transform="translate(843,162)" d="m0 0c-0.87914 0.55043-1.7583 1.1009-2.6641 1.668-3.2988 2.2008-5.9543 4.7869-8.7109 7.6445-3.1416 3.223-6.3009 6.3527-9.75 9.25-2.8194 2.4053-5.2724 4.9422-7.707 7.7344-5.6994 6.3871-11.736 12.422-17.798 18.463-1.9365 1.9311-3.8675 3.8675-5.7981 5.8044-5.5335 5.5362-11.049 11.027-17.017 16.099-2.1348 1.8351-4.0956 3.817-6.0549 5.8367-3.4037 3.4505-6.9244 6.6664-10.602 9.8203-2.455 2.1721-4.7288 4.4971-7.0234 6.8359-1.8109 1.7807-3.6764 3.4458-5.6016 5.1016-4.1474 3.6059-8.1554 7.342-12.148 11.117-1.4111 1.322-2.8226 2.6436-4.2344 3.9648-2.2389 2.0989-4.4567 4.211-6.6562 6.3516-12.756 12.144-30.677 19.789-47.234 25.309-0.69964 1.3163-1.363 2.6522-2 4-1.4805 1.6406-1.4805 1.6406-3.1875 3.25-3.2018 3.0294-6.0544 6.2979-8.9412 9.6226-2.9422 3.3449-5.9993 6.5777-9.0588 9.8149-1.3233 1.4059-2.6462 2.8121-3.9688 4.2188-0.64969 0.69094-1.2994 1.3819-1.9688 2.0938-2.7022 2.8823-5.3852 5.782-8.0625 8.6875-0.4859 0.52715-0.97179 1.0543-1.4724 1.5974-1.922 2.0864-3.8427 4.174-5.7625 6.2625-8.118 8.8299-16.324 17.574-24.552 26.302-5.6877 6.0386-11.357 12.095-17.026 18.151-0.60618 0.64743-1.2124 1.2949-1.8369 1.9619-6.8593 7.3286-13.69 14.682-20.464 22.089-7.7804 8.5011-15.62 16.946-23.49 25.365-3.7309 3.9935-7.4455 8.0013-11.147 12.022-5.716 6.2062-11.487 12.36-17.262 18.512-7.9458 8.4654-15.873 16.948-23.738 25.488-7.6097 8.261-15.309 16.438-22.999 24.624-1.9174 2.0416-3.8344 4.0836-5.751 6.126-0.62117 0.66169-1.2423 1.3234-1.8823 2.0051-3.9812 4.2462-7.9315 8.5194-11.868 12.807-4.4004 4.7913-8.9009 9.4618-13.562 14-5.8423-4.1181-11.1-8.7281-16.355-13.566-4.6205-4.252-9.3708-8.3474-14.145-12.426-0.62673-0.53577-1.2535-1.0715-1.8992-1.6235-1.2542-1.0713-2.5096-2.1413-3.7661-3.21-0.58096-0.49581-1.1619-0.99161-1.7605-1.5024-0.5199-0.44247-1.0398-0.88494-1.5754-1.3408-1.5624-1.3875-3.0357-2.8398-4.4988-4.3311 1.6268-3.6539 3.8669-6.596 6.3125-9.75 0.43441-0.56074 0.86883-1.1215 1.3164-1.6992 4.1028-5.2668 8.3245-10.436 12.55-15.604 3.3615-4.1209 6.6595-8.28 9.8838-12.509 3.5663-4.6743 7.1936-9.2908 10.875-13.875 5.7387-7.148 11.418-14.34 17.062-21.562 0.52288-0.66838 1.0458-1.3368 1.5845-2.0254 8.3281-10.652 16.554-21.378 24.736-32.143 2.9156-3.8344 5.8538-7.6498 8.8047-11.457 4.5205-5.8616 8.8975-11.824 13.273-17.794 4.5458-6.1869 9.1826-12.299 13.852-18.393 4.7428-6.1924 9.4013-12.419 13.884-18.802 3.8186-5.3996 7.843-10.637 11.866-15.885 4.8482-6.3256 9.6231-12.679 14.212-19.195 3.5844-5.0695 7.304-10.033 11.038-14.993 13.008-17.283 25.755-34.749 38.348-52.336 0.59031-0.82234 1.1806-1.6447 1.7888-2.4919 1.1321-1.5772 2.2619-3.1561 3.3892-4.7368 0.50974-0.70955 1.0195-1.4191 1.5447-2.1501 0.44618-0.62383 0.89235-1.2477 1.3521-1.8904 2.4758-3.1838 4.393-4.9888 8.2991-6.1675 0.81133-0.24997 1.6227-0.49994 2.4586-0.75749 0.89321-0.26461 1.7864-0.52921 2.7067-0.80183 0.95336-0.29083 1.9067-0.58166 2.889-0.8813 3.218-0.97942 6.4399-1.9453 9.6618-2.9117 2.2999-0.69745 4.5996-1.3959 6.8989-2.0952 4.3839-1.3323 8.7687-2.6616 13.155-3.9868 9.3777-2.8337 18.747-5.6947 28.114-8.5625 3.0712-0.94012 6.1424-1.8802 9.2136-2.8203 1.1475-0.35129 1.1475-0.35129 2.3183-0.70968 9.2804-2.8405 18.563-5.6724 27.846-8.5048 8.2032-2.5031 16.406-5.0088 24.605-7.5237 21.256-6.5191 42.543-12.934 63.862-19.241 2.6425-0.78197 5.2838-1.5678 7.9242-2.357 3.6676-1.0959 7.3393-2.1775 11.012-3.2577 1.6605-0.49876 1.6605-0.49876 3.3544-1.0076 1.0144-0.29583 2.0289-0.59166 3.074-0.89645 0.88496-0.262 1.7699-0.52399 2.6817-0.79393 2.2531-0.43092 2.2531-0.43092 5.2531 0.56908z" fill="#A8AAA1"/>\n <path transform="translate(868.08 108.59)" d="m0 0c0.70463-0.0067323 1.4093-0.013465 2.1352-0.020401 6.4762 0.12104 11.035 2.1066 15.783 6.4267 6.7355 7.1685 7.4975 15.175 7.2769 24.712-0.32818 6.7315-1.9685 13.117-3.7144 19.6-0.39653 1.5245-0.79241 3.0492-1.1877 4.574-15.141 57.747-33.221 114.75-51.15 171.68-0.77339 2.4566-1.5457 4.9135-2.3178 7.3705-4.8024 15.273-9.6359 30.535-14.809 45.687-0.51513 1.5277-0.51513 1.5277-1.0407 3.0862-5.8617 16.918-5.8617 16.918-12.244 22.918-0.67418 0.65227-1.3484 1.3045-2.043 1.9766-1.7695 1.3984-1.7695 1.3984-3.7695 1.3984v2c-2.0273 1.7234-4.0653 3.3381-6.1875 4.9375-4.8734 3.7442-9.6517 7.5565-14.312 11.562-4.471 3.8341-9.032 7.5173-13.688 11.125-4.9944 3.8756-9.7402 7.9242-14.398 12.203-3.3976 3.0568-6.9447 5.9139-10.496 8.7891-3.7343 3.0494-7.405 6.1702-11.077 9.2942-3.4521 2.9308-6.943 5.8055-10.466 8.6511-4.7271 3.842-9.2068 7.9069-13.688 12.031-3.2993 2.954-6.7453 5.6796-10.227 8.4141-3.423 2.771-6.6461 5.7432-9.8984 8.7109-2.6078 2.3215-5.2829 4.5266-8 6.7188-4.7768 3.8631-9.302 7.9416-13.82 12.102-2.6423 2.3713-5.3491 4.6135-8.1172 6.8359-4.2031 3.3889-8.1871 6.9374-12.125 10.625-4.7712 4.4679-9.6791 8.6676-14.785 12.754-3.9854 3.2972-7.737 6.8279-11.5 10.375-2.2148 1.8711-2.2148 1.8711-4.2148 1.8711v2c-1.2227 1.2695-1.2227 1.2695-3.0625 2.8125-0.72574 0.61746-1.4515 1.2349-2.1992 1.8711-0.90363 0.76441-1.8073 1.5288-2.7383 2.3164-2.4635 2.119-4.9193 4.2469-7.375 6.375-0.6546 0.56598-1.3092 1.132-1.9836 1.7151-3.6698 3.1784-7.3014 6.3911-10.891 9.6599-3.2287 2.9318-6.5326 5.7126-9.9375 8.4375-5.3248 4.3005-10.273 8.933-15.238 13.637-4.625 4.3579-9.3867 8.402-14.403 12.308-2.0969 1.8028-3.6149 3.5924-5.1719 5.8672 5.208 2.3208 10.456 4.2336 15.875 6 4.5547 1.5 4.5547 1.5 6.8157 2.2454 1.6015 0.52332 3.2057 1.0382 4.812 1.5464 0.80478 0.25822 1.6096 0.51643 2.4387 0.78247 0.72905 0.23034 1.4581 0.46068 2.2092 0.698 2.6191 1.0307 3.9951 2.6343 5.8494 4.7278 1.2792 0.95451 2.5725 1.8902 3.875 2.8125 7.5329 5.5831 11.921 11.63 13.938 20.938 1.1447 13.632-5.9612 26.77-14.188 37.188-15.306 17.463-37.523 33.314-58.625 43.062h-2l-1 2c-9.832 3.3392-20.457 3.193-30-1-9.0874-4.8402-17.029-11.545-25-18-1.0018-0.81042-1.0018-0.81042-2.0239-1.6372-3.4276-2.7755-6.85-5.5573-10.269-8.3433-4.5453-3.7035-9.0945-7.3997-13.707-11.02-0.64324-0.51434-1.2865-1.0287-1.9492-1.5586-3.6186-2.7709-6.4181-4.8196-11.051-4.4414-3.0465 1.9411-5.465 4.4432-8 7-0.89461 0.87012-1.7892 1.7402-2.7109 2.6367-4.6551 4.5722-9.1144 9.2354-13.348 14.203-2.5425 2.829-5.236 5.4878-7.9414 8.1602-3.2221 3.1829-6.3905 6.3469-9.3125 9.8125-4.0741 4.7984-8.604 9.1542-13.095 13.558-3.1238 3.0815-6.1309 6.1991-8.991 9.5281-4.0078 4.6483-8.3527 8.9253-12.727 13.227-2.9835 2.9345-5.9455 5.8865-8.875 8.875-0.54793 0.5431-1.0959 1.0862-1.6604 1.6458-2.4213 2.5837-3.3138 4.1479-3.7576 7.6941 0.076055 1.1872 0.15211 2.3745 0.23047 3.5977 0.047874 1.3357 0.088031 2.6717 0.12109 4.0078 0.017886 0.67579 0.035771 1.3516 0.054199 2.0479 0.13648 22.438-9.8287 42.623-25.238 58.386-16.639 15.859-38.194 21.12-60.574 20.77-32.474-0.91475-58.907-15.915-81.383-38.352-17.614-18.76-26.234-43.914-27.043-69.359 0.81801-25.407 10.042-46.905 28.438-64.625 12.128-10.629 27.322-17.522 43.197-20.087 8.9085-1.4767 13.784-3.2843 19.51-10.745 0.6948-0.98355 1.3896-1.9671 2.1055-2.9805 1.4259-1.7595 2.8634-3.5096 4.3125-5.25 0.72832-0.90105 1.4566-1.8021 2.207-2.7305 7.2516-8.8275 14.851-17.375 22.516-25.844 3.9882-4.4163 7.8855-8.9089 11.75-13.434 1.0299-1.2058 2.0599-2.4115 3.0898-3.6172 0.51965-0.60852 1.0393-1.217 1.5747-1.844 3.0292-3.5372 6.1018-7.0249 9.2378-10.469 4.6378-5.11 8.9914-10.434 13.312-15.812 1.0886-1.3052 1.0886-1.3052 2.1992-2.6367 2.6966-3.539 3.2616-6.8067 3.1938-11.236-0.74301-4.0206-3.4519-6.5065-6.2056-9.377-0.58878-0.6455-1.1776-1.291-1.7842-1.9561-1.7834-1.9486-3.5909-3.8723-5.4033-5.7939-1.4678-1.5866-2.93-3.178-4.3914-4.7705-1.3503-1.4704-2.706-2.9359-4.0618-4.4014-3.2209-3.5765-6.2239-7.3042-9.2383-11.055-2.4819-2.9817-5.0951-5.8187-7.7461-8.6484-11.792-12.676-21.99-24.809-21.48-43.066 3.407-27.518 27.039-66.699 47.918-84.559 5.9718-4.5112 12.209-7.1966 19.84-6.8477 17.094 2.7511 34.034 17.486 44.098 30.938 4.2859 6.4381 7.3285 13.191 10.062 20.41 7.824-9.5531 15.526-19.17 23-29 2.0817-2.7304 4.1656-5.4591 6.25-8.1875 0.81356-1.0657 0.81356-1.0657 1.6436-2.1528 4.0884-5.348 8.2159-10.664 12.356-15.972 4.6005-5.8986 9.1409-11.833 13.609-17.832 2.3536-3.1396 4.7426-6.2498 7.1406-9.3555 3.8824-5.0298 7.7073-10.099 11.508-15.191 1.8918-2.5232 3.809-5.0258 5.7344-7.5234 7.5051-9.6188 7.5051-9.6188 14.316-19.73 1.3298-1.8955 2.7369-3.5894 4.2539-5.3359 3.1005-3.572 5.9408-7.2908 8.75-11.094 1.0579-1.4211 2.1165-2.8416 3.1758-4.2617 0.53963-0.72365 1.0793-1.4473 1.6353-2.1929 2.6013-3.4712 5.2376-6.9153 7.8765-10.358 0.52964-0.69182 1.0593-1.3836 1.605-2.0964 2.371-3.0966 4.7431-6.1922 7.1172-9.2864 6.9922-9.117 13.973-18.224 20.592-27.617 3.0266-4.2821 6.1935-8.4387 9.4126-12.577 3.6953-4.7679 7.2699-9.6201 10.836-14.485 5.1531-7.0285 10.394-13.981 15.708-20.889 2.9437-3.8331 5.8403-7.6907 8.6675-11.611 2.947-4.0834 5.9477-8.12 9-12.125 0.79793-1.0493 1.5959-2.0986 2.418-3.1797 7.3745-9.0707 16.159-14.641 27.277-18.121 2.2951-0.62073 2.2951-0.62073 3.1172-2.8242 1.8452-0.2245 3.6914-0.44251 5.5404-0.63281 4.8219-0.71986 9.4052-2.3736 14.034-3.8672 1.11-0.35194 2.2199-0.70389 3.3635-1.0665 3.5853-1.1382 7.1675-2.2859 10.75-3.4335 2.4571-0.78153 4.9145-1.5623 7.3721-2.3423 4.8141-1.5283 9.6274-3.0592 14.44-4.5923 7.9059-2.5156 15.825-4.9889 23.75-7.4404 1.0889-0.33773 2.1777-0.67547 3.2996-1.0234 1.9287-0.59704 3.8581-1.192 5.7883-1.7842 1.8337-0.56302 3.6656-1.1317 5.4961-1.7051 0.89525-0.27683 1.7905-0.55365 2.7129-0.83887 0.78729-0.24573 1.5746-0.49146 2.3857-0.74463 2.0674-0.52881 2.0674-0.52881 5.0674-0.52881l1-2c2.0635-0.65381 2.0635-0.65381 4.8906-1.2734 5.3022-1.2515 10.508-2.6858 15.719-4.2656 0.791-0.2396 1.582-0.4792 2.397-0.72606 1.6915-0.51395 3.3826-1.029 5.0735-1.545 2.7544-0.84057 5.51-1.6773 8.2659-2.5133 8.5257-2.5879 17.048-5.1863 25.57-7.7864 13.103-3.9975 26.21-7.9851 39.326-11.94 6.004-1.8112 12.003-3.6372 17.996-5.485 3.178-0.97486 6.3616-1.9305 9.5474-2.8797 1.3959-0.41997 2.7895-0.84771 4.1802-1.2846 7.4197-2.3263 14.365-3.6465 22.117-3.7067zm-20.992 17.742c-1.5499 0.45619-3.1001 0.91128-4.6507 1.3653-4.0269 1.1832-8.0487 2.3832-12.069 3.5889-2.2846 0.68421-4.5704 1.3645-6.8568 2.043-9.5576 2.8364-19.105 5.7071-28.647 8.5948-2.3569 0.71299-4.7141 1.425-7.0713 2.1368-28.296 8.5445-56.566 17.173-84.795 25.935-1.0035 0.31135-2.0069 0.6227-3.0408 0.94348-11.996 3.723-23.986 7.464-35.967 11.233-6.2251 1.9577-12.455 3.9007-18.687 5.8356-4.2845 1.3329-8.5657 2.676-12.846 4.0215-2.0207 0.63298-4.0427 1.262-6.066 1.8865-23.47 7.0698-23.47 7.0698-41.393 23.08-0.50999 0.67644-1.02 1.3529-1.5454 2.0498-3.6209 4.8229-7.1758 9.692-10.719 14.572-2.5442 3.4854-5.1374 6.9329-7.7358 10.378-4.2914 5.6993-8.5303 11.435-12.75 17.188-5.8112 7.9174-11.743 15.738-17.71 23.538-3.2287 4.2249-6.4375 8.4557-9.54 12.775-3.7697 5.2477-7.6994 10.369-11.625 15.5-5.1908 6.7865-10.327 13.607-15.375 20.5-6.8698 9.373-13.905 18.615-20.968 27.843-3.3505 4.3809-6.6909 8.7694-10.032 13.157-4.0804 5.3567-8.1618 10.713-12.246 16.066-6.2595 8.207-12.508 16.42-18.688 24.688-3.5663 4.7394-7.1935 9.4319-10.818 14.127-2.004 2.5988-4.0003 5.2034-5.9985 7.8066-4.6667 6.073-9.3716 12.116-14.077 18.159-4.201 5.3973-8.3772 10.813-12.54 16.24-2.0141 2.6188-4.0438 5.225-6.0781 7.8281-6.3274 8.0986-12.608 16.201-18.555 24.586-6.9-5.9417-8.8694-12.752-10.5-21.562-3.1413-16.743-15.725-28.293-28.996-38.324-4.9704-3.3265-9.0877-5.0553-15.129-4.6211-9.0228 1.9292-15.349 9.9374-20.217 17.289-1.8379 3.065-3.6047 6.1599-5.3457 9.281-0.63784 1.1267-1.2757 2.2534-1.9329 3.4143-1.9767 3.4985-3.9284 7.0104-5.8796 10.523-0.62262 1.1121-1.2452 2.2243-1.8867 3.3701-1.7787 3.1828-3.543 6.373-5.3008 9.5674-0.52811 0.95076-1.0562 1.9015-1.6003 2.8811-5.3829 9.9109-10.296 19.829-7.7395 31.302 3.2979 10.131 12.086 18.126 18.922 26.019 1.5739 1.8233 3.1383 3.6543 4.6992 5.4888 4.6212 5.4279 9.2691 10.809 14.094 16.059 4.0031 4.367 7.8029 8.8502 11.488 13.488 1.6811 2.0428 3.3639 3.9542 5.1797 5.8672 6.9058 7.4056 6.9058 7.4056 7.5039 11.293-0.47773 2.4506-1.2972 4.4042-2.3594 6.6641-0.34289 0.95906-0.68578 1.9181-1.0391 2.9062-3.9708 10.697-10.773 17.983-18.41 26.258-2.512 2.7928-4.8847 5.659-7.2383 8.5859-2.4836 3.0794-4.9667 6.0024-7.8125 8.75-2.7851 2.6897-5.205 5.5397-7.625 8.5625-3.6156 4.4979-7.4178 8.7384-11.375 12.938-4.6878 4.9792-9.1123 10.082-13.391 15.422-2.8273 3.4556-5.8354 6.7297-8.8438 10.027-3.1691 3.568-6.1497 7.2777-9.125 11.008-0.70641 0.83918-1.4128 1.6784-2.1406 2.543-1.135 1.3632-1.135 1.3632-2.293 2.7539-3.3422 2.7731-6.0931 3.1088-10.27 3.3711-1.4393 0.14086-2.8781 0.28673-4.3164 0.4375-1.056 0.10635-1.056 0.10635-2.1333 0.21484-16.805 1.8824-30.489 10.283-41.988 22.223-0.67547 0.65613-1.3509 1.3123-2.0469 1.9883-12.766 13.19-16.584 32.001-16.428 49.714 0.79634 25.347 11.757 48.491 30.17 65.836 23.549 19.979 49.936 27.238 80.305 25.461 15.018-1.7793 27.461-8.3189 38-19l2.1875-2.1562c11.759-12.293 16.363-28.618 16.137-45.352-0.30927-3.3312-1.0894-5.9615-2.1367-9.1172-0.57812-2.6211-0.57812-2.6211-0.1875-5.375 3.0217-4.5312 7.3532-8.0332 11.426-11.588 1.8251-1.6371 3.3975-3.3898 4.9487-5.2866 3.4775-4.1066 7.3047-7.8415 11.125-11.625 5.675-5.5854 5.675-5.5854 11-11.5 3.9971-4.7466 8.4812-9.0302 12.908-13.371 3.1365-3.094 6.1552-6.2259 9.0293-9.5664 4.4693-5.1832 9.3664-9.9146 14.246-14.707 4.6633-4.6127 9.0401-9.3842 13.316-14.355 5.8809-6.532 11.024-11.289 19.938-12.562 8.3374 0.47177 15.695 7.3299 21.938 12.312 0.78738 0.62052 1.5748 1.241 2.386 1.8804 5.9714 4.719 11.864 9.5308 17.739 14.37 17.718 15.737 17.718 15.737 40 20 20.093-4.875 39.931-21.506 55-35 0.68578-0.59039 1.3716-1.1808 2.0781-1.7891 7.7419-7.0793 13.824-17.234 15.258-27.652 0.11446-6.2152-1.4044-9.4474-5.7383-14.047-9.3288-8.8271-21.917-12.213-34.098-15.105-7.1522-1.9413-12.027-6.5835-17.5-11.406-1.2255-1.0252-2.4539-2.0471-3.6875-3.0625l-2.3125-1.9375c4.1524-4.3666 8.4172-8.4213 13.125-12.188 4.481-3.5935 8.6987-7.3764 12.875-11.312 4.0586-3.8223 8.143-7.5144 12.5-11 5.6914-4.5564 10.964-9.5079 16.277-14.492 3.044-2.8533 6.1523-5.6197 9.3125-8.3438 2.2722-1.9795 4.4948-4.0099 6.7227-6.0391 3.4413-3.1103 6.9507-6.0898 10.562-9 5.1475-4.1646 10.009-8.5781 14.863-13.074 4.5492-4.2018 9.2254-8.2452 13.941-12.258 5.7571-4.9042 11.467-9.8323 17.008-14.98 4.547-4.2233 9.2639-8.1758 14.098-12.066 2.8216-2.3344 5.5208-4.766 8.2148-7.2461 4.3717-4.0197 8.8779-7.7999 13.496-11.531 5.4653-4.4917 10.768-9.1733 16.103-13.818 12.22-10.613 24.536-21.121 37.088-31.338 3.1305-2.574 6.2242-5.1882 9.3125-7.8125 4.8518-4.1229 9.755-8.1747 14.695-12.191 2.5374-2.0886 5.0421-4.2087 7.5398-6.3442 4.884-4.1751 9.8275-8.2129 14.952-12.089 11.32-8.6011 19.234-15.721 23.746-29.301 0.31375-0.92181 0.6275-1.8436 0.95076-2.7934 1.0272-3.028 2.0408-6.0604 3.0531-9.0934 0.72144-2.1435 1.4431-4.2869 2.165-6.4302 6.7188-20.008 13.145-40.1 19.397-60.257 0.55425-1.7845 0.55425-1.7845 1.1197-3.6051 14.365-46.254 28.643-92.522 40.88-139.39 0.33322-1.27 0.66645-2.5401 1.0098-3.8486 0.88961-3.4212 1.7579-6.8469 2.6152-10.276 0.24798-0.95842 0.49597-1.9168 0.75146-2.9043 1.8143-7.4711 3.4038-15.472-0.18896-22.533-2.1576-2.4042-3.8429-4.1941-7.1086-4.7852-8.4095-0.17858-16.031 2.287-23.989 4.6837z" fill="#E8A371"/>\n <path transform="translate(317,466)" d="m0 0c8.7462 9.718 10.895 21.708 13.625 34.062 0.57344 2.5517 1.1507 5.1024 1.7325 7.6522 0.35842 1.5749 0.71172 3.151 1.0587 4.7284 4.77 21.192 20.161 34.423 35.271 49.182 1.9066 1.9581 3.6864 3.9452 5.457 6.0234 0.53601 0.62826 1.072 1.2565 1.6243 1.9038 0.4063 0.47776 0.81259 0.95552 1.2312 1.4478-0.25693-0.55873-0.51385-1.1175-0.77856-1.6931-1.1828-2.5793-2.3584-5.1618-3.5339-7.7444-0.40412-0.8785-0.80824-1.757-1.2246-2.6621-5.3301-11.744-5.3301-11.744-6.4629-16.9l1-2c0.48469 0.49629 0.96938 0.99258 1.4688 1.5039 4.0598 4.1145 8.2155 8.0141 12.598 11.781 1.8885 1.6749 3.6652 3.4143 5.4336 5.2148 2.9516 2.998 6.0442 5.7622 9.2266 8.5117 9.9866 8.734 19.585 17.927 29.273 26.988 17.624 16.481 17.624 16.481 35.469 32.723 13.315 11.98 13.315 11.98 19.156 17.965 4.4612 4.5348 9.3307 8.4477 14.375 12.312l-2 1c-2.2492-0.91904-4.346-1.8912-6.5-3-0.62423-0.31598-1.2485-0.63196-1.8916-0.95752-4.8527-2.5159-9.3176-5.4105-13.718-8.6597-1.8423-1.4282-1.8423-1.4282-3.8906-2.3828 5.3218 4.9306 10.647 9.7769 16.312 14.312 4.4112 3.5554 8.5653 7.3072 12.688 11.188 5.7926 5.4464 11.784 10.539 18 15.5 2.067 1.6821 4.1269 3.3725 6.1875 5.0625 0.92168 0.7541 1.8434 1.5082 2.793 2.2852 0.66645 0.54527 1.3329 1.0905 2.0195 1.6523-0.5775-0.825-1.155-1.65-1.75-2.5-2.4488-3.6557-4.3579-7.5347-6.25-11.5 4.4585 1.407 8.6694 3.1163 12.93 5.0391 0.6352 0.28572 1.2704 0.57144 1.9248 0.86581 2.0081 0.90399 4.0143 1.812 6.0205 2.7201 1.3697 0.61745 2.7395 1.2346 4.1094 1.8516 3.3399 1.5048 6.6782 3.0131 10.016 4.5234v2c-1.5906 1.3393-3.2528 2.5936-4.9375 3.8125-1.1049 0.80888-2.209 1.6188-3.3125 2.4297-0.60199 0.44054-1.204 0.88107-1.8242 1.335-3.4874 2.5767-6.9229 5.2214-10.363 7.8604-1.0758 0.82371-1.0758 0.82371-2.1733 1.6641-6.471 4.9559-12.932 9.924-19.389 14.898-3.2446-1.4708-5.8055-3.3142-8.5625-5.5625l-2.6719-2.1719c-1.369-1.1215-1.369-1.1215-2.7656-2.2656l-2.6406-2.1406c-6.637-5.395-13.172-10.905-19.689-16.443-1.6742-1.4192-3.3531-2.8325-5.0337-4.2441-4.989-4.195-9.9398-8.4091-14.762-12.797-3.3337-3.0326-6.7407-5.9225-10.25-8.75-5.5761-4.5188-10.849-9.321-16.097-14.21-1.4808-1.371-2.977-2.7254-4.4736-4.0791-7.8939-7.1496-15.424-14.634-22.9-22.219-4.2506-4.295-8.5627-8.4059-13.147-12.341-3.8497-3.4059-7.446-7.0711-11.07-10.714-0.76377-0.7599-1.5275-1.5198-2.3145-2.3027-3.4802-3.4862-6.8778-6.9949-10.088-10.732-4.0973-4.7586-8.5621-9.1249-13.035-13.527-5.2022-5.12-10.27-10.263-15.025-15.803-1.7357-1.9977-3.5712-3.8595-5.4746-5.6973-3.1479-3.1059-6.0776-6.3219-8.957-9.6758-2.0924-2.3805-4.2414-4.6975-6.405-7.0129-4.8961-5.2406-9.541-10.56-13.954-16.221-2.0675-2.5664-4.3213-4.797-6.6836-7.0898-2-3-2-3-1.7776-5.4028 0.79878-2.6679 1.8073-4.7553 3.219-7.1519 0.49742-0.85473 0.99483-1.7095 1.5073-2.5901 0.53254-0.90097 1.0651-1.8019 1.6138-2.7302 1.0993-1.891 2.1969-3.7829 3.293-5.6758 0.53802-0.92764 1.076-1.8553 1.6304-2.811 5.5524-9.6742 10.594-19.631 15.514-29.638z" fill="#646C65"/>\n <path transform="translate(843,162)" d="m0 0-7 4-1-1c-2.7155 0.58673-5.3787 1.2293-8.0625 1.9375-0.75861 0.19529-1.5172 0.39059-2.2988 0.5918-1.8809 0.48501-3.76 0.9772-5.6387 1.4707-0.13277 0.73323-0.26555 1.4665-0.40234 2.2219-1.0134 4.7103-2.2424 8.2155-5.5977 11.778-5.1132 2.6545-10.488 4.1934-16 5.8125-1.6126 0.50105-3.2242 1.0055-4.8347 1.5132-3.3608 1.055-6.7263 2.0926-10.096 3.1172-4.8816 1.4902-9.7379 3.0509-14.588 4.6392-0.77013 0.25213-1.5403 0.50426-2.3337 0.76402-1.5468 0.5067-3.0935 1.0136-4.6402 1.5207-3.8779 1.268-7.7605 2.5211-11.643 3.7739-0.75418 0.24344-1.5084 0.48687-2.2854 0.73769-4.7613 1.5365-9.5231 3.0713-14.285 4.6061-1.2268 0.39542-2.4536 0.79084-3.7175 1.1982-2.4766 0.79802-4.9533 1.5955-7.4302 2.3926-7.4276 2.3919-14.848 4.8064-22.262 7.2373-18.255 5.9813-36.529 11.889-54.883 17.562-0.84659 0.26311-1.6932 0.52622-2.5654 0.7973-2.3726 0.73632-4.747 1.4667-7.1221 2.1949-0.70101 0.21801-1.402 0.43603-2.1243 0.66064-2.8482 0.86583-5.1914 1.4722-8.1882 1.4722 0.27264 0.97888 0.27264 0.97888 0.55078 1.9775 3.9917 14.611 6.3633 27.872 5.4492 43.022h-2c-5.0611-9.8452-9.6513-19.822-14-30-4.4853 4.1835-7.9783 8.8493-11.562 13.812-1.2534 1.7178-2.5073 3.4353-3.7617 5.1523-0.62181 0.8532-1.2436 1.7064-1.8843 2.5854-2.5306 3.4604-5.0924 6.8966-7.6665 10.325-0.47784 0.6368-0.95568 1.2736-1.448 1.9297-4.834 6.4273-9.726 12.81-14.61 19.2-4.4604 5.8494-8.8488 11.746-13.192 17.683-5.1353 7.0156-10.405 13.91-15.766 20.755-3.7632 4.8093-7.4615 9.6602-11.109 14.558-4.2179 5.6637-8.5201 11.253-12.875 16.812-4.8811 6.2348-9.638 12.546-14.312 18.938-5.3639 7.3332-10.884 14.513-16.533 21.628-2.1193 2.6872-4.1989 5.4047-6.2793 8.1221-3.4681 4.5256-6.9709 9.0218-10.5 13.5-3.874 4.9169-7.7118 9.8595-11.522 14.826-9.1315 11.896-18.375 23.705-27.652 35.488-2.2775 2.8936-4.5519 5.7897-6.8267 8.6855-2.7961 3.5592-5.5926 7.1181-8.3906 10.676-5.0542 6.4277-10.1 12.862-15.109 19.324 0.99 1.65 1.98 3.3 3 5-4.1242-1.6617-7.0655-4.6234-10.25-7.625-0.5543-0.51562-1.1086-1.0312-1.6797-1.5625-1.3606-1.2668-2.716-2.5391-4.0703-3.8125 1.6268-3.6539 3.8669-6.596 6.3125-9.75 0.43441-0.56074 0.86883-1.1215 1.3164-1.6992 4.1028-5.2668 8.3245-10.436 12.55-15.604 3.3615-4.1209 6.6595-8.28 9.8838-12.509 3.5663-4.6743 7.1936-9.2908 10.875-13.875 5.7387-7.148 11.418-14.34 17.062-21.562 0.52288-0.66838 1.0458-1.3368 1.5845-2.0254 8.3281-10.652 16.554-21.378 24.736-32.143 2.9156-3.8344 5.8538-7.6498 8.8047-11.457 4.5205-5.8616 8.8975-11.824 13.273-17.794 4.5458-6.1869 9.1826-12.299 13.852-18.393 4.7428-6.1924 9.4013-12.419 13.884-18.802 3.8186-5.3996 7.843-10.637 11.866-15.885 4.8482-6.3256 9.6231-12.679 14.212-19.195 3.5844-5.0695 7.304-10.033 11.038-14.993 13.008-17.283 25.755-34.749 38.348-52.336 0.59031-0.82234 1.1806-1.6447 1.7888-2.4919 1.1321-1.5772 2.2619-3.1561 3.3892-4.7368 0.50974-0.70955 1.0195-1.4191 1.5447-2.1501 0.44618-0.62383 0.89235-1.2477 1.3521-1.8904 2.4758-3.1838 4.393-4.9888 8.2991-6.1675 0.81133-0.24997 1.6227-0.49994 2.4586-0.75749 0.89321-0.26461 1.7864-0.52921 2.7067-0.80183 0.95336-0.29083 1.9067-0.58166 2.889-0.8813 3.218-0.97942 6.4399-1.9453 9.6618-2.9117 2.2999-0.69745 4.5996-1.3959 6.8989-2.0952 4.3839-1.3323 8.7687-2.6616 13.155-3.9868 9.3777-2.8337 18.747-5.6947 28.114-8.5625 3.0712-0.94012 6.1424-1.8802 9.2136-2.8203 1.1475-0.35129 1.1475-0.35129 2.3183-0.70968 9.2804-2.8405 18.563-5.6724 27.846-8.5048 8.2032-2.5031 16.406-5.0088 24.605-7.5237 21.256-6.5191 42.543-12.934 63.862-19.241 2.6425-0.78197 5.2838-1.5678 7.9242-2.357 3.6676-1.0959 7.3393-2.1775 11.012-3.2577 1.6605-0.49876 1.6605-0.49876 3.3544-1.0076 1.0144-0.29583 2.0289-0.59166 3.074-0.89645 0.88496-0.262 1.7699-0.52399 2.6817-0.79393 2.2531-0.43092 2.2531-0.43092 5.2531 0.56908z" fill="#DEDBCB"/>\n <path transform="translate(222,752)" d="m0 0c0.097969 1.2207 0.19594 2.4415 0.29688 3.6992 1.3785 15.768 4.5864 28.154 13.703 41.301 0.4602 0.67805 0.92039 1.3561 1.3945 2.0547 8.4689 11.104 24.144 18.685 37.605 20.945 3.6723 0.22116 7.3228 0.19094 11 0.125 0.96551-0.0090234 1.931-0.018047 2.9258-0.027344 2.3583-0.02335 4.7161-0.056096 7.0742-0.097656 0.17549 4.823-0.23757 8.6279-1.8125 13.188-0.33645 1.0042-0.67289 2.0084-1.0195 3.043-1.1557 2.7403-2.1546 4.5916-4.168 6.7695-2.1538 0.50171-2.1538 0.50171-4.6484 0.49609-1.3744 0.004834-1.3744 0.004834-2.7766 0.0097656-0.97348-0.022559-1.947-0.045117-2.95-0.068359-0.99862-0.016113-1.9972-0.032227-3.0261-0.048828-18.19-0.48409-35.191-6.8886-48.599-19.389-1.1312-0.9958-1.1312-0.9958-2.2852-2.0117-15.52-14.402-24.263-35.347-25.277-56.363-0.066406-2.4609-0.066406-2.4609 0.5625-4.625 3.4222-3.4096 7.078-5.0664 11.562-6.75 1.115-0.42797 2.2301-0.85594 3.3789-1.2969 3.0586-0.95312 3.0586-0.95312 7.0586-0.95312z" fill="#D69E43"/>\n <path transform="translate(300,679)" d="m0 0c3.0317 3.6421 5.5712 7.4095 8.0625 11.438 11.9 18.702 27.212 35.21 44.938 48.562-2.783 4.6383-6.0497 8.1612-9.9219 11.926-1.9804 1.9767-3.8182 4.0146-5.6406 6.1367-2.3436 2.6967-4.6882 5.3869-7.125 8-0.54012 0.5891-1.0802 1.1782-1.6367 1.7852-1.6758 1.1523-1.6758 1.1523-3.6211 1.0234-18.143-7.692-32.71-31.267-39.876-48.891-5.0057-13.128-5.0057-13.128-4.1787-18.98 1.9414-2.7109 1.9414-2.7109 4.5625-5.375 1.3632-1.4173 1.3632-1.4173 2.7539-2.8633 0.88559-0.91137 1.7712-1.8227 2.6836-2.7617 1.3448-1.5107 2.6798-3.0302 4-4.5625 1.6261-1.8802 3.241-3.6785 5-5.4375z" fill="#597A53"/>\n <path transform="translate(709,299)" d="m0 0h1c0.2107 4.5403-0.37761 7.9852-1.9375 12.25-0.35965 1.0364-0.7193 2.0728-1.0898 3.1406-5.8514 12.187-19.647 22.363-29.098 31.734-3.2139 3.1871-6.4244 6.3777-9.6328 9.5703-0.72309 0.7148-1.4462 1.4296-2.1912 2.166-4.0306 4.0114-7.8743 8.1207-11.575 12.44-1.8906 2.1757-3.9083 4.1927-5.9765 6.1991-2.6627 2.6271-5.2126 5.2673-7.625 8.125-3.5747 4.1788-7.4706 8.0084-11.375 11.875-4.4304 4.3876-8.7431 8.7779-12.766 13.547-2.7523 3.0994-5.7324 5.9715-8.6819 8.8811-3.2936 3.2663-6.3676 6.6513-9.3767 10.177-2.4423 2.7611-5.0813 5.3092-7.707 7.8945-1.9086 1.9389-3.6959 3.937-5.4688 6-2.3968 2.789-4.8796 5.4199-7.5 8-2.4971 2.4591-4.8606 4.9509-7.125 7.625-3.4278 3.9965-7.1353 7.6743-10.875 11.375-4.2969 4.2521-8.4552 8.5277-12.363 13.145-1.9557 2.2171-4.0323 4.2792-6.1367 6.3555-2.6627 2.6271-5.2126 5.2673-7.625 8.125-4.1496 4.8509-8.727 9.2785-13.282 13.745-3.1547 3.112-6.1806 6.2622-9.062 9.6304-4.1733 4.8399-8.8501 9.0602-13.57 13.355-4.096 3.7718-7.8681 7.6736-11.479 11.914-3.4081 3.9797-7.2579 7.4981-11.107 11.043-1.1331 1.0461-1.1331 1.0461-2.2891 2.1133-2.0859 1.5742-2.0859 1.5742-5.0859 1.5742-2.0948 1.6918-2.0948 1.6918-4.125 3.875-1.0557 1.0789-1.0557 1.0789-2.1328 2.1797-1.7962 1.8336-1.7962 1.8336-2.7422 3.9453l-2-1c5.0659-5.961 10.396-11.664 15.745-17.37 3.2686-3.4905 6.5098-6.9986 9.6926-10.568 4.5965-5.1484 9.3291-10.166 14.072-15.179 3.6989-3.9225 7.2942-7.9151 10.829-11.986 2.4388-2.7858 4.9516-5.4996 7.4736-8.21 1.042-1.1247 2.0836-2.2497 3.125-3.375 0.51305-0.5543 1.0261-1.1086 1.5547-1.6797 5.0266-5.4433 10.031-10.908 14.883-16.508 3.6073-4.1544 7.3481-8.1822 11.099-12.207 2.6949-2.8999 5.3367-5.8352 7.9321-8.8247 4.1992-4.8221 8.5917-9.4524 12.988-14.094 3.7604-3.9861 7.4233-8.034 10.996-12.189 1.6392-1.844 3.3487-3.5828 5.1094-5.3105 2.2933-2.258 4.4643-4.56 6.5625-7 5.1684-5.9857 10.626-11.708 16.036-17.474 1.8617-1.9841 3.7216-3.9698 5.5811-5.9561 3.1132-3.3247 6.2293-6.6466 9.3467-9.9673 1.3605-1.4497 2.7205-2.9 4.0801-4.3506 2.1301-2.2727 4.2617-4.5439 6.3936-6.8149 0.6463-0.69013 1.2926-1.3803 1.9585-2.0913 3.0535-3.2496 6.1349-6.4582 9.2993-9.6001 2.3124-2.2965 4.5196-4.6239 6.6172-7.1211 2.5913-3.0097 5.2975-5.8359 8.125-8.625 2.7862-2.7486 5.4531-5.5286 8-8.5 3.18-3.7101 6.5876-7.1298 10.094-10.531 1.9594-2.0103 3.7888-4.0495 5.6172-6.1758 4.0901-4.7132 8.4794-9.0936 12.914-13.48 1.1776-1.1708 1.1776-1.1708 2.3789-2.3652 1.5045-1.4956 3.01-2.9903 4.5166-4.4839 2.3333-2.3144 4.6578-4.6373 6.9795-6.9634l2-2z" fill="#999E95"/>\n <path transform="translate(330,646)" d="m0 0c3.0643 2.8786 5.7032 5.8393 8.25 9.1875 13.862 18.047 30.869 32.924 48.75 46.812-3.4059 4.8032-6.9622 9.1072-11.195 13.199-2.5843 2.5788-4.947 5.3327-7.3242 8.1016-1.1122 1.2765-2.2833 2.502-3.4805 3.6992-4.3036-0.136-7.245-3.4296-10.312-6.125-0.60812-0.52989-1.2162-1.0598-1.8428-1.6057-16.559-14.619-35.238-32.125-40.845-54.269 0.56848-0.55688 1.137-1.1138 1.7227-1.6875 4.4723-4.42 8.7818-8.9028 12.867-13.684 1.0864-1.255 2.2364-2.4552 3.4102-3.6289z" fill="#557450"/>\n <path transform="translate(269,715)" d="m0 0c1.8167 2.7251 2.8339 5.1722 3.9016 8.2412 7.6075 21.783 22.031 41.387 40.098 55.759-1.3319 3.9444-2.9465 6.3059-5.9141 9.207-0.76055 0.75088-1.5211 1.5018-2.3047 2.2754-0.79406 0.76893-1.5881 1.5379-2.4062 2.3301-0.8018 0.78826-1.6036 1.5765-2.4297 2.3887-1.9752 1.9399-3.957 3.8724-5.9453 5.7988-2.6824-1.2558-4.9113-2.5933-7.1719-4.5039-0.5779-0.48823-1.1558-0.97646-1.7512-1.4795-14.855-12.84-27.297-28.164-30.764-48.079-0.12955-0.68127-0.2591-1.3625-0.39258-2.0645-0.35398-1.9497-0.63857-3.9116-0.91992-5.873-0.15727-1.0068-0.31453-2.0135-0.47656-3.0508 0.73735-4.5631 3.5816-6.9043 6.7891-10.074 1.1851-1.2095 2.3687-2.4204 3.5508-3.6328 0.82685-0.83966 0.82685-0.83966 1.6704-1.6963 1.6526-1.7423 3.1039-3.5687 4.4663-5.5459z" fill="#567651"/>\n <path transform="translate(192,769)" d="m0 0h1c0.14695 1.4715 0.14695 1.4715 0.29688 2.9727 2.6679 24.875 11.39 47.293 30.809 63.898 17.824 13.11 36.184 17.082 57.895 18.129-3.6339 3.1796-6.9801 5.0137-11.5 6.6875-1.1034 0.41637-2.2069 0.83273-3.3438 1.2617-15.543 5.1747-31.668 2.2134-46.242-4.3359-17.807-9.1029-29.218-23.283-36.078-41.746-4.3069-14.772-2.4333-29.741 4.9141-43.18 0.73723-1.2369 1.482-2.4695 2.25-3.6875z" fill="#DBA445"/>\n <path transform="translate(350,620)" d="m0 0c4.1266 1.5864 6.6322 4.5923 9.5 7.8125 1.0729 1.1824 2.1458 2.3646 3.2188 3.5469 0.54527 0.60521 1.0905 1.2104 1.6523 1.834 10.089 11.19 20.27 22.369 31.754 32.154 3.4577 3.0471 6.6484 6.3647 9.875 9.6523l4 4-11 11c-3.0348-1.5174-5.0628-2.7095-7.6094-4.793-1.0017-0.81573-1.0017-0.81573-2.0237-1.6479-1.0479-0.86456-1.0479-0.86456-2.1169-1.7466-0.72373-0.59442-1.4475-1.1888-2.1931-1.8013-2.0228-1.6658-4.0411-3.3368-6.0569-5.0112-0.71422-0.59087-1.4284-1.1817-2.1643-1.7905-14.287-11.926-27.473-26.068-36.836-42.209 3.2076-3.8064 6.4075-7.5456 10-11z" fill="#536F4F"/>\n <path transform="translate(541,482)" d="m0 0c0.8125 2.1875 0.8125 2.1875 1 5-2.3125 2.5-2.3125 2.5-5 5-0.29624 0.78206-0.59249 1.5641-0.89771 2.3699-1.3216 3.1535-2.9794 4.8341-5.4265 7.2122-0.86432 0.85014-1.7286 1.7003-2.6191 2.5762-0.90557 0.87592-1.8111 1.7518-2.7441 2.6543-7.198 6.9689-7.198 6.9689-13.957 14.355-4.1005 4.7943-8.7352 8.9477-13.395 13.188-4.096 3.7718-7.8681 7.6736-11.479 11.914-3.4081 3.9797-7.2579 7.4981-11.107 11.043-0.75539 0.69738-1.5108 1.3948-2.2891 2.1133-2.0859 1.5742-2.0859 1.5742-5.0859 1.5742-2.0948 1.6918-2.0948 1.6918-4.125 3.875-1.0557 1.0789-1.0557 1.0789-2.1328 2.1797-1.7962 1.8336-1.7962 1.8336-2.7422 3.9453l-2-1c5.0659-5.961 10.396-11.664 15.745-17.37 3.2686-3.4905 6.5098-6.9986 9.6926-10.568 4.5965-5.1484 9.3291-10.166 14.072-15.179 3.6989-3.9225 7.2942-7.9151 10.829-11.986 2.4388-2.7858 4.9512-5.5 7.4736-8.21 2.9913-3.22 5.9796-6.4401 8.9023-9.7227 13.359-14.965 13.359-14.965 17.285-14.965z" fill="#8F958D"/>\n <path transform="translate(314,472)" d="m0 0 1 2c-0.70393 1.6517-1.4143 3.301-2.1582 4.9351-1.4948 3.6667-2.2224 7.5243-3.0918 11.377-2.2031 9.317-5.3595 18.002-9.0132 26.835-1.0262 2.5802-1.8744 5.214-2.7368 7.8525l-1 2c-2.6475-2.5778-4.9443-4.9165-7-8 0.34214-3.6963 1.5738-6.3842 3.4414-9.5547 0.49766-0.85521 0.99532-1.7104 1.5081-2.5916 0.79845-1.3507 0.79845-1.3507 1.613-2.7288 1.0954-1.8831 2.1892-3.7673 3.2812-5.6523 0.53754-0.92667 1.0751-1.8533 1.6289-2.8081 4.4393-7.7447 8.5598-15.669 12.527-23.665z" fill="#9EA298"/>\n <path transform="translate(835,164)" d="m0 0 1 3c-14.214 14.476-14.214 14.476-21 19v-3l-2-1c3.1818-11.319 3.1818-11.319 7.8545-14.106 4.5667-1.8864 9.3062-2.9567 14.146-3.8936z" fill="#BBBCAE"/>\n <path transform="translate(489,537)" d="m0 0 1 3c-0.99 0.33-1.98 0.66-3 1l0.375 2.1875c-0.375 2.8125-0.375 2.8125-3.0625 5.3125-0.55043 0.4125-1.1009 0.825-1.668 1.25-1.8702 1.3631-1.8702 1.3631-4.1445 3.75-2.7216 2.7216-5.4617 5.1369-8.5 7.5h-2c-1.9982 1.7153-1.9982 1.7153-4.0625 3.875-0.71285 0.7193-1.4257 1.4386-2.1602 2.1797-1.8323 1.8276-1.8323 1.8276-2.7773 3.9453l-2-1c4.5796-5.3888 9.3633-10.581 14.188-15.75 0.60602-0.64977 1.212-1.2995 1.8364-1.969 4.0865-4.3668 8.1549-8.6631 12.726-12.531l1.8594-1.5781 1.3906-1.1719z" fill="#8A9188"/>\n <path transform="translate(507,525)" d="m0 0c0 3 0 3-1.5605 4.8694-0.71221 0.68377-1.4244 1.3675-2.1582 2.072-1.1505 1.1225-1.1505 1.1225-2.3242 2.2676-1.2162 1.165-1.2162 1.165-2.457 2.3535-1.5981 1.5384-3.1921 3.0812-4.7812 4.6289-0.71221 0.68264-1.4244 1.3653-2.1582 2.0686-1.7831 1.5986-1.7831 1.5986-1.5605 3.74h-3l-0.25 1.875c-0.99452 2.8178-2.1266 2.8352-4.75 4.125-1.7442 1.4565-1.7442 1.4565-3.3828 3.1523-0.60973 0.61166-1.2195 1.2233-1.8477 1.8535-0.6252 0.63744-1.2504 1.2749-1.8945 1.9316-0.63293 0.63357-1.2659 1.2671-1.918 1.9199-2.6158 2.6408-4.8858 5.0357-6.957 8.1426-0.99-0.33-1.98-0.66-3-1 0.4241-0.4125 0.8482-0.825 1.2852-1.25 3.8837-3.824 7.5292-7.7774 11.09-11.902 2.1049-2.3933 4.342-4.6247 6.625-6.8477 2.7908-2.781 5.5691-5.574 8.3398-8.375 1.1992-1.2084 2.3984-2.4167 3.5977-3.625 0.5949-0.60328 1.1898-1.2066 1.8027-1.8281 3.5986-3.6183 7.2862-6.9688 11.26-10.172z" fill="#666E68"/>\n <path transform="translate(317,466)" d="m0 0c8.7329 9.7032 10.899 21.728 13.625 34.062 0.57344 2.5517 1.1507 5.1024 1.7325 7.6522 0.35842 1.5749 0.71172 3.151 1.0587 4.7284 2.1677 10.528 2.1677 10.528 7.5838 19.557l-1 2c-8.3233-7.6297-9.3156-21.34-11-32h-2l-0.25-3.5625c-1.0117-9.1056-3.4093-18.364-7.75-26.438h-4l2-6z" fill="#889088"/>\n <path transform="translate(222,752)" d="m0 0v15c-2.2091-3.3137-2.2248-4.3446-2.125-8.1875 0.018047-0.90105 0.036094-1.8021 0.054688-2.7305 0.023203-0.68707 0.046406-1.3741 0.070312-2.082-1.8983 0.59643-3.7935 1.2025-5.6875 1.8125-1.0557 0.33645-2.1115 0.67289-3.1992 1.0195-4.3488 1.5799-4.3488 1.5799-8.1133 4.168-0.54462 2.7532-0.78934 4.9314-0.8125 7.6875-0.025137 0.70189-0.050273 1.4038-0.076172 2.127-0.058773 1.7279-0.087938 3.4568-0.11133 5.1855h2l1 12c-5.4892-5.4892-5.3219-17.243-5.5938-24.695 0.88616-3.4397 2.6573-4.4001 5.5938-6.3047 3.1914-1.4844 3.1914-1.4844 6.5625-2.75 1.115-0.42797 2.2301-0.85594 3.3789-1.2969 3.0586-0.95312 3.0586-0.95312 7.0586-0.95312z" fill="#F2CF53"/>\n <path transform="translate(630,268)" d="m0 0v20h-2c-1.2284-2.241-2.4323-4.4901-3.625-6.75-0.35062-0.63422-0.70125-1.2684-1.0625-1.9219-0.97656-1.875-0.97656-1.875-2.3125-5.3281 0.78906-2.4531 0.78906-2.4531 2-4 0.99 0.33 1.98 0.66 3 1 0.47438-0.495 0.94875-0.99 1.4375-1.5 1.5625-1.5 1.5625-1.5 2.5625-1.5z" fill="#D4D2C0"/>\n <path transform="translate(221,899)" d="m0 0c6.329 0.82552 6.329 0.82552 8.9004 1.4941 9.0828 2.2894 18.432 1.7221 27.725 1.6309 1.7852-0.010049 3.5703-0.019171 5.3555-0.027344 4.34-0.021864 8.6797-0.056288 13.02-0.097656-14.144 7.6979-38.701 2.826-53.121-1.4141-0.62004-0.19336-1.2401-0.38672-1.8789-0.58594v-1z" fill="#A6724F"/>\n <path transform="translate(463,641)" d="m0 0c3.0879 1.4354 5.6993 3.1697 8.4375 5.1875 5.8984 4.1968 12.138 7.4995 18.562 10.812-3.0103 0.93424-3.8665 1.0445-7 0 0.99 1.32 1.98 2.64 3 4-3.9512-1.622-6.7581-4.3566-9.8125-7.25-1.0629-0.99313-2.1267-1.9853-3.1914-2.9766-0.51192-0.47728-1.0238-0.95455-1.5513-1.4463-1.8547-1.7037-3.7651-3.3342-5.6948-4.9521l-2.75-2.375v-1z" fill="#262B26"/>\n <path transform="translate(232,859)" d="m0 0c0.92941 0.1534 1.8588 0.3068 2.8164 0.46484 5.0197 0.71709 10.059 0.88661 15.121 1.0977 0.97002 0.043184 1.94 0.086367 2.9395 0.13086 2.3742 0.10526 4.7486 0.2074 7.123 0.30664l-1 3c-3.0833 0.058225-6.1664 0.093671-9.25 0.125-1.309 0.025137-1.309 0.025137-2.6445 0.050781-0.84434 0.0064453-1.6887 0.012891-2.5586 0.019531-0.77505 0.010474-1.5501 0.020947-2.3486 0.031738-4.1383-0.42744-6.9982-2.7127-10.198-5.2271z" fill="#D69E3F"/>\n <path transform="translate(594,390)" d="m0 0c0 3 0 3-1.8984 5.0859-1.6456 1.521-3.2915 3.0419-4.9375 4.5625-2.2384 2.4324-3.0164 4.2993-4.1641 7.3516-3.2847 4.1286-6.8038 7.5828-12 9 1.4841-3.4865 3.4621-5.6419 6.1875-8.25 3.6022-3.5155 6.9624-7.1351 10.238-10.953 2.0876-2.3829 4.3006-4.5921 6.5742-6.7969z" fill="#1C211D"/>\n <path transform="translate(500,523)" d="m0 0c0 3 0 3-2 6v3c-1.4258 1.8242-1.4258 1.8242-3.3125 3.6875-0.92232 0.93393-0.92232 0.93393-1.8633 1.8867-1.8242 1.4258-1.8242 1.4258-4.8242 1.4258-1.655 1.0773-1.655 1.0773-3.1875 2.5l-2.8125 2.5c1.4841-3.4865 3.4621-5.6419 6.1875-8.25 4.1709-4.0697 8.0464-8.3058 11.812-12.75z" fill="#989F95"/>\n <path transform="translate(314,472)" d="m0 0 1 2c-0.70673 1.6582-1.4197 3.314-2.1675 4.9541-1.7251 4.2393-2.4514 8.79-3.3813 13.257-0.42594 1.9433-0.93217 3.8686-1.4512 5.7891l-2 1v-7l-3 3c1.5565-5.3537 3.9818-10.002 6.625-14.875 0.42023-0.78375 0.84047-1.5675 1.2734-2.375 1.0297-1.9189 2.065-3.8348 3.1016-5.75z" fill="#AFB2A7"/>\n <path transform="translate(321,656)" d="m0 0c0 3 0 3-1.418 4.5078-0.87592 0.80051-0.87592 0.80051-1.7695 1.6172-2.3576 2.6146-2.3576 2.6146-2.7539 5.9805 2.2333 7.129 6.4275 14.807 11.941 19.895l-1 3c-5.7437-7.2744-11.359-15.002-14-24 0.97563-3.3476 3.1483-5.365 5.625-7.75 0.63164-0.61359 1.2633-1.2272 1.9141-1.8594 0.72316-0.68836 0.72316-0.68836 1.4609-1.3906z" fill="#659060"/>\n <path transform="translate(843,162)" d="m0 0-7 4-1-1c-1.1954 0.37137-1.1954 0.37137-2.415 0.75024-2.9645 0.91567-5.9317 1.8222-8.9009 2.7227-1.9138 0.58341-3.8243 1.1773-5.7349 1.7712-1.8079 0.54624-1.8079 0.54624-3.6523 1.1035-1.6653 0.51059-1.6653 0.51059-3.3643 1.0315-2.8388 0.60099-4.2578 0.62531-6.9326-0.37915 8.6851-3.0151 17.427-5.7923 26.25-8.375 1.3751-0.4121 1.3751-0.4121 2.7781-0.83252 0.86214-0.24863 1.7243-0.49726 2.6125-0.75342 0.7686-0.22478 1.5372-0.44956 2.3291-0.68115 2.0303-0.35791 2.0303-0.35791 5.0303 0.64209z" fill="#EEEEE7"/>\n <path transform="translate(363,539)" d="m0 0c2.4928 2.1978 3.4918 3.8839 4.3906 7.0664 1.9026 6.1312 4.7821 11.714 7.6445 17.443 0.39574 0.81018 0.79148 1.6204 1.1992 2.4551 0.36319 0.72824 0.72639 1.4565 1.1006 2.2068 0.21946 0.60336 0.43893 1.2067 0.66504 1.8284l-1 2c-2.31-2.64-4.62-5.28-7-8l2-1c-0.72316-1.4676-0.72316-1.4676-1.4609-2.9648-3.3664-6.9464-6.3244-13.343-7.5391-21.035z" fill="#202520"/>\n <path transform="translate(434,704)" d="m0 0 2 2-2.125-0.14062-2.875-0.10938c-1.3922-0.069609-1.3922-0.069609-2.8125-0.14062-8.3614 1.0247-13.593 6.2565-19.188 12.141-0.67934 0.69738-1.3587 1.3948-2.0586 2.1133-1.6567 1.7034-3.3033 3.4154-4.9414 5.1367l-2-3c0.71543-0.38285 1.4309-0.7657 2.168-1.1602 3.2202-2.092 5.5201-4.4782 8.1445-7.2773 7.0863-7.2645 13.197-11.239 23.688-9.5625z" fill="#0C0B12"/>\n <path transform="translate(529,502)" d="m0 0c0 3 0 3-1.4961 4.7188-0.961 0.88172-0.961 0.88172-1.9414 1.7812-2.4839 2.2882-3.4713 3.2264-4.5625 6.5-3.3945 3.6854-7.1233 6.8445-11 10l-2-1c2.3733-2.5433 4.7489-5.0843 7.125-7.625 0.66516-0.71285 1.3303-1.4257 2.0156-2.1602 3.882-4.1484 7.8168-8.2227 11.859-12.215z" fill="#5F6662"/>\n <path transform="translate(636,389)" d="m0 0 1 2c-2.7844 3.6093-5.7605 6.7977-9 10-0.9655 0.96419-1.9303 1.929-2.8945 2.8945l-8.1055 8.1055-2-1c2.3733-2.5433 4.7489-5.0843 7.125-7.625 0.66516-0.71285 1.3303-1.4257 2.0156-2.1602 3.882-4.1484 7.8168-8.2227 11.859-12.215z" fill="#69706C"/>\n <path transform="translate(746,366)" d="m0 0c4.8363 0.99044 9.4762 1.957 14 4-3 1-3 1-5 1 0.99902 0.69867 1.998 1.3973 3.0273 2.1172 1.3035 0.91905 2.6069 1.8383 3.9102 2.7578 0.65936 0.4602 1.3187 0.92039 1.998 1.3945 4.9512 3.5039 4.9512 3.5039 6.0645 5.7305-3.9726-1.3958-6.962-3.2766-10.312-5.8125-3.382-2.5251-6.7496-4.9015-10.375-7.0625l-3.3125-2.125v-2z" fill="#1E231E"/>\n <path transform="translate(287,640)" d="m0 0c0 3.3118-0.54378 4.313-2.25 7.0625-0.62648 1.0383-0.62648 1.0383-1.2656 2.0977-1.6814 2.084-3.1057 2.6754-5.4844 3.8398-1.8591 1.8681-1.8591 1.8681-3.5625 4-2.1111 2.5577-3.6372 4.1331-6.4375 6 1.6832-4.2338 4.7224-7.1317 7.8125-10.375 3.8774-4.1027 7.6144-8.2528 11.188-12.625z" fill="#B17C56"/>\n <path transform="translate(269,715)" d="m0 0c1.7369 2.6054 2.691 4.5834 3.6875 7.5 0.27199 0.77344 0.54398 1.5469 0.82422 2.3438 0.48828 2.1562 0.48828 2.1562-0.51172 5.1562l-4-9-3.8125 2.875c-2.3634 1.7822-4.7226 3.4818-7.1875 5.125 1.5778-3.7105 3.907-6.2991 6.625-9.25 0.81727-0.89203 1.6345-1.7841 2.4766-2.7031 0.62648-0.67547 1.253-1.3509 1.8984-2.0469z" fill="#659360"/>\n <path transform="translate(539,583)" d="m0 0 2 1c-2.7654 2.8396-5.5406 5.6692-8.3252 8.49-1.4099 1.4324-2.8119 2.8725-4.2139 4.3127-0.88945 0.89912-1.7789 1.7982-2.6953 2.7246-0.81694 0.83265-1.6339 1.6653-2.4756 2.5232-2.2207 1.8905-3.4429 2.5807-6.29 2.9495 4.1488-5.1314 8.6395-9.4801 13.586-13.844 2.9258-2.6133 5.6771-5.3473 8.4141-8.1562z" fill="#252A24"/>\n <path transform="translate(624,272)" d="m0 0c1.9375 0.5625 1.9375 0.5625 4 2 0.6875 3.1875 0.6875 3.1875 1 7l1 7h-2c-2.6939-4.7755-4.3135-9.5655-5-15l1-1z" fill="#CAC8B8"/>\n <path transform="translate(365,599)" d="m0 0h2c1.4102 1.4688 1.4102 1.4688 3.0625 3.5 2.6813 3.175 5.4664 5.9251 8.625 8.625 3.5174 3.0372 6.0011 5.8552 8.3125 9.875-3.4361-1.4823-5.687-3.4295-8.3281-6.0625-0.79922-0.79664-1.5984-1.5933-2.4219-2.4141-0.825-0.83273-1.65-1.6655-2.5-2.5234-0.84047-0.83273-1.6809-1.6655-2.5469-2.5234-0.79406-0.79664-1.5881-1.5933-2.4062-2.4141-1.093-1.0963-1.093-1.0963-2.208-2.2148-1.5889-1.8477-1.5889-1.8477-1.5889-3.8477z" fill="#6A736B"/>\n <path transform="translate(809,287)" d="m0 0c1.9919 6.925-1.0559 14.487-4.1875 20.75l-1.8125 3.25c-1.1931-3.4444-0.80482-5.3763 0.43359-8.7656 0.31904-0.88945 0.63809-1.7789 0.9668-2.6953 0.34225-0.92039 0.68449-1.8408 1.0371-2.7891 0.33838-0.93586 0.67676-1.8717 1.0254-2.8359 0.83619-2.3083 1.6821-4.6126 2.5371-6.9141z" fill="#272D28"/>\n <path transform="translate(264,854)" d="m0 0h18c-4.4605 3.5684-6.8589 5.1911-12 7-0.99-0.33-1.98-0.66-3-1 2.31-0.99 4.62-1.98 7-3l-10-2v-1z" fill="#EEBC46"/>\n <path transform="translate(782,362)" d="m0 0c1.2403 3.7209 0.5719 4.9946-0.75 8.625-0.5182 1.4734-0.5182 1.4734-1.0469 2.9766-1.2031 2.3984-1.2031 2.3984-4.2031 3.3984-2.6992-0.99609-2.6992-0.99609-5.6875-2.4375-0.99387-0.47309-1.9877-0.94617-3.0117-1.4336-0.75926-0.37254-1.5185-0.74508-2.3008-1.1289 3.4787-1.1596 4.3422-0.77457 7.6875 0.4375 0.80824 0.28746 1.6165 0.57492 2.4492 0.87109 0.61488 0.22816 1.2298 0.45633 1.8633 0.69141v-2h2c0.99-3.3 1.98-6.6 3-10z" fill="#868E89"/>\n <path transform="translate(734,320)" d="m0 0 3 2c0.1875 2.625 0.1875 2.625 0 5h2l-1 3h-4v-3c-0.99-0.33-1.98-0.66-3-1v-5c0.99 0.33 1.98 0.66 3 1v-2z" fill="#7B827E"/>\n <path transform="translate(350,620)" d="m0 0c2.8606 1.3594 4.8593 2.6452 7 5l-1 2-5-4c-0.48211 0.50531-0.96422 1.0106-1.4609 1.5312-0.63164 0.64969-1.2633 1.2994-1.9141 1.9688-0.62648 0.64969-1.253 1.2994-1.8984 1.9688-1.7266 1.5312-1.7266 1.5312-3.7266 1.5312l-1 2c0-3 0-3 1.9688-5.2617 1.253-1.2008 1.253-1.2008 2.5312-2.4258 0.83531-0.80824 1.6706-1.6165 2.5312-2.4492 0.64969-0.61488 1.2994-1.2298 1.9688-1.8633z" fill="#5F845A"/>\n <path transform="translate(193,766)" d="m0 0c2 2 2 2 2.25 5.5-0.25 3.5-0.25 3.5-2.25 5.5l-1-7c-1.98 3.63-3.96 7.26-6 11l-1-2c0.89062-2.2773 0.89062-2.2773 2.25-4.9375 0.43828-0.87527 0.87656-1.7505 1.3281-2.6523 1.2949-2.1948 2.5315-3.7255 4.4219-5.4102z" fill="#1D202B"/>\n <path transform="translate(732,266)" d="m0 0 2 1c-1.9681 1.9681-3.9364 3.936-5.9062 5.9023-1.6034 1.6064-3.1949 3.2245-4.7812 4.8477-2.3234 2.2606-4.7471 4.271-7.3125 6.25l-2-1c0.43868-0.40839 0.87737-0.81678 1.3293-1.2375 1.9949-1.8578 3.989-3.7163 5.9832-5.575 1.0354-0.9639 1.0354-0.9639 2.0918-1.9473 0.66709-0.62197 1.3342-1.2439 2.0215-1.8848 0.91906-0.85622 0.91906-0.85622 1.8567-1.7297 1.6011-1.5155 3.1671-3.0587 4.7175-4.6257z" fill="#69706D"/>\n <path transform="translate(568,461)" d="m0 0v5c-1.4609 1.1836-1.4609 1.1836-3.375 2.4375-2.7109 1.7794-3.753 2.7544-5.625 5.5625-1.7266 1.3867-1.7266 1.3867-3.625 2.6875-0.94746 0.65549-0.94746 0.65549-1.9141 1.3242-0.72316 0.4892-0.72316 0.4892-1.4609 0.98828 1.3584-3.0433 2.8846-5.1231 5.2578-7.4531 0.6252-0.61875 1.2504-1.2375 1.8945-1.875 0.65098-0.63422 1.302-1.2684 1.9727-1.9219 0.65871-0.64969 1.3174-1.2994 1.9961-1.9688 1.6219-1.5984 3.2482-3.1919 4.8789-4.7812z" fill="#686F6B"/>\n <path transform="translate(242,692)" d="m0 0 1 3-1.9375 1.25c-2.2156 1.5244-2.2156 1.5244-2.5 3.6875-0.86056 3.1554-2.9377 4.27-5.5625 6.0625h-2c1.5778-3.7105 3.907-6.2991 6.625-9.25 0.81727-0.89203 1.6345-1.7841 2.4766-2.7031 0.62648-0.67547 1.253-1.3509 1.8984-2.0469z" fill="#D69566"/>\n <path transform="translate(309,616)" d="m0 0c0 3.5166-0.67787 4.3185-2.75 7.0625-0.51047 0.69223-1.0209 1.3845-1.5469 2.0977-1.7987 1.9431-3.3542 2.6892-5.7031 3.8398l-2 3-2-1c1.3891-1.7553 2.7866-3.504 4.1875-5.25 0.7773-0.97453 1.5546-1.9491 2.3555-2.9531 2.3127-2.6326 4.6551-4.7066 7.457-6.7969z" fill="#C58B5F"/>\n <path transform="translate(296,820)" d="m0 0c0.125 3.375 0.125 3.375 0 7l-2 2v-7h-20v-1c2.9166-0.16803 5.8333-0.33448 8.75-0.5 1.2375-0.071543 1.2375-0.071543 2.5-0.14453 1.1988-0.067676 1.1988-0.067676 2.4219-0.13672 0.73315-0.041895 1.4663-0.083789 2.2217-0.12695 2.0338-0.08863 4.0707-0.091797 6.1064-0.091797z" fill="#EDBA44"/>\n <path transform="translate(365,540)" d="m0 0c1.1289 0.93274 2.253 1.8714 3.375 2.8125 0.62648 0.52207 1.253 1.0441 1.8984 1.582 1.7266 1.6055 1.7266 1.6055 3.7266 4.6055h-4l-2 2c-0.50368-1.4571-1.0028-2.9157-1.5-4.375-0.27844-0.81211-0.55688-1.6242-0.84375-2.4609-0.65625-2.1641-0.65625-2.1641-0.65625-4.1641z" fill="#7D867F"/>\n <path transform="translate(710,299)" d="m0 0c0.26925 4.8028-0.56762 8.2823-2.3125 12.75-0.64389 1.6938-0.64389 1.6938-1.3008 3.4219-1.3867 2.8281-1.3867 2.8281-4.3867 4.8281 1.8676-5.7221 3.8529-11.377 6-17l-2-1c2.875-3 2.875-3 4-3z" fill="#A3A89F"/>\n <path transform="translate(805,242)" d="m0 0h4c-1.4526 3.8295-3.429 5.1205-7 7l-2-2c-0.99-0.33-1.98-0.66-3-1l1-2c1.9929-0.37366 3.9936-0.70741 6-1l1-1z" fill="#7B827F"/>\n <path transform="translate(544,647)" d="m0 0c5.6683 0.59468 10.603 2.0924 15.938 4.0625 0.77924 0.28166 1.5585 0.56332 2.3613 0.85352 1.9026 0.68866 3.8022 1.3855 5.7012 2.084-3.4782 1.1594-5.459 0.70821-9 0v-2c-0.91523-0.19336-1.8305-0.38672-2.7734-0.58594-1.1885-0.26039-2.377-0.52078-3.6016-0.78906-1.1834-0.25523-2.3667-0.51047-3.5859-0.77344-3.0391-0.85156-3.0391-0.85156-5.0391-2.8516z" fill="#A47250"/>\n <path transform="translate(477,554)" d="m0 0 2 1c-0.77086 0.83145-1.5417 1.6629-2.3359 2.5195-1.0131 1.0976-2.0261 2.1952-3.0391 3.293-0.50789 0.54721-1.0158 1.0944-1.5391 1.6582-2.2381 2.4295-4.2497 4.775-6.0859 7.5293-0.99-0.33-1.98-0.66-3-1 0.63615-0.61875 0.63615-0.61875 1.2852-1.25 4.4672-4.3985 8.6427-8.9847 12.715-13.75z" fill="#606762"/>\n <path transform="translate(538,756)" d="m0 0c-2.2887 1.3386-4.5807 2.671-6.875 4-0.65098 0.38156-1.302 0.76312-1.9727 1.1562-4.9258 2.8438-4.9258 2.8438-7.1523 2.8438l-1 2-2-2c1.2891-0.67155 2.5814-1.3371 3.875-2 0.7193-0.37125 1.4386-0.7425 2.1797-1.125 1.9453-0.875 1.9453-0.875 3.9453-0.875l1-3c5.4023-2.2989 5.4023-2.2989 8-1z" fill="#A97551"/>\n <path transform="translate(311,481)" d="m0 0h3c-0.56821 5.4548-1.9464 9.9106-4 15l-2-2c0.46094-3.0391 0.46094-3.0391 1.375-6.625 0.29648-1.1885 0.59297-2.377 0.89844-3.6016 0.23977-0.91523 0.47953-1.8305 0.72656-2.7734z" fill="#707770"/>\n <path transform="translate(697,160)" d="m0 0c-2.2881 2.2881-3.8075 2.7545-6.875 3.6875-0.86367 0.27199-1.7273 0.54398-2.6172 0.82422-2.5948 0.50521-4.0386 0.34389-6.5078-0.51172h2v-2c4.9274-1.9709 8.7802-2.18 14-2z" fill="#D39968"/>\n <path transform="translate(275,656)" d="m0 0 2 1c-0.48211 0.47051-0.96422 0.94102-1.4609 1.4258-0.63164 0.62262-1.2633 1.2452-1.9141 1.8867-0.62648 0.61488-1.253 1.2298-1.8984 1.8633-1.9074 1.9123-1.9074 1.9123-3.7266 4.8242-1.9675 1.0625-3.9659 2.0714-6 3 1.5658-4.0372 4.4417-6.4707 7.625-9.25l1.5625-1.3906c1.266-1.1253 2.5386-2.2431 3.8125-3.3594z" fill="#D29566"/>\n <path transform="translate(489,537)" d="m0 0 1 3c-0.99 0.33-1.98 0.66-3 1 0.061875 0.78375 0.12375 1.5675 0.1875 2.375l-0.1875 2.625-3 2-2-4 7-7zm-8 8 1 3-2-1 1-2z" fill="#7E847C"/>\n <path transform="translate(395,449)" d="m0 0 1 3-10 9c0-3.524 0.55115-4.015 2.8125-6.5625 0.78311-0.89912 0.78311-0.89912 1.582-1.8164 1.6055-1.6211 1.6055-1.6211 4.6055-3.6211z" fill="#CA8F63"/>\n <path transform="translate(659,351)" d="m0 0 1 4-2.5625 1.5625c-3.9798 2.631-7.166 5.9918-10.438 9.4375 0-3 0-3 2.625-5.918 1.1175-1.0975 2.2429-2.1871 3.375-3.2695 0.57234-0.55881 1.1447-1.1176 1.7344-1.6934 1.4153-1.3799 2.8396-2.7504 4.2656-4.1191z" fill="#B3B8AE"/>\n <path transform="translate(295,434)" d="m0 0 2 1c-2.8252 4.6725-5.6776 7.66-10 11 0-3.9613 1.3488-4.8291 4-7.6875 0.7425-0.80824 1.485-1.6165 2.25-2.4492 0.5775-0.61488 1.155-1.2298 1.75-1.8633z" fill="#AE7B56"/>\n <path transform="translate(752,369)" d="m0 0c8.282 0.34725 8.282 0.34725 11.062 2.875 0.9375 2.125 0.9375 2.125 0.9375 5.125-4.5567-1.5189-8.3172-3.954-12-7v-1z" fill="#3D443E"/>\n <path transform="translate(197,888)" d="m0 0c3.7189 0.50712 6.7345 1.1161 10 3v2c1.98 0.66 3.96 1.32 6 2-3 1-3 1-6.1367-0.43359-1.1893-0.65777-2.3727-1.3262-3.5508-2.0039-0.6065-0.33838-1.213-0.67676-1.8379-1.0254-1.4966-0.83669-2.9863-1.6857-4.4746-2.5371v-1z" fill="#B9825A"/>\n <path transform="translate(551,613)" d="m0 0 2 1-12 11-2-1c1.3021-1.4974 2.6042-2.9948 3.9062-4.4922 1.2895-1.4672 1.2895-1.4672 1.0938-3.5078 0.78375-0.12375 1.5675-0.2475 2.375-0.375 2.7656-0.41618 2.7656-0.41618 4.625-2.625z" fill="#1E1C1E"/>\n <path transform="translate(456,571)" d="m0 0 2 3-6 4 5 7c-3.7952-1.491-5.6104-3.757-8-7l7-7z" fill="#858E85"/>\n <path transform="translate(282,551)" d="m0 0c1.98 0.66 3.96 1.32 6 2l0.25 2.25c0.88969 3.2622 2.235 4.5595 4.75 6.75l-1 2c-1.6728-1.7863-3.3382-3.5785-5-5.375-0.71543-0.76184-0.71543-0.76184-1.4453-1.5391-3.5547-3.8594-3.5547-3.8594-3.5547-6.0859z" fill="#191B1D"/>\n <path transform="translate(317,466)" d="m0 0c3.3865 3.8702 6.3295 8.1013 8 13l-1 3-5-10h-4l2-6z" fill="#929B92"/>\n <path transform="translate(818,176)" d="m0 0c2 3 2 3 1.875 5-1.114 2.5463-2.5705 3.5132-4.875 5v-3l-2-1 2-4 1 2-1 2h2l1-6z" fill="#B8B9AD"/>\n <path transform="translate(322,838)" d="m0 0h1c-0.0603 1.9175-0.14917 3.8342-0.25 5.75l-0.14062 3.2344c-0.71527 3.5397-1.8652 4.7544-4.6094 7.0156 1.1506-5.398 2.4242-10.71 4-16z" fill="#F4C182"/>\n <path transform="translate(843,162)" d="m0 0-7 4-1-1c-1.9214 0.32744-1.9214 0.32744-4.0625 0.9375-0.73348 0.19465-1.467 0.3893-2.2227 0.58984-0.5659 0.15598-1.1318 0.31195-1.7148 0.47266l-1-2c2.2681-0.69809 4.5387-1.3837 6.8125-2.0625 0.6426-0.19916 1.2852-0.39832 1.9473-0.60352 4.9004-1.4473 4.9004-1.4473 8.2402-0.33398z" fill="#DBDDD0"/>\n <path transform="translate(545,475)" d="m0 0h1l-0.0625 2.8125c-0.095196 3.2104-0.095196 3.2104 1.0625 6.1875l-4 3c0-10 0-10 2-12z" fill="#8E948B"/>\n <path transform="translate(191,773)" d="m0 0h1l1 8h1v6l-1-3h-2l-0.375-1.9375-0.625-2.0625-2-1 3-6z" fill="#E4B44E"/>\n <path transform="translate(380,468)" d="m0 0c0 3.5891-0.66437 4.1086-3 6.6875-0.55688 0.62262-1.1138 1.2452-1.6875 1.8867-0.43312 0.47051-0.86625 0.94102-1.3125 1.4258l-1-4 7-6z" fill="#D89A6A"/>\n <path transform="translate(746,366)" d="m0 0c4.8363 0.99044 9.4762 1.957 14 4-3.1335 1.0445-3.9897 0.93424-7 0l-1 2c-2.0383-1.274-4.0385-2.6106-6-4v-2z" fill="#2A2F2B"/>\n <path transform="translate(610,261)" d="m0 0 1 2c-0.92735 1.4856-1.8672 2.9633-2.8125 4.4375-0.78311 1.2356-0.78311 1.2356-1.582 2.4961-1.6055 2.0664-1.6055 2.0664-4.6055 3.0664 1.4098-3.0385 3.0887-5.594 5.125-8.25 0.80824-1.0596 0.80824-1.0596 1.6328-2.1406 0.40992-0.53109 0.81984-1.0622 1.2422-1.6094z" fill="#9E9F96"/>\n <path transform="translate(822,238)" d="m0 0c1.5639 3.9738 0.36145 6.8138-0.9375 10.75-0.38027 1.1705-0.76055 2.3409-1.1523 3.5469-0.30035 0.89203-0.6007 1.7841-0.91016 2.7031h-1c-0.46904-6.0975 1.2914-11.583 4-17z" fill="#909892"/>\n <path transform="translate(708,200)" d="m0 0c-1 2-1 2-4.3125 3.1875-3.2631 0.71899-4.6803 1.0154-7.6875-0.1875h2v-2c6.2857-2.4286 6.2857-2.4286 10-1z" fill="#272B26"/>\n <path transform="translate(279,856)" d="m0 0 2 1c-4.75 3-4.75 3-7 3v2c-3.287 0.79953-4.7102 1.0966-8 0 2.1204-1.0303 4.2465-2.049 6.375-3.0625 1.1834-0.56848 2.3667-1.137 3.5859-1.7227 1.0029-0.4009 2.0058-0.8018 3.0391-1.2148z" fill="#161929"/>\n <path transform="translate(198,719)" d="m0 0-4 1v3l-5 2-2-3c1.2642-0.69965 2.5367-1.3843 3.8125-2.0625 0.7077-0.38285 1.4154-0.7657 2.1445-1.1602 2.043-0.77734 2.043-0.77734 5.043 0.22266z" fill="#BF885E"/>\n <path transform="translate(477,341)" d="m0 0 1 2c-2.6496 3.6309-5.0182 5.8985-9 8l-1-2c2.8528-2.932 5.6508-5.6432 9-8z" fill="#C48B60"/>\n <path transform="translate(810,225)" d="m0 0 5 2-3 2h2v2h-2v2h-2c-0.79953-3.287-1.0966-4.7102 0-8z" fill="#7B827F"/>\n <path transform="translate(469,559)" d="m0 0 2 3-5 5c-0.99-0.33-1.98-0.66-3-1 1.98-2.31 3.96-4.62 6-7z" fill="#777E76"/>\n <path transform="translate(536,546)" d="m0 0c4.6769 1.4769 4.6769 1.4769 6.3125 4.125 0.22688 0.61875 0.45375 1.2375 0.6875 1.875h-4c-3-4.1786-3-4.1786-3-6z" fill="#6D7570"/>\n <path transform="translate(707,312)" d="m0 0c1 2 1 2 0.375 4.8125-1.5563 3.6078-3.4684 5.5868-6.375 8.1875l-2-1c0.76312-0.86625 1.5262-1.7325 2.3125-2.625 2.4397-2.911 4.1175-5.9044 5.6875-9.375z" fill="#6B726E"/>\n <path transform="translate(355,453)" d="m0 0c6.7046 3.9562 6.7046 3.9562 7.9375 8.3125l0.0625 2.6875c-5.8021-5.6452-5.8021-5.6452-8-9v-2z" fill="#DCA06D"/>\n <path transform="translate(625,277)" d="m0 0c2.7296 2.3574 3.8889 4.5813 5 8v3h-2c-2.1531-3.8576-3.3925-6.5513-3-11z" fill="#C1C0B1"/>\n <path transform="translate(798,225)" d="m0 0 3 2v2l-4 2-2-5c0.99-0.33 1.98-0.66 3-1zm-5 3 3 2h-3v-2z" fill="#7C8480"/>\n <path transform="translate(151,760)" d="m0 0h1c0.125 5.75 0.125 5.75-1 8h-2l-1 6c-1.371-3.6904-0.60011-5.7088 0.9375-9.25 0.38027-0.89203 0.76055-1.7841 1.1523-2.7031 0.30035-0.67547 0.6007-1.3509 0.91016-2.0469z" fill="#AD7B56"/>\n <path transform="translate(520,513)" d="m0 0 1 2-2-1 1-1zm-5 5v3c-2.5 2.1875-2.5 2.1875-5 4l-2-1 7-6z" fill="#676E6A"/>\n <path transform="translate(544,486)" d="m0 0c0 3.7791-0.99704 4.4611-3.5 7.1875-0.64969 0.71543-1.2994 1.4309-1.9688 2.168-0.50531 0.5427-1.0106 1.0854-1.5312 1.6445l-2-1c1.1241-1.2924 2.2493-2.5839 3.375-3.875 0.62648-0.7193 1.253-1.4386 1.8984-2.1797 1.2008-1.353 2.4474-2.6661 3.7266-3.9453z" fill="#646B67"/>\n <path transform="translate(773,326)" d="m0 0c2.9719 1.1245 5.3344 2.2229 8 4l-1 3-1.75-1.4375c-2.1758-1.511-3.676-2.1029-6.25-2.5625l1-3z" fill="#7B827E"/>\n <path transform="translate(511,296)" d="m0 0 1 2c-2.3896 3.243-4.2048 5.509-8 7 1.555-3.8168 4.036-6.192 7-9z" fill="#C68D61"/>\n <path transform="translate(582,222)" d="m0 0c0 3.0522-0.32293 4.0453-1.75 6.625-0.32484 0.61102-0.64969 1.222-0.98438 1.8516-1.6012 1.9273-2.8354 2.1456-5.2656 2.5234 0.95545-1.4602 1.9145-2.9181 2.875-4.375 0.53367-0.81211 1.0673-1.6242 1.6172-2.4609 1.5078-2.1641 1.5078-2.1641 3.5078-4.1641z" fill="#1B1C1F"/>\n <path transform="translate(325,864)" d="m0 0 1 2-6 9-1-2 1-3h2l0.375-2.4375 0.625-2.5625 2-1z" fill="#B67E57"/>\n <path transform="translate(168,863)" d="m0 0 1.8125 1.5c2.1578 1.7828 2.1578 1.7828 5.1875 1.5l1 3-2 2c-1.006-0.95207-2.0046-1.9119-3-2.875-0.55688-0.53367-1.1138-1.0673-1.6875-1.6172-1.3125-1.5078-1.3125-1.5078-1.3125-3.5078z" fill="#BD8259"/>\n <path transform="translate(328,855)" d="m0 0h1c0.25 2.75 0.25 2.75 0 6-2 2.375-2 2.375-4 4l-1-2c0.77734-1.9453 0.77734-1.9453 1.9375-4.125 0.57041-1.0867 0.57041-1.0867 1.1523-2.1953 0.30035-0.5543 0.6007-1.1086 0.91016-1.6797z" fill="#D79969"/>\n <path transform="translate(415,421)" d="m0 0 1 4-6 5c0-4.3897 2.1281-5.7691 5-9z" fill="#B5815A"/>\n <path transform="translate(633,390)" d="m0 0c0 3 0 3-1.5312 4.8242-0.64969 0.61488-1.2994 1.2298-1.9688 1.8633-0.64969 0.62262-1.2994 1.2452-1.9688 1.8867-0.50531 0.47051-1.0106 0.94102-1.5312 1.4258 0-3 0-3 2-6v-2l1.9375-0.4375c2.038-0.37257 2.038-0.37257 3.0625-1.5625z" fill="#9FA49B"/>\n <path transform="translate(500,309)" d="m0 0 1 4-6 5c0-4.3897 2.1281-5.7691 5-9z" fill="#B9835B"/>\n <path transform="translate(808,211)" d="m0 0 1 2h2l1-2c0.99 1.65 1.98 3.3 3 5-1.3333 0.66667-2.6667 1.3333-4 2l-4-6 1-1z" fill="#7D8480"/>\n <path transform="translate(518,686)" d="m0 0c2.5 2.3125 2.5 2.3125 5 5v3l-7-6 2-2z" fill="#252A23"/>\n <path transform="translate(488,567)" d="m0 0c2.125 0.375 2.125 0.375 4 1v3h-2l-2 2-2-4 2-2z" fill="#6A716C"/>\n <path transform="translate(507,550)" d="m0 0h2v3h3l1 3-4 1c-2-5.875-2-5.875-2-7z" fill="#6A726C"/>\n <path transform="translate(453,371)" d="m0 0 1 4-7 5c1.5271-3.436 3.5993-6.1191 6-9z" fill="#B38058"/>\n <path transform="translate(466,354)" d="m0 0 1 4-5 4c0-3.9084 1.5057-5.1159 4-8z" fill="#B8835B"/>\n <path transform="translate(696,312)" d="m0 0 2 4-6 4c1.75-5.75 1.75-5.75 4-8z" fill="#A3A79E"/>\n <path transform="translate(811,219)" d="m0 0 2.875 1.0625c2.9956 1.2878 2.9956 1.2878 5.125-0.0625l-2 4-2-1-1 2-1-4h-2v-2z" fill="#7C8480"/>\n <path transform="translate(220,854)" d="M0 0 C1.46067199 0.45082469 2.91848032 0.91093537 4.375 1.375 C5.18710938 1.63023437 5.99921875 1.88546875 6.8359375 2.1484375 C9 3 9 3 11 5 C4.61764706 5.49095023 4.61764706 5.49095023 1.5625 3.0625 C0 1 0 1 0 0 Z " fill="#CF9940"/>\n <path transform="translate(515,679)" d="m0 0 5 1 1 4-3 2c-0.99-2.31-1.98-4.62-3-7z" fill="#5B645B"/>\n <path transform="translate(463,430)" d="m0 0c0 3.2818-0.47836 5.1089-2 8-2.125 0.8125-2.125 0.8125-4 1 1.5271-3.436 3.5993-6.1191 6-9z" fill="#EFEFE7"/>\n <path transform="translate(506,303)" d="m0 0c0 3 0 3-2.5 5.6875l-2.5 2.3125c0.3505-3.2421 0.56221-4.6153 3.0625-6.8125 0.63938-0.39188 1.2788-0.78375 1.9375-1.1875z" fill="#D89B69"/>\n <path transform="translate(475,753)" d="m0 0c2.3125 0.1875 2.3125 0.1875 5 1 1.8125 2.5625 1.8125 2.5625 3 5-3.3659-1.4425-5.5105-3.3326-8-6z" fill="#B9835A"/>\n <path transform="translate(162,743)" d="m0 0 1 2c-1.25 2.5625-1.25 2.5625-3 5-0.99 0.33-1.98 0.66-3 1 1.1858-3.375 2.2757-5.6472 5-8z" fill="#B47F58"/>\n <path transform="translate(181,727)" d="m0 0 1 2c-1.75 1.5625-1.75 1.5625-4 3-2.25-0.3125-2.25-0.3125-4-1 2.1742-2.5004 3.7305-3.4363 7-4z" fill="#C99064"/>\n <path transform="translate(242,692)" d="m0 0 1 3c-2.3125 2.5-2.3125 2.5-5 5h-3c2.31-2.64 4.62-5.28 7-8z" fill="#AE7B55"/>\n <path transform="translate(370,499)" d="m0 0c0 3 0 3-1.5 4.6875l-1.5 1.3125c-1.5-1.375-1.5-1.375-3-3v-2l1.875 0.625 2.125 0.375 2-2z" fill="#E6BE85"/>\n <path transform="translate(272,467)" d="m0 0 1 2c-0.93579 2.3598-1.9335 4.6963-3 7h-2c1.0588-3.4031 2.009-6.0135 4-9z" fill="#B5805A"/>\n <path transform="translate(277,458)" d="m0 0c1 2 1 2 0.25 5.0625l-1.25 2.9375c-0.99 0.33-1.98 0.66-3 1 1.0588-3.4031 2.009-6.0135 4-9z" fill="#AF7C57"/>\n <path transform="translate(437,392)" d="m0 0 1 4-6 4c1.3715-2.9541 2.9886-5.4401 5-8z" fill="#B18159"/>\n <path transform="translate(553,310)" d="m0 0 1 4-4 3-2-1 5-6z" fill="#E8E7DD"/>\n <path transform="translate(526,274)" d="m0 0 1 4-6 4c1.3715-2.9541 2.9886-5.4401 5-8z" fill="#B37F57"/>\n <path transform="translate(565,222)" d="m0 0c1.125 3.75 1.125 3.75 0 6-1.6436 0.72159-3.3105 1.3935-5 2 1.3715-2.9541 2.9886-5.4401 5-8z" fill="#B98158"/>\n <path transform="translate(407,717)" d="m0 0c0 3 0 3-1.3125 4.3867-1.5625 1.2044-3.125 2.4089-4.6875 3.6133l-1-3 2.375-1.375c2.662-1.5093 2.662-1.5093 4.625-3.625z" fill="#11161B"/>\n <path transform="translate(477,362)" d="m0 0 1 2c-0.93306 2.7144-1.6267 3.7804-4.125 5.25l-1.875 0.75c1.1858-3.375 2.2757-5.6472 5-8z" fill="#191C1F"/>\n <path transform="translate(462,361)" d="m0 0 1 2-5 5c0.3125-2.375 0.3125-2.375 1-5l3-2z" fill="#D59868"/>\n <path transform="translate(531,290)" d="m0 0 2 1c-1.0487 2.6219-1.6493 3.7937-4.125 5.25l-1.875 0.75c1.074-2.9152 1.7781-4.7781 4-7z" fill="#202223"/>\n <path transform="translate(793,209)" d="m0 0c0.99 0.33 1.98 0.66 3 1l-6 5-2-1 5-5z" fill="#6A706E"/>\n <path transform="translate(465,748)" d="m0 0c0.99 0.33 1.98 0.66 3 1v2c-0.99-0.33-1.98-0.66-3-1v-2z" fill="#C78A5F"/>\n <path transform="translate(249,531)" d="m0 0 2 4-2-1v-3z" fill="#B8835C"/>\n <path transform="translate(370,472)" d="m0 0 3 2h-3v-2z" fill="#D7956A"/>\n <path transform="translate(162,859)" d="m0 0 2 1-1 2-1-3z" fill="#BC835A"/>\n <path transform="translate(146,829)" d="m0 0h2l-1 3-1-3z" fill="#BA815A"/>\n <path transform="translate(836,340)" d="m0 0 1 4z" fill="#C98C62"/>\n <path transform="translate(472,341)" d="m0 0 2 1-2 2v-3z" fill="#C2895F"/>\n <path transform="translate(277,903)" d="m0 0c3 1 3 1 3 1z" fill="#BF845A"/>\n <path transform="translate(228,903)" d="m0 0c3 1 3 1 3 1z" fill="#BE855B"/>\n <path transform="translate(555,648)" d="m0 0c3 1 3 1 3 1z" fill="#D29063"/>\n <path transform="translate(306,602)" d="m0 0 2 2h-2v-2z" fill="#CE8F63"/>\n <path transform="translate(884,182)" d="m0 0 2 2h-2v-2z" fill="#C48961"/>\n <path transform="translate(632,176)" d="m0 0c3 1 3 1 3 1z" fill="#CF8F62"/>\n <path transform="translate(672,163)" d="m0 0c3 1 3 1 3 1z" fill="#C78B60"/>\n <path transform="translate(834,114)" d="m0 0c3 1 3 1 3 1z" fill="#CA8B5F"/>\n <path transform="translate(224,902)" d="m0 0 2 1z" fill="#BC835B"/>\n <path transform="translate(491,766)" d="m0 0 2 1z" fill="#C2855B"/>\n <path transform="translate(432,725)" d="m0 0 2 1z" fill="#D09164"/>\n <path transform="translate(193,717)" d="m0 0 2 1z" fill="#C68B60"/>\n <path transform="translate(595,700)" d="m0 0 2 1z" fill="#BA805A"/>\n <path transform="translate(268,658)" d="m0 0 2 1z" fill="#C88B60"/>\n <path transform="translate(564,651)" d="m0 0 2 1z" fill="#D49266"/>\n <path transform="translate(304,601)" d="m0 0 2 1z" fill="#CC8D62"/>\n <path transform="translate(600,591)" d="m0 0 2 1z" fill="#CE8E61"/>\n <path transform="translate(604,588)" d="m0 0 2 1z" fill="#CD8D61"/>\n <path transform="translate(273,565)" d="m0 0 2 1z" fill="#CA8C63"/>\n <path transform="translate(779,438)" d="m0 0 2 1z" fill="#C58A60"/>\n <path transform="translate(496,304)" d="m0 0 2 1z" fill="#BE875E"/>\n <path transform="translate(867,239)" d="m0 0 2 1z" fill="#C88C64"/>\n <path transform="translate(626,178)" d="m0 0 2 1z" fill="#C88A5E"/>\n <path transform="translate(657,168)" d="m0 0 2 1z" fill="#CD8F65"/>\n <path transform="translate(709,152)" d="m0 0 2 1z" fill="#CB8A5E"/>\n <path transform="translate(776,131)" d="m0 0 2 1z" fill="#C7895F"/>\n </svg>\n\n <h1 class="page-title">Glotus Client</h1>\n <p id="script-description" class="page-description"></p>\n </div>\n\n <svg\n id="close-button"\n class="icon"\n xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 30 30"\n >\n <path d="M 7 4 C 6.744125 4 6.4879687 4.0974687 6.2929688 4.2929688 L 4.2929688 6.2929688 C 3.9019687 6.6839688 3.9019687 7.3170313 4.2929688 7.7070312 L 11.585938 15 L 4.2929688 22.292969 C 3.9019687 22.683969 3.9019687 23.317031 4.2929688 23.707031 L 6.2929688 25.707031 C 6.6839688 26.098031 7.3170313 26.098031 7.7070312 25.707031 L 15 18.414062 L 22.292969 25.707031 C 22.682969 26.098031 23.317031 26.098031 23.707031 25.707031 L 25.707031 23.707031 C 26.098031 23.316031 26.098031 22.682969 25.707031 22.292969 L 18.414062 15 L 25.707031 7.7070312 C 26.098031 7.3170312 26.098031 6.6829688 25.707031 6.2929688 L 23.707031 4.2929688 C 23.316031 3.9019687 22.682969 3.9019687 22.292969 4.2929688 L 15 11.585938 L 7.7070312 4.2929688 C 7.5115312 4.0974687 7.255875 4 7 4 z"/>\n </svg>\n</header>';
const Navbar_default = '<div id="navbar-container">\n <button data-id="0" class="open-menu active">\n <span>\n <svg class="small-icon" xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512">\n <path fill="currentColor"\n d="M240 6.1c9.1-8.2 22.9-8.2 32 0l232 208c9.9 8.8 10.7 24 1.8 33.9s-24 10.7-33.9 1.8l-8-7.2v205.3c0 35.3-28.7 64-64 64h-288c-35.3 0-64-28.7-64-64V242.6l-8 7.2c-9.9 8.8-25 8-33.9-1.8s-8-25 1.8-33.9zm16 50.1L96 199.7V448c0 8.8 7.2 16 16 16h48V360c0-39.8 32.2-72 72-72h48c39.8 0 72 32.2 72 72v104h48c8.8 0 16-7.2 16-16V199.7L256 56.3zM208 464h96V360c0-13.3-10.7-24-24-24h-48c-13.3 0-24 10.7-24 24z" />\n </svg>\n Home\n </span>\n </button>\n <button data-id="1" class="open-menu">\n <span>\n <svg class="small-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">\n <path fill="currentColor"\n d="M6.21 13.29a.9.9 0 0 0-.33-.21a1 1 0 0 0-.76 0a.9.9 0 0 0-.54.54a1 1 0 1 0 1.84 0a1 1 0 0 0-.21-.33M13.5 11h1a1 1 0 0 0 0-2h-1a1 1 0 0 0 0 2m-4 0h1a1 1 0 0 0 0-2h-1a1 1 0 0 0 0 2m-3-2h-1a1 1 0 0 0 0 2h1a1 1 0 0 0 0-2M20 5H4a3 3 0 0 0-3 3v8a3 3 0 0 0 3 3h16a3 3 0 0 0 3-3V8a3 3 0 0 0-3-3m1 11a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1Zm-6-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2m3.5-4h-1a1 1 0 0 0 0 2h1a1 1 0 0 0 0-2m.71 4.29a1 1 0 0 0-.33-.21a1 1 0 0 0-.76 0a.9.9 0 0 0-.33.21a1 1 0 0 0-.21.33a1 1 0 1 0 1.92.38a.84.84 0 0 0-.08-.38a1 1 0 0 0-.21-.33" />\n </svg>\n Keybinds\n </span>\n </button>\n <button data-id="2" class="open-menu">\n <span>\n <svg class="small-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">\n <path fill="currentColor"\n d="m19.05 21.6l-2.925-2.9l-2.2 2.2l-.7-.7q-.575-.575-.575-1.425t.575-1.425l4.225-4.225q.575-.575 1.425-.575t1.425.575l.7.7l-2.2 2.2l2.9 2.925q.3.3.3.7t-.3.7l-1.25 1.25q-.3.3-.7.3t-.7-.3M22 5.9L10.65 17.25l.125.1q.575.575.575 1.425t-.575 1.425l-.7.7l-2.2-2.2l-2.925 2.9q-.3.3-.7.3t-.7-.3L2.3 20.35q-.3-.3-.3-.7t.3-.7l2.9-2.925l-2.2-2.2l.7-.7q.575-.575 1.425-.575t1.425.575l.1.125L18 1.9h4zM6.95 10.85L2 5.9v-4h4l4.95 4.95z" />\n </svg>\n Combat\n </span>\n </button>\n <button data-id="3" class="open-menu">\n <span>\n <svg class="small-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">\n <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">\n <path\n d="M12 5c-6.307 0-9.367 5.683-9.91 6.808a.44.44 0 0 0 0 .384C2.632 13.317 5.692 19 12 19s9.367-5.683 9.91-6.808a.44.44 0 0 0 0-.384C21.368 10.683 18.308 5 12 5" />\n <circle cx="12" cy="12" r="3" />\n </g>\n </svg>\n Visuals\n </span>\n </button>\n <button data-id="4" class="open-menu">\n <span>\n <svg class="small-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">\n <path fill="currentColor"\n d="M2 18h7v2H2zm0-7h9v2H2zm0-7h20v2H2zm18.674 9.025l1.156-.391l1 1.732l-.916.805a4 4 0 0 1 0 1.658l.916.805l-1 1.732l-1.156-.391a4 4 0 0 1-1.435.83L19 21h-2l-.24-1.196a4 4 0 0 1-1.434-.83l-1.156.392l-1-1.732l.916-.805a4 4 0 0 1 0-1.658l-.916-.805l1-1.732l1.156.391c.41-.37.898-.655 1.435-.83L17 11h2l.24 1.196a4 4 0 0 1 1.434.83M18 17a1 1 0 1 0 0-2a1 1 0 0 0 0 2" />\n </svg>\n Misc\n </span>\n </button>\n <button data-id="5" class="open-menu">\n <span>\n <svg class="small-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">\n <path fill="currentColor"\n d="M22 14h-1c0-3.87-3.13-7-7-7h-1V5.73A2 2 0 1 0 10 4c0 .74.4 1.39 1 1.73V7h-1c-3.87 0-7 3.13-7 7H2c-.55 0-1 .45-1 1v3c0 .55.45 1 1 1h1v1a2 2 0 0 0 2 2h14c1.11 0 2-.89 2-2v-1h1c.55 0 1-.45 1-1v-3c0-.55-.45-1-1-1m-1 3h-2v3H5v-3H3v-1h2v-2c0-2.76 2.24-5 5-5h4c2.76 0 5 2.24 5 5v2h2zm-3.5-1.5c0 1.11-.89 2-2 2c-.97 0-1.77-.69-1.96-1.6l2.96-2.12c.6.35 1 .98 1 1.72m-10-1.72l2.96 2.12c-.18.91-.99 1.6-1.96 1.6a2 2 0 0 1-2-2c0-.74.4-1.37 1-1.72" />\n </svg>\n Bots\n </span>\n </button>\n <button data-id="6" class="open-menu bottom-align">\n <span>\n <svg class="small-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">\n <path fill="currentColor"\n d="m19.546 7.573l-1.531-1.57l-1.442 1.291l-.959.86l3.876 3.987l-2.426 2.496l-1.451 1.492c.55.499 1.091.99 1.64 1.486l.764.694l2.21-2.277L24 12.14v-.001zM2.992 9.072L0 12.14c2.01 2.073 3.993 4.115 5.984 6.167l.51-.464l1.893-1.715L6.94 14.64l-2.43-2.5l3.109-3.196l.767-.789c-.434-.39-.86-.772-1.288-1.154L5.984 6v.001zm12.585-6.038L11.632 21.6l-.196-.039l-3.029-.595l2.555-12.02L12.353 2.4z" />\n </svg>\n Devtool\n </span>\n </button>\n <div\n style="margin-top: auto; padding: 15px 10px; text-align: center; border-top: 1px solid rgba(255,255,255,0.05); background: rgba(0,0,0,0.1);">\n <span\n style="color: #f5d951; font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: 1px; display: block; opacity: 0.6; margin-bottom: 2px;">Glotus\n Client!</span>\n <span\n style="color: #fff; font-size: 15px; font-weight: 900; display: block; text-shadow: 0 0 8px rgba(245, 217, 81, 0.6);"></span>\n </div>\n</div>';
const Home_default = '<div class="menu-page opened" data-id="0">\n <div class="page-title">Home</div>\n\n <div class="section">\n <div class="section-title">Welcome to the Glotus Client! <span class="highlight"\n style="font-size: 14px;">[Glotus Client!]</span></div>\n <div class="section-content">\n\n <div class="content-option text">\n <span class="text-value simplified">My main goal in creating this hack was to automate absolutely\n everything. So don\'t be surprised by the lack of numerous hotkeys - not even for switching weapons.\n This client is designed for simple <span class="highlight">WASD</span> movement and primarly <span\n class="highlight">polearm + hammer</span>, which is what makes it great. There\'s no need to\n remember dozens of hotkeys, chat commands, or anything else.</span>\n </div>\n\n <div class="content-option text">\n <span class="text-value simplified">It is still in development, so please, report about all issues. Let\n the client keep growing!</span>\n </div>\n </div>\n </div>\n\n <div class="section">\n\n <div class="section-content">\n\n <div class="content-option left-flex text">\n <span class="option-title">Author: </span>\n <span id="author" class="text-value">Murka (<span class="highlight">Glotus Client!</span>)</span>\n </div>\n\n <div class="content-option left-flex text">\n <a href="https://discord.gg/cPRFdcZkeD" class="text-value" target="_blank">\n <svg class="icon link" xmlns="http://www.w3.org/2000/svg" width="24" height="24"\n viewBox="0 0 24 24">\n <path fill="currentColor"\n d="M19.303 5.337A17.3 17.3 0 0 0 14.963 4c-.191.329-.403.775-.552 1.125a16.6 16.6 0 0 0-4.808 0C9.454 4.775 9.23 4.329 9.05 4a17 17 0 0 0-4.342 1.337C1.961 9.391 1.218 13.35 1.59 17.255a17.7 17.7 0 0 0 5.318 2.664a13 13 0 0 0 1.136-1.836c-.627-.234-1.22-.52-1.794-.86c.149-.106.297-.223.435-.34c3.46 1.582 7.207 1.582 10.624 0c.149.117.287.234.435.34c-.573.34-1.167.626-1.793.86a13 13 0 0 0 1.135 1.836a17.6 17.6 0 0 0 5.318-2.664c.457-4.52-.722-8.448-3.1-11.918M8.52 14.846c-1.04 0-1.889-.945-1.889-2.101s.828-2.102 1.89-2.102c1.05 0 1.91.945 1.888 2.102c0 1.156-.838 2.1-1.889 2.1m6.974 0c-1.04 0-1.89-.945-1.89-2.101s.828-2.102 1.89-2.102c1.05 0 1.91.945 1.889 2.102c0 1.156-.828 2.1-1.89 2.1" />\n </svg>\n </a>\n\n <a href="https://github.com/Murka007/Glotus-Client" class="text-value" target="_blank">\n <svg class="icon link" xmlns="http://www.w3.org/2000/svg" width="24" height="24"\n viewBox="0 0 24 24">\n <path fill="currentColor"\n d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2" />\n </svg>\n </a>\n\n <a href="https://greasyfork.org/en/users/919633-murka007" class="text-value" target="_blank">\n <svg class="icon link" version="1.1" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg">\n <circle cx="48" cy="48" r="48" />\n <clipPath id="a">\n <circle cx="48" cy="48" r="47" />\n </clipPath>\n <text clip-path="url(#a)" fill="#fff"\n font-family="\'DejaVu Sans\', Verdana, Arial, \'Liberation Sans\', sans-serif" font-size="18"\n letter-spacing="-.75" pointer-events="none" text-anchor="middle"\n style="-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none">\n <tspan x="51" y="13" textLength="57">= null;</tspan>\n <tspan x="56" y="35" textLength="98">function init</tspan>\n <tspan x="49" y="57" textLength="113">for (const i = 0;</tspan>\n <tspan x="50" y="79" textLength="105">XmlHttpReq</tspan>\n <tspan x="48" y="101" textLength="80">appendCh</tspan>\n </text>\n <path\n d="m44 29a6.364 6.364 0 0 1 0 9l36 36a3.25 3.25 0 0 1-6.5 6.5l-36-36a6.364 6.364 0 0 1-9 0l-19-19a1.7678 1.7678 0 0 1 0-2.5l13-13a1.7678 1.7678 0 0 1 2.5 0z"\n stroke="#000" stroke-width="4" />\n <path\n d="m44 29a6.364 6.364 0 0 1 0 9l36 36a3.25 3.25 0 0 1-6.5 6.5l-36-36a6.364 6.364 0 0 1-9 0l-19-19a1.7678 1.7678 0 0 1 2.5-2.5l14 14 4-4-14-14a1.7678 1.7678 0 0 1 2.5-2.5l14 14 4-4-14-14a1.7678 1.7678 0 0 1 2.5-2.5z"\n fill="#fff" />\n </svg>\n </a>\n\n </div>\n\n <div class="content-option left-flex text">\n <span class="option-title">Building hash: </span>\n <span id="author" class="text-value">{HASH}</span>\n </div>\n\n </div>\n </div>\n\n</div>';
const Keybinds_default = '<div class="menu-page" data-id="1">\n <div class="page-title">Keybinds</div>\n <p class="page-description">Setup keybinds for items, weapons and hats</p>\n\n \x3c!-- Items & Weapons --\x3e\n <div class="section">\n <div class="section-title">Items & Weapons</div>\n <div class="section-content split">\n\n <div class="content-split">\n <div class="content-option">\n <span class="option-title">Food</span>\n <button id="_food" class="hotkeyInput"></button>\n </div>\n\n <div class="content-option">\n <span class="option-title">Wall</span>\n <button id="_wall" class="hotkeyInput"></button>\n </div>\n\n <div class="content-option">\n <span class="option-title">Spike</span>\n <button id="_spike" class="hotkeyInput"></button>\n </div>\n\n <div class="content-option">\n <span class="option-title">Windmill</span>\n <button id="_windmill" class="hotkeyInput"></button>\n </div>\n </div>\n\n <div class="content-split">\n <div class="content-option">\n <span class="option-title">Farm</span>\n <button id="_farm" class="hotkeyInput"></button>\n </div>\n\n <div class="content-option">\n <span class="option-title">Trap</span>\n <button id="_trap" class="hotkeyInput"></button>\n </div>\n\n <div class="content-option">\n <span class="option-title">Turret</span>\n <button id="_turret" class="hotkeyInput"></button>\n </div>\n\n <div class="content-option">\n <span class="option-title">Spawn</span>\n <button id="_spawn" class="hotkeyInput"></button>\n </div>\n </div>\n </div>\n </div>\n\n \x3c!-- Controls & Movement --\x3e\n <div class="section">\n <div class="section-title">Controls & Movement</div>\n <div class="section-content">\n\n <div class="content-split">\n\n <div class="content-option">\n <span class="option-title">Lock bot position</span>\n <button id="_lockBotPosition" class="hotkeyInput"></button>\n </div>\n\n <div class="content-option">\n <span class="option-title">Toggle Shop</span>\n <button id="_toggleShop" class="hotkeyInput"></button>\n </div>\n\n <div class="content-option">\n <span class="option-title">Toggle Clan</span>\n <button id="_toggleClan" class="hotkeyInput"></button>\n </div>\n\n <div class="content-option">\n <span class="option-title">Toggle Menu</span>\n <button id="_toggleMenu" class="hotkeyInput"></button>\n </div>\n\n <div class="content-option">\n <span class="option-title">Instakill</span>\n <button id="_instakill" class="hotkeyInput"></button>\n </div>\n\n </div>\n </div>\n </div>\n</div>';
const Combat_default = '<div class="menu-page" data-id="2">\n <div class="page-title">Combat</div>\n <p class="page-description">Modify combat settings, change pvp behavior</p>\n\n \x3c!-- Defense --\x3e\n <div class="section">\n <div class="section-title">Defense</div>\n <div class="section-content">\n\n \x3c!-- <div class="content-option">\n <span class="option-title">Biome hats</span>\n <label class="switch-checkbox">\n <input id="_biomehats" type="checkbox"></input>\n <span></span>\n </label>\n </div> --\x3e\n\n \x3c!-- <div class="content-option">\n <span class="option-title">Auto emp</span>\n <label class="switch-checkbox">\n <input id="_autoemp" type="checkbox"></input>\n <span></span>\n </label>\n </div> --\x3e\n\n <div class="content-option">\n <span class="option-title">Anti enemy</span>\n <label class="switch-checkbox">\n <input id="_antienemy" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Basic soldier equipment for all types of antis</span>\n </div>\n\n \x3c!-- <div class="content-option">\n <span class="option-title">Soldier default</span>\n <label class="switch-checkbox">\n <input id="_soldierDefault" type="checkbox"></input>\n <span></span>\n </label>\n\n <span class="option-description">Equips soldier by default, when antis fail to do its work</span>\n </div> --\x3e\n\n \x3c!-- <div class="content-option">\n <span class="option-title">Anti animal</span>\n <label class="switch-checkbox">\n <input id="_antianimal" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Equips a soldier when danger animal is nearby</span>\n </div> --\x3e\n\n <div class="content-option">\n <span class="option-title">Anti spike</span>\n <label class="switch-checkbox">\n <input id="_antispike" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Adds additional layer of protection against spikes</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Emp Defense</span>\n <label class="switch-checkbox">\n <input id="_empDefense" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Equips emp by default when you are not moving</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Autoheal</span>\n <label class="switch-checkbox">\n <input id="_autoheal" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n \n <div class="content-option">\n <span class="option-title">Autobreak</span>\n <label class="switch-checkbox">\n <input id="_autobreak" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Destroys nearby enemy traps and spikes</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Safe walk</span>\n <label class="switch-checkbox">\n <input id="_safeWalk" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Prevents from colliding enemy spikes, cactuses, boostpads</span>\n </div>\n </div>\n </div>\n\n \x3c!-- Placement --\x3e\n <div class="section">\n <div class="section-title">Placement</div>\n\n <div class="section-content">\n <div class="content-option">\n <span class="option-title">Autoplacer</span>\n <label class="switch-checkbox">\n <input id="_autoplacer" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Automatically places traps and spikes when enemy is nearby</span>\n </div>\n\n \x3c!-- <div class="content-option">\n <span class="option-title">Preplacer</span>\n <label class="switch-checkbox">\n <input id="_preplacer" type="checkbox"></input>\n <span></span>\n </label>\n </div> --\x3e\n\n <div class="content-option">\n <span class="option-title">Autoplacer radius</span>\n <label class="slider">\n <span class="slider-value"></span>\n <input id="_autoplacerRadius" type="range" step="25" min="100" max="450">\n </label>\n </div>\n\n <div class="content-option">\n <span class="option-title">Placement accuracy</span>\n <label class="slider">\n <span class="slider-value"></span>\n <input id="_placeAttempts" type="range" min="1" max="10">\n </label>\n <span class="option-description">Algorithm calculates all the possible attempts. But later this value decreases in order to avoid lags.</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Automill</span>\n <label class="switch-checkbox">\n <input id="_automill" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Automatically places 3x windmills behind your back</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Auto grind</span>\n <label class="switch-checkbox">\n <input id="_autoGrind" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Stay still to get autogrind working</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Placement Defense</span>\n <label class="switch-checkbox">\n <input id="_placementDefense" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Places a wall/windmill on projectile threats</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Dash Movement</span>\n <label class="switch-checkbox">\n <input id="_dashMovement" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">When holding a boostpad hotkey, it is gonna place boost pad once and immediately destroy it, giving you additional speed.</span>\n </div>\n </div>\n </div>\n \n \x3c!-- Instakills --\x3e\n <div class="section">\n <div class="section-title">Instakills</div>\n\n <div class="section-content">\n <div class="content-option">\n <span class="option-title">Auto sync</span>\n <label class="switch-checkbox">\n <input id="_autoSync" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Attacks when it is possible to sync enemy with 2 primary weapons</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Velocity tick</span>\n <label class="switch-checkbox">\n <input id="_velocityTick" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Attacks using turret + diamond polearm in one tick</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Spike tick</span>\n <label class="switch-checkbox">\n <input id="_spikeTick" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">When enemy is about to collide a spike, attacks with primary weapon</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Spike sync</span>\n <label class="switch-checkbox">\n <input id="_spikeSync" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n <div class="content-option">\n <span class="option-title">Spike sync hammer</span>\n <label class="switch-checkbox">\n <input id="_spikeSyncHammer" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n <div class="content-option">\n <span class="option-title">Knockback tick</span>\n <label class="switch-checkbox">\n <input id="_knockbackTick" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Attacks enemy when its possible to knockback on spike</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Knockback tick hammer</span>\n <label class="switch-checkbox">\n <input id="_knockbackTickHammer" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Knockbacks enemy using hammer + turret + primary weapon on spike</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Knockback tick trap</span>\n <label class="switch-checkbox">\n <input id="_knockbackTickTrap" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Destroys a trap and knockbacks enemy on spike</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Anti Retrap</span>\n <label class="switch-checkbox">\n <input id="_antiRetrap" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">When you are trapped, attacks enemy with primary weapon to push it away</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Tool Spear Insta</span>\n <label class="switch-checkbox">\n <input id="_toolSpearInsta" type="checkbox"></input>\n <span></span>\n </label>\n\n <span class="option-description">When you have Tool Hammer and also Polearm could be upgraded, then it is going to perform instakill on nearest enemy.</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Autosteal</span>\n <label class="switch-checkbox">\n <input id="_autoSteal" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Steals kills/animals from other players</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Autopush</span>\n <label class="switch-checkbox">\n <input id="_autoPush" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n <div class="content-option">\n <span class="option-title">Turret steal</span>\n <label class="switch-checkbox">\n <input id="_turretSteal" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Equips a turret hat if possible to kill with it</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Spike Gear Insta</span>\n <label class="switch-checkbox">\n <input id="_spikeGearInsta" type="checkbox"></input>\n <span></span>\n </label>\n\n <span class="option-description">Equips Spike Gear when it is possible to deal potential damage with it to the enemy. Instakill may happen.</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Turret Sync</span>\n <label class="switch-checkbox">\n <input id="_turretSync" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Attacks using primary in sync with other turret objects</span>\n </div>\n </div>\n </div>\n\n</div>';
const Visuals_default = '<div class="menu-page" data-id="3">\n <div class="page-title">Visuals</div>\n <p class="page-description">Customize your visuals, or you can disable it for performance</p>\n\n \x3c!-- Tracers --\x3e\n <div class="section">\n <div class="section-title">Tracers</div>\n <div class="section-content">\n\n <div class="content-option">\n <span class="option-title">Enemies</span>\n <div class="option-content">\n <button class="reset-color" title="Reset Color"></button>\n <input id="_enemyTracersColor" type="color" title="Select Color">\n <label class="switch-checkbox">\n <input id="_enemyTracers" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n </div>\n\n <div class="content-option">\n <span class="option-title">Teammates</span>\n <div class="option-content">\n <button class="reset-color" title="Reset Color"></button>\n <input id="_teammateTracersColor" type="color" title="Select Color">\n <label class="switch-checkbox">\n <input id="_teammateTracers" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n </div>\n\n <div class="content-option">\n <span class="option-title">Animal</span>\n <div class="option-content">\n <button class="reset-color" title="Reset Color"></button>\n <input id="_animalTracersColor" type="color" title="Select Color">\n <label class="switch-checkbox">\n <input id="_animalTracers" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n </div>\n\n <div class="content-option">\n <span class="option-title">Notification</span>\n <div class="option-content">\n <button class="reset-color" title="Reset Color"></button>\n <input id="_notificationTracersColor" type="color" title="Select Color">\n <label class="switch-checkbox">\n <input id="_notificationTracers" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n </div>\n\n </div>\n </div>\n\n \x3c!-- Markers --\x3e\n <div class="section">\n <div class="section-title">Markers</div>\n\n <div class="section-content">\n\n <div class="content-option">\n <span class="option-title">Item Markers</span>\n <div class="option-content">\n <button class="reset-color" title="Reset Color"></button>\n <input id="_itemMarkersColor" type="color" title="Select Color">\n <label class="switch-checkbox">\n <input id="_itemMarkers" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n </div>\n\n <div class="content-option">\n <span class="option-title">Teammates</span>\n <div class="option-content">\n <button class="reset-color" title="Reset Color"></button>\n <input id="_teammateMarkersColor" type="color" title="Select Color">\n <label class="switch-checkbox">\n <input id="_teammateMarkers" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n </div>\n\n <div class="content-option">\n <span class="option-title">Enemies</span>\n <div class="option-content">\n <button class="reset-color" title="Reset Color"></button>\n <input id="_enemyMarkersColor" type="color" title="Select Color">\n <label class="switch-checkbox">\n <input id="_enemyMarkers" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n </div>\n \n </div>\n </div>\n\n \x3c!-- Player --\x3e\n <div class="section">\n <div class="section-title">Player</div>\n\n <div class="section-content">\n\n <div class="content-option">\n <span class="option-title">Weapon XP Bar</span>\n <label class="switch-checkbox">\n <input id="_weaponXPBar" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n <div class="content-option">\n <span class="option-title">Turret Reload Bar</span>\n <div class="option-content">\n <button class="reset-color" title="Reset Color"></button>\n <input id="_playerTurretReloadBarColor" type="color" title="Select Color">\n <label class="switch-checkbox">\n <input id="_playerTurretReloadBar" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n </div>\n\n <div class="content-option">\n <span class="option-title">Weapon Reload Bar</span>\n <div class="option-content">\n <button class="reset-color" title="Reset Color"></button>\n <input id="_weaponReloadBarColor" type="color" title="Select Color">\n <label class="switch-checkbox">\n <input id="_weaponReloadBar" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n </div>\n\n <div class="content-option">\n <span class="option-title">Render HP</span>\n <label class="switch-checkbox">\n <input id="_renderHP" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n \x3c!-- <div class="content-option">\n <span class="option-title">Stacked Damage</span>\n <label class="switch-checkbox">\n <input id="_stackedDamage" type="checkbox"></input>\n <span></span>\n </label>\n </div> --\x3e\n </div>\n </div>\n\n \x3c!-- Object --\x3e\n <div class="section">\n <div class="section-title">Object</div>\n\n <div class="section-content">\n\n <div class="content-option">\n <span class="option-title">Turret Reload Bar</span>\n <div class="option-content">\n <button class="reset-color" title="Reset Color"></button>\n <input id="_objectTurretReloadBarColor" type="color" title="Select Color">\n <label class="switch-checkbox">\n <input id="_objectTurretReloadBar" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n </div>\n\n <div class="content-option">\n <span class="option-title">Item Health Bar</span>\n <div class="option-content">\n <button class="reset-color" title="Reset Color"></button>\n <input id="_itemHealthBarColor" type="color" title="Select Color">\n <label class="switch-checkbox">\n <input id="_itemHealthBar" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n </div>\n\n </div>\n </div>\n\n</div>';
const Misc_default = '<div class="menu-page" data-id="4">\n <div class="page-title">Misc</div>\n <p class="page-description">Customize misc settings, add autochat messages, reset settings</p>\n\n \x3c!-- Other --\x3e\n <div class="section">\n <h2 class="section-title">Other</h2>\n\n <div class="section-content">\n\n <div class="content-option">\n <span class="option-title">Kill Message</span>\n <div class="option-content">\n <span class="seldoom-locked">seldoom is goated</span>\n </div>\n </div>\n\n <div class="content-option">\n <span class="option-title">Autospawn</span>\n <label class="switch-checkbox">\n <input id="_autospawn" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n <div class="content-option">\n <span class="option-title">Autoaccept</span>\n <label class="switch-checkbox">\n <input id="_autoaccept" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n <div class="content-option">\n <span class="option-title">Texture pack</span>\n <label class="switch-checkbox">\n <input id="_texturepack" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Some old looking texture pack. Reload the page to make it work! :)</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Hide game HUD</span>\n <label class="switch-checkbox">\n <input id="_hideHUD" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n <div class="content-option">\n <span class="option-title">Smooth rendering</span>\n <label class="slider">\n <span class="slider-value"></span>\n <input id="_smoothRendering" type="range" step="10" min="100" max="200">\n </label>\n <span class="option-description">Control how smoothly your game is being rendering. Higher speeds give you more accurate position of entities, making you analyze situation better.</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Chat Log</span>\n <label class="switch-checkbox">\n <input id="_chatLog" type="checkbox"></input>\n <span></span>\n </label>\n\n <span class="option-description">Use this only for debugging purposes. Report about any known problems</span>\n </div>\n\n <div class="content-option">\n <button id="resetSettings" class="option-button red">RESET SETTINGS</button>\n </div>\n\n </div>\n </div>\n\n\n \x3c!-- Menu --\x3e\n \x3c!-- <div class="section">\n <h2 class="section-title">Menu</h2>\n\n <div class="section-content">\n\n <div class="content-option">\n <span class="option-title">Transparency</span>\n <label class="switch-checkbox">\n <input id="_menuTransparency" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n </div>\n </div> --\x3e\n\n</div>';
const Devtool_default = '<div class="menu-page" data-id="6">\n <div class="page-title">Devtool</div>\n <p class="page-description">Test Glotus Client and report about bugs!</p>\n\n\n \x3c!-- myPlayer --\x3e\n <div class="section">\n <h2 class="section-title">myPlayer</h2>\n\n <div class="section-content">\n\n <div class="content-option">\n <span class="option-title">Display player angle</span>\n <label class="switch-checkbox">\n <input id="_displayPlayerAngle" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n </div>\n </div>\n\n\n \x3c!-- Hitboxes --\x3e\n <div class="section">\n <h2 class="section-title">Hitboxes</h2>\n\n <div class="section-content">\n\n <div class="content-option">\n <span class="option-title">Weapon hitbox</span>\n <label class="switch-checkbox">\n <input id="_weaponHitbox" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n <div class="content-option">\n <span class="option-title">Collision hitbox</span>\n <label class="switch-checkbox">\n <input id="_collisionHitbox" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n <div class="content-option">\n <span class="option-title">Placement hitbox</span>\n <label class="switch-checkbox">\n <input id="_placementHitbox" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n\n <div class="content-option">\n <span class="option-title">Possible placement</span>\n <label class="switch-checkbox">\n <input id="_possiblePlacement" type="checkbox"></input>\n <span></span>\n </label>\n </div>\n \n </div>\n </div>\n\n \x3c!-- Statistics --\x3e\n <div class="section">\n <h2 class="section-title">Statistics</h2>\n\n <div class="section-content small-section">\n\n <div class="content-option left-flex text">\n <span class="option-title">Total kills: </span>\n <span id="_totalKills" class="text-value">0</span>\n </div>\n\n <div class="content-option left-flex text">\n <span class="option-title">Global kills with bots: </span>\n <span id="_globalKills" class="text-value">0</span>\n </div>\n\n <div class="content-option left-flex text">\n <span class="option-title">Deaths: </span>\n <span id="_deaths" class="text-value">0</span>\n </div>\n\n <div class="content-option left-flex text">\n <span class="option-title">Autosync: </span>\n <span id="_autoSyncTimes" class="text-value">0</span>\n </div>\n\n <div class="content-option left-flex text">\n <span class="option-title">Velocity tick: </span>\n <span id="_velocityTickTimes" class="text-value">0</span>\n </div>\n\n <div class="content-option left-flex text">\n <span class="option-title">SSHammer: </span>\n <span id="_spikeSyncHammerTimes" class="text-value">0</span>\n </div>\n\n <div class="content-option left-flex text">\n <span class="option-title">Spike sync: </span>\n <span id="_spikeSyncTimes" class="text-value">0</span>\n </div>\n\n <div class="content-option left-flex text">\n <span class="option-title">Spike tick: </span>\n <span id="_spikeTickTimes" class="text-value">0</span>\n </div>\n\n <div class="content-option left-flex text">\n <span class="option-title">KBTrap: </span>\n <span id="_knockbackTickTrapTimes" class="text-value">0</span>\n </div>\n\n <div class="content-option left-flex text">\n <span class="option-title">KBHammer: </span>\n <span id="_knockbackTickHammerTimes" class="text-value">0</span>\n </div>\n\n <div class="content-option left-flex text">\n <span class="option-title">KB Reg: </span>\n <span id="_knockbackTickTimes" class="text-value">0</span>\n </div>\n\n </div>\n </div>\n\n</div>';
const Bots_default = '<div class="menu-page" data-id="5">\n <div class="page-title">Bots</div>\n <p class="page-description">Create bots, control them and dominate the entire server</p>\n\n \x3c!-- Controller --\x3e\n <div class="section">\n <div class="section-title">Controller</div>\n\n <div class="section-content">\n <div class="content-option">\n <span class="option-title">Follow cursor</span>\n <label class="switch-checkbox">\n <input id="_followCursor" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Bots are going to follow your cursor instead of character</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Stop movement radius</span>\n <label class="slider">\n <span class="slider-value"></span>\n <input id="_movementRadius" type="range" step="25" min="25" max="250">\n </label>\n <span class="option-description">Bots will stop movement at this radius</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Circle formation</span>\n <label class="switch-checkbox">\n <input id="_circleFormation" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Bots will form a circle around you</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Circle rotation</span>\n <label class="switch-checkbox">\n <input id="_circleRotation" type="checkbox"></input>\n <span></span>\n </label>\n <span class="option-description">Bots will move in a circular way around you</span>\n </div>\n\n <div class="content-option">\n <span class="option-title">Circle radius</span>\n <label class="slider">\n <span class="slider-value"></span>\n <input id="_circleRadius" type="range" step="25" min="50" max="600">\n </label>\n </div>\n </div>\n\n <div id="bot-container" class="section-content"></div>\n\n <div class="content-option centered">\n <button id="add-bot" class="option-button">Add Bot</button>\n </div>\n </div>\n\n</div>';
const styles_default = '@import "https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;600;800&display=swap";\n\n* {\n user-select: none;\n}\n\n/* Slightly lighter + bluish dark backgrounds */\nheader {\n display: flex;\n justify-content: space-between;\n align-items: center;\n height: 45px;\n background: #16181c; /* was #121212 → lighter + hint of blue */\n padding: 10px;\n border-radius: 6px;\n}\n\nheader .page-title {\n font-size: 2.3em;\n}\n\nheader #credits {\n display: flex;\n justify-content: space-between;\n gap: 10px;\n height: 45px;\n}\n\nheader #credits p {\n margin-top: auto;\n}\n\nheader #logo {\n display: block;\n width: auto;\n height: 100%;\n scale: 1.2;\n}\n\nheader #close-button {\n display: block;\n fill: #b5b5b5; /* slightly lighter */\n cursor: pointer;\n width: auto;\n height: 100%;\n transition: fill 200ms;\n}\n\nheader #close-button:hover {\n fill: #f0f0f0;\n}\n\n@keyframes ripple {\n from {\n opacity: 1;\n transform: scale(0);\n }\n to {\n opacity: 0;\n transform: scale(0.7);\n }\n}\n\n#navbar-container {\n display: flex;\n flex-direction: column;\n background: #16181c; /* was #121212 */\n padding: 10px;\n border-radius: 6px;\n row-gap: 3px;\n}\n\n#navbar-container .open-menu {\n position: relative;\n width: 8.5em;\n height: 3.2em;\n background: #101215; /* was #0d0d0d → slightly lighter + blue */\n font-weight: 800;\n font-size: 1.3em;\n overflow: hidden;\n transition: all 400ms;\n display: flex;\n justify-content: left;\n align-items: center;\n padding: 0px 25px;\n border-radius: 3px;\n border: 1px solid rgba(200, 210, 220, 0.08); /* cooler gray border */\n}\n\n.open-menu > span {\n display: flex;\n justify-content: left;\n align-items: center;\n gap: 10px;\n transition: all 300ms;\n pointer-events: none;\n}\n\n.open-menu:hover {\n background: #3a3d42; /* was #3d3d3d → cooler tone */\n}\n\n.open-menu:hover span {\n transform: translateY(-2px);\n}\n\n.open-menu.active {\n background: #3a3d42;\n pointer-events: none;\n}\n\n#navbar-container .open-menu.bottom-align {\n margin-top: auto;\n}\n\n#navbar-container .open-menu .ripple {\n position: absolute;\n z-index: 5;\n background: rgba(200, 215, 230, 0.4); /* slightly bluish white ripple */\n top: 0;\n left: 0;\n border-radius: 50%;\n opacity: 0;\n animation: ripple 800ms;\n pointer-events: none;\n}\n\n/* Animations unchanged */\n@keyframes toclose {\n from {\n opacity: 1;\n transform: scale(1);\n }\n to {\n opacity: 0;\n transform: scale(0);\n }\n}\n\n@keyframes toopen {\n from {\n opacity: 0;\n transform: scale(0);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n@keyframes appear {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n#page-container {\n width: 100%;\n height: 100%;\n overflow-y: scroll;\n}\n\n.menu-page {\n background: #16181c; /* consistent background */\n padding: 10px;\n border-radius: 6px;\n display: none;\n}\n\n.menu-page.opened {\n display: block;\n}\n\n.menu-page .page-title {\n font-size: 2.8em;\n}\n\n.menu-page > .section {\n margin-top: 20px;\n background: #101215; /* was #0d0d0d */\n padding: 15px;\n border-radius: 6px;\n}\n\n.menu-page > .section .section-title {\n font-weight: 800;\n font-size: 1.8em;\n color: #a0a5aa; /* slightly lighter + bluish gray */\n margin-bottom: 10px;\n}\n\n.section-content {\n display: flex;\n flex-direction: column;\n gap: 5px;\n}\n\n.small-section {\n gap: 0px;\n font-size: 0.85rem;\n}\n\n.menu-page > .section .section-content.split {\n display: flex;\n justify-content: space-between;\n flex-direction: row;\n column-gap: 30px;\n}\n\n.menu-page > .section .section-content .content-split {\n width: 50%;\n display: flex;\n flex-direction: column;\n row-gap: 10px;\n}\n\n.menu-page > .section .section-content .content-option {\n display: flex;\n justify-content: space-between;\n align-items: center;\n min-height: 40px;\n padding: 3px 10px;\n transition: background 300ms;\n border-radius: 8px;\n}\n\n.content-option:hover {\n background: rgba(60, 65, 75, 0.25); /* cooler hover bg */\n}\n\n.option-description {\n position: absolute;\n z-index: 99;\n visibility: hidden;\n background: #282b30; /* was #2a2a2a → bluish dark */\n padding: 8px;\n border-radius: 6px;\n font-weight: 600;\n pointer-events: none;\n max-width: 300px;\n}\n\n.description-show {\n visibility: visible;\n}\n\n.menu-page > .section .content-option.centered {\n display: flex;\n justify-content: center;\n}\n\n.menu-page > .section .section-content .content-option .option-title {\n font-weight: 800;\n font-size: 1.4em;\n color: #60656b; /* was #585858 → lighter + cooler */\n transition: color 300ms;\n}\n\n.menu-page > .section .section-content .content-option .option-content {\n display: flex;\n justify-content: center;\n align-items: center;\n column-gap: 10px;\n}\n\n.menu-page > .section .section-content .content-option .disconnect-button {\n width: 30px;\n height: 30px;\n cursor: pointer;\n fill: rgba(130, 55, 60, 0.5); /* slightly softened */\n transition: fill 300ms;\n}\n\n.menu-page > .section .section-content .content-option:hover .option-title {\n color: #888c92; /* was #7e7d7d */\n}\n\n.menu-page > .section .section-content .content-option:hover .disconnect-button {\n fill: #8a3636;\n}\n\n.menu-page > .section .section-content .content-option:hover .disconnect-button:hover {\n fill: #983a3a;\n}\n\n.menu-page > .section .section-content .text {\n display: flex;\n justify-content: left;\n gap: 10px;\n}\n\n.menu-page > .section .section-content .text .text-value {\n color: #8e8888; /* slightly lighter */\n font-weight: 800;\n font-size: 1.5em;\n}\n\n.simplified {\n font-weight: 600 !important;\n font-size: 1.2em !important;\n word-spacing: 2px;\n}\n\n.highlight {\n color: #c0c5ca; /* cooler highlight */\n}\n\n.menu-page > .section .option-button {\n /* width: 117px;\n height: 45px; */\n background: #2e3136; /* was #303030 → bluish dark */\n border: 5px solid #24272b; /* was #262626 */\n padding: 10px 30px;\n border-radius: 6px;\n font-weight: 800;\n font-size: 1.1em;\n color: #888c92;\n transition: background 300ms, border-color 300ms;\n}\n\n\n#bot-container {\n margin: 10px 0;\n}\n\n.menu-page > .section .option-button:hover {\n background: #34383d;\n border-color: #282b30;\n}\n\n.menu-page > .section .section-content .hotkeyInput {\n width: 90px;\n height: 40px;\n background: #2e3136;\n border: 5px solid #24272b;\n border-radius: 6px;\n font-weight: 800;\n font-size: 1.1em;\n color: #888c92;\n display: flex;\n justify-content: center;\n align-items: center;\n transition: background 300ms, border-color 300ms, color 300ms;\n}\n\n.menu-page > .section .section-content .hotkeyInput:hover {\n background: #34383d;\n border-color: #282b30;\n}\n\n.menu-page > .section .section-content .hotkeyInput.active {\n background: #3a3e44;\n border-color: #2c3035;\n}\n\n.red {\n background: #853838!important;\n border-color: #6f2f2f!important;\n color: #c07878!important;\n}\n\n.red:hover {\n background: #b24848!important;\n border-color: #753131!important;\n}\n\n.red.active {\n background: #9c4040!important;\n border-color: #753131!important;\n}\n\n.menu-page > .section .section-content .switch-checkbox {\n position: relative;\n width: 90px;\n height: 34px;\n}\n\n.menu-page > .section .section-content .switch-checkbox input {\n width: 0;\n height: 0;\n opacity: 0;\n}\n\n.input {\n outline: 3px solid transparent;\n border: none;\n text-align: center;\n padding: 0;\n margin: 0;\n width: 225px;\n height: 30px;\n background: #2e3136;\n box-shadow: 0px -6px 0px 0px #24272b inset;\n border-radius: 6px;\n font-weight: 800;\n font-size: 1.1em;\n color: #888c92;\n display: flex;\n justify-content: center;\n align-items: center;\n transition: background 300ms, border-color 300ms, color 300ms, outline 300ms;\n}\n\n.input:focus {\n outline: 3px solid #757a80; /* cooler focus ring */\n}\n\n.menu-page > .section .section-content .switch-checkbox input:checked + span {\n background: #3a3e44;\n box-shadow: 0px -17px 0px 0px #2f3338 inset;\n}\n\n.menu-page > .section .section-content .switch-checkbox input:checked + span:before {\n transform: translateX(50px) scale(0.6);\n background: #888c92;\n}\n\n.menu-page > .section .section-content .switch-checkbox span {\n position: absolute;\n cursor: pointer;\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n background: #2e3136;\n border-radius: 6px;\n box-shadow: 0px -17px 0px 0px #282b30 inset;\n}\n\n.menu-page > .section .section-content .switch-checkbox span:before {\n position: absolute;\n content: "";\n transform: scale(0.6);\n transition: transform 300ms;\n width: 40px;\n height: 40px;\n border-radius: 6px;\n background: #60656b;\n}\n\n.menu-page > .section .section-content input[id][type="color"] {\n width: 60px;\n height: 33.3333333333px;\n outline: none;\n border: none;\n padding: 3px;\n margin: 0;\n background: #2e3136;\n border-radius: 6px;\n cursor: pointer;\n}\n\n.menu-page > .section .section-content .reset-color {\n background: var(--data-color);\n width: 10px;\n height: 10px;\n border-radius: 50%;\n}\n\n.menu-page > .section .section-content .slider {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n}\n\n.menu-page > .section .section-content .slider input {\n appearance: none;\n outline: none;\n cursor: pointer;\n padding: 0;\n margin: 0;\n border: none;\n width: 144px;\n height: 30px;\n background: #3a3e44;\n box-shadow: 0px -15px 0px 0px #2f3338 inset;\n border-radius: 6px;\n}\n\n.menu-page > .section .section-content .slider input::-webkit-slider-thumb {\n -webkit-appearance: none;\n transform: scale(0.7);\n width: 30px;\n height: 30px;\n background: #888c92;\n border-radius: 6px;\n}\n\n.menu-page > .section .section-content .slider .slider-value {\n color: #60656b;\n font-weight: 800;\n font-size: 1.4em;\n opacity: 0.4;\n}\n\n.left-flex {\n display: flex;\n justify-content: left !important;\n gap: 10px;\n}\n\nhtml,\nbody {\n margin: 0;\n padding: 0;\n scrollbar-width: thin;\n scrollbar-track-color: #2e3136;\n scrollbar-face-color: #24272b;\n overflow: hidden;\n}\n\n* {\n font-family: "Noto Sans", sans-serif;\n color: #f2f4f6; /* slightly softer white */\n}\n\nh1, .page-title {\n font-weight: 800;\n margin: 0;\n}\n\nh2 {\n margin: 0;\n}\n\np {\n font-weight: 800;\n font-size: 1.1rem;\n margin: 0;\n color: #c0c5ca; /* cooler light gray */\n}\n\nbutton {\n border: none;\n outline: none;\n cursor: pointer;\n}\n\n#menu-container {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 1280px;\n height: 720px;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n#menu-container.transparent #menu-wrapper {\n background: rgba(10, 12, 16, 0.6); /* bluish transparent */\n backdrop-filter: blur(3px);\n box-shadow: 0 0 15px rgba(0, 10, 20, 0.4); /* subtle blue shadow */\n}\n\n#menu-container.transparent header,\n#menu-container.transparent .menu-page,\n#menu-container.transparent #navbar-container {\n background: rgba(22, 24, 28, 0.59); /* matching transparent bg */\n}\n\n#menu-container.transparent .section {\n background: rgba(16, 18, 21, 0.46);\n}\n\n#menu-container.transparent .open-menu {\n background: rgba(16, 18, 21, 0.46);\n}\n\n#menu-container.transparent .open-menu:hover,\n#menu-container.transparent .open-menu.active {\n background: rgba(58, 61, 66, 0.60);\n}\n\n#menu-wrapper {\n position: relative;\n display: flex;\n flex-direction: column;\n row-gap: 5px;\n width: 85%;\n height: 85%;\n padding: 10px;\n border-radius: 6px;\n background: #0a0c10; /* bluish black */\n}\n\n#menu-wrapper.toclose {\n animation: 150ms ease-in toclose forwards;\n}\n\n#menu-wrapper.toopen {\n animation: 150ms ease-in toopen forwards;\n}\n\nmain {\n display: flex;\n column-gap: 10px;\n width: 100%;\n height: calc(100% - 75px);\n}\n\n::-webkit-scrollbar {\n width: 12px;\n}\n\n::-webkit-scrollbar-track {\n background: #2e3136;\n border-radius: 6px;\n}\n\n::-webkit-scrollbar-thumb {\n background: #24272b;\n border-radius: 6px;\n}\n\n.icon {\n width: 50px;\n height: 50px;\n}\n\n.small-icon {\n width: 22px;\n height: 22px;\n}';
// Style de la ligne verrouillee du message de kill.
const Seldoom_style = ".seldoom-locked{display:inline-block;padding:4px 10px;border-radius:6px;"
+ "background:rgba(245,217,81,.12);border:1px solid rgba(245,217,81,.45);"
+ "color:#f5d951;font-weight:700;letter-spacing:.4px;white-space:nowrap}";
const Game_default = '#iframe-container {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n width: 100%;\n height: 100%;\n border: none;\n outline: none;\n z-index: 10;\n}\n\n#promoImgHolder,\n.menuHeader,\n.menuText,\n#guideCard,\n#altServer,\n#gameName,\n#pingDisplay,\n#partyButton,\n#onetrust-consent-sdk,\n.adMenuCard,\n#topInfoHolder > div:not([id]):not([class]),\n#touch-controls-fullscreen,\n#altcha,\n#joinPartyButton {\n display: none!important;\n}\n\n.menuCard {\n box-shadow: none;\n}\n\n#setupCard {\n display: flex;\n flex-direction: column;\n gap: 12px;\n background: #6d6d6d77;\n max-height: auto;\n width: 280px;\n}\n\n#setupCard > * {\n margin: 0!important;\n}\n\n#linksContainer2 {\n background: #6d6d6d77;\n}\n\n#bottomContainer {\n bottom: 20px;\n}\n\n#topInfoHolder {\n display: flex;\n flex-direction: column;\n justify-content: right;\n align-items: flex-end;\n gap: 10px;\n}\n\n#killCounter, #totalKillCounter {\n position: static;\n margin: 0;\n background-image: url(../img/icons/skull.png);\n}\n\n.actionBarItem {\n position: relative;\n}\n\n.itemCounter {\n position: absolute;\n top: 3px;\n right: 3px;\n font-size: 0.95em;\n color: white;\n text-shadow: #3d3f42 2px 0px 0px, #3d3f42 1.75517px 0.958851px 0px, #3d3f42 1.0806px 1.68294px 0px, #3d3f42 0.141474px 1.99499px 0px, #3d3f42 -0.832294px 1.81859px 0px, #3d3f42 -1.60229px 1.19694px 0px, #3d3f42 -1.97998px 0.28224px 0px, #3d3f42 -1.87291px -0.701566px 0px, #3d3f42 -1.30729px -1.5136px 0px, #3d3f42 -0.421592px -1.95506px 0px, #3d3f42 0.567324px -1.91785px 0px, #3d3f42 1.41734px -1.41108px 0px, #3d3f42 1.92034px -0.558831px 0px;\n}\n\n.itemCounter.hidden {\n display: none;\n}\n\n#glotusStats {\n position: absolute;\n color: rgb(221, 221, 221);\n font: 13px "Hammersmith One";\n bottom: 210px;\n left: 20px;\n\n display: flex;\n flex-direction: column;\n gap: 5px;\n}\n\n.hidden {\n display: none!important;\n}\n\n#chatLog {\n position: absolute;\n top: 65px;\n left: 10px;\n\n width: 380px;\n height: 180px;\n\n background: rgba(10, 12, 16, 0.6);\n padding: 10px;\n color: #f2f4f6;\n border-radius: 6px;\n\n display: flex;\n flex-direction: column;\n}\n\n#chatLogHeader {\n font-size: 1.8rem;\n margin: 0 0 5px 0;\n flex-shrink: 0;\n}\n\n#messageContainer {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n#messageContainer::-webkit-scrollbar {\n width: 6px;\n}\n\n#messageContainer::-webkit-scrollbar-track {\n background: #4c4f55;\n border-radius: 6px;\n}\n\n#messageContainer::-webkit-scrollbar-thumb {\n background: #303338;\n border-radius: 6px;\n}\n\n.logMessage {\n display: flex;\n gap: 8px;\n align-items: flex-start;\n}\n\n.logMessage span {\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n.logMessage .darken {\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.logMessage .log,\n.logMessage .warn,\n.logMessage .error {\n flex: 1;\n min-width: 0;\n}';
const Store_default = "#storeContainer {\n display: flex;\n flex-direction: column;\n gap: 10px;\n max-width: 400px;\n width: 100%;\n\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%) scale(0.9);\n}\n\n#toggleStoreType {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 10px;\n background-color: rgba(0, 0, 0, 0.15);\n color: #fff;\n border-radius: 4px;\n cursor: pointer;\n font-size: 20px;\n pointer-events: all;\n}\n\n#itemHolder {\n background-color: rgba(0, 0, 0, 0.15);\n max-height: 200px;\n height: 100%;\n padding: 10px;\n overflow-y: scroll;\n border-radius: 4px;\n pointer-events: all;\n scrollbar-width: none;\n}\n\n#itemHolder::-webkit-scrollbar {\n display: none;\n width: 0;\n height: 0;\n background: transparent;\n}\n\n.storeItemContainer {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 5px;\n height: 50px;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n.storeHat {\n display: flex;\n justify-content: center;\n align-items: center;\n width: 45px;\n height: 45px;\n margin-top: -5px;\n pointer-events: none;\n}\n\n.storeItemName {\n color: #fff;\n font-size: 20px;\n}\n\n.equipButton {\n margin-left: auto;\n color: #80eefc;\n cursor: pointer;\n font-size: 35px;\n}";
const Hats = {
0: {
index: 0,
id: 0,
name: "Unequip",
dontSell: !0,
price: 0,
scale: 0,
description: "None"
},
45: {
index: 1,
id: 45,
name: "Shame!",
dontSell: !0,
price: 0,
scale: 120,
description: "hacks are for losers"
},
51: {
index: 2,
id: 51,
name: "Moo Cap",
price: 0,
scale: 120,
description: "coolest mooer around"
},
50: {
index: 3,
id: 50,
name: "Apple Cap",
price: 0,
scale: 120,
description: "apple farms remembers"
},
28: {
index: 4,
id: 28,
name: "Moo Head",
price: 0,
scale: 120,
description: "no effect"
},
29: {
index: 5,
id: 29,
name: "Pig Head",
price: 0,
scale: 120,
description: "no effect"
},
30: {
index: 6,
id: 30,
name: "Fluff Head",
price: 0,
scale: 120,
description: "no effect"
},
36: {
index: 7,
id: 36,
name: "Pandou Head",
price: 0,
scale: 120,
description: "no effect"
},
37: {
index: 8,
id: 37,
name: "Bear Head",
price: 0,
scale: 120,
description: "no effect"
},
38: {
index: 9,
id: 38,
name: "Monkey Head",
price: 0,
scale: 120,
description: "no effect"
},
44: {
index: 10,
id: 44,
name: "Polar Head",
price: 0,
scale: 120,
description: "no effect"
},
35: {
index: 11,
id: 35,
name: "Fez Hat",
price: 0,
scale: 120,
description: "no effect"
},
42: {
index: 12,
id: 42,
name: "Enigma Hat",
price: 0,
scale: 120,
description: "join the enigma army"
},
43: {
index: 13,
id: 43,
name: "Blitz Hat",
price: 0,
scale: 120,
description: "hey everybody i'm blitz"
},
49: {
index: 14,
id: 49,
name: "Bob XIII Hat",
price: 0,
scale: 120,
description: "like and subscribe"
},
57: {
index: 15,
id: 57,
name: "Pumpkin",
price: 50,
scale: 120,
description: "Spooooky"
},
8: {
index: 16,
id: 8,
name: "Bummle Hat",
price: 100,
scale: 120,
description: "no effect"
},
2: {
index: 17,
id: 2,
name: "Straw Hat",
price: 500,
scale: 120,
description: "no effect"
},
15: {
index: 18,
id: 15,
name: "Winter Cap",
price: 600,
scale: 120,
description: "allows you to move at normal speed in snow",
coldM: 1
},
5: {
index: 19,
id: 5,
name: "Cowboy Hat",
price: 1e3,
scale: 120,
description: "no effect"
},
4: {
index: 20,
id: 4,
name: "Ranger Hat",
price: 2e3,
scale: 120,
description: "no effect"
},
18: {
index: 21,
id: 18,
name: "Explorer Hat",
price: 2e3,
scale: 120,
description: "no effect"
},
31: {
index: 22,
id: 31,
name: "Flipper Hat",
price: 2500,
scale: 120,
description: "have more control while in water",
watrImm: !0
},
1: {
index: 23,
id: 1,
name: "Marksman Cap",
price: 3e3,
scale: 120,
description: "increases arrow speed and range",
aMlt: 1.3
},
10: {
index: 24,
id: 10,
name: "Bush Gear",
price: 3e3,
scale: 160,
description: "allows you to disguise yourself as a bush"
},
48: {
index: 25,
id: 48,
name: "Halo",
price: 3e3,
scale: 120,
description: "no effect"
},
6: {
index: 26,
id: 6,
name: "Soldier Helmet",
price: 4e3,
scale: 120,
description: "reduces damage taken but slows movement",
spdMult: .94,
dmgMult: .75
},
23: {
index: 27,
id: 23,
name: "Anti Venom Gear",
price: 4e3,
scale: 120,
description: "makes you immune to poison",
poisonRes: 1
},
13: {
index: 28,
id: 13,
name: "Medic Gear",
price: 5e3,
scale: 110,
description: "slowly regenerates health over time",
healthRegen: 3
},
9: {
index: 29,
id: 9,
name: "Miners Helmet",
price: 5e3,
scale: 120,
description: "earn 1 extra gold per resource",
extraGold: 1
},
32: {
index: 30,
id: 32,
name: "Musketeer Hat",
price: 5e3,
scale: 120,
description: "reduces cost of projectiles",
projCost: .5
},
7: {
index: 31,
id: 7,
name: "Bull Helmet",
price: 6e3,
scale: 120,
description: "increases damage done but drains health",
healthRegen: -5,
dmgMultO: 1.5,
spdMult: .96
},
22: {
index: 32,
id: 22,
name: "Emp Helmet",
price: 6e3,
scale: 120,
description: "turrets won't attack but you move slower",
antiTurret: 1,
spdMult: .7
},
12: {
index: 33,
id: 12,
name: "Booster Hat",
price: 6e3,
scale: 120,
description: "increases your movement speed",
spdMult: 1.16
},
26: {
index: 34,
id: 26,
name: "Barbarian Armor",
price: 8e3,
scale: 120,
description: "knocks back enemies that attack you",
dmgK: .6
},
21: {
index: 35,
id: 21,
name: "Plague Mask",
price: 1e4,
scale: 120,
description: "melee attacks deal poison damage",
poisonDmg: 5,
poisonTime: 6
},
46: {
index: 36,
id: 46,
name: "Bull Mask",
price: 1e4,
scale: 120,
description: "bulls won't target you unless you attack them",
bullRepel: 1
},
14: {
index: 37,
id: 14,
name: "Windmill Hat",
topSprite: !0,
price: 1e4,
scale: 120,
description: "generates points while worn",
pps: 1.5
},
11: {
index: 38,
id: 11,
name: "Spike Gear",
topSprite: !0,
price: 1e4,
scale: 120,
description: "deal damage to players that damage you",
dmg: .45
},
53: {
index: 39,
id: 53,
name: "Turret Gear",
topSprite: !0,
price: 1e4,
scale: 120,
description: "you become a walking turret",
turret: {
projectile: 1,
range: 700,
rate: 2500
},
spdMult: .7,
knockback: 60
},
20: {
index: 40,
id: 20,
name: "Samurai Armor",
price: 12e3,
scale: 120,
description: "increased attack speed and fire rate",
atkSpd: .78
},
58: {
index: 41,
id: 58,
name: "Dark Knight",
price: 12e3,
scale: 120,
description: "restores health when you deal damage",
healD: .4
},
27: {
index: 42,
id: 27,
name: "Scavenger Gear",
price: 15e3,
scale: 120,
description: "earn double points for each kill",
kScrM: 2
},
40: {
index: 43,
id: 40,
name: "Tank Gear",
price: 15e3,
scale: 120,
description: "increased damage to buildings but slower movement",
spdMult: .3,
bDmg: 3.3
},
52: {
index: 44,
id: 52,
name: "Thief Gear",
price: 15e3,
scale: 120,
description: "steal half of a players gold when you kill them",
goldSteal: .5
},
55: {
index: 45,
id: 55,
name: "Bloodthirster",
price: 2e4,
scale: 120,
description: "Restore Health when dealing damage. And increased damage",
healD: .25,
dmgMultO: 1.2
},
56: {
index: 46,
id: 56,
name: "Assassin Gear",
price: 2e4,
scale: 120,
description: "Go invisible when not moving. Can't eat. Increased speed",
noEat: !0,
spdMult: 1.1,
invisTimer: 1e3
}
}, Accessories = {
0: {
index: 0,
id: 0,
name: "Unequip",
dontSell: !0,
price: 0,
scale: 0,
xOffset: 0,
description: "None"
},
12: {
index: 1,
id: 12,
name: "Snowball",
price: 1e3,
scale: 105,
xOffset: 18,
description: "no effect"
},
9: {
index: 2,
id: 9,
name: "Tree Cape",
price: 1e3,
scale: 90,
description: "no effect"
},
10: {
index: 3,
id: 10,
name: "Stone Cape",
price: 1e3,
scale: 90,
description: "no effect"
},
3: {
index: 4,
id: 3,
name: "Cookie Cape",
price: 1500,
scale: 90,
description: "no effect"
},
8: {
index: 5,
id: 8,
name: "Cow Cape",
price: 2e3,
scale: 90,
description: "no effect"
},
11: {
index: 6,
id: 11,
name: "Monkey Tail",
price: 2e3,
scale: 97,
xOffset: 25,
description: "Super speed but reduced damage",
spdMult: 1.35,
dmgMultO: .2
},
17: {
index: 7,
id: 17,
name: "Apple Basket",
price: 3e3,
scale: 80,
xOffset: 12,
description: "slowly regenerates health over time",
healthRegen: 1
},
6: {
index: 8,
id: 6,
name: "Winter Cape",
price: 3e3,
scale: 90,
description: "no effect"
},
4: {
index: 9,
id: 4,
name: "Skull Cape",
price: 4e3,
scale: 90,
description: "no effect"
},
5: {
index: 10,
id: 5,
name: "Dash Cape",
price: 5e3,
scale: 90,
description: "no effect"
},
2: {
index: 11,
id: 2,
name: "Dragon Cape",
price: 6e3,
scale: 90,
description: "no effect"
},
1: {
index: 12,
id: 1,
name: "Super Cape",
price: 8e3,
scale: 90,
description: "no effect"
},
7: {
index: 13,
id: 7,
name: "Troll Cape",
price: 8e3,
scale: 90,
description: "no effect"
},
14: {
index: 14,
id: 14,
name: "Thorns",
price: 1e4,
scale: 115,
xOffset: 20,
description: "no effect"
},
15: {
index: 15,
id: 15,
name: "Blockades",
price: 1e4,
scale: 95,
xOffset: 15,
description: "no effect"
},
20: {
index: 16,
id: 20,
name: "Devils Tail",
price: 1e4,
scale: 95,
xOffset: 20,
description: "no effect"
},
16: {
index: 17,
id: 16,
name: "Sawblade",
price: 12e3,
scale: 90,
spin: !0,
xOffset: 0,
description: "deal damage to players that damage you",
dmg: .15
},
13: {
index: 18,
id: 13,
name: "Angel Wings",
price: 15e3,
scale: 138,
xOffset: 22,
description: "slowly regenerates health over time",
healthRegen: 3
},
19: {
index: 19,
id: 19,
name: "Shadow Wings",
price: 15e3,
scale: 138,
xOffset: 22,
description: "increased movement speed",
spdMult: 1.1
},
18: {
index: 20,
id: 18,
name: "Blood Wings",
price: 2e4,
scale: 178,
xOffset: 26,
description: "restores health when you deal damage",
healD: .2
},
21: {
index: 21,
id: 21,
name: "Corrupt X Wings",
price: 2e4,
scale: 178,
xOffset: 26,
description: "deal damage to players that damage you",
dmg: .25
}
}, store = [ Hats, Accessories ];
const DataHandler = new class {
isWeaponType(type) {
return type <= 1;
}
isItemType(type) {
return type >= 2;
}
getStore(type) {
return store[type];
}
getStoreItem(type, id) {
switch (type) {
case 0:
return Hats[id];
case 1:
return Accessories[id];
default:
throw Error(`getStoreItem Error: type "${type}" is not defined`);
}
}
getProjectile(id) {
return Projectiles[this.getWeapon(id).projectile];
}
getWeapon(id) {
return Weapons[id];
}
getItem(id) {
return Items[id];
}
isWeapon(id) {
return this.getWeapon(id) !== void 0;
}
isItem(id) {
return Items[id] !== void 0;
}
isPrimary(id) {
return id != null && this.getWeapon(id).itemType === 0;
}
isSecondary(id) {
return id != null && this.getWeapon(id).itemType === 1;
}
isMelee(id) {
return id != null && "damage" in this.getWeapon(id);
}
isAttackable(id) {
return id != null && "range" in this.getWeapon(id);
}
isShootable(id) {
return id != null && "projectile" in this.getWeapon(id);
}
isPlaceable(id) {
return id !== -1 && "itemGroup" in Items[id];
}
isHealable(id) {
return "restore" in Items[id];
}
isDestroyable(id) {
return "health" in Items[id];
}
canMoveOnTop(id) {
return "ignoreCollision" in Items[id];
}
}, DataHandler_default = DataHandler;
class ObjectItem {
id;
pos;
angle;
scale=0;
constructor(id, x, y, angle, scale) {
this.id = id, this.pos = {
current: new Vector_default(x, y)
}, this.angle = angle, this.scale = scale;
}
get hitScale() {
return this.scale;
}
}
class Resource extends ObjectItem {
type;
layer;
constructor(id, x, y, angle, scale, type) {
super(id, x, y, angle, scale);
this.type = type, this.layer = type === 0 ? 3 : type === 2 ? 0 : 2;
}
formatScale(scaleMult = 1) {
let reduceScale = this.type === 0 || this.type === 1 ? .6 * scaleMult : 1;
return this.scale * reduceScale;
}
get collisionScale() {
return this.formatScale();
}
get placementScale() {
return this.formatScale(.6);
}
get isCactus() {
return this.type === 1 && pointInDesert(this.pos.current);
}
getDamage() {
if (this.isCactus) {
return 35;
}
return 0;
}
}
class PlayerObject extends ObjectItem {
type;
ownerID;
collisionDivider;
health;
tempHealth;
maxHealth;
reload=-1;
maxReload=-1;
isDestroyable;
destroyingTick=0;
canBeDestroyed=!1;
trapActivated=!1;
wasTeammate=!1;
seenPlacement=!1;
layer;
itemGroup;
projectile=null;
constructor(id, x, y, angle, scale, type, ownerID) {
super(id, x, y, angle, scale);
this.type = type, this.ownerID = ownerID;
let item = Items[type];
if (this.collisionDivider = "colDiv" in item ? item.colDiv : 1, this.health = "health" in item ? item.health : 1 / 0,
this.tempHealth = this.health, this.maxHealth = this.health, this.isDestroyable = this.maxHealth !== 1 / 0,
item.id === 17) {
this.reload = Math.ceil(item.shootRate / 111), this.maxReload = this.reload;
}
this.layer = ItemGroups[item.itemGroup].layer, this.itemGroup = item.itemGroup;
}
formatScale(placeCollision = !1) {
return this.scale * (placeCollision ? 1 : this.collisionDivider);
}
get collisionScale() {
return this.formatScale();
}
get placementScale() {
let item = Items[this.type];
if (item.id === 21) {
return item.blocker;
}
return this.scale;
}
get isSpike() {
return this.itemGroup === 2;
}
getDamage() {
if (this.isSpike) {
let type = this.type;
return DataHandler_default.getItem(type).damage;
}
return 0;
}
}
class Entity {
id=-1;
pos={
previous: new Vector_default,
current: new Vector_default,
future: new Vector_default
};
angle=0;
scale=0;
speed=0;
move_dir=0;
setFuturePosition() {
let {previous: previous, current: current, future: future} = this.pos, distance = previous.distance(current);
this.speed = distance;
let angle = previous.angle(current);
this.move_dir = angle, future.setVec(current.addDirection(angle, distance));
}
get collisionScale() {
return this.scale;
}
get hitScale() {
return this.scale * 1.8;
}
client;
constructor(client) {
this.client = client;
}
getFuturePosition(speed) {
return this.pos.current.copy().add(Vector_default.fromAngle(this.move_dir, speed));
}
colliding(object, radius) {
let {previous: a0, current: a1, future: a2} = this.pos, b0 = object.pos.current;
return a0.distance(b0) <= radius || a1.distance(b0) <= radius || a2.distance(b0) <= radius;
}
collidingObject(object, addRadius = 0, checkType = 3) {
let {previous: a0, current: a1, future: a2} = this.pos, b0 = object.pos.current, radius = this.collisionScale + object.collisionScale + addRadius;
return !!(checkType & 4) && a0.distance(b0) <= radius || !!(checkType & 2) && a1.distance(b0) <= radius || !!(checkType & 1) && a2.distance(b0) <= radius;
}
collidingSimple(entity, range, tempPos = this.pos.current) {
let pos1 = tempPos, pos2 = entity.pos.current;
return pos1.distance(pos2) <= range;
}
collidingEntity(entity, range, checkBased = !1, prev = !0) {
let {previous: a0, current: a1, future: a2} = this.pos, {previous: b0, current: b1, future: b2} = entity.pos;
if (checkBased) {
return prev && a0.distance(b0) <= range || a1.distance(b1) <= range || a2.distance(b2) <= range;
}
return a0.distance(b0) <= range || a0.distance(b1) <= range || a0.distance(b2) <= range || a1.distance(b0) <= range || a1.distance(b1) <= range || a1.distance(b2) <= range || a2.distance(b0) <= range || a2.distance(b1) <= range || a2.distance(b2) <= range;
}
runningAwayFrom(entity, angle) {
if (angle === null) {
return !1;
}
let pos1 = this.pos.current, pos2 = entity.pos.current, angleTo = pos1.angle(pos2);
if (getAngleDist(angle, angleTo) <= Math.PI / 2) {
return !1;
}
return !0;
}
}
const Entity_default = Entity;
class EnemyManager {
client;
dangerousEnemies=[];
_nearestEnemy=[ null, null ];
nearestDangerAnimal=null;
nearestTrap=null;
nearestCollider=null;
secondNearestCollider=null;
nearestEnemySpikeCollider=null;
spikeCollider=null;
enemySpikeCollider=null;
nearestTurretEntity=null;
detectedEnemy=!1;
dangerWithoutSoldier=!1;
detectedDangerEnemy=!1;
nearestTrappedEnemy=null;
previousTrappedEnemy=null;
nearestPlayerObject=null;
secondNearestPlayerObject=null;
nearestObject=null;
nearestEnemyObject=null;
secondNearestEnemyObject=null;
nearestSpike=null;
willCollideSpike=!1;
collidingSpike=!1;
nearestSpikePlacerAngle=null;
prevNearestSpikePlacerAngle=null;
nearestEnemyToNearestEnemy=null;
enemyCanPlaceSpike=!1;
possibleToKnockback=!1;
potentialSpikeKnockbackDamage=0;
potentialSpikeDamage=0;
potentialDamage=0;
primaryDamage=0;
detectedDanger=!1;
reverseInsta=!1;
rangedBowInsta=!1;
spikeSyncThreat=!1;
velocityTickThreat=!1;
nearestLowEntity=null;
nearestEnemyPush=null;
nearestPushSpike=null;
nearestLowHPObjectPrev=null;
nearestLowHPObject=null;
nearestSyncEnemy=null;
constructor(client) {
this.client = client;
}
preReset() {
this._nearestEnemy[0] = null, this._nearestEnemy[1] = null, this.nearestDangerAnimal = null,
this.nearestLowEntity = null;
}
reset() {
this.nearestEnemyToNearestEnemy = null, this.willCollideSpike = !1, this.collidingSpike = !1,
this.prevNearestSpikePlacerAngle = this.nearestSpikePlacerAngle, this.nearestSpikePlacerAngle = null,
this.dangerousEnemies.length = 0, this.nearestTrap = null, this.nearestCollider = null,
this.nearestEnemySpikeCollider = null, this.spikeCollider = null, this.enemySpikeCollider = null,
this.nearestTurretEntity = null, this.detectedEnemy = !1, this.dangerWithoutSoldier = !1,
this.detectedDangerEnemy = !1, this.previousTrappedEnemy = this.nearestTrappedEnemy,
this.nearestTrappedEnemy = null, this.nearestPlayerObject = null, this.nearestObject = null,
this.secondNearestPlayerObject = null, this.nearestEnemyObject = null, this.secondNearestEnemyObject = null,
this.nearestSpike = null, this.enemyCanPlaceSpike = !1, this.possibleToKnockback = !1,
this.velocityTickThreat = !1, this.potentialSpikeKnockbackDamage = 0, this.potentialSpikeDamage = 0,
this.potentialDamage = 0, this.detectedDanger = !1, this.reverseInsta = !1,
this.rangedBowInsta = !1, this.spikeSyncThreat = !1, this.nearestEnemyPush = null,
this.nearestPushSpike = null, this.nearestLowHPObjectPrev = this.nearestLowHPObject,
this.nearestLowHPObject = null, this.nearestSyncEnemy = null, this.primaryDamage = 0;
}
get wasTrappedEnemy() {
let enemy = this.previousTrappedEnemy;
if (enemy !== null && this.nearestTrappedEnemy === null) {
return enemy;
}
return null;
}
get nearestPlaceSpikeAngle() {
let prevAngle = this.prevNearestSpikePlacerAngle, currAngle = this.nearestSpikePlacerAngle;
if (prevAngle === null && currAngle !== null) {
return currAngle;
}
return null;
}
get nearestEnemy() {
return this._nearestEnemy[0];
}
get nearestAnimal() {
return this._nearestEnemy[1];
}
get canSpikeSync() {
return this.nearestPlaceSpikeAngle !== null && this.client.ObjectManager.isDestroyedObject();
}
isNear(enemy, nearest, owner = this.client.myPlayer) {
if (nearest === null || enemy === nearest) {
return !0;
}
let a0 = owner.pos.current, distance1 = a0.distanceDefault(enemy.pos.current), distance2 = a0.distanceDefault(nearest.pos.current);
return distance1 < distance2;
}
get nearestEntity() {
let target1 = this.nearestEnemy, target2 = this.nearestAnimal;
if (target1 === null) {
return target2;
}
return this.isNear(target1, target2) ? target1 : target2;
}
instaThreat() {
return this.velocityTickThreat || this.reverseInsta || this.rangedBowInsta || this.primaryDamage + this.potentialSpikeKnockbackDamage >= 100;
}
shouldIgnoreModule() {
return this.instaThreat() || this.detectedDangerEnemy || this.spikeSyncThreat;
}
nearestEnemyInRangeOf(range, target) {
let enemy = target || this.nearestEnemy;
return enemy !== null && this.client.myPlayer.collidingEntity(enemy, range);
}
handleDanger(enemy) {
let danger = enemy.canPossiblyInstakill();
if (enemy.prevDanger = enemy.danger, enemy.danger = danger, enemy.canPlaceSpikeObject) {
this.potentialSpikeDamage = Math.max(this.potentialSpikeDamage, enemy.spikeDamage);
}
if (this.potentialDamage += enemy.potentialDamage, this.primaryDamage = Math.max(enemy.primaryDamage, this.primaryDamage),
enemy.prevDanger !== enemy.danger && enemy.danger >= 2) {
this.detectedDanger = !0;
}
if (enemy.velocityTicking) {
this.velocityTickThreat = !0;
}
if (enemy.reverseInsta) {
this.reverseInsta = !0;
}
if (enemy.rangedBowInsta) {
this.rangedBowInsta = !0;
}
if (enemy.spikeSyncThreat) {
this.spikeSyncThreat = !0;
}
}
checkCollision(target, isOwner = !1) {
target.isTrapped = !1, target.trappedInPrev = target.trappedIn, target.trappedIn = null;
let {ObjectManager: ObjectManager, PlayerManager: PlayerManager, myPlayer: myPlayer, ModuleHandler: ModuleHandler} = this.client, pos1 = myPlayer.pos.current, pos2 = target.pos.current, distanceToTarget = pos1.distance(pos2), angleToTarget = pos1.angle(pos2);
ObjectManager.grid2D.query(target.pos.current.x, target.pos.current.y, 3, id => {
let object = ObjectManager.objects.get(id), pos3 = object.pos.current, isPlayerObject = object instanceof PlayerObject, isCactus = !isPlayerObject && object.isCactus, isSpike = isPlayerObject && object.itemGroup === 2, isEnemyObject = !isPlayerObject || PlayerManager.isEnemyByID(object.ownerID, target), isEnemyObjectToMyPlayer = !isPlayerObject || PlayerManager.isEnemyByID(object.ownerID, myPlayer), collidingObject = target.collidingObject(object, 1), collidingCurrent = target.collidingObject(object, 1, 1);
if (isPlayerObject && !isEnemyObject) {
object.wasTeammate = !0;
}
if (isPlayerObject && isEnemyObject && object.type === 15) {
if (collidingObject) {
if (!isOwner) {
if (this.isNear(target, this.nearestTrappedEnemy)) {
this.nearestTrappedEnemy = target;
}
if (!isEnemyObjectToMyPlayer && this.isNear(target, this.nearestEnemyPush)) {
this.nearestEnemyPush = target;
}
}
if (target.isTrapped = !0, target.hatID === 40) {
target.usesTank = !0;
}
if (this.isNear(object, target.trappedIn)) {
target.trappedIn = object;
}
if (isOwner && this.isNear(object, this.nearestTrap)) {
this.nearestTrap = object;
}
}
if (collidingCurrent || !object.seenPlacement && !object.wasTeammate) {
object.trapActivated = !0;
}
}
if (isOwner && isPlayerObject && object.type === 22 && collidingCurrent) {
myPlayer.teleportPos.setVec(pos1), myPlayer.teleported = !0;
}
if (isPlayerObject && object.isDestroyable) {
if (object.destroyingTick !== ModuleHandler.tickCount) {
object.canBeDestroyed = !1, object.tempHealth = object.health;
}
let damage = target.getMaxBuildingDamage(object, !0), canSee = !isEnemyObject || object.type !== 15 || isEnemyObject && object.type === 15 && object.trapActivated;
if (damage !== null && canSee) {
if (object.destroyingTick = ModuleHandler.tickCount, object.tempHealth -= damage,
object.tempHealth <= 0) {
object.canBeDestroyed = !0;
}
}
}
if (isOwner) {
if (isEnemyObject && isPlayerObject && object.isDestroyable) {
if (object.type === 15 || object.type === 16 || object.itemGroup === 2) {
if (this.isNear(object, this.nearestEnemyObject)) {
this.secondNearestEnemyObject = this.nearestEnemyObject, this.nearestEnemyObject = object;
}
if (object !== this.nearestEnemyObject && this.isNear(object, this.secondNearestEnemyObject)) {
this.secondNearestEnemyObject = object;
}
}
if (object.itemGroup === 2 && this.isNear(object, this.nearestSpike)) {
this.nearestSpike = object;
}
}
if (this.isNear(object, this.nearestObject)) {
this.nearestObject = object;
}
if (isPlayerObject && object.isDestroyable) {
if (this.isNear(object, this.nearestPlayerObject)) {
this.secondNearestPlayerObject = this.nearestPlayerObject, this.nearestPlayerObject = object;
}
if (object !== this.nearestPlayerObject && this.isNear(object, this.secondNearestPlayerObject)) {
this.secondNearestPlayerObject = object;
}
}
if (!this.willCollideSpike && isEnemyObject && (isSpike || isCactus) && target.collidingObject(object, 70)) {
this.willCollideSpike = !0;
}
if (isEnemyObject && (isSpike || isCactus) && target.colliding(object, target.collisionScale + object.collisionScale + 1)) {
this.collidingSpike = !0, this.potentialSpikeDamage = Math.max(this.potentialSpikeDamage, object.getDamage());
}
let isAdditional = isPlayerObject && object.type === 16;
if (isEnemyObject && (isSpike || isCactus || isAdditional) && target.collidingObject(object, 150)) {
if (this.isNear(object, this.nearestCollider)) {
this.secondNearestCollider = this.nearestCollider, this.nearestCollider = object;
}
if (object !== this.nearestCollider && this.isNear(object, this.secondNearestCollider)) {
this.secondNearestCollider = object;
}
}
} else {
let {primary: primary, secondary: secondary} = myPlayer.weapon;
if (isPlayerObject && object.isDestroyable && secondary === 10 && primary !== null && primary !== 8) {
let damage = myPlayer.getBuildingDamage(secondary, !0), primaryRange = DataHandler_default.getWeapon(primary).range + target.hitScale, secondaryRange = DataHandler_default.getWeapon(secondary).range + object.hitScale;
if (myPlayer.collidingSimple(target, primaryRange) && myPlayer.collidingSimple(object, secondaryRange) && object.health <= damage) {
let itemType = 4, spikeID = myPlayer.getItemByType(itemType), placeLength = myPlayer.getItemPlaceScale(spikeID), spikeScale = Items[spikeID].scale, spikePos = pos1.addDirection(angleToTarget, placeLength), distance = pos2.distance(spikePos), range = target.collisionScale + spikeScale;
if (distance <= range && this.isNear(object, this.nearestLowHPObject)) {
this.nearestLowHPObject = object, this.nearestSyncEnemy = target;
}
}
}
if (isEnemyObjectToMyPlayer && (isSpike || isCactus) && !myPlayer.isTrapped) {
let KBDistance = target.getActualMaxKnockback(myPlayer), spikeScale = object.collisionScale + myPlayer.collisionScale, angleToEnemy = pos2.angle(pos1), angleToSpike = pos2.angle(pos3), distanceToSpike1 = pos2.distance(pos3), offset = Math.asin(2 * spikeScale / (2 * distanceToSpike1)), intersecting = getAngleDist(angleToEnemy, angleToSpike) <= offset, overlapping = distanceToTarget <= distanceToSpike1, inRange2 = KBDistance !== 0 && myPlayer.collidingObject(object, KBDistance);
if (intersecting && overlapping && inRange2) {
this.possibleToKnockback = !0, this.potentialSpikeKnockbackDamage = Math.max(this.potentialSpikeKnockbackDamage, object.getDamage());
}
}
if (isEnemyObject && (isSpike || isCactus) && target.collidingObject(object) && this.isNear(target, this.enemySpikeCollider)) {
this.enemySpikeCollider = target;
}
if (isEnemyObject && (isSpike || isCactus) && this.isNear(target, this.nearestEnemySpikeCollider)) {
let KBDistance = myPlayer.getActualMaxKnockback(target), spikeScale = object.collisionScale + target.collisionScale * 1.5, angleToEnemy = pos1.angle(pos2), angleToSpike = pos1.angle(pos3), distanceToSpike1 = pos1.distance(pos3), offset = Math.asin(2 * spikeScale / (2 * distanceToSpike1)), intersecting = getAngleDist(angleToEnemy, angleToSpike) <= offset, overlapping = distanceToTarget <= distanceToSpike1, inRange2 = KBDistance !== 0 && target.collidingObject(object, KBDistance);
if (intersecting && overlapping && inRange2) {
if (this.spikeCollider === null) {
this.nearestEnemySpikeCollider = target, this.spikeCollider = object;
} else {
let pos4 = this.spikeCollider.pos.current, angle1 = pos2.angle(pos3), angle2 = pos1.angle(pos3), angle3 = pos2.angle(pos4), angle4 = pos1.angle(pos4), angleDist1 = getAngleDist(angle1, angle2), angleDist2 = getAngleDist(angle3, angle4);
if (angleDist1 < angleDist2) {
this.nearestEnemySpikeCollider = target, this.spikeCollider = object;
}
}
}
}
}
});
}
handleNearest(type, enemy) {
let {myPlayer: myPlayer} = this.client;
if (myPlayer.getMaxWeaponDamage(myPlayer.weapon.primary, !1) >= enemy.currentHealth && this.isNear(enemy, this.nearestLowEntity)) {
this.nearestLowEntity = enemy;
}
if (this.isNear(enemy, this._nearestEnemy[type])) {
if (this._nearestEnemy[type] = enemy, enemy.canUseTurret && this.client.myPlayer.collidingSimple(enemy, 700)) {
this.nearestTurretEntity = enemy;
}
}
}
handleNearestDangerAnimal(animal) {
let {myPlayer: myPlayer} = this.client;
if (!animal.isDanger) {
return;
}
if (!myPlayer.collidingEntity(animal, animal.collisionRange)) {
return;
}
if (!this.isNear(animal, this.nearestDangerAnimal)) {
return;
}
this.nearestDangerAnimal = animal;
}
handleAnimal(animal) {
this.handleNearest(1, animal), this.handleNearestDangerAnimal(animal);
}
attemptSpikePlacement() {
let {ModuleHandler: ModuleHandler} = this.client, placementAngles = this.nearestSpikePlacerAngle;
if (placementAngles === null) {
return;
}
let itemType = 4;
for (let angle of placementAngles) {
ModuleHandler.place(itemType, angle);
}
ModuleHandler.placedOnce = !0, ModuleHandler.placeAngles[0] = itemType, ModuleHandler.placeAngles[1] = placementAngles;
}
handleEnemies(enemies) {
this.reset();
let {myPlayer: myPlayer, ObjectManager: ObjectManager, PlayerManager: PlayerManager} = this.client;
this.checkCollision(myPlayer, !0);
for (let i = 0, len = enemies.length; i < len; i++) {
let enemy = enemies[i];
this.checkCollision(enemy), this.handleDanger(enemy), this.handleNearest(0, enemy);
}
if (myPlayer.isBullTickTime()) {
this.potentialDamage += 5;
}
this.potentialDamage += this.client.ProjectileManager.totalDamage;
let actualSpikeDamage = Math.max(this.potentialSpikeDamage, this.potentialSpikeKnockbackDamage);
this.potentialSpikeDamage = actualSpikeDamage;
let potentialDamage = this.potentialDamage + actualSpikeDamage, soldierDefense = Hats[6].dmgMult, soldierMult = myPlayer.hatID === 6 ? soldierDefense : 1;
if (potentialDamage * soldierDefense >= myPlayer.currentHealth) {
this.detectedDangerEnemy = !0;
} else if (potentialDamage * soldierMult >= myPlayer.currentHealth) {
this.detectedEnemy = !0;
}
if (potentialDamage >= myPlayer.currentHealth) {
this.dangerWithoutSoldier = !0;
}
let nearest = this.nearestEnemy;
if (nearest !== null) {
let pos1 = myPlayer.pos.current, pos2 = nearest.pos.current, angleToEnemy = pos1.angle(pos2), itemType = 4, spikeID = myPlayer.getItemByType(itemType), placeLength = myPlayer.getItemPlaceScale(spikeID), angles = ObjectManager.getBestPlacementAngles({
position: pos1,
id: spikeID,
targetAngle: angleToEnemy,
ignoreID: null,
preplace: !1,
reduce: !1,
fill: !1
}), spikeScale = Items[spikeID].scale, possibleAngles = angles.filter(angle => {
let spikePos = pos1.addDirection(angle, placeLength), distance = pos2.distance(spikePos), range = nearest.collisionScale + spikeScale;
return distance <= range;
});
if (possibleAngles.length !== 0) {
this.nearestSpikePlacerAngle = possibleAngles;
}
if (Settings_default._autoSync) {
for (let i = 0; i < PlayerManager.players.length; i++) {
let player = PlayerManager.players[i];
if (myPlayer.isMyPlayerByID(player.id)) {
continue;
}
if (PlayerManager.isEnemyByID(nearest.id, player) && this.isNear(player, this.nearestEnemyToNearestEnemy, nearest)) {
this.nearestEnemyToNearestEnemy = player;
}
}
}
}
let nearestEnemyPush = this.nearestEnemyPush;
if (nearestEnemyPush !== null && myPlayer.trappedIn === null) {
let trappedIn = nearestEnemyPush.trappedIn, pos0 = trappedIn.pos.current;
ObjectManager.grid2D.query(pos0.x, pos0.y, 2, id => {
let object = ObjectManager.objects.get(id);
if (object === trappedIn) {
return;
}
let isPlayerObject = object instanceof PlayerObject, isCactus = !isPlayerObject && object.isCactus, isSpike = isPlayerObject && object.itemGroup === 2;
isPlayerObject && object.type;
if ((!isPlayerObject || PlayerManager.isEnemyByID(object.ownerID, nearestEnemyPush)) && (isCactus || isSpike) && this.isNear(object, this.nearestPushSpike, nearestEnemyPush)) {
let pos1 = object.pos.current, distance = pos0.distance(pos1), range = object.collisionScale + trappedIn.collisionScale + nearestEnemyPush.collisionScale * 2;
if (distance <= range) {
this.nearestPushSpike = object;
}
}
});
}
if (this.client.isOwner) {
GameUI_default.updateSpikeDamage(actualSpikeDamage), GameUI_default.updatePotentialDamage(`${this.potentialDamage}, ${this.primaryDamage}`),
GameUI_default.updateDangerState(`${this.detectedDangerEnemy}, ${this.detectedEnemy}, ${this.dangerWithoutSoldier}, ${this.rangedBowInsta}`),
GameUI_default.updateCollideSpike(this.collidingSpike);
}
}
}
const EnemyManager_default = EnemyManager;
class LeaderboardManager {
client;
list=new Set;
constructor(client) {
this.client = client;
}
updatePlayer(id, nickname, gold) {
let owner = this.client.PlayerManager.playerData.get(id) || this.client.PlayerManager.createPlayer({
id: id,
nickname: nickname
});
this.list.add(owner);
}
update(data) {
this.list.clear();
for (let i = 0; i < data.length; i += 3) {
let id = data[i + 0], nickname = data[i + 1], gold = data[i + 2];
this.updatePlayer(id, nickname, gold);
}
}
}
const LeaderboardManager_default = LeaderboardManager;
const HatPredictor = new class {
transitions=new Map;
train(history) {
this.transitions.clear();
for (let i = 0; i < history.length - 1; i++) {
let currentHat = history[i], nextHat = history[i + 1];
if (!this.transitions.has(currentHat)) {
this.transitions.set(currentHat, new Map);
}
let nextMap = this.transitions.get(currentHat);
nextMap.set(nextHat, (nextMap.get(nextHat) || 0) + 1);
}
}
predict(currentHat) {
if (!this.transitions.has(currentHat)) {
return null;
}
let nextMap = this.transitions.get(currentHat), maxCount = 0, predictedHat = null;
for (let [hat, count] of nextMap) {
if (count > maxCount) {
maxCount = count, predictedHat = hat;
}
}
return predictedHat;
}
}, HatPredictor_default = HatPredictor;
class Player extends Entity_default {
currentItem=-1;
clanName=null;
isLeader=!1;
prevNickname="";
nickname="unknown";
skinID=0;
scale=35;
storeData=[ 0, 0 ];
hatID=0;
prevHat=0;
accessoryID=0;
usesTurret=!1;
previousHealth=100;
currentHealth=100;
tempHealth=100;
maxHealth=100;
primaryReloadTickCount=0;
nextDamageTick=0;
globalInventory={};
weapon={};
oldWeapon=[ 0, null ];
variant={};
reload=[ {}, {}, {} ];
objects=new Set;
newlyCreated=!0;
usingBoost=!1;
isTrapped=!1;
usesTank=!1;
trappedIn=null;
trappedInPrev=null;
isFullyUpgraded=!1;
potentialDamage=0;
primaryDamage=0;
spikeDamage=0;
dangerList=[];
danger=0;
prevDanger=0;
hatHistory=[];
futureHat=0;
shameActive=!1;
shameTimer=0;
shameCount=0;
receivedDamage=null;
bullTick=0;
poisonCount=0;
isDmgOverTime=!1;
tickCount=0;
damageTick=0;
canPlaceSpikePrev=!1;
canPlaceSpike=!1;
velocityTicking=!1;
reverseInsta=!1;
rangedBowInsta=!1;
spikeSyncThreat=!1;
tickDamage=100;
stackedDamage=0;
damages=[];
prevSeenBefore=!1;
seenBefore=!1;
isPlayer=!0;
lastAttacked=0;
constructor(client) {
super(client);
}
justAppeared() {
return !this.prevSeenBefore && this.seenBefore;
}
wasTrapped() {
return this.trappedIn === null && this.trappedInPrev !== null;
}
addFound(projectile) {
projectile.owner = this, this.client.ProjectileManager.foundProjectile(projectile);
}
resetReload() {
let {primary: primary, secondary: secondary} = this.weapon, primarySpeed = this.getWeaponSpeed(primary), secondarySpeed = this.getWeaponSpeed(secondary), reload = this.reload;
reload[0].previous = primarySpeed, reload[0].current = primarySpeed, reload[0].max = primarySpeed,
reload[1].previous = secondarySpeed, reload[1].current = secondarySpeed, reload[1].max = secondarySpeed,
reload[2].previous = 23, reload[2].current = 23, reload[2].max = 23;
}
resetGlobalInventory() {
this.globalInventory[0] = null, this.globalInventory[1] = null, this.globalInventory[2] = null,
this.globalInventory[3] = null, this.globalInventory[4] = null, this.globalInventory[5] = null,
this.globalInventory[6] = null, this.globalInventory[7] = null, this.globalInventory[8] = null,
this.globalInventory[9] = null;
}
init() {
this.weapon.current = 0, this.weapon.oldCurrent = 0, this.weapon.primary = null,
this.weapon.secondary = null, this.oldWeapon[0] = null, this.oldWeapon[1] = null,
this.variant.current = 0, this.variant.primary = 0, this.variant.secondary = 0,
this.resetReload(), this.resetGlobalInventory(), this.newlyCreated = !0, this.usingBoost = !1,
this.isFullyUpgraded = !1;
}
get canUseTurret() {
return this.hatID !== 22;
}
get canPlaceSpikeObject() {
return !this.canPlaceSpikePrev && this.canPlaceSpike || this.speed >= 10 && this.canPlaceSpike;
}
isBullTickTime(adjust = 0) {
return (this.tickCount - this.bullTick - adjust) % 9 === 0;
}
update(id, x, y, angle, currentItem, currentWeapon, weaponVariant, clanName, isLeader, hatID, accessoryID) {
if (this.prevSeenBefore = this.seenBefore, this.seenBefore = !0, this.justAppeared()) {
this.resetReload();
}
this.tickCount += 1, this.id = id, this.pos.previous.setVec(this.pos.current),
this.pos.current.setXY(x, y), this.setFuturePosition(), this.angle = angle,
this.currentItem = currentItem, this.weapon.oldCurrent = this.weapon.current;
let weaponType = DataHandler_default.getWeapon(this.weapon.current).itemType;
if (this.oldWeapon[weaponType] = this.weapon.current, this.weapon.current = currentWeapon,
this.variant.current = weaponVariant, this.clanName = clanName, this.isLeader = !!isLeader,
this.prevHat = this.hatID, this.hatID = hatID, this.prevHat === 7 && hatID === 53) {
this.usesTurret = !0;
}
if (this.hatHistory.push(hatID), this.hatHistory.length > 4) {
this.hatHistory.shift();
}
if (HatPredictor_default.train(this.hatHistory), this.futureHat = HatPredictor_default.predict(hatID),
this.usesTurret && hatID === 7) {
this.futureHat = 53;
}
if (this.accessoryID = accessoryID, this.storeData[0] = hatID, this.storeData[1] = accessoryID,
this.newlyCreated = !1, this.potentialDamage = 0, this.primaryDamage = 0, this.spikeDamage = 0,
this.canPlaceSpikePrev = this.canPlaceSpike, this.canPlaceSpike = !1, this.velocityTicking = !1,
this.reverseInsta = !1, this.rangedBowInsta = !1, this.spikeSyncThreat = !1,
this.predictItems(), this.predictWeapons(), this.updateReloads(), this.isDmgOverTime = !1,
this.hatID === 45 && !this.shameActive) {
this.shameActive = !0, this.shameTimer = 0, this.shameCount = 8;
}
let {PlayerManager: PlayerManager, myPlayer: myPlayer} = this.client;
if (this.shameTimer += PlayerManager.step, this.shameTimer >= 3e4 && this.shameActive) {
this.shameActive = !1, this.shameTimer = 0, this.shameCount = 0;
}
if (this.isBullTickTime()) {
if (this.shameCount > 0) {
this.futureHat = 7;
}
this.poisonCount = Math.max(this.poisonCount - 1, 0);
}
let reload = this.reload;
reload[0].previous = reload[0].current, reload[1].previous = reload[1].current,
reload[2].previous = reload[2].current;
}
updateHealth(health) {
if (this.previousHealth = this.currentHealth, this.currentHealth = health, this.tempHealth = health,
this.shameActive) {
return;
}
let {myPlayer: myPlayer, PlayerManager: PlayerManager} = this.client, isEnemy = myPlayer.isEnemyByID(this.id), {currentHealth: currentHealth, previousHealth: previousHealth} = this, difference = Math.abs(currentHealth - previousHealth);
if (this.currentHealth < this.previousHealth) {
if (this.receivedDamage = Date.now(), this.damageTick !== this.tickCount + 1) {
this.tickDamage = 0, this.stackedDamage = 0, this.damages.length = 0;
}
if (this.tickDamage += difference, this.damageTick = this.tickCount + 1, isEnemy) {
PlayerManager.lastEnemyReceivedDamage[0] = this.id, PlayerManager.lastEnemyReceivedDamage[1] = Math.round(difference);
}
} else if (this.receivedDamage !== null) {
let step = Date.now() - this.receivedDamage;
if (this.receivedDamage = null, step <= 120) {
this.shameCount += 1;
} else {
this.shameCount -= 2;
}
this.shameCount = clamp(this.shameCount, 0, 7);
}
let isDmgOverTime = (difference === 5 || difference === 2 || difference === 4) && currentHealth < previousHealth;
if (this.isDmgOverTime = isDmgOverTime, isDmgOverTime) {
this.bullTick = this.tickCount;
}
}
predictItems() {
if (this.currentItem === -1) {
return;
}
let item = Items[this.currentItem];
this.globalInventory[item.itemType] = this.currentItem;
}
increaseReload(reload) {
if (reload.previous = reload.current, reload.current += 1, reload.current > reload.max) {
reload.current = reload.max;
}
}
updateMaxReload(reload, weaponID) {
let speed = this.getWeaponSpeed(weaponID);
reload.current = speed, reload.max = speed;
}
resetCurrentReload(reload) {
reload.current = 0;
}
updateTurretReload() {
let reload = this.reload[2];
if (this.increaseReload(reload), this.hatID !== 53) {
return;
}
let {ProjectileManager: ProjectileManager} = this.client, speed = Projectiles[1].speed, list = ProjectileManager.projectiles.get(speed);
if (list === void 0) {
return;
}
let current = this.pos.current;
for (let i = 0; i < list.length; i++) {
let projectile = list[i];
if (current.distance(projectile.pos.current) < 5) {
this.addFound(projectile), this.resetCurrentReload(reload), removeFast(list, i);
break;
}
}
}
updateReloads() {
if (this.updateTurretReload(), this.currentItem !== -1) {
return;
}
let weapon = DataHandler_default.getWeapon(this.weapon.current), reload = this.reload[weapon.itemType];
if (this.increaseReload(reload), "projectile" in weapon) {
let {ProjectileManager: ProjectileManager} = this.client, speedMult = this.getWeaponSpeedMult(), type = weapon.projectile, speed = Projectiles[type].speed * speedMult, list = ProjectileManager.projectiles.get(speed);
if (list === void 0) {
return;
}
let current = this.pos.current;
for (let i = 0; i < list.length; i++) {
let projectile = list[i];
if (current.distance(projectile.pos.current) < 5 && this.angle === projectile.angle) {
this.addFound(projectile), this.updateMaxReload(reload, weapon.id), this.resetCurrentReload(reload),
removeFast(list, i);
break;
}
}
}
}
handleObjectPlacement(object) {
this.objects.add(object);
let {myPlayer: myPlayer, ObjectManager: ObjectManager} = this.client, item = Items[object.type];
if (object.seenPlacement) {
if (object.type === 17) {
ObjectManager.resetTurret(object.id);
} else if (object.type === 16 && !this.newlyCreated) {
this.usingBoost = !0;
}
this.updateInventory(object.type);
}
if (myPlayer.isMyPlayerByID(this.id) && item.itemType === 5) {
myPlayer.totalGoldAmount += item.pps;
}
}
handleObjectDeletion(object) {
this.objects.delete(object);
let {myPlayer: myPlayer} = this.client, item = Items[object.type];
if (myPlayer.isMyPlayerByID(this.id) && item.itemType === 5) {
myPlayer.totalGoldAmount -= item.pps;
}
}
updateInventory(type) {
let item = Items[type], inventoryID = this.globalInventory[item.itemType];
if (inventoryID === null || item.age > Items[inventoryID].age) {
this.globalInventory[item.itemType] = item.id;
}
}
detectFullUpgrade() {
let inventory = this.globalInventory, primary = inventory[0], secondary = inventory[1], spike = inventory[4];
if (primary && secondary) {
if ("isUpgrade" in DataHandler_default.getWeapon(primary) && "isUpgrade" in DataHandler_default.getWeapon(secondary)) {
return !0;
}
}
return primary && DataHandler_default.getWeapon(primary).age === 8 || secondary && DataHandler_default.getWeapon(secondary).age === 9 || spike && Items[spike].age === 9 || inventory[5] === 12 || inventory[9] === 20;
}
predictPrimary(id) {
if (id === 11) {
return 4;
}
return 5;
}
predictSecondary(id) {
if (id === 0) {
return null;
}
if (id === 2 || id === 4) {
return 10;
}
return 15;
}
predictWeapons() {
let {current: current, oldCurrent: oldCurrent} = this.weapon, weapon = DataHandler_default.getWeapon(current), type = WeaponTypeString[weapon.itemType], reload = this.reload[weapon.itemType], oldWeapon = this.oldWeapon[weapon.itemType], upgradedWeapon = oldWeapon === null || current !== oldWeapon && weapon.itemType === DataHandler_default.getWeapon(oldWeapon).itemType;
if (reload.max === -1 || upgradedWeapon) {
this.updateMaxReload(reload, weapon.id);
}
this.globalInventory[weapon.itemType] = current, this.variant[type] = this.variant.current;
let currentType = this.weapon[type];
if (currentType === null || weapon.age > DataHandler_default.getWeapon(currentType).age) {
this.weapon[type] = current;
}
let primary = this.globalInventory[0], secondary = this.globalInventory[1], notPrimaryUpgrade = primary === null || !("isUpgrade" in DataHandler_default.getWeapon(primary)), notSecondaryUpgrade = secondary === null || !("isUpgrade" in DataHandler_default.getWeapon(secondary));
if (DataHandler_default.isSecondary(current) && notPrimaryUpgrade) {
let predicted = this.predictPrimary(current);
if (primary === null || DataHandler_default.getWeapon(predicted).upgradeType === DataHandler_default.getWeapon(primary).upgradeType) {
this.weapon.primary = predicted;
}
} else if (DataHandler_default.isPrimary(current) && notSecondaryUpgrade) {
let predicted = this.predictSecondary(current);
if (predicted === null || secondary === null || DataHandler_default.getWeapon(predicted).upgradeType === DataHandler_default.getWeapon(secondary).upgradeType) {
this.weapon.secondary = predicted;
}
}
if (this.isFullyUpgraded = this.detectFullUpgrade(), this.isFullyUpgraded) {
if (primary !== null) {
this.weapon.primary = primary;
}
if (secondary !== null) {
this.weapon.secondary = secondary;
}
}
if (this.weapon.primary === void 0) {
throw Error("Primary is 'undefined', value must be at least 'null' or 'number'");
}
if (this.weapon.secondary === void 0) {
throw Error("Secondary is 'undefined', value must be at least 'null' or 'number'");
}
}
getWeaponVariant(id) {
let type = DataHandler_default.getWeapon(id || 0).itemType, variant = this.variant[WeaponTypeString[type]];
return {
current: variant,
next: Math.min(variant + 1, 3)
};
}
getBuildingDamage(id, isTank = !1) {
let weapon = DataHandler_default.getWeapon(id), variant = WeaponVariants[this.getWeaponVariant(id).current], damage = weapon.damage * variant.val;
if ("sDmg" in weapon) {
damage *= weapon.sDmg;
}
let hat = Hats[isTank ? 40 : this.hatID];
if ("bDmg" in hat) {
damage *= hat.bDmg;
}
return damage;
}
getMaxBuildingDamage(object, isTank = !0) {
let {primary: primary, secondary: secondary} = this.weapon;
if (DataHandler_default.isMelee(secondary) && secondary === 10 && this.isReloaded(1, 1)) {
if (this.collidingSimple(object, DataHandler_default.getWeapon(secondary).range + object.hitScale)) {
return this.getBuildingDamage(secondary, isTank);
}
}
if (DataHandler_default.isMelee(primary) && this.isReloaded(0, 1)) {
if (this.collidingSimple(object, DataHandler_default.getWeapon(primary).range + object.hitScale)) {
return this.getBuildingDamage(primary, isTank);
}
}
return null;
}
canDealPoison(weaponID) {
let isRuby = this.getWeaponVariant(weaponID).current === 3, hasPlague = this.hatID === 21;
return {
isAble: isRuby || hasPlague,
count: isRuby ? 5 : hasPlague ? 6 : 0
};
}
getWeaponSpeed(id, hat = this.hatID) {
if (id === null) {
return -1;
}
let reloadSpeed = hat === 20 ? Hats[hat].atkSpd : 1, speed = DataHandler_default.getWeapon(id).speed * reloadSpeed;
return Math.ceil(speed / this.client.SocketManager.TICK);
}
getWeaponSpeedMult() {
if (this.hatID === 1) {
return Hats[this.hatID].aMlt;
}
return 1;
}
getMaxWeaponRange() {
let {primary: primary, secondary: secondary} = this.weapon, primaryRange = DataHandler_default.getWeapon(primary).range;
if (DataHandler_default.isMelee(secondary)) {
let range = DataHandler_default.getWeapon(secondary).range;
if (range > primaryRange) {
return range;
}
}
return primaryRange;
}
getWeaponRange(weaponID) {
if (weaponID === null) {
return 0;
}
let range = DataHandler_default.getWeapon(weaponID).range;
if (DataHandler_default.isMelee(weaponID)) {
return range + this.hitScale;
}
return range + this.collisionScale;
}
getMaxWeaponDamage(id, lookingShield, addBull = !0) {
if (DataHandler_default.isMelee(id)) {
let bull = Hats[7], variant = this.getWeaponVariant(id).current, damage = DataHandler_default.getWeapon(id).damage;
if (addBull) {
damage *= bull.dmgMultO;
}
if (damage *= WeaponVariants[variant].val, lookingShield) {
damage *= DataHandler_default.getWeapon(11).shield;
}
return damage;
} else if (DataHandler_default.isShootable(id) && !lookingShield) {
return DataHandler_default.getProjectile(id).damage;
}
return 0;
}
getMaxKnockback() {
let knockback = 60, {primary: primary, secondary: secondary} = this.weapon;
if (primary != null) {
knockback += DataHandler_default.getWeapon(primary).knockback;
}
if (secondary != null) {
knockback += DataHandler_default.getWeapon(secondary).knockback;
}
return knockback;
}
getPrimaryKnockback(target) {
let {primary: primary} = this.weapon;
if (primary !== null && this.isReloaded(0, 1)) {
let {range: range, knockback: knockback} = DataHandler_default.getWeapon(primary);
if (this.collidingEntity(target, range)) {
return knockback;
}
}
return 0;
}
getActualMaxKnockback(target) {
let output = 0, {primary: primary, secondary: secondary} = this.weapon, hitScale = target.hitScale;
if (primary !== null && this.isReloaded(0, 1)) {
let {range: range, knockback: knockback} = DataHandler_default.getWeapon(primary);
if (this.collidingEntity(target, range + hitScale)) {
output += knockback;
}
}
if (secondary !== null && this.isReloaded(1, 1)) {
let {range: range, knockback: knockback} = DataHandler_default.getWeapon(secondary);
if (this.collidingEntity(target, range + hitScale)) {
output += knockback;
}
}
if (this.isReloaded(2, 1)) {
if (this.collidingEntity(target, 700 + hitScale)) {
output += 60;
}
}
return output;
}
getItemPlaceScale(itemID) {
let item = Items[itemID];
return this.scale + item.scale + item.placeOffset;
}
isReloaded(type, tick) {
let reload = this.reload[type].current, max = this.reload[type].max - tick;
return reload >= max;
}
atExact(type, tick) {
let {current: current, max: max} = this.reload[type];
return current === max - tick;
}
isEmptyReload(type) {
return this.reload[type].current === 0;
}
detectSpikeInsta() {
let {myPlayer: myPlayer, ObjectManager: ObjectManager} = this.client, spikeID = this.globalInventory[4] || 9, placeLength = this.getItemPlaceScale(spikeID), pos1 = this.pos.current, pos2 = myPlayer.pos.current, angleToMyPlayer = pos1.angle(pos2), spike = Items[spikeID], range = this.collisionScale + spike.scale, straightSpikePos = pos1.addDirection(angleToMyPlayer, placeLength);
if (pos2.distance(straightSpikePos) > range) {
return 0;
}
myPlayer.trappedIn !== null && myPlayer.trappedIn.canBeDestroyed && myPlayer.trappedIn.id;
let angles = ObjectManager.getBestPlacementAngles({
position: pos1,
id: spikeID,
targetAngle: angleToMyPlayer,
ignoreID: null,
preplace: !1,
reduce: !1,
fill: !1
});
for (let angle of angles) {
let spikePos = pos1.addDirection(angle, placeLength);
if (pos2.distance(spikePos) <= range) {
return spike.damage;
}
}
return 0;
}
canPossiblyInstakill() {
let {PlayerManager: PlayerManager, myPlayer: myPlayer} = this.client, lookingShield = PlayerManager.lookingShield(myPlayer, this), {primary: primary, secondary: secondary} = this.weapon, primaryDamage = this.getMaxWeaponDamage(primary, lookingShield), secondaryDamage = this.getMaxWeaponDamage(secondary, lookingShield), addRange = this.isTrapped ? 20 : 115, boostRange = this.usingBoost && !this.isTrapped ? 430 : addRange, primaryRange = this.getWeaponRange(primary) + boostRange, secondaryRange = this.getWeaponRange(secondary) + addRange, turretRange = 700 + addRange, primaryReloaded = this.isReloaded(0, 1), primaryVariant = this.getWeaponVariant(primary).current, isDiamondPolearm = primary === 5 && primaryVariant >= 2, collidingPrimary = myPlayer.collidingEntity(this, primaryRange), collidingSecondary = myPlayer.collidingEntity(this, DataHandler_default.isShootable(secondary) ? primaryRange : secondaryRange), collidingTurret = myPlayer.collidingEntity(this, turretRange), spikeSyncDamage = 0, includeTurret = !1;
if (collidingPrimary) {
if (primaryReloaded) {
this.potentialDamage += primaryDamage, this.primaryDamage = primaryDamage, spikeSyncDamage += primaryDamage;
}
includeTurret = !0;
}
if (collidingSecondary) {
if (this.isReloaded(1, 1)) {
this.potentialDamage += secondaryDamage;
}
if (DataHandler_default.isMelee(secondary)) {
includeTurret = !0;
}
}
if (this.isReloaded(2, 1) && includeTurret && !lookingShield) {
this.potentialDamage += 25;
}
if (collidingPrimary && collidingTurret && this.isEmptyReload(2) && primaryReloaded && isDiamondPolearm) {
this.velocityTicking = !0;
}
if (collidingPrimary && collidingSecondary && collidingTurret && this.isEmptyReload(1) && this.isEmptyReload(2) && primaryReloaded) {
this.reverseInsta = !0;
}
let pos1 = this.pos.current, pos2 = myPlayer.pos.current, distance = pos1.distance(pos2), angle = pos1.angle(pos2), offset = Math.asin(2 * myPlayer.scale / (2 * distance)), lookingAt = getAngleDist(angle, this.angle) <= offset, {current: current, oldCurrent: oldCurrent} = this.weapon, bowDetect = current === 9 && oldCurrent !== 9 || current === 12 && oldCurrent === 9 || current === 15 && oldCurrent === 12;
if (distance > 300 && lookingAt && bowDetect) {
this.rangedBowInsta = !0;
}
let spikeDamage = this.detectSpikeInsta();
if (spikeDamage !== 0) {
if (this.canPlaceSpike = !0, this.spikeDamage = spikeDamage, spikeSyncDamage += spikeDamage,
spikeSyncDamage >= 100) {
this.spikeSyncThreat = !0;
}
}
let soldierDefense = Hats[6].dmgMult;
if (this.potentialDamage * soldierDefense >= myPlayer.currentHealth) {
return 3;
}
let soldierMult = myPlayer.hatID === 6 ? soldierDefense : 1;
if (this.potentialDamage * soldierMult >= myPlayer.currentHealth) {
return 2;
}
return 0;
}
}
const Player_default = Player;
const resizeEvent = new Event("resize"), ZoomHandler = new class {
scale={
Default: {
w: 1920,
h: 1080
},
current: {
w: 1920,
h: 1080
},
smooth: {
w: Hooker_default.linker(1920),
h: Hooker_default.linker(1080)
}
};
getScale() {
return Math.max(window.innerWidth / this.scale.Default.w, window.innerHeight / this.scale.Default.h) * 1;
}
tempScale=1;
handler(event) {
if (!(event.target instanceof HTMLCanvasElement) || event.ctrlKey || event.shiftKey || event.altKey || isActiveInput()) {
return;
}
let {Default: Default, current: current} = this.scale;
if (event.deltaY < 0) {
this.tempScale *= 1.1;
} else {
this.tempScale /= 1.1;
}
this.tempScale = clamp(this.tempScale, .1, 22);
let zoom = this.tempScale;
current.w = Default.w * zoom, current.h = Default.h * zoom;
}
renderStart=Date.now();
smoothUpdate() {
let {current: current, smooth: smooth} = this.scale, now = Date.now(), delta = now - this.renderStart;
this.renderStart = now;
let dt = delta / 1e3, blend = .4 * (1 - Math.exp(-10 * dt));
smooth.w[0] = lerp(smooth.w[0], current.w, blend), smooth.h[0] = lerp(smooth.h[0], current.h, blend),
window.dispatchEvent(resizeEvent);
}
}, ZoomHandler_default = ZoomHandler;
const renderText = (ctx, text, size = 25, posx = 10, posy = 9, fill = "#eaeaea", alpha = .6) => {
ctx.save(), ctx.font = `700 ${size}px sans-serif`, ctx.textAlign = "left", ctx.textBaseline = "top",
ctx.setTransform(1, 0, 0, 1, 0, 0);
let scale = ZoomHandler_default.getScale();
ctx.scale(scale, scale), ctx.fillStyle = fill, ctx.strokeStyle = "#1f2029",
ctx.lineWidth = 8, ctx.globalAlpha = alpha, ctx.letterSpacing = "6px", ctx.lineJoin = "round",
ctx.strokeText(text, posx, posy), ctx.fillText(text, posx, posy), ctx.restore();
}, Renderer = new class {
renderObjects=[];
totalTimes=[];
lastLogTime=performance.now();
preRender() {
ZoomHandler_default.smoothUpdate();
}
postRender() {
let now = performance.now();
while (this.totalTimes.length > 0 && this.totalTimes[0] <= now - 1e3) {
this.totalTimes.shift();
}
this.totalTimes.push(now);
let fps = this.totalTimes.length;
if (now - this.lastLogTime >= 1e3) {
GameUI_default.updateFPS(fps), this.lastLogTime = now;
}
let ctx = document.querySelector("#gameCanvas").getContext("2d");
// Titre, credit d origine (impose par la licence MIT de Glotus),
// puis la signature de cette version.
renderText(ctx, atob("R2xvdHVz") + " v" + Glotus.version);
renderText(ctx, "by Murka", 15, 15, 36);
renderText(ctx, "fixed by seldoom", 15, 15, 57, "#f5d951", .85);
}
mapPreRender(ctx) {
ctx.save(), ctx.globalAlpha = .6;
let width = ctx.canvas.width, height = ctx.canvas.height;
ctx.fillStyle = "#fff", ctx.fillRect(0, 0, width, Config_default.snowBiomeTop / Config_default.mapScale * height),
ctx.fillStyle = "#dbc666", ctx.fillRect(0, 12e3 / Config_default.mapScale * height, width, height),
ctx.fillStyle = "#91b2db";
let startY = (Config_default.mapScale / 2 - Config_default.riverWidth / 2) / Config_default.mapScale * height;
ctx.fillRect(0, startY, width, Config_default.riverWidth / Config_default.mapScale * height);
let {ModuleHandler: ModuleHandler, myPlayer: myPlayer} = client;
ctx.globalAlpha = 1;
let markSize = 8;
if (ModuleHandler.followPath) {
let pos = ModuleHandler.endTarget.copy().div(Config_default.mapScale).mult(width);
ctx.fillStyle = "#c2383d", ctx.beginPath(), ctx.arc(pos.x, pos.y, markSize, 0, 2 * Math.PI),
ctx.fill();
}
if (myPlayer.teleported) {
let pos = myPlayer.teleportPos.copy().div(Config_default.mapScale).mult(width);
ctx.fillStyle = "#d76edb", ctx.beginPath(), ctx.arc(pos.x, pos.y, markSize, 0, 2 * Math.PI),
ctx.fill();
}
ctx.fillStyle = Settings_default._notificationTracersColor;
let notifications = NotificationRenderer_default.notifications;
for (let notify of notifications) {
let x = notify.x / Config_default.mapScale * width, y = notify.y / Config_default.mapScale * width;
ctx.beginPath(), ctx.arc(x, y, markSize * 1.5, 0, 2 * Math.PI), ctx.fill();
}
ctx.restore();
}
drawNorthArrow(ctx, x, y, angle) {
ctx.save(), ctx.globalAlpha = .7, ctx.fillStyle = "#883131", ctx.translate(x, y),
ctx.rotate(angle + Math.PI / 2), ctx.beginPath(), ctx.moveTo(0, -17.5), ctx.lineTo(11.666666666666666, 17.5),
ctx.lineTo(0, 11.666666666666666), ctx.lineTo(-11.666666666666666, 17.5), ctx.closePath(),
ctx.fill(), ctx.restore();
}
rotation=0;
arrowPart=2 * Math.PI / 3;
drawTarget(ctx, entity) {
let len = entity.scale + 30;
this.rotation = (this.rotation + .01) % 6.28, ctx.save(), ctx.translate(-client.myPlayer.offset.x, -client.myPlayer.offset.y),
ctx.translate(entity.x, entity.y), ctx.rotate(this.rotation), this.drawNorthArrow(ctx, len * Math.cos(this.arrowPart * 1), len * Math.sin(this.arrowPart * 1), -1.04),
this.drawNorthArrow(ctx, len * Math.cos(this.arrowPart * 2), len * Math.sin(this.arrowPart * 2), 1.04),
this.drawNorthArrow(ctx, len * Math.cos(this.arrowPart * 3), len * Math.sin(this.arrowPart * 3), 3.14),
ctx.restore();
}
rect(ctx, pos, scale, color, lineWidth = 4, alpha = 1) {
ctx.save(), ctx.globalAlpha = alpha, ctx.strokeStyle = color, ctx.lineWidth = lineWidth,
ctx.beginPath(), ctx.translate(-client.myPlayer.offset.x, -client.myPlayer.offset.y),
ctx.translate(pos.x, pos.y), ctx.rect(-scale, -scale, scale * 2, scale * 2),
ctx.stroke(), ctx.closePath(), ctx.restore();
}
roundRect(ctx, x, y, w, h, r) {
if (w < 2 * r) {
r = w / 2;
}
if (h < 2 * r) {
r = h / 2;
}
if (r < 0) {
r = 0;
}
ctx.beginPath(), ctx.moveTo(x + r, y), ctx.arcTo(x + w, y, x + w, y + h, r),
ctx.arcTo(x + w, y + h, x, y + h, r), ctx.arcTo(x, y + h, x, y, r), ctx.arcTo(x, y, x + w, y, r),
ctx.closePath();
}
circle(ctx, x, y, radius, color, opacity = 1, lineWidth = 4) {
ctx.save(), ctx.globalAlpha = opacity, ctx.strokeStyle = color, ctx.lineWidth = lineWidth,
ctx.beginPath(), ctx.translate(-client.myPlayer.offset.x, -client.myPlayer.offset.y),
ctx.arc(x, y, radius, 0, 2 * Math.PI), ctx.stroke(), ctx.closePath(), ctx.restore();
}
fillCircle(ctx, x, y, radius, color, opacity = 1) {
ctx.save(), ctx.globalAlpha = opacity, ctx.fillStyle = color, ctx.beginPath(),
ctx.translate(-client.myPlayer.offset.x, -client.myPlayer.offset.y), ctx.arc(x, y, radius, 0, 2 * Math.PI),
ctx.fill(), ctx.closePath(), ctx.restore();
}
renderText(ctx, text, x, y, fontSize = 14, opacity = .5) {
ctx.save(), ctx.fillStyle = "#fff", ctx.strokeStyle = "#3d3f42", ctx.lineWidth = 8,
ctx.lineJoin = "round", ctx.textBaseline = "top", ctx.globalAlpha = opacity,
ctx.font = fontSize + "px Hammersmith One", ctx.translate(-client.myPlayer.offset.x, -client.myPlayer.offset.y),
ctx.strokeText(text, x, y), ctx.fillText(text, x, y), ctx.restore();
}
line(ctx, start, end, color, opacity = 1, lineWidth = 4) {
ctx.save(), ctx.translate(-client.myPlayer.offset.x, -client.myPlayer.offset.y),
ctx.globalAlpha = opacity, ctx.strokeStyle = color, ctx.lineCap = "round", ctx.lineWidth = lineWidth,
ctx.beginPath(), ctx.moveTo(start.x, start.y), ctx.lineTo(end.x, end.y), ctx.stroke(),
ctx.restore();
}
arrow(ctx, length, x, y, angle, color) {
ctx.save(), ctx.translate(-client.myPlayer.offset.x, -client.myPlayer.offset.y),
ctx.translate(x, y), ctx.rotate(Math.PI / 4), ctx.rotate(angle), ctx.globalAlpha = .75,
ctx.strokeStyle = color, ctx.lineCap = "round", ctx.lineWidth = 8, ctx.beginPath(),
ctx.moveTo(-length, -length), ctx.lineTo(length, -length), ctx.lineTo(length, length),
ctx.stroke(), ctx.restore();
}
cross(ctx, x, y, size, lineWidth, color) {
ctx.save(), ctx.globalAlpha = 1, ctx.lineWidth = lineWidth, ctx.strokeStyle = color,
ctx.translate(x - client.myPlayer.offset.x, y - client.myPlayer.offset.y);
let halfSize = size / 2;
ctx.beginPath(), ctx.moveTo(-halfSize, -halfSize), ctx.lineTo(halfSize, halfSize),
ctx.stroke(), ctx.beginPath(), ctx.moveTo(halfSize, -halfSize), ctx.lineTo(-halfSize, halfSize),
ctx.stroke(), ctx.restore();
}
getTracerColor(entity) {
if (entity instanceof Notify) {
return Settings_default._notificationTracersColor;
}
if (Settings_default._animalTracers && entity.isAI) {
return Settings_default._animalTracersColor;
}
if (Settings_default._teammateTracers && entity.isPlayer && client.myPlayer.isTeammateByID(entity.sid)) {
return Settings_default._teammateTracersColor;
}
if (Settings_default._enemyTracers && entity.isPlayer && client.myPlayer.isEnemyByID(entity.sid)) {
return Settings_default._enemyTracersColor;
}
return null;
}
renderTracer(ctx, entity, player) {
let color = this.getTracerColor(entity);
if (color === null) {
return;
}
let pos1 = new Vector_default(player.x, player.y), pos2 = new Vector_default(entity.x, entity.y), w = 8, distance = Math.min(125 + w * 2, pos1.distance(pos2) - w * 2), angle = pos1.angle(pos2), pos = pos1.addDirection(angle, distance);
this.arrow(ctx, w, pos.x, pos.y, angle, color);
}
renderDistance(ctx, entity, player) {
let pos1 = new Vector_default(player.x, player.y), pos2 = new Vector_default(entity.x, entity.y), entityTarget = client.PlayerManager.getEntity(entity.sid, !!entity.isPlayer);
if (entityTarget === null) {
return;
}
let pos3 = client.myPlayer.pos.current, pos4 = entityTarget.pos.current, distance = fixTo(pos3.distance(pos4), 2), center = pos1.addDirection(pos1.angle(pos2), pos1.distance(pos2) / 2);
this.renderText(ctx, `[${entity.sid}]: ${distance}`, center.x, center.y);
}
getMarkerColor(object) {
let id = object.owner?.sid;
if (typeof id !== "number") {
return null;
}
if (Settings_default._itemMarkers && client.myPlayer.isMyPlayerByID(id)) {
return Settings_default._itemMarkersColor;
}
if (Settings_default._teammateMarkers && client.myPlayer.isTeammateByID(id)) {
return Settings_default._teammateMarkersColor;
}
if (Settings_default._enemyMarkers && client.myPlayer.isEnemyByID(id)) {
return Settings_default._enemyMarkersColor;
}
return null;
}
renderMarker(ctx, object) {
let color = this.getMarkerColor(object);
if (color === null) {
return;
}
let x = object.x + object.xWiggle - client.myPlayer.offset.x, y = object.y + object.yWiggle - client.myPlayer.offset.y;
ctx.save(), ctx.strokeStyle = "#3b3b3b", ctx.lineWidth = 3, ctx.fillStyle = color,
ctx.beginPath(), ctx.arc(x, y, 9, 0, 2 * Math.PI), ctx.fill(), ctx.stroke(),
ctx.closePath(), ctx.restore();
}
barContainer(ctx, x, y, w, h, r = 8) {
ctx.fillStyle = "#3d3f42", this.roundRect(ctx, x, y, w, h, r), ctx.fill();
}
barContent(ctx, x, y, w, h, fill, color) {
let barPad = Config_default.barPad;
ctx.fillStyle = color, this.roundRect(ctx, x + barPad, y + barPad, (w - barPad * 2) * fill, h - barPad * 2, 7),
ctx.fill();
}
getNameY(target) {
let nameY = 34, height = 5;
if (target === client.myPlayer && Settings_default._weaponXPBar) {
nameY += height;
}
if (Settings_default._playerTurretReloadBar) {
nameY += height;
}
if (Settings_default._weaponReloadBar) {
nameY += height;
}
return nameY;
}
getContainerHeight(entity) {
let {barHeight: barHeight, barPad: barPad} = Config_default, height = barHeight;
if (entity.isPlayer) {
let smallBarHeight = barHeight - 4, player = client.PlayerManager.playerData.get(entity.sid);
if (player === void 0) {
return height;
}
if (player === client.myPlayer && Settings_default._weaponXPBar) {
height += smallBarHeight - barPad;
}
if (Settings_default._playerTurretReloadBar) {
height += smallBarHeight - barPad;
}
if (Settings_default._weaponReloadBar) {
height += barHeight - barPad;
}
}
return height;
}
renderBar(ctx, entity) {
let {barWidth: barWidth, barHeight: barHeight, barPad: barPad} = Config_default, smallBarHeight = barHeight - 4, totalWidth = barWidth + barPad, scale = entity.scale + 34, {myPlayer: myPlayer, PlayerManager: PlayerManager} = client, x = entity.x - myPlayer.offset.x - totalWidth, y = entity.y - myPlayer.offset.y + scale;
ctx.save();
let player = entity.isPlayer && PlayerManager.playerData.get(entity.sid), animal = entity.isAI && PlayerManager.animalData.get(entity.sid), height = 0;
if (player instanceof Player_default) {
let [primary, secondary, turret] = player.reload;
if (player === myPlayer && Settings_default._weaponXPBar) {
let weapon = DataHandler_default.getWeapon(myPlayer.weapon.current), current = WeaponVariants[myPlayer.getWeaponVariant(weapon.id).current].color, next = WeaponVariants[myPlayer.getWeaponVariant(weapon.id).next].color, XP = myPlayer.weaponXP[weapon.itemType];
this.barContainer(ctx, x, y, totalWidth * 2, smallBarHeight), this.barContent(ctx, x, y, totalWidth * 2, smallBarHeight, 1, current),
this.barContent(ctx, x, y, totalWidth * 2, smallBarHeight, clamp(XP.current / XP.max, 0, 1), next),
height += smallBarHeight - barPad;
}
if (Settings_default._playerTurretReloadBar) {
this.barContainer(ctx, x, y + height, totalWidth * 2, smallBarHeight), this.barContent(ctx, x, y + height, totalWidth * 2, smallBarHeight, turret.current / turret.max, Settings_default._playerTurretReloadBarColor),
height += smallBarHeight - barPad;
}
if (Settings_default._weaponReloadBar) {
this.barContainer(ctx, x, y + height, totalWidth * 2, barHeight), this.barContent(ctx, x, y + height, totalWidth + 2.25, barHeight, primary.current / primary.max, Settings_default._weaponReloadBarColor),
this.barContent(ctx, x + totalWidth - 2.25, y + height, totalWidth + 2.25, barHeight, secondary.current / secondary.max, Settings_default._weaponReloadBarColor),
height += barHeight - barPad;
}
}
let target = player || animal;
if (target) {
let container = getTargetValue(Glotus, "config");
setTargetValue(container, "nameY", this.getNameY(target));
let {currentHealth: currentHealth, maxHealth: maxHealth} = target, health = animal ? maxHealth : 100, color = PlayerManager.isEnemyTarget(myPlayer, target) ? "#cc5151" : "#8ecc51";
this.barContainer(ctx, x, y + height, totalWidth * 2, barHeight), this.barContent(ctx, x, y + height, totalWidth * 2, barHeight, currentHealth / health, color),
height += barHeight;
}
ctx.restore();
}
renderHP(ctx, entity) {
if (!Settings_default._renderHP) {
return;
}
let {barPad: barPad, nameY: nameY} = Config_default, containerHeight = this.getContainerHeight(entity), text = `HP ${Math.floor(entity.health)}/${entity.maxHealth}`, offset = entity.scale + nameY + barPad + containerHeight, {myPlayer: myPlayer} = client, x = entity.x - myPlayer.offset.x, y = entity.y - myPlayer.offset.y + offset;
if (entity.isPlayer && myPlayer.isMyPlayerByID(entity.sid)) {
text += ` ${myPlayer.shameCount}/8`;
}
ctx.save(), ctx.fillStyle = "#fff", ctx.strokeStyle = "#3d3f42", ctx.lineWidth = 8,
ctx.lineJoin = "round", ctx.textBaseline = "top", ctx.font = "19px Hammersmith One",
ctx.strokeText(text, x, y), ctx.fillText(text, x, y), ctx.restore();
}
circularBar(ctx, object, perc, angle, color, offset = 0) {
let x = object.x + object.xWiggle - client.myPlayer.offset.x, y = object.y + object.yWiggle - client.myPlayer.offset.y, height = Config_default.barHeight * .5, defaultScale = 10 + height / 2, scale = defaultScale + 1 + offset;
return ctx.save(), ctx.translate(x, y), ctx.rotate(angle), ctx.lineCap = "round",
ctx.strokeStyle = "#3b3b3b", ctx.lineWidth = height, ctx.beginPath(), ctx.arc(0, 0, scale, 0, perc * 2 * Math.PI),
ctx.stroke(), ctx.closePath(), ctx.strokeStyle = color, ctx.lineWidth = height / 3,
ctx.beginPath(), ctx.arc(0, 0, scale, 0, perc * 2 * Math.PI), ctx.stroke(),
ctx.closePath(), ctx.restore(), defaultScale - 3;
}
}, Renderer_default = Renderer;
const Animals = [ {
id: 0,
src: "cow_1",
hostile: !1,
killScore: 150,
health: 500,
weightM: .8,
speed: 95e-5,
turnSpeed: .001,
scale: 72,
drop: [ "food", 50 ]
}, {
id: 1,
src: "pig_1",
hostile: !1,
killScore: 200,
health: 800,
weightM: .6,
speed: 85e-5,
turnSpeed: .001,
scale: 72,
drop: [ "food", 80 ]
}, {
id: 2,
name: "Bull",
src: "bull_2",
hostile: !0,
dmg: 20,
killScore: 1e3,
health: 1800,
weightM: .5,
speed: 94e-5,
turnSpeed: 74e-5,
scale: 78,
viewRange: 800,
chargePlayer: !0,
drop: [ "food", 100 ]
}, {
id: 3,
name: "Bully",
src: "bull_1",
hostile: !0,
dmg: 20,
killScore: 2e3,
health: 2800,
weightM: .45,
speed: .001,
turnSpeed: 8e-4,
scale: 90,
viewRange: 900,
chargePlayer: !0,
drop: [ "food", 400 ]
}, {
id: 4,
name: "Wolf",
src: "wolf_1",
hostile: !0,
dmg: 8,
killScore: 500,
health: 300,
weightM: .45,
speed: .001,
turnSpeed: .002,
scale: 84,
viewRange: 800,
chargePlayer: !0,
drop: [ "food", 200 ]
}, {
id: 5,
name: "Quack",
src: "chicken_1",
hostile: !1,
dmg: 8,
killScore: 2e3,
noTrap: !0,
health: 300,
weightM: .2,
speed: .0018,
turnSpeed: .006,
scale: 70,
drop: [ "food", 100 ]
}, {
id: 6,
name: "MOOSTAFA",
nameScale: 50,
src: "enemy",
hostile: !0,
dontRun: !0,
fixedSpawn: !0,
spawnDelay: 6e4,
noTrap: !0,
colDmg: 100,
dmg: 40,
killScore: 8e3,
health: 18e3,
weightM: .4,
speed: 7e-4,
turnSpeed: .01,
scale: 80,
spriteMlt: 1.8,
leapForce: .9,
viewRange: 1e3,
hitRange: 210,
hitDelay: 1e3,
chargePlayer: !0,
drop: [ "food", 100 ]
}, {
id: 7,
name: "Treasure",
hostile: !0,
nameScale: 35,
src: "crate_1",
fixedSpawn: !0,
spawnDelay: 12e4,
colDmg: 200,
killScore: 5e3,
health: 2e4,
weightM: .1,
speed: 0,
turnSpeed: 0,
scale: 70,
spriteMlt: 1
}, {
id: 8,
name: "MOOFIE",
src: "wolf_2",
hostile: !0,
fixedSpawn: !0,
dontRun: !0,
hitScare: 4,
spawnDelay: 3e4,
noTrap: !0,
nameScale: 35,
dmg: 10,
colDmg: 100,
killScore: 3e3,
health: 7e3,
weightM: .45,
speed: .0015,
turnSpeed: .002,
scale: 90,
viewRange: 800,
chargePlayer: !0,
drop: [ "food", 1e3 ]
}, {
id: 9,
name: "💀MOOFIE",
src: "wolf_2",
hostile: !0,
fixedSpawn: !0,
dontRun: !0,
hitScare: 50,
spawnDelay: 6e4,
noTrap: !0,
nameScale: 35,
dmg: 12,
colDmg: 100,
killScore: 3e3,
health: 9e3,
weightM: .45,
speed: .0015,
turnSpeed: .0025,
scale: 94,
viewRange: 1440,
chargePlayer: !0,
drop: [ "food", 3e3 ],
minSpawnRange: .85,
maxSpawnRange: .9
}, {
id: 10,
name: "💀Wolf",
src: "wolf_1",
hostile: !0,
fixedSpawn: !0,
dontRun: !0,
hitScare: 50,
spawnDelay: 3e4,
dmg: 10,
killScore: 700,
health: 500,
weightM: .45,
speed: .00115,
turnSpeed: .0025,
scale: 88,
viewRange: 1440,
chargePlayer: !0,
drop: [ "food", 400 ],
minSpawnRange: .85,
maxSpawnRange: .9
}, {
id: 11,
name: "💀Bully",
src: "bull_1",
hostile: !0,
fixedSpawn: !0,
dontRun: !0,
hitScare: 50,
dmg: 20,
killScore: 5e3,
health: 5e3,
spawnDelay: 1e5,
weightM: .45,
speed: .00115,
turnSpeed: .0025,
scale: 94,
viewRange: 1440,
chargePlayer: !0,
drop: [ "food", 800 ],
minSpawnRange: .85,
maxSpawnRange: .9
} ], Animals_default = Animals;
const colors = [ [ "orange", "red" ], [ "aqua", "blue" ] ], EntityRenderer = new class {
start=Date.now();
step=0;
drawWeaponHitbox(ctx, player) {
if (!Settings_default._weaponHitbox) {
return;
}
let {myPlayer: myPlayer} = client, current = myPlayer.weapon.current;
if (DataHandler_default.isMelee(current)) {
let weapon = DataHandler_default.getWeapon(current);
Renderer_default.circle(ctx, player.x, player.y, weapon.range, "#f5cb42", .5, 1);
}
}
drawPlacement(ctx) {
if (!Settings_default._possiblePlacement) {
return;
}
let {myPlayer: myPlayer, ModuleHandler: ModuleHandler} = client, [type, angles] = ModuleHandler.placeAngles;
if (type === null || angles === null) {
return;
}
let id = myPlayer.getItemByType(type);
if (id === null) {
return;
}
let dist = myPlayer.getItemPlaceScale(id), item = Items[id];
for (let i = 0; i < angles.length; i++) {
let angle = angles[i], pos = myPlayer.pos.current.addDirection(angle, dist);
Renderer_default.circle(ctx, pos.x, pos.y, item.scale, "#80edf2", .4, 1);
}
}
drawEntityHP(ctx, entity) {
Renderer_default.renderBar(ctx, entity), Renderer_default.renderHP(ctx, entity);
}
drawHitScale(ctx, entity) {
if (!Settings_default._weaponHitbox) {
return;
}
let {PlayerManager: PlayerManager} = client, target = (entity.isPlayer ? PlayerManager.playerData : PlayerManager.animalData).get(entity.sid);
if (target !== void 0) {
Renderer_default.circle(ctx, entity.x, entity.y, target.hitScale, "#3f4ec4", .5, 1);
}
if (entity.isAI && entity.index === 6) {
let moostafa = Animals_default[6];
Renderer_default.circle(ctx, entity.x, entity.y, moostafa.hitRange, "#f5cb42", .5, 1);
}
}
drawDanger(ctx, entity) {
let {PlayerManager: PlayerManager} = client;
if (entity.isPlayer) {
let player = PlayerManager.playerData.get(entity.sid);
if (player !== void 0 && player.danger !== 0) {
let isBoost = Number(player.usingBoost), isDanger = Number(player.danger >= 3);
Renderer_default.fillCircle(ctx, entity.x, entity.y, player.scale, colors[isBoost][isDanger], .3);
}
}
if (entity.isAI) {
let animal = PlayerManager.animalData.get(entity.sid);
if (animal) {
let color = animal.isDanger ? "red" : "green";
Renderer_default.fillCircle(ctx, entity.x, entity.y, animal.attackRange, color, .3);
}
}
}
render(ctx, entity, player) {
let now = Date.now();
this.step = now - this.start, this.start = now;
let {myPlayer: myPlayer, EnemyManager: EnemyManager2, ModuleHandler: ModuleHandler, ObjectManager: ObjectManager, InputHandler: InputHandler} = client, isMyPlayer = entity === player;
if (isMyPlayer) {
let pos = new Vector_default(player.x, player.y);
if (Settings_default._displayPlayerAngle) {
Renderer_default.line(ctx, pos, pos.addDirection(client.myPlayer.angle, 70), "#e9adf0");
}
if (this.drawWeaponHitbox(ctx, player), this.drawPlacement(ctx), myPlayer.isTrapped) {
Renderer_default.fillCircle(ctx, pos.x, pos.y, 35, "yellow", .5);
}
let {pushPos: pushPos} = ModuleHandler.staticModules.autoPush, nearestPushSpike = client.EnemyManager.nearestPushSpike;
if (pushPos !== null && nearestPushSpike !== null) {
Renderer_default.line(ctx, pos, pushPos, "white", .6, 1), Renderer_default.line(ctx, pushPos, nearestPushSpike.pos.current, "white", .6, 1);
}
}
if (this.drawEntityHP(ctx, entity), Settings_default._collisionHitbox) {
Renderer_default.circle(ctx, entity.x, entity.y, entity.scale, "#c7fff2", .5, 1);
}
if (!isMyPlayer) {
this.drawHitScale(ctx, entity), Renderer_default.renderTracer(ctx, entity, player),
Renderer_default.renderDistance(ctx, entity, player);
let nearestEnemyToNearestEnemy = EnemyManager2.nearestEnemyToNearestEnemy;
if (nearestEnemyToNearestEnemy !== null && !entity.isAI && entity.sid === nearestEnemyToNearestEnemy.id) {
Renderer_default.fillCircle(ctx, entity.x, entity.y, 35, "#48f072", .5);
} else {
this.drawDanger(ctx, entity);
}
let spikeCollider = EnemyManager2.enemySpikeCollider;
if (spikeCollider && !entity.isAI && entity.sid === spikeCollider.id) {
Renderer_default.fillCircle(ctx, entity.x, entity.y, 10, "#691313");
}
}
if (isMyPlayer) {
NotificationRenderer_default.render(ctx, player);
}
let instakillTarget = InputHandler.instakillTarget;
if (entity.isPlayer && instakillTarget !== null && entity.sid === instakillTarget.id) {
Renderer_default.drawTarget(ctx, entity);
let {bowInsta: bowInsta} = ModuleHandler.staticModules;
if (bowInsta.active) {
Renderer_default.circle(ctx, entity.x, entity.y, bowInsta.distMin, "#eda0ee", .4, 1),
Renderer_default.circle(ctx, entity.x, entity.y, bowInsta.distMax, "#eda0ee", .4, 1);
}
}
let {target: velTickTarget, minKB: minKB, maxKB: maxKB} = ModuleHandler.staticModules.velocityTick;
if (entity.isPlayer && velTickTarget !== null && entity.sid === velTickTarget.id) {
let diff = Math.abs(maxKB - minKB), length = minKB + (maxKB - minKB) / 2, angle = getAngle(entity.x, entity.y, player.x, player.y), posX = entity.x + Math.cos(angle) * length, posY = entity.y + Math.sin(angle) * length;
Renderer_default.circle(ctx, posX, posY, diff, "#e25176", .5, 1);
}
}
}, EntityRenderer_default = EntityRenderer;
class Notify {
x;
y;
timeout={
value: 0,
max: 2e3
};
constructor(x, y) {
this.x = x, this.y = y;
}
animate() {
let {value: value, max: max} = this.timeout;
if (value >= max) {
NotificationRenderer.remove(this);
return;
}
this.timeout.value += EntityRenderer_default.step;
}
render(ctx, player) {
this.animate(), Renderer_default.renderTracer(ctx, this, player);
}
}
const NotificationRenderer = new class {
notifications=new Set;
remove(notify) {
this.notifications.delete(notify);
}
add(object) {
let {x: x, y: y} = object.pos.current, notify = new Notify(x, y);
this.notifications.add(notify);
}
render(ctx, player) {
for (let notification of this.notifications) {
notification.render(ctx, player);
}
}
}, NotificationRenderer_default = NotificationRenderer;
class SpatialHashGrid2D {
cellSize=0;
grid=new Map;
constructor(cellSize) {
this.cellSize = cellSize;
}
_getKey(x, y) {
return x << 16 | y;
}
clear() {
this.grid.clear();
}
insert(x, y, radius, objectId) {
let startX = (x - radius) / this.cellSize | 0, startY = (y - radius) / this.cellSize | 0, endX = (x + radius) / this.cellSize | 0, endY = (y + radius) / this.cellSize | 0;
for (let i = startX; i <= endX; i++) {
for (let j = startY; j <= endY; j++) {
let key = this._getKey(i, j);
if (!this.grid.has(key)) {
this.grid.set(key, new Set);
}
this.grid.get(key).add(objectId);
}
}
}
query(x, y, search = 1, callback) {
let cellX = x / this.cellSize | 0, cellY = y / this.cellSize | 0, candidates = new Set, callbackSuccess = !1;
outerLoop: for (let i = -search; i <= search; i++) {
for (let j = -search; j <= search; j++) {
let key = this._getKey(cellX + i, cellY + j);
if (this.grid.has(key)) {
for (let objectId of this.grid.get(key)) {
if (!candidates.has(objectId)) {
if (candidates.add(objectId), callback(objectId)) {
callbackSuccess = !0;
break outerLoop;
}
}
}
}
}
}
return callbackSuccess;
}
queryFull(x, y, search = 1) {
let cellX = x / this.cellSize | 0, cellY = y / this.cellSize | 0, candidates = new Set;
for (let i = -search; i <= search; i++) {
for (let j = -search; j <= search; j++) {
let key = this._getKey(cellX + i, cellY + j);
if (this.grid.has(key)) {
for (let objectId of this.grid.get(key)) {
candidates.add(objectId);
}
}
}
}
return Array.from(candidates);
}
remove(x, y, radius, objectId) {
let startX = (x - radius) / this.cellSize | 0, startY = (y - radius) / this.cellSize | 0, endX = (x + radius) / this.cellSize | 0, endY = (y + radius) / this.cellSize | 0;
for (let i = startX; i <= endX; i++) {
for (let j = startY; j <= endY; j++) {
let key = this._getKey(i, j);
if (this.grid.has(key)) {
let cell = this.grid.get(key);
if (cell.delete(objectId), cell.size === 0) {
this.grid.delete(key);
}
}
}
}
}
}
class Sorting {
static byDistance(target, typeA, typeB) {
return (a, b) => {
let dist1 = target.position[typeA].distanceDefault(a.position[typeB]), dist2 = target.position[typeA].distanceDefault(b.position[typeB]);
return dist1 - dist2;
};
}
static byAngleDistance(angle) {
return (a, b) => getAngleDist(a, angle) - getAngleDist(b, angle);
}
static byDanger(a, b) {
return b.danger - a.danger;
}
}
const Sorting_default = Sorting;
class ObjectManager {
objects=new Map;
grid2D=new SpatialHashGrid2D(100);
reloadingTurrets=new Map;
attackedObjects=new Map;
client;
constructor(client2) {
this.client = client2;
}
insertObject(object) {
if (this.grid2D.insert(object.pos.current.x, object.pos.current.y, object.collisionScale, object.id),
this.objects.set(object.id, object), object instanceof PlayerObject) {
let {PlayerManager: PlayerManager, myPlayer: myPlayer} = this.client, owner = PlayerManager.playerData.get(object.ownerID) || PlayerManager.createPlayer({
id: object.ownerID
});
if (object.seenPlacement = this.inPlacementRange(object), owner.handleObjectPlacement(object),
object.type === 22) {
if (myPlayer.collidingObject(object, 1) || myPlayer.collidingObject(object, 4)) {
myPlayer.teleportPos.setVec(object.pos.current), myPlayer.teleported = !0;
}
}
}
}
createObjects(buffer) {
for (let i = 0; i < buffer.length; i += 8) {
let isResource = buffer[i + 6] === null, data = [ buffer[i + 0], buffer[i + 1], buffer[i + 2], buffer[i + 3], buffer[i + 4] ];
this.insertObject(isResource ? new Resource(...data, buffer[i + 5]) : new PlayerObject(...data, buffer[i + 6], buffer[i + 7]));
}
}
deletedObjects=new Set;
isDestroyedObject() {
return this.deletedObjects.size !== 0;
}
removeObject(object) {
if (this.grid2D.remove(object.pos.current.x, object.pos.current.y, object.collisionScale, object.id),
this.objects.delete(object.id), object instanceof PlayerObject) {
let player = this.client.PlayerManager.playerData.get(object.ownerID);
if (player !== void 0) {
player.handleObjectDeletion(object);
let {myPlayer: myPlayer} = this.client, pos1 = object.pos.current.copy(), pos2 = this.client.myPlayer.pos.current.copy(), distance = pos1.distance(pos2), spikeID = myPlayer.getItemByType(4), range = myPlayer.getItemPlaceScale(spikeID) + object.placementScale + myPlayer.speed + 25;
if (distance <= range) {
this.deletedObjects.add(object);
}
}
}
}
removeObjectByID(id) {
let object = this.objects.get(id);
if (object !== void 0) {
if (this.removeObject(object), this.client.isOwner) {
let pos1 = object.pos.current.copy(), pos2 = this.client.myPlayer.pos.current.copy();
if (Settings_default._notificationTracers && !targetInsideRect(pos1, pos2, object.scale)) {
NotificationRenderer_default.add(object);
}
}
}
}
removePlayerObjects(player) {
for (let object of player.objects) {
this.removeObject(object);
}
}
resetTurret(id) {
let object = this.objects.get(id);
if (object instanceof PlayerObject) {
object.reload = 0, this.reloadingTurrets.set(id, object);
}
}
isEnemyObject(object) {
if (object instanceof PlayerObject && !this.client.myPlayer.isEnemyByID(object.ownerID)) {
return !1;
}
return !0;
}
isTurretReloaded(object, tick = 1) {
let turret = this.reloadingTurrets.get(object.id);
if (turret === void 0) {
return !0;
}
return turret.reload > turret.maxReload - tick;
}
postTick() {
for (let [id, turret] of this.reloadingTurrets) {
if (turret.reload += 1, turret.reload >= turret.maxReload) {
turret.reload = turret.maxReload, this.reloadingTurrets.delete(id);
}
}
}
canPlaceItem(id, position, addRadius = 0) {
if (id !== 18 && pointInRiver(position)) {
return !1;
}
let item = Items[id];
return !this.grid2D.query(position.x, position.y, 1, id2 => {
let object = this.objects.get(id2), scale = item.scale + object.placementScale + addRadius;
if (position.distance(object.pos.current) < scale) {
return !0;
}
});
}
inPlacementRange(object) {
let owner = this.client.PlayerManager.playerData.get(object.ownerID);
if (owner === void 0 || !this.client.PlayerManager.players.includes(owner)) {
return !1;
}
let {previous: a0, current: a1, future: a2} = owner.pos, b0 = object.pos.current, item = Items[object.type], range = owner.scale * 2 + item.scale + item.placeOffset;
return a0.distance(b0) <= range || a1.distance(b0) <= range || a2.distance(b0) <= range;
}
getBestPlacementAngles(options) {
let {position: position, id: id, targetAngle: targetAngle, ignoreID: ignoreID, reduce: reduce, preplace: preplace, fill: fill} = options, item = DataHandler_default.getItem(id), {myPlayer: myPlayer, ModuleHandler: ModuleHandler} = this.client, length = myPlayer.getItemPlaceScale(id), angles = [];
this.grid2D.query(position.x, position.y, 1, id2 => {
let object = this.objects.get(id2);
if (ignoreID !== null && ignoreID === object.id) {
return;
}
let pos1 = object.pos.current, angle = position.angle(pos1), a = object.placementScale + item.scale + 1, b = position.distance(pos1), c = length, cosArg = (b * b + c * c - a * a) / (2 * b * c);
if (cosArg < -1) {
angles.push([ angle, Math.PI ]);
} else if (cosArg <= 1) {
let offset = Math.acos(cosArg);
angles.push([ angle, offset ]);
}
});
let finalAngles = findPlacementAngles(angles);
if (!angles.some(([angle, offset]) => getAngleDist(targetAngle, angle) <= offset)) {
if (finalAngles.push(targetAngle), finalAngles.length === 1 && fill) {
if (item.itemType === 4) {
return [];
}
let offset = Math.asin((2 * item.scale + 1) / (2 * length)) * 2;
return finalAngles.push(targetAngle - offset), finalAngles.push(targetAngle + offset),
finalAngles.push(reverseAngle(targetAngle)), finalAngles.slice(0, Settings_default._placeAttempts);
}
}
let anglesSorted = finalAngles.sort(Sorting_default.byAngleDistance(targetAngle));
if (reduce) {
if (!DataHandler_default.canMoveOnTop(id) && ModuleHandler.move_dir !== null && myPlayer.speed !== 0) {
let scale = item.scale, offset = Math.asin(2 * scale / (2 * length));
anglesSorted = anglesSorted.filter(angle => getAngleDist(angle, ModuleHandler.move_dir) > offset);
}
return anglesSorted.slice(0, Settings_default._placeAttempts);
}
return anglesSorted;
}
}
const ObjectManager_default = ObjectManager;
class PacketManager {
client;
Encoder=null;
Decoder=null;
packetCount=0;
constructor(client2) {
if (this.client = client2, this.client.isOwner) {
setInterval(() => {
GameUI_default.updatePackets(this.packetCount), this.packetCount = 0;
}, 1e3);
}
}
send(data) {
let {socket: socket, socketSend: socketSend} = this.client.SocketManager;
if (socket === null || socket.readyState !== socket.OPEN || this.Encoder === null || socketSend === null) {
return;
}
let [type, ...args] = data;
// HLM : passer par le canal du jeu quand il existe. Il signe le
// paquet et lui donne le bon numero de sequence. Deux compteurs
// concurrents sur une meme connexion font fermer le serveur.
let SM = this.client.SocketManager;
// Rien avant le spawn : sur une connexion neuve le serveur
// n'accepte que "M" en premier paquet.
if (!SM.hlmSpawned && type !== "M") {
if (!SM.hlmDropped) {
SM.hlmDropped = 0;
}
SM.hlmDropped += 1;
return;
}
SM.hlmSent = (SM.hlmSent || 0) + 1;
if (!SM.hlmLog) SM.hlmLog = [];
if (SM.hlmLog.length < 40) SM.hlmLog.push(String(type));
if (type === "M") {
SM.hlmSpawned = !0;
}
let gameSend = SM.gameSend;
if (gameSend !== null) {
gameSend.apply(null, [ type ].concat(args));
} else if (SM.hlmState !== null) {
// Bot : on signe avec SA cle et SON compteur.
let binary = HLM.encode(SM.hlmState, this.Encoder, type, args);
if (binary !== null) socketSend(binary);
} else {
socketSend(this.Encoder.encode([ type, args ]));
}
if (this.client.isOwner) {
this.packetCount += 1;
}
}
clanRequest(id, accept) {
this.send([ "P", id, Number(accept) ]);
}
kick(id) {
this.send([ "Q", id ]);
}
joinClan(name) {
this.send([ "b", name ]);
}
createClan(name) {
if (!/Glotus Client!/i.test(name)) {
name += " | Glotus Client!";
}
this.send([ "L", name ]);
}
leaveClan() {
this.client.myPlayer.joinRequests.length = 0, this.send([ "N" ]);
}
equip(type, id) {
this.send([ "c", 0, id, type ]);
}
buy(type, id) {
this.send([ "c", 1, id, type ]);
}
chat(message) {
this.send([ "6", message ]);
}
attack(angle) {
this.send([ "F", 1, angle ]);
}
stopAttack() {
this.send([ "F", 0, null ]);
}
resetMoveDir() {
this.send([ "e" ]);
}
move(angle) {
this.send([ "9", angle ]);
}
autoAttack() {
this.send([ "K", 1 ]);
}
lockRotation() {
this.send([ "K", 0 ]);
}
pingMap() {
this.send([ "S" ]);
}
selectItemByID(id, type) {
this.send([ "z", id, type ]);
}
spawn(name, moofoll, skin) {
this.send([ "M", {
name: name,
moofoll: moofoll,
skin: skin
} ]);
}
upgradeItem(id) {
this.send([ "H", id ]);
}
updateAngle(radians) {
this.send([ "D", radians ]);
}
pingRequest() {
this.client.SocketManager.startPing = performance.now(), this.send([ "0" ]);
}
}
class Animal extends Entity_default {
type;
prevHealth=0;
currentHealth=0;
receivedDamage=0;
maxHealth=0;
isDanger=!1;
isHostile=!1;
isPlayer=!1;
constructor(client2) {
super(client2);
}
canBeTrapped() {
return !("noTrap" in Animals_default[this.type]);
}
update(id, type, x, y, angle, health, nameIndex) {
this.id = id, this.type = type, this.pos.previous.setVec(this.pos.current),
this.pos.current.setXY(x, y), this.setFuturePosition();
let animal = Animals_default[type];
this.angle = angle, this.prevHealth = this.currentHealth, this.currentHealth = health,
this.maxHealth = animal.health, this.scale = animal.scale;
let isHostile = animal.hostile && type !== 7;
this.isHostile = animal.hostile, this.isDanger = isHostile, this.receivedDamage = 0;
let difference = Math.abs(this.currentHealth - this.prevHealth);
if (this.currentHealth < this.prevHealth) {
this.receivedDamage = difference;
}
}
get attackRange() {
if (this.type === 6) {
return Animals_default[this.type].hitRange + Config_default.playerScale;
}
return this.scale;
}
get collisionRange() {
if (this.type === 6) {
return Animals_default[this.type].hitRange + Config_default.playerScale;
}
return this.scale + 60;
}
get canUseTurret() {
return this.isHostile;
}
}
const Animal_default = Animal;
class ClientPlayer extends Player_default {
inventory={};
weaponXP=[ {}, {} ];
itemCount=new Map;
resources={};
tempGold=0;
deathPosition=new Vector_default;
offset=new Vector_default;
teleportPos=new Vector_default;
teleported=!1;
inGame=!1;
wasDead=!0;
diedOnce=!1;
teammates=new Set;
totalGoldAmount=0;
age=1;
upgradeAge=1;
prevKills=0;
underTurretAttack=!1;
upgradeOrder=[];
upgradeIndex=0;
joinRequests=[];
killedSomeone=!1;
actuallyKilledSomeone=!1;
totalKills=0;
deaths=0;
constructor(client2) {
super(client2);
this.reset(!0);
}
isMyPlayerByID(id) {
return id === this.id;
}
isTeammateByID(id) {
return this.teammates.has(id);
}
isEnemyByID(id) {
return !this.isMyPlayerByID(id) && !this.isTeammateByID(id);
}
get isSandbox() {
return /sandbox/.test(location.hostname) || this.client.SocketManager.isSandbox;
}
getItemByType(type) {
return this.inventory[type];
}
hasResourcesForType(type) {
if (this.isSandbox) {
return !0;
}
let res = this.resources, {food: food, wood: wood, stone: stone, gold: gold} = Items[this.getItemByType(type)].cost;
return res.food >= food && res.wood >= wood && res.stone >= stone && res.gold >= gold;
}
getItemCount(group) {
let item = ItemGroups[group];
return {
count: this.itemCount.get(group) || 0,
limit: this.isSandbox ? "sandboxLimit" in item ? item.sandboxLimit : 99 : item.limit
};
}
hasItemCountForType(type) {
if (type === 2) {
return !0;
}
let item = Items[this.getItemByType(type)], {count: count, limit: limit} = this.getItemCount(item.itemGroup);
return count < limit;
}
canPlace(type) {
return type !== null && this.getItemByType(type) !== null && this.hasResourcesForType(type) && this.hasItemCountForType(type);
}
canPlaceObject(type, angle) {
let {myPlayer: myPlayer, ObjectManager: ObjectManager2} = this.client, id = myPlayer.getItemByType(type), current = myPlayer.getPlacePosition(myPlayer.pos.current, id, angle);
return ObjectManager2.canPlaceItem(id, current);
}
getBestDestroyingWeapon(target = null) {
let primaryID = this.getItemByType(0), primary = DataHandler_default.getWeapon(primaryID), secondaryID = this.getItemByType(1), isHammer = secondaryID === 10, notStick = primary.damage !== 1, notPolearm = primaryID !== 5, {reloading: reloading} = this.client.ModuleHandler.staticModules, primaryDamage = this.getBuildingDamage(primaryID, !1);
if (isHammer && notStick && notPolearm && (!reloading.isReloaded(1) || reloading.isFasterThan(0, 1)) && reloading.isReloaded(0) && target != null && primaryDamage >= target.health) {
return 0;
}
if (target != null && isHammer && notStick && notPolearm && this.isTrapped) {
let hammerRange = DataHandler_default.getWeapon(secondaryID).range + target.hitScale + 1, primaryRange = primary.range + target.hitScale, pos1 = this.pos.current, pos2 = target.pos.current, distance = pos1.distance(pos2);
if (inRange(distance, hammerRange, primaryRange)) {
return 0;
}
}
if (isHammer) {
return 1;
}
if (notStick) {
return 0;
}
return null;
}
getWeaponRangeByType(type) {
let item = this.getItemByType(type);
if (DataHandler_default.isMelee(item)) {
return DataHandler_default.getWeapon(item).range;
}
return 0;
}
getFastestWeapon() {
let primary = DataHandler_default.getWeapon(this.getItemByType(0)), secondaryID = this.getItemByType(1);
if (secondaryID === null) {
return 0;
}
let secondary = DataHandler_default.getWeapon(secondaryID);
if (primary.spdMult > secondary.spdMult) {
return 0;
}
return 1;
}
getDmgOverTime() {
let hat = Hats[this.hatID], accessory = Accessories[this.accessoryID], damage = 0;
if ("healthRegen" in hat) {
damage += hat.healthRegen;
}
if ("healthRegen" in accessory) {
damage += accessory.healthRegen;
}
if (this.poisonCount !== 0) {
damage += -5;
}
return Math.abs(damage);
}
getMaxWeaponRangeClient() {
let primary = this.inventory[0], secondary = this.inventory[1], primaryRange = DataHandler_default.getWeapon(primary).range;
if (DataHandler_default.isMelee(secondary)) {
let range = DataHandler_default.getWeapon(secondary).range;
if (range > primaryRange) {
return range;
}
}
return primaryRange;
}
getMaxRangeTypeDestroy() {
let primaryID = this.inventory[0], secondaryID = this.inventory[1], primary = DataHandler_default.getWeapon(primaryID);
if (DataHandler_default.isMelee(secondaryID)) {
let secondary = DataHandler_default.getWeapon(secondaryID);
if (secondaryID === 10 && secondary.range > primary.range) {
return {
type: 1,
range: secondary.range
};
}
}
if (primaryID !== 8) {
return {
type: 0,
range: primary.range
};
}
return null;
}
getPlacePosition(start, itemID, angle) {
return start.addDirection(angle, this.getItemPlaceScale(itemID));
}
tickUpdate() {
if (this.inGame && this.wasDead) {
this.wasDead = !1, this.prevKills = 0, this.onFirstTickAfterSpawn();
}
let {ModuleHandler: ModuleHandler, PlayerManager: PlayerManager} = this.client;
if (this.killedSomeone = !1, this.actuallyKilledSomeone = !1, this.totalKills > this.prevKills) {
if (this.prevKills = this.totalKills, this.killedSomeone = !0, PlayerManager.prevPlayers.size !== 0) {
this.actuallyKilledSomeone = !0;
}
}
ModuleHandler.postTick();
}
updateHealth(health) {
if (!this.inGame) {
return;
}
if (super.updateHealth(health), this.shameActive) {
return;
}
if (health < 100) {
let {ModuleHandler: ModuleHandler} = this.client;
ModuleHandler.staticModules.shameReset.healthUpdate();
}
}
playerInit(id) {
this.id = id;
let {PlayerManager: PlayerManager} = this.client;
if (!PlayerManager.playerData.has(id)) {
PlayerManager.playerData.set(id, this);
}
}
onFirstTickAfterSpawn() {
let {ModuleHandler: ModuleHandler, isOwner: isOwner} = this.client, {mouse: mouse, staticModules: staticModules} = ModuleHandler;
if (ModuleHandler.equip(0, 0), ModuleHandler.updateAngle(mouse.sentAngle, !0),
!isOwner) {
let owner = this.client.owner;
UI_default.updateBotOption(this.client, "title"), owner.clientIDList.add(this.id),
staticModules.tempData.setAttacking(owner.ModuleHandler.attacking), staticModules.tempData.setStore(0, owner.ModuleHandler.store[0].actual),
staticModules.tempData.setStore(1, owner.ModuleHandler.store[1].actual);
}
}
playerSpawn() {
this.inGame = !0;
}
isUpgradeWeapon(id) {
let weapon = DataHandler_default.getWeapon(id);
if ("upgradeOf" in weapon) {
return this.inventory[weapon.itemType] === weapon.upgradeOf;
}
return !0;
}
newUpgrade(points, age) {
if (this.upgradeAge = age, points === 0 || age === 10) {
return;
}
let ids = [];
for (let weapon of Weapons) {
if (weapon.age === age && this.isUpgradeWeapon(weapon.id)) {
ids.push(weapon.id);
}
}
for (let item of Items) {
if (item.age === age) {
ids.push(item.id + 16);
}
}
if (!this.client.isOwner) {
let id = this.client.owner.myPlayer.upgradeOrder[this.upgradeIndex];
if (id !== void 0 && ids.includes(id)) {
this.upgradeIndex += 1, this.client.ModuleHandler.upgradeItem(id);
}
}
}
updateAge(age) {
this.age = age;
}
upgradeItem(id) {
this.upgradeOrder.push(id);
let {isOwner: isOwner, clients: clients} = this.client;
if (isOwner) {
for (let client2 of clients) {
let {age: age, upgradeAge: upgradeAge} = client2.myPlayer;
if (age > this.upgradeAge) {
client2.myPlayer.newUpgrade(1, upgradeAge);
}
}
}
if (id < 16) {
let weapon = DataHandler_default.getWeapon(id);
this.inventory[weapon.itemType] = id;
let XP = this.weaponXP[weapon.itemType];
XP.current = 0, XP.max = -1;
} else {
id -= 16;
let item = Items[id];
this.inventory[item.itemType] = id;
}
this.upgradeAge += 1;
}
updateClanMembers(teammates) {
this.teammates.clear();
for (let i = 0; i < teammates.length; i += 2) {
let id = teammates[i + 0];
if (!this.isMyPlayerByID(id)) {
this.teammates.add(id);
}
}
}
updateItemCount(group, count) {
if (this.itemCount.set(group, count), this.client.isOwner) {
GameUI_default.updateItemCount(group);
}
}
updateResources(type, amount) {
let previousAmount = this.resources[type];
if (this.resources[type] = amount, type === "gold") {
this.tempGold = amount;
return;
}
if (amount < previousAmount) {
return;
}
let difference = amount - previousAmount;
if (type === "kills") {
if (this.totalKills += difference, this.client.StatsManager.kills = difference,
this.client.StatsManager.totalKills = difference, this.client.owner.StatsManager.globalKills = difference,
this.client.isOwner) {
GameUI_default.updateTotalKills(this.totalKills);
}
return;
}
this.updateWeaponXP(difference);
}
updateWeaponXP(amount) {
let {next: next} = this.getWeaponVariant(this.weapon.current), XP = this.weaponXP[DataHandler_default.getWeapon(this.weapon.current).itemType], maxXP = WeaponVariants[next].needXP;
if (XP.current += amount, XP.max !== -1 && XP.current >= XP.max) {
XP.current -= XP.max, XP.max = maxXP;
return;
}
if (XP.max === -1) {
XP.max = maxXP;
}
if (XP.current >= XP.max) {
XP.current -= XP.max, XP.max = -1;
}
}
resetResources() {
this.resources.food = 100, this.resources.wood = 100, this.resources.stone = 100,
this.resources.gold = 100, this.resources.kills = 0;
}
resetInventory() {
this.inventory[0] = 0, this.inventory[1] = null, this.inventory[2] = 0, this.inventory[3] = 3,
this.inventory[4] = 6, this.inventory[5] = 10, this.inventory[6] = null, this.inventory[7] = null,
this.inventory[8] = null, this.inventory[9] = null;
}
resetWeaponXP() {
for (let XP of this.weaponXP) {
XP.current = 0, XP.max = -1;
}
}
spawn(customName) {
let name = customName || window.localStorage.getItem("moo_name") || "", skin = Number(window.localStorage.getItem("skin_color")) || 0;
this.client.PacketManager.spawn(name, 1, skin === 10 ? "constructor" : skin);
}
handleJoinRequest(id, name) {
this.joinRequests.push([ id, name ]);
}
reset(first = !1) {
this.resetResources(), this.resetInventory(), this.resetWeaponXP();
let {ModuleHandler: ModuleHandler, PlayerManager: PlayerManager} = this.client;
if (ModuleHandler.reset(), this.inGame = !1, this.wasDead = !0, this.upgradeOrder.length = 0,
this.upgradeIndex = 0, first) {
return;
}
if (this.previousHealth = 100, this.currentHealth = 100, this.tempHealth = 100,
this.shameActive = !1, this.shameCount = 0, this.shameTimer = 0, this.deathPosition.setVec(this.pos.current),
this.diedOnce = !0, this.client.StatsManager.deaths = 1, this.deaths += 1, this.client.isOwner) {
GameUI_default.reset(), GameUI_default.updateTotalDeaths(this.deaths);
}
}
}
const ClientPlayer_default = ClientPlayer;
class PlayerManager {
playerData=new Map;
players=[];
enemies=[];
prevPlayers=new Set;
animalData=new Map;
clanData=new Map;
start=Date.now();
step=0;
damagesByHits=[];
lastEnemyReceivedDamage=[ 0, 0 ];
nearestTeammate=null;
client;
constructor(client2) {
this.client = client2;
}
get timeSinceTick() {
return Date.now() - this.start;
}
getEntity(id, isPlayer) {
if (isPlayer && this.playerData.has(id)) {
return this.playerData.get(id);
} else if (!isPlayer && this.animalData.has(id)) {
return this.animalData.get(id);
}
return null;
}
createPlayer({socketID: socketID, id: id, nickname: nickname, health: health, skinID: skinID}) {
let {myPlayer: myPlayer} = this.client;
if (socketID === this.client.clientID && myPlayer.id === -1) {
myPlayer.playerInit(id);
}
let player = this.playerData.get(id) || new Player_default(this.client);
if (!this.playerData.has(id)) {
this.playerData.set(id, player);
}
if (player.id = id, player.prevNickname = player.nickname, player.nickname = nickname || "",
player.currentHealth = health || 100, player.skinID = typeof skinID > "u" ? -1 : skinID,
player.init(), myPlayer.isMyPlayerByID(id)) {
myPlayer.playerSpawn();
}
return player;
}
createClan(name, ownerID) {
this.clanData.set(name, ownerID);
}
deleteClan(name) {
this.clanData.delete(name);
}
clanExist(name) {
return name !== null && this.clanData.has(name);
}
canHitTarget(player, weaponID, target) {
let pos = target.pos.current, distance = player.pos.current.distance(pos), angle = player.pos.current.angle(pos), range = DataHandler_default.getWeapon(weaponID).range + target.hitScale;
return distance <= range && getAngleDist(angle, player.angle) <= Config_default.gatherAngle;
}
attackPlayer(id, gathering, weaponID) {
let player = this.playerData.get(id);
if (player === void 0) {
return;
}
let {hatID: hatID, reload: reload} = player, {myPlayer: myPlayer, ObjectManager: ObjectManager2} = this.client;
if (player.lastAttacked = myPlayer.tickCount, myPlayer.isMyPlayerByID(id) && !myPlayer.inGame) {
return;
}
let weapon = DataHandler_default.getWeapon(weaponID), type = weapon.itemType;
if (player.updateMaxReload(reload[type], weaponID), player.resetCurrentReload(reload[type]),
myPlayer.isEnemyByID(id)) {
if (this.canHitTarget(player, weaponID, myPlayer)) {
let {isAble: isAble, count: count} = player.canDealPoison(weaponID);
if (isAble) {
myPlayer.poisonCount = count;
}
}
}
if (gathering === 1) {
let objects = ObjectManager2.attackedObjects;
for (let [id2, data] of objects) {
let [hitAngle, object] = data;
if (this.canHitTarget(player, weaponID, object) && getAngleDist(hitAngle, player.angle) <= 1.25) {
if (objects.delete(id2), object instanceof PlayerObject) {
let damage = player.getBuildingDamage(weaponID);
object.health = Math.max(0, object.health - damage);
} else if (player === myPlayer) {
let amount = hatID === 9 ? 1 : 0;
if (object.type === 3) {
amount += weapon.gather + 4;
}
myPlayer.updateWeaponXP(amount);
}
}
}
}
}
updatePlayer(buffer) {
this.players.length = 0, this.enemies.length = 0, this.damagesByHits.length = 0,
this.nearestTeammate = null;
let now = Date.now();
this.step = now - this.start, this.start = now;
let {myPlayer: myPlayer, isOwner: isOwner, EnemyManager: EnemyManager2} = this.client;
for (let i = 0; i < buffer.length; i += 13) {
let id = buffer[i], player = this.playerData.get(id);
if (this.players.push(player), player.update(id, buffer[i + 1], buffer[i + 2], buffer[i + 3], buffer[i + 4], buffer[i + 5], buffer[i + 6], buffer[i + 7], buffer[i + 8], buffer[i + 9], buffer[i + 10]),
!this.client.isBotByID(id) && !myPlayer.isMyPlayerByID(id) && myPlayer.isTeammateByID(id) && EnemyManager2.isNear(player, this.nearestTeammate, myPlayer)) {
this.nearestTeammate = player;
} else if (myPlayer.isEnemyByID(id)) {
this.enemies.push(player);
}
}
}
updateAnimal(buffer) {
let {EnemyManager: EnemyManager2} = this.client;
for (let i = 0; i < buffer.length; i += 7) {
let id = buffer[i];
if (!this.animalData.has(id)) {
this.animalData.set(id, new Animal_default(this.client));
}
let animal = this.animalData.get(id);
animal.update(id, buffer[i + 1], buffer[i + 2], buffer[i + 3], buffer[i + 4], buffer[i + 5], buffer[i + 6]),
EnemyManager2.handleAnimal(animal);
}
}
postTick() {
let {EnemyManager: EnemyManager2, ProjectileManager: ProjectileManager, ObjectManager: ObjectManager2, myPlayer: myPlayer, isOwner: isOwner} = this.client;
if (ProjectileManager.postTick(), EnemyManager2.handleEnemies(this.enemies),
ObjectManager2.postTick(), myPlayer.inGame) {
myPlayer.tickUpdate();
}
if (ObjectManager2.deletedObjects.clear(), (Settings_default._autospawn || !isOwner) && !myPlayer.inGame) {
myPlayer.spawn();
}
}
isEnemy(target1, target2) {
return target1 == null || target2 == null || target1 !== target2 && (target1.clanName === null || target2.clanName === null || target1.clanName !== target2.clanName);
}
isEnemyByID(ownerID, target) {
let player = this.playerData.get(ownerID);
if (player == null) {
throw Error("isEnemyByID Error: Failed to find an owner!");
}
if (player instanceof ClientPlayer_default) {
return player.isEnemyByID(target.id);
}
if (target instanceof ClientPlayer_default) {
return target.isEnemyByID(player.id);
}
return this.isEnemy(player, target);
}
isEnemyTarget(owner, target) {
if (target instanceof Animal_default) {
return !0;
}
return this.isEnemyByID(owner.id, target);
}
canShoot(ownerID, target) {
return target instanceof Animal_default || this.isEnemyByID(ownerID, target);
}
canMoveOnTop(object) {
if (object instanceof Resource) {
return !1;
}
let item = DataHandler_default.getItem(object.type), isEnemyObject = this.isEnemyByID(object.ownerID, this.client.myPlayer);
if ("ignoreCollision" in item && (object.type !== 15 || !isEnemyObject)) {
return !0;
}
return !1;
}
lookingShield(owner, target) {
if (owner instanceof Animal_default) {
return !1;
}
if (owner.weapon.current !== 11) {
return !1;
}
let {myPlayer: myPlayer, ModuleHandler: ModuleHandler} = this.client, pos1 = owner.pos.current, pos2 = target.pos.current, angle = pos1.angle(pos2), ownerAngle = myPlayer.isMyPlayerByID(owner.id) ? ModuleHandler.mouse.sentAngle : owner.angle;
return getAngleDist(angle, ownerAngle) <= Config_default.shieldAngle;
}
}
const PlayerManager_default = PlayerManager;
class ProjectileManager {
client;
projectiles=new Map;
ignoreCreation=new Map;
dangerProjectiles=new Set;
toRemove=new Set;
totalDamage=0;
constructor(client2) {
this.client = client2;
}
createProjectile(projectile) {
let key = projectile.speed;
if (!this.projectiles.has(key)) {
this.projectiles.set(key, []);
}
this.projectiles.get(key).push(projectile);
}
foundProjectile(projectile) {
let owner = projectile.owner;
if (owner === null) {
return;
}
let {PlayerManager: PlayerManager2, myPlayer: myPlayer} = this.client;
if (PlayerManager2.isEnemyByID(owner.id, myPlayer)) {
let pos1 = projectile.pos.current, pos2 = myPlayer.pos.current, distance = pos1.distance(pos2), angle = pos1.angle(pos2), offset = Math.asin(2 * myPlayer.scale / (2 * distance));
if (getAngleDist(angle, projectile.angle) <= offset) {
this.dangerProjectiles.add(projectile);
}
}
}
foundProjectileThreat(projectile) {
let owner = projectile.owner;
if (owner === null) {
return;
}
let {PlayerManager: PlayerManager2, myPlayer: myPlayer, SocketManager: SocketManager} = this.client;
for (let enemy of PlayerManager2.enemies) {
if (!PlayerManager2.isEnemyByID(owner.id, enemy)) {
continue;
}
let pos1 = projectile.pos.current, pos2 = enemy.pos.current, distance = pos1.distance(pos2), angle = pos1.angle(pos2), offset = Math.asin(2 * enemy.scale / (2 * distance));
if (getAngleDist(angle, projectile.angle) <= offset) {
let tickDistance = Math.ceil(distance / (projectile.speed * SocketManager.TICK));
enemy.nextDamageTick = myPlayer.tickCount + tickDistance;
}
}
}
postTick() {
this.projectiles.clear(), this.totalDamage = 0;
for (let proj of this.dangerProjectiles) {
if (proj.life -= 1, proj.shouldRemove() || this.toRemove.delete(proj.id)) {
this.dangerProjectiles.delete(proj);
continue;
}
this.totalDamage += proj.damage;
}
this.toRemove.clear();
}
}
const ProjectileManager_default = ProjectileManager;
class Projectile {
pos={};
angle;
range;
speed;
type;
onPlatform;
id;
isTurret;
scale;
maxRange;
damage;
owner=null;
life=9;
constructor(angle, range, speed, type, onPlatform, id, maxRange) {
this.isTurret = type === 1, this.angle = angle, this.range = range, this.speed = speed,
this.type = type, this.onPlatform = onPlatform, this.id = id, this.scale = Projectiles[type].scale,
this.maxRange = maxRange || 0, this.damage = Projectiles[type].damage;
}
formatFromCurrent(pos, increase) {
if (this.isTurret) {
return pos;
}
return pos.addDirection(this.angle, increase ? 70 : -70);
}
shouldRemove() {
return this.life <= 0;
}
}
const Projectile_default = Projectile;
const StoreHandler = new class {
isOpened=!1;
store=[ {
previous: -1,
current: -1,
list: new Map
}, {
previous: -1,
current: -1,
list: new Map
} ];
currentType=0;
isRightStore(type) {
return this.isOpened && this.currentType === type;
}
createStore(type) {
let storeContainer = document.createElement("div");
storeContainer.id = "storeContainer", storeContainer.style.display = "none";
let button = document.createElement("div");
button.id = "toggleStoreType", button.textContent = type === 0 ? "Hats" : "Accessories",
button.onmousedown = () => {
if (this.currentType = this.currentType === 0 ? 1 : 0, button.textContent = this.currentType === 0 ? "Hats" : "Accessories",
this.isOpened) {
this.fillStore(this.currentType);
}
}, storeContainer.appendChild(button);
let itemHolder = document.createElement("div");
itemHolder.id = "itemHolder", storeContainer.appendChild(itemHolder), itemHolder.addEventListener("wheel", event => {
event.preventDefault();
let scale = Math.sign(event.deltaY) * 50;
itemHolder.scroll(0, itemHolder.scrollTop + scale);
});
let {gameUI: gameUI} = GameUI_default.getElements();
gameUI.appendChild(storeContainer);
}
getTextEquip(type, id, price) {
let {list: list, current: current} = this.store[type];
if (current === id) {
return "Unequip";
}
if (list.has(id) || price === 0) {
return "Equip";
}
return "Buy";
}
generateStoreElement(type, id, name, price, isTop) {
let src = [ [ "hats/hat", "accessories/access" ][type], id ];
if (isTop) {
src.push("p");
}
let html = `\n <div class="storeItemContainer">\n <img class="storeHat" src="./img/${src.join("_")}.png">\n <span class="storeItemName">${name}</span>\n <div class="equipButton" data-id="${id}">${this.getTextEquip(type, id, price)}</div>\n </div>\n `, div = document.createElement("div");
div.innerHTML = html;
let img = div.querySelector(".storeHat");
img.src = `./img/${src.join("_")}.png`;
let equipButton = div.querySelector(".equipButton");
return equipButton.onmousedown = () => {
client.ModuleHandler.equip(type, id, !0, !0);
}, div.firstElementChild;
}
fillStore(type) {
let {itemHolder: itemHolder} = GameUI_default.getElements();
itemHolder.innerHTML = "";
let items = Settings_default._storeItems[type];
for (let id of items) {
let item = DataHandler_default.getStoreItem(type, id), element = this.generateStoreElement(type, id, item.name, item.price, "topSprite" in item);
itemHolder.appendChild(element);
}
}
handleEquipUpdate(type, prev, curr, isBuy) {
if (!this.isRightStore(type)) {
return;
}
let current = document.querySelector(`.equipButton[data-id="${curr}"]`);
if (current !== null) {
current.textContent = isBuy ? "Equip" : "Unequip";
}
if (!isBuy && prev !== -1) {
let previous = document.querySelector(`.equipButton[data-id="${prev}"]`);
if (previous !== null) {
previous.textContent = "Equip";
}
}
}
updateStoreState(type, action, id) {
let store2 = this.store[type];
if (action === 0) {
store2.previous = store2.current, store2.current = id;
let {previous: previous, current: current, list: list} = store2;
list.set(previous, 0), list.set(current, 1), this.handleEquipUpdate(type, store2.previous, id, !1);
} else {
store2.list.set(id, 0), this.handleEquipUpdate(type, store2.previous, id, !0);
}
}
closeStore() {
let {storeContainer: storeContainer, itemHolder: itemHolder} = GameUI_default.getElements();
itemHolder.innerHTML = "", storeContainer.style.display = "none", this.isOpened = !1;
}
openStore() {
GameUI_default.closePopups();
let {storeContainer: storeContainer} = GameUI_default.getElements();
this.fillStore(this.currentType), storeContainer.style.display = "", storeContainer.classList.remove("closedItem"),
this.isOpened = !0;
}
toggleStore() {
let {storeContainer: storeContainer, itemHolder: itemHolder} = GameUI_default.getElements();
if (this.isOpened) {
itemHolder.innerHTML = "";
} else {
GameUI_default.closePopups(), this.fillStore(this.currentType);
}
storeContainer.style.display = storeContainer.style.display === "none" ? "" : "none",
this.isOpened = !this.isOpened;
}
init() {
this.createStore(0);
}
}, StoreHandler_default = StoreHandler;
class SocketManager {
client;
socket=null;
socketSend=null;
gameSend=null;
hlmSpawned=!1;
hlmPingStarted=!1;
hlmState=null;
PacketQueue=[];
startPing=Date.now();
pong=0;
TICK=111.11111111111111;
packetCount=0;
action=null;
constructor(client2) {
this.client = client2;
}
get isSandbox() {
return this.socket !== null && /localhost/.test(this.socket.url);
}
init(socket) {
if (this.socket = socket, this.socketSend = socket.send.bind(socket), socket.addEventListener("message", event => this.handleMessage(event)),
socket.addEventListener("close", event => {
// Seule information qui dit POURQUOI le serveur coupe.
console.error("[HLM] SOCKET FERME code:", event.code, " raison:",
event.reason || "(vide)", " propre:", event.wasClean,
" paquets emis par nous:", this.hlmSent || 0,
" sequence du jeu:", (window.__glotusEnc && window.__glotusEnc())
? window.__glotusEnc().seq : "n/a");
console.error("[HLM] derniers types emis :", (this.hlmLog || []).join(" "),
" | retenus avant spawn :", this.hlmDropped || 0,
" | spawn parti :", this.hlmSpawned);
}),
!this.client.isOwner) {
return;
}
// ==========================================================
// HLM - INTERCEPTION DES ENVOIS DU JEU
// Avant : on remplacait socket.send. Le jeu ne passe plus par
// la - il capture WebSocket.prototype.send au chargement de
// son bundle et appelle cette reference native. Le spawn
// n'etait donc plus intercepte.
// On enveloppe desormais la methode send de son objet reseau,
// que le bundle reecrit nous expose. Bonus decisif : ses
// paquets restent numerotes par SON compteur de sequence, et
// les notres empruntent le meme - il n'y en a qu'un.
// ==========================================================
let that = this, io = window.__glotusIO ? window.__glotusIO() : null;
if (io === null) {
Logger.error("Objet reseau du jeu introuvable (crochet exposeIO)");
return;
}
let _send = io.send;
this.gameSend = function() {
return _send.apply(io, arguments);
};
io.send = function(type) {
if (type === "M") {
that.hlmSpawned = !0;
let data2 = arguments[1];
data2.skin = GameUI_default.selectSkinColor(CustomStorage.get("skin_color") || 0),
that.client.PacketManager.spawn(data2.name, data2.moofoll, data2.skin);
return;
}
return _send.apply(this, arguments);
};
}
pingTimeout;
handlePing() {
if (this.pong = Math.round(performance.now() - this.startPing), this.client.isOwner) {
GameUI_default.updatePing(this.pong);
}
clearTimeout(this.pingTimeout), this.pingTimeout = setTimeout(() => {
this.client.PacketManager.pingRequest();
}, 3e3);
}
handleMessage(event) {
let decoder = this.client.PacketManager.Decoder;
if (decoder === null) {
return;
}
let data = event.data, decoded = decoder.decode(new Uint8Array(data));
// HLM : en mode chiffre le type arrive en NOMBRE. Sans traduction,
// aucun cas du switch ne correspondait et le client restait vide.
if (decoded[0] === "io-init" && !this.client.isOwner) {
// Un bot a SA propre graine : on construit son etat a lui.
this.hlmState = HLM.makeState(decoded[1]);
}
if (typeof decoded[0] === "number") {
// Le proprietaire lit les tables du jeu, un bot les siennes.
let s2c = null;
if (this.client.isOwner) {
let enc = window.__glotusEnc ? window.__glotusEnc() : null;
if (enc !== null) s2c = enc.tables.s2c;
} else if (this.hlmState !== null) {
s2c = this.hlmState.s2c;
}
if (s2c === null) return;
decoded[0] = s2c.dec[decoded[0]];
if (decoded[0] === undefined) return;
}
let temp = [ decoded[0], ...decoded[1] ], {myPlayer: myPlayer, EnemyManager: EnemyManager2, ModuleHandler: ModuleHandler, PlayerManager: PlayerManager2, ObjectManager: ObjectManager2, ProjectileManager: ProjectileManager2, LeaderboardManager: LeaderboardManager2, PacketManager: PacketManager2} = this.client;
switch (temp[0]) {
case "0":
this.handlePing();
break;
case "io-init":
// HLM : plus de ping ici. Le journal de fermeture l'a montre :
// le premier paquet de la connexion etait un "0" (ping) envoye
// des le io-init, avant le "M" de spawn. Le serveur fermait
// proprement (code 1000) juste apres - la sequence du jeu etait
// restee a 1, donc le spawn n'est jamais parti. Le ping demarre
// maintenant a l'arrivee du paquet "C", donc apres le spawn.
if (this.client.connectSuccess = !0, this.client.clientID = temp[1],
this.client.isOwner) {
GameUI_default.loadGame(), Logger.staticLog("%c Glotus Client! ", "background: #f5d951; color: #000; font-weight: bold; font-size: 20px;"),
GameUI_default.handleMessageLog("GLOTUS"), Logger.test("Successfully connected to a server.. [Glotus Client!]"),
document.title = "Glotus Client";
} else {
let originalName = window.localStorage.getItem("moo_name") || "Player";
this.client.myPlayer.spawn(originalName), this.socket.dispatchEvent(new Event("connected")),
Logger.test("Bot spawned.. [Glotus Client!]");
}
break;
case "C":
myPlayer.playerInit(temp[1]);
if (!this.hlmPingStarted) {
this.hlmPingStarted = !0, PacketManager2.pingRequest();
}
break;
case "P":
myPlayer.reset(), this.client.InputHandler.reset();
break;
case "N":
this.PacketQueue.push(() => {
let type = temp[1] === "points" ? "gold" : temp[1];
myPlayer.updateResources(type, temp[2]);
});
break;
case "D":
{
let data2 = temp[1];
PlayerManager2.createPlayer({
socketID: data2[0],
id: data2[1],
nickname: data2[2],
health: data2[6],
skinID: data2[9]
});
break;
}
case "O":
{
let player = PlayerManager2.playerData.get(temp[1]);
if (player !== void 0) {
player.updateHealth(temp[2]);
}
break;
}
case "a":
PlayerManager2.updatePlayer(temp[1]);
for (let i = 0; i < this.PacketQueue.length; i++) {
this.PacketQueue[i]();
}
this.PacketQueue.length = 0, ObjectManager2.attackedObjects.clear(), EnemyManager2.preReset(),
this.action = createAction(() => {
PlayerManager2.postTick();
}, 1);
break;
case "I":
PlayerManager2.updateAnimal(temp[1] || []);
break;
case "H":
if (ObjectManager2.createObjects(temp[1]), this.action !== null) {
this.action();
}
break;
case "Q":
ObjectManager2.removeObjectByID(temp[1]);
break;
case "R":
{
let player = PlayerManager2.playerData.get(temp[1]);
if (player !== void 0) {
ObjectManager2.removePlayerObjects(player);
}
break;
}
case "L":
{
let object = ObjectManager2.objects.get(temp[2]);
if (object instanceof Resource || object && object.isDestroyable) {
ObjectManager2.attackedObjects.set(getUniqueID(), [ temp[1], object ]);
}
break;
}
case "K":
this.PacketQueue.push(() => PlayerManager2.attackPlayer(temp[1], temp[2], temp[3]));
break;
case "M":
{
let id = temp[1], angle = temp[2], turret = ObjectManager2.objects.get(id);
if (turret instanceof PlayerObject) {
let creations = ProjectileManager2.ignoreCreation, pos = turret.pos.current.makeString();
creations.set(pos + ":" + angle, turret);
let owner = PlayerManager2.playerData.get(turret.ownerID);
if (owner !== void 0) {
let projTurret = Projectiles[1], projectile = new Projectile_default(angle, projTurret.range, projTurret.speed, projTurret.index, projTurret.layer, -1);
if (projectile.pos.current = turret.pos.current.copy(), projectile.owner = owner,
turret.projectile = projectile, PlayerManager2.isEnemyByID(turret.ownerID, myPlayer)) {
ProjectileManager2.foundProjectile(projectile);
}
ProjectileManager2.foundProjectileThreat(projectile);
}
}
this.PacketQueue.push(() => ObjectManager2.resetTurret(id));
break;
}
case "X":
{
let x = temp[1], y = temp[2], angle = temp[3], key = `${x}:${y}:${angle}`;
if (ProjectileManager2.ignoreCreation.has(key)) {
let proj = ProjectileManager2.ignoreCreation.get(key).projectile;
if (proj !== null) {
proj.id = temp[8];
}
ProjectileManager2.ignoreCreation.delete(key);
return;
}
let projectile = new Projectile_default(angle, temp[4], temp[5], temp[6], temp[7], temp[8]);
projectile.pos.current = projectile.formatFromCurrent(new Vector_default(x, y), !1),
ProjectileManager2.createProjectile(projectile);
break;
}
case "Y":
{
let id = temp[1];
ProjectileManager2.toRemove.add(id);
break;
}
case "4":
myPlayer.updateClanMembers(temp[1]);
break;
case "3":
if (typeof temp[1] !== "string") {
myPlayer.teammates.clear();
}
break;
case "g":
break;
case "2":
myPlayer.handleJoinRequest(temp[1], temp[2]);
break;
case "T":
if (temp.length === 4) {
myPlayer.updateAge(temp[3]);
}
break;
case "U":
myPlayer.newUpgrade(temp[1], temp[2]);
break;
case "S":
myPlayer.updateItemCount(temp[1], temp[2]);
break;
case "G":
LeaderboardManager2.update(temp[1]);
break;
case "5":
{
let action = temp[1] === 0 ? 1 : 0;
if (StoreHandler_default.updateStoreState(temp[3], action, temp[2]), temp[1] === 0) {
let boughtStorage = ModuleHandler.bought[temp[3]];
if (boughtStorage !== void 0) {
boughtStorage.add(temp[2]);
}
}
break;
}
case "A":
{
let teams = temp[1].teams;
for (let team of teams) {
PlayerManager2.createClan(team.sid, team.owner);
}
break;
}
case "g":
PlayerManager2.createClan(temp[1].sid, temp[1].owner);
break;
case "1":
PlayerManager2.deleteClan(temp[1]);
break;
case "6":
{
let id = temp[1], message = temp[2], player = PlayerManager2.playerData.get(id);
if (this.client.isOwner && player) {
GameUI_default.handleMessageLog(`${player.nickname}: ${message}`);
}
break;
}
case "7":
break;
default:
break;
}
}
}
const SocketManager_default = SocketManager;
class StatsManager {
client;
kills=0;
_totalKills=0;
_globalKills=0;
_deaths=0;
_autoSyncTimes=0;
_velocityTickTimes=0;
_spikeSyncHammerTimes=0;
_spikeSyncTimes=0;
_spikeTickTimes=0;
_knockbackTickTrapTimes=0;
_knockbackTickHammerTimes=0;
_knockbackTickTimes=0;
constructor(client2) {
this.client = client2;
}
init() {
this.totalKills = Settings_default._totalKills, this.globalKills = Settings_default._globalKills,
this.deaths = Settings_default._deaths, this.autoSyncTimes = Settings_default._autoSyncTimes,
this.velocityTickTimes = Settings_default._velocityTickTimes, this.spikeSyncHammerTimes = Settings_default._spikeSyncHammerTimes,
this.spikeSyncTimes = Settings_default._spikeSyncTimes, this.spikeTickTimes = Settings_default._spikeTickTimes,
this.knockbackTickTrapTimes = Settings_default._knockbackTickTrapTimes, this.knockbackTickHammerTimes = Settings_default._knockbackTickHammerTimes,
this.knockbackTickTimes = Settings_default._knockbackTickTimes;
}
get totalKills() {
return this._totalKills;
}
get globalKills() {
return this._globalKills;
}
get deaths() {
return this._deaths;
}
get autoSyncTimes() {
return this._autoSyncTimes;
}
get velocityTickTimes() {
return this._velocityTickTimes;
}
get spikeSyncHammerTimes() {
return this._spikeSyncHammerTimes;
}
get spikeSyncTimes() {
return this._spikeSyncTimes;
}
get spikeTickTimes() {
return this._spikeTickTimes;
}
get knockbackTickTrapTimes() {
return this._knockbackTickTrapTimes;
}
get knockbackTickHammerTimes() {
return this._knockbackTickHammerTimes;
}
get knockbackTickTimes() {
return this._knockbackTickTimes;
}
set totalKills(value) {
if (this._totalKills += value, !this.client.isOwner) {
return;
}
UI_default.updateStats("_totalKills", this._totalKills);
}
set globalKills(value) {
if (this._globalKills += value, !this.client.isOwner) {
return;
}
UI_default.updateStats("_globalKills", this._globalKills);
}
set deaths(value) {
if (this._deaths += value, !this.client.isOwner) {
return;
}
UI_default.updateStats("_deaths", this._deaths);
}
set autoSyncTimes(value) {
if (this._autoSyncTimes += value, !this.client.isOwner) {
return;
}
UI_default.updateStats("_autoSyncTimes", this._autoSyncTimes);
}
set velocityTickTimes(value) {
if (this._velocityTickTimes += value, !this.client.isOwner) {
return;
}
UI_default.updateStats("_velocityTickTimes", this._velocityTickTimes);
}
set spikeSyncHammerTimes(value) {
if (this._spikeSyncHammerTimes += value, !this.client.isOwner) {
return;
}
UI_default.updateStats("_spikeSyncHammerTimes", this._spikeSyncHammerTimes);
}
set spikeSyncTimes(value) {
if (this._spikeSyncTimes += value, !this.client.isOwner) {
return;
}
UI_default.updateStats("_spikeSyncTimes", this._spikeSyncTimes);
}
set spikeTickTimes(value) {
if (this._spikeTickTimes += value, !this.client.isOwner) {
return;
}
UI_default.updateStats("_spikeTickTimes", this._spikeTickTimes);
}
set knockbackTickTrapTimes(value) {
if (this._knockbackTickTrapTimes += value, !this.client.isOwner) {
return;
}
UI_default.updateStats("_knockbackTickTrapTimes", this._knockbackTickTrapTimes);
}
set knockbackTickHammerTimes(value) {
if (this._knockbackTickHammerTimes += value, !this.client.isOwner) {
return;
}
UI_default.updateStats("_knockbackTickHammerTimes", this._knockbackTickHammerTimes);
}
set knockbackTickTimes(value) {
if (this._knockbackTickTimes += value, !this.client.isOwner) {
return;
}
UI_default.updateStats("_knockbackTickTimes", this._knockbackTickTimes);
}
}
class InputHandler {
client;
hotkeys=new Map;
move;
lastPosition=new Vector_default(0, 0);
lockPosition=!1;
mouse={
x: 0,
y: 0,
angle: 0
};
rotation=!0;
instaToggle=!1;
instakillTarget=null;
constructor(client2) {
this.client = client2, this.reset();
}
instaReset() {
this.instaToggle = !1, this.instakillTarget = null;
}
reset() {
this.hotkeys.clear(), this.move = 0, this.instaReset();
}
init() {
window.addEventListener("keydown", event => this.handleKeydown(event), !0),
window.addEventListener("keyup", event => this.handleKeyup(event), !0), window.addEventListener("mousedown", event => this.handleMousedown(event), !0),
window.addEventListener("mouseup", event => this.handleMouseup(event), !0),
window.addEventListener("mousemove", event => this.handleMouseMove(event), !0),
window.addEventListener("mouseover", event => this.handleMouseMove(event), !0),
window.addEventListener("wheel", event => ZoomHandler_default.handler(event), !0);
}
placementHandler(type, code) {
if (this.client.myPlayer.getItemByType(type) === null) {
return;
}
this.hotkeys.set(code, type), this.client.ModuleHandler.startPlacement(type);
let {isOwner: isOwner, clients: clients} = this.client;
if (isOwner) {
for (let client2 of clients) {
client2.ModuleHandler.startPlacement(type);
}
}
}
cursorPosition(force = !1) {
if (!force && this.lockPosition) {
return this.lastPosition;
}
let {myPlayer: myPlayer} = this.client, pos = myPlayer.pos.future, {w: w, h: h} = ZoomHandler_default.scale.current, scale = Math.max(window.innerWidth / w, window.innerHeight / h), cursorX = (this.mouse.x - window.innerWidth / 2) / scale, cursorY = (this.mouse.y - window.innerHeight / 2) / scale;
return new Vector_default(pos.x + cursorX, pos.y + cursorY);
}
getMovePosition(force = !1) {
if (!force && this.lockPosition) {
return this.lastPosition;
}
if (Settings_default._followCursor) {
return this.cursorPosition(!0);
}
let {myPlayer: myPlayer, ModuleHandler: ModuleHandler} = this.client;
if (ModuleHandler.move_dir !== null) {
return myPlayer.pos.current.addDirection(ModuleHandler.move_dir, Settings_default._movementRadius);
}
return myPlayer.pos.future;
}
postTick() {}
toggleBotPosition() {
let state = !this.lockPosition;
if (state) {
this.lastPosition.setVec(this.getMovePosition(!0));
}
this.lockPosition = state;
}
handleMovement() {
let angle = getAngleFromBitmask(this.move, !1);
this.client.ModuleHandler.startMovement(angle);
}
toggleRotation() {
if (this.rotation = !this.rotation, this.rotation) {
this.client.ModuleHandler.currentAngle = this.mouse.angle;
}
}
handleKeydown(event) {
let target = event.target;
if (event.code === "Space" && target.tagName === "BODY") {
event.preventDefault();
}
if (event.ctrlKey && [ "KeyD", "KeyS", "KeyW" ].includes(event.code)) {
event.preventDefault();
}
if (event.repeat) {
return;
}
if (UI_default.isActiveButton()) {
return;
}
let isInput = isActiveInput();
if (event.code === Settings_default._toggleMenu && !isInput) {
UI_default.toggleMenu();
}
if (event.code === Settings_default._toggleChat && !UI_default.isMenuOpened) {
GameUI_default.handleEnter(event);
}
if (!this.client.myPlayer.inGame) {
return;
}
if (isInput) {
return;
}
let {ModuleHandler: ModuleHandler} = this.client;
if (event.code === Settings_default._food) {
this.placementHandler(2, event.code);
}
if (event.code === Settings_default._wall) {
this.placementHandler(3, event.code);
}
if (event.code === Settings_default._spike) {
this.placementHandler(4, event.code);
}
if (event.code === Settings_default._windmill) {
this.placementHandler(5, event.code);
}
if (event.code === Settings_default._farm) {
this.placementHandler(6, event.code);
}
if (event.code === Settings_default._trap) {
this.placementHandler(7, event.code);
}
if (event.code === Settings_default._turret) {
this.placementHandler(8, event.code);
}
if (event.code === Settings_default._spawn) {
this.placementHandler(9, event.code);
}
let copyMove = this.move;
if (event.code === Settings_default._up) {
this.move |= 1;
}
if (event.code === Settings_default._left) {
this.move |= 4;
}
if (event.code === Settings_default._down) {
this.move |= 2;
}
if (event.code === Settings_default._right) {
this.move |= 8;
}
if (copyMove !== this.move) {
this.handleMovement();
}
if (event.code === Settings_default._autoattack) {
ModuleHandler.toggleAutoattack();
}
if (event.code === Settings_default._lockrotation) {
this.toggleRotation();
}
if (event.code === Settings_default._lockBotPosition) {
this.toggleBotPosition();
}
if (event.code === Settings_default._instakill) {
this.instaToggle = !this.instaToggle;
}
if (UI_default.isMenuOpened) {
return;
}
if (event.code === Settings_default._toggleShop) {
StoreHandler_default.toggleStore();
}
if (event.code === Settings_default._toggleClan) {
GameUI_default.openClanMenu();
}
}
handleKeyup(event) {
let {myPlayer: myPlayer, ModuleHandler: ModuleHandler, isOwner: isOwner, clients: clients} = this.client;
if (!myPlayer.inGame) {
return;
}
let copyMove = this.move;
if (event.code === Settings_default._up) {
this.move &= -2;
}
if (event.code === Settings_default._left) {
this.move &= -5;
}
if (event.code === Settings_default._down) {
this.move &= -3;
}
if (event.code === Settings_default._right) {
this.move &= -9;
}
if (copyMove !== this.move) {
this.handleMovement();
}
if (ModuleHandler.currentType !== null && this.hotkeys.delete(event.code)) {
let entry = [ ...this.hotkeys ].pop(), type = entry !== void 0 ? entry[1] : null;
if (ModuleHandler.startPlacement(type), isOwner) {
for (let client2 of clients) {
client2.ModuleHandler.startPlacement(type);
}
}
}
}
handleMousedown(event) {
if (!(event.target instanceof HTMLCanvasElement) || event.target.id === "mapDisplay") {
return;
}
let button = formatButton(event.button);
if (button === "MBTN") {
this.instaToggle = !this.instaToggle;
return;
}
let {isOwner: isOwner, clients: clients, ModuleHandler: ModuleHandler} = this.client, state = button === "LBTN" ? 1 : button === "RBTN" ? 2 : null;
if (state !== null && ModuleHandler.attacking === 0) {
if (ModuleHandler.attacking = state, ModuleHandler.attackingState = state, isOwner) {
for (let client2 of clients) {
client2.ModuleHandler.staticModules.tempData.setAttacking(state);
}
}
}
}
handleMouseup(event) {
let button = formatButton(event.button), {isOwner: isOwner, clients: clients, ModuleHandler: ModuleHandler} = this.client;
if ((button === "LBTN" || button === "RBTN") && ModuleHandler.attacking !== 0) {
if (!ModuleHandler.autoattack) {
ModuleHandler.attacking = 0;
}
if (isOwner) {
for (let client2 of clients) {
client2.ModuleHandler.staticModules.tempData.setAttacking(0);
}
}
}
}
handleMouseMove(event) {
let {clientX: x, clientY: y} = event, angle = getAngle(window.innerWidth / 2, window.innerHeight / 2, x, y);
if (this.mouse.angle = angle, this.rotation) {
this.mouse.x = x, this.mouse.y = y, this.client.ModuleHandler.currentAngle = angle;
}
}
}
class TempData {
moduleName="tempData";
client;
store=[ 0, 0 ];
constructor(client2) {
this.client = client2;
}
setAttacking(attacking) {
let {ModuleHandler: ModuleHandler} = this.client;
if (ModuleHandler.attacking = attacking, attacking !== 0) {
ModuleHandler.attackingState = attacking;
}
}
setStore(type, id) {
this.store[type] = id, this.handleBuy(type);
}
handleBuy(type) {
let {ModuleHandler: ModuleHandler} = this.client, id = this.store[type];
if (ModuleHandler.store[type].actual === id) {
return;
}
if (ModuleHandler.sentHatEquip) {
return;
}
let temp = ModuleHandler.canBuy(type, id) ? id : 0;
ModuleHandler.equip(type, temp, !0);
}
postTick() {
this.handleBuy(0), this.handleBuy(1);
}
}
const TempData_default = TempData;
class Movement {
moduleName="movement";
client;
isStopped=!0;
constructor(client2) {
this.client = client2;
}
getMovePosition() {
return this.client.owner.InputHandler.getMovePosition();
}
circlePosition(vec) {
let totalBots = this.client.owner.clients.size;
if (totalBots === 0) {
return vec;
}
let {circleOffset: circleOffset} = this.client.owner.ModuleHandler, botIndex = this.client.owner.getClientIndex(this.client), angle = 2 * Math.PI * botIndex / totalBots + circleOffset;
return vec.addDirection(angle, Settings_default._circleRadius);
}
getActualPosition() {
let pos = this.getMovePosition();
if (Settings_default._circleFormation) {
return this.circlePosition(pos);
}
return pos;
}
someColliding(pos, radius) {
let {myPlayer: myPlayer} = this.client, {previous: previous, current: current} = myPlayer.pos;
return previous.distance(pos) <= radius || current.distance(pos) <= radius;
}
postTick() {
let {InputHandler: InputHandler2} = this.client.owner, {myPlayer: myPlayer, ModuleHandler: ModuleHandler} = this.client, pos1 = myPlayer.pos.current, walkPos = this.getActualPosition(), lookPos = InputHandler2.cursorPosition(), lookAt = pos1.angle(lookPos);
if (ModuleHandler.currentAngle = lookAt, !this.someColliding(walkPos, Settings_default._movementRadius)) {
let walkTo = pos1.angle(walkPos);
this.isStopped = !ModuleHandler.startMovement(walkTo);
} else if (!this.isStopped) {
this.isStopped = !0, ModuleHandler.stopMovement();
}
}
}
const Movement_default = Movement;
class ClanJoiner {
moduleName="clanJoiner";
client;
joinCount=0;
prevState=!1;
constructor(client2) {
this.client = client2;
}
postTick() {
let {myPlayer: myPlayer, PacketManager: PacketManager2, owner: owner, PlayerManager: PlayerManager2} = this.client, ownerClan = owner.myPlayer.clanName, myClan = myPlayer.clanName, state = ownerClan !== myClan;
if (this.prevState !== state) {
this.prevState = state, this.joinCount = 0;
}
if (ownerClan === null || myClan === ownerClan || !PlayerManager2.clanExist(ownerClan)) {
return;
}
if (this.joinCount === 3) {
if (this.joinCount = 0, myClan !== null) {
PacketManager2.leaveClan();
} else if (!owner.pendingJoins.has(myPlayer.id)) {
owner.pendingJoins.add(myPlayer.id), PacketManager2.joinClan(ownerClan);
}
}
this.joinCount += 1;
}
}
const ClanJoiner_default = ClanJoiner;
class Autobreak {
moduleName="autoBreak";
client;
constructor(client2) {
this.client = client2;
}
getWeaponRange(id, target) {
if (id === null) {
return 0;
}
if (DataHandler_default.isMelee(id)) {
return DataHandler_default.getWeapon(id).range + target.hitScale;
}
return 0;
}
getDestroyingObject() {
let {EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client, pos0 = myPlayer.pos.current, primary = myPlayer.getItemByType(0), secondary = myPlayer.getItemByType(1), isPrimary = primary !== 8 && primary !== 5, isHammer = secondary === 10, nearestTrap = EnemyManager2.nearestTrap || EnemyManager2.nearestEnemyObject, nearestSpike = EnemyManager2.nearestSpike || EnemyManager2.nearestEnemyObject;
if (nearestSpike) {
let pos2 = nearestSpike.pos.current, distPlayerSpike = pos0.distance(pos2), canUseHammer = isHammer && distPlayerSpike <= this.getWeaponRange(secondary, nearestSpike);
if (nearestTrap) {
let canUsePrimary = isPrimary && distPlayerSpike <= this.getWeaponRange(primary, nearestSpike);
if (canUseHammer || canUsePrimary) {
return nearestSpike;
}
return nearestTrap;
}
if (canUseHammer) {
return nearestSpike;
}
}
return nearestTrap;
}
getDestroyingWeapon(target) {
let {myPlayer: myPlayer, ModuleHandler: ModuleHandler} = this.client, pos0 = myPlayer.pos.current, pos1 = target.pos.current, distance = pos0.distance(pos1), primary = myPlayer.getItemByType(0), secondary = myPlayer.getItemByType(1), inPrimaryRange = distance <= this.getWeaponRange(primary, target), inSecondaryRange = distance <= this.getWeaponRange(secondary, target), isHammer = secondary === 10, notStick = primary !== 8, notPolearm = primary !== 5, {reloading: reloading} = ModuleHandler.staticModules, primaryDamage = myPlayer.getBuildingDamage(primary, !1);
if (inPrimaryRange && isHammer && notStick && notPolearm && (!reloading.isReloaded(1) || reloading.isFasterThan(0, 1)) && primaryDamage >= target.health) {
return 0;
}
if (isHammer && inSecondaryRange) {
return 1;
}
if (notStick && (notPolearm || !isHammer) && inPrimaryRange) {
return 0;
}
return null;
}
postTick() {
let {EnemyManager: EnemyManager2, myPlayer: myPlayer, ModuleHandler: ModuleHandler} = this.client;
if (!Settings_default._autobreak || ModuleHandler.moduleActive) {
return;
}
let target = this.getDestroyingObject();
if (target === null) {
return;
}
let type = this.getDestroyingWeapon(target);
if (type === null) {
return;
}
let weapon = myPlayer.getItemByType(type), range = this.getWeaponRange(weapon, target), pos1 = myPlayer.pos.current, pos2 = target.pos.current;
if (pos1.distance(pos2) > range) {
return;
}
let angle = pos1.angle(pos2), buildingDamage = myPlayer.getBuildingDamage(weapon, !1), isEnoughDamage = target.health <= buildingDamage, nearestEnemy = EnemyManager2.nearestEnemy, totalDamage = EnemyManager2.primaryDamage + EnemyManager2.potentialSpikeDamage, shouldIgnore = EnemyManager2.instaThreat() || nearestEnemy !== null && nearestEnemy.reload[0].previous !== nearestEnemy.reload[0].current && myPlayer.currentHealth <= totalDamage && myPlayer.currentHealth > totalDamage * .75, {reloading: reloading} = ModuleHandler.staticModules;
if (ModuleHandler.forceWeapon = type, reloading.isReloaded(type) && !shouldIgnore) {
if (ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle, !isEnoughDamage) {
ModuleHandler.forceHat = 40;
}
ModuleHandler.shouldAttack = !0;
}
}
}
class AutoPlacer {
moduleName="autoPlacer";
client;
placementCount=0;
angleList=new Map;
constructor(client2) {
this.client = client2;
}
canKnockbackSpike(newSpikePos, scale, enemy) {
let pos1 = newSpikePos, pos2 = enemy.pos.current, knockbackAngle = pos1.angle(pos2);
if (!(pos1.distance(pos2) <= enemy.collisionScale + scale)) {
return !1;
}
let {ObjectManager: ObjectManager2, PlayerManager: PlayerManager2} = this.client;
return ObjectManager2.grid2D.query(pos1.x, pos1.y, 3, id => {
let object = ObjectManager2.objects.get(id);
if (!object) {
return;
}
let pos3 = object.pos.current, isPlayerObject = object instanceof PlayerObject, isCactus = !isPlayerObject && object.isCactus, isSpike = isPlayerObject && object.itemGroup === 2;
if (!((!isPlayerObject || PlayerManager2.isEnemyByID(object.ownerID, enemy)) && (isSpike || isCactus))) {
return;
}
let KBDistance = 200, spikeScale = object.collisionScale + enemy.collisionScale, angleToSpike = pos1.angle(pos3), distanceToTarget = pos2.distance(pos3), distanceToSpike = pos1.distance(pos3), offset = Math.asin(2 * spikeScale / (2 * distanceToSpike)), intersecting = getAngleDist(knockbackAngle, angleToSpike) <= offset, overlapping = distanceToTarget <= distanceToSpike, inRange2 = enemy.collidingObject(object, KBDistance);
return intersecting && overlapping && inRange2;
});
}
postTick() {
if (!Settings_default._autoplacer) {
return;
}
let {myPlayer: myPlayer, ObjectManager: ObjectManager2, ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2} = this.client, {currentType: currentType} = ModuleHandler, pos0 = myPlayer.pos.current;
if (ModuleHandler.placedOnce) {
return;
}
let nearestEnemy = EnemyManager2.nearestTrappedEnemy || EnemyManager2.nearestEnemy;
if (nearestEnemy === null) {
return;
}
if (!myPlayer.collidingSimple(nearestEnemy, Settings_default._autoplacerRadius)) {
return;
}
if (myPlayer.speed > 5 || ObjectManager2.isDestroyedObject() || nearestEnemy.lastAttacked === myPlayer.tickCount) {
this.angleList.clear();
}
let nearestAngle = pos0.angle(nearestEnemy.pos.current), itemType = null, spike = myPlayer.getItemByType(4), spikeAngles = ObjectManager2.getBestPlacementAngles({
position: pos0,
id: spike,
targetAngle: nearestAngle,
ignoreID: null,
preplace: !0,
reduce: !0,
fill: !0
}), spikeScale = Items[spike].scale, angles = [], length = myPlayer.getItemPlaceScale(spike);
for (let angle of spikeAngles) {
let newPos = pos0.addDirection(angle, length), shouldPlaceSpike = nearestEnemy.wasTrapped(), enemy = EnemyManager2.nearestTrappedEnemy;
if (enemy !== null && !shouldPlaceSpike) {
let distanceToEnemy = newPos.distance(enemy.pos.current), enemyRange = spikeScale + enemy.collisionScale + 8, trap = enemy.trappedIn, distanceToTrap = newPos.distance(trap.pos.current), trapRange = spikeScale + trap.placementScale + 8;
if (distanceToEnemy <= enemyRange || distanceToTrap <= trapRange) {
shouldPlaceSpike = !0;
}
}
if (!shouldPlaceSpike && this.canKnockbackSpike(newPos, spikeScale, nearestEnemy)) {
shouldPlaceSpike = !0;
}
if (shouldPlaceSpike) {
angles = spikeAngles, itemType = 4;
break;
}
}
if (angles.length === 0) {
let type = currentType && currentType !== 2 ? currentType : 7;
if (!myPlayer.canPlace(type)) {
return;
}
let id = myPlayer.getItemByType(type);
if (id === 16) {
return;
}
if (this.placementCount >= 4) {
type = 4;
}
if (angles = ObjectManager2.getBestPlacementAngles({
position: pos0,
id: id,
targetAngle: nearestAngle,
ignoreID: null,
preplace: !0,
reduce: !0,
fill: !0
}), itemType = type, type === 4 && angles.length !== 0) {
this.placementCount = 0;
}
}
if (itemType === null || angles.length === 0) {
return;
}
ModuleHandler.placeAngles[0] = itemType, ModuleHandler.placedOnce = !0;
for (let angle of angles) {
if (!this.angleList.has(angle)) {
this.angleList.set(angle, 0);
}
let angleCount = this.angleList.get(angle);
if (angleCount >= 4) {
continue;
}
this.angleList.set(angle, angleCount + 1), ModuleHandler.place(itemType, angle),
ModuleHandler.placeAngles[1].push(angle);
}
if (itemType !== 4) {
this.placementCount += 1;
}
}
}
const AutoPlacer_default = AutoPlacer;
class AutoSync {
moduleName="autoSync";
client;
useTurret=!1;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._autoSync) {
this.useTurret = !1;
return;
}
let {nearestEnemy: nearestEnemy, nearestEnemyToNearestEnemy: nearestEnemyToNearestEnemy} = EnemyManager2;
if (nearestEnemy === null || nearestEnemyToNearestEnemy === null) {
return;
}
let reloading = ModuleHandler.staticModules.reloading, turretReloaded = reloading.isReloaded(2);
if (this.useTurret) {
if (this.useTurret = !1, turretReloaded) {
ModuleHandler.moduleActive = !0, ModuleHandler.forceHat = 53;
}
return;
}
let primary1 = myPlayer.getItemByType(0), primaryDamage1 = myPlayer.getMaxWeaponDamage(primary1, !1), range1 = DataHandler_default.getWeapon(primary1).range + nearestEnemy.hitScale, isPrimaryReloaded1 = reloading.isReloaded(0), primary2 = nearestEnemyToNearestEnemy.weapon.primary, primaryDamage2 = nearestEnemyToNearestEnemy.getMaxWeaponDamage(primary2, !1), range2 = DataHandler_default.getWeapon(primary2).range + nearestEnemy.hitScale, isPrimaryReloaded2 = nearestEnemyToNearestEnemy.isReloaded(0, 0), soldierDefense = Hats[6].dmgMult;
if ((primaryDamage1 + primaryDamage2) * soldierDefense < 100) {
return;
}
let inWeaponRange1 = myPlayer.collidingSimple(nearestEnemy, range1, myPlayer.getFuturePosition(myPlayer.speed / 3)), inWeaponRange2 = nearestEnemyToNearestEnemy.collidingSimple(nearestEnemy, range2, nearestEnemyToNearestEnemy.getFuturePosition(nearestEnemyToNearestEnemy.speed / 3));
if (!inWeaponRange1 || !inWeaponRange2) {
return;
}
let pos1 = myPlayer.pos.future, pos2 = nearestEnemy.pos.future, angleToEnemy = pos1.angle(pos2);
if (!isPrimaryReloaded1) {
if (ModuleHandler.forceWeapon = 0, isPrimaryReloaded2) {
ModuleHandler.moduleActive = !0;
}
}
if (isPrimaryReloaded1 && isPrimaryReloaded2) {
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angleToEnemy, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0, this.useTurret = !0,
this.client.StatsManager.autoSyncTimes = 1;
}
}
}
class Instakill {
moduleName="instakill";
client;
targetEnemy=null;
constructor(client2) {
this.client = client2;
}
reset() {
this.targetEnemy = null;
}
postTick() {
let {myPlayer: myPlayer, EnemyManager: EnemyManager2, PlayerManager: PlayerManager2, ModuleHandler: ModuleHandler, InputHandler: InputHandler2} = this.client;
if (!InputHandler2.instaToggle) {
this.reset(), InputHandler2.instaReset();
return;
}
let nearestEnemy = EnemyManager2.nearestEnemy;
if (nearestEnemy === null) {
return;
}
let lookingShield = PlayerManager2.lookingShield(nearestEnemy, myPlayer), primary = myPlayer.getItemByType(0), primaryDamage = myPlayer.getMaxWeaponDamage(primary, lookingShield), secondary = myPlayer.getItemByType(1);
if (secondary === null || !DataHandler_default.isShootable(secondary)) {
return;
}
let secondaryDamage = myPlayer.getMaxWeaponDamage(secondary, lookingShield);
if ((primaryDamage + secondaryDamage + 25) * .75 < 100) {
return;
}
let pos1 = myPlayer.pos.future, pos2 = nearestEnemy.pos.future, angle = pos1.angle(pos2);
if (this.targetEnemy !== null) {
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle, ModuleHandler.forceHat = 53,
ModuleHandler.forceWeapon = 1, ModuleHandler.shouldAttack = !0, this.targetEnemy = null,
InputHandler2.instaReset();
return;
}
InputHandler2.instakillTarget = nearestEnemy;
let {reloading: reloading} = ModuleHandler.staticModules, primaryReloaded = reloading.isReloaded(0), secondaryReloaded = reloading.isReloaded(1), turretReloaded = reloading.isReloaded(2), range = DataHandler_default.getWeapon(primary).range + nearestEnemy.hitScale;
if (!primaryReloaded || !secondaryReloaded || !turretReloaded || !myPlayer.collidingSimple(nearestEnemy, range)) {
return;
}
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0, this.targetEnemy = nearestEnemy;
}
}
class AntiRetrap {
moduleName="antiRetrap";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._antiRetrap) {
return;
}
let {reloading: reloading} = ModuleHandler.staticModules, nearestTrap = EnemyManager2.nearestTrap, primary = myPlayer.getItemByType(0), isReloadedPrimary = reloading.isReloaded(0), isHammer = myPlayer.getItemByType(1) === 10, isReloadedSecondary = reloading.isReloaded(1), damage = myPlayer.getBuildingDamage(10, !0), turretReloaded = reloading.isReloaded(2), nearestEnemy = EnemyManager2.nearestEnemy;
if (nearestEnemy === null || nearestTrap === null || nearestTrap.health > damage || !isHammer || !isReloadedSecondary) {
return;
}
let range = DataHandler_default.getWeapon(primary).range + nearestEnemy.hitScale;
if (!myPlayer.collidingEntity(nearestEnemy, range)) {
return;
}
let pos1 = myPlayer.pos.current, pos2 = nearestEnemy.pos.current, angle = pos1.angle(pos2);
if (isReloadedPrimary) {
if (ModuleHandler.moduleActive = !0, ModuleHandler.forceWeapon = 0, ModuleHandler.useAngle = angle,
ModuleHandler.shouldAttack = !0, turretReloaded) {
ModuleHandler.forceHat = 53;
}
}
}
}
class KnockbackTick {
moduleName="knockbackTick";
client;
useTurret=!1;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._knockbackTick || EnemyManager2.shouldIgnoreModule()) {
this.useTurret = !1;
return;
}
let {nearestEnemySpikeCollider: nearestEnemySpikeCollider, spikeCollider: spikeCollider} = EnemyManager2, reloading = ModuleHandler.staticModules.reloading, primary = myPlayer.getItemByType(0), primaryReloaded = reloading.isReloaded(0);
reloading.isReloaded(2);
if (this.useTurret) {
this.useTurret = !1, ModuleHandler.moduleActive = !0, ModuleHandler.forceHat = 53;
return;
}
if (nearestEnemySpikeCollider !== null && !nearestEnemySpikeCollider.isTrapped && spikeCollider !== null && primaryReloaded) {
let pos1 = myPlayer.pos.current, pos2 = nearestEnemySpikeCollider.pos.current, pos3 = spikeCollider.pos.current, angleToEnemy = pos1.angle(pos2), distanceToSpike2 = pos2.distance(pos3), primaryKnockback = DataHandler_default.getWeapon(primary).knockback, knockback = primaryKnockback + 60, collisionScale = spikeCollider.collisionScale + nearestEnemySpikeCollider.collisionScale, collisionRangeTurret = collisionScale + knockback, isPrimaryEnough = distanceToSpike2 <= collisionScale + primaryKnockback;
if (distanceToSpike2 <= collisionRangeTurret) {
let hitRange = DataHandler_default.getWeapon(primary).range + nearestEnemySpikeCollider.hitScale;
if (myPlayer.collidingSimple(nearestEnemySpikeCollider, hitRange)) {
if (ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angleToEnemy,
ModuleHandler.forceHat = 7, ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0,
!isPrimaryEnough) {
this.useTurret = !0;
}
this.client.StatsManager.knockbackTickTimes = 1;
}
}
}
}
}
class KnockbackTickHammer {
moduleName="knockbackTickHammer";
client;
targetEnemy=null;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._knockbackTickHammer || EnemyManager2.shouldIgnoreModule()) {
this.targetEnemy = null;
return;
}
let {nearestEnemySpikeCollider: nearestEnemySpikeCollider, spikeCollider: spikeCollider} = EnemyManager2, reloading = ModuleHandler.staticModules.reloading, primary = myPlayer.getItemByType(0), secondary = myPlayer.getItemByType(1), isHammer = secondary !== null && secondary !== 11, primaryReloaded = reloading.isReloaded(0), secondaryReloaded = reloading.isReloaded(1), turretReloaded = reloading.isReloaded(2), pos1 = myPlayer.pos.current;
if (this.targetEnemy !== null) {
let pos2 = this.targetEnemy.pos.current, angleToEnemy = pos1.angle(pos2);
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angleToEnemy, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0, this.targetEnemy = null,
EnemyManager2.attemptSpikePlacement();
return;
}
if (nearestEnemySpikeCollider !== null && !nearestEnemySpikeCollider.isTrapped && spikeCollider !== null && isHammer && primaryReloaded && secondaryReloaded && turretReloaded) {
let pos2 = nearestEnemySpikeCollider.pos.current, pos3 = spikeCollider.pos.current, angleToEnemy = pos1.angle(pos2), distanceToSpike2 = pos2.distance(pos3), {knockback: primaryKnockback, range: primaryRange} = DataHandler_default.getWeapon(primary), {knockback: secondaryKnockback, range: secondaryRange} = DataHandler_default.getWeapon(secondary), weaponRange = Math.min(primaryRange, secondaryRange) + nearestEnemySpikeCollider.hitScale, minKB = primaryKnockback + 60, maxKB = primaryKnockback + secondaryKnockback + 60, spikeRange = spikeCollider.collisionScale + nearestEnemySpikeCollider.collisionScale;
if (inRange(distanceToSpike2, spikeRange + minKB, spikeRange + maxKB) && myPlayer.collidingSimple(nearestEnemySpikeCollider, weaponRange)) {
let hitRange = DataHandler_default.getWeapon(secondary).range + nearestEnemySpikeCollider.hitScale;
if (myPlayer.collidingSimple(nearestEnemySpikeCollider, hitRange)) {
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angleToEnemy, ModuleHandler.forceHat = 53,
ModuleHandler.forceWeapon = 1, ModuleHandler.shouldAttack = !0, this.targetEnemy = nearestEnemySpikeCollider,
this.client.StatsManager.knockbackTickHammerTimes = 1;
}
}
}
}
}
class KnockbackTickTrap {
moduleName="knockbackTickTrap";
client;
targetEnemy=null;
useTurret=!1;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._knockbackTickTrap || EnemyManager2.shouldIgnoreModule()) {
this.targetEnemy = null, this.useTurret = !1;
return;
}
let {nearestEnemySpikeCollider: nearestEnemySpikeCollider, nearestTrappedEnemy: nearestTrappedEnemy, spikeCollider: spikeCollider} = EnemyManager2, reloading = ModuleHandler.staticModules.reloading, primary = myPlayer.getItemByType(0), secondary = myPlayer.getItemByType(1), isHammer = secondary === 10, primaryReloaded = reloading.isReloaded(0), secondaryReloaded = reloading.isReloaded(1), turretReloaded = reloading.isReloaded(2);
if (this.useTurret) {
if (turretReloaded) {
ModuleHandler.moduleActive = !0, ModuleHandler.forceHat = 53;
}
this.useTurret = !1;
return;
}
let pos1 = myPlayer.pos.current;
if (this.targetEnemy !== null) {
let pos2 = this.targetEnemy.pos.current, angleToEnemy = pos1.angle(pos2);
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angleToEnemy, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0, this.targetEnemy = null,
this.useTurret = !0;
return;
}
if (nearestEnemySpikeCollider !== null && nearestTrappedEnemy !== null && nearestTrappedEnemy === nearestEnemySpikeCollider && spikeCollider !== null && isHammer && primaryReloaded && secondaryReloaded) {
let nearestTrap = nearestTrappedEnemy.trappedIn, hammer = DataHandler_default.getWeapon(secondary), playerRange = hammer.range + nearestTrappedEnemy.hitScale, trapRange = hammer.range + nearestTrap.hitScale, canAttackEnemy = myPlayer.collidingSimple(nearestTrappedEnemy, playerRange), canAttackTrap = myPlayer.collidingSimple(nearestTrap, trapRange), buildingDamage = myPlayer.getBuildingDamage(secondary, !0);
if (!canAttackEnemy || !canAttackTrap || nearestTrap.health > buildingDamage) {
return;
}
let pos12 = myPlayer.pos.current, pos2 = nearestTrappedEnemy.pos.current, pos3 = nearestTrap.pos.current, pos4 = spikeCollider.pos.current, angleToEnemy = pos12.angle(pos2), angleToTrap = pos12.angle(pos3), middleAngle = findMiddleAngle(angleToEnemy, angleToTrap), distanceToSpike2 = pos2.distance(pos4), turretKnockback = 60, knockback = DataHandler_default.getWeapon(primary).knockback + turretKnockback, collisionRange = spikeCollider.collisionScale + nearestEnemySpikeCollider.collisionScale + knockback;
if (distanceToSpike2 <= collisionRange) {
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = middleAngle, ModuleHandler.forceHat = 40,
ModuleHandler.forceWeapon = 1, ModuleHandler.shouldAttack = !0, this.targetEnemy = nearestTrappedEnemy,
this.client.StatsManager.knockbackTickTrapTimes = 1;
}
}
}
}
class SpikeSync {
moduleName="spikeSync";
client;
useTurret=!1;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._spikeSync) {
this.useTurret = !1;
return;
}
let {nearestEnemy: nearest, nearestSpikePlacerAngle: placementAngles} = EnemyManager2, reloading = ModuleHandler.staticModules.reloading, primary = myPlayer.getItemByType(0), isPolearm = primary !== 8, primaryReloaded = reloading.isReloaded(0), turretReloaded = reloading.isReloaded(2);
if (this.useTurret) {
if (this.useTurret = !1, turretReloaded && !EnemyManager2.shouldIgnoreModule()) {
ModuleHandler.moduleActive = !0, ModuleHandler.forceHat = 53;
}
return;
}
if (!EnemyManager2.shouldIgnoreModule() && nearest !== null && EnemyManager2.canSpikeSync && placementAngles !== null && isPolearm && primaryReloaded) {
let range = DataHandler_default.getWeapon(primary).range + nearest.hitScale;
if (!myPlayer.collidingSimple(nearest, range)) {
return;
}
let pos1 = myPlayer.pos.current, pos2 = nearest.pos.current, angleTo = pos1.angle(pos2), itemType = 4;
for (let angle of placementAngles) {
ModuleHandler.place(itemType, angle);
}
ModuleHandler.placedOnce = !0, ModuleHandler.placeAngles[0] = itemType, ModuleHandler.placeAngles[1] = placementAngles,
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angleTo, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0, this.client.StatsManager.spikeSyncTimes = 1,
this.useTurret = !0;
}
}
}
class SpikeSyncHammer {
moduleName="spikeSyncHammer";
client;
targetEnemy=null;
useTurret=!1;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer, ObjectManager: ObjectManager2} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._spikeSyncHammer || EnemyManager2.shouldIgnoreModule()) {
this.targetEnemy = null, this.useTurret = !1;
return;
}
let nearestSyncEnemy = EnemyManager2.nearestSyncEnemy, reloading = ModuleHandler.staticModules.reloading, primary = myPlayer.getItemByType(0), secondary = myPlayer.getItemByType(1), isPolearm = primary !== 8, isHammer = secondary === 10, primaryReloaded = reloading.isReloaded(0), secondaryReloaded = reloading.isReloaded(1), turretReloaded = reloading.isReloaded(2);
if (this.useTurret) {
if (turretReloaded) {
ModuleHandler.moduleActive = !0, ModuleHandler.forceHat = 53;
}
this.useTurret = !1;
return;
}
if (this.targetEnemy !== null) {
let nearest = this.targetEnemy, pos1 = myPlayer.pos.current, pos2 = nearest.pos.current, itemType = 4, spikeID = myPlayer.getItemByType(itemType), placeLength = myPlayer.getItemPlaceScale(spikeID), angleToNearest = pos1.angle(pos2), spikePos = pos1.addDirection(angleToNearest, placeLength), angleFromSpike = spikePos.angle(pos2), futureEnemyPos = spikePos.addDirection(angleFromSpike, 140), futureAngle = pos1.angle(futureEnemyPos), placementAngles = EnemyManager2.nearestSpikePlacerAngle;
if (placementAngles !== null) {
for (let angle of placementAngles) {
ModuleHandler.place(itemType, angle);
}
ModuleHandler.placedOnce = !0, ModuleHandler.placeAngles[0] = itemType, ModuleHandler.placeAngles[1] = placementAngles,
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = futureAngle, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0;
}
this.targetEnemy = null, this.useTurret = !0;
return;
}
if (nearestSyncEnemy !== null && isPolearm && primaryReloaded && isHammer && secondaryReloaded) {
let nearestLowHPObject = EnemyManager2.nearestLowHPObject;
if (nearestLowHPObject === null) {
return;
}
let hammer = DataHandler_default.getWeapon(secondary), playerRange = hammer.range + nearestSyncEnemy.hitScale, trapRange = hammer.range + nearestLowHPObject.hitScale, canAttackEnemy = myPlayer.collidingSimple(nearestSyncEnemy, playerRange), canAttackTrap = myPlayer.collidingSimple(nearestLowHPObject, trapRange), buildingDamage = myPlayer.getBuildingDamage(secondary, !0);
if (!canAttackEnemy || !canAttackTrap || nearestLowHPObject.health > buildingDamage) {
return;
}
let itemType = 4, spikeID = myPlayer.getItemByType(itemType), placeLength = myPlayer.getItemPlaceScale(spikeID), pos1 = myPlayer.pos.current, pos2 = nearestSyncEnemy.pos.current, pos3 = nearestLowHPObject.pos.current, angleToEnemy = pos1.angle(pos2), angleToTrap = pos1.angle(pos3), middleAngle = findMiddleAngle(angleToEnemy, angleToTrap), angles = ObjectManager2.getBestPlacementAngles({
position: pos1,
id: spikeID,
targetAngle: angleToEnemy,
ignoreID: nearestLowHPObject.id,
preplace: !1,
reduce: !1,
fill: !1
}), spikeScale = Items[spikeID].scale, possibleAngles = angles.filter(angle => {
let spikePos = pos1.addDirection(angle, placeLength), distance = pos2.distance(spikePos), range = nearestSyncEnemy.collisionScale + spikeScale;
return distance <= range;
});
if (possibleAngles.length !== 0) {
ModuleHandler.placeAngles[0] = itemType, ModuleHandler.placeAngles[1] = possibleAngles,
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = middleAngle, ModuleHandler.forceHat = 40,
ModuleHandler.forceWeapon = 1, ModuleHandler.shouldAttack = !0, this.targetEnemy = nearestSyncEnemy,
this.client.StatsManager.spikeSyncHammerTimes = 1;
}
}
}
}
class SpikeTick {
moduleName="spikeTick";
client;
useTurret=!1;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._spikeTick) {
return;
}
let reloading = ModuleHandler.staticModules.reloading, primary = myPlayer.getItemByType(0), isPrimary = primary !== 8, primaryReloaded = reloading.isReloaded(0), turretReloaded = reloading.isReloaded(2), spikeCollider = EnemyManager2.enemySpikeCollider;
if (this.useTurret) {
if (this.useTurret = !1, turretReloaded) {
ModuleHandler.moduleActive = !0, ModuleHandler.forceHat = 53;
return;
}
}
if (EnemyManager2.shouldIgnoreModule() || !isPrimary || !primaryReloaded || spikeCollider === null) {
return;
}
let range = DataHandler_default.getWeapon(primary).range + spikeCollider.hitScale;
if (!myPlayer.collidingEntity(spikeCollider, range, !0)) {
return;
}
let pos1 = myPlayer.pos.future, pos2 = spikeCollider.pos.future, angle = pos1.angle(pos2);
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0, EnemyManager2.attemptSpikePlacement(),
this.useTurret = !0, this.client.StatsManager.spikeTickTimes = 1;
}
}
const SpikeTick_default = SpikeTick;
class ToolHammerSpearInsta {
moduleName="toolHammerSpearInsta";
client;
nearestTarget=null;
useTurret=!1;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, myPlayer: myPlayer, EnemyManager: EnemyManager2} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._toolSpearInsta) {
this.nearestTarget = null;
return;
}
let nearestEnemy = EnemyManager2.nearestEnemy;
if (nearestEnemy === null || !ModuleHandler.canBuy(0, 7)) {
return;
}
if (this.useTurret) {
if (ModuleHandler.canBuy(0, 53)) {
ModuleHandler.moduleActive = !0, ModuleHandler.forceHat = 53;
}
this.useTurret = !1;
return;
}
if (myPlayer.upgradeAge !== 2) {
return;
}
let pos1 = myPlayer.pos.current;
if (this.nearestTarget !== null) {
let pos22 = this.nearestTarget.pos.current, angle2 = pos1.angle(pos22);
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle2, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0, ModuleHandler.upgradeItem(5),
this.nearestTarget = null, this.useTurret = !0, EnemyManager2.attemptSpikePlacement();
return;
}
let pos2 = nearestEnemy.pos.current, angle = pos1.angle(pos2), {reloading: reloading} = ModuleHandler.staticModules, primaryReloaded = reloading.isReloaded(0), turretReloaded = reloading.isReloaded(2), range = DataHandler_default.getWeapon(0).range + nearestEnemy.hitScale;
if (!primaryReloaded || !turretReloaded || !myPlayer.collidingSimple(nearestEnemy, range)) {
return;
}
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0, this.nearestTarget = nearestEnemy;
}
}
class VelocityTick {
moduleName="velocityTick";
client;
nearestTarget=null;
target=null;
minKB=220;
maxKB=245;
constructor(client2) {
this.client = client2;
}
isValidHat(hatID) {
return hatID !== null && hatID !== 6 && hatID !== 22;
}
postTick() {
let {EnemyManager: EnemyManager2, myPlayer: myPlayer, ModuleHandler: ModuleHandler} = this.client;
if (this.target = null, ModuleHandler.moduleActive || !Settings_default._velocityTick || ModuleHandler.moveTo !== "disable" || EnemyManager2.shouldIgnoreModule()) {
this.nearestTarget = null;
return;
}
let {reloading: reloading} = ModuleHandler.staticModules, nearestEnemy = EnemyManager2.nearestEnemy, primary = myPlayer.getItemByType(0), isPolearm = primary === 5, isDiamond = myPlayer.getWeaponVariant(primary).current >= 2, isReloadedPrimary = reloading.isReloaded(0), isReloadedTurret = reloading.isReloaded(2);
if (this.nearestTarget !== null) {
let pos1 = myPlayer.pos.current, pos22 = this.nearestTarget.pos.current, angle2 = pos1.angle(pos22);
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle2, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0, ModuleHandler.moveTo = angle2,
this.nearestTarget = null;
return;
}
if (nearestEnemy === null || !isPolearm || !isDiamond || !isReloadedPrimary || !isReloadedTurret) {
return;
}
this.target = nearestEnemy;
let pos0 = myPlayer.pos.current, pos2 = nearestEnemy.pos.future, distance = pos0.distance(pos2), angle = pos0.angle(pos2), {current: current} = nearestEnemy.weapon, type = DataHandler_default.getWeapon(current).type, almostReloaded = DataHandler_default.isMelee(current) && nearestEnemy.atExact(type, 1), detectFutureHat = this.isValidHat(nearestEnemy.futureHat), canSend = almostReloaded || detectFutureHat;
if (inRange(distance, this.minKB, this.maxKB) && canSend) {
ModuleHandler.moduleActive = !0, ModuleHandler.forceHat = 53, ModuleHandler.moveTo = angle,
this.nearestTarget = nearestEnemy, this.client.StatsManager.velocityTickTimes = 1;
}
}
}
class Placer {
moduleName="placer";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, myPlayer: myPlayer} = this.client, {currentType: currentType, placedOnce: placedOnce, healedOnce: healedOnce, currentAngle: currentAngle} = ModuleHandler;
if (!myPlayer.canPlace(currentType)) {
return;
}
if (currentType === 2) {
if (healedOnce) {
return;
}
if (myPlayer.shameCount < 7) {
ModuleHandler.heal(), ModuleHandler.healedOnce = !0, ModuleHandler.didAntiInsta = !0;
}
return;
}
if (placedOnce) {
return;
}
ModuleHandler.place(currentType, currentAngle), ModuleHandler.placedOnce = !0;
}
}
const Placer_default = Placer;
class PreAttack {
moduleName="preAttack";
client;
constructor(client2) {
this.client = client2;
}
isReloadedByType(type) {
let {weapon: weapon, staticModules: staticModules} = this.client.ModuleHandler, weaponType = type !== null ? type : weapon;
return staticModules.reloading.isReloaded(weaponType);
}
postTick() {
let {ModuleHandler: ModuleHandler} = this.client, {useWeapon: useWeapon, weapon: weapon, forceWeapon: forceWeapon} = ModuleHandler, nextWeapon = forceWeapon !== null ? forceWeapon : useWeapon, forceReloaded = this.isReloadedByType(nextWeapon), canAttack = ModuleHandler.shouldAttack && (forceReloaded && this.isReloadedByType(weapon) || forceWeapon !== null && forceReloaded);
ModuleHandler.shouldAttack = canAttack;
}
}
const PreAttack_default = PreAttack;
class Reloading {
moduleName="reloading";
client;
clientReload=[ {}, {}, {} ];
constructor(client2) {
this.client = client2, this.reset();
}
reset() {
let [primary, secondary, turret] = this.clientReload;
primary.current = primary.max = 0, secondary.current = secondary.max = 0, turret.current = turret.max = 23;
}
get currentReload() {
return this.clientReload[this.client.ModuleHandler.weapon];
}
getReload(type) {
return this.clientReload[type];
}
updateMaxReload(type) {
let {myPlayer: myPlayer, ModuleHandler: ModuleHandler, SocketManager: SocketManager2} = this.client, reload = this.getReload(type), id = myPlayer.getItemByType(type), store2 = ModuleHandler.getHatStore(), pingAccount = Math.floor(SocketManager2.pong / SocketManager2.TICK), speed = myPlayer.getWeaponSpeed(id, store2.last) - pingAccount;
reload.current = speed, reload.max = speed;
}
resetReload(reload) {
reload.current = -1;
}
resetByType(type) {
this.resetReload(this.getReload(type));
}
isReloaded(type, ticks = 0) {
let reload = this.clientReload[type];
return reload.current >= reload.max - ticks;
}
isFasterThan(type1, type2) {
let reload1 = this.clientReload[type1], reload2 = this.clientReload[type2], data1 = reload1.max - reload1.current, data2 = reload2.max - reload2.current;
return Math.abs(data1) <= Math.abs(data2);
}
isEmptyReload(type) {
return this.clientReload[type].current === 0;
}
postTick() {
let {myPlayer: myPlayer} = this.client, primaryReload = myPlayer.reload[0].current, secondaryReload = myPlayer.reload[1].current;
if (primaryReload !== -1) {
this.clientReload[0].current = primaryReload;
}
if (secondaryReload !== -1) {
this.clientReload[1].current = secondaryReload;
}
this.clientReload[2].current = myPlayer.reload[2].current;
}
}
const Reloading_default = Reloading;
class UpdateAngle {
moduleName="updateAngle";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {sentAngle: sentAngle, currentAngle: currentAngle} = this.client.ModuleHandler;
if (sentAngle > 1) {
return;
}
this.client.ModuleHandler.updateAngle(currentAngle);
}
}
const UpdateAngle_default = UpdateAngle;
class UpdateAttack {
moduleName="updateAttack";
client;
didReset=!1;
constructor(client2) {
this.client = client2;
}
getAttackAngle() {
let {useAngle: useAngle, currentAngle: currentAngle} = this.client.ModuleHandler;
if (useAngle !== null) {
return useAngle;
}
return currentAngle;
}
postTick() {
let {ModuleHandler: ModuleHandler, myPlayer: myPlayer} = this.client, {useWeapon: useWeapon, forceWeapon: forceWeapon, weapon: weapon, attacking: attacking, useItem: useItem, sentAngle: sentAngle, staticModules: staticModules} = ModuleHandler, {reloading: reloading} = staticModules, nextWeapon = forceWeapon !== null ? forceWeapon : useWeapon;
if (nextWeapon !== null && (nextWeapon !== weapon || ModuleHandler.currentHolding !== nextWeapon || myPlayer.currentItem !== -1)) {
if (reloading.isReloaded(weapon) || forceWeapon !== null) {
ModuleHandler.whichWeapon(nextWeapon);
}
}
if (useItem !== null) {
ModuleHandler.selectItem(useItem);
}
if (ModuleHandler.shouldAttack) {
let angle = this.getAttackAngle();
ModuleHandler.attack(angle), ModuleHandler.stopAttack();
let weaponType = ModuleHandler.weapon;
if (ModuleHandler.attacked) {
reloading.updateMaxReload(weaponType);
}
reloading.resetByType(weaponType);
} else if (!attacking && sentAngle !== 0) {
ModuleHandler.stopAttack(), this.didReset = !0;
} else if (this.didReset) {
this.didReset = !1, ModuleHandler.stopAttack();
}
}
}
const UpdateAttack_default = UpdateAttack;
class UseAttacking {
moduleName="useAttacking";
client;
constructor(client2) {
this.client = client2;
}
getWeaponType() {
let {EnemyManager: EnemyManager2, myPlayer: myPlayer, ModuleHandler: ModuleHandler} = this.client, pos1 = myPlayer.pos.future, nearestEntity = EnemyManager2.nearestEntity, nearestObject = EnemyManager2.nearestObject, primaryID = myPlayer.getItemByType(0), secondaryID = myPlayer.getItemByType(1), range = DataHandler_default.getWeapon(primaryID).range;
if (nearestEntity !== null) {
let pos2 = nearestEntity.pos.future, angle = pos1.angle(pos2);
if (myPlayer.collidingEntity(nearestEntity, range + nearestEntity.hitScale)) {
return [ 0, angle ];
}
if (DataHandler_default.isShootable(secondaryID) && !ModuleHandler.autoattack) {
return [ 1, angle ];
}
}
if (nearestObject === null) {
return null;
}
if (myPlayer.colliding(nearestObject, range + nearestObject.hitScale)) {
return [ 0, null ];
}
return null;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive || ModuleHandler.attackingState !== 1 || ModuleHandler.forceWeapon !== null) {
return;
}
let weaponType = this.getWeaponType();
if (weaponType === null) {
return;
}
let [type, angle] = weaponType;
if (ModuleHandler.forceWeapon = type, angle !== null) {
ModuleHandler.useAngle = angle;
}
ModuleHandler.shouldAttack = !0;
}
}
class UseDestroying {
moduleName="useDestroying";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {myPlayer: myPlayer, ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2} = this.client;
if (ModuleHandler.moduleActive || ModuleHandler.attackingState !== 2 || ModuleHandler.forceWeapon !== null) {
return;
}
let nearestObject = EnemyManager2.nearestPlayerObject, type = myPlayer.getBestDestroyingWeapon(nearestObject);
ModuleHandler.forceWeapon = type, ModuleHandler.shouldAttack = !0;
}
}
class UseFastest {
moduleName="useFastest";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {myPlayer: myPlayer, ModuleHandler: ModuleHandler} = this.client;
if (ModuleHandler.moduleActive) {
return;
}
let {reloading: reloading} = ModuleHandler.staticModules, type = myPlayer.getFastestWeapon(), reverse_type = type === 0 ? 1 : 0;
if (!reloading.isReloaded(type)) {
ModuleHandler.useWeapon = type;
} else if (!reloading.isReloaded(reverse_type) && myPlayer.getItemByType(reverse_type) !== null) {
ModuleHandler.useWeapon = reverse_type;
} else {
ModuleHandler.useWeapon = type;
}
}
}
class UtilityHat {
moduleName="utilityHat";
client;
constructor(client2) {
this.client = client2;
}
getBestUtilityHat(weaponType) {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client, id = myPlayer.getItemByType(weaponType);
if (id === 11) {
return null;
}
if (DataHandler_default.isShootable(id)) {
return ModuleHandler.canHitEntity = !0, 20;
}
let weapon = DataHandler_default.getWeapon(id), range = weapon.range;
if (weapon.damage <= 1) {
return null;
}
if (ModuleHandler.attackingState === 1) {
let nearest = EnemyManager2.nearestEntity;
if (nearest !== null && myPlayer.collidingEntity(nearest, range + nearest.hitScale)) {
return ModuleHandler.canHitEntity = !0, 7;
}
}
if (ModuleHandler.attackingState !== 0) {
let nearestObject = EnemyManager2.nearestPlayerObject;
if (nearestObject === null) {
return null;
}
if (myPlayer.colliding(nearestObject, range + nearestObject.hitScale)) {
return 40;
}
}
return null;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive) {
return;
}
let {forceWeapon: forceWeapon, useWeapon: useWeapon, weapon: weapon} = ModuleHandler, weaponType = forceWeapon !== null ? forceWeapon : useWeapon !== null ? useWeapon : weapon, hat = this.getBestUtilityHat(weaponType), {reloading: reloading} = ModuleHandler.staticModules, isReloaded = reloading.isReloaded(weaponType), isEmptyReload = reloading.isEmptyReload(weaponType), turretReloaded = reloading.isReloaded(2);
if (!isReloaded) {
hat = null;
}
if (ModuleHandler.canHitEntity && isEmptyReload && turretReloaded) {
let nearest = EnemyManager2.nearestEntity;
if (nearest !== null && myPlayer.collidingEntity(nearest, 700)) {
hat = 53;
}
}
if (hat !== null) {
ModuleHandler.useHat = hat;
}
}
}
class AntiInsta {
moduleName="antiInsta";
client;
toggleAnti=!1;
healingCount=0;
constructor(client2) {
this.client = client2;
}
isSaveHealTime() {
let {myPlayer: myPlayer, SocketManager: SocketManager2} = this.client, startHit = myPlayer.receivedDamage || 0;
return Date.now() - startHit + SocketManager2.pong >= 125;
}
isSaveHealTick() {
let {tickCount: tickCount, damageTick: damageTick} = this.client.myPlayer;
return tickCount - damageTick > 0;
}
isSaveHeal() {
return this.isSaveHealTime();
}
postTick() {
if (!Settings_default._autoheal) {
return;
}
let {myPlayer: myPlayer, ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, ProjectileManager: ProjectileManager2} = this.client;
if (myPlayer.shameActive) {
return;
}
let foodID = myPlayer.getItemByType(2), restore = Items[foodID].restore, needTimes = Math.ceil((myPlayer.maxHealth - myPlayer.tempHealth) / restore), healingTimes = null, forceHeal = !1;
if (EnemyManager2.velocityTickThreat || EnemyManager2.reverseInsta || EnemyManager2.rangedBowInsta || EnemyManager2.detectedDangerEnemy || EnemyManager2.detectedEnemy || myPlayer.tempHealth <= 20 || ModuleHandler.shouldEquipSoldier && ModuleHandler.forceHat !== 6 || EnemyManager2.dangerWithoutSoldier) {
forceHeal = !0;
}
if (myPlayer.shameCount < 7 && forceHeal && myPlayer.tempHealth < 95) {
ModuleHandler.didAntiInsta = !0, healingTimes = needTimes || 1;
} else if (this.isSaveHeal() && myPlayer.tempHealth < 100) {
healingTimes = needTimes || 1;
}
if (healingTimes !== null) {
ModuleHandler.healedOnce = !0;
for (let i = 0; i <= healingTimes; i++) {
ModuleHandler.heal();
}
}
}
}
const AntiInsta_default = AntiInsta;
class Autohat {
moduleName="autoHat";
client;
constructor(client2) {
this.client = client2;
}
handleEquip(type, use) {
let {ModuleHandler: ModuleHandler} = this.client;
if (type === 0 && ModuleHandler.forceHat !== null) {
use = ModuleHandler.forceHat;
}
if (use !== null && ModuleHandler.equip(type, use)) {
return !0;
}
return !1;
}
postTick() {
let {ModuleHandler: ModuleHandler} = this.client;
if (!ModuleHandler.sentHatEquip) {
this.handleEquip(0, ModuleHandler.useHat);
}
if (!ModuleHandler.sentAccEquip && !ModuleHandler.sentHatEquip) {
this.handleEquip(1, ModuleHandler.useAcc);
}
}
}
const Autohat_default = Autohat;
class DefaultAcc {
moduleName="defaultAcc";
client;
constructor(client2) {
this.client = client2;
}
shouldUseTail() {
let {ModuleHandler: ModuleHandler, myPlayer: myPlayer} = this.client, {reloading: reloading} = ModuleHandler.staticModules, primary = myPlayer.getItemByType(0), secondary = myPlayer.getItemByType(1);
return DataHandler_default.isMelee(primary) && primary !== 8 && !reloading.isReloaded(0, 2) || DataHandler_default.isMelee(secondary) && !reloading.isReloaded(1, 2);
}
getBestCurrentAcc() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2} = this.client, {actual: actual} = ModuleHandler.getAccStore(), useCorrupt = ModuleHandler.canBuy(1, 21), useShadow = ModuleHandler.canBuy(1, 19), useTail = ModuleHandler.canBuy(1, 11), useActual = ModuleHandler.canBuy(1, actual);
if (EnemyManager2.detectedEnemy || EnemyManager2.nearestEnemyInRangeOf(300, EnemyManager2.nearestEntity)) {
if (EnemyManager2.nearestEntity === EnemyManager2.nearestEnemy && useCorrupt && Settings_default._antienemy) {
return 21;
}
if (useShadow) {
return 19;
}
if (useActual && actual !== 11) {
return actual;
}
return 0;
}
if (useTail) {
return 11;
}
return 0;
}
postTick() {
let {ModuleHandler: ModuleHandler} = this.client, acc = this.getBestCurrentAcc();
ModuleHandler.useAcc = acc;
}
}
class DefaultHat {
moduleName="defaultHat";
client;
platformActivated=!1;
constructor(client2) {
this.client = client2;
}
getBestCurrentHat() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client, {current: current, future: future} = myPlayer.pos, {actual: actual} = ModuleHandler.getHatStore(), useFlipper = ModuleHandler.canBuy(0, 31), useSoldier = ModuleHandler.canBuy(0, 6), useWinter = ModuleHandler.canBuy(0, 15), useActual = ModuleHandler.canBuy(0, actual), useBooster = ModuleHandler.canBuy(0, 12), useBull = ModuleHandler.canBuy(0, 7), useEmp = ModuleHandler.canBuy(0, 22);
if (useActual && !ModuleHandler.isMoving && myPlayer.speed <= 5 && actual !== 0) {
return actual;
}
if (useSoldier) {
if (Settings_default._antienemy) {
if (EnemyManager2.detectedDangerEnemy || EnemyManager2.detectedEnemy || EnemyManager2.velocityTickThreat || EnemyManager2.reverseInsta || EnemyManager2.rangedBowInsta) {
return ModuleHandler.shouldEquipSoldier = !0, ModuleHandler.forceHat = 6, 6;
}
if (useBull && myPlayer.shameCount > 0 || EnemyManager2.dangerWithoutSoldier) {
return 6;
}
}
if (Settings_default._antispike && EnemyManager2.willCollideSpike) {
return 6;
}
}
if (Settings_default._biomehats && useFlipper) {
if (pointInRiver(current) || pointInRiver(future)) {
return 31;
}
}
if (useSoldier) {
if (Settings_default._antianimal && EnemyManager2.nearestDangerAnimal !== null) {
return 6;
}
}
if (useEmp && Settings_default._empDefense && (!ModuleHandler.isMoving || myPlayer.speed <= 5)) {
return 22;
}
if (Settings_default._biomehats && useWinter) {
if (current.y <= 2400 || future.y <= 2400) {
return 15;
}
}
if (useBooster) {
return 12;
}
return 0;
}
postTick() {
let {ModuleHandler: ModuleHandler} = this.client, hat = this.getBestCurrentHat();
ModuleHandler.useHat = hat;
}
}
class SafeWalk {
moduleName="safeWalk";
client;
movingState=!1;
constructor(client2) {
this.client = client2;
}
reset() {
this.movingState = !1;
}
willGetHit(angle, speed, target) {
if (angle === null || !Settings_default._safeWalk) {
return !1;
}
let {myPlayer: myPlayer} = this.client, nearestCollider = target;
if (nearestCollider === null) {
return !1;
}
let distance = Vector_default.fromAngle(angle, speed + myPlayer.speed / 4).add(myPlayer.pos.current).distance(nearestCollider.pos.current), range = myPlayer.collisionScale + nearestCollider.collisionScale;
if (distance > range) {
return !1;
}
return !0;
}
postTick() {
let {ModuleHandler: ModuleHandler, myPlayer: myPlayer, ObjectManager: ObjectManager2, EnemyManager: EnemyManager2} = this.client, {prevMoveTo: prevMoveTo, moveTo: moveTo} = ModuleHandler;
if (prevMoveTo !== moveTo) {
let angle = moveTo === "disable" ? ModuleHandler.move_dir : moveTo;
ModuleHandler.startMovement(angle, !0);
return;
}
let offset = myPlayer.speed + 45;
if (this.willGetHit(ModuleHandler.move_dir, offset, EnemyManager2.nearestCollider) || this.willGetHit(ModuleHandler.move_dir, offset, EnemyManager2.secondNearestCollider)) {
if (!this.movingState) {
this.movingState = !0, ModuleHandler.stopMovement();
}
return;
}
if (this.movingState) {
this.movingState = !1, ModuleHandler.startMovement();
}
}
}
class ShameReset {
moduleName="shameReset";
client;
tickToggle=!1;
constructor(client2) {
this.client = client2;
}
isBullTickTime() {
let {myPlayer: myPlayer} = this.client;
return !myPlayer.shameActive && myPlayer.shameCount > 0 && myPlayer.poisonCount === 0 && myPlayer.isBullTickTime();
}
get shouldReset() {
let {ModuleHandler: ModuleHandler} = this.client;
return this.isBullTickTime() && ModuleHandler.canBuy(0, 7);
}
notSave() {
let {EnemyManager: EnemyManager2, myPlayer: myPlayer, ModuleHandler: ModuleHandler} = this.client;
return ModuleHandler.forceHat === 40 || EnemyManager2.instaThreat() || EnemyManager2.collidingSpike || myPlayer.wasTrapped() || ModuleHandler.currentType === 2;
}
postTick() {
let {ModuleHandler: ModuleHandler} = this.client;
if (!this.notSave() && (this.shouldReset || this.tickToggle)) {
this.tickToggle = !0, ModuleHandler.moduleActive = !0, ModuleHandler.forceHat = 7;
}
}
healthUpdate() {
if (this.client.myPlayer.isDmgOverTime) {
this.tickToggle = !1;
}
}
}
const ShameReset_default = ShameReset;
class AutoAccept {
moduleName="autoAccept";
client;
prevClan=null;
constructor(client2) {
this.client = client2;
}
postTick() {
let {myPlayer: myPlayer, clientIDList: clientIDList, PacketManager: PacketManager2, isOwner: isOwner} = this.client, currentClan = myPlayer.clanName;
if (currentClan !== this.prevClan) {
this.prevClan = currentClan, myPlayer.joinRequests.length = 0, this.client.pendingJoins.clear();
}
if (!myPlayer.isLeader || myPlayer.joinRequests.length === 0) {
return;
}
let id = myPlayer.joinRequests[0][0];
if (Settings_default._autoaccept || this.client.pendingJoins.size !== 0) {
if (PacketManager2.clanRequest(id, Settings_default._autoaccept || clientIDList.has(id)),
myPlayer.joinRequests.shift(), this.client.pendingJoins.delete(id), isOwner) {
GameUI_default.clearNotication();
}
}
let nextID = myPlayer.joinRequests[0];
if (isOwner && nextID !== void 0) {
GameUI_default.createRequest(nextID);
}
}
}
const AutoAccept_default = AutoAccept;
class AutoBuy {
moduleName="autoBuy";
client;
buyIndex=0;
buyList=[ [ 1, 11 ], [ 0, 12 ], [ 0, 7 ], [ 0, 6 ], [ 0, 40 ], [ 0, 53 ], [ 1, 21 ], [ 0, 11 ], [ 1, 19 ], [ 0, 15 ], [ 0, 31 ], [ 0, 20 ], [ 0, 22 ] ];
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, myPlayer: myPlayer} = this.client;
if (this.buyIndex >= this.buyList.length || !myPlayer.isSandbox) {
return;
}
let [type, id] = this.buyList[this.buyIndex];
if (ModuleHandler.canBuy(type, id)) {
ModuleHandler.buy(type, id);
}
if (ModuleHandler.bought[type].has(id)) {
this.buyIndex += 1;
}
}
}
class AutoGrind {
moduleName="autoGrind";
client;
constructor(client2) {
this.client = client2;
}
isFullyUpgraded() {
let {myPlayer: myPlayer} = this.client, primary = myPlayer.getItemByType(0), secondary = myPlayer.getItemByType(1), upgradedSecondary = secondary === 10 && myPlayer.getWeaponVariant(secondary).current >= 1, upgradedPrimary = primary !== 8 && myPlayer.getWeaponVariant(primary).current >= 2;
return upgradedSecondary && upgradedPrimary;
}
getGrindWeapon() {
let {myPlayer: myPlayer, EnemyManager: EnemyManager2, ModuleHandler: ModuleHandler} = this.client, nearestObject = EnemyManager2.nearestPlayerObject, secondNearestObject = EnemyManager2.secondNearestPlayerObject;
if (nearestObject === null) {
return null;
}
let primary = myPlayer.getItemByType(0), secondary = myPlayer.getItemByType(1);
if (secondary === 10) {
if (myPlayer.getWeaponVariant(secondary).current < 1) {
return 1;
}
let useTank = ModuleHandler.canBuy(0, 40), damage = myPlayer.getBuildingDamage(10, useTank), range = DataHandler_default.getWeapon(secondary).range, canHit1 = myPlayer.colliding(nearestObject, range + nearestObject.hitScale) && nearestObject.health > damage, canHit2 = secondNearestObject !== null && myPlayer.colliding(secondNearestObject, range + secondNearestObject.hitScale) && secondNearestObject.health > damage;
if (canHit1 && canHit2) {
return 1;
}
}
if (primary !== 8 && myPlayer.getWeaponVariant(primary).current < 2) {
return 0;
}
return null;
}
placeTurret(angle) {
let {myPlayer: myPlayer, ObjectManager: ObjectManager2, ModuleHandler: ModuleHandler} = this.client, id = myPlayer.getItemByType(8), position = myPlayer.getPlacePosition(myPlayer.pos.future, id, angle);
if (!ObjectManager2.canPlaceItem(id, position)) {
return !1;
}
let type = 8;
return ModuleHandler.place(type, angle), ModuleHandler.placedOnce = !0, ModuleHandler.placeAngles[0] = 8,
ModuleHandler.placeAngles[1].push(angle), !0;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (!Settings_default._autoGrind || ModuleHandler.moduleActive || ModuleHandler.placedOnce || ModuleHandler.healedOnce || ModuleHandler.isMoving || myPlayer.speed > 5 || this.isFullyUpgraded()) {
return;
}
let {autoMill: autoMill, reloading: reloading} = ModuleHandler.staticModules;
if (autoMill.isActive) {
return;
}
let farmItem = myPlayer.getItemByType(8);
if (farmItem !== 17 && farmItem !== 22) {
return;
}
let nearestEnemy = EnemyManager2.nearestEnemy;
if (nearestEnemy !== null && myPlayer.collidingSimple(nearestEnemy, 400)) {
return;
}
let itemType = 8;
if (!myPlayer.canPlace(itemType)) {
return;
}
let item = DataHandler_default.getItem(farmItem), distance = myPlayer.getItemPlaceScale(item.id), angle = ModuleHandler.currentAngle, angleBetween = Math.asin((2 * item.scale + 15) / (2 * distance));
this.placeTurret(angle - angleBetween), this.placeTurret(angle + angleBetween);
let {nearestPlayerObject: nearestObject, secondNearestPlayerObject: secondNearestObject} = EnemyManager2;
if (nearestObject === null || nearestObject.type !== 17 && nearestObject.type !== 22) {
return;
}
let pos1 = myPlayer.pos.current, tempAngle = pos1.angle(nearestObject.pos.current), weaponType = this.getGrindWeapon();
if (weaponType === null) {
return;
}
let weapon = myPlayer.getItemByType(weaponType);
if (secondNearestObject !== null && nearestObject !== secondNearestObject) {
let pos3 = secondNearestObject.pos.current, distance2 = pos1.distance(pos3), range = DataHandler_default.getWeapon(weapon).range + secondNearestObject.hitScale, angle2 = pos1.angle(pos3), middleAngle = findMiddleAngle(tempAngle, angle2);
if (distance2 <= range && getAngleDist(tempAngle, middleAngle) <= Config_default.gatherAngle && getAngleDist(angle2, middleAngle) <= Config_default.gatherAngle) {
tempAngle = middleAngle;
}
}
if (reloading.isReloaded(weaponType)) {
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = tempAngle, ModuleHandler.useHat = 40,
ModuleHandler.forceWeapon = weaponType, ModuleHandler.shouldAttack = !0;
}
}
}
class Automill {
moduleName="autoMill";
toggle=!1;
active=!0;
client;
tickCount=0;
constructor(client2) {
this.client = client2;
}
get isActive() {
return this.toggle && this.active;
}
reset() {
this.active = !0;
}
get canAutomill() {
let isOwner = this.client.isOwner, {attacking: attacking, placedOnce: placedOnce} = this.client.ModuleHandler;
return Settings_default._automill && this.client.myPlayer.isSandbox && !placedOnce && (!isOwner || !attacking) && this.active;
}
canPlaceWindmill(angle) {
return this.client.myPlayer.canPlaceObject(5, angle);
}
placeWindmill(angle) {
let {ModuleHandler: ModuleHandler} = this.client, type = 5;
ModuleHandler.place(type, angle), ModuleHandler.placedOnce = !0, ModuleHandler.placeAngles[0] = type,
ModuleHandler.placeAngles[1].push(angle);
}
postTick() {
let {myPlayer: myPlayer, ModuleHandler: ModuleHandler} = this.client;
if (this.toggle = !0, !this.canAutomill) {
this.toggle = !1;
return;
}
if (!myPlayer.canPlace(5)) {
this.toggle = !1, this.active = !1;
return;
}
let angle = ModuleHandler.reverse_move_dir;
if (angle === null) {
return;
}
let item = Items[myPlayer.getItemByType(5)], distance = myPlayer.getItemPlaceScale(item.id), offset = Math.asin((2 * item.scale + 9e-13) / (2 * distance)) * 2, leftAngle = angle - offset, rightAngle = angle + offset;
if (this.canPlaceWindmill(angle) && this.canPlaceWindmill(leftAngle) && this.canPlaceWindmill(rightAngle)) {
this.placeWindmill(angle), this.placeWindmill(leftAngle), this.placeWindmill(rightAngle);
}
}
}
const Automill_default = Automill;
class AutoSteal {
moduleName="autoSteal";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._autoSteal) {
return;
}
let nearestLowEntity = EnemyManager2.nearestLowEntity;
if (nearestLowEntity === null) {
return;
}
let {reloading: reloading} = ModuleHandler.staticModules, primary = myPlayer.getItemByType(0), range = DataHandler_default.getWeapon(primary).range + nearestLowEntity.hitScale;
if (!myPlayer.collidingSimple(nearestLowEntity, range) || !reloading.isReloaded(0)) {
return;
}
let canUseBull = ModuleHandler.canBuy(0, 7), pos1 = myPlayer.pos.current, pos2 = nearestLowEntity.pos.current, angle = pos1.angle(pos2), maxDamageBull = myPlayer.getMaxWeaponDamage(primary, !1, canUseBull), maxDamage = myPlayer.getMaxWeaponDamage(primary, !1, !1);
if (!(maxDamageBull >= nearestLowEntity.currentHealth)) {
return;
}
if (ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle, maxDamage < nearestLowEntity.currentHealth) {
ModuleHandler.forceHat = 7;
}
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0;
}
}
class AutoPush {
moduleName="autoPush";
client;
pushPos=null;
constructor(client2) {
this.client = client2;
}
postTick() {
let {EnemyManager: EnemyManager2, myPlayer: myPlayer, ModuleHandler: ModuleHandler, ObjectManager: ObjectManager2, PlayerManager: PlayerManager2} = this.client;
this.pushPos = null;
let {nearestEnemyPush: nearestEnemyPush, nearestPushSpike: nearestPushSpike} = EnemyManager2;
if (EnemyManager2.nearestEnemyPush = null, EnemyManager2.nearestPushSpike = null,
ModuleHandler.moduleActive || !Settings_default._autoPush || ModuleHandler.moveTo !== "disable") {
return;
}
if (nearestEnemyPush === null || nearestPushSpike === null) {
return;
}
if (nearestEnemyPush.trappedIn === null || myPlayer.trappedIn) {
return;
}
let pos0 = myPlayer.pos.current, pos1 = nearestEnemyPush.pos.current, pos2 = nearestPushSpike.pos.current;
if (!myPlayer.collidingSimple(nearestEnemyPush, 250) || nearestEnemyPush.colliding(nearestPushSpike, nearestEnemyPush.collisionScale + nearestPushSpike.collisionScale + 1)) {
return;
}
let distanceFromSpikeToEnemy = pos2.distance(pos1), angleFromSpikeToEnemy = pos2.angle(pos1), angleToEnemy = pos0.angle(pos1), angleToSpike = pos0.angle(pos2), distanceToSpike = pos0.distance(pos2), pushPos = pos2.addDirection(angleFromSpikeToEnemy, distanceFromSpikeToEnemy + nearestEnemyPush.collisionScale + 7), objectIDs = ObjectManager2.grid2D.queryFull(pushPos.x, pushPos.y, 1);
for (let id of objectIDs) {
let object = ObjectManager2.objects.get(id);
if (PlayerManager2.canMoveOnTop(object)) {
continue;
}
let pos = object.pos.current, distance = pushPos.distance(pos), playerScale = myPlayer.collisionScale * 1.3, range = object.collisionScale + playerScale;
if (distance <= range) {
return;
}
}
this.pushPos = pos2.addDirection(angleFromSpikeToEnemy, distanceFromSpikeToEnemy + 250),
ModuleHandler.moveTo = pos0.angle(this.pushPos), EnemyManager2.nearestEnemyPush = nearestEnemyPush,
EnemyManager2.nearestPushSpike = nearestPushSpike;
let activationScale2 = nearestEnemyPush.collisionScale * 3.2, offset2 = Math.asin(2 * activationScale2 / (2 * distanceToSpike));
if (!(getAngleDist(angleToEnemy, angleToSpike) <= offset2)) {
return;
}
this.pushPos = pushPos, ModuleHandler.moveTo = pos0.angle(this.pushPos);
}
}
class ReverseInstakill {
moduleName="reverseInstakill";
client;
targetEnemy=null;
constructor(client2) {
this.client = client2;
}
reset() {
this.targetEnemy = null;
}
postTick() {
let {myPlayer: myPlayer, EnemyManager: EnemyManager2, PlayerManager: PlayerManager2, ModuleHandler: ModuleHandler, InputHandler: InputHandler2} = this.client;
if (!InputHandler2.instaToggle) {
this.reset(), InputHandler2.instaReset();
return;
}
let nearestEnemy = EnemyManager2.nearestEnemy;
if (nearestEnemy === null) {
return;
}
let lookingShield = PlayerManager2.lookingShield(nearestEnemy, myPlayer), primary = myPlayer.getItemByType(0), primaryDamage = myPlayer.getMaxWeaponDamage(primary, lookingShield), secondary = myPlayer.getItemByType(1);
if (secondary !== 10) {
return;
}
let secondaryDamage = myPlayer.getMaxWeaponDamage(secondary, lookingShield);
if (primaryDamage + secondaryDamage + 25 < 100) {
return;
}
let pos1 = myPlayer.pos.current, pos2 = nearestEnemy.pos.current, angle = pos1.angle(pos2);
if (this.targetEnemy !== null) {
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0, this.targetEnemy = null,
InputHandler2.instaReset(), EnemyManager2.attemptSpikePlacement();
return;
}
InputHandler2.instakillTarget = nearestEnemy;
let {reloading: reloading} = ModuleHandler.staticModules, primaryReloaded = reloading.isReloaded(0), secondaryReloaded = reloading.isReloaded(1), turretReloaded = reloading.isReloaded(2), range = DataHandler_default.getWeapon(primary).range + nearestEnemy.hitScale;
if (!primaryReloaded || !secondaryReloaded || !turretReloaded || !myPlayer.collidingSimple(nearestEnemy, range)) {
return;
}
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle, ModuleHandler.forceHat = 53,
ModuleHandler.forceWeapon = 1, ModuleHandler.shouldAttack = !0, this.targetEnemy = nearestEnemy;
}
}
class BowInsta {
moduleName="bowInsta";
client;
targetEnemy=null;
tickAction=0;
distMin=660;
distMax=700;
active=!1;
constructor(client2) {
this.client = client2;
}
reset() {
this.targetEnemy = null, this.tickAction = 0, this.active = !1;
}
postTick() {
let {EnemyManager: EnemyManager2, ModuleHandler: ModuleHandler, myPlayer: myPlayer, InputHandler: InputHandler2} = this.client;
if (!InputHandler2.instaToggle) {
this.reset(), InputHandler2.instaReset();
return;
}
let nearestEnemy = EnemyManager2.nearestEnemy, nearest = this.targetEnemy || nearestEnemy;
if (nearest === null) {
this.reset();
return;
}
let pos1 = myPlayer.pos.current, pos2 = nearest.pos.current, angle = pos1.angle(pos2), distance = pos1.distance(pos2);
if (InputHandler2.instakillTarget = nearest, this.targetEnemy !== null) {
if (this.tickAction === 2) {
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle, ModuleHandler.forceWeapon = 1,
ModuleHandler.shouldAttack = !0, ModuleHandler.moveTo = null, ModuleHandler.upgradeItem(15),
this.reset(), InputHandler2.instaReset();
return;
}
if (this.tickAction === 1) {
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle, ModuleHandler.forceWeapon = 1,
ModuleHandler.shouldAttack = !0, ModuleHandler.moveTo = null, ModuleHandler.upgradeItem(12),
this.tickAction = 2;
return;
}
return;
}
if (!(inRange(myPlayer.upgradeAge, 6, 8) && myPlayer.age >= 9)) {
return;
}
this.active = !0;
let {reloading: reloading} = ModuleHandler.staticModules;
if (!ModuleHandler.canBuy(0, 53) || !reloading.isReloaded(2) || !inRange(distance, this.distMin, this.distMax)) {
return;
}
if (ModuleHandler.moveTo = null, ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle,
ModuleHandler.forceHat = 53, ModuleHandler.forceWeapon = 1, ModuleHandler.shouldAttack = !0,
myPlayer.upgradeAge === 6) {
ModuleHandler.upgradeItem(9);
}
if (myPlayer.upgradeAge === 7) {
ModuleHandler.upgradeItem(18, !0);
}
if (myPlayer.upgradeAge === 8 && myPlayer.getItemByType(8) === 18) {
ModuleHandler.place(8, angle), ModuleHandler.place(8, angle - toRadians(90)),
ModuleHandler.place(8, angle + toRadians(90)), ModuleHandler.place(8, reverseAngle(angle));
}
this.tickAction = 1, this.targetEnemy = nearestEnemy;
}
}
class PlacementDefense {
moduleName="placementDefense";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {EnemyManager: EnemyManager2, myPlayer: myPlayer, ModuleHandler: ModuleHandler, ProjectileManager: ProjectileManager2} = this.client, nearestEnemy = EnemyManager2.nearestEnemy;
if (nearestEnemy === null || !Settings_default._placementDefense) {
return;
}
if (EnemyManager2.rangedBowInsta || ProjectileManager2.totalDamage >= myPlayer.currentHealth) {
let pos1 = myPlayer.pos.current, pos2 = nearestEnemy.pos.current, angle = pos1.angle(pos2), type = 3;
if (myPlayer.canPlace(5)) {
type = 5;
}
ModuleHandler.place(type, angle), ModuleHandler.placedOnce = !0, ModuleHandler.placeAngles[0] = type,
ModuleHandler.placeAngles[1] = [ angle ];
}
}
}
class TurretSteal {
moduleName="turretSteal";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, myPlayer: myPlayer, EnemyManager: EnemyManager2} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._turretSteal) {
return;
}
let nearestEnemy = EnemyManager2.nearestTurretEntity;
if (nearestEnemy === null || nearestEnemy.currentHealth > 25 || !ModuleHandler.canBuy(0, 53)) {
return;
}
let pos0 = myPlayer.pos.current, pos1 = nearestEnemy.pos.current;
if (pos0.distance(pos1) > 700) {
return;
}
let {reloading: reloading} = ModuleHandler.staticModules;
if (!reloading.isReloaded(2, 0)) {
return;
}
ModuleHandler.moduleActive = !0, ModuleHandler.forceHat = 53;
}
}
class KillChat {
moduleName="killChat";
client;
constructor(client2) {
this.client = client2;
}
// Message de kill fige. Il ne depend plus d un reglage : ni le menu,
// ni le stockage local, ni la console ne peuvent le changer.
static get MESSAGE() { return "seldoom is goated"; }
postTick() {
let {myPlayer: myPlayer, PacketManager: PacketManager2} = this.client;
if (!myPlayer.killedSomeone || myPlayer.resources.kills === 0) {
return;
}
PacketManager2.chat(KillChat.MESSAGE);
}
}
class SwordKatanaInsta {
moduleName="swordKatanaInsta";
client;
nearestTarget=null;
useTurret=!1;
constructor(client2) {
this.client = client2;
}
postTick() {
let {myPlayer: myPlayer, ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2} = this.client, nearestEnemy = EnemyManager2.nearestEnemy;
if (ModuleHandler.moduleActive || !nearestEnemy) {
this.nearestTarget = null, this.useTurret = !1;
return;
}
let {reloading: reloading} = ModuleHandler.staticModules, primaryReloaded = reloading.isReloaded(0), turretReloaded = reloading.isReloaded(2);
if (this.useTurret) {
if (this.useTurret = !1, turretReloaded && ModuleHandler.canBuy(0, 53)) {
ModuleHandler.moduleActive = !0, ModuleHandler.forceHat = 53;
}
return;
}
let primary = myPlayer.getItemByType(0), isSword = primary === 3, pos1 = myPlayer.pos.current, target = this.nearestTarget;
if (target !== null) {
let pos22 = target.pos.current, angle2 = pos1.angle(pos22);
if (ModuleHandler.useAngle = angle2, ModuleHandler.forceHat = 7, ModuleHandler.forceWeapon = 0,
ModuleHandler.shouldAttack = !0, myPlayer.upgradeAge === 3) {
ModuleHandler.upgradeItem(1, !0);
}
if (myPlayer.upgradeAge === 4) {
ModuleHandler.upgradeItem(15, !0);
}
if (myPlayer.upgradeAge === 5) {
ModuleHandler.upgradeItem(7, !0);
}
if (myPlayer.upgradeAge === 6) {
ModuleHandler.upgradeItem(10);
}
if (myPlayer.upgradeAge === 7) {
ModuleHandler.upgradeItem(22, !0);
}
if (myPlayer.upgradeAge === 8) {
ModuleHandler.upgradeItem(4);
}
if (this.nearestTarget = null, ModuleHandler.canBuy(0, 53)) {
this.useTurret = !0;
}
EnemyManager2.attemptSpikePlacement();
}
if (myPlayer.age < 8 || !isSword || !primaryReloaded || !ModuleHandler.canBuy(0, 7)) {
return;
}
let range = DataHandler_default.getWeapon(primary).range + nearestEnemy.hitScale;
if (!myPlayer.collidingSimple(nearestEnemy, range)) {
return;
}
let pos2 = nearestEnemy.pos.current, angle = pos1.angle(pos2);
ModuleHandler.useAngle = angle, ModuleHandler.forceHat = 7, ModuleHandler.forceWeapon = 0,
ModuleHandler.shouldAttack = !0, this.nearestTarget = nearestEnemy;
}
}
class SpikeGearInsta {
moduleName="spikeGearInsta";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive || EnemyManager2.instaThreat() || EnemyManager2.spikeSyncThreat || !Settings_default._spikeGearInsta) {
return;
}
let nearestEnemy = EnemyManager2.nearestEnemy;
if (nearestEnemy === null || !ModuleHandler.canBuy(0, 11) || !ModuleHandler.canBuy(1, 21) || myPlayer.accessoryID !== 21 || nearestEnemy.variant.primary !== 0) {
return;
}
let pos1 = myPlayer.pos.current, pos2 = nearestEnemy.pos.current, angle = pos1.angle(pos2), primary1 = myPlayer.getItemByType(0), primary2 = nearestEnemy.weapon.primary;
if (primary2 === null) {
return;
}
let range1 = DataHandler_default.getWeapon(primary1).range + nearestEnemy.hitScale, range2 = DataHandler_default.getWeapon(primary2).range + myPlayer.hitScale;
if (!myPlayer.collidingSimple(nearestEnemy, range1) || !nearestEnemy.collidingSimple(myPlayer, range2)) {
return;
}
if (ModuleHandler.forceHat = 11, nearestEnemy.hatID !== 7 || !nearestEnemy.isEmptyReload(0) || myPlayer.hatID !== 11) {
return;
}
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0;
}
}
class TeammateSpikeTrap {
moduleName="teammateSpikeTrap";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, InputHandler: InputHandler2, PlayerManager: PlayerManager2, myPlayer: myPlayer, PacketManager: PacketManager2} = this.client;
if (ModuleHandler.moduleActive) {
return;
}
if (!InputHandler2.instaToggle) {
InputHandler2.instaReset();
return;
}
let nearestTeammate = PlayerManager2.nearestTeammate;
if (!nearestTeammate) {
return;
}
let pos1 = myPlayer.pos.current, pos2 = nearestTeammate.pos.current, distance = pos1.distance(pos2), angle = pos1.angle(pos2);
if (distance > 500) {
return;
}
if (InputHandler2.instakillTarget = nearestTeammate, distance > 175) {
return;
}
let angles = [ angle, angle - toRadians(90), angle + toRadians(90), angle + toRadians(180) ], id = myPlayer.getItemByType(4), distance2 = myPlayer.getPlacePosition(pos1, id, angle).distance(pos1);
if (ModuleHandler.placeAngles[0] = 4, ModuleHandler.placeAngles[1] = angles,
distance > distance2 || !angles.every(angle2 => myPlayer.canPlaceObject(4, angle2))) {
return;
}
InputHandler2.instaReset(), PacketManager2.leaveClan();
for (let angle2 of angles) {
ModuleHandler.place(4, angle2);
}
}
}
class SpikeTrap {
moduleName="spikeTrap";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, myPlayer: myPlayer, EnemyManager: EnemyManager2} = this.client;
if (ModuleHandler.moduleActive) {
return;
}
let trapId = myPlayer.getItemByType(7), nearestEnemy = EnemyManager2.nearestEnemy;
if (!nearestEnemy || myPlayer.isTrapped || trapId !== 16) {
return;
}
let pos1 = myPlayer.pos.current, pos2 = nearestEnemy.pos.current, distance = pos1.distance(pos2), angle = pos1.angle(pos2);
if (distance > 175) {
return;
}
let angles = [ angle, angle - toRadians(90), angle + toRadians(90), angle + toRadians(180) ], id = myPlayer.getItemByType(4), len = ModuleHandler.currentType === 7 ? 30 : 0, distance2 = myPlayer.getPlacePosition(pos1, id, angle).distance(pos1) + len;
if (ModuleHandler.placeAngles[0] = 4, ModuleHandler.placeAngles[1] = angles,
distance > distance2) {
return;
}
for (let angle2 of angles) {
ModuleHandler.place(4, angle2);
}
}
}
class TurretSync {
moduleName="turretSync";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._turretSync) {
return;
}
let nearestEnemy = EnemyManager2.nearestEnemy;
if (nearestEnemy === null) {
return;
}
let primary = myPlayer.getItemByType(0), weapon = DataHandler_default.getWeapon(primary);
if (weapon.damage < 20) {
return;
}
let range = weapon.range + nearestEnemy.hitScale, {reloading: reloading} = ModuleHandler.staticModules;
if (!myPlayer.collidingSimple(nearestEnemy, range) || !reloading.isReloaded(0) || nearestEnemy.nextDamageTick !== myPlayer.tickCount + 2) {
return;
}
let pos1 = myPlayer.pos.current, pos2 = nearestEnemy.pos.current, angle = pos1.angle(pos2);
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angle, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0;
}
}
class DashMovement {
moduleName="dashMovement";
client;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, myPlayer: myPlayer} = this.client, {currentType: currentType, currentAngle: currentAngle} = ModuleHandler;
if (!myPlayer.canPlace(currentType) || !Settings_default._dashMovement) {
return;
}
let {reloading: reloading} = ModuleHandler.staticModules, primary = myPlayer.getItemByType(0), secondary = myPlayer.getItemByType(1);
if (myPlayer.getItemByType(7) !== 16 || !ModuleHandler.hasStoreItem(0, 40) || currentType !== 7 || ModuleHandler.placedOnce) {
return;
}
let hasHammer = secondary === 10, canOneHit = myPlayer.getBuildingDamage(primary, !0) >= DataHandler_default.getItem(16).health, weaponType = null;
if (canOneHit) {
let primaryData = DataHandler_default.getWeapon(primary), secondaryData = DataHandler_default.isMelee(secondary) && DataHandler_default.getWeapon(secondary) || null;
if (secondaryData === null || primaryData.speed < secondaryData.speed) {
weaponType = 0;
}
}
if (weaponType === null && hasHammer) {
weaponType = 1;
}
if (weaponType === null) {
return;
}
if (ModuleHandler.placedOnce = !0, !reloading.isReloaded(weaponType)) {
return;
}
ModuleHandler.place(currentType, currentAngle), ModuleHandler.useAngle = currentAngle,
ModuleHandler.useHat = 40, ModuleHandler.forceWeapon = weaponType, ModuleHandler.shouldAttack = !0;
}
}
class KBTickHammerV2 {
moduleName="kbTickHammerV2";
client;
targetEnemy=null;
constructor(client2) {
this.client = client2;
}
postTick() {
let {ModuleHandler: ModuleHandler, EnemyManager: EnemyManager2, myPlayer: myPlayer} = this.client;
if (ModuleHandler.moduleActive || !Settings_default._knockbackTickHammer || EnemyManager2.shouldIgnoreModule()) {
this.targetEnemy = null;
return;
}
let {nearestEnemySpikeCollider: nearestEnemySpikeCollider, spikeCollider: spikeCollider} = EnemyManager2, reloading = ModuleHandler.staticModules.reloading, primary = myPlayer.getItemByType(0), secondary = myPlayer.getItemByType(1), isHammer = secondary !== null && secondary !== 11, primaryReloaded = reloading.isReloaded(0), secondaryReloaded = reloading.isReloaded(1), pos1 = myPlayer.pos.current;
if (this.targetEnemy !== null) {
let pos2 = this.targetEnemy.pos.current, angleToEnemy = pos1.angle(pos2);
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angleToEnemy, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 0, ModuleHandler.shouldAttack = !0, this.targetEnemy = null,
EnemyManager2.attemptSpikePlacement();
return;
}
if (nearestEnemySpikeCollider !== null && !nearestEnemySpikeCollider.isTrapped && spikeCollider !== null && isHammer && primaryReloaded && secondaryReloaded) {
let pos2 = nearestEnemySpikeCollider.pos.current, pos3 = spikeCollider.pos.current, angleToEnemy = pos1.angle(pos2), distanceToSpike2 = pos2.distance(pos3), {knockback: primaryKnockback, range: primaryRange} = DataHandler_default.getWeapon(primary), {knockback: secondaryKnockback, range: secondaryRange} = DataHandler_default.getWeapon(secondary), weaponRange = Math.min(primaryRange, secondaryRange) + nearestEnemySpikeCollider.hitScale, minKB = primaryKnockback, maxKB = primaryKnockback + secondaryKnockback, spikeRange = spikeCollider.collisionScale + nearestEnemySpikeCollider.collisionScale;
if (inRange(distanceToSpike2, spikeRange + minKB, spikeRange + maxKB) && myPlayer.collidingSimple(nearestEnemySpikeCollider, weaponRange)) {
let hitRange = DataHandler_default.getWeapon(secondary).range + nearestEnemySpikeCollider.hitScale;
if (myPlayer.collidingSimple(nearestEnemySpikeCollider, hitRange)) {
ModuleHandler.moduleActive = !0, ModuleHandler.useAngle = angleToEnemy, ModuleHandler.forceHat = 7,
ModuleHandler.forceWeapon = 1, ModuleHandler.shouldAttack = !0, this.targetEnemy = nearestEnemySpikeCollider,
this.client.StatsManager.knockbackTickHammerTimes = 1;
}
}
}
}
}
class ModuleHandler {
client;
staticModules={};
botModules;
modules;
store=[ {
utility: new Map,
lastUtility: null,
current: 0,
best: 0,
actual: -1,
last: 0
}, {
utility: new Map,
lastUtility: null,
current: 0,
best: 0,
actual: -1,
last: 0
} ];
bought=[ new Set, new Set ];
followTarget=new Vector_default(0, 0);
lookTarget=new Vector_default(0, 0);
endTarget=new Vector_default(0, 0);
followPath=!1;
tickCount=0;
currentHolding=0;
weapon;
currentType;
attacking;
attackingState;
sentAngle;
sentHatEquip;
sentAccEquip;
needToHeal;
didAntiInsta;
placedOnce;
healedOnce;
totalPlaces;
attacked;
canHitEntity=!1;
moduleActive=!1;
useAngle=null;
useWeapon=null;
useItem=null;
forceWeapon=null;
useHat=null;
forceHat=null;
shouldEquipSoldier=!1;
useAcc=null;
previousWeapon=null;
currentAngle=0;
move_dir=null;
reverse_move_dir=null;
moveTo="disable";
prevMoveTo="disable";
autoattack=!1;
shouldAttack=!1;
mouse={
sentAngle: 0
};
placeAngles=[ null, [] ];
constructor(client2) {
this.client = client2, this.staticModules = {
tempData: new TempData_default(client2),
movement: new Movement_default(client2),
clanJoiner: new ClanJoiner_default(client2),
autoAccept: new AutoAccept_default(client2),
autoBuy: new AutoBuy(client2),
defaultHat: new DefaultHat(client2),
reloading: new Reloading_default(client2),
defaultAcc: new DefaultAcc(client2),
autoSync: new AutoSync(client2),
spikeSyncHammer: new SpikeSyncHammer(client2),
spikeSync: new SpikeSync(client2),
spikeTick: new SpikeTick_default(client2),
knockbackTickTrap: new KnockbackTickTrap(client2),
knockbackTick: new KnockbackTick(client2),
knockbackTickHammer: new KnockbackTickHammer(client2),
kbTickHammerV2: new KBTickHammerV2(client2),
antiRetrap: new AntiRetrap(client2),
autoPush: new AutoPush(client2),
velocityTick: new VelocityTick(client2),
spikeTrap: new SpikeTrap(client2),
teammateSpikeTrap: new TeammateSpikeTrap(client2),
turretSync: new TurretSync(client2),
toolHammerSpearInsta: new ToolHammerSpearInsta(client2),
swordKatanaInsta: new SwordKatanaInsta(client2),
bowInsta: new BowInsta(client2),
instakill: new Instakill(client2),
reverseInstakill: new ReverseInstakill(client2),
autoBreak: new Autobreak(client2),
autoSteal: new AutoSteal(client2),
turretSteal: new TurretSteal(client2),
spikeGearInsta: new SpikeGearInsta(client2),
useFastest: new UseFastest(client2),
useDestroying: new UseDestroying(client2),
useAttacking: new UseAttacking(client2),
utilityHat: new UtilityHat(client2),
antiInsta: new AntiInsta_default(client2),
shameReset: new ShameReset_default(client2),
safeWalk: new SafeWalk(client2),
placementDefense: new PlacementDefense(client2),
dashMovement: new DashMovement(client2),
autoPlacer: new AutoPlacer_default(client2),
placer: new Placer_default(client2),
autoMill: new Automill_default(client2),
autoGrind: new AutoGrind(client2),
preAttack: new PreAttack_default(client2),
autoHat: new Autohat_default(client2),
updateAttack: new UpdateAttack_default(client2),
updateAngle: new UpdateAngle_default(client2),
killChat: new KillChat(client2)
}, this.botModules = [ this.staticModules.tempData, this.staticModules.clanJoiner, this.staticModules.movement ],
this.modules = [ this.staticModules.autoAccept, this.staticModules.autoBuy, this.staticModules.defaultHat, this.staticModules.reloading, this.staticModules.defaultAcc, this.staticModules.autoSync, this.staticModules.spikeSyncHammer, this.staticModules.spikeSync, this.staticModules.spikeTick, this.staticModules.knockbackTickTrap, this.staticModules.knockbackTickHammer, this.staticModules.kbTickHammerV2, this.staticModules.knockbackTick, this.staticModules.antiRetrap, this.staticModules.autoPush, this.staticModules.velocityTick, this.staticModules.spikeTrap, this.staticModules.teammateSpikeTrap, this.staticModules.turretSync, this.staticModules.toolHammerSpearInsta, this.staticModules.swordKatanaInsta, this.staticModules.bowInsta, this.staticModules.instakill, this.staticModules.reverseInstakill, this.staticModules.autoBreak, this.staticModules.autoSteal, this.staticModules.turretSteal, this.staticModules.spikeGearInsta, this.staticModules.useFastest, this.staticModules.useDestroying, this.staticModules.useAttacking, this.staticModules.utilityHat, this.staticModules.antiInsta, this.staticModules.shameReset, this.staticModules.safeWalk, this.staticModules.placementDefense, this.staticModules.autoPlacer, this.staticModules.dashMovement, this.staticModules.placer, this.staticModules.autoMill, this.staticModules.autoGrind, this.staticModules.preAttack, this.staticModules.autoHat, this.staticModules.updateAttack, this.staticModules.updateAngle, this.staticModules.killChat ],
this.reset();
}
movementReset() {
this.currentHolding = 0, this.weapon = 0, this.currentType = null, this.attacking = 0,
this.attackingState = 0, this.move_dir = null, this.reverse_move_dir = null;
}
reset() {
let {isOwner: isOwner, clients: clients} = this.client;
this.movementReset(), this.getHatStore().utility.clear(), this.getAccStore().utility.clear(),
this.sentAngle = 0, this.sentHatEquip = !1, this.sentAccEquip = !1, this.needToHeal = !1,
this.didAntiInsta = !1, this.placedOnce = !1, this.healedOnce = !1, this.totalPlaces = 0,
this.attacked = !1, this.canHitEntity = !1, this.autoattack = !1;
for (let module of this.modules) {
if ("reset" in module) {
module.reset();
}
}
if (isOwner) {
for (let client2 of clients) {
client2.ModuleHandler.movementReset(), client2.ModuleHandler.toggleAutoattack(!1);
}
}
}
get holdingWeapon() {
return this.currentHolding <= 1;
}
get isMoving() {
return this.move_dir !== null;
}
setForceHat(hat) {
if (this.forceHat !== null && hat !== null) {
return;
}
this.forceHat = hat;
}
getHatStore() {
return this.store[0];
}
getAccStore() {
return this.store[1];
}
setFollowTarget(x, y) {
this.followTarget.setXY(x, y);
}
setLookTarget(x, y) {
this.lookTarget.setXY(x, y);
}
updateSentAngle(priority) {
if (this.sentAngle >= priority) {
return;
}
this.sentAngle = priority;
}
upgradeItem(id, isItem = !1) {
if (isItem) {
id += 16;
}
if (this.client.PacketManager.upgradeItem(id), this.client.myPlayer.upgradeItem(id),
DataHandler_default.isWeapon(id)) {
let type = DataHandler_default.getWeapon(id).type, {reloading: reloading} = this.staticModules;
reloading.updateMaxReload(type);
}
}
startMovement(angle = this.move_dir, ignore = !1) {
if (!ignore) {
if (this.move_dir = angle, this.reverse_move_dir = angle === null ? null : reverseAngle(angle),
this.moveTo !== "disable") {
return;
}
}
let {EnemyManager: EnemyManager2} = this.client, {safeWalk: safeWalk} = this.staticModules;
if (safeWalk.willGetHit(angle, 45, EnemyManager2.nearestCollider) || safeWalk.willGetHit(angle, 45, EnemyManager2.secondNearestCollider)) {
return !1;
}
return this.client.PacketManager.move(angle), !0;
}
stopMovement() {
this.client.PacketManager.resetMoveDir();
}
startPlacement(type) {
this.currentType = type;
}
canBuy(type, id) {
if (id === -1) {
return !1;
}
let price = DataHandler_default.getStore(type)[id].price;
return this.bought[type].has(id) || this.client.myPlayer.tempGold >= price && this.client.myPlayer.isSandbox;
}
buy(type, id, force = !1) {
let store2 = DataHandler_default.getStore(type), {isOwner: isOwner, clients: clients, myPlayer: myPlayer, PacketManager: PacketManager2} = this.client;
if (!myPlayer.inGame) {
return !1;
}
if (force) {
if (isOwner) {
for (let client2 of clients) {
client2.ModuleHandler.buy(type, id, force);
}
}
}
let price = store2[id].price, bought = this.bought[type];
if (price === 0) {
return bought.add(id), !0;
}
if (!bought.has(id) && myPlayer.tempGold >= price && (myPlayer.isSandbox || force)) {
return PacketManager2.buy(type, id), myPlayer.tempGold -= price, !1;
}
return bought.has(id);
}
hasStoreItem(type, id) {
return this.bought[type].has(id);
}
equip(type, id, force = !1, toggle = !1) {
let store2 = this.store[type], {myPlayer: myPlayer, PacketManager: PacketManager2, EnemyManager: EnemyManager2, isOwner: isOwner, clients: clients} = this.client;
if (toggle && store2.last === id && id !== 0) {
id = 0;
}
if (!myPlayer.inGame || !this.buy(type, id, force)) {
return !1;
}
if (store2.last === id && myPlayer.storeData[type] === id) {
return !1;
}
if (store2.last = id, PacketManager2.equip(type, id), type === 0) {
this.sentHatEquip = !0;
} else {
this.sentAccEquip = !0;
}
if (force) {
if (store2.actual = id, isOwner) {
for (let client2 of clients) {
client2.ModuleHandler.staticModules.tempData.setStore(type, id);
}
}
}
let nearest = EnemyManager2.nearestTurretEntity, reloading = this.staticModules.reloading;
if (nearest !== null && reloading.isReloaded(2) && type === 0 && id === 53) {
reloading.resetByType(2);
}
return !0;
}
updateAngle(angle, force = !1) {
if (!force && angle === this.mouse.sentAngle) {
return;
}
this.mouse.sentAngle = angle, this.updateSentAngle(3), this.client.PacketManager.updateAngle(angle);
}
selectItem(type) {
let {myPlayer: myPlayer} = this.client, item = myPlayer.getItemByType(type);
if (myPlayer.currentItem !== -1) {
myPlayer.currentItem = -1, this.whichWeapon();
}
this.client.PacketManager.selectItemByID(item, !1), this.currentHolding = type;
}
attack(angle, priority = 2) {
if (angle !== null) {
this.mouse.sentAngle = angle;
}
if (this.updateSentAngle(priority), this.client.PacketManager.attack(angle),
this.holdingWeapon) {
this.attacked = !0;
}
}
stopAttack() {
this.client.PacketManager.stopAttack();
}
toggleAutoattack(state = !this.autoattack) {
this.autoattack = state, this.attacking = state ? 1 : 0;
}
whichWeapon(type = this.weapon) {
let weapon = this.client.myPlayer.getItemByType(type);
if (weapon === null) {
return;
}
this.currentHolding = type, this.weapon = type, this.client.PacketManager.selectItemByID(weapon, !0);
}
place(type, angle = this.currentAngle) {
this.totalPlaces += 1, this.selectItem(type), this.attack(angle, 1), this.whichWeapon();
}
heal() {
this.selectItem(2), this.attack(null, 1), this.whichWeapon();
}
circleOffset=0;
targetSpeed=65;
activeModule=null;
postTick() {
if (Settings_default._circleRotation && this.move_dir === null) {
let rotationSpeed = this.targetSpeed / Settings_default._circleRadius;
this.circleOffset = (this.circleOffset + rotationSpeed) % (Math.PI * 2);
}
let {isOwner: isOwner} = this.client;
if (this.placeAngles[0] = null, this.placeAngles[1].length = 0, this.activeModule = null,
this.tickCount += 1, this.sentAngle = 0, this.sentHatEquip = !1, this.sentAccEquip = !1,
this.didAntiInsta = !1, this.placedOnce = !1, this.healedOnce = !1, this.totalPlaces = 0,
this.attacked = !1, this.canHitEntity = !1, this.moduleActive = !1, this.useWeapon = null,
this.useItem = null, this.forceWeapon = null, this.useHat = null, this.forceHat = null,
this.shouldEquipSoldier = !1, this.useAcc = null, this.useAngle = null, this.shouldAttack = !1,
this.prevMoveTo = this.moveTo, this.moveTo = "disable", !isOwner) {
for (let botModule of this.botModules) {
botModule.postTick();
}
}
for (let module of this.modules) {
let prevg = this.moduleActive;
if (module.postTick(), !prevg && this.moduleActive) {
this.activeModule = module.moduleName;
}
}
if (this.attackingState = this.attacking, isOwner) {
this.client.InputHandler.postTick(), GameUI_default.updateFastQ(this.didAntiInsta),
GameUI_default.updatePlaces(this.totalPlaces), GameUI_default.updateActiveModule(this.activeModule + ", " + this.tickCount),
GameUI_default.updateEquipHat(`${this.store[0].last}, ${this.shouldEquipSoldier}`);
}
}
}
const ModuleHandler_default = ModuleHandler;
class PlayerClient {
id=-1;
connectSuccess=!1;
clientID=null;
owner;
SocketManager;
ObjectManager;
PlayerManager;
ProjectileManager;
LeaderboardManager;
EnemyManager;
ModuleHandler;
myPlayer;
PacketManager;
InputHandler;
StatsManager;
pendingJoins=new Set;
clientIDList=new Set;
clients=new Set;
constructor(owner) {
this.owner = owner || this, this.SocketManager = new SocketManager_default(this),
this.ObjectManager = new ObjectManager_default(this), this.PlayerManager = new PlayerManager_default(this),
this.ProjectileManager = new ProjectileManager_default(this), this.LeaderboardManager = new LeaderboardManager_default(this),
this.EnemyManager = new EnemyManager_default(this), this.ModuleHandler = new ModuleHandler_default(this),
this.myPlayer = new ClientPlayer_default(this), this.PacketManager = new PacketManager(this),
this.InputHandler = new InputHandler(this), this.StatsManager = new StatsManager(this);
}
getClientIndex(client2) {
return [ ...this.clients ].indexOf(client2);
}
get isOwner() {
return this.owner === this;
}
isBotByID(id) {
return this.clientIDList.has(id);
}
disconnect() {
let socket = this.SocketManager.socket;
if (socket !== null) {
socket.close();
}
}
removeBots() {
for (let client2 of this.clients) {
client2.disconnect();
}
}
spawn() {
this.myPlayer.spawn();
}
}
const PlayerClient_default = PlayerClient;
const UI = new class {
frame;
activeHotkeyInput=null;
activeInput=null;
toggleTimeout;
menuOpened=!1;
menuLoaded=!1;
menuScale=1;
get isMenuOpened() {
return this.menuOpened;
}
isActiveButton() {
return this.activeHotkeyInput || this.activeInput;
}
getFrameContent() {
return `\n <!DOCTYPE html>\n <style>${styles_default}${Seldoom_style}</style>\n <div id="menu-container" class="transparent">\n <div id="menu-wrapper">\n ${Header_default}\n\n <main>\n ${Navbar_default}\n \n <div id="page-container">\n ${Home_default}\n ${Keybinds_default}\n ${Combat_default}\n ${Visuals_default}\n ${Misc_default}\n ${Devtool_default}\n ${Bots_default}\n </div>\n </main>\n </div>\n </div>\n `;
}
injectStyles() {
let style = document.createElement("style");
style.innerHTML = Game_default + Store_default, document.head.appendChild(style);
}
createFrame() {
this.injectStyles();
let iframe = document.createElement("iframe"), blob = new Blob([ this.getFrameContent() ], {
type: "text/html; charset=utf-8"
});
return iframe.src = URL.createObjectURL(blob), iframe.id = "iframe-container",
iframe.style.display = "none", document.body.appendChild(iframe), new Promise(resolve => {
iframe.onload = () => {
let iframeWindow = iframe.contentWindow, iframeDocument = iframeWindow.document;
URL.revokeObjectURL(iframe.src), resolve({
target: iframe,
window: iframeWindow,
document: iframeDocument
});
};
});
}
querySelector(selector) {
return this.frame.document.querySelector(selector);
}
querySelectorAll(selector) {
return this.frame.document.querySelectorAll(selector);
}
getElements() {
let that = this;
return {
menuContainer: this.querySelector("#menu-container"),
menuWrapper: this.querySelector("#menu-wrapper"),
pageContainer: this.querySelector("#page-container"),
hotkeyInputs: this.querySelectorAll(".hotkeyInput[id]"),
checkboxes: this.querySelectorAll("input[type='checkbox'][id]"),
colorPickers: this.querySelectorAll("input[type='color'][id]"),
textInputs: this.querySelectorAll("input[type='text'][id]"),
sliders: this.querySelectorAll("input[type='range'][id]"),
closeButton: this.querySelector("#close-button"),
openMenuButtons: this.querySelectorAll(".open-menu[data-id]"),
menuPages: this.querySelectorAll(".menu-page[data-id]"),
buttons: this.querySelectorAll(".option-button[id]"),
botContainer: this.querySelector("#bot-container"),
connectingBot: this.querySelector("#connectingBot"),
scriptDescription: this.querySelector("#script-description"),
author: this.querySelector("#author"),
optionDescriptions: this.querySelectorAll(".option-description"),
addBot: this.querySelector("#add-bot"),
resetSettings: this.querySelector("#resetSettings"),
botOption(id) {
let option = that.querySelector(`.content-option[data-bot-id="${id}"]`), title = option.querySelector(".option-title"), disconnect = option.querySelector(".disconnect-button");
return {
option: option,
title: title,
disconnect: disconnect
};
}
};
}
updateStats(id, value) {
let stats = this.querySelector("#" + id);
if (stats == null) {
throw Error(`updateStats Error: can't find an element with ID: '${id}'`);
}
if (stats.textContent = value, id in Settings_default) {
Settings_default[id] = value, SaveSettings();
}
}
handleResize() {
let {menuContainer: menuContainer} = this.getElements(), scale = Math.min(.9, Math.min(window.innerWidth / 1280, window.innerHeight / 720));
this.menuScale = scale, menuContainer.style.transform = `translate(-50%, -50%) scale(${scale})`;
}
createRipple(selector) {
let buttons = this.frame.document.querySelectorAll(selector);
for (let button of buttons) {
button.addEventListener("click", event => {
let {width: width, height: height} = button.getBoundingClientRect(), size = Math.max(width, height) * 2, ripple = document.createElement("span");
ripple.style.width = size + "px", ripple.style.height = size + "px", ripple.style.marginTop = -size / 2 + "px",
ripple.style.marginLeft = -size / 2 + "px", ripple.style.left = event.offsetX + "px",
ripple.style.top = event.offsetY + "px", ripple.classList.add("ripple"), button.appendChild(ripple),
setTimeout(() => ripple.remove(), 750);
});
}
}
attachHotkeyInputs() {
let {hotkeyInputs: hotkeyInputs} = this.getElements();
for (let hotkeyInput of hotkeyInputs) {
let id = hotkeyInput.id, value = Settings_default[id];
if (id in Settings_default && typeof value === "string") {
hotkeyInput.textContent = formatCode(value);
} else {
Logger.error(`attachHotkeyInputs Error: Property "${id}" does not exist in settings`);
}
}
}
checkForRepeats() {
let {hotkeyInputs: hotkeyInputs} = this.getElements(), list = new Map;
for (let hotkeyInput of hotkeyInputs) {
let id = hotkeyInput.id;
if (id in Settings_default) {
let value = Settings_default[id], [count, inputs] = list.get(value) || [ 0, [] ];
list.set(value, [ (count || 0) + 1, [ ...inputs, hotkeyInput ] ]), hotkeyInput.classList.remove("red");
} else {
Logger.error(`checkForRepeats Error: Property "${id}" does not exist in settings`);
}
}
for (let data of list) {
let [number, hotkeyInputs2] = data[1];
if (number === 1) {
continue;
}
for (let hotkeyInput of hotkeyInputs2) {
hotkeyInput.classList.add("red");
}
}
}
applyCode(code) {
if (this.activeHotkeyInput === null) {
return;
}
let deleting = code === "Backspace", isCode = typeof code === "string", keyText = isCode ? formatCode(code) : formatButton(code), keySetting = isCode ? code : keyText, id = this.activeHotkeyInput.id;
if (id in Settings_default) {
Settings_default[id] = deleting ? "..." : keySetting, SaveSettings();
} else {
Logger.error(`applyCode Error: Property "${id}" does not exist in settings`);
}
this.activeHotkeyInput.textContent = deleting ? "..." : keyText, this.activeHotkeyInput.blur(),
this.activeHotkeyInput.classList.remove("active"), this.activeHotkeyInput = null,
this.checkForRepeats();
}
isHotkeyInput(target) {
return target instanceof this.frame.window.HTMLButtonElement && target.classList.contains("hotkeyInput") && target.hasAttribute("id");
}
handleCheckboxToggle(id, checked) {
switch (id) {
case "_menuTransparency":
{
let {menuContainer: menuContainer} = this.getElements();
menuContainer.classList.toggle("transparent");
break;
}
case "_hideHUD":
{
let {gameUI: gameUI} = GameUI_default.getElements();
if (checked) {
gameUI.classList.add("hidden");
} else {
gameUI.classList.remove("hidden");
}
break;
}
case "_chatLog":
GameUI_default.toggleChatLog();
break;
}
}
attachCheckboxes() {
let {checkboxes: checkboxes} = this.getElements();
for (let checkbox of checkboxes) {
let id = checkbox.id;
if (!(id in Settings_default)) {
Logger.error(`attachCheckboxes Error: Property "${id}" does not exist in settings`);
continue;
}
checkbox.checked = Settings_default[id], this.handleCheckboxToggle(id, checkbox.checked),
checkbox.onchange = () => {
if (id in Settings_default) {
Settings_default[id] = checkbox.checked, SaveSettings(), this.handleCheckboxToggle(id, checkbox.checked);
} else {
Logger.error(`attachCheckboxes Error: Property "${id}" was deleted from settings`);
}
};
}
}
attachColorPickers() {
let {colorPickers: colorPickers} = this.getElements();
for (let picker of colorPickers) {
let id = picker.id;
if (!(id in Settings_default)) {
Logger.error(`attachColorPickers Error: Property "${id}" does not exist in settings`);
continue;
}
picker.value = Settings_default[id], picker.onchange = () => {
if (id in Settings_default) {
Settings_default[id] = picker.value, SaveSettings(), picker.blur();
} else {
Logger.error(`attachColorPickers Error: Property "${id}" was deleted from settings`);
}
};
let resetColor = picker.previousElementSibling;
if (resetColor instanceof this.frame.window.HTMLButtonElement) {
resetColor.style.setProperty("--data-color", defaultSettings[id]), resetColor.onclick = () => {
if (id in Settings_default) {
picker.value = defaultSettings[id], Settings_default[id] = defaultSettings[id],
SaveSettings();
} else {
Logger.error(`resetColor Error: Property "${id}" was deleted from settings`);
}
};
}
}
}
attachSliders() {
let {sliders: sliders} = this.getElements();
for (let slider of sliders) {
let id = slider.id;
if (!(id in Settings_default)) {
Logger.error(`attachSliders Error: Property "${id}" does not exist in settings`);
continue;
}
let updateSliderValue = () => {
let sliderValue = slider.previousElementSibling;
if (sliderValue instanceof this.frame.window.HTMLSpanElement) {
sliderValue.textContent = slider.value;
}
};
slider.value = Settings_default[id].toString(), updateSliderValue(), slider.oninput = () => {
if (id in Settings_default) {
Settings_default[id] = Number(slider.value), SaveSettings(), updateSliderValue();
} else {
Logger.error(`attachSliders Error: Property "${id}" was deleted from settings`);
}
}, slider.onchange = () => slider.blur();
}
}
attachTextInputs() {
let {textInputs: textInputs} = this.getElements();
for (let input of textInputs) {
let id = input.id;
if (!(id in Settings_default)) {
Logger.error(`attachTextInputs Error: Property "${id}" does not exist in settings`);
continue;
}
input.value = Settings_default[id], input.oninput = () => {
input.value = input.value.replace(/[^\x20-\x7E]/g, "");
}, input.onfocus = () => {
this.activeInput = input;
}, input.onblur = () => {
this.activeInput = null;
}, input.onchange = () => {
if (id in Settings_default) {
let value = input.value;
Settings_default[id] = value, input.value = value, SaveSettings();
} else {
Logger.error(`attachTextInputs Error: Property "${id}" was deleted from settings`);
}
};
}
}
attachDescriptions() {
let {optionDescriptions: optionDescriptions, menuWrapper: menuWrapper} = this.getElements();
for (let description of optionDescriptions) {
let parent = description.parentElement;
parent.onmouseenter = () => {
description.classList.add("description-show");
}, parent.onmouseleave = () => {
description.classList.remove("description-show");
}, parent.onmousemove = event => {
let target = event.target;
if (target !== null && target.className !== "content-option" && target.className !== "option-title") {
description.classList.remove("description-show");
return;
}
description.classList.add("description-show");
let bounds = menuWrapper.getBoundingClientRect(), x = (event.clientX - bounds.left + 10) / this.menuScale, y = (event.clientY - bounds.top + 10) / this.menuScale;
description.style.left = x + "px", description.style.top = y + "px";
};
}
}
createBotOption(player) {
let {botContainer: botContainer, botOption: botOption, pageContainer: pageContainer} = this.getElements(), html = `\n <div class="content-option" data-bot-id="${player.id}">\n <span class="option-title"></span>\n <svg\n class="icon disconnect-button"\n xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 30 30"\n title="Kick bot"\n >\n <path d="M 7 4 C 6.744125 4 6.4879687 4.0974687 6.2929688 4.2929688 L 4.2929688 6.2929688 C 3.9019687 6.6839688 3.9019687 7.3170313 4.2929688 7.7070312 L 11.585938 15 L 4.2929688 22.292969 C 3.9019687 22.683969 3.9019687 23.317031 4.2929688 23.707031 L 6.2929688 25.707031 C 6.6839688 26.098031 7.3170313 26.098031 7.7070312 25.707031 L 15 18.414062 L 22.292969 25.707031 C 22.682969 26.098031 23.317031 26.098031 23.707031 25.707031 L 25.707031 23.707031 C 26.098031 23.316031 26.098031 22.682969 25.707031 22.292969 L 18.414062 15 L 25.707031 7.7070312 C 26.098031 7.3170312 26.098031 6.6829688 25.707031 6.2929688 L 23.707031 4.2929688 C 23.316031 3.9019687 22.682969 3.9019687 22.292969 4.2929688 L 15 11.585938 L 7.7070312 4.2929688 C 7.5115312 4.0974687 7.255875 4 7 4 z"/>\n </svg>\n </div>\n `, div = document.createElement("div");
div.innerHTML = html, botContainer.appendChild(div.firstElementChild), pageContainer.scrollTop = pageContainer.scrollHeight;
let option = botOption(player.id);
option.disconnect.onclick = () => {
player.disconnect();
};
}
deleteBotOption(player) {
if (!player.connectSuccess) {
return;
}
let {botOption: botOption} = this.getElements();
botOption(player.id).option.remove();
}
updateBotOption(player, type) {
if (!player.connectSuccess) {
return;
}
let {botOption: botOption} = this.getElements(), option = botOption(player.id);
switch (type) {
case "title":
option.title.textContent = `[${player.id}]: ${player.myPlayer.nickname}`;
break;
}
}
addBotConnecting() {
let {botContainer: botContainer} = this.getElements(), div = document.createElement("div");
div.id = "connectingBot", div.textContent = "Connecting...", botContainer.appendChild(div);
}
removeBotConnecting() {
let {connectingBot: connectingBot} = this.getElements();
if (connectingBot !== null) {
connectingBot.remove();
}
}
createBot() {
let {addBot: addBot} = this.getElements();
addBot.click();
}
handleBotCreation(button) {
let id = 0;
button.onclick = async () => {
let ws = client.SocketManager.socket;
if (ws === null) {
return;
}
this.addBotConnecting();
let socket = await createSocket_default(ws.url);
socket.addEventListener("close", () => {
this.removeBotConnecting();
}), socket.onopen = () => {
let player = new PlayerClient_default(client);
player.PacketManager.Encoder = client.PacketManager.Encoder, player.PacketManager.Decoder = client.PacketManager.Decoder,
player.SocketManager.init(socket);
let onconnect = () => {
player.id = id++, client.clients.add(player), this.createBotOption(player),
this.removeBotConnecting();
};
socket.addEventListener("connected", onconnect);
let handleClose = () => {
socket.removeEventListener("connected", onconnect), client.clients.delete(player),
client.clientIDList.delete(player.myPlayer.id), client.pendingJoins.delete(player.myPlayer.id),
this.deleteBotOption(player), this.removeBotConnecting();
};
socket.addEventListener("error", handleClose), socket.addEventListener("close", handleClose);
};
};
}
handleResetSettings(button) {
button.onclick = () => {
resetSettings();
};
}
attachButtons() {
let {buttons: buttons} = this.getElements();
for (let button of buttons) {
switch (button.id) {
case "add-bot":
this.handleBotCreation(button);
break;
case "resetSettings":
this.handleResetSettings(button);
break;
}
}
}
closeMenu() {
let {menuWrapper: menuWrapper} = this.getElements();
menuWrapper.classList.remove("toopen"), menuWrapper.classList.add("toclose"),
this.menuOpened = !1, clearTimeout(this.toggleTimeout), this.toggleTimeout = setTimeout(() => {
menuWrapper.classList.remove("toclose"), this.frame.target.style.display = "none";
}, 150);
}
openMenu() {
let {menuWrapper: menuWrapper} = this.getElements();
this.frame.target.removeAttribute("style"), menuWrapper.classList.remove("toclose"),
menuWrapper.classList.add("toopen"), this.menuOpened = !0, clearTimeout(this.toggleTimeout),
this.toggleTimeout = setTimeout(() => {
menuWrapper.classList.remove("toopen");
}, 150);
}
toggleMenu() {
if (!this.menuLoaded) {
return;
}
if (this.menuOpened) {
this.closeMenu();
} else {
this.openMenu();
}
}
attachOpenMenu() {
let {openMenuButtons: openMenuButtons, menuPages: menuPages} = this.getElements();
for (let i = 0; i < openMenuButtons.length; i++) {
let button = openMenuButtons[i], id = button.getAttribute("data-id"), menuPage = this.querySelector(`.menu-page[data-id='${id}']`);
button.onclick = () => {
if (menuPage instanceof this.frame.window.HTMLDivElement) {
removeClass(openMenuButtons, "active"), button.classList.add("active"), removeClass(menuPages, "opened"),
menuPage.classList.add("opened");
} else {
Logger.error(`attachOpenMenu Error: Cannot find "${button.textContent}" menu`);
}
};
}
}
attachListeners() {
let {closeButton: closeButton, scriptDescription: scriptDescription} = this.getElements();
closeButton.onclick = () => {
this.closeMenu();
};
let preventDefaults = target => {
target.addEventListener("contextmenu", event => event.preventDefault()), target.addEventListener("mousedown", event => {
if (event.button === 1) {
event.preventDefault();
}
}), target.addEventListener("mouseup", event => {
if (event.button === 3 || event.button === 4) {
event.preventDefault();
}
});
};
preventDefaults(window), preventDefaults(this.frame.window);
let description = "v" + Glotus.version + " by Murka \u00b7 fixed by seldoom";
scriptDescription.textContent = description, this.handleResize(), window.addEventListener("resize", () => this.handleResize()),
this.frame.document.addEventListener("mouseup", event => {
if (this.activeHotkeyInput) {
this.applyCode(event.button);
} else if (this.isHotkeyInput(event.target) && event.button === 0) {
event.target.textContent = "Wait...", this.activeHotkeyInput = event.target,
event.target.classList.add("active");
}
}), this.frame.document.addEventListener("keyup", event => {
if (this.activeHotkeyInput && this.isHotkeyInput(event.target)) {
this.applyCode(event.code);
}
}), this.frame.window.addEventListener("keydown", event => client.InputHandler.handleKeydown(event)),
this.frame.window.addEventListener("keyup", event => client.InputHandler.handleKeyup(event)),
this.openMenu();
let watermark = document.createElement("div");
watermark.id = "Glotus Client!", watermark.textContent = "GLOTUS",
document.body.appendChild(watermark);
}
resetFrame() {
this.frame.target.remove(), this.init();
}
async init() {
try {
this.frame = await this.createFrame(), this.attachListeners(), this.attachHotkeyInputs(),
this.checkForRepeats(), this.attachCheckboxes(), this.attachColorPickers(),
this.attachSliders(), this.attachTextInputs(), this.attachDescriptions(), this.attachButtons(),
this.attachOpenMenu(), this.createRipple(".open-menu"), client.StatsManager.init();
let {menuContainer: menuContainer} = this.getElements();
if (Settings_default._menuTransparency) {
menuContainer.classList.add("transparent");
}
this.menuLoaded = !0, this.frame.window.focus(), Logger.test("Successfully injected iframe menu..");
} catch (err) {
Logger.error("Failed to inject iframe.. " + err);
}
}
}, UI_default = UI;
const defaultSettings = {
_primary: "Digit1",
_secondary: "Digit2",
_food: "KeyQ",
_wall: "Digit4",
_spike: "KeyC",
_windmill: "KeyV",
_farm: "KeyT",
_trap: "Space",
_turret: "KeyF",
_spawn: "KeyG",
_up: "KeyW",
_left: "KeyA",
_down: "KeyS",
_right: "KeyD",
_autoattack: "KeyE",
_lockrotation: "KeyX",
_lockBotPosition: "KeyZ",
_toggleChat: "Enter",
_toggleShop: "ShiftLeft",
_toggleClan: "ControlLeft",
_toggleMenu: "Escape",
_instakill: "KeyR",
_biomehats: !0,
_autoemp: !0,
_antienemy: !0,
_soldierDefault: !0,
_antianimal: !0,
_antispike: !0,
_empDefense: !0,
_autoheal: !0,
_autoSync: !0,
_velocityTick: !0,
_spikeSyncHammer: !0,
_spikeSync: !0,
_spikeTick: !0,
_knockbackTickTrap: !0,
_knockbackTickHammer: !0,
_knockbackTick: !0,
_toolSpearInsta: !0,
_autoSteal: !0,
_autoPush: !0,
_turretSteal: !0,
_spikeGearInsta: !0,
_antiRetrap: !0,
_turretSync: !0,
_automill: !0,
_autoplacer: !0,
_placementDefense: !0,
_preplacer: !1,
_autoplacerRadius: 325,
_placeAttempts: 4,
_autobreak: !0,
_safeWalk: !0,
_dashMovement: !0,
_autoGrind: !1,
_enemyTracers: !1,
_enemyTracersColor: "#cc5151",
_teammateTracers: !1,
_teammateTracersColor: "#8ecc51",
_animalTracers: !1,
_animalTracersColor: "#518ccc",
_notificationTracers: !0,
_notificationTracersColor: "#f5d951",
_itemMarkers: !0,
_itemMarkersColor: "#84bd4b",
_teammateMarkers: !0,
_teammateMarkersColor: "#bdb14b",
_enemyMarkers: !0,
_enemyMarkersColor: "#ba4949",
_weaponXPBar: !0,
_playerTurretReloadBar: !0,
_playerTurretReloadBarColor: "#cf7148",
_weaponReloadBar: !0,
_weaponReloadBarColor: "#5155cc",
_renderHP: !0,
_stackedDamage: !0,
_objectTurretReloadBar: !1,
_objectTurretReloadBarColor: "#66d9af",
_itemHealthBar: !1,
_itemHealthBarColor: "#6b449e",
_displayPlayerAngle: !1,
_weaponHitbox: !1,
_collisionHitbox: !1,
_placementHitbox: !1,
_possiblePlacement: !0,
// _killMessage et _killMessageText retires : le message est fige
// dans le module KillChat, il n y a plus rien a regler.
_autospawn: !1,
_autoaccept: !1,
_texturepack: !1,
_hideHUD: !1,
_smoothRendering: 160,
_menuTransparency: !0,
_chatLog: !1,
_followCursor: !0,
_movementRadius: 150,
_circleFormation: !1,
_circleRotation: !0,
_circleRadius: 100,
_storeItems: [ [ 15, 31, 6, 7, 22, 12, 26, 11, 53, 20, 40, 56 ], [ 11, 17, 16, 13, 19, 18, 21 ] ],
_totalKills: 0,
_globalKills: 0,
_deaths: 0,
_autoSyncTimes: 0,
_velocityTickTimes: 0,
_spikeSyncHammerTimes: 0,
_spikeSyncTimes: 0,
_spikeTickTimes: 0,
_knockbackTickTrapTimes: 0,
_knockbackTickHammerTimes: 0,
_knockbackTickTimes: 0
}, settings = {
...defaultSettings,
...CustomStorage.get("Glotus")
};
for (let iterator in settings) {
let key = iterator;
if (!defaultSettings.hasOwnProperty(key)) {
delete settings[key];
}
}
const SaveSettings = () => {
CustomStorage.set("Glotus", settings);
};
SaveSettings();
const resetSettings = () => {
for (let iterator in defaultSettings) {
let key = iterator;
settings[key] = defaultSettings[key];
}
SaveSettings(), UI_default.resetFrame();
}, Settings_default = settings;
const GameUI = new class {
getElements() {
let querySelector = document.querySelector.bind(document), querySelectorAll = document.querySelectorAll.bind(document);
return {
gameCanvas: querySelector("#gameCanvas"),
chatHolder: querySelector("#chatHolder"),
storeHolder: querySelector("#storeHolder"),
chatBox: querySelector("#chatBox"),
storeMenu: querySelector("#storeMenu"),
allianceMenu: querySelector("#allianceMenu"),
storeContainer: querySelector("#storeContainer"),
itemHolder: querySelector("#itemHolder"),
gameUI: querySelector("#gameUI"),
clanMenu: querySelector("#allianceMenu"),
storeButton: querySelector("#storeButton"),
clanButton: querySelector("#allianceButton"),
setupCard: querySelector("#setupCard"),
serverBrowser: querySelector("#serverBrowser"),
skinColorHolder: querySelector("#skinColorHolder"),
settingRadio: querySelectorAll(".settingRadio"),
pingDisplay: querySelector("#pingDisplay"),
enterGame: querySelector("#enterGame"),
nameInput: querySelector("#nameInput"),
allianceInput: querySelector("#allianceInput"),
allianceButton: querySelector("#allianceButton"),
noticationDisplay: querySelector("#noticationDisplay"),
nativeResolution: querySelector("#nativeResolution"),
showPing: querySelector("#showPing"),
mapDisplay: querySelector("#mapDisplay"),
chatLog: querySelector("#chatLog")
};
}
selectSkinColor(skin) {
let skinValue = skin === 10 ? "toString" : skin;
CustomStorage.set("skin_color", skinValue);
let selectSkin = getTargetValue(window, "selectSkinColor");
if (selectSkin !== void 0) {
selectSkin(skinValue);
}
return skinValue;
}
createSkinColors() {
let skin_color = CustomStorage.get("skin_color") || 0, index = skin_color === "toString" ? 10 : skin_color, {setupCard: setupCard} = this.getElements(), skinHolder = document.createElement("div");
skinHolder.id = "skinHolder";
let prevIndex = index;
for (let i = 0; i < Config_default.skinColors.length; i++) {
let color = Config_default.skinColors[i], div = document.createElement("div");
if (div.classList.add("skinColorItem"), i === index) {
div.classList.add("activeSkin");
}
div.style.backgroundColor = color, div.onclick = () => {
let colorButton = skinHolder.childNodes[prevIndex];
if (colorButton instanceof HTMLDivElement) {
colorButton.classList.remove("activeSkin");
}
div.classList.add("activeSkin"), prevIndex = i, this.selectSkinColor(i);
}, skinHolder.appendChild(div);
}
setupCard.appendChild(skinHolder);
}
formatMainMenu() {
let {setupCard: setupCard, serverBrowser: serverBrowser, settingRadio: settingRadio, gameUI: gameUI} = this.getElements();
setupCard.appendChild(serverBrowser), setupCard.querySelector("br")?.remove(),
this.createSkinColors();
let radio = settingRadio[0];
if (radio) {
setupCard.appendChild(radio);
}
let div = document.createElement("div");
div.id = "glotusStats", div.innerHTML = '\n <span>PING: <span id="glotusPing"></span>ms</span>\n <span>FPS: <span id="glotusFPS"></span></span>\n <span>PACKETS: <span id="glotusPackets"></span></span>\n <span>FastQ: <span id="glotusFastQ">false</span></span>\n <span>Places: <span id="glotusPlaces">0</span></span>\n <span>Total Kills: <span id="glotusTotalKills">0</span></span>\n <span>Deaths: <span id="glotusTotalDeaths">0</span></span>\n <span>Module: <span id="glotusActiveModule">null</span></span>\n <span>SpikeDmg: <span id="glotusSpikeDamage"></span></span>\n <span>PotDmg: <span id="glotusPotentialDamage"></span></span>\n <span>Danger: <span id="glotusDangerState"></span></span>\n <span>Hat: <span id="glotusEquipHat">0</span></span>\n <span>CollideSpike: <span id="glotusCollideSpike"></span></span>\n <span style="color: #f5d951; margin-top: 5px; display: block;">Glotus Client!</span>\n ',
gameUI.appendChild(div);
}
attachItemCount() {
let actionBar = document.querySelectorAll("div[id*='actionBarItem'");
for (let i = 19; i < 39; i++) {
let item = Items[i - 16];
if (actionBar[i] instanceof HTMLDivElement && item !== void 0 && "itemGroup" in item) {
let group = item.itemGroup, span = document.createElement("span");
span.classList.add("itemCounter"), span.setAttribute("data-id", group + "");
let {count: count, limit: limit} = client.myPlayer.getItemCount(group);
span.textContent = `${count}/${limit}`, actionBar[i].appendChild(span);
}
}
}
modifyInputs() {
let {chatHolder: chatHolder, chatBox: chatBox, nameInput: nameInput} = this.getElements();
chatBox.onblur = () => {
chatHolder.style.display = "none";
let value = chatBox.value;
if (value.length > 0) {
client.PacketManager.chat(value);
}
chatBox.value = "";
}, nameInput.onchange = () => {
CustomStorage.set("moo_name", nameInput.value, !1);
};
}
updateItemCount(group) {
let items = document.querySelectorAll(`span.itemCounter[data-id='${group}']`), {count: count, limit: limit} = client.myPlayer.getItemCount(group);
for (let item of items) {
item.textContent = `${count}/${limit}`;
}
}
interceptEnterGame() {
let enterGame = document.querySelector("#enterGame"), observer = new MutationObserver(() => {
observer.disconnect(), this.load();
});
observer.observe(enterGame, {
attributes: !0
});
}
updatePing(ping) {
let span = document.querySelector("#glotusPing");
if (span !== null) {
span.textContent = ping.toString();
}
}
updateFPS(fps) {
let span = document.querySelector("#glotusFPS");
if (span !== null) {
span.textContent = fps.toString();
}
}
updatePackets(packets) {
let span = document.querySelector("#glotusPackets");
if (span !== null) {
span.textContent = packets.toString();
}
}
updateFastQ(state) {
let span = document.querySelector("#glotusFastQ");
if (span !== null) {
span.textContent = state.toString();
}
}
updatePlaces(count) {}
updateTotalKills(kills) {
let span = document.querySelector("#glotusTotalKills");
if (span !== null) {
span.textContent = kills.toString();
}
}
updateTotalDeaths(deaths) {
let span = document.querySelector("#glotusTotalDeaths");
if (span !== null) {
span.textContent = deaths.toString();
}
}
updateActiveModule(name) {
let span = document.querySelector("#glotusActiveModule");
if (span !== null) {
span.textContent = name + "";
}
}
updateSpikeDamage(state) {
let span = document.querySelector("#glotusSpikeDamage");
if (span !== null) {
span.textContent = state + "";
}
}
updatePotentialDamage(state) {
let span = document.querySelector("#glotusPotentialDamage");
if (span !== null) {
span.textContent = state + "";
}
}
updateCollideSpike(state) {
let span = document.querySelector("#glotusCollideSpike");
if (span !== null) {
span.textContent = state + "";
}
}
updateDangerState(state) {
let span = document.querySelector("#glotusDangerState");
if (span !== null) {
span.textContent = state + "";
}
}
updateEquipHat(state) {
let span = document.querySelector("#glotusEquipHat");
if (span !== null) {
span.textContent = state + "";
}
}
init() {
this.formatMainMenu(), this.modifyInputs(), this.interceptEnterGame();
}
load() {
let {nativeResolution: nativeResolution, enterGame: enterGame} = this.getElements();
if (!nativeResolution.checked) {
nativeResolution.click();
}
this.selectSkinColor(CustomStorage.get("skin_color") || 0);
let enterGameButton = enterGame, _enterGame = enterGameButton.onclick;
enterGameButton.onclick = function() {
delete enterGameButton.onclick, Glotus.startGame(), enterGameButton.onclick = _enterGame;
}, Object.defineProperty(enterGameButton, "onclick", {
set(callback) {
_enterGame = callback;
},
configurable: !0
});
}
loadGame() {
this.attachItemCount();
let {storeButton: storeButton, allianceButton: allianceButton, mapDisplay: mapDisplay} = this.getElements(), that = this, _storeClick = storeButton.onclick;
storeButton.onclick = function(...args) {
that.reset(), _storeClick.apply(this, args);
};
let _allianceClick = allianceButton.onclick;
allianceButton.onclick = function(...args) {
that.reset(), _allianceClick.apply(this, args);
};
let _mapClick = mapDisplay.onclick;
mapDisplay.onclick = function(event) {
let bounds = mapDisplay.getBoundingClientRect(), scale = 14400 / bounds.width, posX = (event.clientX - bounds.left) * scale, posY = (event.clientY - bounds.top) * scale;
client.ModuleHandler.endTarget.setXY(posX, posY), client.ModuleHandler.followPath = !0,
_mapClick.call(this, event);
}, this.createChatLog();
}
isOpened(element) {
return element.style.display !== "none";
}
closePopups(element) {
let {allianceMenu: allianceMenu, clanButton: clanButton} = this.getElements();
if (this.isOpened(allianceMenu) && element !== allianceMenu) {
clanButton.click();
}
let popups = document.querySelectorAll("#chatHolder, #storeMenu, #allianceMenu, #storeContainer");
for (let popup of popups) {
if (popup === element) {
continue;
}
popup.style.display = "none";
}
if (element instanceof HTMLElement) {
element.style.display = this.isOpened(element) ? "none" : "";
}
}
createAcceptButton(type) {
let data = [ [ "#cc5151", "" ], [ "#8ecc51", "" ] ], [color, code] = data[type], button = document.createElement("div");
return button.classList.add("notifButton"), button.innerHTML = `<i class="material-icons" style="font-size:28px; color:${color};">${code}</i>`,
button;
}
resetNotication(noticationDisplay) {
noticationDisplay.innerHTML = "", noticationDisplay.style.display = "none";
}
clearNotication() {
let {noticationDisplay: noticationDisplay} = this.getElements();
this.resetNotication(noticationDisplay);
}
createRequest(user) {
let [id, name] = user, {noticationDisplay: noticationDisplay} = this.getElements();
if (noticationDisplay.style.display !== "none") {
return;
}
noticationDisplay.innerHTML = "", noticationDisplay.style.display = "block";
let text = document.createElement("div");
text.classList.add("notificationText"), text.textContent = name, noticationDisplay.appendChild(text);
let handleClick = type => {
let button = this.createAcceptButton(type);
button.onclick = () => {
this.resetNotication(noticationDisplay), client.PacketManager.clanRequest(id, !!type),
client.myPlayer.joinRequests.shift(), client.pendingJoins.delete(id);
}, noticationDisplay.appendChild(button);
};
handleClick(0), handleClick(1);
}
clientSpawn() {
let {enterGame: enterGame} = this.getElements();
enterGame.click();
}
handleEnter(event) {
let {allianceInput: allianceInput, allianceButton: allianceButton} = this.getElements(), active = document.activeElement;
if (client.myPlayer.inGame) {
if (active === allianceInput) {
allianceButton.click();
} else {
this.toggleChat(event);
}
return;
}
this.clientSpawn();
}
toggleChat(event) {
let {chatHolder: chatHolder, chatBox: chatBox} = this.getElements();
if (this.closePopups(chatHolder), this.isOpened(chatHolder)) {
event.preventDefault(), chatBox.focus();
} else {
chatBox.blur();
}
}
reset() {
StoreHandler_default.closeStore();
}
openClanMenu() {
let {clanButton: clanButton} = this.getElements();
this.reset(), clanButton.click();
}
logCache=[];
chatLog=null;
addLogMessage(cache) {
let [type, message] = cache, div = document.createElement("div");
div.className = "logMessage", div.innerHTML = `\n <span class="darken">${formatDate()}</span>\n <span class="messageContent ${type}"></span>\n `,
div.querySelector(".messageContent").textContent = message;
let messageContainer = document.querySelector("#messageContainer");
if (messageContainer !== null) {
messageContainer.appendChild(div), messageContainer.scrollTop = messageContainer.scrollHeight;
}
}
addCacheMessage(cache) {
if (this.chatLog === null) {
this.logCache.push(cache);
} else {
this.addLogMessage(cache);
}
}
createChatLog() {
if (this.chatLog !== null) {
return;
}
let container = document.createElement("div");
container.id = "chatLog", container.innerHTML = '\n <h1 id="chatLogHeader">DevTools Chat Log</h1>\n <div id="messageContainer"></div>\n ',
document.body.appendChild(container), this.chatLog = container;
for (let log of this.logCache) {
this.addLogMessage(log);
}
}
toggleChatLog() {
if (this.chatLog === null) {
this.createChatLog();
}
if (Settings_default._chatLog) {
this.chatLog.classList.remove("hidden");
} else {
this.chatLog.classList.add("hidden");
}
}
lastMessages=[];
handleMessageLog(message) {
if (message = message.trim().replace(/\s+/g, " "), this.lastMessages.length > 3) {
this.lastMessages.shift();
}
if (this.lastMessages.includes(message)) {
return;
}
this.lastMessages.push(message), this.addLogMessage([ "log", message ]);
}
}, GameUI_default = GameUI;
class Logger {
static staticLog=console.log;
static staticError=console.error;
static staticWarn=console.warn;
static log(msg) {
if (GameUI_default.addCacheMessage([ "log", msg ]), isProd) {
return;
}
this.staticLog(msg);
}
static error(msg) {
if (GameUI_default.addCacheMessage([ "error", msg ]), isProd) {
return;
}
this.staticError(msg);
}
static warn(msg) {
if (GameUI_default.addCacheMessage([ "warn", msg ]), isProd) {
return;
}
this.staticWarn(msg);
}
static test(msg) {
if (GameUI_default.addCacheMessage([ "log", msg ]), isProd) {
return;
}
this.staticLog(msg);
}
}
/* ==================================================================
* HLM - COUCHE CRYPTO PAR SOCKET (pour les bots)
*
* La connexion principale emprunte le canal du jeu, qui signe et
* numerote pour nous. Chaque bot, lui, ouvre SA connexion : il recoit
* son propre io-init, donc sa propre graine, sa propre cle et son
* propre compteur de sequence. Il faut donc un etat par socket.
* ================================================================== */
const HLM_C2S = ["M", "D", "9", "e", "F", "z", "H", "K", "L", "N", "b", "P", "Q", "c", "6", "S", "0"];
const HLM_S2C = ["A", "B", "C", "D", "E", "a", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P",
"Q", "R", "S", "T", "U", "V", "X", "Y", "Z", "g", "1", "2", "3", "4", "5", "6",
"7", "8", "9", "0"];
const HLM_K = new Uint32Array([
1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, 2870763221,
3624381080, 310598401, 607225278, 1426881987, 1925078388, 2162078206, 2614888103, 3248222580,
3835390401, 4022224774, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986,
2554220882, 2821834349, 2952996808, 3210313671, 3336571891, 3584528711, 113926993, 338241895,
666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, 2177026350, 2456956037,
2730485921, 2820302411, 3259730800, 3345764771, 3516065817, 3600352804, 4094571909, 275423344,
430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779,
1955562222, 2024104815, 2227730452, 2361852424, 2428436474, 2756734187, 3204031479, 3329325298
]);
const HLM = {
rotr(x, n) { return x >>> n | x << 32 - n; },
sha256(bytes) {
const h = new Uint32Array([1779033703, 3144134277, 1013904242, 2773480762,
1359893119, 2600822924, 528734635, 1541459225]);
const len = bytes.length, bitLen = 8 * len, padded = len + 9;
const buf = new Uint8Array(64 * Math.ceil(padded / 64));
buf.set(bytes); buf[len] = 128;
const view = new DataView(buf.buffer);
view.setUint32(buf.length - 4, bitLen >>> 0, false);
view.setUint32(buf.length - 8, Math.floor(bitLen / 4294967296), false);
const w = new Uint32Array(64);
for (let off = 0; off < buf.length; off += 64) {
for (let i = 0; i < 16; i++) w[i] = view.getUint32(off + 4 * i, false);
for (let i = 16; i < 64; i++) {
const s0 = this.rotr(w[i - 15], 7) ^ this.rotr(w[i - 15], 18) ^ w[i - 15] >>> 3;
const s1 = this.rotr(w[i - 2], 17) ^ this.rotr(w[i - 2], 19) ^ w[i - 2] >>> 10;
w[i] = w[i - 16] + s0 + w[i - 7] + s1 | 0;
}
let a = h[0], b = h[1], c = h[2], d = h[3], e = h[4], f = h[5], g = h[6], hh = h[7];
for (let i = 0; i < 64; i++) {
const t1 = hh + (this.rotr(e, 6) ^ this.rotr(e, 11) ^ this.rotr(e, 25)) + (e & f ^ ~e & g) + HLM_K[i] + w[i] | 0;
const maj = a & b ^ a & c ^ b & c;
hh = g; g = f; f = e; e = d + t1 | 0; d = c; c = b; b = a;
a = t1 + ((this.rotr(a, 2) ^ this.rotr(a, 13) ^ this.rotr(a, 22)) + maj | 0) | 0;
}
h[0] = h[0] + a | 0; h[1] = h[1] + b | 0; h[2] = h[2] + c | 0; h[3] = h[3] + d | 0;
h[4] = h[4] + e | 0; h[5] = h[5] + f | 0; h[6] = h[6] + g | 0; h[7] = h[7] + hh | 0;
}
const out = new Uint8Array(32), ov = new DataView(out.buffer);
for (let k = 0; k < 8; k++) ov.setUint32(4 * k, h[k], false);
return out;
},
hmac6(key, message) {
let k = key;
if (k.length > 64) k = this.sha256(k);
const padKey = new Uint8Array(64); padKey.set(k);
const inner = new Uint8Array(64 + message.length);
const outer = new Uint8Array(96);
for (let i = 0; i < 64; i++) { inner[i] = 54 ^ padKey[i]; outer[i] = 92 ^ padKey[i]; }
inner.set(message, 64);
outer.set(this.sha256(inner), 64);
return this.sha256(outer).subarray(0, 6);
},
hexToBytes(hex) {
const out = new Uint8Array(hex.length / 2);
for (let i = 0; i < out.length; i++) out[i] = parseInt(hex.substr(2 * i, 2), 16);
return out;
},
buildTable(list, seed) {
const n = list.length;
const idx = list.map((_, i) => i);
const rand = (s => () => {
s = (s |= 0) + 1831565813 | 0;
let t = Math.imul(s ^ s >>> 15, 1 | s);
return (((t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t) ^ t >>> 14) >>> 0) / 4294967296;
})(seed >>> 0);
for (let i = n - 1; i > 0; i--) {
const jj = Math.floor(rand() * (i + 1));
const tmp = idx[i]; idx[i] = idx[jj]; idx[jj] = tmp;
}
const enc = {}, dec = {};
for (let i = 0; i < n; i++) { enc[list[i]] = idx[i]; dec[idx[i]] = list[i]; }
return { enc: enc, dec: dec };
},
// Construit l etat a partir des donnees du paquet io-init
makeState(data) {
if (!data || data[3] !== 1) return null;
const seed = data[1] >>> 0;
const mixed = (seed ^ Math.imul(1, 2654435761)) >>> 0;
return {
key: this.hexToBytes(data[2]),
c2s: this.buildTable(HLM_C2S, mixed),
s2c: this.buildTable(HLM_S2C, (2246822507 ^ mixed) >>> 0),
seq: 0
};
},
// msgpack([type, args, seq]) prefixe du HMAC tronque a 6 octets
encode(state, encoder, type, args) {
const encType = state.c2s.enc[type];
if (encType === undefined) return null;
const body = encoder.encode([ encType, args, ++state.seq ]);
const sig = this.hmac6(state.key, body);
const out = new Uint8Array(6 + body.length);
out.set(sig, 0); out.set(body, 6);
return out;
}
};
class Regexer {
code;
COPY_CODE;
hookCount=0;
hookAttempts=0;
ANY_LETTER="(?:[^\\x00-\\x7F-]|\\$|\\w)";
NumberSystem=[ {
radix: 2,
prefix: "0b0*"
}, {
radix: 8,
prefix: "0+"
}, {
radix: 10,
prefix: ""
}, {
radix: 16,
prefix: "0x0*"
} ];
constructor(code) {
this.code = code, this.COPY_CODE = code;
}
isRegExp(regex) {
return regex instanceof RegExp;
}
generateNumberSystem(int) {
return `(?:${this.NumberSystem.map(({radix: radix, prefix: prefix}) => prefix + int.toString(radix)).join("|")})`;
}
parseVariables(regex) {
return regex = regex.replace(/{VAR}/g, "(?:let|var|const)"), regex = regex.replace(/{QUOTE{(\w+)}}/g, "(?:'$1'|\"$1\"|`$1`)"),
regex = regex.replace(/NUM{(\d+)}/g, (...args) => this.generateNumberSystem(Number(args[1]))),
regex = regex.replace(/\\w/g, this.ANY_LETTER), regex;
}
format(name, inputRegex, flags) {
this.hookAttempts++;
let regex = "";
if (Array.isArray(inputRegex)) {
regex = inputRegex.map(exp => this.isRegExp(exp) ? exp.source : exp).join("\\s*");
} else if (this.isRegExp(inputRegex)) {
regex = inputRegex.source;
} else {
regex = inputRegex + "";
}
regex = this.parseVariables(regex);
let expression = RegExp(regex, flags);
if (!expression.test(this.code)) {
Logger.error("Failed to find: " + name);
} else {
this.hookCount++;
}
return expression;
}
match(name, regex, flags) {
let expression = this.format(name, regex, flags);
return this.code.match(expression) || [];
}
replace(name, regex, substr, flags) {
let expression = this.format(name, regex, flags);
return this.code = this.code.replace(expression, substr), expression;
}
insertAtIndex(index, str) {
return this.code.slice(0, index) + str + this.code.slice(index, this.code.length);
}
template(name, regex, substr, getIndex) {
let expression = this.format(name, regex), match = this.code.match(expression);
if (match === null) {
return;
}
let index = getIndex(match);
this.code = this.insertAtIndex(index, substr.replace(/\$(\d+)/g, (...args) => match[args[1]]));
}
append(name, regex, substr) {
this.template(name, regex, substr, match => (match.index || 0) + match[0].length);
}
prepend(name, regex, substr) {
this.template(name, regex, substr, match => match.index || 0);
}
wrap(left, right) {
// Le bundle du jeu est desormais un MODULE ES : il commence par des
// instructions import de premier niveau. Les envelopper dans une
// fonction est une erreur de syntaxe. On laisse donc le prologue
// d'imports au niveau superieur et on n'encapsule que le reste.
let prologue = "", body = this.code;
let re = /^\s*import\s*(?:[^"';]*from\s*)?("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')\s*;?/;
for (;;) {
let m = body.match(re);
if (m === null || m.index !== 0) break;
prologue += m[0];
body = body.slice(m[0].length);
}
this.code = prologue + left + body + right;
}
}
const Regexer_default = Regexer;
const formatCode2 = code => {
let Hook = new Regexer_default(code);
if (!isProd) {
Hook.code = 'console.log("Loaded bundle..");' + Hook.code;
}
Hook.append("preRenderLoop", /\)\}\}\(\);function \w+\(\)\{/, "Glotus.Renderer.preRender();"),
Hook.append("postRenderLoop", /\w+,\w+\(\),requestAnimFrame\(\w+\)/, ";Glotus.Renderer.postRender();"),
Hook.append("mapPreRender", /(\w+)\.lineWidth=NUM{4};/, "Glotus.Renderer.mapPreRender($1);"),
Hook.prepend("gameInit", /function (\w+)\(\w+\)\{\w+\.\w+\(\w+,f/, "Glotus.gameInit=function(a){$1(a);};"),
Hook.prepend("LockRotationClient", /return \w+\?\(\!/, "return Glotus.myClient.ModuleHandler.currentAngle;"),
Hook.replace("DisableResetMoveDir", /\w+=\{\},\w+\.send\("\w+"\)/, ""), Hook.append("offset", /\W170\W.+?(\w+)=\w+\-\w+\/2.+?(\w+)=\w+\-\w+\/2;/, "Glotus.myClient.myPlayer.offset.setXY($1,$2);"),
Hook.prepend("renderEntity", /\w+\.health>NUM{0}.+?(\w+)\.fillStyle=(\w+)==(\w+)/, ";Glotus.hooks.EntityRenderer.render($1,$2,$3);false&&"),
Hook.append("renderItemPush", /,(\w+)\.blocker,\w+.+?2\)\)/, ",Glotus.Renderer.renderObjects.push($1)"),
Hook.append("renderItem", /70, 0.35\)",(\w+).+?\w+\)/, ",Glotus.hooks.ObjectRenderer.render($1)"),
Hook.append("RemoveSendAngle", /clientSendRate\)/, "&&false"), Hook.replace("handleEquip", /\w+\.send\("\w+",0,(\w+),(\w+)\)/, "Glotus.myClient.ModuleHandler.equip($2,$1,true,true)"),
Hook.replace("handleBuy", /\w+\.send\("\w+",1,(\w+),(\w+)\)/, "Glotus.myClient.ModuleHandler.buy($2,$1,true)"),
Hook.prepend("RemovePingCall", /\w+&&clearTimeout/, "return;"), Hook.append("RemovePingState", /let \w+=-1;function \w+\(\)\{/, "return;"),
Hook.prepend("preRender", /(\w+)\.lineWidth=NUM{4},/, "Glotus.hooks.ObjectRenderer.preRender($1);"),
Hook.replace("RenderGrid", /("#91b2db".+?)(for.+?)(\w+\.stroke)/, "$1$3"), Hook.replace("upgradeItem", /(upgradeItem.+?onclick.+?)\w+\.send\("\w+",(\w+)\)\}/, "$1Glotus.myClient.ModuleHandler.upgradeItem($2)}");
let data = Hook.match("DeathMarker", /99999.+?(\w+)=\{x:(\w+)/);
Hook.append("playerDied", /NUM{99999};function \w+\(\)\{/, `if(Glotus.settings._autospawn){${data[1]}={x:${data[2]}.x,y:${data[2]}.y};return};`),
Hook.append("updateNotificationRemove", /\w+=\[\],\w+=\[\];function \w+\(\w+,\w+\)\{/, "return;"),
Hook.replace("checkTrusted", /checkTrusted:(\w+)/, "checkTrusted:(callback)=>(event)=>callback(event)"),
Hook.replace("removeSkins", /(\(\)\{)(let \w+="";for\(let)/, "$1return;$2"),
Hook.prepend("unlockedItems", /\w+\.list\[\w+\]\.pre==/, "true||"), Hook.replace("gameColor", /rgba\(0, 0, 70, 0.35\)/, "rgba(23, 6, 62, 0.6)"),
Hook.prepend("renderPlayer", /function (\w+)\(\w+,\w+\)\{\w+=\w+\|\|\w+,/, "Glotus.hooks.renderPlayer=$1;"),
Hook.replace("maskFRVR", /window\.FRVR/, "FRVR", "g"), Hook.replace("scaleWidth", /=1920/, "=Glotus.ZoomHandler.scale.smooth.w"),
Hook.replace("scaleHeight", /=1080/, "=Glotus.ZoomHandler.scale.smooth.h"),
Hook.replace("maskLerp", /Math\.lerpAngle/, "THIS_STORAGE.lerpAngle", "g"),
Hook.replace("smoothRendering", /(\w+=)NUM{170};/, "$1Glotus._getSmoothRendering();");
// ------------------------------------------------------------------
// HLM - trois crochets ajoutes
//
// Le jeu capture WebSocket.prototype.send au chargement de son
// bundle et appelle ensuite cette reference native. Un Proxy sur
// window.WebSocket ne le verrait donc pas - et de toute facon
// window.WebSocket est devenu non modifiable.
// Comme on reecrit le bundle, on demande au jeu de nous donner
// directement son socket, son objet reseau et son etat de
// chiffrement. Un seul compteur de sequence pour tout le monde.
// ------------------------------------------------------------------
Hook.append("exposeSocket", /this\.socket=new \w+\(\w+\),this\.socket\.binaryType="arraybuffer"/,
",window.__glotusSocket&&window.__glotusSocket(this.socket)"),
Hook.prepend("exposeIO", /let (\w+)=null;const (\w+)=\{socket:null,connected:!NUM{1},socketId:-NUM{1},/,
"window.__glotusEnc=function(){return $1};window.__glotusIO=function(){return $2};");
let addCode = isProd ? "const Glotus=window.Glotus;delete window.Glotus;" : "";
return Hook.wrap("(function THIS_STORAGE(){const FRVR=window.FRVR;delete window.FRVR;" + addCode, "})();"),
Logger.test(`Modified bundle, total amount of hooks: ${Hook.hookCount}/${Hook.hookAttempts}`),
Hook.code;
}, formatCode_default = formatCode2;
const Injector = new class {
init(node) {
this.loadScript(node.src);
}
loadScript(src) {
let xhr = new XMLHttpRequest;
xhr.open("GET", src, !1), xhr.send();
// HLM : si le bundle d'origine s'est deja execute, injecter une
// seconde copie fait tourner le jeu en double - c'est ce que
// signalaient "Turnstile already has been loaded" et "already been
// rendered in this container", et c'est ce qui provoquait la
// deconnexion. Mieux vaut s'arreter et le dire clairement.
let alreadyRan = typeof window.loadedScript !== "undefined"
|| document.querySelector("#turnstileWidget iframe") !== null;
console.log("[HLM] avant injection : jeu d'origine deja execute = " + alreadyRan);
if (alreadyRan) {
// On continue : en injection lente, l'instance d'origine est
// gelee car Glotus intercepte son requestAnimFrame. Elle a
// seulement eu le temps de dessiner le widget Turnstile, d'ou
// le refus de rendu pour le notre - sans consequence, on lit
// le jeton dans le champ cache.
console.warn("[HLM] le bundle d'origine a demarre avant nous :"
+ " son instance est gelee, on injecte quand meme.");
}
let code = formatCode_default(xhr.responseText);
// Les specificateurs relatifs ("./vendor-xxxx.js") se resoudraient
// par rapport a l'URL blob: et non au site : on les rend absolus.
code = code.replace(/(\bfrom\s*|\bimport\s*\(\s*)("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/g, function (whole, kw, lit) {
let spec = lit.slice(1, -1);
if (!/^[.\/]/.test(spec)) return whole;
try { return kw + JSON.stringify(new URL(spec, src).href); } catch (e) { return whole; }
});
// Function(code)() et un script classique ne peuvent pas executer un
// import de premier niveau : on injecte desormais un module.
let blob = new Blob([ code ], {
type: "text/javascript"
}), element = document.createElement("script");
element.type = "module", element.src = URL.createObjectURL(blob),
this.waitForBody(function () {
document.head.appendChild(element);
});
}
waitForBody(callback) {
if (document.readyState !== "loading") {
callback(), Logger.test("Page already loaded, instant inject..");
return;
}
document.addEventListener("readystatechange", () => {
if (document.readyState !== "loading") {
callback();
}
}, {
once: !0
});
}
}, Injector_default = Injector;
const resetGame = loadedFast => {
let scriptExecuteHandler = node => {
node.addEventListener("beforescriptexecute", event => {
event.preventDefault();
}, {
once: !0
}), node.remove();
}, scriptBundle = null, hlmTurnstileApiSeen = !1, handleScriptElement = node => {
// Le jeu ayant demarre deux fois, api.js de Turnstile etait injecte
// deux fois : "Turnstile already has been loaded", puis les deux
// instances se disputaient le widget et aucun jeton ne sortait.
if (node instanceof HTMLScriptElement && /challenges\.cloudflare\.com\/turnstile/.test(node.src)) {
if (hlmTurnstileApiSeen) {
console.warn("[HLM] second chargement de l'api Turnstile ignore"), node.remove();
return;
}
hlmTurnstileApiSeen = !0;
return;
}
let isScript = node instanceof HTMLScriptElement, isLink = node instanceof HTMLLinkElement, regex = /frvr|jquery|howler|assets|cookie|securepubads|google|ads/i;
if (isScript && regex.test(node.src) || isLink && regex.test(node.href) || regex.test(node.innerHTML)) {
scriptExecuteHandler(node);
}
if (isScript && /assets.+\.js$/.test(node.src) && scriptBundle === null) {
if (scriptBundle = node, Logger.test("Found script element, resolving.."), scriptExecuteHandler(node),
loadedFast) {
Injector_default.init(node);
}
}
};
new MutationObserver(mutations => {
for (let mutation of mutations) {
for (let node of mutation.addedNodes) {
if (node instanceof HTMLScriptElement || node instanceof HTMLLinkElement) {
handleScriptElement(node);
}
}
}
}).observe(document, {
childList: !0,
subtree: !0
}), document.querySelectorAll("script").forEach(handleScriptElement), document.querySelectorAll("link").forEach(handleScriptElement),
document.querySelectorAll("iframe").forEach(iframe => {
iframe.remove();
});
let resolvePromise = data => new Promise(function(resolve) {
resolve(data);
}), win = window;
if (blockProperty(win, "onbeforeunload"), win.frvrSdkInitPromise = resolvePromise(),
blockProperty(win, "frvrSdkInitPromise"), win.FRVR = {
bootstrapper: {
complete() {}
},
tracker: {
levelStart() {}
},
ads: {
show() {
return resolvePromise();
}
},
channelCharacteristics: {
allowNavigation: !0
},
setChannel() {}
}, blockProperty(win, "FRVR"), !loadedFast) {
let _define = win.customElements.define;
win.customElements.define = function() {
win.customElements.define = _define;
}, win.requestAnimFrame = function() {
if (delete win.requestAnimFrame, scriptBundle !== null) {
Injector_default.init(scriptBundle);
}
}, blockProperty(win, "requestAnimFrame");
}
let _fetch = window.fetch;
if (window.fetch = new Proxy(_fetch, {
apply(target, _this, args) {
let link = args[0];
if (typeof link === "string") {
if (/ping/.test(link)) {
return resolvePromise();
}
}
return target.apply(_this, args);
}
}), CustomStorage.set("moofoll", 1), CustomStorage.get("skin_color") === null) {
CustomStorage.set("skin_color", "toString");
}
window.addEventListener = new Proxy(window.addEventListener, {
apply(target, _this, args) {
if ([ "keydown", "keyup" ].includes(args[0]) && args[2] === void 0) {
if (args[0] === "keyup" && loadedFast) {
window.addEventListener = target;
}
return null;
}
return target.apply(_this, args);
}
});
let proto = HTMLDivElement.prototype;
proto.addEventListener = new Proxy(proto.addEventListener, {
apply(target, _this, args) {
if (_this.id === "touch-controls-fullscreen" && /^mouse/.test(args[0]) && args[2] === !1) {
if (/up$/.test(args[0]) && loadedFast) {
proto.addEventListener = target;
}
return null;
}
return target.apply(_this, args);
}
}), window.setInterval = new Proxy(window.setInterval, {
apply(target, _this, args) {
if (/cordova/.test(args[0].toString()) && args[1] === 1e3) {
if (loadedFast) {
window.setInterval = target;
}
return null;
}
return target.apply(_this, args);
}
});
let deleteProp = (target, name) => {
delete target[name];
};
Hooker_default.createRecursiveHook(window, "config", (that, config) => (deleteProp(that, "openLink"),
deleteProp(that, "aJoinReq"), deleteProp(that, "follmoo"), deleteProp(that, "kickFromClan"),
deleteProp(that, "sendJoin"), deleteProp(that, "leaveAlliance"), deleteProp(that, "createAlliance"),
deleteProp(that, "storeBuy"), deleteProp(that, "storeEquip"), deleteProp(that, "showItemInfo"),
deleteProp(that, "selectSkinColor"), deleteProp(that, "config"), deleteProp(that, "altchaCreateWorker"),
deleteProp(that, "captchaCallbackHook"), deleteProp(that, "showPreAd"), deleteProp(that, "setUsingTouch"),
that.addEventListener("blur", that.onblur), deleteProp(that, "onblur"), that.addEventListener("focus", that.onfocus),
deleteProp(that, "onfocus"), Glotus.config = config, loadedFast)), Hooker_default.createRecursiveHook(Object.prototype, "initialBufferSize", _this => (client.PacketManager.Encoder = _this,
!0)), Hooker_default.createRecursiveHook(Object.prototype, "maxExtLength", _this => (client.PacketManager.Decoder = _this,
!0));
let patterns = {
"./img/hats/hat_12.png": "https://i.postimg.cc/BQPfhPwD/Booster-V2.png",
"./img/hats/hat_23.png": "https://i.postimg.cc/WpHP6wST/Anti-Venom-Gear.png",
"./img/hats/hat_6.png": "https://i.postimg.cc/662BPP8y/Soldier-Helmet.png",
"./img/hats/hat_15.png": "https://i.postimg.cc/pXKRWnYv/Winter-Cap.png",
"./img/hats/hat_7.png": "https://i.postimg.cc/zGnZNZNG/Bull-Helmet-V2.png",
"./img/hats/hat_58.png": "https://i.postimg.cc/B67RpJTM/Bushido-Armor.png",
"./img/hats/hat_8.png": "https://i.postimg.cc/XJYT9rCr/Bummel-Hat.png",
"./img/hats/hat_5.png": "https://i.postimg.cc/hvJ63NMg/Cowboy-Hat.png",
"./img/hats/hat_50.png": "https://i.postimg.cc/y8h55mhJ/Honeycrisp-Hat.png",
"./img/hats/hat_18.png": "https://i.postimg.cc/RhjyrGbt/Explorer-Hat-V2.png",
"./img/hats/hat_27.png": "https://i.postimg.cc/mkFpSC2g/Scavenger-Gear.png",
"./img/hats/hat_26.png": "https://i.postimg.cc/t40Q8RLc/Barbarian-Armor.png",
"./img/hats/hat_20.png": "https://i.postimg.cc/Dmkjp08d/Samurai-Hat.png",
"./img/hats/hat_22.png": "https://i.postimg.cc/5t3hHB6c/Emp-Helmet.png",
"./img/hats/hat_13.png": "https://i.postimg.cc/BvqyGjNm/Medic-Gear-V2.png",
"./img/hats/hat_9.png": "https://i.postimg.cc/g0N7cGTm/Miner.png",
"./img/hats/hat_4.png": "https://i.postimg.cc/Tw14pBzm/Ranger-Hat.png",
"./img/hats/hat_31.png": "https://i.postimg.cc/2SNM2cWR/Flipper-Hat.png",
"./img/hats/hat_1.png": "https://i.postimg.cc/fWF60TTb/Fiddler-Hat.png",
"./img/hats/hat_11.png": "https://i.postimg.cc/7PFqrNzX/Spike-V2.png",
"./img/hats/hat_11_p.png": "https://i.postimg.cc/7PFqrNzX/Spike-V2.png",
"./img/hats/hat_11_top.png": ""
};
if (Settings_default._texturepack) {
let imageDesc = Object.getOwnPropertyDescriptor(Image.prototype, "src");
Object.defineProperty(Image.prototype, "src", {
get() {
return imageDesc.get?.call(this);
},
set(value) {
if (value in patterns) {
value = patterns[value];
}
if (value === "") {
return;
}
return imageDesc.set?.call(this, value);
},
configurable: !0
});
}
let _proto_ = Object.prototype;
Object.defineProperty(_proto_, "processServers", {
set(value) {
delete _proto_.processServers, this.processServers = function(data) {
for (let server of data) {
server.playerCapacity += 1;
}
return value.call(this, data);
};
},
configurable: !0
});
}, resetGame_default = resetGame;
class DeadPlayer {
moveAngle;
skinColor;
angle;
weapon;
variant;
hatID;
accID;
rotation;
baseTime=2e3;
elapsedTime=0;
pos=new Vector_default;
lerpPos=new Vector_default;
acc=7;
velocity=0;
opacity=1;
shortSign;
constructor(startPos, moveAngle, skin, rotation, weapon, variant, hatID, accID, impulse) {
this.moveAngle = moveAngle, this.skinColor = skin, this.angle = rotation, this.weapon = weapon,
this.variant = variant, this.hatID = hatID, this.accID = accID, this.rotation = rotation,
this.pos.setVec(startPos), this.lerpPos.setVec(startPos), this.shortSign = Math.sign(shortAngle(this.angle, this.moveAngle)),
this.acc = (impulse || 10) / 10 * 75;
}
update(delta) {
this.elapsedTime += delta;
let progress = Math.min(this.elapsedTime / this.baseTime, 1), easedProgress = easeOutQuad(progress);
this.opacity = 1 - easedProgress;
let dt = delta / 1e3, blend = 1 - Math.exp(-10 * dt), PI3 = Math.PI, rotationSpeed = (1 - easedProgress) / PI3 * blend;
this.rotation += rotationSpeed * this.shortSign, this.velocity = this.acc * (1 - easedProgress),
this.pos.add(Vector_default.fromAngle(this.moveAngle, this.velocity * dt)),
this.lerpPos.x = lerp(this.lerpPos.x, this.pos.x, blend), this.lerpPos.y = lerp(this.lerpPos.y, this.pos.y, blend);
}
isFinished() {
return this.elapsedTime >= this.baseTime;
}
}
const DeadPlayerHandler = new class {
deadPlayers=new Set;
start=Date.now();
add(player) {
this.deadPlayers.add(player);
}
update(ctx) {
let now = Date.now(), delta = now - this.start;
this.start = now;
let offset = client.myPlayer.offset;
for (let player of this.deadPlayers) {
if (player.update(delta), ctx.save(), ctx.translate(player.lerpPos.x - offset.x, player.lerpPos.y - offset.y),
ctx.rotate(player.rotation), ctx.globalAlpha = player.opacity, ctx.strokeStyle = "#525252",
Glotus.hooks.renderPlayer({
weaponIndex: player.weapon,
buildIndex: -1,
tailIndex: player.accID,
skinIndex: player.hatID,
weaponVariant: player.variant,
skinColor: player.skinColor,
scale: 35
}, ctx), ctx.restore(), player.isFinished()) {
this.deadPlayers.delete(player);
}
}
}
};
const ObjectRenderer = new class {
healthBar(ctx, entity, object) {
if (!(Settings_default._itemHealthBar && object.seenPlacement && object.isDestroyable)) {
return 0;
}
let {health: health, maxHealth: maxHealth, angle: angle} = object, perc = health / maxHealth, color = Settings_default._itemHealthBarColor;
return Renderer_default.circularBar(ctx, entity, perc, angle, color);
}
renderTurret(ctx, entity, object, scale) {
if (object.type !== 17) {
return;
}
if (Settings_default._objectTurretReloadBar) {
let {reload: reload, maxReload: maxReload, angle: angle} = object, perc = reload / maxReload, color = Settings_default._objectTurretReloadBarColor;
Renderer_default.circularBar(ctx, entity, perc, angle, color, scale);
}
}
renderWindmill(entity) {
if (Items[entity.id].itemType === 5) {
entity.turnSpeed = 0;
}
}
renderCollisions(ctx, entity, object) {
let x = entity.x + entity.xWiggle, y = entity.y + entity.yWiggle;
if (Settings_default._collisionHitbox) {
Renderer_default.circle(ctx, x, y, object.collisionScale, "#c7fff2", .5, 1),
Renderer_default.rect(ctx, new Vector_default(x, y), object.collisionScale, "#ecffbd", 1, .5);
}
if (Settings_default._weaponHitbox) {
Renderer_default.circle(ctx, x, y, object.hitScale, "#3f4ec4", .5, 1);
}
if (Settings_default._placementHitbox) {
Renderer_default.circle(ctx, x, y, object.placementScale, "#73b9ba", .5, 1);
}
let spikeCollider = client.EnemyManager.spikeCollider;
if (spikeCollider === object) {
let scale = spikeCollider.scale * .3;
Renderer_default.fillCircle(ctx, x, y, scale, "#bf3d59", .6);
}
if (object instanceof PlayerObject && object.canBeDestroyed) {
Renderer_default.fillCircle(ctx, x, y, 10, "#f88a41ff", .3);
}
}
render(ctx) {
if (Renderer_default.renderObjects.length === 0) {
return;
}
let {ObjectManager: ObjectManager2, ModuleHandler: ModuleHandler2, myPlayer: myPlayer} = client;
for (let entity of Renderer_default.renderObjects) {
let object = ObjectManager2.objects.get(entity.sid);
if (object === void 0) {
continue;
}
if (Renderer_default.renderMarker(ctx, entity), object instanceof PlayerObject) {
let scale = this.healthBar(ctx, entity, object);
this.renderTurret(ctx, entity, object, scale), this.renderWindmill(entity);
}
this.renderCollisions(ctx, entity, object);
}
Renderer_default.renderObjects.length = 0;
}
volcanoBoxSize=940;
volcanoAggressionRadius=1440;
volcanoBoxPos=new Vector_default(14400, 14400).sub(this.volcanoBoxSize);
volcanoPos=new Vector_default(13960, 13960);
preRender(ctx) {
if (Renderer_default.rect(ctx, this.volcanoBoxPos, this.volcanoBoxSize, "red", 1, .5),
Renderer_default.circle(ctx, this.volcanoPos.x, this.volcanoPos.y, this.volcanoAggressionRadius, "red", 1, .4),
client.myPlayer.diedOnce) {
let {x: x, y: y} = client.myPlayer.deathPosition;
Renderer_default.cross(ctx, x, y, 50, 15, "#cc5151");
}
DeadPlayerHandler.update(ctx);
}
}, ObjectRenderer_default = ObjectRenderer;
const isProd = !0;
const loadedFast = document.head === null;
// HLM : ce mode conditionne TOUT. En injection lente, le bundle
// d'origine a le temps de demarrer et le jeu tourne en double :
// deux widgets Turnstile, deux connexions, et le serveur coupe.
console.log("%c[HLM] injection rapide : " + loadedFast
+ " | document.head deja present : " + (document.head !== null),
loadedFast ? "color:#6f6" : "color:#f66;font-weight:bold");
if (!loadedFast) {
console.error("[HLM] INJECTION LENTE. Dans Tampermonkey : Reglages > General >"
+ " Mode de config = Avance, puis Securite > Content Script API ="
+ " UserScripts API Dynamic, puis Sauvegarder et recharger.");
Logger.warn("Glotus Client loading warning! It is generally recommended to use faster injection mode.");
}
Logger.test("Glotus Client initialization [Glotus Client!]..");
// HLM : plus de jeton altcha fabrique au chargement. Le jeton
// Cloudflare est lu au moment du clic sur Play (voir startGame).
let hlmTurnstileToken = null;
// Point d'extension officiel du jeu : appele des que le jeton arrive.
window.captchaCallbackHook = function() {
let f = document.querySelector('[name="cf-turnstile-response"]');
if (f && f.value) hlmTurnstileToken = f.value;
// Un bot attend peut-etre ce jeton (voir hlmFreshToken).
if (window.__hlmTokenDelivery) window.__hlmTokenDelivery(hlmTurnstileToken);
};
const client = new PlayerClient_default;
// ==================================================================
// HLM - CAPTURE DU SOCKET SANS TOUCHER A window.WebSocket
// moomoo.io a rendu window.WebSocket non modifiable : le Proxy levait
// une TypeError qui interrompait tout le script. Le bundle reecrit
// nous transmet desormais son socket a la creation (crochet
// exposeSocket), c'est-a-dire avant meme le io-init.
// ==================================================================
window.__glotusSocket = function(socket) {
window.__glotusSocket = null;
Logger.test("Found socket! Socket initialization.."), client.SocketManager.init(socket);
};
const win = window, Glotus = {
myClient: client,
settings: Settings_default,
Renderer: Renderer_default,
DataHandler: DataHandler_default,
ZoomHandler: ZoomHandler_default,
hooks: {
EntityRenderer: EntityRenderer_default,
ObjectRenderer: ObjectRenderer_default,
renderPlayer: function() {},
showText: function() {}
},
_getSmoothRendering() {
return Settings_default._smoothRendering;
},
version: "5.3",
hash: "{HASH}",
config: {},
gameInit(token) {},
async startGame() {
// Le jeu attend desormais un jeton de la forme "cf:<jeton>".
// L'ancien prefixe "alt:" n'est plus reconnu par le serveur.
if (hlmTurnstileToken === null) {
let f = document.querySelector('[name="cf-turnstile-response"]');
if (f && f.value) hlmTurnstileToken = f.value;
}
if (hlmTurnstileToken === null) {
Logger.error("Jeton Cloudflare absent : attends la fin de la verification");
return;
}
this.gameInit("cf:" + hlmTurnstileToken);
}
};
win.Glotus = Glotus;
resetGame_default(loadedFast);
const contentLoaded = () => {
Logger.test("Menu initialization.."), client.InputHandler.init(), GameUI_default.init(),
UI_default.init(), StoreHandler_default.init();
};
window.addEventListener("DOMContentLoaded", contentLoaded);
if (document.readyState !== "loading") {
contentLoaded();
}
const onload = () => {
Logger.test("Page loaded..");
let {enterGame: enterGame} = GameUI_default.getElements();
enterGame.classList.remove("disabled");
};
window.addEventListener("load", onload);
if (document.readyState === "complete") {
onload();
}
})();