AlterAle - zombs.io (greasyfork version)

weeb mod de-weeb'd

  1. // ==UserScript==
  2. // @name AlterAle - zombs.io (greasyfork version)
  3. // @namespace http://tampermonkey.net/
  4. // @version -.4.1
  5. // @description weeb mod de-weeb'd
  6. // @author rdm / AyuBloom
  7. // @match zombs.io
  8. // @icon https://cdn.glitch.global/ba7f4151-2a49-416a-985b-56301606ae3d/AlterAle%20Arcaea.webp?v=1717835928442
  9. // @grant none
  10. // @license GNU GPLv3
  11. // ==/UserScript==
  12.  
  13. /* @Dependencies */
  14. /*
  15. bytebuffer.js (c) 2015 Daniel Wirtz <dcode@dcode.io>
  16. Backing buffer: ArrayBuffer, Accessor: Uint8Array
  17. Released under the Apache License, Version 2.0
  18. see: https://github.com/dcodeIO/bytebuffer.js for details
  19. */
  20. (function (h, l) {
  21. if ("function" === typeof define && define.amd) define(["long"], l);
  22. else if ("function" === typeof require && "object" === typeof module && module && module.exports) {
  23. h = module;
  24. try {
  25. var t = require("long");
  26. } catch (v) {}
  27. l = l(t);
  28. h.exports = l;
  29. } else (h.dcodeIO = h.dcodeIO || {}).ByteBuffer = l(h.dcodeIO.Long);
  30. })(this, function (h) {
  31. function l(a) {
  32. var b = 0;
  33. return function () {
  34. return b < a.length ? a.charCodeAt(b++) : null;
  35. };
  36. }
  37. function t() {
  38. var a = [],
  39. b = [];
  40. return function () {
  41. if (0 === arguments.length) return b.join("") + x.apply(String, a);
  42. 1024 < a.length + arguments.length && (b.push(x.apply(String, a)), (a.length = 0));
  43. Array.prototype.push.apply(a, arguments);
  44. };
  45. }
  46. function v(a, b, c, e, k) {
  47. var f = 8 * k - e - 1;
  48. var d = (1 << f) - 1,
  49. g = d >> 1,
  50. n = -7;
  51. k = c ? k - 1 : 0;
  52. var h = c ? -1 : 1,
  53. q = a[b + k];
  54. k += h;
  55. c = q & ((1 << -n) - 1);
  56. q >>= -n;
  57. for (n += f; 0 < n; c = 256 * c + a[b + k], k += h, n -= 8);
  58. f = c & ((1 << -n) - 1);
  59. c >>= -n;
  60. for (n += e; 0 < n; f = 256 * f + a[b + k], k += h, n -= 8);
  61. if (0 === c) c = 1 - g;
  62. else {
  63. if (c === d) return f ? NaN : Infinity * (q ? -1 : 1);
  64. f += Math.pow(2, e);
  65. c -= g;
  66. }
  67. return (q ? -1 : 1) * f * Math.pow(2, c - e);
  68. }
  69. function y(a, b, c, e, k, f) {
  70. var d,
  71. g = 8 * f - k - 1,
  72. n = (1 << g) - 1,
  73. h = n >> 1,
  74. q = 23 === k ? Math.pow(2, -24) - Math.pow(2, -77) : 0;
  75. f = e ? 0 : f - 1;
  76. var l = e ? 1 : -1,
  77. m = 0 > b || (0 === b && 0 > 1 / b) ? 1 : 0;
  78. b = Math.abs(b);
  79. isNaN(b) || Infinity === b
  80. ? ((b = isNaN(b) ? 1 : 0), (e = n))
  81. : ((e = Math.floor(Math.log(b) / Math.LN2)),
  82. 1 > b * (d = Math.pow(2, -e)) && (e--, (d *= 2)),
  83. (b = 1 <= e + h ? b + q / d : b + q * Math.pow(2, 1 - h)),
  84. 2 <= b * d && (e++, (d /= 2)),
  85. e + h >= n ? ((b = 0), (e = n)) : 1 <= e + h ? ((b = (b * d - 1) * Math.pow(2, k)), (e += h)) : ((b = b * Math.pow(2, h - 1) * Math.pow(2, k)), (e = 0)));
  86. for (; 8 <= k; a[c + f] = b & 255, f += l, b /= 256, k -= 8);
  87. e = (e << k) | b;
  88. for (g += k; 0 < g; a[c + f] = e & 255, f += l, e /= 256, g -= 8);
  89. a[c + f - l] |= 128 * m;
  90. }
  91. var g = function (a, b, c) {
  92. "undefined" === typeof a && (a = g.DEFAULT_CAPACITY);
  93. "undefined" === typeof b && (b = g.DEFAULT_ENDIAN);
  94. "undefined" === typeof c && (c = g.DEFAULT_NOASSERT);
  95. if (!c) {
  96. a |= 0;
  97. if (0 > a) throw RangeError("Illegal capacity");
  98. b = !!b;
  99. c = !!c;
  100. }
  101. this.buffer = 0 === a ? w : new ArrayBuffer(a);
  102. this.view = 0 === a ? null : new Uint8Array(this.buffer);
  103. this.offset = 0;
  104. this.markedOffset = -1;
  105. this.limit = a;
  106. this.littleEndian = b;
  107. this.noAssert = c;
  108. };
  109. g.VERSION = "5.0.1";
  110. g.LITTLE_ENDIAN = !0;
  111. g.BIG_ENDIAN = !1;
  112. g.DEFAULT_CAPACITY = 16;
  113. g.DEFAULT_ENDIAN = g.BIG_ENDIAN;
  114. g.DEFAULT_NOASSERT = !1;
  115. g.Long = h || null;
  116. var d = g.prototype;
  117. Object.defineProperty(d, "__isByteBuffer__", { value: !0, enumerable: !1, configurable: !1 });
  118. var w = new ArrayBuffer(0),
  119. x = String.fromCharCode;
  120. g.accessor = function () {
  121. return Uint8Array;
  122. };
  123. g.allocate = function (a, b, c) {
  124. return new g(a, b, c);
  125. };
  126. g.concat = function (a, b, c, e) {
  127. if ("boolean" === typeof b || "string" !== typeof b) (e = c), (c = b), (b = void 0);
  128. for (var k = 0, f = 0, d = a.length, u; f < d; ++f) g.isByteBuffer(a[f]) || (a[f] = g.wrap(a[f], b)), (u = a[f].limit - a[f].offset), 0 < u && (k += u);
  129. if (0 === k) return new g(0, c, e);
  130. b = new g(k, c, e);
  131. for (f = 0; f < d; ) (c = a[f++]), (u = c.limit - c.offset), 0 >= u || (b.view.set(c.view.subarray(c.offset, c.limit), b.offset), (b.offset += u));
  132. b.limit = b.offset;
  133. b.offset = 0;
  134. return b;
  135. };
  136. g.isByteBuffer = function (a) {
  137. return !0 === (a && a.__isByteBuffer__);
  138. };
  139. g.type = function () {
  140. return ArrayBuffer;
  141. };
  142. g.wrap = function (a, b, c, e) {
  143. "string" !== typeof b && ((e = c), (c = b), (b = void 0));
  144. if ("string" === typeof a)
  145. switch (("undefined" === typeof b && (b = "utf8"), b)) {
  146. case "base64":
  147. return g.fromBase64(a, c);
  148. case "hex":
  149. return g.fromHex(a, c);
  150. case "binary":
  151. return g.fromBinary(a, c);
  152. case "utf8":
  153. return g.fromUTF8(a, c);
  154. case "debug":
  155. return g.fromDebug(a, c);
  156. default:
  157. throw Error("Unsupported encoding: " + b);
  158. }
  159. if (null === a || "object" !== typeof a) throw TypeError("Illegal buffer");
  160. if (g.isByteBuffer(a)) return (b = d.clone.call(a)), (b.markedOffset = -1), b;
  161. if (a instanceof Uint8Array) (b = new g(0, c, e)), 0 < a.length && ((b.buffer = a.buffer), (b.offset = a.byteOffset), (b.limit = a.byteOffset + a.byteLength), (b.view = new Uint8Array(a.buffer)));
  162. else if (a instanceof ArrayBuffer) (b = new g(0, c, e)), 0 < a.byteLength && ((b.buffer = a), (b.offset = 0), (b.limit = a.byteLength), (b.view = 0 < a.byteLength ? new Uint8Array(a) : null));
  163. else if ("[object Array]" === Object.prototype.toString.call(a)) for (b = new g(a.length, c, e), b.limit = a.length, c = 0; c < a.length; ++c) b.view[c] = a[c];
  164. else throw TypeError("Illegal buffer");
  165. return b;
  166. };
  167. d.writeBitSet = function (a, b) {
  168. var c = "undefined" === typeof b;
  169. c && (b = this.offset);
  170. if (!this.noAssert) {
  171. if (!(a instanceof Array)) throw TypeError("Illegal BitSet: Not an array");
  172. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  173. b >>>= 0;
  174. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  175. }
  176. var e = b,
  177. k = a.length,
  178. f = k >> 3,
  179. d = 0;
  180. for (b += this.writeVarint32(k, b); f--; ) {
  181. var g = (!!a[d++] & 1) | ((!!a[d++] & 1) << 1) | ((!!a[d++] & 1) << 2) | ((!!a[d++] & 1) << 3) | ((!!a[d++] & 1) << 4) | ((!!a[d++] & 1) << 5) | ((!!a[d++] & 1) << 6) | ((!!a[d++] & 1) << 7);
  182. this.writeByte(g, b++);
  183. }
  184. if (d < k) {
  185. for (g = f = 0; d < k; ) g |= (!!a[d++] & 1) << f++;
  186. this.writeByte(g, b++);
  187. }
  188. return c ? ((this.offset = b), this) : b - e;
  189. };
  190. d.readBitSet = function (a) {
  191. var b = "undefined" === typeof a;
  192. b && (a = this.offset);
  193. var c = this.readVarint32(a),
  194. e = c.value,
  195. k = e >> 3,
  196. f = 0,
  197. d = [];
  198. for (a += c.length; k--; )
  199. (c = this.readByte(a++)), (d[f++] = !!(c & 1)), (d[f++] = !!(c & 2)), (d[f++] = !!(c & 4)), (d[f++] = !!(c & 8)), (d[f++] = !!(c & 16)), (d[f++] = !!(c & 32)), (d[f++] = !!(c & 64)), (d[f++] = !!(c & 128));
  200. if (f < e) for (k = 0, c = this.readByte(a++); f < e; ) d[f++] = !!((c >> k++) & 1);
  201. b && (this.offset = a);
  202. return d;
  203. };
  204. d.readBytes = function (a, b) {
  205. var c = "undefined" === typeof b;
  206. c && (b = this.offset);
  207. if (!this.noAssert) {
  208. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  209. b >>>= 0;
  210. if (0 > b || b + a > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+" + a + ") <= " + this.buffer.byteLength);
  211. }
  212. b = this.slice(b, b + a);
  213. c && (this.offset += a);
  214. return b;
  215. };
  216. d.writeInt8 = function (a, b) {
  217. var c = "undefined" === typeof b;
  218. c && (b = this.offset);
  219. if (!this.noAssert) {
  220. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal value: " + a + " (not an integer)");
  221. a |= 0;
  222. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  223. b >>>= 0;
  224. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  225. }
  226. b += 1;
  227. var e = this.buffer.byteLength;
  228. b > e && this.resize((e *= 2) > b ? e : b);
  229. this.view[b - 1] = a;
  230. c && (this.offset += 1);
  231. return this;
  232. };
  233. d.writeByte = d.writeInt8;
  234. d.readInt8 = function (a) {
  235. var b = "undefined" === typeof a;
  236. b && (a = this.offset);
  237. if (!this.noAssert) {
  238. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  239. a >>>= 0;
  240. if (0 > a || a + 1 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+1) <= " + this.buffer.byteLength);
  241. }
  242. a = this.view[a];
  243. 128 === (a & 128) && (a = -(255 - a + 1));
  244. b && (this.offset += 1);
  245. return a;
  246. };
  247. d.readByte = d.readInt8;
  248. d.writeUint8 = function (a, b) {
  249. var c = "undefined" === typeof b;
  250. c && (b = this.offset);
  251. if (!this.noAssert) {
  252. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal value: " + a + " (not an integer)");
  253. a >>>= 0;
  254. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  255. b >>>= 0;
  256. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  257. }
  258. b += 1;
  259. var e = this.buffer.byteLength;
  260. b > e && this.resize((e *= 2) > b ? e : b);
  261. this.view[b - 1] = a;
  262. c && (this.offset += 1);
  263. return this;
  264. };
  265. d.writeUInt8 = d.writeUint8;
  266. d.readUint8 = function (a) {
  267. var b = "undefined" === typeof a;
  268. b && (a = this.offset);
  269. if (!this.noAssert) {
  270. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  271. a >>>= 0;
  272. if (0 > a || a + 1 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+1) <= " + this.buffer.byteLength);
  273. }
  274. a = this.view[a];
  275. b && (this.offset += 1);
  276. return a;
  277. };
  278. d.readUInt8 = d.readUint8;
  279. d.writeInt16 = function (a, b) {
  280. var c = "undefined" === typeof b;
  281. c && (b = this.offset);
  282. if (!this.noAssert) {
  283. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal value: " + a + " (not an integer)");
  284. a |= 0;
  285. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  286. b >>>= 0;
  287. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  288. }
  289. b += 2;
  290. var e = this.buffer.byteLength;
  291. b > e && this.resize((e *= 2) > b ? e : b);
  292. b -= 2;
  293. this.littleEndian ? ((this.view[b + 1] = (a & 65280) >>> 8), (this.view[b] = a & 255)) : ((this.view[b] = (a & 65280) >>> 8), (this.view[b + 1] = a & 255));
  294. c && (this.offset += 2);
  295. return this;
  296. };
  297. d.writeShort = d.writeInt16;
  298. d.readInt16 = function (a) {
  299. var b = "undefined" === typeof a;
  300. b && (a = this.offset);
  301. if (!this.noAssert) {
  302. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  303. a >>>= 0;
  304. if (0 > a || a + 2 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+2) <= " + this.buffer.byteLength);
  305. }
  306. if (this.littleEndian) {
  307. var c = this.view[a];
  308. c |= this.view[a + 1] << 8;
  309. } else (c = this.view[a] << 8), (c |= this.view[a + 1]);
  310. 32768 === (c & 32768) && (c = -(65535 - c + 1));
  311. b && (this.offset += 2);
  312. return c;
  313. };
  314. d.readShort = d.readInt16;
  315. d.writeUint16 = function (a, b) {
  316. var c = "undefined" === typeof b;
  317. c && (b = this.offset);
  318. if (!this.noAssert) {
  319. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal value: " + a + " (not an integer)");
  320. a >>>= 0;
  321. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  322. b >>>= 0;
  323. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  324. }
  325. b += 2;
  326. var e = this.buffer.byteLength;
  327. b > e && this.resize((e *= 2) > b ? e : b);
  328. b -= 2;
  329. this.littleEndian ? ((this.view[b + 1] = (a & 65280) >>> 8), (this.view[b] = a & 255)) : ((this.view[b] = (a & 65280) >>> 8), (this.view[b + 1] = a & 255));
  330. c && (this.offset += 2);
  331. return this;
  332. };
  333. d.writeUInt16 = d.writeUint16;
  334. d.readUint16 = function (a) {
  335. var b = "undefined" === typeof a;
  336. b && (a = this.offset);
  337. if (!this.noAssert) {
  338. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  339. a >>>= 0;
  340. if (0 > a || a + 2 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+2) <= " + this.buffer.byteLength);
  341. }
  342. if (this.littleEndian) {
  343. var c = this.view[a];
  344. c |= this.view[a + 1] << 8;
  345. } else (c = this.view[a] << 8), (c |= this.view[a + 1]);
  346. b && (this.offset += 2);
  347. return c;
  348. };
  349. d.readUInt16 = d.readUint16;
  350. d.writeInt32 = function (a, b) {
  351. var c = "undefined" === typeof b;
  352. c && (b = this.offset);
  353. if (!this.noAssert) {
  354. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal value: " + a + " (not an integer)");
  355. a |= 0;
  356. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  357. b >>>= 0;
  358. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  359. }
  360. b += 4;
  361. var e = this.buffer.byteLength;
  362. b > e && this.resize((e *= 2) > b ? e : b);
  363. b -= 4;
  364. this.littleEndian
  365. ? ((this.view[b + 3] = (a >>> 24) & 255), (this.view[b + 2] = (a >>> 16) & 255), (this.view[b + 1] = (a >>> 8) & 255), (this.view[b] = a & 255))
  366. : ((this.view[b] = (a >>> 24) & 255), (this.view[b + 1] = (a >>> 16) & 255), (this.view[b + 2] = (a >>> 8) & 255), (this.view[b + 3] = a & 255));
  367. c && (this.offset += 4);
  368. return this;
  369. };
  370. d.writeInt = d.writeInt32;
  371. d.readInt32 = function (a) {
  372. var b = "undefined" === typeof a;
  373. b && (a = this.offset);
  374. if (!this.noAssert) {
  375. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  376. a >>>= 0;
  377. if (0 > a || a + 4 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+4) <= " + this.buffer.byteLength);
  378. }
  379. if (this.littleEndian) {
  380. var c = this.view[a + 2] << 16;
  381. c |= this.view[a + 1] << 8;
  382. c |= this.view[a];
  383. c += (this.view[a + 3] << 24) >>> 0;
  384. } else (c = this.view[a + 1] << 16), (c |= this.view[a + 2] << 8), (c |= this.view[a + 3]), (c += (this.view[a] << 24) >>> 0);
  385. b && (this.offset += 4);
  386. return c | 0;
  387. };
  388. d.readInt = d.readInt32;
  389. d.writeUint32 = function (a, b) {
  390. var c = "undefined" === typeof b;
  391. c && (b = this.offset);
  392. if (!this.noAssert) {
  393. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal value: " + a + " (not an integer)");
  394. a >>>= 0;
  395. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  396. b >>>= 0;
  397. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  398. }
  399. b += 4;
  400. var e = this.buffer.byteLength;
  401. b > e && this.resize((e *= 2) > b ? e : b);
  402. b -= 4;
  403. this.littleEndian
  404. ? ((this.view[b + 3] = (a >>> 24) & 255), (this.view[b + 2] = (a >>> 16) & 255), (this.view[b + 1] = (a >>> 8) & 255), (this.view[b] = a & 255))
  405. : ((this.view[b] = (a >>> 24) & 255), (this.view[b + 1] = (a >>> 16) & 255), (this.view[b + 2] = (a >>> 8) & 255), (this.view[b + 3] = a & 255));
  406. c && (this.offset += 4);
  407. return this;
  408. };
  409. d.writeUInt32 = d.writeUint32;
  410. d.readUint32 = function (a) {
  411. var b = "undefined" === typeof a;
  412. b && (a = this.offset);
  413. if (!this.noAssert) {
  414. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  415. a >>>= 0;
  416. if (0 > a || a + 4 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+4) <= " + this.buffer.byteLength);
  417. }
  418. if (this.littleEndian) {
  419. var c = this.view[a + 2] << 16;
  420. c |= this.view[a + 1] << 8;
  421. c |= this.view[a];
  422. c += (this.view[a + 3] << 24) >>> 0;
  423. } else (c = this.view[a + 1] << 16), (c |= this.view[a + 2] << 8), (c |= this.view[a + 3]), (c += (this.view[a] << 24) >>> 0);
  424. b && (this.offset += 4);
  425. return c;
  426. };
  427. d.readUInt32 = d.readUint32;
  428. h &&
  429. ((d.writeInt64 = function (a, b) {
  430. var c = "undefined" === typeof b;
  431. c && (b = this.offset);
  432. if (!this.noAssert) {
  433. if ("number" === typeof a) a = h.fromNumber(a);
  434. else if ("string" === typeof a) a = h.fromString(a);
  435. else if (!(a && a instanceof h)) throw TypeError("Illegal value: " + a + " (not an integer or Long)");
  436. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  437. b >>>= 0;
  438. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  439. }
  440. "number" === typeof a ? (a = h.fromNumber(a)) : "string" === typeof a && (a = h.fromString(a));
  441. b += 8;
  442. var e = this.buffer.byteLength;
  443. b > e && this.resize((e *= 2) > b ? e : b);
  444. b -= 8;
  445. e = a.low;
  446. a = a.high;
  447. this.littleEndian
  448. ? ((this.view[b + 3] = (e >>> 24) & 255),
  449. (this.view[b + 2] = (e >>> 16) & 255),
  450. (this.view[b + 1] = (e >>> 8) & 255),
  451. (this.view[b] = e & 255),
  452. (b += 4),
  453. (this.view[b + 3] = (a >>> 24) & 255),
  454. (this.view[b + 2] = (a >>> 16) & 255),
  455. (this.view[b + 1] = (a >>> 8) & 255),
  456. (this.view[b] = a & 255))
  457. : ((this.view[b] = (a >>> 24) & 255),
  458. (this.view[b + 1] = (a >>> 16) & 255),
  459. (this.view[b + 2] = (a >>> 8) & 255),
  460. (this.view[b + 3] = a & 255),
  461. (b += 4),
  462. (this.view[b] = (e >>> 24) & 255),
  463. (this.view[b + 1] = (e >>> 16) & 255),
  464. (this.view[b + 2] = (e >>> 8) & 255),
  465. (this.view[b + 3] = e & 255));
  466. c && (this.offset += 8);
  467. return this;
  468. }),
  469. (d.writeLong = d.writeInt64),
  470. (d.readInt64 = function (a) {
  471. var b = "undefined" === typeof a;
  472. b && (a = this.offset);
  473. if (!this.noAssert) {
  474. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  475. a >>>= 0;
  476. if (0 > a || a + 8 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+8) <= " + this.buffer.byteLength);
  477. }
  478. if (this.littleEndian) {
  479. var c = this.view[a + 2] << 16;
  480. c |= this.view[a + 1] << 8;
  481. c |= this.view[a];
  482. c += (this.view[a + 3] << 24) >>> 0;
  483. a += 4;
  484. var e = this.view[a + 2] << 16;
  485. e |= this.view[a + 1] << 8;
  486. e |= this.view[a];
  487. e += (this.view[a + 3] << 24) >>> 0;
  488. } else
  489. (e = this.view[a + 1] << 16),
  490. (e |= this.view[a + 2] << 8),
  491. (e |= this.view[a + 3]),
  492. (e += (this.view[a] << 24) >>> 0),
  493. (a += 4),
  494. (c = this.view[a + 1] << 16),
  495. (c |= this.view[a + 2] << 8),
  496. (c |= this.view[a + 3]),
  497. (c += (this.view[a] << 24) >>> 0);
  498. a = new h(c, e, !1);
  499. b && (this.offset += 8);
  500. return a;
  501. }),
  502. (d.readLong = d.readInt64),
  503. (d.writeUint64 = function (a, b) {
  504. var c = "undefined" === typeof b;
  505. c && (b = this.offset);
  506. if (!this.noAssert) {
  507. if ("number" === typeof a) a = h.fromNumber(a);
  508. else if ("string" === typeof a) a = h.fromString(a);
  509. else if (!(a && a instanceof h)) throw TypeError("Illegal value: " + a + " (not an integer or Long)");
  510. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  511. b >>>= 0;
  512. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  513. }
  514. "number" === typeof a ? (a = h.fromNumber(a)) : "string" === typeof a && (a = h.fromString(a));
  515. b += 8;
  516. var e = this.buffer.byteLength;
  517. b > e && this.resize((e *= 2) > b ? e : b);
  518. b -= 8;
  519. e = a.low;
  520. a = a.high;
  521. this.littleEndian
  522. ? ((this.view[b + 3] = (e >>> 24) & 255),
  523. (this.view[b + 2] = (e >>> 16) & 255),
  524. (this.view[b + 1] = (e >>> 8) & 255),
  525. (this.view[b] = e & 255),
  526. (b += 4),
  527. (this.view[b + 3] = (a >>> 24) & 255),
  528. (this.view[b + 2] = (a >>> 16) & 255),
  529. (this.view[b + 1] = (a >>> 8) & 255),
  530. (this.view[b] = a & 255))
  531. : ((this.view[b] = (a >>> 24) & 255),
  532. (this.view[b + 1] = (a >>> 16) & 255),
  533. (this.view[b + 2] = (a >>> 8) & 255),
  534. (this.view[b + 3] = a & 255),
  535. (b += 4),
  536. (this.view[b] = (e >>> 24) & 255),
  537. (this.view[b + 1] = (e >>> 16) & 255),
  538. (this.view[b + 2] = (e >>> 8) & 255),
  539. (this.view[b + 3] = e & 255));
  540. c && (this.offset += 8);
  541. return this;
  542. }),
  543. (d.writeUInt64 = d.writeUint64),
  544. (d.readUint64 = function (a) {
  545. var b = "undefined" === typeof a;
  546. b && (a = this.offset);
  547. if (!this.noAssert) {
  548. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  549. a >>>= 0;
  550. if (0 > a || a + 8 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+8) <= " + this.buffer.byteLength);
  551. }
  552. if (this.littleEndian) {
  553. var c = this.view[a + 2] << 16;
  554. c |= this.view[a + 1] << 8;
  555. c |= this.view[a];
  556. c += (this.view[a + 3] << 24) >>> 0;
  557. a += 4;
  558. var e = this.view[a + 2] << 16;
  559. e |= this.view[a + 1] << 8;
  560. e |= this.view[a];
  561. e += (this.view[a + 3] << 24) >>> 0;
  562. } else
  563. (e = this.view[a + 1] << 16),
  564. (e |= this.view[a + 2] << 8),
  565. (e |= this.view[a + 3]),
  566. (e += (this.view[a] << 24) >>> 0),
  567. (a += 4),
  568. (c = this.view[a + 1] << 16),
  569. (c |= this.view[a + 2] << 8),
  570. (c |= this.view[a + 3]),
  571. (c += (this.view[a] << 24) >>> 0);
  572. a = new h(c, e, !0);
  573. b && (this.offset += 8);
  574. return a;
  575. }),
  576. (d.readUInt64 = d.readUint64));
  577. d.writeFloat32 = function (a, b) {
  578. var c = "undefined" === typeof b;
  579. c && (b = this.offset);
  580. if (!this.noAssert) {
  581. if ("number" !== typeof a) throw TypeError("Illegal value: " + a + " (not a number)");
  582. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  583. b >>>= 0;
  584. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  585. }
  586. b += 4;
  587. var e = this.buffer.byteLength;
  588. b > e && this.resize((e *= 2) > b ? e : b);
  589. y(this.view, a, b - 4, this.littleEndian, 23, 4);
  590. c && (this.offset += 4);
  591. return this;
  592. };
  593. d.writeFloat = d.writeFloat32;
  594. d.readFloat32 = function (a) {
  595. var b = "undefined" === typeof a;
  596. b && (a = this.offset);
  597. if (!this.noAssert) {
  598. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  599. a >>>= 0;
  600. if (0 > a || a + 4 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+4) <= " + this.buffer.byteLength);
  601. }
  602. a = v(this.view, a, this.littleEndian, 23, 4);
  603. b && (this.offset += 4);
  604. return a;
  605. };
  606. d.readFloat = d.readFloat32;
  607. d.writeFloat64 = function (a, b) {
  608. var c = "undefined" === typeof b;
  609. c && (b = this.offset);
  610. if (!this.noAssert) {
  611. if ("number" !== typeof a) throw TypeError("Illegal value: " + a + " (not a number)");
  612. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  613. b >>>= 0;
  614. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  615. }
  616. b += 8;
  617. var e = this.buffer.byteLength;
  618. b > e && this.resize((e *= 2) > b ? e : b);
  619. y(this.view, a, b - 8, this.littleEndian, 52, 8);
  620. c && (this.offset += 8);
  621. return this;
  622. };
  623. d.writeDouble = d.writeFloat64;
  624. d.readFloat64 = function (a) {
  625. var b = "undefined" === typeof a;
  626. b && (a = this.offset);
  627. if (!this.noAssert) {
  628. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  629. a >>>= 0;
  630. if (0 > a || a + 8 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+8) <= " + this.buffer.byteLength);
  631. }
  632. a = v(this.view, a, this.littleEndian, 52, 8);
  633. b && (this.offset += 8);
  634. return a;
  635. };
  636. d.readDouble = d.readFloat64;
  637. g.MAX_VARINT32_BYTES = 5;
  638. g.calculateVarint32 = function (a) {
  639. a >>>= 0;
  640. return 128 > a ? 1 : 16384 > a ? 2 : 2097152 > a ? 3 : 268435456 > a ? 4 : 5;
  641. };
  642. g.zigZagEncode32 = function (a) {
  643. return (((a |= 0) << 1) ^ (a >> 31)) >>> 0;
  644. };
  645. g.zigZagDecode32 = function (a) {
  646. return ((a >>> 1) ^ -(a & 1)) | 0;
  647. };
  648. d.writeVarint32 = function (a, b) {
  649. var c = "undefined" === typeof b;
  650. c && (b = this.offset);
  651. if (!this.noAssert) {
  652. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal value: " + a + " (not an integer)");
  653. a |= 0;
  654. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  655. b >>>= 0;
  656. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  657. }
  658. var e = g.calculateVarint32(a);
  659. b += e;
  660. var k = this.buffer.byteLength;
  661. b > k && this.resize((k *= 2) > b ? k : b);
  662. b -= e;
  663. for (a >>>= 0; 128 <= a; ) (k = (a & 127) | 128), (this.view[b++] = k), (a >>>= 7);
  664. this.view[b++] = a;
  665. return c ? ((this.offset = b), this) : e;
  666. };
  667. d.writeVarint32ZigZag = function (a, b) {
  668. return this.writeVarint32(g.zigZagEncode32(a), b);
  669. };
  670. d.readVarint32 = function (a) {
  671. var b = "undefined" === typeof a;
  672. b && (a = this.offset);
  673. if (!this.noAssert) {
  674. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  675. a >>>= 0;
  676. if (0 > a || a + 1 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+1) <= " + this.buffer.byteLength);
  677. }
  678. var c = 0,
  679. e = 0;
  680. do {
  681. if (!this.noAssert && a > this.limit) throw ((a = Error("Truncated")), (a.truncated = !0), a);
  682. var k = this.view[a++];
  683. 5 > c && (e |= (k & 127) << (7 * c));
  684. ++c;
  685. } while (0 !== (k & 128));
  686. e |= 0;
  687. return b ? ((this.offset = a), e) : { value: e, length: c };
  688. };
  689. d.readVarint32ZigZag = function (a) {
  690. a = this.readVarint32(a);
  691. "object" === typeof a ? (a.value = g.zigZagDecode32(a.value)) : (a = g.zigZagDecode32(a));
  692. return a;
  693. };
  694. h &&
  695. ((g.MAX_VARINT64_BYTES = 10),
  696. (g.calculateVarint64 = function (a) {
  697. "number" === typeof a ? (a = h.fromNumber(a)) : "string" === typeof a && (a = h.fromString(a));
  698. var b = a.toInt() >>> 0,
  699. c = a.shiftRightUnsigned(28).toInt() >>> 0;
  700. a = a.shiftRightUnsigned(56).toInt() >>> 0;
  701. return 0 == a ? (0 == c ? (16384 > b ? (128 > b ? 1 : 2) : 2097152 > b ? 3 : 4) : 16384 > c ? (128 > c ? 5 : 6) : 2097152 > c ? 7 : 8) : 128 > a ? 9 : 10;
  702. }),
  703. (g.zigZagEncode64 = function (a) {
  704. "number" === typeof a ? (a = h.fromNumber(a, !1)) : "string" === typeof a ? (a = h.fromString(a, !1)) : !1 !== a.unsigned && (a = a.toSigned());
  705. return a.shiftLeft(1).xor(a.shiftRight(63)).toUnsigned();
  706. }),
  707. (g.zigZagDecode64 = function (a) {
  708. "number" === typeof a ? (a = h.fromNumber(a, !1)) : "string" === typeof a ? (a = h.fromString(a, !1)) : !1 !== a.unsigned && (a = a.toSigned());
  709. return a.shiftRightUnsigned(1).xor(a.and(h.ONE).toSigned().negate()).toSigned();
  710. }),
  711. (d.writeVarint64 = function (a, b) {
  712. var c = "undefined" === typeof b;
  713. c && (b = this.offset);
  714. if (!this.noAssert) {
  715. if ("number" === typeof a) a = h.fromNumber(a);
  716. else if ("string" === typeof a) a = h.fromString(a);
  717. else if (!(a && a instanceof h)) throw TypeError("Illegal value: " + a + " (not an integer or Long)");
  718. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  719. b >>>= 0;
  720. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  721. }
  722. "number" === typeof a ? (a = h.fromNumber(a, !1)) : "string" === typeof a ? (a = h.fromString(a, !1)) : !1 !== a.unsigned && (a = a.toSigned());
  723. var e = g.calculateVarint64(a),
  724. k = a.toInt() >>> 0,
  725. f = a.shiftRightUnsigned(28).toInt() >>> 0;
  726. a = a.shiftRightUnsigned(56).toInt() >>> 0;
  727. b += e;
  728. var d = this.buffer.byteLength;
  729. b > d && this.resize((d *= 2) > b ? d : b);
  730. b -= e;
  731. switch (e) {
  732. case 10:
  733. this.view[b + 9] = (a >>> 7) & 1;
  734. case 9:
  735. this.view[b + 8] = 9 !== e ? a | 128 : a & 127;
  736. case 8:
  737. this.view[b + 7] = 8 !== e ? (f >>> 21) | 128 : (f >>> 21) & 127;
  738. case 7:
  739. this.view[b + 6] = 7 !== e ? (f >>> 14) | 128 : (f >>> 14) & 127;
  740. case 6:
  741. this.view[b + 5] = 6 !== e ? (f >>> 7) | 128 : (f >>> 7) & 127;
  742. case 5:
  743. this.view[b + 4] = 5 !== e ? f | 128 : f & 127;
  744. case 4:
  745. this.view[b + 3] = 4 !== e ? (k >>> 21) | 128 : (k >>> 21) & 127;
  746. case 3:
  747. this.view[b + 2] = 3 !== e ? (k >>> 14) | 128 : (k >>> 14) & 127;
  748. case 2:
  749. this.view[b + 1] = 2 !== e ? (k >>> 7) | 128 : (k >>> 7) & 127;
  750. case 1:
  751. this.view[b] = 1 !== e ? k | 128 : k & 127;
  752. }
  753. return c ? ((this.offset += e), this) : e;
  754. }),
  755. (d.writeVarint64ZigZag = function (a, b) {
  756. return this.writeVarint64(g.zigZagEncode64(a), b);
  757. }),
  758. (d.readVarint64 = function (a) {
  759. var b = "undefined" === typeof a;
  760. b && (a = this.offset);
  761. if (!this.noAssert) {
  762. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  763. a >>>= 0;
  764. if (0 > a || a + 1 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+1) <= " + this.buffer.byteLength);
  765. }
  766. var c = a,
  767. e = 0,
  768. k = 0;
  769. var d = this.view[a++];
  770. var g = d & 127;
  771. if (
  772. d & 128 &&
  773. ((d = this.view[a++]), (g |= (d & 127) << 7), d & 128 || (this.noAssert && "undefined" === typeof d)) &&
  774. ((d = this.view[a++]), (g |= (d & 127) << 14), d & 128 || (this.noAssert && "undefined" === typeof d)) &&
  775. ((d = this.view[a++]), (g |= (d & 127) << 21), d & 128 || (this.noAssert && "undefined" === typeof d)) &&
  776. ((d = this.view[a++]), (e = d & 127), d & 128 || (this.noAssert && "undefined" === typeof d)) &&
  777. ((d = this.view[a++]), (e |= (d & 127) << 7), d & 128 || (this.noAssert && "undefined" === typeof d)) &&
  778. ((d = this.view[a++]), (e |= (d & 127) << 14), d & 128 || (this.noAssert && "undefined" === typeof d)) &&
  779. ((d = this.view[a++]), (e |= (d & 127) << 21), d & 128 || (this.noAssert && "undefined" === typeof d)) &&
  780. ((d = this.view[a++]), (k = d & 127), d & 128 || (this.noAssert && "undefined" === typeof d)) &&
  781. ((d = this.view[a++]), (k |= (d & 127) << 7), d & 128 || (this.noAssert && "undefined" === typeof d))
  782. )
  783. throw Error("Buffer overrun");
  784. g = h.fromBits(g | (e << 28), (e >>> 4) | (k << 24), !1);
  785. return b ? ((this.offset = a), g) : { value: g, length: a - c };
  786. }),
  787. (d.readVarint64ZigZag = function (a) {
  788. (a = this.readVarint64(a)) && a.value instanceof h ? (a.value = g.zigZagDecode64(a.value)) : (a = g.zigZagDecode64(a));
  789. return a;
  790. }));
  791. d.writeCString = function (a, b) {
  792. var c = "undefined" === typeof b;
  793. c && (b = this.offset);
  794. var e,
  795. d = a.length;
  796. if (!this.noAssert) {
  797. if ("string" !== typeof a) throw TypeError("Illegal str: Not a string");
  798. for (e = 0; e < d; ++e) if (0 === a.charCodeAt(e)) throw RangeError("Illegal str: Contains NULL-characters");
  799. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  800. b >>>= 0;
  801. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  802. }
  803. d = m.calculateUTF16asUTF8(l(a))[1];
  804. b += d + 1;
  805. e = this.buffer.byteLength;
  806. b > e && this.resize((e *= 2) > b ? e : b);
  807. b -= d + 1;
  808. m.encodeUTF16toUTF8(
  809. l(a),
  810. function (a) {
  811. this.view[b++] = a;
  812. }.bind(this)
  813. );
  814. this.view[b++] = 0;
  815. return c ? ((this.offset = b), this) : d;
  816. };
  817. d.readCString = function (a) {
  818. var b = "undefined" === typeof a;
  819. b && (a = this.offset);
  820. if (!this.noAssert) {
  821. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  822. a >>>= 0;
  823. if (0 > a || a + 1 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+1) <= " + this.buffer.byteLength);
  824. }
  825. var c = a,
  826. e,
  827. d = -1;
  828. m.decodeUTF8toUTF16(
  829. function () {
  830. if (0 === d) return null;
  831. if (a >= this.limit) throw RangeError("Illegal range: Truncated data, " + a + " < " + this.limit);
  832. d = this.view[a++];
  833. return 0 === d ? null : d;
  834. }.bind(this),
  835. (e = t()),
  836. !0
  837. );
  838. return b ? ((this.offset = a), e()) : { string: e(), length: a - c };
  839. };
  840. d.writeIString = function (a, b) {
  841. var c = "undefined" === typeof b;
  842. c && (b = this.offset);
  843. if (!this.noAssert) {
  844. if ("string" !== typeof a) throw TypeError("Illegal str: Not a string");
  845. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  846. b >>>= 0;
  847. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  848. }
  849. var e = b;
  850. var d = m.calculateUTF16asUTF8(l(a), this.noAssert)[1];
  851. b += 4 + d;
  852. var f = this.buffer.byteLength;
  853. b > f && this.resize((f *= 2) > b ? f : b);
  854. b -= 4 + d;
  855. this.littleEndian
  856. ? ((this.view[b + 3] = (d >>> 24) & 255), (this.view[b + 2] = (d >>> 16) & 255), (this.view[b + 1] = (d >>> 8) & 255), (this.view[b] = d & 255))
  857. : ((this.view[b] = (d >>> 24) & 255), (this.view[b + 1] = (d >>> 16) & 255), (this.view[b + 2] = (d >>> 8) & 255), (this.view[b + 3] = d & 255));
  858. b += 4;
  859. m.encodeUTF16toUTF8(
  860. l(a),
  861. function (a) {
  862. this.view[b++] = a;
  863. }.bind(this)
  864. );
  865. if (b !== e + 4 + d) throw RangeError("Illegal range: Truncated data, " + b + " == " + (b + 4 + d));
  866. return c ? ((this.offset = b), this) : b - e;
  867. };
  868. d.readIString = function (a) {
  869. var b = "undefined" === typeof a;
  870. b && (a = this.offset);
  871. if (!this.noAssert) {
  872. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  873. a >>>= 0;
  874. if (0 > a || a + 4 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+4) <= " + this.buffer.byteLength);
  875. }
  876. var c = a,
  877. e = this.readUint32(a);
  878. e = this.readUTF8String(e, g.METRICS_BYTES, (a += 4));
  879. a += e.length;
  880. return b ? ((this.offset = a), e.string) : { string: e.string, length: a - c };
  881. };
  882. g.METRICS_CHARS = "c";
  883. g.METRICS_BYTES = "b";
  884. d.writeUTF8String = function (a, b) {
  885. var c = "undefined" === typeof b;
  886. c && (b = this.offset);
  887. if (!this.noAssert) {
  888. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  889. b >>>= 0;
  890. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  891. }
  892. var e = b;
  893. var d = m.calculateUTF16asUTF8(l(a))[1];
  894. b += d;
  895. var f = this.buffer.byteLength;
  896. b > f && this.resize((f *= 2) > b ? f : b);
  897. b -= d;
  898. m.encodeUTF16toUTF8(
  899. l(a),
  900. function (a) {
  901. this.view[b++] = a;
  902. }.bind(this)
  903. );
  904. return c ? ((this.offset = b), this) : b - e;
  905. };
  906. d.writeString = d.writeUTF8String;
  907. g.calculateUTF8Chars = function (a) {
  908. return m.calculateUTF16asUTF8(l(a))[0];
  909. };
  910. g.calculateUTF8Bytes = function (a) {
  911. return m.calculateUTF16asUTF8(l(a))[1];
  912. };
  913. g.calculateString = g.calculateUTF8Bytes;
  914. d.readUTF8String = function (a, b, c) {
  915. "number" === typeof b && ((c = b), (b = void 0));
  916. var e = "undefined" === typeof c;
  917. e && (c = this.offset);
  918. "undefined" === typeof b && (b = g.METRICS_CHARS);
  919. if (!this.noAssert) {
  920. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal length: " + a + " (not an integer)");
  921. a |= 0;
  922. if ("number" !== typeof c || 0 !== c % 1) throw TypeError("Illegal offset: " + c + " (not an integer)");
  923. c >>>= 0;
  924. if (0 > c || c + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + c + " (+0) <= " + this.buffer.byteLength);
  925. }
  926. var d = 0,
  927. f = c;
  928. if (b === g.METRICS_CHARS) {
  929. var p = t();
  930. m.decodeUTF8(
  931. function () {
  932. return d < a && c < this.limit ? this.view[c++] : null;
  933. }.bind(this),
  934. function (a) {
  935. ++d;
  936. m.UTF8toUTF16(a, p);
  937. }
  938. );
  939. if (d !== a) throw RangeError("Illegal range: Truncated data, " + d + " == " + a);
  940. return e ? ((this.offset = c), p()) : { string: p(), length: c - f };
  941. }
  942. if (b === g.METRICS_BYTES) {
  943. if (!this.noAssert) {
  944. if ("number" !== typeof c || 0 !== c % 1) throw TypeError("Illegal offset: " + c + " (not an integer)");
  945. c >>>= 0;
  946. if (0 > c || c + a > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + c + " (+" + a + ") <= " + this.buffer.byteLength);
  947. }
  948. var h = c + a;
  949. m.decodeUTF8toUTF16(
  950. function () {
  951. return c < h ? this.view[c++] : null;
  952. }.bind(this),
  953. (p = t()),
  954. this.noAssert
  955. );
  956. if (c !== h) throw RangeError("Illegal range: Truncated data, " + c + " == " + h);
  957. return e ? ((this.offset = c), p()) : { string: p(), length: c - f };
  958. }
  959. throw TypeError("Unsupported metrics: " + b);
  960. };
  961. d.readString = d.readUTF8String;
  962. d.writeVString = function (a, b) {
  963. var c = "undefined" === typeof b;
  964. c && (b = this.offset);
  965. if (!this.noAssert) {
  966. if ("string" !== typeof a) throw TypeError("Illegal str: Not a string");
  967. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: " + b + " (not an integer)");
  968. b >>>= 0;
  969. if (0 > b || b + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + b + " (+0) <= " + this.buffer.byteLength);
  970. }
  971. var e = b;
  972. var d = m.calculateUTF16asUTF8(l(a), this.noAssert)[1];
  973. var f = g.calculateVarint32(d);
  974. b += f + d;
  975. var p = this.buffer.byteLength;
  976. b > p && this.resize((p *= 2) > b ? p : b);
  977. b -= f + d;
  978. b += this.writeVarint32(d, b);
  979. m.encodeUTF16toUTF8(
  980. l(a),
  981. function (a) {
  982. this.view[b++] = a;
  983. }.bind(this)
  984. );
  985. if (b !== e + d + f) throw RangeError("Illegal range: Truncated data, " + b + " == " + (b + d + f));
  986. return c ? ((this.offset = b), this) : b - e;
  987. };
  988. d.readVString = function (a) {
  989. var b = "undefined" === typeof a;
  990. b && (a = this.offset);
  991. if (!this.noAssert) {
  992. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  993. a >>>= 0;
  994. if (0 > a || a + 1 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+1) <= " + this.buffer.byteLength);
  995. }
  996. var c = a,
  997. e = this.readVarint32(a);
  998. e = this.readUTF8String(e.value, g.METRICS_BYTES, (a += e.length));
  999. a += e.length;
  1000. return b ? ((this.offset = a), e.string) : { string: e.string, length: a - c };
  1001. };
  1002. d.append = function (a, b, c) {
  1003. if ("number" === typeof b || "string" !== typeof b) (c = b), (b = void 0);
  1004. var e = "undefined" === typeof c;
  1005. e && (c = this.offset);
  1006. if (!this.noAssert) {
  1007. if ("number" !== typeof c || 0 !== c % 1) throw TypeError("Illegal offset: " + c + " (not an integer)");
  1008. c >>>= 0;
  1009. if (0 > c || c + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + c + " (+0) <= " + this.buffer.byteLength);
  1010. }
  1011. a instanceof g || (a = g.wrap(a, b));
  1012. b = a.limit - a.offset;
  1013. if (0 >= b) return this;
  1014. c += b;
  1015. var d = this.buffer.byteLength;
  1016. c > d && this.resize((d *= 2) > c ? d : c);
  1017. c -= b;
  1018. this.view.set(a.view.subarray(a.offset, a.limit), c);
  1019. a.offset += b;
  1020. e && (this.offset += b);
  1021. return this;
  1022. };
  1023. d.appendTo = function (a, b) {
  1024. a.append(this, b);
  1025. return this;
  1026. };
  1027. d.writeBytes = d.append;
  1028. d.assert = function (a) {
  1029. this.noAssert = !a;
  1030. return this;
  1031. };
  1032. d.capacity = function () {
  1033. return this.buffer.byteLength;
  1034. };
  1035. d.clear = function () {
  1036. this.offset = 0;
  1037. this.limit = this.buffer.byteLength;
  1038. this.markedOffset = -1;
  1039. return this;
  1040. };
  1041. d.clone = function (a) {
  1042. var b = new g(0, this.littleEndian, this.noAssert);
  1043. a ? ((b.buffer = new ArrayBuffer(this.buffer.byteLength)), (b.view = new Uint8Array(b.buffer))) : ((b.buffer = this.buffer), (b.view = this.view));
  1044. b.offset = this.offset;
  1045. b.markedOffset = this.markedOffset;
  1046. b.limit = this.limit;
  1047. return b;
  1048. };
  1049. d.compact = function (a, b) {
  1050. "undefined" === typeof a && (a = this.offset);
  1051. "undefined" === typeof b && (b = this.limit);
  1052. if (!this.noAssert) {
  1053. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal begin: Not an integer");
  1054. a >>>= 0;
  1055. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal end: Not an integer");
  1056. b >>>= 0;
  1057. if (0 > a || a > b || b > this.buffer.byteLength) throw RangeError("Illegal range: 0 <= " + a + " <= " + b + " <= " + this.buffer.byteLength);
  1058. }
  1059. if (0 === a && b === this.buffer.byteLength) return this;
  1060. var c = b - a;
  1061. if (0 === c) return (this.buffer = w), (this.view = null), 0 <= this.markedOffset && (this.markedOffset -= a), (this.limit = this.offset = 0), this;
  1062. var e = new ArrayBuffer(c),
  1063. d = new Uint8Array(e);
  1064. d.set(this.view.subarray(a, b));
  1065. this.buffer = e;
  1066. this.view = d;
  1067. 0 <= this.markedOffset && (this.markedOffset -= a);
  1068. this.offset = 0;
  1069. this.limit = c;
  1070. return this;
  1071. };
  1072. d.copy = function (a, b) {
  1073. "undefined" === typeof a && (a = this.offset);
  1074. "undefined" === typeof b && (b = this.limit);
  1075. if (!this.noAssert) {
  1076. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal begin: Not an integer");
  1077. a >>>= 0;
  1078. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal end: Not an integer");
  1079. b >>>= 0;
  1080. if (0 > a || a > b || b > this.buffer.byteLength) throw RangeError("Illegal range: 0 <= " + a + " <= " + b + " <= " + this.buffer.byteLength);
  1081. }
  1082. if (a === b) return new g(0, this.littleEndian, this.noAssert);
  1083. var c = b - a,
  1084. e = new g(c, this.littleEndian, this.noAssert);
  1085. e.offset = 0;
  1086. e.limit = c;
  1087. 0 <= e.markedOffset && (e.markedOffset -= a);
  1088. this.copyTo(e, 0, a, b);
  1089. return e;
  1090. };
  1091. d.copyTo = function (a, b, c, e) {
  1092. var d, f;
  1093. if (!this.noAssert && !g.isByteBuffer(a)) throw TypeError("Illegal target: Not a ByteBuffer");
  1094. b = (f = "undefined" === typeof b) ? a.offset : b | 0;
  1095. c = (d = "undefined" === typeof c) ? this.offset : c | 0;
  1096. e = "undefined" === typeof e ? this.limit : e | 0;
  1097. if (0 > b || b > a.buffer.byteLength) throw RangeError("Illegal target range: 0 <= " + b + " <= " + a.buffer.byteLength);
  1098. if (0 > c || e > this.buffer.byteLength) throw RangeError("Illegal source range: 0 <= " + c + " <= " + this.buffer.byteLength);
  1099. var p = e - c;
  1100. if (0 === p) return a;
  1101. a.ensureCapacity(b + p);
  1102. a.view.set(this.view.subarray(c, e), b);
  1103. d && (this.offset += p);
  1104. f && (a.offset += p);
  1105. return this;
  1106. };
  1107. d.ensureCapacity = function (a) {
  1108. var b = this.buffer.byteLength;
  1109. return b < a ? this.resize((b *= 2) > a ? b : a) : this;
  1110. };
  1111. d.fill = function (a, b, c) {
  1112. var e = "undefined" === typeof b;
  1113. e && (b = this.offset);
  1114. "string" === typeof a && 0 < a.length && (a = a.charCodeAt(0));
  1115. "undefined" === typeof b && (b = this.offset);
  1116. "undefined" === typeof c && (c = this.limit);
  1117. if (!this.noAssert) {
  1118. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal value: " + a + " (not an integer)");
  1119. a |= 0;
  1120. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal begin: Not an integer");
  1121. b >>>= 0;
  1122. if ("number" !== typeof c || 0 !== c % 1) throw TypeError("Illegal end: Not an integer");
  1123. c >>>= 0;
  1124. if (0 > b || b > c || c > this.buffer.byteLength) throw RangeError("Illegal range: 0 <= " + b + " <= " + c + " <= " + this.buffer.byteLength);
  1125. }
  1126. if (b >= c) return this;
  1127. for (; b < c; ) this.view[b++] = a;
  1128. e && (this.offset = b);
  1129. return this;
  1130. };
  1131. d.flip = function () {
  1132. this.limit = this.offset;
  1133. this.offset = 0;
  1134. return this;
  1135. };
  1136. d.mark = function (a) {
  1137. a = "undefined" === typeof a ? this.offset : a;
  1138. if (!this.noAssert) {
  1139. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal offset: " + a + " (not an integer)");
  1140. a >>>= 0;
  1141. if (0 > a || a + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + a + " (+0) <= " + this.buffer.byteLength);
  1142. }
  1143. this.markedOffset = a;
  1144. return this;
  1145. };
  1146. d.order = function (a) {
  1147. if (!this.noAssert && "boolean" !== typeof a) throw TypeError("Illegal littleEndian: Not a boolean");
  1148. this.littleEndian = !!a;
  1149. return this;
  1150. };
  1151. d.LE = function (a) {
  1152. this.littleEndian = "undefined" !== typeof a ? !!a : !0;
  1153. return this;
  1154. };
  1155. d.BE = function (a) {
  1156. this.littleEndian = "undefined" !== typeof a ? !a : !1;
  1157. return this;
  1158. };
  1159. d.prepend = function (a, b, c) {
  1160. if ("number" === typeof b || "string" !== typeof b) (c = b), (b = void 0);
  1161. var e = "undefined" === typeof c;
  1162. e && (c = this.offset);
  1163. if (!this.noAssert) {
  1164. if ("number" !== typeof c || 0 !== c % 1) throw TypeError("Illegal offset: " + c + " (not an integer)");
  1165. c >>>= 0;
  1166. if (0 > c || c + 0 > this.buffer.byteLength) throw RangeError("Illegal offset: 0 <= " + c + " (+0) <= " + this.buffer.byteLength);
  1167. }
  1168. a instanceof g || (a = g.wrap(a, b));
  1169. b = a.limit - a.offset;
  1170. if (0 >= b) return this;
  1171. var d = b - c;
  1172. if (0 < d) {
  1173. var f = new ArrayBuffer(this.buffer.byteLength + d),
  1174. p = new Uint8Array(f);
  1175. p.set(this.view.subarray(c, this.buffer.byteLength), b);
  1176. this.buffer = f;
  1177. this.view = p;
  1178. this.offset += d;
  1179. 0 <= this.markedOffset && (this.markedOffset += d);
  1180. this.limit += d;
  1181. c += d;
  1182. } else new Uint8Array(this.buffer);
  1183. this.view.set(a.view.subarray(a.offset, a.limit), c - b);
  1184. a.offset = a.limit;
  1185. e && (this.offset -= b);
  1186. return this;
  1187. };
  1188. d.prependTo = function (a, b) {
  1189. a.prepend(this, b);
  1190. return this;
  1191. };
  1192. d.printDebug = function (a) {
  1193. "function" !== typeof a && (a = console.log.bind(console));
  1194. a(this.toString() + "\n-------------------------------------------------------------------\n" + this.toDebug(!0));
  1195. };
  1196. d.remaining = function () {
  1197. return this.limit - this.offset;
  1198. };
  1199. d.reset = function () {
  1200. 0 <= this.markedOffset ? ((this.offset = this.markedOffset), (this.markedOffset = -1)) : (this.offset = 0);
  1201. return this;
  1202. };
  1203. d.resize = function (a) {
  1204. if (!this.noAssert) {
  1205. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal capacity: " + a + " (not an integer)");
  1206. a |= 0;
  1207. if (0 > a) throw RangeError("Illegal capacity: 0 <= " + a);
  1208. }
  1209. if (this.buffer.byteLength < a) {
  1210. a = new ArrayBuffer(a);
  1211. var b = new Uint8Array(a);
  1212. b.set(this.view);
  1213. this.buffer = a;
  1214. this.view = b;
  1215. }
  1216. return this;
  1217. };
  1218. d.reverse = function (a, b) {
  1219. "undefined" === typeof a && (a = this.offset);
  1220. "undefined" === typeof b && (b = this.limit);
  1221. if (!this.noAssert) {
  1222. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal begin: Not an integer");
  1223. a >>>= 0;
  1224. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal end: Not an integer");
  1225. b >>>= 0;
  1226. if (0 > a || a > b || b > this.buffer.byteLength) throw RangeError("Illegal range: 0 <= " + a + " <= " + b + " <= " + this.buffer.byteLength);
  1227. }
  1228. if (a === b) return this;
  1229. Array.prototype.reverse.call(this.view.subarray(a, b));
  1230. return this;
  1231. };
  1232. d.skip = function (a) {
  1233. if (!this.noAssert) {
  1234. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal length: " + a + " (not an integer)");
  1235. a |= 0;
  1236. }
  1237. var b = this.offset + a;
  1238. if (!this.noAssert && (0 > b || b > this.buffer.byteLength)) throw RangeError("Illegal length: 0 <= " + this.offset + " + " + a + " <= " + this.buffer.byteLength);
  1239. this.offset = b;
  1240. return this;
  1241. };
  1242. d.slice = function (a, b) {
  1243. "undefined" === typeof a && (a = this.offset);
  1244. "undefined" === typeof b && (b = this.limit);
  1245. if (!this.noAssert) {
  1246. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal begin: Not an integer");
  1247. a >>>= 0;
  1248. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal end: Not an integer");
  1249. b >>>= 0;
  1250. if (0 > a || a > b || b > this.buffer.byteLength) throw RangeError("Illegal range: 0 <= " + a + " <= " + b + " <= " + this.buffer.byteLength);
  1251. }
  1252. var c = this.clone();
  1253. c.offset = a;
  1254. c.limit = b;
  1255. return c;
  1256. };
  1257. d.toBuffer = function (a) {
  1258. var b = this.offset,
  1259. c = this.limit;
  1260. if (!this.noAssert) {
  1261. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal offset: Not an integer");
  1262. b >>>= 0;
  1263. if ("number" !== typeof c || 0 !== c % 1) throw TypeError("Illegal limit: Not an integer");
  1264. c >>>= 0;
  1265. if (0 > b || b > c || c > this.buffer.byteLength) throw RangeError("Illegal range: 0 <= " + b + " <= " + c + " <= " + this.buffer.byteLength);
  1266. }
  1267. if (!a && 0 === b && c === this.buffer.byteLength) return this.buffer;
  1268. if (b === c) return w;
  1269. a = new ArrayBuffer(c - b);
  1270. new Uint8Array(a).set(new Uint8Array(this.buffer).subarray(b, c), 0);
  1271. return a;
  1272. };
  1273. d.toArrayBuffer = d.toBuffer;
  1274. d.toString = function (a, b, c) {
  1275. if ("undefined" === typeof a) return "ByteBufferAB(offset=" + this.offset + ",markedOffset=" + this.markedOffset + ",limit=" + this.limit + ",capacity=" + this.capacity() + ")";
  1276. "number" === typeof a && (c = b = a = "utf8");
  1277. switch (a) {
  1278. case "utf8":
  1279. return this.toUTF8(b, c);
  1280. case "base64":
  1281. return this.toBase64(b, c);
  1282. case "hex":
  1283. return this.toHex(b, c);
  1284. case "binary":
  1285. return this.toBinary(b, c);
  1286. case "debug":
  1287. return this.toDebug();
  1288. case "columns":
  1289. return this.toColumns();
  1290. default:
  1291. throw Error("Unsupported encoding: " + a);
  1292. }
  1293. };
  1294. var z = (function () {
  1295. for (
  1296. var a = {},
  1297. b = [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99,
  1298. 100,
  1299. 101,
  1300. 102,
  1301. 103,
  1302. 104,
  1303. 105,
  1304. 106,
  1305. 107,
  1306. 108,
  1307. 109,
  1308. 110,
  1309. 111,
  1310. 112,
  1311. 113,
  1312. 114,
  1313. 115,
  1314. 116,
  1315. 117,
  1316. 118,
  1317. 119,
  1318. 120,
  1319. 121,
  1320. 122,
  1321. 48,
  1322. 49,
  1323. 50,
  1324. 51,
  1325. 52,
  1326. 53,
  1327. 54,
  1328. 55,
  1329. 56,
  1330. 57,
  1331. 43,
  1332. 47,
  1333. ],
  1334. c = [],
  1335. e = 0,
  1336. d = b.length;
  1337. e < d;
  1338. ++e
  1339. )
  1340. c[b[e]] = e;
  1341. a.encode = function (a, c) {
  1342. for (var e, d; null !== (e = a()); )
  1343. c(b[(e >> 2) & 63]),
  1344. (d = (e & 3) << 4),
  1345. null !== (e = a())
  1346. ? ((d |= (e >> 4) & 15), c(b[(d | ((e >> 4) & 15)) & 63]), (d = (e & 15) << 2), null !== (e = a()) ? (c(b[(d | ((e >> 6) & 3)) & 63]), c(b[e & 63])) : (c(b[d & 63]), c(61)))
  1347. : (c(b[d & 63]), c(61), c(61));
  1348. };
  1349. a.decode = function (a, b) {
  1350. function e(a) {
  1351. throw Error("Illegal character code: " + a);
  1352. }
  1353. for (var d, k, f; null !== (d = a()); )
  1354. if (((k = c[d]), "undefined" === typeof k && e(d), null !== (d = a()) && ((f = c[d]), "undefined" === typeof f && e(d), b(((k << 2) >>> 0) | ((f & 48) >> 4)), null !== (d = a())))) {
  1355. k = c[d];
  1356. if ("undefined" === typeof k)
  1357. if (61 === d) break;
  1358. else e(d);
  1359. b((((f & 15) << 4) >>> 0) | ((k & 60) >> 2));
  1360. if (null !== (d = a())) {
  1361. f = c[d];
  1362. if ("undefined" === typeof f)
  1363. if (61 === d) break;
  1364. else e(d);
  1365. b((((k & 3) << 6) >>> 0) | f);
  1366. }
  1367. }
  1368. };
  1369. a.test = function (a) {
  1370. return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(a);
  1371. };
  1372. return a;
  1373. })();
  1374. d.toBase64 = function (a, b) {
  1375. "undefined" === typeof a && (a = this.offset);
  1376. "undefined" === typeof b && (b = this.limit);
  1377. a |= 0;
  1378. b |= 0;
  1379. if (0 > a || b > this.capacity || a > b) throw RangeError("begin, end");
  1380. var c;
  1381. z.encode(
  1382. function () {
  1383. return a < b ? this.view[a++] : null;
  1384. }.bind(this),
  1385. (c = t())
  1386. );
  1387. return c();
  1388. };
  1389. g.fromBase64 = function (a, b) {
  1390. if ("string" !== typeof a) throw TypeError("str");
  1391. var c = new g((a.length / 4) * 3, b),
  1392. e = 0;
  1393. z.decode(l(a), function (a) {
  1394. c.view[e++] = a;
  1395. });
  1396. c.limit = e;
  1397. return c;
  1398. };
  1399. g.btoa = function (a) {
  1400. return g.fromBinary(a).toBase64();
  1401. };
  1402. g.atob = function (a) {
  1403. return g.fromBase64(a).toBinary();
  1404. };
  1405. d.toBinary = function (a, b) {
  1406. "undefined" === typeof a && (a = this.offset);
  1407. "undefined" === typeof b && (b = this.limit);
  1408. a |= 0;
  1409. b |= 0;
  1410. if (0 > a || b > this.capacity() || a > b) throw RangeError("begin, end");
  1411. if (a === b) return "";
  1412. for (var c = [], e = []; a < b; ) c.push(this.view[a++]), 1024 <= c.length && (e.push(String.fromCharCode.apply(String, c)), (c = []));
  1413. return e.join("") + String.fromCharCode.apply(String, c);
  1414. };
  1415. g.fromBinary = function (a, b) {
  1416. if ("string" !== typeof a) throw TypeError("str");
  1417. for (var c = 0, e = a.length, d = new g(e, b); c < e; ) {
  1418. b = a.charCodeAt(c);
  1419. if (255 < b) throw RangeError("illegal char code: " + b);
  1420. d.view[c++] = b;
  1421. }
  1422. d.limit = e;
  1423. return d;
  1424. };
  1425. d.toDebug = function (a) {
  1426. for (var b = -1, c = this.buffer.byteLength, e, d = "", f = "", g = ""; b < c; ) {
  1427. -1 !== b && ((e = this.view[b]), (d = 16 > e ? d + ("0" + e.toString(16).toUpperCase()) : d + e.toString(16).toUpperCase()), a && (f += 32 < e && 127 > e ? String.fromCharCode(e) : "."));
  1428. ++b;
  1429. if (a && 0 < b && 0 === b % 16 && b !== c) {
  1430. for (; 51 > d.length; ) d += " ";
  1431. g += d + f + "\n";
  1432. d = f = "";
  1433. }
  1434. d =
  1435. b === this.offset && b === this.limit
  1436. ? d + (b === this.markedOffset ? "!" : "|")
  1437. : b === this.offset
  1438. ? d + (b === this.markedOffset ? "[" : "<")
  1439. : b === this.limit
  1440. ? d + (b === this.markedOffset ? "]" : ">")
  1441. : d + (b === this.markedOffset ? "'" : a || (0 !== b && b !== c) ? " " : "");
  1442. }
  1443. if (a && " " !== d) {
  1444. for (; 51 > d.length; ) d += " ";
  1445. g += d + f + "\n";
  1446. }
  1447. return a ? g : d;
  1448. };
  1449. g.fromDebug = function (a, b, c) {
  1450. var e = a.length;
  1451. b = new g(((e + 1) / 3) | 0, b, c);
  1452. for (var d = 0, f = 0, h, l = !1, n = !1, m = !1, q = !1, r = !1; d < e; ) {
  1453. switch ((h = a.charAt(d++))) {
  1454. case "!":
  1455. if (!c) {
  1456. if (n || m || q) {
  1457. r = !0;
  1458. break;
  1459. }
  1460. n = m = q = !0;
  1461. }
  1462. b.offset = b.markedOffset = b.limit = f;
  1463. l = !1;
  1464. break;
  1465. case "|":
  1466. if (!c) {
  1467. if (n || q) {
  1468. r = !0;
  1469. break;
  1470. }
  1471. n = q = !0;
  1472. }
  1473. b.offset = b.limit = f;
  1474. l = !1;
  1475. break;
  1476. case "[":
  1477. if (!c) {
  1478. if (n || m) {
  1479. r = !0;
  1480. break;
  1481. }
  1482. n = m = !0;
  1483. }
  1484. b.offset = b.markedOffset = f;
  1485. l = !1;
  1486. break;
  1487. case "<":
  1488. if (!c) {
  1489. if (n) {
  1490. r = !0;
  1491. break;
  1492. }
  1493. n = !0;
  1494. }
  1495. b.offset = f;
  1496. l = !1;
  1497. break;
  1498. case "]":
  1499. if (!c) {
  1500. if (q || m) {
  1501. r = !0;
  1502. break;
  1503. }
  1504. q = m = !0;
  1505. }
  1506. b.limit = b.markedOffset = f;
  1507. l = !1;
  1508. break;
  1509. case ">":
  1510. if (!c) {
  1511. if (q) {
  1512. r = !0;
  1513. break;
  1514. }
  1515. q = !0;
  1516. }
  1517. b.limit = f;
  1518. l = !1;
  1519. break;
  1520. case "'":
  1521. if (!c) {
  1522. if (m) {
  1523. r = !0;
  1524. break;
  1525. }
  1526. m = !0;
  1527. }
  1528. b.markedOffset = f;
  1529. l = !1;
  1530. break;
  1531. case " ":
  1532. l = !1;
  1533. break;
  1534. default:
  1535. if (!c && l) r = !0;
  1536. else {
  1537. h = parseInt(h + a.charAt(d++), 16);
  1538. if (!c && (isNaN(h) || 0 > h || 255 < h)) throw TypeError("Illegal str: Not a debug encoded string");
  1539. b.view[f++] = h;
  1540. l = !0;
  1541. }
  1542. }
  1543. if (r) throw TypeError("Illegal str: Invalid symbol at " + d);
  1544. }
  1545. if (!c) {
  1546. if (!n || !q) throw TypeError("Illegal str: Missing offset or limit");
  1547. if (f < b.buffer.byteLength) throw TypeError("Illegal str: Not a debug encoded string (is it hex?) " + f + " < " + e);
  1548. }
  1549. return b;
  1550. };
  1551. d.toHex = function (a, b) {
  1552. a = "undefined" === typeof a ? this.offset : a;
  1553. b = "undefined" === typeof b ? this.limit : b;
  1554. if (!this.noAssert) {
  1555. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal begin: Not an integer");
  1556. a >>>= 0;
  1557. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal end: Not an integer");
  1558. b >>>= 0;
  1559. if (0 > a || a > b || b > this.buffer.byteLength) throw RangeError("Illegal range: 0 <= " + a + " <= " + b + " <= " + this.buffer.byteLength);
  1560. }
  1561. for (var c = Array(b - a), e; a < b; ) (e = this.view[a++]), 16 > e ? c.push("0", e.toString(16)) : c.push(e.toString(16));
  1562. return c.join("");
  1563. };
  1564. g.fromHex = function (a, b, c) {
  1565. if (!c) {
  1566. if ("string" !== typeof a) throw TypeError("Illegal str: Not a string");
  1567. if (0 !== a.length % 2) throw TypeError("Illegal str: Length not a multiple of 2");
  1568. }
  1569. var e = a.length;
  1570. b = new g((e / 2) | 0, b);
  1571. for (var d, f = 0, h = 0; f < e; f += 2) {
  1572. d = parseInt(a.substring(f, f + 2), 16);
  1573. if (!c && (!isFinite(d) || 0 > d || 255 < d)) throw TypeError("Illegal str: Contains non-hex characters");
  1574. b.view[h++] = d;
  1575. }
  1576. b.limit = h;
  1577. return b;
  1578. };
  1579. var m = (function () {
  1580. var a = {
  1581. MAX_CODEPOINT: 1114111,
  1582. encodeUTF8: function (a, c) {
  1583. var b = null;
  1584. "number" === typeof a &&
  1585. ((b = a),
  1586. (a = function () {
  1587. return null;
  1588. }));
  1589. for (; null !== b || null !== (b = a()); )
  1590. 128 > b
  1591. ? c(b & 127)
  1592. : (2048 > b ? c(((b >> 6) & 31) | 192) : 65536 > b ? (c(((b >> 12) & 15) | 224), c(((b >> 6) & 63) | 128)) : (c(((b >> 18) & 7) | 240), c(((b >> 12) & 63) | 128), c(((b >> 6) & 63) | 128)), c((b & 63) | 128)),
  1593. (b = null);
  1594. },
  1595. decodeUTF8: function (a, c) {
  1596. for (
  1597. var b,
  1598. d,
  1599. f,
  1600. g,
  1601. h = function (a) {
  1602. a = a.slice(0, a.indexOf(null));
  1603. var b = Error(a.toString());
  1604. b.name = "TruncatedError";
  1605. b.bytes = a;
  1606. throw b;
  1607. };
  1608. null !== (b = a());
  1609.  
  1610. )
  1611. if (0 === (b & 128)) c(b);
  1612. else if (192 === (b & 224)) null === (d = a()) && h([b, d]), c(((b & 31) << 6) | (d & 63));
  1613. else if (224 === (b & 240)) (null !== (d = a()) && null !== (f = a())) || h([b, d, f]), c(((b & 15) << 12) | ((d & 63) << 6) | (f & 63));
  1614. else if (240 === (b & 248)) (null !== (d = a()) && null !== (f = a()) && null !== (g = a())) || h([b, d, f, g]), c(((b & 7) << 18) | ((d & 63) << 12) | ((f & 63) << 6) | (g & 63));
  1615. else throw RangeError("Illegal starting byte: " + b);
  1616. },
  1617. UTF16toUTF8: function (a, c) {
  1618. for (var b, d = null; null !== (b = null !== d ? d : a()); ) 55296 <= b && 57343 >= b && null !== (d = a()) && 56320 <= d && 57343 >= d ? (c(1024 * (b - 55296) + d - 56320 + 65536), (d = null)) : c(b);
  1619. null !== d && c(d);
  1620. },
  1621. UTF8toUTF16: function (a, c) {
  1622. var b = null;
  1623. "number" === typeof a &&
  1624. ((b = a),
  1625. (a = function () {
  1626. return null;
  1627. }));
  1628. for (; null !== b || null !== (b = a()); ) 65535 >= b ? c(b) : ((b -= 65536), c((b >> 10) + 55296), c((b % 1024) + 56320)), (b = null);
  1629. },
  1630. encodeUTF16toUTF8: function (b, c) {
  1631. a.UTF16toUTF8(b, function (b) {
  1632. a.encodeUTF8(b, c);
  1633. });
  1634. },
  1635. decodeUTF8toUTF16: function (b, c) {
  1636. a.decodeUTF8(b, function (b) {
  1637. a.UTF8toUTF16(b, c);
  1638. });
  1639. },
  1640. calculateCodePoint: function (a) {
  1641. return 128 > a ? 1 : 2048 > a ? 2 : 65536 > a ? 3 : 4;
  1642. },
  1643. calculateUTF8: function (a) {
  1644. for (var b, d = 0; null !== (b = a()); ) d += 128 > b ? 1 : 2048 > b ? 2 : 65536 > b ? 3 : 4;
  1645. return d;
  1646. },
  1647. calculateUTF16asUTF8: function (b) {
  1648. var c = 0,
  1649. d = 0;
  1650. a.UTF16toUTF8(b, function (a) {
  1651. ++c;
  1652. d += 128 > a ? 1 : 2048 > a ? 2 : 65536 > a ? 3 : 4;
  1653. });
  1654. return [c, d];
  1655. },
  1656. };
  1657. return a;
  1658. })();
  1659. d.toUTF8 = function (a, b) {
  1660. "undefined" === typeof a && (a = this.offset);
  1661. "undefined" === typeof b && (b = this.limit);
  1662. if (!this.noAssert) {
  1663. if ("number" !== typeof a || 0 !== a % 1) throw TypeError("Illegal begin: Not an integer");
  1664. a >>>= 0;
  1665. if ("number" !== typeof b || 0 !== b % 1) throw TypeError("Illegal end: Not an integer");
  1666. b >>>= 0;
  1667. if (0 > a || a > b || b > this.buffer.byteLength) throw RangeError("Illegal range: 0 <= " + a + " <= " + b + " <= " + this.buffer.byteLength);
  1668. }
  1669. var c;
  1670. try {
  1671. m.decodeUTF8toUTF16(
  1672. function () {
  1673. return a < b ? this.view[a++] : null;
  1674. }.bind(this),
  1675. (c = t())
  1676. );
  1677. } catch (e) {
  1678. if (a !== b) throw RangeError("Illegal range: Truncated data, " + a + " != " + b);
  1679. }
  1680. return c();
  1681. };
  1682. g.fromUTF8 = function (a, b, c) {
  1683. if (!c && "string" !== typeof a) throw TypeError("Illegal str: Not a string");
  1684. var d = new g(m.calculateUTF16asUTF8(l(a), !0)[1], b, c),
  1685. h = 0;
  1686. m.encodeUTF16toUTF8(l(a), function (a) {
  1687. d.view[h++] = a;
  1688. });
  1689. d.limit = h;
  1690. return d;
  1691. };
  1692. return g;
  1693. });
  1694. const { ByteBuffer } = dcodeIO;
  1695.  
  1696. // @WasmModule
  1697. let PacketIds_1 = {
  1698. default: {
  1699. 0: "PACKET_ENTITY_UPDATE",
  1700. 1: "PACKET_PLAYER_COUNTER_UPDATE",
  1701. 2: "PACKET_SET_WORLD_DIMENSIONS",
  1702. 3: "PACKET_INPUT",
  1703. 4: "PACKET_ENTER_WORLD",
  1704. 5: "PACKET_PRE_ENTER_WORLD",
  1705. 6: "PACKET_ENTER_WORLD2",
  1706. 7: "PACKET_PING",
  1707. 9: "PACKET_RPC",
  1708. 10: "PACKET_BLEND",
  1709. PACKET_PRE_ENTER_WORLD: 5,
  1710. PACKET_ENTER_WORLD: 4,
  1711. PACKET_ENTER_WORLD2: 6,
  1712. PACKET_ENTITY_UPDATE: 0,
  1713. PACKET_INPUT: 3,
  1714. PACKET_PING: 7,
  1715. PACKET_PLAYER_COUNTER_UPDATE: 1,
  1716. PACKET_RPC: 9,
  1717. PACKET_SET_WORLD_DIMENSIONS: 2,
  1718. PACKET_BLEND: 10,
  1719. },
  1720. },
  1721. e_AttributeType = {
  1722. 0: "Uninitialized",
  1723. 1: "Uint32",
  1724. 2: "Int32",
  1725. 3: "Float",
  1726. 4: "String",
  1727. 5: "Vector2",
  1728. 6: "EntityType",
  1729. 7: "ArrayVector2",
  1730. 8: "ArrayUint32",
  1731. 9: "Uint16",
  1732. 10: "Uint8",
  1733. 11: "Int16",
  1734. 12: "Int8",
  1735. 13: "Uint64",
  1736. 14: "Int64",
  1737. 15: "Double",
  1738. Uninitialized: 0,
  1739. Uint32: 1,
  1740. Int32: 2,
  1741. Float: 3,
  1742. String: 4,
  1743. Vector2: 5,
  1744. EntityType: 6,
  1745. ArrayVector2: 7,
  1746. ArrayUint32: 8,
  1747. Uint16: 9,
  1748. Uint8: 10,
  1749. Int16: 11,
  1750. Int8: 12,
  1751. Uint64: 13,
  1752. Int64: 14,
  1753. Double: 15,
  1754. },
  1755. e_ParameterType = { 0: "Uint32", 1: "Int32", 2: "Float", 3: "String", 4: "Uint64", 5: "Int64", Uint32: 0, Int32: 1, Float: 2, String: 3, Uint64: 4, Int64: 5 };
  1756. class BinCodec {
  1757. constructor() {
  1758. (this.attributeMaps = {}), (this.entityTypeNames = {}), (this.rpcMaps = []), (this.rpcMapsByName = {}), (this.sortedUidsByType = {}), (this.removedEntities = {}), (this.absentEntitiesFlags = []), (this.updatedEntityFlags = []);
  1759. }
  1760. encode(e, t, a) {
  1761. let r = new dcodeIO.ByteBuffer(100, !0);
  1762. switch (e) {
  1763. case PacketIds_1.default.PACKET_ENTER_WORLD:
  1764. r.writeUint8(PacketIds_1.default.PACKET_ENTER_WORLD), this.encodeEnterWorld(r, t);
  1765. break;
  1766. case PacketIds_1.default.PACKET_ENTER_WORLD2:
  1767. r.writeUint8(PacketIds_1.default.PACKET_ENTER_WORLD2), this.encodeEnterWorld2(r, a);
  1768. break;
  1769. case PacketIds_1.default.PACKET_INPUT:
  1770. r.writeUint8(PacketIds_1.default.PACKET_INPUT), this.encodeInput(r, t);
  1771. break;
  1772. case PacketIds_1.default.PACKET_PING:
  1773. r.writeUint8(PacketIds_1.default.PACKET_PING), this.encodePing(r, t);
  1774. break;
  1775. case PacketIds_1.default.PACKET_RPC:
  1776. r.writeUint8(PacketIds_1.default.PACKET_RPC), this.encodeRpc(r, t);
  1777. break;
  1778. case PacketIds_1.default.PACKET_BLEND:
  1779. r.writeUint8(PacketIds_1.default.PACKET_BLEND), this.encodeBlend(r, t);
  1780. }
  1781. return r.flip(), r.compact(), r.toArrayBuffer(!1);
  1782. }
  1783. decode(e, t) {
  1784. let a = dcodeIO.ByteBuffer.wrap(e);
  1785. a.littleEndian = !0;
  1786. let r = a.readUint8(),
  1787. n;
  1788. switch (r) {
  1789. case PacketIds_1.default.PACKET_PRE_ENTER_WORLD:
  1790. n = this.decodePreEnterWorldResponse(a, t);
  1791. break;
  1792. case PacketIds_1.default.PACKET_ENTER_WORLD:
  1793. n = this.decodeEnterWorldResponse(a);
  1794. break;
  1795. case PacketIds_1.default.PACKET_ENTITY_UPDATE:
  1796. n = this.decodeEntityUpdate(a);
  1797. break;
  1798. case PacketIds_1.default.PACKET_PING:
  1799. n = this.decodePing(a);
  1800. break;
  1801. case PacketIds_1.default.PACKET_RPC:
  1802. n = this.decodeRpc(a);
  1803. break;
  1804. case PacketIds_1.default.PACKET_BLEND:
  1805. n = this.decodeBlend(a, t);
  1806. }
  1807. return (n.opcode = r), n;
  1808. }
  1809. safeReadVString(e) {
  1810. let t = e.offset,
  1811. a = e.readVarint32(t);
  1812. try {
  1813. var r = e.readUTF8String.bind(e)(a.value, "b", (t += a.length));
  1814. return (t += r.length), (e.offset = t), r.string;
  1815. } catch (n) {
  1816. return (t += a.value), (e.offset = t), "?";
  1817. }
  1818. }
  1819. decodePreEnterWorldResponse(e, t) {
  1820. return t._MakeBlendField(255, 140), { extra: this.decodeBlendInternal(e, t) };
  1821. }
  1822. decodeEnterWorldResponse(e) {
  1823. let t = {
  1824. allowed: e.readUint32(),
  1825. uid: e.readUint32(),
  1826. startingTick: e.readUint32(),
  1827. tickRate: e.readUint32(),
  1828. effectiveTickRate: e.readUint32(),
  1829. players: e.readUint32(),
  1830. maxPlayers: e.readUint32(),
  1831. chatChannel: e.readUint32(),
  1832. effectiveDisplayName: this.safeReadVString(e),
  1833. x1: e.readInt32(),
  1834. y1: e.readInt32(),
  1835. x2: e.readInt32(),
  1836. y2: e.readInt32(),
  1837. },
  1838. a = e.readUint32();
  1839. (this.attributeMaps = {}), (this.entityTypeNames = {});
  1840. for (let r = 0; r < a; r++) {
  1841. let n = [],
  1842. i = e.readUint32(),
  1843. s = e.readVString(),
  1844. d = e.readUint32();
  1845. for (let o = 0; o < d; o++) {
  1846. let c = e.readVString(),
  1847. l = e.readUint32();
  1848. n.push({ name: c, type: l });
  1849. }
  1850. (this.attributeMaps[i] = n), (this.entityTypeNames[i] = s), (this.sortedUidsByType[i] = []);
  1851. }
  1852. let p = e.readUint32();
  1853. (this.rpcMaps = []), (this.rpcMapsByName = {});
  1854. for (let h = 0; h < p; h++) {
  1855. let f = e.readVString(),
  1856. U = e.readUint8(),
  1857. u = 0 != e.readUint8(),
  1858. y = [];
  1859. for (let E = 0; E < U; E++) {
  1860. let $ = e.readVString(),
  1861. m = e.readUint8();
  1862. y.push({ name: $, type: m });
  1863. }
  1864. let b = { name: f, parameters: y, isArray: u, index: this.rpcMaps.length };
  1865. this.rpcMaps.push(b), (this.rpcMapsByName[f] = b);
  1866. }
  1867. return t;
  1868. }
  1869. decodeEntityUpdate(e) {
  1870. var t = e.readUint32(),
  1871. a = e.readVarint32(),
  1872. r = {};
  1873. for (var n in ((r.tick = t), (r.entities = {}), this.removedEntities)) delete this.removedEntities[n];
  1874. for (var i = 0; i < a; i++) {
  1875. var n = e.readUint32();
  1876. this.removedEntities[n] = 1;
  1877. }
  1878. for (var s = e.readVarint32(), i = 0; i < s; i++) {
  1879. var d = e.readVarint32(),
  1880. o = e.readUint32();
  1881. this.entityTypeNames[o];
  1882. for (var c = 0; c < d; c++) {
  1883. var l = e.readUint32();
  1884. this.sortedUidsByType[o].push(l);
  1885. }
  1886. }
  1887. for (var i in this.sortedUidsByType) {
  1888. for (var p = this.sortedUidsByType[i], h = [], c = 0; c < p.length; c++) {
  1889. var n = p[c];
  1890. n in this.removedEntities || h.push(n);
  1891. }
  1892. h.sort(function (e, t) {
  1893. return e < t ? -1 : e > t ? 1 : 0;
  1894. }),
  1895. (this.sortedUidsByType[i] = h);
  1896. }
  1897. for (; e.remaining(); ) {
  1898. var f = e.readUint32();
  1899. if ((this.entityTypeNames[f], !(f in this.attributeMaps))) throw Error("Entity type is not in attribute map: " + f);
  1900. var U = Math.floor((this.sortedUidsByType[f].length + 7) / 8);
  1901. this.absentEntitiesFlags.length = 0;
  1902. for (var i = 0; i < U; i++) this.absentEntitiesFlags.push(e.readUint8());
  1903. for (var u = this.attributeMaps[f], y = 0; y < this.sortedUidsByType[f].length; y++) {
  1904. var n = this.sortedUidsByType[f][y];
  1905. if ((this.absentEntitiesFlags[Math.floor(y / 8)] & (1 << y % 8)) != 0) {
  1906. r.entities[n] = !0;
  1907. continue;
  1908. }
  1909. var E = { uid: n };
  1910. this.updatedEntityFlags.length = 0;
  1911. for (var c = 0; c < Math.ceil(u.length / 8); c++) this.updatedEntityFlags.push(e.readUint8());
  1912. for (var c = 0; c < u.length; c++) {
  1913. var $ = u[c],
  1914. m = Math.floor(c / 8),
  1915. b = c % 8,
  1916. v = void 0,
  1917. g = [];
  1918. if (this.updatedEntityFlags[m] & (1 << b))
  1919. switch ($.type) {
  1920. case e_AttributeType.Uint32:
  1921. E[$.name] = e.readUint32();
  1922. break;
  1923. case e_AttributeType.Int32:
  1924. E[$.name] = e.readInt32();
  1925. break;
  1926. case e_AttributeType.Float:
  1927. E[$.name] = e.readInt32() / 100;
  1928. break;
  1929. case e_AttributeType.String:
  1930. E[$.name] = this.safeReadVString(e);
  1931. break;
  1932. case e_AttributeType.Vector2:
  1933. var T = e.readInt32() / 100,
  1934. k = e.readInt32() / 100;
  1935. E[$.name] = { x: T, y: k };
  1936. break;
  1937. case e_AttributeType.ArrayVector2:
  1938. (v = e.readInt32()), (g = []);
  1939. for (var i = 0; i < v; i++) {
  1940. var P = e.readInt32() / 100,
  1941. I = e.readInt32() / 100;
  1942. g.push({ x: P, y: I });
  1943. }
  1944. E[$.name] = g;
  1945. break;
  1946. case e_AttributeType.ArrayUint32:
  1947. (v = e.readInt32()), (g = []);
  1948. for (var i = 0; i < v; i++) {
  1949. var B = e.readInt32();
  1950. g.push(B);
  1951. }
  1952. E[$.name] = g;
  1953. break;
  1954. case e_AttributeType.Uint16:
  1955. E[$.name] = e.readUint16();
  1956. break;
  1957. case e_AttributeType.Uint8:
  1958. E[$.name] = e.readUint8();
  1959. break;
  1960. case e_AttributeType.Int16:
  1961. E[$.name] = e.readInt16();
  1962. break;
  1963. case e_AttributeType.Int8:
  1964. E[$.name] = e.readInt8();
  1965. break;
  1966. case e_AttributeType.Uint64:
  1967. E[$.name] = e.readUint32() + 4294967296 * e.readUint32();
  1968. break;
  1969. case e_AttributeType.Int64:
  1970. var R = e.readUint32(),
  1971. w = e.readInt32();
  1972. w < 0 && (R *= -1), (R += 4294967296 * w), (E[$.name] = R);
  1973. break;
  1974. case e_AttributeType.Double:
  1975. var _ = e.readUint32(),
  1976. A = e.readInt32();
  1977. A < 0 && (_ *= -1), (_ += 4294967296 * A), (_ /= 100), (E[$.name] = _);
  1978. break;
  1979. default:
  1980. throw Error("Unsupported attribute type: " + $.type);
  1981. }
  1982. }
  1983. r.entities[E.uid] = E;
  1984. }
  1985. }
  1986. return (r.byteSize = e.capacity()), r;
  1987. }
  1988. decodePing() {
  1989. return {};
  1990. }
  1991. encodeRpc(e, t) {
  1992. if (!(t.name in this.rpcMapsByName)) throw Error("RPC not in map: " + t.name);
  1993. var a = this.rpcMapsByName[t.name];
  1994. e.writeUint32(a.index);
  1995. for (var r = 0; r < a.parameters.length; r++) {
  1996. var n = t[a.parameters[r].name];
  1997. switch (a.parameters[r].type) {
  1998. case e_ParameterType.Float:
  1999. e.writeInt32(Math.floor(100 * n));
  2000. break;
  2001. case e_ParameterType.Int32:
  2002. e.writeInt32(n);
  2003. break;
  2004. case e_ParameterType.String:
  2005. e.writeVString(n);
  2006. break;
  2007. case e_ParameterType.Uint32:
  2008. e.writeUint32(n);
  2009. }
  2010. }
  2011. }
  2012. decodeBlend(e, t) {
  2013. return { extra: this.decodeBlendInternal(e, t) };
  2014. }
  2015. decodeBlendInternal(e, t) {
  2016. t._MakeBlendField(24, 132);
  2017. for (let a = t._MakeBlendField(228, e.remaining()), r = 0; e.remaining(); ) (t.HEAPU8[a + r] = e.readUint8()), r++;
  2018. t._MakeBlendField(172, 36);
  2019. for (var n = new ArrayBuffer(64), i = new Uint8Array(n), s = t._MakeBlendField(4, 152), d = 0; d < 64; d++) i[d] = t.HEAPU8[s + d];
  2020. return n;
  2021. }
  2022. decodeRpcObject(e, t) {
  2023. for (var a = {}, r = 0; r < t.length; r++)
  2024. switch (t[r].type) {
  2025. case e_ParameterType.Uint32:
  2026. a[t[r].name] = e.readUint32();
  2027. break;
  2028. case e_ParameterType.Int32:
  2029. a[t[r].name] = e.readInt32();
  2030. break;
  2031. case e_ParameterType.Float:
  2032. a[t[r].name] = e.readInt32() / 100;
  2033. break;
  2034. case e_ParameterType.String:
  2035. a[t[r].name] = this.safeReadVString(e);
  2036. break;
  2037. case e_ParameterType.Uint64:
  2038. a[t[r].name] = e.readUint32() + 4294967296 * e.readUint32();
  2039. }
  2040. return a;
  2041. }
  2042. decodeRpc(e) {
  2043. var t = e.readUint32(),
  2044. a = this.rpcMaps[t],
  2045. r = { name: a.name, response: null };
  2046. if (a.isArray) {
  2047. for (var n = [], i = e.readUint16(), s = 0; s < i; s++) n.push(this.decodeRpcObject(e, a.parameters));
  2048. r.response = n;
  2049. } else r.response = this.decodeRpcObject(e, a.parameters);
  2050. return r;
  2051. }
  2052. encodeBlend(e, t) {
  2053. for (var a = new Uint8Array(t.extra), r = 0; r < t.extra.byteLength; r++) e.writeUint8(a[r]);
  2054. }
  2055. encodeEnterWorld(e, t) {
  2056. e.writeVString(t.displayName);
  2057. for (var a = new Uint8Array(t.extra), r = 0; r < t.extra.byteLength; r++) e.writeUint8(a[r]);
  2058. }
  2059. encodeEnterWorld2(e, t) {
  2060. for (var a = t._MakeBlendField(187, 22), r = 0; r < 16; r++) e.writeUint8(t.HEAPU8[a + r]);
  2061. }
  2062. encodeInput(e, t) {
  2063. e.writeVString(JSON.stringify(t));
  2064. }
  2065. encodePing(e) {
  2066. e.writeUint8(0);
  2067. }
  2068. }
  2069. let codec = new BinCodec(),
  2070. wasmBuffers;
  2071. fetch("/asset/zombs_wasm.wasm").then((e) =>
  2072. e.arrayBuffer().then((e) => {
  2073. wasmBuffers = e;
  2074. })
  2075. );
  2076. const wasmModule = (callback, data_12, hostname) => {
  2077. function _a(e, t, r) {
  2078. for (var a = t + r, n = t; e[n] && !(n >= a); ) ++n;
  2079. if (n - t > 16 && e.subarray && _n) return _n.decode(e.subarray(t, n));
  2080. for (var i = ""; t < n; ) {
  2081. let d = e[t++];
  2082. if (128 & d) {
  2083. var s = 63 & e[t++];
  2084. if (192 != (224 & d)) {
  2085. var l = 63 & e[t++];
  2086. if ((d = 224 == (240 & d) ? ((15 & d) << 12) | (s << 6) | l : ((7 & d) << 18) | (s << 12) | (l << 6) | (63 & e[t++])) < 65536) i += String.fromCharCode(d);
  2087. else {
  2088. var c = d - 65536;
  2089. i += String.fromCharCode(55296 | (c >> 10), 56320 | (1023 & c));
  2090. }
  2091. } else i += String.fromCharCode(((31 & d) << 6) | s);
  2092. } else i += String.fromCharCode(d);
  2093. }
  2094. return i;
  2095. }
  2096. function _b(e, t) {
  2097. return e ? _a(_k, e, t) : "";
  2098. }
  2099. function _c(e, t, r, a) {
  2100. if (!(a > 0)) return 0;
  2101. for (var n = r, i = r + a - 1, d = 0; d < e.length; ++d) {
  2102. var s = e.charCodeAt(d);
  2103. if ((s >= 55296 && s <= 57343 && (s = (65536 + ((1023 & s) << 10)) | (1023 & e.charCodeAt(++d))), s <= 127)) {
  2104. if (r >= i) break;
  2105. t[r++] = s;
  2106. } else if (s <= 2047) {
  2107. if (r + 1 >= i) break;
  2108. (t[r++] = 192 | (s >> 6)), (t[r++] = 128 | (63 & s));
  2109. } else if (s <= 65535) {
  2110. if (r + 2 >= i) break;
  2111. (t[r++] = 224 | (s >> 12)), (t[r++] = 128 | ((s >> 6) & 63)), (t[r++] = 128 | (63 & s));
  2112. } else {
  2113. if (r + 3 >= i) break;
  2114. (t[r++] = 240 | (s >> 18)), (t[r++] = 128 | ((s >> 12) & 63)), (t[r++] = 128 | ((s >> 6) & 63)), (t[r++] = 128 | (63 & s));
  2115. }
  2116. }
  2117. return (t[r] = 0), r - n;
  2118. }
  2119. function _d(e, t, r) {
  2120. return _c(e, _k, t, r);
  2121. }
  2122. function _e(e) {
  2123. for (var t = 0, r = 0; r < e.length; ++r) {
  2124. var a = e.charCodeAt(r);
  2125. a >= 55296 && a <= 57343 && (a = (65536 + ((1023 & a) << 10)) | (1023 & e.charCodeAt(++r))), a <= 127 ? ++t : (t += a <= 2047 ? 2 : a <= 65535 ? 3 : 4);
  2126. }
  2127. return t;
  2128. }
  2129. function _f(e) {
  2130. (_m.HEAP8 = new Int8Array(e)),
  2131. (_m.HEAP16 = new Int16Array(e)),
  2132. (_m.HEAP32 = _l = new Int32Array(e)),
  2133. (_m.HEAPU8 = _k = new Uint8Array(e)),
  2134. (_m.HEAPU16 = new Uint16Array(e)),
  2135. (_m.HEAPU32 = new Uint32Array(e)),
  2136. (_m.HEAPF32 = new Float32Array(e)),
  2137. (_m.HEAPF64 = new Float64Array(e));
  2138. }
  2139. function _g() {
  2140. function e(e) {
  2141. (_m.asm = e.exports), _f(_m.asm.g.buffer), _o(), _j();
  2142. }
  2143. function t(t) {
  2144. e(t.instance);
  2145. }
  2146. function r(e) {
  2147. WebAssembly.instantiate(wasmBuffers, a).then((t) => {
  2148. e(t), "function" == typeof callback && callback(_m.decodeOpcode5(hostname, data_12));
  2149. });
  2150. }
  2151. var a = { a: { d() {}, e() {}, c() {}, f() {}, b: _h, a: _i } };
  2152. if (_m.instantiateWasm)
  2153. try {
  2154. return _m.instantiateWasm(a, e);
  2155. } catch (n) {
  2156. return console.log("Module.instantiateWasm callback failed with error: " + n), !1;
  2157. }
  2158. return r(t), {};
  2159. }
  2160. function _h(_hh) {
  2161. let e = _b(_hh);
  2162. if (e.includes('typeof window === "undefined" ? 1 : 0;') || e.includes("typeof process !== 'undefined' ? 1 : 0;")) return 0;
  2163. if (e.includes("Game.currentGame.network.connected ? 1 : 0")) return 1;
  2164. if (e.includes("Game.currentGame.world.myUid === null ? 0 : Game.currentGame.world.myUid;")) return 0;
  2165. if (e.includes('document.getElementById("hud").children.length;')) return 24;
  2166. if (e.includes("hostname")) return hostname;
  2167. let data;
  2168. return 0 | eval(_b(_hh));
  2169. }
  2170. function _i(e) {
  2171. var t = hostname;
  2172. if (null == t) return 0;
  2173. t = String(t);
  2174. var r = _i,
  2175. a = _e(t);
  2176. return (!r.bufferSize || r.bufferSize < a + 1) && (r.bufferSize && _s(r.buffer), (r.bufferSize = a + 1), (r.buffer = _r(r.bufferSize))), _d(t, r.buffer, r.bufferSize), r.buffer;
  2177. }
  2178. function _j() {
  2179. (_l[1328256] = 5313008), (_l[1328257] = 0), _m._main(1, 5313024);
  2180. }
  2181. var _k,
  2182. _l,
  2183. _m = {},
  2184. _n = new TextDecoder("utf8");
  2185. _g();
  2186. var _o = (_m.___wasm_call_ctors = function () {
  2187. return (_o = _m.___wasm_call_ctors = _m.asm.h).apply(null, arguments);
  2188. }),
  2189. _p = (_m._main = function () {
  2190. return (_p = _m._main = _m.asm.i).apply(null, arguments);
  2191. }),
  2192. _q = (_m._MakeBlendField = function () {
  2193. return (_q = _m._MakeBlendField = _m.asm.j).apply(null, arguments);
  2194. }),
  2195. _r = (_m._malloc = function () {
  2196. return (_r = _m._malloc = _m.asm.l).apply(null, arguments);
  2197. }),
  2198. _s = (_m._free = function () {
  2199. return (_s = _m._free = _m.asm.m).apply(null, arguments);
  2200. });
  2201. return (
  2202. (_m.decodeOpcode5 = function (e, t) {
  2203. _m.hostname = e;
  2204. let r = codec.decode(new Uint8Array(t), _m),
  2205. a = codec.encode(6, {}, _m);
  2206. return { 5: r, 6: a, 10: _m };
  2207. }),
  2208. _m
  2209. );
  2210. };
  2211.  
  2212. // @FontAwesome
  2213. const fontAwesome = document.createElement("script");
  2214. fontAwesome.type = "text/javascript";
  2215. fontAwesome.src = "https://kit.fontawesome.com/1c239b2e80.js";
  2216. document.head.appendChild(fontAwesome);
  2217.  
  2218. document.querySelectorAll('#hud-respawn > div > div > div > h2, #hud-respawn > div > div > div > p, #hud-respawn > div > div > div > div, .ad-unit, #hud-intro > div.hud-intro-footer > a:nth-child(2), #hud-intro > div.hud-intro-footer > a:nth-child(4), #hud-intro > div.hud-intro-wrapper > h1, #hud-intro > div.hud-intro-wrapper > h2, .hud-intro-left, .hud-intro-guide, .hud-intro > .hud-intro-stone, .hud-intro >.hud-intro-tree, .hud-intro-youtuber, .hud-intro-more-games, .hud-intro-social, .hud-respawn-corner-bottom-left, .hud-respawn-twitter-btn, .hud-respawn-facebook-btn').forEach(el => el.remove());
  2219. const css = `
  2220. /* @Root */
  2221. :root {
  2222. --normal-btn: rgb(40 152 231);
  2223. --light-hover-btn: rgb(111 208 247);
  2224. }
  2225.  
  2226. ::-webkit-scrollbar {
  2227. width: 12px;
  2228. height: 0px;
  2229. border-radius: 10px;
  2230. background-color: rgba(0, 0, 0, 0);
  2231. }
  2232. ::-webkit-scrollbar-thumb {
  2233. border-radius: 10px;
  2234. background-image: url(https://cdn.glitch.global/ba7f4151-2a49-416a-985b-56301606ae3d/whiteslider.png?v=1714878503407);
  2235. }
  2236.  
  2237. input[type='range'] {
  2238. accent-color: var(--normal-btn);
  2239. }
  2240.  
  2241. .btn-theme {
  2242. background: var(--normal-btn);
  2243. }
  2244. .btn-theme:hover {
  2245. background: var(--light-hover-btn);
  2246. }
  2247.  
  2248. /* @CustomKeyframes */
  2249. @keyframes bounce {
  2250. 50% { transform: translateY(-30px); }
  2251. 100% { transform: translateY(-10px); }
  2252. }
  2253.  
  2254. .hud-intro::before {
  2255. background-image: var(--bg-image);
  2256. background-size: cover;
  2257. background-position: center;
  2258. transition: all 0.5s ease-out;
  2259. }
  2260. .hud-intro::after {
  2261. background: unset;
  2262. }
  2263.  
  2264. #hud-intro > div.hud-intro-corner-top-left > div {
  2265. padding: 10px;
  2266. backdrop-filter: blur(10px);
  2267. background: rgba(0, 0, 0, 0.1);
  2268. box-shadow: 0px 0px 10px 10px rgba(0, 0, 0, 0.2);
  2269. display: flex;
  2270. line-height: 20px;
  2271. margin: 0 0 10px;
  2272. font-size: 14px;
  2273. color: rgba(255, 255, 255, 0.4);
  2274. border-radius: 4px;
  2275. flex-direction: column;
  2276. }
  2277.  
  2278. #hud-intro > div.hud-intro-corner-top-right > div {
  2279. padding: 10px;
  2280. backdrop-filter: blur(10px);
  2281. background: rgba(0, 0, 0, 0.1);
  2282. box-shadow: 0px 0px 10px 10px rgba(0, 0, 0, 0.2);
  2283. }
  2284.  
  2285. #hud-intro > div.hud-intro-wrapper {
  2286. justify-content: flex-end;
  2287. margin: 40px 0 0;
  2288. }
  2289. #hud-intro > div.hud-intro-wrapper > div > div {
  2290. padding: 10px;
  2291. background: rgba(0, 0, 0, 0.1);
  2292. }
  2293. #hud-intro > div.hud-intro-wrapper > div > div > input {
  2294. color: white;
  2295. backdrop-filter: blur(10px);
  2296. background: rgba(0, 0, 0, 0.1);
  2297. box-shadow: 0px 0px 5px 5px rgba(0, 0, 0, 0.2);
  2298. }
  2299. #hud-intro > div.hud-intro-wrapper > div > div > select {
  2300. color: white;
  2301. backdrop-filter: blur(10px);
  2302. background: rgba(0, 0, 0, 0.1);
  2303. box-shadow: 0px 0px 5px 5px rgba(0, 0, 0, 0.2);
  2304. border: 0px;
  2305. margin: 0 0 10px;
  2306. }
  2307.  
  2308. #hud-intro > div.hud-intro-footer {
  2309. left: unset;
  2310. right: 20px;
  2311. }
  2312.  
  2313. /* @CustomIntroStyles */
  2314. #intro-animation {
  2315. display: block;
  2316. position: absolute;
  2317. top: 0px;
  2318. left: 0px;
  2319. width: 100%;
  2320. height: 100%;
  2321. z-index: 0;
  2322. }
  2323. #background-canvas {
  2324. display: block;
  2325. position: absolute;
  2326. top: 0px;
  2327. left: 0px;
  2328. width: 100%;
  2329. height: 100%;
  2330. z-index: 1;
  2331. filter: blur(2px);
  2332. }
  2333. #intro-animation > img {
  2334. position: absolute;
  2335. z-index: 2;
  2336. height: calc(1400px + 5vw);
  2337. max-height: 170vh;
  2338. left: calc(15vw - 300px);
  2339. bottom: calc(20vh - 600px - 2.5vw);
  2340. top: unset;
  2341. z-index: 2;
  2342. transform: translateY(-10px);
  2343. transition: all 0.5s ease-out;
  2344. animation-name: bounce;
  2345. animation-duration: 5s;
  2346. animation-iteration-count: infinite;
  2347. }
  2348. #foreground-canvas {
  2349. display: block;
  2350. position: absolute;
  2351. top: 0px;
  2352. left: 0px;
  2353. width: 100%;
  2354. height: 100%;
  2355. z-index: 3;
  2356. }
  2357.  
  2358. #start-btn {
  2359. display: flex;
  2360. flex-direction: column;
  2361. align-items: flex-end;
  2362. justify-content: center;
  2363. margin: auto;
  2364. position: absolute;
  2365. top: calc(50vh - 75px);
  2366. right: 0px;
  2367. height: 150px;
  2368. zoom: 140%;
  2369. cursor: pointer;
  2370. background: rgba(0, 0, 0, 0.1);
  2371. backdrop-filter: blur(3px);
  2372. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2373. border-top-left-radius: 15px;
  2374. border-bottom-left-radius: 15px;
  2375. }
  2376. #start-btn > h1 {
  2377. color: white;
  2378. margin-right: 20px;
  2379. font-size: 60px;
  2380. text-transform: none;
  2381. }
  2382. #start-btn > hr {
  2383. border: 2px solid white;
  2384. width: 225px;
  2385. }
  2386. #start-btn > h2 {
  2387. margin-right: 20px;
  2388. font-size: 20px;
  2389. color: rgba(255, 255, 255, 0.8);
  2390. }
  2391.  
  2392. #sesSelect {
  2393. display: none;
  2394. float: left;
  2395. width: 100%;
  2396. height: 50px;
  2397. line-height: 34px;
  2398. padding: 8px 14px;
  2399. margin: 0 0 10px;
  2400. border: 0;
  2401. font-size: 14px;
  2402. border-radius: 4px;
  2403. color: white;
  2404. backdrop-filter: blur(10px);
  2405. background: rgba(0, 0, 0, 0.1);
  2406. box-shadow: 0px 0px 5px 5px rgba(0, 0, 0, 0.2);
  2407. }
  2408. #sesSelect:disabled {
  2409. opacity: 0.4;
  2410. }
  2411. #delBtn, #addBtn {
  2412. display: none;
  2413. width: calc(50% - 5px);
  2414. height: 50px;
  2415. line-height: 34px;
  2416. padding: 8px 14px;
  2417. font-size: 14px;
  2418. border-left: 0;
  2419. border-right: 0;
  2420. border-top: 0;
  2421. border-radius: 4px;
  2422. color: #eee;
  2423. cursor: pointer;
  2424. backdrop-filter: blur(10px);
  2425. background: rgba(0, 0, 0, 0.1);
  2426. box-shadow: 0px 0px 5px 5px rgba(0, 0, 0, 0.2);
  2427. }
  2428.  
  2429. #delBtn {
  2430. margin: 0 5px 10px 0;
  2431. border-bottom: 2px solid red;
  2432. }
  2433. #addBtn {
  2434. margin: 0 0 10px 5px;
  2435. border-bottom: 2px solid white;
  2436. }
  2437.  
  2438. #hud-intro-overlay {
  2439. display: none;
  2440. opacity: 0;
  2441. position: absolute;
  2442. top: 0px;
  2443. left: 0px;
  2444. z-index: 999;
  2445. backdrop-filter: blur(10px);
  2446. width: 100%;
  2447. height: 100%;
  2448. background: rgba(0, 0, 0, 0.3);
  2449. justify-content: center;
  2450. align-items: center;
  2451. flex-direction: column;
  2452. transition: all 0.5s;
  2453. }
  2454. #hud-intro-overlay h2 {
  2455. color: white;
  2456. font-size: 30px;
  2457. text-shadow: 0 0 20px black;
  2458. margin-bottom: 15px;
  2459. }
  2460. #hud-intro-overlay strong {
  2461. margin: -15px 0 5px;
  2462. color: #aaa;
  2463. }
  2464. #hud-intro-overlay p {
  2465. color: #eee;
  2466. margin: 10px 0;
  2467. font-weight: bold;
  2468. }
  2469. #hud-intro-overlay input, #hud-intro-overlay select, #hud-intro-overlay button:not(.session-back):not(#create-session):not(#create-endpoint) {
  2470. width: 100%;
  2471. height: 50px;
  2472. line-height: 34px;
  2473. padding: 8px 14px;
  2474. margin: 0 0 15px;
  2475. border: 0;
  2476. text-align: start;
  2477. font-size: 15px;
  2478. border-radius: 10px;
  2479. color: white;
  2480. backdrop-filter: blur(10px);
  2481. background: rgba(0, 0, 0, 0.1);
  2482. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.2);
  2483. }
  2484. #hud-intro-overlay button {
  2485. cursor: pointer;
  2486. }
  2487. #loading-div {
  2488. display: none;
  2489. pointer-events: none;
  2490. justify-content: center;
  2491. align-items: center;
  2492. flex-direction: column;
  2493. }
  2494. #loading-div > span {
  2495. width: 100px;
  2496. height: 100px;
  2497. }
  2498. #loading-div > a {
  2499. margin-top: 20px;
  2500. color: rgba(255, 255, 255, 0.4);
  2501. pointer-events: all;
  2502. }
  2503. #select-session-add, #endpoint-add-menu, #session-add-menu {
  2504. width: 40vw;
  2505. display: none;
  2506. align-items: flex-start;
  2507. flex-direction: column;
  2508. padding: 20px;
  2509. border-radius: 10px;
  2510. background: rgba(0, 0, 0, 0.2);
  2511. }
  2512. .session-navigator {
  2513. display: flex;
  2514. justify-content: space-between;
  2515. width: 100%;
  2516. margin-top: 10px;
  2517. }
  2518. .session-navigator button {
  2519. height: 20px;
  2520. background: none;
  2521. border: 0;
  2522. color: #eee;
  2523. font-weight: bold;
  2524. zoom: 130%;
  2525. }
  2526.  
  2527. /* @CustomUIStyles */
  2528. .dragBox {
  2529. position: absolute;
  2530. background-color: rgba(233, 233, 233, 0.3);
  2531. border: 5px solid rgba(255, 255, 255, 0.3);
  2532. border-radius: 3px;
  2533. }
  2534. .dragBoxMenu {
  2535. background-color: whitesmoke;
  2536. border-radius: 5px;
  2537. color: #111;
  2538. transform: translate(-50%, -50%);
  2539. position: absolute;
  2540. padding: 3px;
  2541. width: auto;
  2542. z-index: 999;
  2543. }
  2544. .dragBoxMenu > button, .dragBoxMenu > input {
  2545. width: 100%;
  2546. background-color: whitesmoke;
  2547. border: none;
  2548. border-radius: 2px;
  2549. cursor: default;
  2550. transition: none;
  2551. }
  2552. .dragBoxMenu > button:hover, .dragBoxMenu > input:focus {
  2553. background-color: grey;
  2554. color: whitesmoke;
  2555. }
  2556. .dragBoxMenu > input:focus::placeholder {
  2557. color: whitesmoke;
  2558. }
  2559.  
  2560. #joinWithPsk {
  2561. display: none;
  2562. backdrop-filter: blur(5px);
  2563. background: rgba(255, 255, 255, 0.1);
  2564. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2565. padding: 4px 5px;
  2566. border-radius: 8px;
  2567. color: white;
  2568. width: 30vw;
  2569. height: 40px;
  2570. position: fixed;
  2571. left: 35vw;
  2572. top: 60vh;
  2573. }
  2574.  
  2575. .interaction-wheel {
  2576. display: none;
  2577. height: 250px;
  2578. width: 250px;
  2579. border: 80px solid rgba(255, 255, 255, 0.1);
  2580. backdrop-filter: blur(3px);
  2581. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2582. border-radius: 125px;
  2583. position: fixed;
  2584. top: calc(50vh - 125px);
  2585. left: calc(50vw - 125px);
  2586. }
  2587. .tag-is-disabled {
  2588. opacity: 0.4;
  2589. pointer-events: none;
  2590. cursor: no-drop;
  2591. }
  2592. #next-wheel {
  2593. background: rgba(255, 255, 255, 0.1);
  2594. backdrop-filter: blur(3px);
  2595. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2596. color: white;
  2597. right: -120px;
  2598. position: absolute;
  2599. top: -80px;
  2600. height: 60px;
  2601. width: 60px;
  2602. border-radius: 50%;
  2603. border: none;
  2604. cursor: pointer;
  2605. }
  2606. #next-wheel::after {
  2607. content: '\\f363';
  2608. position: absolute;
  2609. width: 100%;
  2610. height: 100%;
  2611. top: 5%;
  2612. left: 5%;
  2613. }
  2614. #zoom-mode {
  2615. background: rgba(255, 255, 255, 0.1);
  2616. backdrop-filter: blur(3px);
  2617. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2618. color: white;
  2619. left: -120px;
  2620. position: absolute;
  2621. bottom: -80px;
  2622. height: 60px;
  2623. width: 60px;
  2624. border-radius: 50%;
  2625. border: none;
  2626. text-align: center;
  2627. padding: 20px 0;
  2628. font-family: 'Hammersmith One';
  2629. }
  2630. .hud-zoom-item {
  2631. width: 48px;
  2632. height: 48px;
  2633. color: white;
  2634. position: absolute;
  2635. transition: all 0.15s ease-in-out;
  2636. }
  2637. .zoom-reset {
  2638. top: -60px;
  2639. left: calc(50% - 15px);
  2640. }
  2641. .zoom-up {
  2642. left: -60px;
  2643. top: calc(50% - 15px);
  2644. }
  2645. .zoom-down {
  2646. top: calc(50% - 15px);
  2647. right: -80px;
  2648. }
  2649. .zoom-prop {
  2650. font-size: 20px;
  2651. bottom: -80px;
  2652. left: 25%;
  2653. }
  2654.  
  2655. #ent-settings {
  2656. flex-direction: column;
  2657. padding: 20px;
  2658. position: absolute;
  2659. color: white;
  2660. background: rgba(255, 255, 255, 0.1);
  2661. backdrop-filter: blur(3px);
  2662. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2663. border-radius: 10px;
  2664. max-width: 180px;
  2665. }
  2666. #current-side {
  2667. background: none;
  2668. border: none;
  2669. margin-top: 5px;
  2670. color: white;
  2671. width: 100%;
  2672. }
  2673. #ent-width {
  2674. margin: 5px -1px 10px;
  2675. width: calc(100% - 45px);
  2676. }
  2677. #ent-width::after {
  2678. content: attr(data-width);
  2679. position: absolute;
  2680. right: 20px;
  2681. color: white;
  2682. }
  2683. #ent-controls {
  2684. display: flex;
  2685. justify-content: space-between;
  2686. margin: 5px -5px 0;
  2687. zoom: 130%;
  2688. }
  2689. #ent-controls button {
  2690. color: white;
  2691. background: none;
  2692. border: none;
  2693. cursor: pointer;
  2694. }
  2695.  
  2696. #hud-debug {
  2697. color: rgb(0, 255, 255);
  2698. }
  2699. #hud-debug > strong {
  2700. font-family: "HammerSmith One";
  2701. color: red;
  2702. font-weight: 700;
  2703. }
  2704.  
  2705. .hud-popup-overlay > div.hud-popup-message {
  2706. background: rgba(255, 255, 255, 0.1);
  2707. backdrop-filter: blur(3px);
  2708. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2709. }
  2710. .hud-popup-overlay .hud-popup-confirmation .hud-confirmation-actions .btn.btn-green {
  2711. background: var(--normal-btn);
  2712. }
  2713.  
  2714. .hud-tooltip {
  2715. background: rgba(255, 255, 255, 0.1);
  2716. backdrop-filter: blur(3px);
  2717. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2718. border-radius: 10px;
  2719. }
  2720. .hud-tooltip-left::after {
  2721. left: calc(100% + 5px);
  2722. border-left: 6px solid rgba(255, 255, 255, 0.2);
  2723. }
  2724. .hud-tooltip-right::after {
  2725. right: calc(100% + 5px);
  2726. border-right: 6px solid rgba(255, 255, 255, 0.2);
  2727. }
  2728. .hud-tooltip-top::after {
  2729. top: calc(100% + 5px);
  2730. border-top: 6px solid rgba(255, 255, 255, 0.2);
  2731. }
  2732. .hud-tooltip-bottom::after {
  2733. bottom: calc(100% + 5px);
  2734. border-bottom: 6px solid rgba(255, 255, 255, 0.2);
  2735. }
  2736. .hud-building-view, .hud-building-ahrc {
  2737. position: relative;
  2738. display: block;
  2739. padding: 0 10px;
  2740. margin: 0 0 6px;
  2741. font-family: 'Hammersmith One', sans-serif;
  2742. text-shadow: 0 1px 3px rgb(0 0 0 / 20%);
  2743. text-align: left;
  2744. }
  2745.  
  2746. .hud-chat {
  2747. resize: vertical;
  2748. max-height: 380px;
  2749. min-height: 75px;
  2750. overflow-y: auto;
  2751. border-radius: 4px 4px 4px 0;
  2752. }
  2753. .hud-chat .hud-chat-message {
  2754. display: block;
  2755. position: relative;
  2756. width: 90%;
  2757. white-space: unset;
  2758. word-break: break-all;
  2759. overflow: visible;
  2760. }
  2761. .hud-chat .hud-chat-message strong {
  2762. display: inline-block;
  2763. }
  2764. .hud-chat .hud-chat-message > small {
  2765. position: absolute;
  2766. right: -12%;
  2767. font-weight: bold;
  2768. opacity: 0.4;
  2769. }
  2770.  
  2771. #hud-spell-icons {
  2772. background: rgba(255, 255, 255, 0.1);
  2773. backdrop-filter: blur(3px);
  2774. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2775. border-top-right-radius: 10px;
  2776. border-bottom-right-radius: 10px;
  2777. }
  2778. #hud-spell-icons > div {
  2779. background: none;
  2780. }
  2781.  
  2782. #hud-menu-icons {
  2783. background: rgba(255, 255, 255, 0.1);
  2784. backdrop-filter: blur(3px);
  2785. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2786. border-top-left-radius: 10px;
  2787. border-bottom-left-radius: 10px;
  2788. }
  2789. #hud-menu-icons > div {
  2790. background: none;
  2791. }
  2792.  
  2793. #hud > div.hud-bottom-left {
  2794. z-index: 20;
  2795. backdrop-filter: blur(3px);
  2796. background: rgba(255, 255, 255, 0.15);
  2797. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2798. padding: 10px;
  2799. border-radius: 4px;
  2800. }
  2801. #hud-map {
  2802. cursor: crosshair;
  2803. pointer-events: all;
  2804. background: rgba(0, 0, 0, 0.4);
  2805. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2806. }
  2807. #hud-day-night-ticker {
  2808. background: rgba(0, 0, 0, 0.4);
  2809. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2810. margin-top: 0px;
  2811. }
  2812.  
  2813. #hud-resources {
  2814. background: rgba(255, 255, 255, 0.1);
  2815. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2816. backdrop-filter: blur(3px);
  2817. }
  2818. #hud-health-bar {
  2819. height: 3px;
  2820. padding: 0px;
  2821. }
  2822. #hud-health-bar::after {
  2823. content: unset;
  2824. }
  2825. #hud-health-bar > div {
  2826. height: 3px;
  2827. }
  2828. #hud-shield-bar {
  2829. height: 3px;
  2830. padding: 0px;
  2831. margin: 0px 0px 5px !important;
  2832. }
  2833. #hud-shield-bar > div {
  2834. height: 3px;
  2835. border-radius: 0px;
  2836. }
  2837. #hud-party-icons > div {
  2838. background: rgba(255, 255, 255, 0.1);
  2839. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2840. backdrop-filter: blur(3px);
  2841. }
  2842. #hud-party-icons > div.is-empty {
  2843. background: rgba(255, 255, 255, 0.1) !important;
  2844. opacity: 0.4;
  2845. }
  2846. .hud-buff-bar .hud-buff-bar-item::before {
  2847. content: attr(data-tier);
  2848. }
  2849. #hud-buff-bar > a {
  2850. background: rgba(255, 255, 255, 0.1);
  2851. box-shadow: 0px 0px 5px 2px rgba(0, 0, 0, 0.1);
  2852. backdrop-filter: blur(2px);
  2853. }
  2854.  
  2855. #hud-toolbar > div.hud-toolbar-buildings > a {
  2856. background: rgba(255, 255, 255, 0.1);
  2857. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  2858. backdrop-filter: blur(3px);
  2859. }
  2860. #hud-toolbar > div.hud-toolbar-buildings > a.is-disabled {
  2861. background: rgba(255, 255, 255, 0.1) !important;
  2862. }
  2863.  
  2864. #hud-respawn {
  2865. background: none;
  2866. z-index: 9999;
  2867. width: 600px;
  2868. height: 200px;
  2869. top: calc(50vh - 100px);
  2870. left: calc(50vw - 300px);
  2871. }
  2872. #hud-respawn > div {
  2873. margin: 0px;
  2874. }
  2875. #hud-respawn > div > div > div {
  2876. display: flex;
  2877. width: 500px;
  2878. backdrop-filter: blur(3px);
  2879. background: rgba(255, 255, 255, 0.1);
  2880. box-shadow: 0px 0px 30px 10px rgba(0, 0, 0, 0.1);
  2881. border-radius: 10px;
  2882. align-items: flex-end;
  2883. justify-content: space-between;
  2884. padding: 10px 20px 30px;
  2885. }
  2886.  
  2887. /* @CustomMenuStyles */
  2888. #hud-menu-shop {
  2889. top: calc(50vh - 215px);
  2890. left: calc(50vw - 345px);
  2891. width: 690px;
  2892. height: 430px;
  2893. backdrop-filter: blur(3px);
  2894. background: rgba(255, 255, 255, 0.1);
  2895. box-shadow: 0px 0px 30px 10px rgba(0, 0, 0, 0.1);
  2896. margin: 0 0 0 0;
  2897. padding: 0px;
  2898. z-index: 20;
  2899. overflow: hidden;
  2900. border-radius: 10px;
  2901. }
  2902. #hud-menu-shop > h3 {
  2903. margin: 20px;
  2904. }
  2905. .hud-menu-shop .hud-shop-grid {
  2906. height: 360px;
  2907. border-radius: 0px;
  2908. background: rgba(0, 0, 0, 0.1);
  2909. }
  2910. .hud-menu-shop .hud-shop-grid .hud-shop-item .hud-shop-item-actions .hud-shop-actions-equip {
  2911. background: var(--normal-btn);
  2912. }
  2913. .hud-menu-shop .hud-shop-grid .hud-shop-item .hud-shop-item-actions .hud-shop-actions-equip:hover, .hud-menu-shop .hud-shop-grid .hud-shop-item .hud-shop-item-actions .hud-shop-actions-equip:active {
  2914. background: var(--light-hover-btn);
  2915. }
  2916. .hud-menu-shop .hud-shop-grid .hud-shop-item .hud-shop-item-actions .hud-shop-actions-equip.is-disabled {
  2917. background: none;
  2918. }
  2919. .hud-menu-shop .hud-shop-grid .hud-shop-item[data-item=HatComingSoon] .hud-shop-item-coming-soon {
  2920. background: none;
  2921. }
  2922. #hud-menu-shop > div.hud-shop-tabs > a.hud-shop-tabs-link.is-active {
  2923. background: rgba(0, 0, 0, 0.1);
  2924. }
  2925. #hud-menu-shop > div.hud-shop-tabs > a.hud-shop-tabs-link:first-child {
  2926. border-radius: 0px;
  2927. }
  2928.  
  2929. .hud-menu-party .hud-party-members .hud-member-link::before {
  2930. display: block;
  2931. position: absolute;
  2932. content: " ";
  2933. left: 0px;
  2934. bottom: 0px;
  2935. height: 3px;
  2936. width: 30%;
  2937. }
  2938. .hud-menu-party .hud-party-grid .hud-party-link span:nth-child(4) {
  2939. display: none;
  2940. position: absolute;
  2941. top: 10px;
  2942. right: 15px;
  2943. }
  2944. #hud-menu-party > div.hud-party-members > div:nth-child(1)::before {
  2945. background: #8473d4;
  2946. }
  2947. #hud-menu-party > div.hud-party-members > div:nth-child(2)::before {
  2948. background: #d6ab35;
  2949. }
  2950. #hud-menu-party > div.hud-party-members > div:nth-child(3)::before {
  2951. background: #76bd2f;
  2952. }
  2953. #hud-menu-party > div.hud-party-members > div:nth-child(4)::before {
  2954. background: #d67820;
  2955. }
  2956. #hud-menu-party {
  2957. top: calc(50vh - 240px);
  2958. left: calc(50vw - 305px);
  2959. margin: 0;
  2960. width: 610px;
  2961. height: 480px;
  2962. backdrop-filter: blur(3px);
  2963. background: rgba(255, 255, 255, 0.1);
  2964. box-shadow: 0px 0px 30px 10px rgba(0, 0, 0, 0.1);
  2965. z-index: 20;
  2966. border-radius: 10px;
  2967.  
  2968. /* Alternative
  2969. backdrop-filter: blur(5px);
  2970. background: rgba(111, 208, 247, 0.05);
  2971. box-shadow: 0px 0px 10px 10px rgba(0, 0, 0, 0.1);
  2972. z-index: 20;
  2973. */
  2974. }
  2975. .hud-menu-party .hud-party-grid .hud-party-link.is-active {
  2976. background: var(--normal-btn) !important;
  2977. }
  2978. .hud-menu-party .hud-party-visibility {
  2979. width: 275.5px;
  2980. margin: 10px 3px 0 0;
  2981. background: var(--normal-btn);
  2982. }
  2983. .hud-menu-party .hud-party-share {
  2984. width: 395px;
  2985. margin: 0 0 0 5px;
  2986. }
  2987. .hud-menu-party .hud-party-visibility:hover, .hud-menu-party .hud-party-visibility:active {
  2988. background: var(--light-hover-btn);
  2989. }
  2990.  
  2991. /* @CustomModMenuStyles */
  2992. #hud-menu-settings {
  2993. backdrop-filter: blur(3px);
  2994. background: rgba(255, 255, 255, 0.1);
  2995. box-shadow: 0px 0px 30px 10px rgba(0, 0, 0, 0.1);
  2996. margin: 0px;
  2997. top: calc(50vh - 250px);
  2998. left: calc(50vw - 360px);
  2999. width: 720px;
  3000. height: 500px;
  3001. padding: 0px;
  3002. border-radius: 10px;
  3003. overflow: hidden;
  3004. z-index: 20;
  3005. }
  3006. .hud-menu-tabs {
  3007. position: relative;
  3008. height: 40px;
  3009. line-height: 40px;
  3010. margin-top: 30px;
  3011. }
  3012. .hud-menu-tabs-link {
  3013. display: block;
  3014. float: left;
  3015. padding: 0 14px;
  3016. margin: 0 1px 0 0;
  3017. font-size: 14px;
  3018. background: rgba(0, 0, 0, 0.1);
  3019. color: rgba(255, 255, 255, 0.4);
  3020. transition: all 0.15s ease-in-out;
  3021. }
  3022. .hud-menu-tabs-link.is-active, .hud-menu-tabs-link:hover {
  3023. background: rgba(0, 0, 0, 0.36);
  3024. color: #eee;
  3025. }
  3026. .hud-menu-tabs-link:last-child {
  3027. border-top-right-radius: 3px;
  3028. }
  3029. .hint-controls {
  3030. position: absolute;
  3031. display: flex;
  3032. flex-direction: column;
  3033. zoom: 83%;
  3034. width: fit-content;
  3035. height: 65px;
  3036. top: 55px;
  3037. left: 53%;
  3038. overflow-y: scroll;
  3039. }
  3040. .hint-controls > li {
  3041. opacity: 0.5;
  3042. -webkit-font-smoothing: antialiased;
  3043. margin: 0 5px 0 0;
  3044. }
  3045. #hud-menu-settings > h3 {
  3046. margin: 20px;
  3047. }
  3048. .hud-menu-settings .hud-settings-grid {
  3049. height: 390px;
  3050. margin: 0px;
  3051. overflow: hidden;
  3052. padding: unset;
  3053. border-top-left-radius: 0px;
  3054. border-top-right-radius: 0px;
  3055. }
  3056. .hud-settings-page {
  3057. width: 100%;
  3058. height: 100%;
  3059. }
  3060. .hud-settings-page > span {
  3061. position: relative;
  3062. margin: auto;
  3063. font-size: 17px;
  3064. opacity: 0.7;
  3065. }
  3066. .hud-settings-options {
  3067. display: inline-block;
  3068. position: relative;
  3069. width: 50%;
  3070. height: 100%;
  3071. background: rgba(0, 0, 0, 0.2);
  3072. overflow: auto;
  3073. scrollbar-width: none;
  3074. }
  3075. .hud-settings-options > div {
  3076. opacity: 0.8;
  3077. display: block;
  3078. position: relative;
  3079. height: 120px;
  3080. border-bottom: 3px solid rgba(255, 255, 255, 0.2);
  3081. padding: 15px;
  3082. }
  3083. .hud-settings-options > div.disabled {
  3084. pointer-events: none;
  3085. opacity: 0.4;
  3086. }
  3087. .hud-settings-options > div:nth-child(even) {
  3088. background: rgba(0, 0, 0, 0.15);
  3089. }
  3090. .hud-settings-options > div:last-child {
  3091. border-bottom: none;
  3092. }
  3093. .hud-settings-options h2 {
  3094. font-family: "Open Sans";
  3095. margin: 5px 0;
  3096. font-size: 1.4em;
  3097. }
  3098. .hud-settings-options span {
  3099. display: block;
  3100. position: absolute;
  3101. opacity: 0.7;
  3102. width: 55%;
  3103. -webkit-font-smoothing: antialiased;
  3104. font-size: 14px;
  3105. }
  3106. .hud-settings-options button {
  3107. position: absolute;
  3108. top: calc(50% - 20px);
  3109. right: 50px;
  3110. height: 40px;
  3111. width: 25%;
  3112. background: #fff;
  3113. border: none;
  3114. border-bottom: 3px solid lightgreen;
  3115. color: #111;
  3116. font-size: 16px;
  3117. cursor: pointer;
  3118. transition: all 0.15s ease-in-out;
  3119. border-radius: 5px;
  3120. box-shadow: 0px 0px 5px 5px rgba(0, 0, 0, 0.05);
  3121. }
  3122. .hud-settings-options .underline-red {
  3123. border-bottom: 3px solid red;
  3124. }
  3125. .hud-settings-options a {
  3126. position: absolute;
  3127. top: calc(50% - 10px);
  3128. right: 10px;
  3129. height: 20px;
  3130. width: 20px;
  3131. background: unset;
  3132. opacity: 0.4;
  3133. transition: all 0.15s ease-in-out;
  3134. }
  3135. .hud-settings-options a::before {
  3136. font-family: "Font Awesome 5 Free";
  3137. content: "\\f054";
  3138. font-size: 20px;
  3139. height: 100%;
  3140. width: 100%;
  3141. display: block;
  3142. font-weight: 900;
  3143. }
  3144. .hud-settings-options a:hover {
  3145. opacity: 1;
  3146. }
  3147. .hud-settings-more {
  3148. position: relative;
  3149. display: inline-block;
  3150. width: 50%;
  3151. height: 100%;
  3152. padding: 15px;
  3153. overflow: auto;
  3154. }
  3155. .hud-settings-more h2 {
  3156. margin: 5px 0px 10px;
  3157. }
  3158. .hud-settings-more select {
  3159. height: 40px;
  3160. width: 35%;
  3161. background: #fff;
  3162. border: none;
  3163. color: #111;
  3164. cursor: pointer;
  3165. transition: all 0.15s ease-in-out;
  3166. border-radius: 5px;
  3167. box-shadow: 0px 0px 5px 5px rgba(0, 0, 0, 0.1);
  3168. float: right;
  3169. padding: 0px 10px;
  3170. }
  3171. .hud-settings-more select:hover {
  3172. background: #fff;
  3173. color: black;
  3174. }
  3175. .hud-settings-more input:not([type="checkbox"]) {
  3176. height: 40px;
  3177. width: 100%;
  3178. background: rgba(0, 0, 0, 0.2);
  3179. border: none;
  3180. border-radius: 4px;
  3181. padding: 5px 10px;
  3182. color: #eee;
  3183. margin: 10px 0;
  3184. box-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.1);
  3185. }
  3186. .hud-settings-more span {
  3187. display: block;
  3188. opacity: 0.5;
  3189. }
  3190. .hud-menu-settings > .hud-settings-grid label > span {
  3191. display: inline-block;
  3192. color: white;
  3193. text-transform: unset;
  3194. font-size: 16px;
  3195. }
  3196. .hud-settings-more p {
  3197. display: inline-block;
  3198. height: 40px;
  3199. align-content: center;
  3200. margin: unset;
  3201. opacity: 0.8;
  3202. font-size: 15px;
  3203. }
  3204. .hud-settings-more span {
  3205. display: block;
  3206. opacity: 0.5;
  3207. }
  3208. .hud-settings-more hr {
  3209. width: 8%;
  3210. float: left;
  3211. margin-top: -5px;
  3212. opacity: 0.4;
  3213. }
  3214.  
  3215. /* @CustomMoreSettings */
  3216. .base-card {
  3217. position: relative;
  3218. display: block;
  3219. width: 100%;
  3220. height: 64px;
  3221. margin: 0 0 10px;
  3222. padding: 10px 10px 10px 10px;
  3223. text-decoration: none;
  3224. background: rgba(255, 255, 255, 0.1);
  3225. cursor: pointer;
  3226. color: #eee;
  3227. border-radius: 3px;
  3228. transition: all 0.15s ease-in-out;
  3229. text-align: left;
  3230. }
  3231. .base-card:hover {
  3232. background: rgba(255, 255, 255, 0.2);
  3233. }
  3234. #base-management {
  3235. position: absolute;
  3236. top: 0px;
  3237. width: 100%;
  3238. height: 75%;
  3239. margin: 0px -15px;
  3240. padding: 0 15px;
  3241. overflow-y: scroll;
  3242. overflow-x: visible;
  3243. scrollbar-width: none;
  3244. }
  3245. #base-management input {
  3246. margin: 0px;
  3247. }
  3248. #target-base-name {
  3249. background: none;
  3250. box-shadow: none;
  3251. text-align: left;
  3252. font-weight: bold;
  3253. padding: 0px;
  3254. font-size: 16px;
  3255. }
  3256. #target-base-description {
  3257. background: none;
  3258. box-shadow: none;
  3259. text-align: left;
  3260. padding: 0px;
  3261. opacity: 0.8;
  3262. height: 20px;
  3263. margin-bottom: 10px;
  3264. }
  3265. #target-base-design {
  3266. background: none;
  3267. box-shadow: none;
  3268. text-align: left;
  3269. padding: 0px;
  3270. opacity: 0.4;
  3271. height: 20px;
  3272. margin-bottom: 20px;
  3273. font-size: 8px;
  3274. }
  3275. #action-tab {
  3276. display: flex;
  3277. flex-direction: row;
  3278. justify-content: space-around;
  3279. height: 40px;
  3280. margin: 0 -15px -10px;
  3281. overflow-x: visible;
  3282. background: rgba(0, 0, 0, 0.1);
  3283. }
  3284. #action-tab > button {
  3285. width: 40px;
  3286. background: none;
  3287. border: none;
  3288. color: #eee;
  3289. filter: drop-shadow(2px 2px 0px rgba(0, 0, 0, 0.1));
  3290. font-size: 16px;
  3291. cursor: pointer;
  3292. }
  3293. #useful-info {
  3294. display: flex;
  3295. flex-wrap: wrap;
  3296. flex-direction: column;
  3297. align-items: flex-start;
  3298. height: 50px;
  3299. margin-top: 10px;
  3300. font-size: 14px;
  3301. }
  3302.  
  3303. #switch-ses {
  3304. display: flex;
  3305. }
  3306. #switch-ses select {
  3307. display: block;
  3308. width: 85%;
  3309. margin: 0px 10px 0 0;
  3310. box-shadow: 0px 0px 5px 5px rgba(0, 0, 0, 0.1);
  3311. }
  3312. #switch-ses button {
  3313. background: none;
  3314. box-shadow: unset;
  3315. border: 0px;
  3316. color: white;
  3317. cursor: pointer;
  3318. width: 40px;
  3319. font-size: 20px;
  3320. }
  3321.  
  3322. .more-title {
  3323. display: flex;
  3324. flex-direction: row;
  3325. justify-content: space-between;
  3326. align-items: stretch;
  3327. margin: 20px -15px 10px;
  3328. padding: 5px 15px 10px;
  3329. background: rgba(0, 0, 0, 0.2);
  3330. height: 50px;
  3331. }
  3332. .more-title:first-child {
  3333. margin: -15px -15px 10px;
  3334. }
  3335. #socket-info {
  3336. display: flex;
  3337. align-items: baseline;
  3338. gap: 12px;
  3339. }
  3340. .more-title > * {
  3341. margin: 0;
  3342. }
  3343. #clone-status > p {
  3344. position: relative;
  3345. margin: 10px 0 0;
  3346. }
  3347.  
  3348. #heat-range, #scene-alpha-range {
  3349. display: flex;
  3350. margin: 10px 0;
  3351. }
  3352. #heat-range input[type="number"], #scene-alpha-range input[type="number"] {
  3353. width: 26%;
  3354. }
  3355. #heat-range input[type="range"], #scene-alpha-range input[type="range"] {
  3356. margin: 10px;
  3357. box-shadow: none;
  3358. }
  3359. `;
  3360. let styles = document.createElement("style");
  3361. styles.type = "text/css";
  3362. styles.appendChild(document.createTextNode(css));
  3363. document.head.appendChild(styles);
  3364.  
  3365. window.getClass = (DOMClass) => {
  3366. return document.getElementsByClassName(DOMClass);
  3367. };
  3368.  
  3369. window.getId = (DOMId) => {
  3370. return document.getElementById(DOMId);
  3371. };
  3372.  
  3373. const getClass = window.getClass;
  3374. const getId = window.getId;
  3375.  
  3376. /* @IntroJsStyles */
  3377. document.querySelector("#hud-intro > div.hud-intro-wrapper > div > div").removeChild(document.querySelector("#hud-intro > div.hud-intro-wrapper > div > div > button"));
  3378.  
  3379. getClass("hud-intro-corner-top-left")[0].insertAdjacentHTML("afterbegin", `
  3380. <div>
  3381. <label>
  3382. <input type="checkbox" id="useSes">
  3383. <span>Session Mode</span>
  3384. </label>
  3385. <label>
  3386. <input type="checkbox" id="shouldUseOptimization">
  3387. <span>Enhanced Optimization</span>
  3388. </label>
  3389. </div>
  3390. `);
  3391. document.querySelector(".hud-intro-corner-top-left > div").insertAdjacentElement("beforeend", document.querySelector("#hud-intro > div.hud-intro-wrapper > div > div > label"));
  3392.  
  3393. document.querySelector("#hud-intro").setAttribute("style", "--bg-image: url('https://cdn.glitch.global/ba7f4151-2a49-416a-985b-56301606ae3d/BG_eden_append_light.webp?v=1717285760533');");
  3394. document.querySelector("#hud-intro").insertAdjacentHTML("afterbegin", `
  3395. <div id="intro-animation">
  3396. <canvas id="background-canvas"></canvas>
  3397. <img src="https://cdn.glitch.global/ba7f4151-2a49-416a-985b-56301606ae3d/eto_large.png?v=1717285769725" />
  3398. <canvas id="foreground-canvas"></canvas>
  3399. </div>
  3400. `);
  3401. document.querySelector("#hud-intro").insertAdjacentHTML("beforeend", `
  3402. <div id="start-btn">
  3403. <h1>Play</h1>
  3404. <hr />
  3405. <h2>Click to play</h2>
  3406. </div>
  3407. <div id="hud-intro-overlay">
  3408. <div id="loading-div">
  3409. <span class="hud-loading"></span>
  3410. <a href="javascript:void(0);" onclick="game.ui.components.Intro.hideLoadingScreen();">Click to return</a>
  3411. </div>
  3412. </div>
  3413. `);
  3414. document.getElementsByClassName('hud-party-tag')[0].setAttribute('maxlength', 49);
  3415. document.getElementsByClassName('hud-intro-name')[0].setAttribute('maxlength', 29);
  3416.  
  3417. const allLines = {};
  3418. function createLines(linesOnScreen) {
  3419. // if (Object.keys(allLines).length >= linesOnScreen) return;
  3420. for (const lineId in allLines) {
  3421. const line = allLines[lineId];
  3422. if (line.x < -line.length) delete allLines[lineId];
  3423. };
  3424. for (let i = 0; i < (linesOnScreen - Object.keys(allLines).length); i++) {
  3425. const rctx = ["background-canvas", "foreground-canvas"][Math.floor(Math.random() * 2)];
  3426. const rLineLength = getRandomArbitrary(50, 400);
  3427. const rPosY = getRandomArbitrary(50, window.innerHeight - 50);
  3428. const rSpeed = getRandomArbitrary(20, 50);
  3429. const rTimeout = getRandomArbitrary(20, 5000);
  3430.  
  3431. allLines[genUUID()] = {x: window.innerWidth, y: rPosY, length: rLineLength, speed: rSpeed, ctxId: rctx, timeout: rTimeout, shouldTimeout: true};
  3432. };
  3433. };
  3434.  
  3435. function drawLine() {
  3436. for (const lineId in allLines) {
  3437. const line = allLines[lineId];
  3438. // console.log(line);
  3439.  
  3440. // setTimeout(() => {
  3441. const ctx = getId(line.ctxId).getContext("2d");
  3442. ctx.strokeStyle = "White";
  3443. ctx.lineCap = "round";
  3444. ctx.lineWidth = 5;
  3445.  
  3446. ctx.beginPath();
  3447. ctx.moveTo(line.x, line.y);
  3448. ctx.lineTo(line.x + line.length, line.y);
  3449. ctx.stroke();
  3450. line.shouldTimeout = false;
  3451. // }, line.shouldTimeout ? line.timeout : 0);
  3452. };
  3453. }
  3454.  
  3455. function moveLine(lineIndex) {
  3456. for (const lineId in allLines) {
  3457. allLines[lineId].x -= allLines[lineId].speed;
  3458. };
  3459. }
  3460.  
  3461. let drawLoopId;
  3462. function drawLoop() {
  3463. const linesOnScreen = 5;
  3464. createLines(linesOnScreen);
  3465.  
  3466. const background = getId("background-canvas");
  3467. const bctx = background.getContext("2d");
  3468. bctx.clearRect(0, 0, background.width, background.height);
  3469.  
  3470. const foreground = getId("foreground-canvas");
  3471. const fctx = foreground.getContext("2d");
  3472. fctx.clearRect(0, 0, foreground.width, foreground.height);
  3473.  
  3474. moveLine();
  3475. drawLine();
  3476.  
  3477. drawLoopId = requestAnimationFrame(drawLoop);
  3478. }
  3479. drawLoopId = requestAnimationFrame(drawLoop);
  3480.  
  3481. game.network.addEnterWorldHandler((e) => {
  3482. if (!e.allowed) return game.ui.components.Intro.hideLoadingScreen();
  3483. cancelAnimationFrame(drawLoopId);
  3484. });
  3485.  
  3486. function resizeIntroCanvases() {
  3487. const background = getId("background-canvas");
  3488. background.width = window.innerWidth;
  3489. background.height = window.innerHeight;
  3490.  
  3491. const foreground = getId("foreground-canvas");
  3492. foreground.width = window.innerWidth;
  3493. foreground.height = window.innerHeight;
  3494. };
  3495. resizeIntroCanvases();
  3496. window.addEventListener("resize", resizeIntroCanvases);
  3497.  
  3498. // game.ui.components.Intro.submitElem = getId("start-btn");
  3499. game.ui.components.Intro.hideLoadingScreen = function() {
  3500. getId("hud-intro-overlay").style.display = "none";
  3501. getId("hud-intro-overlay").style.opacity = 0;
  3502. getId("loading-div").style.display = "none";
  3503. };
  3504. game.ui.components.Intro.showLoadingScreen = function() {
  3505. getId("select-session-add").style.display = "none";
  3506. getId("endpoint-add-menu").style.display = "none";
  3507. getId("session-add-menu").style.display = "none";
  3508.  
  3509. getId("hud-intro-overlay").style.display = "flex";
  3510. getId("hud-intro-overlay").style.opacity = 1;
  3511. getId("loading-div").style.display = "flex";
  3512. };
  3513.  
  3514. game.ui.components.Intro.onSubmitClick = function () {
  3515. const realNicknameLength = new Blob([this.nameInputElem.value]).size;
  3516. if (realNicknameLength > 29) return void game.ui.components.Intro.onConnectionError('Your nickname length is too long. Please shorten it/use less special characters.');
  3517. const server = this.ui.getOption(`servers`)[this.serverElem.value];
  3518. localStorage.setItem(`name`, this.nameInputElem.value.trim());
  3519. this.connecting || (
  3520. this.connecting = true,
  3521. getId("hud-intro-overlay").style.display = "flex",
  3522. getId("hud-intro-overlay").style.opacity = 1,
  3523. getId("loading-div").style.display = "flex",
  3524. this.connectionTimer = setTimeout(() => {
  3525. const _this = game.ui.components.Intro;
  3526. _this.connecting = false;
  3527. game.network.disconnect();
  3528. _this.hideLoadingScreen();
  3529. _this.serverElem?.classList.add('has-error');
  3530. _this.errorElem.style.display = 'block';
  3531. _this.errorElem.innerText = `We failed to join the game - this is a known issue with anti-virus software. Please try disabling any web filtering features.`;
  3532. }, 15000),
  3533. this.errorElem.style.display = `none`,
  3534. this.ui.setOption(`nickname`,this.nameInputElem.value.trim()),
  3535. this.ui.setOption(`serverId`, this.serverElem.value),
  3536. game.network.connect(server)
  3537. );
  3538. }
  3539. getId("start-btn").onclick = game.ui.components.Intro.onSubmitClick.bind(game.ui.components.Intro);
  3540.  
  3541. game.ui.components.Intro.onEnterWorld = function (data) {
  3542. this.connecting = false;
  3543. if (this.connectionTimer) {
  3544. clearInterval(this.connectionTimer);
  3545. delete this.connectionTimer;
  3546. }
  3547. if (!data.allowed) {
  3548. _this.hideLoadingScreen();
  3549. this.serverElem.classList.add('has-error');
  3550. this.errorElem.style.display = 'block';
  3551. this.errorElem.innerText = 'This server is currently full. Please try again later or select another server.';
  3552. return;
  3553. }
  3554. this.hide();
  3555. };
  3556.  
  3557. game.ui.components.Intro.onConnectionError = function (errorText) {
  3558. errorText ||= `We were unable to connect to the gameserver. Please try another server.`;
  3559. this.connecting = false;
  3560. this.connectionTimer && (
  3561. clearInterval(this.connectionTimer),
  3562. delete this.connectionTimer
  3563. );
  3564. this.hideLoadingScreen();
  3565. this.serverElem.classList.add('has-error');
  3566. this.errorElem.style.display = 'block';
  3567. this.errorElem.innerText = errorText;
  3568. };
  3569.  
  3570. document.addEventListener('keyup', function(e) {
  3571. if (document.activeElement.tagName.toLowerCase() !== "input" && document.activeElement.tagName.toLowerCase() !== "textarea") {
  3572. if (e.code == 'Escape') {
  3573. game.ui.components.Intro.hideLoadingScreen();
  3574. };
  3575. if (e.key == "Enter") {
  3576. (game.ui?.playerTick?.dead === 1) && game.ui.components.Chat.startTyping();
  3577. };
  3578. if (e.key == ";") {
  3579. game.ui.getPlayerPetUid() && Game.currentGame.network.sendRpc({name: "DeleteBuilding", uid: game.ui.getPlayerPetUid()});
  3580. }
  3581. if (e.key == "'") {
  3582. if (game.ui.getPlayerPetUid()) {
  3583. game.network.sendRpc({name: "BuyItem", itemName: "PetRevive", tier: 1});
  3584. game.network.sendRpc({name: "EquipItem", itemName: "PetRevive", tier: 1});
  3585. };
  3586. };
  3587. if (e.code == 'KeyC' && !e.ctrlKey) {
  3588. setTimeout(() => {
  3589. document.querySelector('#joinWithPsk').style.display = 'block';
  3590. document.querySelector('#joinWithPsk').focus();
  3591. document.querySelector('#joinWithPsk').value = "";
  3592. }, 100);
  3593. }
  3594. };
  3595. });
  3596.  
  3597. /* @Misc. */
  3598. getId('hud').insertAdjacentHTML('beforeend', `
  3599. <input id="joinWithPsk" type="tel" placeholder="insert PSK..." class="btn">
  3600. `);
  3601. document.querySelector('#joinWithPsk').addEventListener('keyup', (e) => {
  3602. if (e.key == "Enter" || e.key == "Escape") {
  3603. e.target.style.display = 'none';
  3604. e.key == "Enter" && game.network.sendRpc({name: "JoinPartyByShareKey", partyShareKey: e.target.value});
  3605. };
  3606. });
  3607.  
  3608. document.querySelector("#hud-resources").appendChild(getId("hud-shield-bar"));
  3609. document.querySelector("#hud-resources").appendChild(getId("hud-health-bar"));
  3610.  
  3611. document.querySelector("#hud-respawn > div > div > div").insertAdjacentHTML("afterbegin", `
  3612. <div id="respawn-text-div" style="display: flex;flex-direction: column;flex-wrap: wrap;width: fit-content;padding: 0 10px;opacity: 0.7;align-items: flex-start;"></div>
  3613. <button class="hud-respawn-btn" id="hud-spectate-btn">Spectate</button>
  3614. `);
  3615.  
  3616. game.ui.components.Respawn.respawnTextElem = getId("respawn-text-div");
  3617. game.ui.components.Respawn.onPlayerDeath = function (deadResponse) {
  3618. window.deadPos = game.ui.playerTick.position;
  3619. const player = Game.currentGame.world.getEntityByUid(Game.currentGame.world.getMyUid()),
  3620. playerTick = player.getTargetTick();
  3621. this.lastTick = playerTick;
  3622. this.respawnTextElem.innerHTML = `<li>Wave: ` + playerTick.wave + `</li><li>Score: ` + playerTick.score.toLocaleString() + `</li><li>Leaderboard: #` + (game.ui.components.Leaderboard.leaderboardData.find(e => e.uid == game.world.myUid).rank + 1) + `</li>`;
  3623. this.show();
  3624. }
  3625. game.network.addRpcHandler("Dead", game.ui.components.Respawn.onPlayerDeath.bind(game.ui.components.Respawn));
  3626.  
  3627. /* @ModMenuJsStyles */
  3628. getId('hud-menu-settings').innerHTML = `
  3629. <a class="hud-menu-close" onclick="getId('hud-menu-settings').style.display = 'none';"></a>
  3630. <h3>Advanced</h3>
  3631. <div class="hud-menu-tabs">
  3632. <a class="hud-menu-tabs-link" data-menu="0">Build</a>
  3633. <a class="hud-menu-tabs-link" data-menu="1">Player</a>
  3634. <a class="hud-menu-tabs-link" data-menu="2">WS & Raid</a>
  3635. <a class="hud-menu-tabs-link" data-menu="3">Visual</a>
  3636. <a class="hud-menu-tabs-link" data-menu="4">Misc.</a>
  3637. </div>
  3638. <div class="hint-controls"></div>
  3639. <div class="hud-settings-grid" page="0"></div>
  3640. `;
  3641.  
  3642. getClass('hud-settings-grid')[0].innerHTML = `
  3643. <div class="hud-settings-page" id="page0">
  3644. <div class="hud-settings-options"></div>
  3645. <div class="hud-settings-more"></div>
  3646. </div>
  3647. <div class="hud-settings-page" id="page1">
  3648. <div class="hud-settings-options"></div>
  3649. <div class="hud-settings-more"></div>
  3650. </div>
  3651. <div class="hud-settings-page" id="page2">
  3652. <div class="hud-settings-options"></div>
  3653. <div class="hud-settings-more"></div>
  3654. </div>
  3655. <div class="hud-settings-page" id="page3">
  3656. <div class="hud-settings-options"></div>
  3657. <div class="hud-settings-more"></div>
  3658. </div>
  3659. <div class="hud-settings-page" id="page4">
  3660. <div class="hud-settings-options"></div>
  3661. <div class="hud-settings-more"></div>
  3662. </div>
  3663. `;
  3664.  
  3665. const hint_enum = {
  3666. 0: `<li><strong>Shift + 1</strong> [!] toggles Wall Block.</li>
  3667. <li><strong>Comma</strong> [,] toggles Rebuilder.</li>
  3668. <li><strong>Period</strong> [.] toggles Auto Upgrade.</li>`,
  3669.  
  3670. 1: `<li><strong>Shift-click</strong> on the minimap to navigate.</li>
  3671. <li><strong>Equal</strong> [=] toggles Auto Bow.</li>
  3672. <li><strong>C</strong> toggles quick join via PSK input.</li>
  3673. <li><strong>G</strong> toggles zoom menu.</li>
  3674. <li><strong>Dash</strong> [-] toggles local info indicators.</li>
  3675. <li><strong>Semi-colon</strong> [;] deletes your pet.</li>
  3676. <li><strong>Back-tick</strong> ['] revives your pet.</li>`,
  3677. 2: ``,
  3678.  
  3679. 3: /*`<li><strong>?</strong> toggles Screenshot Mode.</li>
  3680. <li><strong>~</strong> marks your position.</li>
  3681. <li><strong>+</strong> toggles Map Inspector.</li>`*/``,
  3682. 4: ``,
  3683. };
  3684.  
  3685. function refreshMore(page) {
  3686. const container = document.querySelector("#" + page + " > div.hud-settings-more");
  3687. for (let children of container.children) {
  3688. children.style.display = "none";
  3689. }
  3690. }
  3691.  
  3692. function refreshPage() {
  3693. for (let i = 0; i < getClass('hud-settings-grid')[0].children.length; i++) getId(`page${i}`).style.display = "none";
  3694. };
  3695.  
  3696. function setPage(page) {
  3697. const lastPage = parseInt(getClass('hud-settings-grid')[0].getAttribute('page'));
  3698.  
  3699. refreshPage();
  3700.  
  3701. getClass("hud-menu-tabs")[0].children[lastPage].classList.remove("is-active");
  3702. getClass("hud-menu-tabs")[0].children[page].classList.add("is-active");
  3703.  
  3704. getId(`page${page}`).style.display = "flex";
  3705. getClass('hint-controls')[0].innerHTML = hint_enum[page];
  3706. getClass('hud-settings-grid')[0].setAttribute('page', page);
  3707. };
  3708. setPage('0');
  3709. Array.from(getClass("hud-menu-tabs")[0].children).forEach((e) => {
  3710. e.onclick = () => { setPage(e.getAttribute("data-menu")); };
  3711. });
  3712.  
  3713. const menu = {
  3714. page0: {
  3715. AHRC: {
  3716. name: `AHRC`,
  3717. description: `Automatically harvests resources.`,
  3718. more: {
  3719. html: `
  3720. <p>AHRC type: </p>
  3721. <select id="ahrcOptions">
  3722. <option value="ch" selected>All</option>
  3723. <option value="h">Harvest</option>
  3724. <option value="c">Collect</option>
  3725. </select>
  3726. <br><br>
  3727. <span>The <strong>All</strong> option is both Harvest + Collect.</span>
  3728. `,
  3729. functions: () => {},
  3730. },
  3731. },
  3732. wallBlock: {
  3733. name: `Defense Block`,
  3734. description: `Allows you to place mulitple defenses at once.`,
  3735. more: {
  3736. html: `
  3737. <p>Block width: </p>
  3738. <select id="blockX" class="btn">
  3739. ${[3, 5, 7, 9, 11, 13, 15].map(size => {
  3740. return `<option value="${size}" ${size == 5 ? "selected" : ""}>${size} blocks</option>`;
  3741. }).join("\n")}
  3742. </select>
  3743. <br><br>
  3744. <p>Block height: </p>
  3745. <select id="blockY" class="btn">
  3746. ${[3, 5, 7, 9, 11, 13, 15].map(size => {
  3747. return `<option value="${size}" ${size == 5 ? "selected" : ""}>${size} blocks</option>`;
  3748. }).join("\n")}
  3749. </select>
  3750. <br><br>
  3751. <p>Type of defense: </p>
  3752. <select id="defense-select" class="btn">
  3753. <option value="Wall" selected>Wall</option>
  3754. <option value="Door">Door</option>
  3755. </select>
  3756. <br><br>
  3757. <span>Default value is 5x5, maximum is 15x15 (cells).</span>
  3758. `,
  3759. functions: () => {
  3760. getId("blockX").onchange = () => { game.script.wallBlock.wallElem.setAttribute("data-tier", `${getId("blockX").value}x${getId("blockY").value}`); };
  3761. getId("blockY").onchange = () => { game.script.wallBlock.wallElem.setAttribute("data-tier", `${getId("blockX").value}x${getId("blockY").value}`); };
  3762. getId("defense-select").onchange = ({target}) => {
  3763. game.script.wallBlock.typeOfDefense = target.value;
  3764. game.script.wallBlock.wallElem.setAttribute("data-building", target.value);
  3765. };
  3766. }
  3767. },
  3768. onCallback: () => {
  3769. game.script.wallBlock.wallElem.style.display = "block";
  3770. },
  3771. offCallback: () => {
  3772. game.script.wallBlock.wallElem.style.display = "none";
  3773. },
  3774. },
  3775. autoTrap: {
  3776. name: `Auto Trap`,
  3777. description: `Automatically traps players with wall blocks.`,
  3778. more: {
  3779. html: `
  3780. <p>Should trap: </p>
  3781. <select id="autoTrapOptions" class="btn">
  3782. <option value="pl" selected>Non-party members</option>
  3783. <option value="al">All players</option>
  3784. </select>
  3785. <br><br>
  3786. <span>Each block is always 7x7.</span>
  3787. `,
  3788. functions: () => {}
  3789. },
  3790. },
  3791. rebuild: {
  3792. name: `Auto Rebuild`,
  3793. description: `Automatically rebuilds dead towers and upgrades them.`,
  3794. more: {
  3795. html: `
  3796. <p>Rebuild to tier: </p>
  3797. <select id="rebuilderTierOptions" class="btn">
  3798. <option value="current" selected>Current</option>
  3799. ${[1, 2, 3, 4, 5, 6, 7, 8].map(tier => {
  3800. return `<option value="tier-${tier}">Tier ${tier}</option>`;
  3801. }).join("\n")}
  3802. </select>
  3803. <br><br>
  3804. <span>By behaviour, if the previously destroyed tower has a lower tier than the selected tier, it will be rebuilt to the old tier.</span>
  3805. `,
  3806. functions: () => {
  3807. const tierEnum = {
  3808. 'current': null,
  3809. 'tier-1': 1,
  3810. 'tier-2': 2,
  3811. 'tier-3': 3,
  3812. 'tier-4': 4,
  3813. 'tier-5': 5,
  3814. 'tier-6': 6,
  3815. 'tier-7': 7,
  3816. 'tier-8': 8
  3817. };
  3818. getId("rebuilderTierOptions").onchange = function({target}) {
  3819. game.script.rebuild.shouldRebuildToTier = tierEnum[target.value];
  3820. };
  3821. },
  3822. },
  3823. onCallback: () => {
  3824. for (let i in Game.currentGame.ui.buildings) {
  3825. const building = Game.currentGame.ui.buildings[i];
  3826. game.script.rebuild.savedBase[building.type] ||= {};
  3827. game.script.rebuild.savedBase[building.type][building.x] ||= {};
  3828. game.script.rebuild.savedBase[building.type][building.x][building.y] = building.tier;
  3829. }
  3830. },
  3831. offCallback: () => {
  3832. game.script.rebuild.savedBase = {};
  3833. game.script.rebuild.toBeReplaced = {};
  3834. game.script.rebuild.toBeUpgraded = {};
  3835. },
  3836. },
  3837. autoUpgrade: {
  3838. name: `Auto Upgrader`,
  3839. description: `Automatically upgrades towers to maximum tier.`,
  3840. more: null,
  3841. onCallback: () => {
  3842. for (let building of Object.values(game.ui.buildings)) {
  3843. if (building.tier < 8) {
  3844. game.script.autoUpgrade.autoUpgradeList[building.uid] = true;
  3845. }
  3846. }
  3847. },
  3848. offCallback: () => {
  3849. game.script.autoUpgrade.autoUpgradeList = {};
  3850. }
  3851. },
  3852. AULHT: {
  3853. name: `AULHT`,
  3854. description: `Automatically upgrades low-health towers.`,
  3855. },
  3856. autoBuild: {
  3857. name: "Auto Builder",
  3858. description: `Automatically builds a base when placing stash.`,
  3859. },
  3860. baseSaver: {
  3861. name: "Base Saver",
  3862. description: `Manage all your saved bases here.`,
  3863. more: {
  3864. html: `
  3865. <div id="base-container"></div>
  3866. <div id="base-management" style="display: none;">
  3867. <div id="action-tab">
  3868. <button id="return-to-manager"><i class="fa-solid fa-chevron-left"></i></button>
  3869. <button id="save-config" onclick="window.saveCurrentBaseConfig();"><i class="fa-solid fa-floppy-disk"></i></button>
  3870. <button id="encode-target-design"><i class="fa-solid fa-code"></i></button>
  3871. <button id="view-target-design"><i class="fa-solid fa-eye"></i></button>
  3872. <button id="build-design"><i class="fa-solid fa-hammer"></i></button>
  3873. <button id="clear-target-design"><i class="fa-solid fa-trash-can"></i></button>
  3874. </div>
  3875. <br><h2>Info</h2><hr />
  3876. <input id="target-base-name" type="tel" placeholder="Base name" class="btn" maxlength="20">
  3877. <input id="target-base-description" type="tel" placeholder="Base description" class="btn" maxlength="40">
  3878. <input id="target-base-design" type="tel" placeholder="Base string" class="btn">
  3879. <div id="useful-info"></div>
  3880. <label>
  3881. <input type="checkbox" id="shouldBuildBase">
  3882. <span>Set default for Auto Builder</span>
  3883. </label>
  3884. </div>
  3885. `,
  3886. functions: () => {
  3887. localStorage.totalSlots ||= 2;
  3888. getId("return-to-manager").onclick = () => document.querySelector("#more-baseSaver").click();
  3889. localStorage.baseslot0 = `3,0,-96,0;3,-96,0,0;3,0,-192,0;3,-96,-240,0;3,-192,0,0;3,-240,-96,0;4,-336,-96,0;4,-432,-288,0;4,-96,-336,0;4,-288,-432,0;8,-192,-384,0;8,-384,-192,0;8,-288,-192,0;8,-192,-192,0;8,-192,-288,0;8,-288,-288,0;8,-384,-384,0;8,-96,-96,0;7,-288,0,0;7,-384,0,0;7,-432,-96,0;7,0,-288,0;7,0,-384,0;7,-96,-432,0;0,-168,-504,0;0,-216,-504,0;0,-264,-552,0;0,-312,-552,0;0,-312,-504,0;0,-504,-216,0;0,-504,-168,0;0,-552,-264,0;0,-552,-312,0;0,-504,-312,0;1,-360,-456,0;1,-456,-360,0;9,96,-96,0;9,-96,96,0;|Lucky's 1P corner farm base|Can be changed for current session|default`;
  3890.  
  3891. window.isSlotEmpty = function(index) {
  3892. const baseData = localStorage[`baseslot${index}`]?.split("|");
  3893. return !!baseData?.[0];
  3894. };
  3895.  
  3896. window.createBaseSlot = function() {
  3897. const oldTotalSlots = parseInt(localStorage.totalSlots);
  3898. const nextItem = oldTotalSlots + 1;
  3899. localStorage.totalSlots = nextItem;
  3900. localStorage[`baseslot${nextItem}`] = '|||';
  3901. document.querySelector("#more-baseSaver").click();
  3902. };
  3903.  
  3904. window.saveCurrentBaseConfig = function() {
  3905. const [design, title, description, date] = [...document.querySelectorAll("#target-base-design, #target-base-name, #target-base-description"), new Date().toLocaleDateString()];
  3906. const baseManagement = getId('base-management');
  3907. const currentBaseItem = baseManagement.getAttribute('current-item');
  3908. localStorage[`baseslot${currentBaseItem}`] = `${design.value}|${title.value}|${description.value}|${date}`;
  3909. return void game.ui.components.PopupOverlay.showHint('Current base configuration saved.');
  3910. };
  3911. },
  3912. bind: () => {
  3913. const baseContainer = getId('base-container');
  3914. const baseManagement = getId('base-management');
  3915. baseContainer.innerHTML = '';
  3916. baseManagement.style.display = "none";
  3917.  
  3918. for (let i = 0; i < parseInt(localStorage.totalSlots) + 1; i++) {
  3919. const baseItem = document.createElement('div');
  3920. const baseData = localStorage[`baseslot${i}`]?.split("|");
  3921. const baseId = genUUID();
  3922.  
  3923. baseData?.[1] && (baseData[1] = window.filterXSS(baseData[1]));
  3924. baseData?.[2] && (baseData[2] = window.filterXSS(baseData[2]));
  3925.  
  3926. baseItem.classList.add('base-card');
  3927. baseItem.id = `base-item-${i}`;
  3928. baseItem.setAttribute('item-base', i);
  3929. baseItem.innerHTML = `
  3930. <strong></strong>
  3931. <span style="color: rgba(255, 255, 255, 0.4);font-size: 13px;display: flex;"></span>
  3932. <span style="color: rgba(255, 255, 255, 0.4);font-size: 13px;display: flex;justify-content: flex-end;transform: translate(0px, -40px);"></span>
  3933. `;
  3934.  
  3935. const [title, description, date] = baseItem.children;
  3936. title.innerText = baseData?.[1] || "Unoccupied";
  3937. description.innerText = baseData?.[2] || "-";
  3938. date.innerText = baseData?.[3] || "";
  3939.  
  3940. baseItem.onclick = function() {
  3941. const [titleField, descriptionField, designField] = [...document.querySelectorAll("#target-base-name, #target-base-description, #target-base-design")];
  3942. designField.value = baseData?.[0] || "";
  3943. titleField.value = baseData?.[1] || "";
  3944. descriptionField.value = baseData?.[2] || "";
  3945.  
  3946. getId("encode-target-design").onclick = game.script.builder.recordBase.bind(game.script.builder);
  3947. getId("view-target-design").onclick = () => game.script.builder.showOverlay(designField.value, 10000);
  3948.  
  3949. baseManagement.setAttribute('current-item', i);
  3950. for (let otherItem = 0; otherItem < parseInt(localStorage.totalSlots) + 1; otherItem++) {
  3951. const item = getId(`base-item-${otherItem}`);
  3952. const isThisItem = item.getAttribute('item-base') == i;
  3953. if (isThisItem) continue;
  3954. item.style.display = "none";
  3955. };
  3956.  
  3957. baseItem.style.transform = 'translate(0px, 306px)';
  3958. getId('add-base-slot').style.display = "none";
  3959. baseManagement.style.display = "block";
  3960.  
  3961. getId("build-design").onclick = function() {
  3962. game.ui.components.PopupOverlay.showConfirmation("Are you sure you want to build base?", 5000, function() {
  3963. game.script.builder.buildBase(designField.value);
  3964. });
  3965. };
  3966.  
  3967. const {wood, stone} = game.script.builder.calculateResourceNeeded(designField.value);
  3968. const neededPlayers = game.script.builder.calculateNeededPlayers(designField.value);
  3969. getId("useful-info").innerHTML = `
  3970. <li>Wood: ${wood}</li>
  3971. <li>Needed players: ${neededPlayers}</li>
  3972. <li>Stone: ${stone}</li>
  3973. `;
  3974.  
  3975. const autoBuildElem = getId("shouldBuildBase");
  3976. autoBuildElem.checked = sessionStorage[`base-item-${i}`] && sessionStorage[`base-item-${i}`] == "true";
  3977. autoBuildElem.onchange = function() {
  3978. if (autoBuildElem.checked == true) {
  3979. for (let otherItem = 0; otherItem < parseInt(localStorage.totalSlots) + 1; otherItem++) sessionStorage[`base-item-${otherItem}`] = false;
  3980. sessionStorage[`base-item-${i}`] = true;
  3981. game.script.autoBuild.defaultBase = designField.value;
  3982. }
  3983. };
  3984. };
  3985. baseContainer.appendChild(baseItem);
  3986. }
  3987. const addItem = document.createElement('div');
  3988. addItem.classList.add('base-card');
  3989. addItem.id = "add-base-slot";
  3990. addItem.innerHTML = `
  3991. <strong style="position: absolute;top: 20px;left: 40px;opacity: 0.4;"><i class="fas fa-plus"></i></strong>
  3992. <span style="color: rgba(255, 255, 255, 0.4);display: flex;justify-content: flex-end;position: absolute;left: 65px;top: 20px;">Add another base slot</span>
  3993. `;
  3994. addItem.onclick = window.createBaseSlot;
  3995. baseContainer.appendChild(addItem);
  3996. },
  3997. },
  3998. },
  3999. },
  4000. page1: {
  4001. autoAim: {
  4002. name: "Auto Aim",
  4003. description: "Automate attacks against enemies.",
  4004. more: {
  4005. html: `
  4006. <p>Aim for: </p>
  4007. <select id="autoAimOptions">
  4008. <option value="player" selected>Players</option>
  4009. <option value="zombie">Zombies</option>
  4010. <option value="zom/dem">Zombies/Demons</option>
  4011. <option value="all">All</option>
  4012. </select>
  4013. `,
  4014. },
  4015. },
  4016. autoHeal: {
  4017. name: "Auto Heal",
  4018. description: "Heals your player/pet automatically.",
  4019. more: {
  4020. html: `
  4021. <strong>Define the health percentage where the Auto Heal will kick in.</strong>
  4022. <span>Default value is 15%.</span>
  4023. <input id="auto-heal-threshold" type="number" placeholder="Enter a valid percentile here..." min="1" max="100" value="15" />
  4024. `,
  4025. functions: () => {},
  4026. }
  4027. },
  4028. autoRespawn: {
  4029. name: "Auto Respawn",
  4030. description: "Automatically respawns player upon death.",
  4031. },
  4032. spam: {
  4033. name: `Chat Spam`,
  4034. description: `Annoys other players with messages.`,
  4035. more: {
  4036. html: `
  4037. <strong>Input the text that you want to spam.</strong>
  4038. <span>If no text is inputted, random messages with be sent.</span>
  4039. <input id="chat-spam-input" placeholder="Spam text here..." />
  4040. `,
  4041. functions: () => {
  4042. const spamInputElem = getId("chat-spam-input");
  4043. spamInputElem.oninput = game.script.spam.onchange.bind(game.script.spam);
  4044. }
  4045. },
  4046. onCallback: () => { game.script.spam.start(); },
  4047. offCallback: () => { game.script.spam.stop(); },
  4048. },
  4049. movementCopy: {
  4050. name: `Movement Copy`,
  4051. description: `Copies the closest player's movement.`,
  4052. more: null,
  4053. offCallback: () => {
  4054. game.script.movementCopy.target = null;
  4055. },
  4056. },
  4057. },
  4058. page2: {
  4059. sessions: {
  4060. name: "Session Saver",
  4061. description: "Switch sockets on the fly.",
  4062. more: {
  4063. html: `
  4064. <div class="more-title">
  4065. <h2>Manage</h2>
  4066. <button id="refresh-ses" style="background: none;box-shadow: unset;border: 0px;color: white;cursor: pointer;"><i class="fa-solid fa-arrows-rotate"></i></button>
  4067. </div>
  4068. <div id="switch-ses">
  4069. <button id="switch-btn"><i class="fa-solid fa-repeat"></i></button>
  4070. </div>
  4071. `,
  4072. functions: () => {
  4073. let isInit = false;
  4074. game.network.addEnterWorldHandler(() => {
  4075. if (isInit) return;
  4076. isInit = true;
  4077.  
  4078. getId("switch-ses").insertBefore(getId("sesSelect"), getId("switch-btn"));
  4079. getId("switch-ses").insertAdjacentElement("afterend", getId("addBtn"));
  4080. getId("switch-ses").insertAdjacentElement("afterend", getId("delBtn"));
  4081. getId("switch-ses").insertAdjacentHTML("afterend", `<br>`);
  4082.  
  4083. getId("sesSelect").style.display = "block";
  4084. getId("delBtn").style.display = "inline-block";
  4085. getId("addBtn").style.display = "inline-block";
  4086. });
  4087. getId("refresh-ses").onclick = () => game.script.sessions.fetchSessions();
  4088. getId("switch-btn").onclick = () => {
  4089. if (!getId("useSes").checked) {
  4090. getId("useSes").checked = true;
  4091. getId("useSes").onchange();
  4092. };
  4093.  
  4094. game.network.disconnect();
  4095. game.network.connect();
  4096. };
  4097. },
  4098. },
  4099. },
  4100. cloneSockets: {
  4101. name: "Clones",
  4102. description: "Otherwise known as sockets, alts, etc.",
  4103. more: {
  4104. html: `
  4105. <div class="more-title">
  4106. <div id="socket-info">
  4107. <h2>Status</h2>
  4108. <span id="clone-amount">0 active</span>
  4109. </div>
  4110. <button id="toggle-status" style="background: none;box-shadow: unset;border: 0px;color: white;cursor: pointer;"><i class="fa-solid fa-chevron-up"></i></button>
  4111. </div>
  4112. <div id="clone-status" style="display: block;"><span>Nothing here yet...</span></div>
  4113.  
  4114. <div class="more-title"><h2>General</h2></div>
  4115. <label>
  4116. <input type="checkbox" id="alt-autoFill">
  4117. <span>Auto fill server</span>
  4118. </label>
  4119. <label>
  4120. <input type="checkbox" id="alt-randomizeName" checked>
  4121. <span>Use randomized names</span>
  4122. </label>
  4123. <p>Default socket type: </p>
  4124. <select id="socketTypeOptions" class="btn">
  4125. <option value="Multibox">Multibox</option>
  4126. <option value="Filler">Filler</option>
  4127. <option value="PlayerTrick">Player Trick</option>
  4128. <option value="AITO">AITO</option>
  4129. </select>
  4130. <div class="more-title"><h2>Multibox</h2></div>
  4131. <label>
  4132. <input type="checkbox" id="alt-control" checked>
  4133. <span>Control clones</span>
  4134. </label>
  4135. <p>Default movement type: </p>
  4136. <select id="movementTypeOptions" class="btn">
  4137. <option value="0">Copy</option>
  4138. <option value="1" selected>Mouse</option>
  4139. <option value="2">Lock</option>
  4140. <option value="3">Player</option>
  4141. </select>
  4142. `,
  4143. functions: () => {
  4144. getId("toggle-status").onclick = () => {
  4145. const cloneStatus = getId("clone-status");
  4146. getId("toggle-status").innerHTML = `<i class="fa-solid fa-chevron-${cloneStatus.style.display === "none" ? "up" : "down"}"></i>`;
  4147. cloneStatus.style.display = cloneStatus.style.display === "none" ? "block" : "none";
  4148. };
  4149. const observer = new MutationObserver((mutationsList) => {
  4150. for (const mutation of mutationsList) {
  4151. if (mutation.type == 'childList') {
  4152. getId("clone-status").firstChild.localName == "span" && getId("clone-status").removeChild(getId("clone-status").firstChild);
  4153. };
  4154. };
  4155. });
  4156. observer.observe(getId("clone-status"), { attributes: true, childList: true, subtree: true });
  4157.  
  4158. for (const option in game.script.sockets.shared.options) {
  4159. const toggleElem = getId("alt-" + option);
  4160. toggleElem.addEventListener("change", ({target}) => {
  4161. if (target.checked) {
  4162. game.script.sockets.shared.options[option].enabled = true;
  4163. game.script.sockets.shared.options[option]?.onCallback?.();
  4164. } else {
  4165. game.script.sockets.shared.options[option].enabled = false;
  4166. game.script.sockets.shared.options[option]?.offCallback?.();
  4167. };
  4168. });
  4169. }
  4170.  
  4171. getId("movementTypeOptions").onchange = ({target}) => {
  4172. for (const uuid in game.script.sockets.shared.all) {
  4173. const socket = game.script.sockets.shared.all[uuid];
  4174. if (socket.typeSpecificVariables.overrides && !socket.typeSpecificVariables.overrides.autoMove) {
  4175. socket.typeSpecificVariables.autoMove = parseInt(target.value);
  4176. };
  4177. };
  4178. };
  4179. },
  4180. },
  4181. isToggle: false,
  4182. customButtonText: "Send",
  4183. callback: () => {
  4184. const type = getId("socketTypeOptions").value;
  4185. game.script.sockets.createSocket(type);
  4186. },
  4187. },
  4188. },
  4189. page3: {
  4190. optimize: {
  4191. name: "Optimizers",
  4192. description: "Disables rendering features for better performance.",
  4193. more: {
  4194. html: `
  4195. <h2>Sprite refreshing</h2>
  4196. <label>
  4197. <input type="checkbox" id="zombieSprite" checked>
  4198. <span>Zombie sprites</span>
  4199. </label>
  4200. <label>
  4201. <input type="checkbox" id="towerSprite" checked>
  4202. <span>Tower sprites</span>
  4203. </label>
  4204. <label>
  4205. <input type="checkbox" id="projectileSprite" checked>
  4206. <span>Projectile sprites</span>
  4207. </label>
  4208. <h2>Other</h2>
  4209. <label>
  4210. <input type="checkbox" id="updateAnimation" checked>
  4211. <span>Update entity models</span>
  4212. </label>
  4213. `,
  4214. functions: () => {
  4215. for (const option in game.script.optimize) {
  4216. if (["background", "init"].indexOf(option) > -1) continue;
  4217. getId(option).addEventListener("change", ({target}) => {
  4218. game.script.optimize[option] = target.checked;
  4219. });
  4220. }
  4221. }
  4222. },
  4223. },
  4224. showAoe: {
  4225. name: "AOE Map",
  4226. description: "Shows the area of damage for all AOE towers.",
  4227. more: null,
  4228. },
  4229. stashIndicators: {
  4230. name: "Stash Indicators",
  4231. description: "Shows useful borders Gold Stash-related.",
  4232. more: null,
  4233. onCallback: () => {
  4234. const { indicators } = game.script.stashIndicators.currentIndicators;
  4235. for (const indicator of indicators) indicator.setVisible(true);
  4236. },
  4237. offCallback: () => {
  4238. const { indicators } = game.script.stashIndicators.currentIndicators;
  4239. for (const indicator of indicators) indicator.setVisible(false);
  4240. },
  4241. },
  4242. buildingLife: {
  4243. name: "Building Lifetime",
  4244. description: "Shows a heat map indicating buildings' lifespan.",
  4245. more: {
  4246. html: `
  4247. <strong>Limit the amount of towers to be indicated via heat map</strong>
  4248. <span>counting from most recently placed towers</span>
  4249. <div id="heat-range">
  4250. <input type="number" id="heat-min" min="0" value="0" disabled />
  4251. <input type="range" id="heat-slider" step="1" min="0" max="0" />
  4252. <input type="number" id="heat-max" min="0" value="0" disabled />
  4253. </div>
  4254. <div id="scene-alpha-range">
  4255. <input type="number" id="scene-alpha-val" value="0.5" disabled />
  4256. <input type="range" id="scene-alpha-slider" step="0.1" min="0" max="1" />
  4257. </div>
  4258. `,
  4259. functions: () => {
  4260. getId("heat-slider").addEventListener("input", ({target}) => {
  4261. game.script.buildingLife.startingIndex = target.valueAsNumber;
  4262. getId("heat-min").value = target.valueAsNumber;
  4263.  
  4264. clearTimeout(game.script.buildingLife.refreshTimeout);
  4265. game.script.buildingLife.refreshTimeout = setTimeout(() => {
  4266. game.script.buildingLife.refreshMap();
  4267. game.options.options.buildingLife && (
  4268. game.script.buildingLife.hideMap(),
  4269. game.script.buildingLife.showMap()
  4270. );
  4271. }, 50);
  4272. });
  4273. getId("scene-alpha-slider").addEventListener("input", ({target}) => {
  4274. getId("scene-alpha-val").value = target.valueAsNumber;
  4275. game.script.buildingLife.setSceneryAlpha(target.valueAsNumber);
  4276. });
  4277. },
  4278. },
  4279. onCallback: () => { game.script.buildingLife.showMap(); },
  4280. offCallback: () => { game.script.buildingLife.hideMap(); },
  4281. },
  4282. grouping: {
  4283. name: "Grouping Grid",
  4284. description: "Shows the grids of tower ranges' groups.",
  4285. more: null,
  4286. isToggle: false,
  4287. customButtonText: "Cycle",
  4288. callback: () => {
  4289. game.script.grouping.cycleGrid();
  4290. },
  4291. },
  4292. bossAlert: {
  4293. name: "Boss Alert",
  4294. description: "Alerts you before a boss wave.",
  4295. more: null,
  4296. },
  4297. },
  4298. page4: {},
  4299. };
  4300.  
  4301. const addFunctionToElem = ({ id, option, buttonText, colors, isToggle, callback, onCallback, offCallback }) => {
  4302. const options = game.options.options;
  4303. colors ||= 'btn-red?btn-theme';
  4304.  
  4305. getId(id).addEventListener('click', e => {
  4306. if (isToggle === false) {
  4307. callback?.();
  4308. } else {
  4309. let toggleColor = colors.split('?');
  4310. if (options[option] === false) {
  4311. options[option] = true;
  4312. toggleColor[1] && e.target.classList.remove(toggleColor[1]);
  4313. e.target.classList.add(toggleColor[0]);
  4314. buttonText === undefined || (e.target.innerText = `Disable ${buttonText}`);
  4315. onCallback?.();
  4316. } else {
  4317. options[option] = false;
  4318. e.target.classList.remove(toggleColor[0]);
  4319. toggleColor[1] && e.target.classList.add(toggleColor[1]);
  4320. buttonText === undefined || (e.target.innerText = `Enable ${buttonText}`);
  4321. offCallback?.();
  4322. }
  4323. };
  4324. });
  4325. };
  4326.  
  4327. /* @GeneralFunctions + Enums */
  4328. const towerCodes = ["Wall", "Door", "SlowTrap", "ArrowTower", "CannonTower", "MeleeTower", "BombTower", "MagicTower", "GoldMine", "Harvester"];
  4329. const allBossWaves = [9, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, 105, 121];
  4330.  
  4331. function bindTooltip(elem, innerHTML, anchor = 'top') {
  4332. elem.targetElem = elem;
  4333. elem.anchor = anchor;
  4334. elem.hide = function() { this.tooltipElem && (this.tooltipElem.remove(), delete this.tooltipElem); };
  4335. elem.targetElem.addEventListener('mouseenter', function() {
  4336. let toolTip = innerHTML;
  4337. document.body.insertAdjacentHTML(`beforeend`, toolTip);
  4338. this.tooltipElem = document.getElementById(`hud-tooltip`);
  4339.  
  4340. let clientRect = this.targetElem.getBoundingClientRect();
  4341. let position = {'left': 0, 'top': 0};
  4342. switch(this.anchor) {
  4343. case 'top':
  4344. position.left = clientRect.left + clientRect.width / 0x2 - this.tooltipElem.offsetWidth / 0x2;
  4345. position.top = clientRect.top - this.tooltipElem.offsetHeight - 0x14;
  4346. break;
  4347. case 'bottom':
  4348. position.left = clientRect.left + clientRect.width / 0x2 - this.tooltipElem.offsetWidth / 0x2;
  4349. position.top = clientRect.top + clientRect.height + 0x14;
  4350. break;
  4351. case 'left':
  4352. position.left = clientRect.left - this.tooltipElem.offsetWidth - 0x14;
  4353. position.top = clientRect.top + clientRect.height / 0x2 - this.tooltipElem.offsetHeight / 0x2;
  4354. break;
  4355. case 'right':
  4356. position.left = clientRect.left + clientRect.width + 0x14;
  4357. position.top = clientRect.top + clientRect.height / 0x2 - this.tooltipElem.offsetHeight / 0x2;
  4358. break;
  4359. }
  4360. this.tooltipElem.className = `hud-tooltip hud-tooltip-` + this.anchor;
  4361. this.tooltipElem.style.left = position.left + 'px';
  4362. this.tooltipElem.style.top = position.top + 'px';
  4363. this.tooltipElem.style.zIndex = "999";
  4364. });
  4365. elem.targetElem.addEventListener(`mouseleave`, elem.hide);
  4366. }
  4367.  
  4368. function inRange(pos, target, range) {
  4369. return pos < target + range && pos > target - range;
  4370. }
  4371.  
  4372. function getRandomArbitrary(min, max) {
  4373. return Math.random() * (max - min) + min;
  4374. }
  4375.  
  4376. function isPointInCircle(circle, point, radius) {
  4377. if ((point.x - circle.x)**2 + (point.y - circle.y)**2 <= radius**2) return true;
  4378. return false;
  4379. }
  4380.  
  4381. function genUUID() {
  4382. return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(
  4383. /[018]/g, c => (
  4384. c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4
  4385. ).toString(16)
  4386. );
  4387. };
  4388.  
  4389. function getRandomItem(array) {
  4390. return array[Math.floor(Math.random() * array.length)];
  4391. };
  4392.  
  4393. function msToTime(s) {
  4394.  
  4395. // Pad to 2 or 3 digits, default is 2
  4396. function pad(n, z) {
  4397. z = z || 2;
  4398. return ('00' + n).slice(-z);
  4399. }
  4400.  
  4401. var ms = s % 1000;
  4402. s = (s - ms) / 1000;
  4403. var secs = s % 60;
  4404. s = (s - secs) / 60;
  4405. var mins = s % 60;
  4406. var hrs = (s - mins) / 60;
  4407.  
  4408. return pad(hrs) + ':' + pad(mins) + ':' + pad(secs) + '.' + pad(ms, 3);
  4409. }
  4410.  
  4411. function hexToRgb(hex) {
  4412. var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  4413. if(result){
  4414. var r= parseInt(result[1], 16);
  4415. var g= parseInt(result[2], 16);
  4416. var b= parseInt(result[3], 16);
  4417. return [r, g, b];
  4418. }
  4419. return null;
  4420. };
  4421.  
  4422. function shuffleArray(array) {
  4423. for (let i = array.length - 1; i > 0; i--) {
  4424. const j = Math.floor(Math.random() * (i + 1));
  4425. const temp = array[i];
  4426. array[i] = array[j];
  4427. array[j] = temp;
  4428. };
  4429. return array;
  4430. }
  4431.  
  4432. function garbageGenerator(garbageLength = 25) {
  4433. let garbageCharacters = localStorage.literallyEveryUnicodeEver;
  4434. let garbage = "";
  4435. for (let i = 0; i < garbageLength; i++) garbage += garbageCharacters[Math.floor(Math.random() * garbageCharacters.length)];
  4436. return garbage;
  4437. }
  4438.  
  4439. function counter(e = 0) {
  4440. if (e <= -0.99949999999999999e24) {
  4441. return Math.round(e/-1e23)/-10 + "TT";
  4442. }
  4443. if (e <= -0.99949999999999999e21) {
  4444. return Math.round(e/-1e20)/-10 + "TB";
  4445. }
  4446. if (e <= -0.99949999999999999e18) {
  4447. return Math.round(e/-1e17)/-10 + "TM";
  4448. }
  4449. if (e <= -0.99949999999999999e15) {
  4450. return Math.round(e/-1e14)/-10 + "TK";
  4451. }
  4452. if (e <= -0.99949999999999999e12) {
  4453. return Math.round(e/-1e11)/-10 + "T";
  4454. }
  4455. if (e <= -0.99949999999999999e9) {
  4456. return Math.round(e/-1e8)/-10 + "B";
  4457. }
  4458. if (e <= -0.99949999999999999e6) {
  4459. return Math.round(e/-1e5)/-10 + "M";
  4460. }
  4461. if (e <= -0.99949999999999999e3) {
  4462. return Math.round(e/-1e2)/-10 + "K";
  4463. }
  4464. if (e <= 0.99949999999999999e3) {
  4465. return Math.round(e) + "";
  4466. }
  4467. if (e <= 0.99949999999999999e6) {
  4468. return Math.round(e/1e2)/10 + "K";
  4469. }
  4470. if (e <= 0.99949999999999999e9) {
  4471. return Math.round(e/1e5)/10 + "M";
  4472. }
  4473. if (e <= 0.99949999999999999e12) {
  4474. return Math.round(e/1e8)/10 + "B";
  4475. }
  4476. if (e <= 0.99949999999999999e15) {
  4477. return Math.round(e/1e11)/10 + "T";
  4478. }
  4479. if (e <= 0.99949999999999999e18) {
  4480. return Math.round(e/1e14)/10 + "TK";
  4481. }
  4482. if (e <= 0.99949999999999999e21) {
  4483. return Math.round(e/1e17)/10 + "TM";
  4484. }
  4485. if (e <= 0.99949999999999999e24) {
  4486. return Math.round(e/1e20)/10 + "TB";
  4487. }
  4488. if (e <= 0.99949999999999999e27) {
  4489. return Math.round(e/1e+23)/10 + "TT";
  4490. }
  4491. if (e >= 0.99949999999999999e27) {
  4492. return Math.round(e/1e+23)/10 + "TT";
  4493. }
  4494. }
  4495.  
  4496. const getClock = (_date) => {
  4497. let date = _date || new Date(),
  4498. d = date.getDate(),
  4499. d1 = date.getDay(),
  4500. h = date.getHours(),
  4501. m = date.getMinutes(),
  4502. s = date.getSeconds(),
  4503. session = "PM";
  4504.  
  4505. if (h == 2) h = 12;
  4506.  
  4507. if (h < 13) session = "AM"
  4508. if (h > 12) {
  4509. session = "PM";
  4510. h -= 12;
  4511. };
  4512.  
  4513. h = (h < 10) ? "0" + h : h;
  4514. m = (m < 10) ? "0" + m : m;
  4515. s = (s < 10) ? "0" + s : s;
  4516. return `${h}:${m} ${session}`;
  4517. }
  4518.  
  4519. const measureDistance = (obj1, obj2) => {
  4520. if (!(obj1.x && obj1.y && obj2.x && obj2.y)) return Infinity;
  4521. let xDif = obj2.x - obj1.x;
  4522. let yDif = obj2.y - obj1.y;
  4523. return Math.abs((xDif**2) + (yDif**2));
  4524. };
  4525.  
  4526. const getEntityAtPos = (x, y, width = 1, height = 1) => {
  4527. const cell = game.world.entityGrid.getCellIndexes(x, y, { width, height });
  4528. return game.world.entityGrid.getEntitiesInCell(cell);
  4529. }
  4530.  
  4531. const isEntityOccupied = (x, y, width = 1, height = 1) => {
  4532. const cell = game.world.entityGrid.getCellIndexes(x, y, { width, height });
  4533. const entity = game.world.entityGrid.getEntitiesInCell(cell);
  4534. return Object.keys(entity).length > 0;
  4535. }
  4536.  
  4537. const canAfford = (resources, costs, tier) => {
  4538. const { gold, wood, stone } = resources;
  4539. const goldCosts = costs.goldCosts[tier - 1];
  4540. const stoneCosts = costs.stoneCosts[tier - 1];
  4541. const woodCosts = costs.woodCosts[tier - 1];
  4542. return !(gold < goldCosts || wood < woodCosts || stone < stoneCosts);
  4543. }
  4544.  
  4545. const predictDirection = (lastPos, currentPos, acc = 2) => {
  4546. const anchors = {up: 0, down: 0, left: 0, right: 0};
  4547. if (!lastPos || !currentPos) return anchors;
  4548. if (acc > 100) acc = 100;
  4549. // limitation might be position changes in the slightest
  4550. // rounding numbers may help
  4551. const xDelta = lastPos.x - currentPos.x;
  4552. const yDelta = lastPos.y - currentPos.y;
  4553. xDelta < -acc ? (anchors.right = 1) : xDelta > acc && (anchors.left = 1);
  4554. yDelta < -acc ? (anchors.down = 1) : yDelta > acc && (anchors.up = 1);
  4555. return anchors;
  4556. };
  4557.  
  4558. const moveTowards = (a, b, acc = 24) => {
  4559. const packet = {down: 0, up: 0, left: 0, right: 0};
  4560.  
  4561. if (a.y - b.y <= acc) packet.down = 1;
  4562. if (-a.y + b.y <= acc) packet.up = 1;
  4563. if (-a.x + b.x <= acc) packet.left = 1;
  4564. if (a.x - b.x <= acc) packet.right = 1;
  4565.  
  4566. return packet;
  4567. };
  4568.  
  4569. function getIsNextWaveActive() {
  4570. let isNextWaveActive = false;
  4571. const allComingBossWaves = allBossWaves.map(wave => wave - 1);
  4572. for (let wave of allComingBossWaves) {
  4573. isNextWaveActive = game.ui.playerTick.wave == wave;
  4574. }
  4575. return isNextWaveActive;
  4576. };
  4577.  
  4578. class EventEmitter extends EventTarget {
  4579. constructor() {
  4580. super();
  4581. this._events = {};
  4582. };
  4583. on(event, callback, options) {
  4584. this._events[event] ||= [];
  4585. this._events[event].push(callback);
  4586. this.addEventListener(event, ({detail: data}) => {
  4587. callback(data);
  4588. }, options);
  4589. };
  4590. once(event, callback) {
  4591. this.on(event, callback, {once: true});
  4592. };
  4593. emit(event, data) {
  4594. const Event = new CustomEvent(event, { detail: data });
  4595. this.dispatchEvent(Event);
  4596. };
  4597. };
  4598.  
  4599. /* @CustomFunctions */
  4600. game.options.options = {
  4601. AHRC: false,
  4602. wallBlock: false,
  4603. rebuild: false,
  4604. autoTrap: false,
  4605. autoUpgrade: false,
  4606. AULHT: false,
  4607. autoBuild: false,
  4608. dragBox: false,
  4609.  
  4610. lockAim: false,
  4611. movementCopy: false,
  4612. spam: false,
  4613. autoHeal: true,
  4614. getRSS: false,
  4615. autoBow: false,
  4616. autoAim: false,
  4617. autoRespawn: false,
  4618.  
  4619. showAoe: false,
  4620. stashIndicators: false,
  4621. buildingLife: false,
  4622. bossAlert: true,
  4623.  
  4624. spectate: false,
  4625. navigator: false,
  4626. XKey: false,
  4627. };
  4628.  
  4629. game.script = {
  4630. AHRC: {
  4631. handlers: [{type: "entityUpdate", names: "onTick"}],
  4632. checkedHarvesters: new Set(),
  4633. workingHarvesters: new Set(),
  4634. excludedHarvesters: new Set(),
  4635. onTick: function() {
  4636. const options = game.options.options;
  4637. if (options.AHRC) {
  4638. for (let uid in game.world.entities) {
  4639. if (this.excludedHarvesters.has(parseInt(uid))) continue;
  4640. const entity = game.world.entities[uid];
  4641. if (entity.targetTick.model == "Harvester" && entity.targetTick.partyId == game.ui.playerPartyId && game.ui.playerTick.gold > 0.69) {
  4642. if (this.checkedHarvesters.has(uid)) {
  4643. if (entity.targetTick.stone != 0 || entity.targetTick.wood != 0) this.workingHarvesters.add(uid);
  4644. } else {
  4645. this.checkedHarvesters.add(uid);
  4646. game.network.sendRpc({
  4647. name: "AddDepositToHarvester",
  4648. uid: parseInt(uid),
  4649. deposit: 0.69
  4650. });
  4651. };
  4652. };
  4653. if (this.workingHarvesters.has(uid)) {
  4654. if (entity.targetTick.stone >= entity.targetTick.harvestMax || entity.targetTick.wood >= entity.targetTick.harvestMax) continue;
  4655. const amount = entity.fromTick.tier * 0.05 - 0.02;
  4656. const ahrcOptions = getId('ahrcOptions');
  4657. ahrcOptions.value !== "c" && game.network.sendRpc({name: "AddDepositToHarvester", uid: parseInt(uid), deposit: amount});
  4658. ahrcOptions.value !== "h" && game.network.sendRpc({name: "CollectHarvester", uid: parseInt(uid)});
  4659. };
  4660. };
  4661. };
  4662. },
  4663. },
  4664. wallBlock: {
  4665. handlers: [{type: "packetFunc", names: ["sendRpc", "onSendRpc", 9]}, {type: "keybind", names: "keyup"}],
  4666. wallElem: document.createElement("a"),
  4667. typeOfDefense: "Wall",
  4668. isEven: function(number) {
  4669. return number % 2 === 0;
  4670. },
  4671. placeWallBlock: function(blockWidth, blockHeight, data, offset) {
  4672. let offsetFromTarget,
  4673. isOffsetUsed = !!offset;
  4674. isOffsetUsed && (offsetFromTarget = 48 * offset);
  4675. for (let x =
  4676. -((blockWidth -
  4677. (this.isEven(blockWidth) ? 0 : 1)) / 2) * 48;
  4678. x <= (blockWidth -
  4679. (this.isEven(blockWidth) ? 0 : 1)) / 2 * 48;
  4680. x += 48) {
  4681. // if (isOffsetUsed && (Math.abs(x) <= offsetFromTarget)) continue;
  4682. for (let y =
  4683. -((blockHeight -
  4684. (this.isEven(blockHeight) ? 0 : 1)) / 2) * 48;
  4685. y <= (blockHeight -
  4686. (this.isEven(blockHeight) ? 0 : 1)) / 2 * 48;
  4687. y += 48) {
  4688. if (isOffsetUsed && Math.abs(y) <= offsetFromTarget && Math.abs(x) <= offsetFromTarget) continue;
  4689. const posX = data.x + x,
  4690. posY = data.y + y,
  4691. shouldPlace = !isEntityOccupied(posX, posY);
  4692. shouldPlace && (x !== 0 || y !== 0) && game.network.sendPacket(9, {name: "MakeBuilding", type: this.typeOfDefense, x: posX, y: posY, yaw: 0});
  4693. };
  4694. };
  4695. },
  4696. onSendRpc: function(data) {
  4697. if (data.name === "MakeBuilding" && data.type === this.typeOfDefense && game.options.options.wallBlock) {
  4698. if (!game.script.rebuild.savedBase?.[data.type]?.[data.x]?.[data.y]) {
  4699. const blockWidth = parseInt(document.querySelector('#blockX').value);
  4700. const blockHeight = parseInt(document.querySelector('#blockY').value);
  4701. this.placeWallBlock(blockWidth, blockHeight, data);
  4702. };
  4703. };
  4704. },
  4705. keyup: function(e) {
  4706. if (e.key == "!") getId("toggle-wallBlock").click();
  4707. },
  4708. init: function() {
  4709. this.wallElem.classList.add("hud-buff-bar-item");
  4710. this.wallElem.setAttribute("data-building", "Wall");
  4711. this.wallElem.style.display = "none";
  4712. this.wallElem.setAttribute("data-tier", `${getId("blockX").value}x${getId("blockY").value}`);
  4713. document.getElementsByClassName("hud-buff-bar")[0].appendChild(this.wallElem);
  4714. },
  4715. },
  4716. autoTrap: {
  4717. handlers: [{type: "entityUpdate", names: "onEntityUpdate"}],
  4718. onEntityUpdate: function() {
  4719. if (game.options.options.diep) {
  4720. for (let i of game.renderer.npcs.attachments) {
  4721. const criteria = document.querySelector("#autoTrapOptions").value == "pl" ? i.targetTick.partyId !== game.ui.playerPartyId : i.targetTick.uid !== game.world.myUid;
  4722. if (i.entityClass === "PlayerEntity" && criteria) {
  4723. if (isPointInCircle(i.targetTick.position, game.ui.playerTick.position, 500)) {
  4724. const position = i.targetTick.position;
  4725. const data = { x: Math.round(position.x / 24) * 24, y: Math.round(position.y / 24) * 24 };
  4726. game.script.wallBlock.placeWallBlock(7, 7, data, 1);
  4727. };
  4728. };
  4729. };
  4730. };
  4731. },
  4732. },
  4733. rebuild: {
  4734. handlers: [{type: "entityUpdate", names: "onEntityUpdate"}, {type: "rpc", names: ["LocalBuilding"]}, {type: "keybind", names: "keyup"}],
  4735. goldStashTier: null,
  4736. savedBase: {},
  4737. toBeReplaced: {},
  4738. toBeUpgraded: {},
  4739. shouldRebuildToTier: null,
  4740. LocalBuilding: function(buildings) {
  4741. const options = game.options.options;
  4742. const allBuildings = Object.values(Game.currentGame.ui.buildings);
  4743. this.goldStashTier = game.ui.components.BuildingOverlay.getGoldStashTier();
  4744.  
  4745. if (options.rebuild) {
  4746. for (let i in buildings) {
  4747. const building = buildings[i];
  4748. if (building.dead === 1) {
  4749. // The building has died
  4750. if (this.savedBase[building.type]?.[building.x]?.[building.y]) {
  4751. this.toBeReplaced[building.type] ||= {};
  4752. this.toBeReplaced[building.type][building.x] ||= {};
  4753. this.toBeReplaced[building.type][building.x][building.y] = true;
  4754. delete this.toBeUpgraded[building.uid];
  4755. }
  4756. } else {
  4757. // The building was upgraded/placed
  4758. if (this.savedBase[building.type]?.[building.x]?.[building.y] !== undefined) {
  4759. if (typeof this.toBeUpgraded[building.uid] === "number" && this.toBeUpgraded[building.uid] <= 1) {
  4760. this.toBeUpgraded[building.uid] = false;
  4761. } else if (this.toBeUpgraded[building.uid] === undefined) {
  4762. if (this.shouldRebuildToTier !== null && this.savedBase[building.type][building.x][building.y] > this.shouldRebuildToTier) {
  4763. this.toBeUpgraded[building.uid] = this.shouldRebuildToTier;
  4764. } else if (building.tier < this.savedBase[building.type][building.x][building.y]) {
  4765. this.toBeUpgraded[building.uid] = this.savedBase[building.type][building.x][building.y];
  4766. };
  4767. };
  4768. delete this.toBeReplaced[building.type]?.[building.x]?.[building.y];
  4769. }
  4770. }
  4771. }
  4772. }
  4773. },
  4774. onEntityUpdate: function({ entities }) {
  4775. const options = game.options.options;
  4776. if (options.rebuild && this.goldStashTier) {
  4777. for (let i in this.toBeReplaced) {
  4778. for (let x in this.toBeReplaced[i]) {
  4779. for (let y in this.toBeReplaced[i][x]) {
  4780. Game.currentGame.network.sendRpc({
  4781. name: "MakeBuilding",
  4782. type: i,
  4783. x: parseInt(x),
  4784. y: parseInt(y),
  4785. yaw: 0
  4786. });
  4787. }
  4788. }
  4789. }
  4790. for (let uid in this.toBeUpgraded) {
  4791. if (!(uid in entities)) {
  4792. delete this.toBeUpgraded[uid];
  4793. continue;
  4794. };
  4795. if (this.toBeUpgraded[uid] == false || this.toBeUpgraded[uid] <= 1) continue;
  4796. Game.currentGame.network.sendRpc({
  4797. name: "UpgradeBuilding",
  4798. uid: parseInt(uid)
  4799. });
  4800. this.toBeUpgraded[uid]--;
  4801. };
  4802. };
  4803. },
  4804. keyup: function(e) {
  4805. if (e.key == ",") getId("toggle-rebuild").click();
  4806. },
  4807. },
  4808. autoUpgrade: {
  4809. handlers: [{type: "entityUpdate", names: "onEntityUpdate"}, {type: "rpc", names: ["LocalBuilding"]}, {type: "keybind", names: "keyup"}],
  4810. autoUpgradeList: {},
  4811. goldStashTier: null,
  4812. LocalBuilding: function(buildings) {
  4813. const options = game.options.options;
  4814. this.goldStashTier = game.ui.components.BuildingOverlay.getGoldStashTier();
  4815. if (options.autoUpgrade) {
  4816. for (let i in buildings) {
  4817. const building = buildings[i];
  4818. if (building.dead !== 1) {
  4819. if (building.tier < 8) this.autoUpgradeList[building.uid] = true;
  4820. else delete this.autoUpgradeList[building.uid];
  4821. };
  4822. };
  4823. };
  4824. },
  4825. onEntityUpdate: function({entities}) {
  4826. const options = game.options.options;
  4827. if (options.autoUpgrade && this.goldStashTier) {
  4828. let resourcesClone = {
  4829. wood: game.ui.playerTick.wood,
  4830. stone: game.ui.playerTick.stone,
  4831. gold: game.ui.playerTick.gold
  4832. }
  4833.  
  4834. for (let i in this.autoUpgradeList) {
  4835. const building = game.ui.buildings[i];
  4836. if (building?.type !== "GoldStash" && building?.tier >= this.goldStashTier) continue;
  4837. if (!(i in game.world.entities)) continue;
  4838.  
  4839. const costs = game.ui.buildingSchema[building.type];
  4840. if (canAfford(resourcesClone, costs, building.tier + 1)) {
  4841. resourcesClone.wood -= costs.woodCosts[building.tier];
  4842. resourcesClone.stone -= costs.stoneCosts[building.tier];
  4843. resourcesClone.gold -= costs.goldCosts[building.tier];
  4844.  
  4845. game.network.sendRpc({name: "UpgradeBuilding", uid: parseInt(i)});
  4846. }
  4847. }
  4848. }
  4849. },
  4850. keyup: function(e) {
  4851. if (e.key == ".") getId("toggle-autoUpgrade").click();
  4852. },
  4853. },
  4854. AULHT: {
  4855. handlers: [{type: "entityUpdate", names: "onTick"}, {type: "rpc", names: ["LocalBuilding"]}],
  4856. shouldHaveBeenUpgraded: {},
  4857. LocalBuilding: function(buildings) {
  4858. if (game.options.options.AULHT) {
  4859. for (let i in buildings) {
  4860. const building = buildings[i];
  4861. if (building.dead === 0 && building.uid in this.shouldHaveBeenUpgraded) {
  4862. building.tier > this.shouldHaveBeenUpgraded[building.uid] && delete this.shouldHaveBeenUpgraded[building.uid];
  4863. }
  4864. }
  4865. }
  4866. },
  4867. onTick: function({entities}) {
  4868. if (game.options.options.AULHT) {
  4869. for (let uid in entities) {
  4870. const currentEntity = entities[uid];
  4871. const worldEntity = game.world.entities[uid];
  4872.  
  4873. if (currentEntity == true || worldEntity == undefined) continue;
  4874. if (uid in this.shouldHaveBeenUpgraded) continue;
  4875.  
  4876. if (uid in game.ui.buildings && typeof currentEntity.health == 'number') {
  4877. const buildingHealth = (currentEntity.health / worldEntity.targetTick.maxHealth) * 100;
  4878. if (buildingHealth <= 20 && worldEntity.targetTick.tier != game.ui.components.BuildingOverlay.getGoldStashTier()) {
  4879. game.network.sendRpc({name: "UpgradeBuilding", uid: parseInt(uid)});
  4880. this.shouldHaveBeenUpgraded[uid] = structuredClone(worldEntity.targetTick.tier);
  4881. };
  4882. };
  4883. };
  4884. };
  4885. },
  4886. },
  4887. autoBuild: {
  4888. handlers: [{type: "rpc", names: ["LocalBuilding"]}],
  4889. defaultBase: '3,0,-96,0;3,-96,0,0;3,0,-192,0;3,-96,-240,0;3,-192,0,0;3,-240,-96,0;4,-336,-96,0;4,-432,-288,0;4,-96,-336,0;4,-288,-432,0;8,-192,-384,0;8,-384,-192,0;8,-288,-192,0;8,-192,-192,0;8,-192,-288,0;8,-288,-288,0;8,-384,-384,0;8,-96,-96,0;7,-288,0,0;7,-384,0,0;7,-432,-96,0;7,0,-288,0;7,0,-384,0;7,-96,-432,0;0,-168,-504,0;0,-216,-504,0;0,-264,-552,0;0,-312,-552,0;0,-312,-504,0;0,-504,-216,0;0,-504,-168,0;0,-552,-264,0;0,-552,-312,0;0,-504,-312,0;1,-360,-456,0;1,-456,-360,0;9,96,-96,0;9,-96,96,0;',
  4890. LocalBuilding: function(buildings) {
  4891. if (game.options.options.autoBuild) {
  4892. for (let i in buildings) {
  4893. const building = buildings[i];
  4894. if (building.type == "GoldStash" && building.dead === 0) game.script.builder.buildBase(this.defaultBase);
  4895. };
  4896. };
  4897. },
  4898. },
  4899. reconstruct: {
  4900. HORIZONTAL_DELTA: 500,
  4901. VERTICAL_DELTA: 1,
  4902.  
  4903. isMapping: false,
  4904. isMappingNow: false,
  4905.  
  4906. currentMap: {},
  4907. currentEntTowers: {},
  4908.  
  4909. currentWidth: 2,
  4910. currentlyMapping: null,
  4911.  
  4912. buildNote: document.createElement('p'),
  4913. entSettings: document.createElement('div'),
  4914.  
  4915. pathWayIndicators: {},
  4916. validCellsIndicators: {},
  4917.  
  4918. currentBase: '',
  4919. entranceGroups: {},
  4920. entPriority: ["right", "bottom", "top", "left"],
  4921.  
  4922. init: function() {
  4923. this.buildNote.innerHTML = `Map out the entrance path by drag-clicking the right mouse button.<br>Press Esc to save the current configuration.`;
  4924. this.buildNote.style.display = "none";
  4925. this.buildNote.style.color = "white";
  4926. this.buildNote.style.opacity = '0.5';
  4927. this.buildNote.style.textAlign = "center";
  4928. getClass('hud-top-center')[0].appendChild(this.buildNote);
  4929.  
  4930. this.entSettings.id = "ent-settings";
  4931. this.entSettings.innerHTML = `
  4932. Anchor: <select id="current-side">
  4933. <option value="top">Top</option>
  4934. <option value="bottom">Bottom</option>
  4935. <option value="left">Left</option>
  4936. <option value="right">Right</option>
  4937. </select><br>
  4938. Entrance span: <input id="ent-width" type="range" step="1" data-width="2 cells" value="2" min="2" max="8" /><br>
  4939.  
  4940. <div id="ent-controls">
  4941. <button id="undo-ent"><i class="fa-solid fa-xmark"></i></button>
  4942. <button id="create-ent"><i class="fa-solid fa-check"></i></button>
  4943. </div>
  4944. `;
  4945. this.entSettings.style.display = "none";
  4946. getClass("hud")[0].appendChild(this.entSettings);
  4947.  
  4948. document.addEventListener("keyup", (e) => {
  4949. if (document.activeElement.tagName.toLowerCase() !== "input" && document.activeElement.tagName.toLowerCase() !== "textarea") {
  4950. if (e.key == "Escape") {
  4951. if (this.isMapping) {
  4952. this.isMapping = false;
  4953. this.buildNote.style.display = "none";
  4954. game.renderer.follow(game.world.entities[game.world.myUid]);
  4955.  
  4956. this.currentMap = {};
  4957. this.currentEntTowers = {};
  4958.  
  4959. this.removeAllIndicators();
  4960. this.entSettings.style.display = "none";
  4961. };
  4962. };
  4963. };
  4964. });
  4965.  
  4966. getId("current-side").addEventListener("select", ({target}) => {
  4967. this.currentlyMapping = target.value;
  4968. });
  4969. getId("ent-width").addEventListener("input", ({target}) => {
  4970. target.setAttribute("data-width", target.value + ` cells`);
  4971. this.currentWidth = target.valueAsNumber;
  4972. this.updateEntranceTowers();
  4973. });
  4974. getId("undo-ent").addEventListener("click", ({target}) => {
  4975. this.currentMap = {};
  4976. this.currentEntTowers = {};
  4977.  
  4978. this.removeAllIndicators();
  4979. this.entSettings.style.display = "none";
  4980. });
  4981. getId("create-ent").addEventListener("click", ({target}) => {
  4982. this.entranceGroups[this.currentlyMapping] = Object.values(this.currentEntTowers).map(({x, y, type, yaw}) => {
  4983. return `${type},${x},${y},${yaw};`;
  4984. }).join("");
  4985.  
  4986. this.currentMap = {};
  4987. this.currentEntTowers = {};
  4988. for (const validCellIndex in this.validCellsIndicators) {
  4989. game.renderer.npcs.removeAttachment(this.validCellsIndicators[validCellIndex]);
  4990. delete this.validCellsIndicators[validCellIndex];
  4991. };
  4992. this.entSettings.style.display = "none";
  4993. });
  4994.  
  4995. game.network.addRpcHandler("LocalBuilding", this.onLocalBuilding.bind(this));
  4996. getId("hud").addEventListener("mousedown", this.onMouseDown.bind(this));
  4997. getId("hud").addEventListener("mousemove", this.onMouseMove.bind(this));
  4998. getId("hud").addEventListener("mouseup", this.onMouseUp.bind(this));
  4999. },
  5000. reconstructBaseByPriority: function() {
  5001. for (const side of this.entPriority) {
  5002. game.script.builder.buildBase(this.entranceGroups[side]);
  5003. };
  5004.  
  5005. },
  5006. removeAllIndicators: function() {
  5007. for (const cellIndex in this.currentMap) {
  5008. game.renderer.npcs.removeAttachment(this.pathWayIndicators[cellIndex]);
  5009. delete this.pathWayIndicators[cellIndex];
  5010. };
  5011. for (const validCellIndex in this.validCellsIndicators) {
  5012. game.renderer.npcs.removeAttachment(this.validCellsIndicators[validCellIndex]);
  5013. delete this.validCellsIndicators[validCellIndex];
  5014. };
  5015. },
  5016. getNonEntTowers: function() {
  5017. const map = {};
  5018. for (let x = this.goldStash.x - 12 * 48; x < this.goldStash.x + 12 * 48; x++) {
  5019. for (let y = this.goldStash.y - 12 * 48; y < this.goldStash.y + 12 * 48; y++) {
  5020. map[x] ||= {};
  5021. map[x][y] = false;
  5022. };
  5023. };
  5024. for (const relativePos of Object.values(this.currentMap)) {
  5025. map[this.goldStash.x - relativePos.x][this.goldStash.y - relativePos.y] = true;
  5026. };
  5027.  
  5028. // <tab>
  5029.  
  5030. const movementsX = [1, 0, -1, 0];
  5031. const movementsY = [0, 1, 0, -1];
  5032.  
  5033.  
  5034. let yourFuckinAnswer = [];
  5035.  
  5036. for (let XxX = this.goldStash.x - 12 * 48; XxX < this.goldStash.x + 12 * 48; XxX++) {
  5037. for (let YyY = this.goldStash.y - 12 * 48; YyY < this.goldStash.y + 12 * 48; YyY++) {
  5038. if (map[XxX][YyY]) continue;
  5039.  
  5040. let newAnswer = [];
  5041.  
  5042. let queueX = [];
  5043. let queueY = [];
  5044.  
  5045. queueX.push(XxX);
  5046. queueY.push(YyY);
  5047. map[XxX][YyY] = true;
  5048.  
  5049. while (queueX.length != 0) {
  5050. let x = queueX.shift();
  5051. let y = queueY.shift();
  5052.  
  5053. newAnswer.push({x, y});
  5054.  
  5055. for (let i = 0; i < 4; i++) {
  5056. let newX = x + movementsX[i];
  5057. let newY = y + movementsY[i];
  5058.  
  5059. if (map[newX][newY]) continue;
  5060. if (newX < this.goldStash.x - 12 * 48 || newX >= this.goldStash.x + 12 * 48) continue;
  5061. if (newY < this.goldStash.y - 12 * 48 || newY >= this.goldStash.y + 12 * 48) continue;
  5062.  
  5063. map[newX][newY] = true;
  5064.  
  5065. queueX.push(newX);
  5066. queueY.push(newY);
  5067. }
  5068. }
  5069.  
  5070. yourFuckinAnswer.push(newAnswer);
  5071. }
  5072. }
  5073. console.log(yourFuckinAnswer);
  5074. // </tab>
  5075.  
  5076. },
  5077. updateEntranceTowers: function() {
  5078. for (const validCellIndex in this.validCellsIndicators) {
  5079. game.renderer.npcs.removeAttachment(this.validCellsIndicators[validCellIndex]);
  5080. delete this.validCellsIndicators[validCellIndex];
  5081. };
  5082. this.currentEntTowers = {};
  5083.  
  5084. for (let cellIndex in this.currentMap) {
  5085. cellIndex = parseInt(cellIndex);
  5086. for (let CIx = cellIndex - this.HORIZONTAL_DELTA * this.currentWidth; CIx <= cellIndex + this.HORIZONTAL_DELTA * this.currentWidth; CIx += this.HORIZONTAL_DELTA) {
  5087. if (CIx < 0 || CIx > this.HORIZONTAL_DELTA ** 2) continue;
  5088. for (let CIy = CIx - this.VERTICAL_DELTA * this.currentWidth; CIy <= CIx + this.VERTICAL_DELTA * this.currentWidth; CIy += this.VERTICAL_DELTA) {
  5089. if (CIy < 0 || CIy > this.HORIZONTAL_DELTA ** 2) continue;
  5090. if (!(CIy in this.currentMap)) this.validCellsIndicators[CIy] = null;
  5091. };
  5092. };
  5093. };
  5094. for (const validCellIndex in this.validCellsIndicators) {
  5095. const entities = game.world.entityGrid.getEntitiesInCell(validCellIndex);
  5096. if (this.validCellsIndicators[validCellIndex] !== null) continue;
  5097. for (const uid in entities) {
  5098. const building = game.ui.buildings[uid];
  5099. if (!building || building.dead === 1) continue;
  5100.  
  5101. this.currentEntTowers[uid] = {
  5102. type: towerCodes.indexOf(building.type),
  5103. x: this.goldStash.x - building.x,
  5104. y: this.goldStash.y - building.y,
  5105. yaw: game.world.entities[building.uid]?.targetTick?.yaw
  5106. };
  5107.  
  5108. const buildingSchema = game.ui.buildingSchema[building.type];
  5109. const buildingSize = buildingSchema.gridWidth * 48;
  5110.  
  5111. const indicator = game.assetManager.models.rangeIndicatorModel({
  5112. width: buildingSize,
  5113. height: buildingSize,
  5114. }, {r: 111, g: 208, b: 247}, {r: 111, g: 208, b: 247}, 0);
  5115. indicator.setPosition(building.x, building.y);
  5116.  
  5117. this.validCellsIndicators[validCellIndex] = indicator;
  5118. game.renderer.npcs.addAttachment(indicator);
  5119. };
  5120. this.validCellsIndicators[validCellIndex] === null && delete this.validCellsIndicators[validCellIndex];
  5121. };
  5122. console.log(this.validCellsIndicators);
  5123. },
  5124. startReconstruction: function() {
  5125. if (!this.goldStash) return;
  5126.  
  5127. game.ui.components.MenuParty.hide();
  5128. game.ui.components.MenuShop.hide();
  5129. game.ui.components.MenuSettings.hide();
  5130.  
  5131. this.isMapping = true;
  5132. this.buildNote.style.display = "block";
  5133. this.currentBase = game.script.builder.recordBase(false);
  5134. game.renderer.follow(game.world.entities[this.goldStash.uid]);
  5135. },
  5136. onLocalBuilding: function(buildings) {
  5137. for (const building of buildings) {
  5138. if (building.type == "GoldStash") {
  5139. this.goldStash = building.dead === 0 ? building : null;
  5140. };
  5141. };
  5142. },
  5143. onMouseDown: function(e) {
  5144. if (!this.isMapping || e.button !== 2) return;
  5145. if (!e.repeat) {
  5146. console.log('a');
  5147. this.currentMap = {};
  5148. this.isMappingNow = true;
  5149. };
  5150. },
  5151. onMouseMove: function(e) {
  5152. if (!this.isMappingNow) return;
  5153.  
  5154. const absolutePos = game.renderer.screenToWorld(e.clientX, e.clientY);
  5155. const cellBeneath = game.world.entityGrid.getCellIndexes(absolutePos.x, absolutePos.y, {width: 1, height: 1})[0];
  5156.  
  5157. const cellCoordByCells = game.world.entityGrid.getCellCoords(cellBeneath);
  5158. const cellCoordsByAbsPos = {x: cellCoordByCells.x * 48, y: cellCoordByCells.y * 48};
  5159.  
  5160. this.currentMap[cellBeneath] = {
  5161. x: this.goldStash.x - cellCoordsByAbsPos.x,
  5162. y: this.goldStash.y - cellCoordsByAbsPos.y,
  5163. };
  5164.  
  5165. if (!this.pathWayIndicators[cellBeneath]) {
  5166. console.log(cellBeneath, cellCoordByCells, cellCoordsByAbsPos);
  5167. const indicator = game.assetManager.models.rangeIndicatorModel({
  5168. width: 48,
  5169. height: 48,
  5170. }, {r: 255, g: 0, b: 0}, {r: 255, g: 0, b: 0}, 0);
  5171.  
  5172. indicator.setPosition(cellCoordsByAbsPos.x + 24, cellCoordsByAbsPos.y + 24);
  5173. game.renderer.npcs.addAttachment(indicator);
  5174. this.pathWayIndicators[cellBeneath] = indicator;
  5175. };
  5176. },
  5177. onMouseUp: function(e) {
  5178. if (!this.isMappingNow) return;
  5179. this.isMappingNow = false;
  5180.  
  5181. this.entSettings.style.display = "block";
  5182. this.entSettings.style.left = e.clientX + "px";
  5183. this.entSettings.style.top = e.clientY + "px";
  5184.  
  5185. this.updateEntranceTowers();
  5186. },
  5187. },
  5188. autoHeal: {
  5189. init: function() {
  5190. Game.currentGame.ui._events.playerPetTickUpdate.push(pet => this.petTickUpdate.onTick(pet));
  5191. game.ui._events.playerTickUpdate.push(player => this.playerTickUpdate.onTick(player));
  5192. },
  5193. playerTickUpdate: {
  5194. hasEquipedPotion: false,
  5195. lastTickHealth: 100,
  5196. onTick: function(player) {
  5197. const options = game.options.options;
  5198.  
  5199. if (options.autoHeal) {
  5200. if (!game.ui.inventory.HealthPotion && player.gold >= 100) {
  5201. Game.currentGame.network.sendRpc({name: "BuyItem", itemName: "HealthPotion", tier: 1});
  5202. };
  5203. const playerHealth = (player.health / player.maxHealth) * 100;
  5204. this.hasEquipedPotion = (this.lastTickHealth <= playerHealth);
  5205. const healThreshold = getId("auto-heal-threshold").valueAsNumber || 15;
  5206. if (playerHealth <= healThreshold && !this.hasEquipedPotion) {
  5207. Game.currentGame.network.sendRpc({name: "EquipItem", itemName: "HealthPotion", tier: 1});
  5208. };
  5209. this.lastTickHealth = playerHealth;
  5210. };
  5211. },
  5212. },
  5213. petTickUpdate: {
  5214. buyItem: (itemName, tier = 1) => Game.currentGame.network.sendRpc({name: "BuyItem", itemName, tier}),
  5215. equipItem: (itemName, tier = 1) => Game.currentGame.network.sendRpc({name: "EquipItem", itemName, tier}),
  5216. petLevelEnum: [8, 16, 24, 32, 48, 64, 96],
  5217. petTokenEnum: [100, 100, 100, 100, 200, 200, 300, Infinity],
  5218. onTick: function(pet) {
  5219. const options = game.options.options;
  5220. if (options.autoHeal) {
  5221. if (pet.health <= 0) {
  5222. this.buyItem("PetRevive");
  5223. this.equipItem("PetRevive");
  5224. }
  5225. let petHealth = (pet.health / pet.maxHealth) * 100;
  5226. const healThreshold = getId("auto-heal-threshold").valueAsNumber || 15;
  5227. if (petHealth <= healThreshold) {
  5228. this.buyItem('PetHealthPotion');
  5229. this.equipItem("PetHealthPotion");
  5230. }
  5231. };
  5232. this.petLevelEnum.indexOf(game.ui.components.MenuShop.shopItems[pet.model].level) > -1 && (
  5233. game.ui.playerTick.token >= this.petTokenEnum[pet.tier - 1] && this.buyItem(pet.model, pet.tier + 1)
  5234. );
  5235. },
  5236. },
  5237. },
  5238. spam: {
  5239. randomSpamText: [
  5240. `?verify`,
  5241. "hi",
  5242. "ez",
  5243. "Super Idol的笑容都没你的甜八月正午的阳光都没你耀眼热爱 105 °C的你滴滴清纯的蒸馏水",
  5244. "Zǎoshang hǎo zhōngguó xiànzài wǒ yǒu BING CHILLING 🥶🍦",
  5245. "Wǒ hěn xǐhuān BING CHILLING 🥶🍦 Dànshì sùdù yǔ jīqíng 9 bǐ BING CHILLING 🥶🍦",
  5246. ],
  5247. spamInterval: null,
  5248. spamText: '',
  5249. fetchUnicode: async function() {
  5250. if (!localStorage.literallyEveryUnicodeEver) {
  5251. localStorage.literallyEveryUnicodeEver = await fetch('https://raw.githubusercontent.com/bits/UTF-8-Unicode-Test-Documents/master/UTF-8_sequence_unseparated/utf8_sequence_0-0xffff_assigned_printable_unseparated.txt')
  5252. .then(response => response.text());
  5253. this.randomSpamText.push(`${garbageGenerator()} BIG RAID ${garbageGenerator()}`);
  5254. }
  5255. },
  5256. onchange: function({target}) {
  5257. this.spamText = target.value;
  5258. },
  5259. start: function() {
  5260. this.spamInterval = setInterval(() => {
  5261. let text;
  5262. if (this.spamText !== '') text = `${garbageGenerator()} ${this.spamText} ${garbageGenerator()}`;
  5263. else text = getRandomItem(this.randomSpamText);
  5264. game.network.sendRpc({
  5265. name: "SendChatMessage",
  5266. channel: "Local",
  5267. message: text
  5268. });
  5269. }, 1050);
  5270. },
  5271. stop: function() {
  5272. clearInterval(this.spamInterval);
  5273. },
  5274. init: function() {
  5275. this.fetchUnicode();
  5276. },
  5277. },
  5278. autoBow: {
  5279. handlers: [{type: "entityUpdate", names: "onEntityUpdate"}, {type: "keybind", names: "keyup"}],
  5280. onEntityUpdate: function() {
  5281. if (game.options.options.autoBow) {
  5282. game.network.sendInput({space: 0});
  5283. game.network.sendInput({space: 1});
  5284. };
  5285. },
  5286. keyup: function(e) {
  5287. if (e.key == "=" && game.world.inWorld) {
  5288. if (game.ui.inventory.Bow) {
  5289. game.options.options.autoBow = !game.options.options.autoBow;
  5290. game.options.options.autoBow && game.network.sendRpc({name: "EquipItem", itemName: "Bow", tier: game.ui.inventory.Bow.tier});
  5291. } else if (game.ui.playerTick.gold > 100) {
  5292. game.network.sendRpc({name: "BuyItem", itemName: "Bow", tier: 1});
  5293. };
  5294. }
  5295. },
  5296. },
  5297. autoAim: {
  5298. handlers: [{type: "entityUpdate", names: "onEntityUpdate"}],
  5299. aimTarget: "player",
  5300. targets: [],
  5301. init: function() {
  5302. getId("autoAimOptions").addEventListener("change", ({target}) => {
  5303. this.aimTarget = target.value;
  5304. });
  5305. },
  5306. onEntityUpdate: function() {
  5307. const options = game.options.options;
  5308. if (options.autoAim) {
  5309. this.targets = [];
  5310. const entities = game.renderer.npcs.attachments;
  5311.  
  5312. for (let entity of entities) {
  5313. switch(this.aimTarget) {
  5314. case "player":
  5315. if (entity.fromTick.model == "GamePlayer" && entity.targetTick.partyId !== game.ui.playerPartyId && entity.fromTick.dead == 0) {
  5316. this.targets.push(entity.fromTick);
  5317. };
  5318. break;
  5319. case "zombie":
  5320. if (entity.fromTick.model !== "NeutralTier1" && entity.fromTick.entityClass == "Npc") {
  5321. this.targets.push(entity.fromTick);
  5322. };
  5323. break;
  5324. case "zom/dem":
  5325. if (entity.fromTick.entityClass == "Npc") {
  5326. this.targets.push(entity.fromTick);
  5327. };
  5328. break;
  5329. default:
  5330. if (entity.fromTick.uid !== game.world.myUid) {
  5331. this.targets.push(entity.fromTick);
  5332. };
  5333. };
  5334. };
  5335.  
  5336. if (this.targets.length > 0) {
  5337. const myPos = game.ui.playerTick.position;
  5338. this.targets.sort((a, b) => {
  5339. const distThisToA = measureDistance(myPos, a.position);
  5340. const distThisToB = measureDistance(myPos, b.position);
  5341.  
  5342. if (distThisToA < distThisToB) return -1;
  5343. else if (distThisToA > distThisToB) return 1;
  5344.  
  5345. return 0;
  5346. });
  5347.  
  5348. const target = this.targets[0];
  5349. const clientPos = game.renderer.worldToScreen(target.position.x, target.position.y);
  5350. game.inputManager.onMouseMoved({clientX: clientPos.x, clientY: clientPos.y});
  5351. }
  5352. };
  5353. }
  5354. },
  5355. autoRespawn: {
  5356. handlers: [{type: "rpc", names: ["Dead"]}],
  5357. Dead: function() {
  5358. if (!game.options.options.autoRespawn) return;
  5359. document.querySelector("#hud-respawn > div > div > div > button:nth-child(3)").click();
  5360. },
  5361. },
  5362. getRSS: {
  5363. handlers: [{type: "entityUpdate", names: "onTick"}, {type: "keybind", names: ["keyup", "mousemove"]}, {type: "rpc", names: ["DayCycle"]}],
  5364. dayTickData: null,
  5365. scoreData: {},
  5366.  
  5367. lastHoveredPlayers: {},
  5368. allowedRSS: true,
  5369. assignOldTick: function(player, playerTick) {
  5370. const [wood_1, stone_1, gold_1, token_1, px_1, py_1, info] = playerTick;
  5371. player.targetTick.oldWood = wood_1;
  5372. player.targetTick.oldStone = stone_1;
  5373. player.targetTick.oldGold = gold_1;
  5374. player.targetTick.oldToken = token_1;
  5375. player.targetTick.oldPX = px_1;
  5376. player.targetTick.oldPY = py_1;
  5377. player.targetTick.info = info;
  5378. player.targetTick.name = player.targetTick.info;
  5379. },
  5380. highlightColor: function(uid, rgb) {
  5381. // const hr = hexToRgb(hex);
  5382. game.world.entities[uid].currentModel.nameEntity.setColor(111, 208, 247);
  5383. },
  5384. resetColor: function(uid) {
  5385. game.world.entities[uid].currentModel.nameEntity.setColor(220, 220, 220);
  5386. },
  5387. DayCycle: function(e) {
  5388. this.dayTickData = e;
  5389. if (!game.ui.playerTick) return;
  5390. if (game.ui.playerTick.wave == 0) return;
  5391. for (const player of game.ui.playerPartyMembers) {
  5392. if (!e.isDay) {
  5393. const { playerUid } = player;
  5394. const playerTick = game.world.entities[playerUid].targetTick;
  5395. this.scoreData[playerUid] ||= {
  5396. spw: 0,
  5397. lastWaveScore: playerTick.score,
  5398. };
  5399. this.scoreData[playerUid].spw = playerTick.score - this.scoreData[playerUid].lastWaveScore;
  5400. this.scoreData[playerUid].lastWaveScore = playerTick.score;
  5401. };
  5402. };
  5403. for (const uid in this.scoreData) {
  5404. game.ui.playerPartyMembers.findIndex(e => e.playerUid == uid) == -1 && delete this.scoreData[uid];
  5405. };
  5406. },
  5407. onTick: function() {
  5408. const options = game.options.options;
  5409. if (options.getRSS) !this.allowedRSS && (this.allowedRSS = true);
  5410. if (options.getRSS || this.allowedRSS) {
  5411. // game.debug.allEntities = [];
  5412. for (let player of game.renderer.npcs.attachments) {
  5413. if (!!player.fromTick.name) {
  5414. let wood_1 = counter(player.targetTick.wood);
  5415. let stone_1 = counter(player.targetTick.stone);
  5416. let gold_1 = counter(player.targetTick.gold);
  5417. let token_1 = counter(player.targetTick.token);
  5418. let px_1 = counter(player.targetTick.position.x);
  5419. let py_1 = counter(player.targetTick.position.y);
  5420. let timeout_1 = player.targetTick.isPaused ? "On Timeout" : "";
  5421. if (options.getRSS && !player.targetTick.oldName) {
  5422. player.targetTick.oldName = player.targetTick.name;
  5423. let info = `
  5424. ${window.filterXSS(player.targetTick.oldName)}; score: ${player.targetTick.score.toLocaleString()}
  5425. UID: ${player.targetTick.uid}
  5426. W: ${wood_1}, S: ${stone_1}, G: ${gold_1}, T: ${token_1}
  5427. partyId: ${Math.round(player.targetTick.partyId)}
  5428. timeDead: ${msToTime(player.targetTick.timeDead)}
  5429. ${(player.targetTick.uid in this.scoreData) ? `SPW: ${this.scoreData[player.targetTick.uid].spw.toLocaleString()}` : ""}
  5430. ${timeout_1}
  5431.  
  5432.  
  5433.  
  5434.  
  5435.  
  5436. `;
  5437. this.assignOldTick(player, [wood_1, stone_1, gold_1, token_1, px_1, py_1, info]);
  5438. }
  5439. if (!options.getRSS && player.targetTick.oldName) {
  5440. player.targetTick.info = player.targetTick.oldName;
  5441. player.targetTick.name = player.targetTick.info;
  5442. player.targetTick.oldName = null;
  5443. }
  5444. if (options.getRSS) {
  5445. if (player.targetTick.oldGold !== gold_1
  5446. || player.targetTick.oldWood !== wood_1
  5447. || player.targetTick.oldStone !== stone_1
  5448. || player.targetTick.oldToken !== token_1
  5449. || player.targetTick.oldPX !== px_1
  5450. || player.targetTick.oldPY !== py_1) {
  5451. let info = `
  5452. ${window.filterXSS(player.targetTick.oldName)}; score: ${player.targetTick.score.toLocaleString()}
  5453. UID: ${player.targetTick.uid}
  5454. W: ${wood_1}, S: ${stone_1}, G: ${gold_1}, T: ${token_1}
  5455. partyId: ${Math.round(player.targetTick.partyId)}
  5456. timeDead: ${msToTime(player.targetTick.timeDead)}
  5457. ${(player.targetTick.uid in this.scoreData) ? `SPW: ${this.scoreData[player.targetTick.uid].spw.toLocaleString()}` : ""}
  5458. ${timeout_1}
  5459.  
  5460.  
  5461.  
  5462.  
  5463.  
  5464. `;
  5465. this.assignOldTick(player, [wood_1, stone_1, gold_1, token_1, px_1, py_1, info]);
  5466. }
  5467. }
  5468. }
  5469. }
  5470. }
  5471. if (!options.getRSS) this.allowedRSS = false;
  5472. },
  5473. mousemove: function(e) {
  5474. if (!game.options.options.getRSS) return;
  5475. const worldPos = game.renderer.screenToWorld(e.clientX, e.clientY);
  5476. const entitiesUnderMouse = getEntityAtPos(worldPos.x, worldPos.y);
  5477. for (const uid in this.lastHoveredPlayers) {
  5478. if (!(uid in entitiesUnderMouse)) {
  5479. uid in game.world.entities && this.resetColor(uid);
  5480. delete this.lastHoveredPlayers[uid];
  5481. }
  5482. }
  5483. for (const uid in entitiesUnderMouse) {
  5484. if (game.world.entities[uid].targetTick.name && !(uid in this.lastHoveredPlayers)) {
  5485. this.lastHoveredPlayers[uid] = true;
  5486. this.highlightColor(uid);
  5487. }
  5488. }
  5489. },
  5490. keyup: function(e) {
  5491. if (e.key == "-") game.options.options.getRSS = !game.options.options.getRSS;
  5492. },
  5493. },
  5494. showAoe: {
  5495. modelIndicatorsPool: {},
  5496. projectileEnums: {
  5497. "CannonProjectile": {
  5498. parent: 'CannonTower',
  5499. innerRGB: {r: 60, g: 188, b: 92},
  5500. borderRGB: {r: 58, g: 170, b: 86},
  5501. aoe: 250,
  5502. },
  5503. "BombProjectile": {
  5504. parent: 'BombTower',
  5505. innerRGB: {r: 0xd8, g: 0x0, b: 0x27},
  5506. borderRGB: {r: 0xd8, g: 0x4d, b: 0x5c},
  5507. aoe: 250,
  5508. },
  5509. "FireballProjectile": {
  5510. parent: "MagicTower",
  5511. innerRGB: {r: 73, g: 178, b: 204},
  5512. borderRGB: {r: 48, g: 130, b: 150},
  5513. aoe: 100
  5514. }
  5515. },
  5516. init: function() {
  5517. const poolSize = 50;
  5518. for (let modelName in this.projectileEnums) {
  5519. this.modelIndicatorsPool[modelName] = [];
  5520. for (let i = 0; i < poolSize; i++) {
  5521. const {innerRGB, borderRGB, aoe, parent} = this.projectileEnums[modelName];
  5522. const aoeIndicator = game.assetManager.models.rangeIndicatorModel({
  5523. isCircular: true,
  5524. radius: aoe,
  5525. }, innerRGB, borderRGB);
  5526. aoeIndicator.setVisible(true);
  5527. this.modelIndicatorsPool[modelName].push(aoeIndicator);
  5528. }
  5529. }
  5530. },
  5531. onEntityRemoved: function(t) {
  5532. if (game.options.options.showAoe) {
  5533. const entityTick = game.world.entities[t].targetTick;
  5534. if (entityTick.model in this.projectileEnums) {
  5535. const { msBetweenFiresTiers, lifetimeTiers } = game.ui.buildingSchema[this.projectileEnums[entityTick.model].parent];
  5536. let aoeIndicator;
  5537. if (this.modelIndicatorsPool[entityTick.model].length > 0) {
  5538. aoeIndicator = this.modelIndicatorsPool[entityTick.model].shift();
  5539. } else {
  5540. const {innerRGB, borderRGB, aoe, parent} = this.projectileEnums[entityTick.model];
  5541. aoeIndicator = game.assetManager.models.rangeIndicatorModel({
  5542. isCircular: true,
  5543. radius: aoe,
  5544. }, innerRGB, borderRGB);
  5545. aoeIndicator.setVisible(true);
  5546. }
  5547. aoeIndicator.setPosition(entityTick.position.x, entityTick.position.y);
  5548. game.renderer.ground.addAttachment(aoeIndicator);
  5549.  
  5550. setTimeout(() => {
  5551. game.renderer.ground.removeAttachment(aoeIndicator);
  5552. this.modelIndicatorsPool[entityTick.model].push(aoeIndicator);
  5553. }, msBetweenFiresTiers[7]);
  5554. }
  5555. }
  5556. },
  5557. },
  5558. stashIndicators: {
  5559. BUILDING_DISTANCE: 864,
  5560. MIN_STASH_DISTANCE: 2496,
  5561. ZOMBIE_SPAWN_RANGE: 48 * Math.sqrt(2 * (18 ** 2)),
  5562. currentIndicators: {
  5563. uid: null,
  5564. indicators: [],
  5565. },
  5566. onEntityCreated: function(t) {
  5567. if (t.model == "GoldStash") {
  5568. if (this.currentIndicators.uid == t.uid) return;
  5569.  
  5570. for (const indicator of this.currentIndicators.indicators) game.renderer.ground.removeAttachment(indicator);
  5571.  
  5572. const buildLimitIndicator = game.assetManager.models.rangeIndicatorModel({
  5573. width: this.BUILDING_DISTANCE * 2,
  5574. height: this.BUILDING_DISTANCE * 2,
  5575. }, null, {r: 0xee, g: 0xee, b: 0xee}, 12);
  5576. buildLimitIndicator.setVisible(game.options.options.stashIndicators);
  5577. buildLimitIndicator.setPosition(t.position.x, t.position.y);
  5578. game.renderer.ground.addAttachment(buildLimitIndicator);
  5579.  
  5580. const stashLimitIndicator = game.assetManager.models.rangeIndicatorModel({
  5581. width: this.MIN_STASH_DISTANCE * 2,
  5582. height: this.MIN_STASH_DISTANCE * 2,
  5583. }, null, {r: 0xee, g: 0xee, b: 0xee}, 12);
  5584. stashLimitIndicator.setVisible(game.options.options.stashIndicators);
  5585. stashLimitIndicator.setPosition(t.position.x, t.position.y);
  5586. game.renderer.ground.addAttachment(stashLimitIndicator);
  5587.  
  5588. const zombieSpawnIndicator = game.assetManager.models.rangeIndicatorModel({
  5589. isCircular: true,
  5590. radius: this.ZOMBIE_SPAWN_RANGE,
  5591. }, {r: 0xff, g: 0xff, b: 0xff}, {r: 0xee, g: 0xee, b: 0xee});
  5592. zombieSpawnIndicator.setVisible(game.options.options.stashIndicators);
  5593. zombieSpawnIndicator.setPosition(t.position.x, t.position.y);
  5594. game.renderer.ground.addAttachment(zombieSpawnIndicator);
  5595.  
  5596. this.currentIndicators = {
  5597. uid: t.uid,
  5598. indicators: [buildLimitIndicator, stashLimitIndicator, zombieSpawnIndicator],
  5599. };
  5600. }
  5601. },
  5602. },
  5603. grouping: {
  5604. loadedGrid: false,
  5605. displays: ["none", "blue", "purple"],
  5606. currentlyDisplaying: "none",
  5607. init: function() {
  5608. game.network.addEnterWorldHandler(() => {
  5609. if (this.loadedGrid) return;
  5610. this.makeGrid();
  5611. });
  5612. document.addEventListener("keyup", function(e) {
  5613. if (document.activeElement.tagName.toLowerCase() !== "input" && document.activeElement.tagName.toLowerCase() !== "textarea") {
  5614. if (e.key == "v") getId("Grouping Grid").click();
  5615. };
  5616. });
  5617. },
  5618. makeGrid: function(width, height) {
  5619. this.loadedGrid = true;
  5620. const blueCell = game.assetManager.models.rangeIndicatorModel({
  5621. width: 196,
  5622. height: 196,
  5623. }, null, {r: 111, g: 208, b: 247}, 4);
  5624.  
  5625. const purpleCell = game.assetManager.models.rangeIndicatorModel({
  5626. width: 196,
  5627. height: 196,
  5628. }, null, {r: 213, g: 118, b: 211}, 4);
  5629.  
  5630. this.blueGrid = new game.renderer.spriteType(blueCell.goldRegion.getTexture(), true);
  5631. this.blueGrid.setDimensions(0, 0, 24000, 24000);
  5632. this.blueGrid.setAnchor(0, 0);
  5633. this.blueGrid.setAlpha(1.5);
  5634. this.blueGrid.setVisible(this.currentlyDisplaying == "blue");
  5635.  
  5636. this.purpleGrid = new game.renderer.spriteType(purpleCell.goldRegion.getTexture(), true);
  5637. this.purpleGrid.setDimensions(48, 48, 23952, 23952);
  5638. this.purpleGrid.setAnchor(0, 0);
  5639. this.purpleGrid.setAlpha(1.75);
  5640. this.purpleGrid.setVisible(this.currentlyDisplaying == "purple");
  5641.  
  5642. game.renderer.ground.addAttachment(this.blueGrid);
  5643. game.renderer.ground.addAttachment(this.purpleGrid);
  5644. },
  5645. refreshGrid: function() {
  5646. this.blueGrid.setVisible(this.currentlyDisplaying == "blue");
  5647. this.purpleGrid.setVisible(this.currentlyDisplaying == "purple");
  5648. },
  5649. cycleGrid: function() {
  5650. this.currentlyDisplaying = this.displays[(this.displays.indexOf(this.currentlyDisplaying) + 1) % 3];
  5651. this.refreshGrid();
  5652. },
  5653. },
  5654. buildingLife: {
  5655. handlers: [{type: "rpc", names: ["LocalBuilding"]}],
  5656.  
  5657. MAX_ALPHA: 5,
  5658.  
  5659. buildingWeights: {},
  5660. indicators: [],
  5661. sceneryAlpha: 0.5,
  5662.  
  5663. startingIndex: 0,
  5664. refreshTimeout: null,
  5665.  
  5666. LocalBuilding: function(buildings) {
  5667. for (let building of buildings) {
  5668. if (building.dead === 1) {
  5669. building.uid in this.buildingWeights && delete this.buildingWeights[building.uid];
  5670. } else {
  5671. if (building.uid in this.buildingWeights) continue;
  5672. this.buildingWeights[building.uid] = null;
  5673. };
  5674. };
  5675. getId("heat-slider").max = Object.keys(this.buildingWeights).length - 1;
  5676. getId("heat-max").value = Object.keys(this.buildingWeights).length;
  5677.  
  5678. this.refreshMap();
  5679. },
  5680. refreshMap: function() {
  5681. const sortedUids = Object.keys(this.buildingWeights).sort((a, b) => a - b);
  5682. const gap = this.MAX_ALPHA / (sortedUids.length - this.startingIndex);
  5683.  
  5684. let i = 0,
  5685. _i = -1;
  5686. for (let uid of sortedUids) {
  5687. _i++;
  5688. if (_i < this.startingIndex) {
  5689. this.buildingWeights[uid] = null;
  5690. continue;
  5691. } else if (_i == this.startingIndex) i = 0;
  5692.  
  5693. this.buildingWeights[uid] = gap * i++;
  5694. };
  5695. },
  5696. setSceneryAlpha: function(alpha) {
  5697. this.sceneryAlpha = alpha;
  5698. game.options.options.buildingLife && game.renderer.scenery.setAlpha(this.sceneryAlpha);
  5699. },
  5700. showMap: function() {
  5701. for (let uid in this.buildingWeights) {
  5702. if (this.buildingWeights[uid] === null) {
  5703. const entity = game.renderer.scenery.attachments.find(e => e.uid == uid);
  5704. entity?.setAlpha?.(0);
  5705. continue;
  5706. };
  5707. const building = game.ui.buildings[uid];
  5708. if (!building || building.dead === 1) continue;
  5709.  
  5710. const buildingSchema = game.ui.buildingSchema[building.type];
  5711. const buildingSize = buildingSchema.gridWidth * 48;
  5712.  
  5713. const indicator = game.assetManager.models.rangeIndicatorModel({
  5714. width: buildingSize,
  5715. height: buildingSize,
  5716. }, {r: 255, g: 0, b: 0}, {r: 255, g: 0, b: 0}, 0);
  5717. indicator.setAlpha(this.MAX_ALPHA - this.buildingWeights[uid]);
  5718. indicator.setPosition(building.x, building.y);
  5719.  
  5720. this.indicators.push(indicator);
  5721. game.renderer.npcs.addAttachment(indicator);
  5722. };
  5723. game.renderer.scenery.setAlpha(this.sceneryAlpha);
  5724. },
  5725. hideMap: function() {
  5726. for (const indicator of this.indicators) game.renderer.npcs.removeAttachment(indicator);
  5727. for (const entities of game.renderer.scenery.attachments) entities.setAlpha(1);
  5728. game.renderer.scenery.setAlpha(1);
  5729. },
  5730. },
  5731. bossAlert: {
  5732. handlers: [{type: "keybind", names: ["DayCycle"]}],
  5733. init: function() {
  5734. this.bossAlert = document.createElement('p');
  5735. this.bossAlert.innerHTML = `<i class="fa fa-exclamation-triangle"></i> Boss wave incoming`;
  5736. this.bossAlert.style.display = "none";
  5737. this.bossAlert.style.color = "white";
  5738. this.bossAlert.style.opacity = '0.5';
  5739. getClass('hud-top-center')[0].appendChild(this.bossAlert);
  5740. },
  5741. DayCycle: function(e) {
  5742. if (!game.ui.playerTick) return;
  5743. if (e.isDay) this.bossAlert.style.display = (getIsNextWaveActive() && game.options.options.bossAlert) ? "block" : "none";
  5744. },
  5745. },
  5746. lockAim: {
  5747. handlers: [{type: "keybind", names: "keyup"}],
  5748. init: function() {
  5749. game.inputManager._emit = game.inputManager.emit;
  5750. game.inputManager.emit = function(...args) {
  5751. if (args[0].indexOf("mouse") > -1 && game.options.options.lockAim) return;
  5752. return this._emit(...args);
  5753. };
  5754. },
  5755. keyup: function(e) {
  5756. if (e.key == "u") game.options.options.lockAim = !game.options.options.lockAim;
  5757. },
  5758. },
  5759. /* @Rebinds */
  5760. sell: {
  5761. sellAllByType: function(type) {
  5762. if (!game.ui.playerPartyCanSell) return;
  5763. let lastSoldBuilding = null;
  5764. let allBuildings = [Infinity, ...Object.values(game.ui.buildings).filter(e => e.type == type)];
  5765. let sellInterval = () => {
  5766. if (!game.ui.buildings[lastSoldBuilding?.uid]) allBuildings.shift();
  5767. if (window.sellBreak || allBuildings.length == 0) return;
  5768. const target = allBuildings[0];
  5769. if (target !== undefined && !game.ui.buildings[target]?.dead) {
  5770. lastSoldBuilding = target;
  5771. Game.currentGame.network.sendRpc({
  5772. name: "DeleteBuilding",
  5773. uid: parseInt(target.uid)
  5774. });
  5775. setTimeout(sellInterval, 50);
  5776. };
  5777. };
  5778. sellInterval();
  5779. },
  5780. sellAllWithUids: function(uids) {
  5781. if (!game.ui.playerPartyCanSell) return;
  5782. let lastSoldBuilding = null;
  5783.  
  5784. uids = uids.filter(e => game.ui.buildings[e]?.type !== "GoldStash");
  5785. let allBuildings = [Infinity, ...uids];
  5786.  
  5787. let sellInterval = () => {
  5788. if (!game.ui.buildings[lastSoldBuilding]) allBuildings.shift();
  5789. if (window.sellBreak || allBuildings.length == 0) return;
  5790. const target = allBuildings[0];
  5791. if (target !== undefined && !game.ui.buildings[target]?.dead) {
  5792. lastSoldBuilding = target;
  5793. Game.currentGame.network.sendRpc({
  5794. name: "DeleteBuilding",
  5795. uid: parseInt(target)
  5796. });
  5797. setTimeout(sellInterval, 50);
  5798. };
  5799. };
  5800. sellInterval();
  5801. },
  5802. sellAll: function() {
  5803. this.isSellingAll = true;
  5804. const sellInterval = () => {
  5805. if (window.sellBreak) return;
  5806. if (Object.keys(game.ui.buildings).length > 1 && game.ui.playerPartyCanSell) {
  5807. Game.currentGame.network.sendRpc({
  5808. name: "DeleteBuilding",
  5809. uid: parseInt(Object.keys(game.ui.buildings)[1])
  5810. });
  5811. setTimeout(() => { sellInterval(); }, 100);
  5812. Object.keys(game.ui.buildings).length == 2 && (this.isSellingAll = false);
  5813. }
  5814. }
  5815. sellInterval();
  5816. },
  5817. sellBuilding: function () {
  5818. if (this.buildingUid) {
  5819. if ('GoldStash' == this.buildingId) {
  5820. game.ui.components.PopupOverlay.showConfirmation(`Are you sure you want to delete all buildings?`, 5000, function() {
  5821. game.script.sell.sellAll();
  5822. });
  5823. return this.stopWatching();
  5824. }
  5825. if (this.shouldUpgradeAll) {
  5826. const id = this.buildingId;
  5827. game.ui.components.PopupOverlay.showConfirmation(`Are you sure you want to delete all buildings of this type?`, 5000, function() {
  5828. game.script.sell.sellAllByType(id);
  5829. });
  5830. } else Game.currentGame.network.sendRpc({name: 'DeleteBuilding', uid: this.buildingUid});
  5831. };
  5832. },
  5833. init: function() {
  5834. game.ui.components.BuildingOverlay.sellBuilding = this.sellBuilding.bind(game.ui.components.BuildingOverlay);
  5835. },
  5836. },
  5837. chat: {
  5838. blockedUids: [],
  5839. emojiList: {
  5840. hmm: "https://cdn.discordapp.com/emojis/724365641963929611.png?size=48",
  5841. pog: "https://cdn.discordapp.com/emojis/721070353337811026.png?size=48",
  5842. pepehands: "https://cdn.discordapp.com/emojis/733406770139103293.png?size=48",
  5843. pepeEyes: "https://cdn.discordapp.com/emojis/869573233794486323.gif?size=48",
  5844. pepeHappy: "https://cdn.discordapp.com/emojis/801475958883614811.png?size=48",
  5845. sadge: "https://cdn.discordapp.com/emojis/826530556974989344.png?size=48",
  5846. ha: "https://cdn.discordapp.com/emojis/782756472886525953.png?size=48",
  5847. kekw: "https://cdn.discordapp.com/emojis/748511358076846183.png?size=48",
  5848. pogEyes: "https://cdn.discordapp.com/emojis/786979080406564885.png?size=48",
  5849. appalled: "https://cdn.discordapp.com/emojis/830880294881853530.png?size=48",
  5850. pogYou: "https://cdn.discordapp.com/emojis/790293794716516430.png?size=48",
  5851. pogChag: "https://cdn.discordapp.com/emojis/831156303497134090.png?size=48",
  5852. pogey: "https://cdn.discordapp.com/emojis/790293759861719050.png?size=48",
  5853. weirdChamp: "https://cdn.discordapp.com/emojis/757553915389673502.png?size=48",
  5854. monkaS: "https://cdn.discordapp.com/emojis/757179783573405766.png?size=48",
  5855. yep: "https://cdn.discordapp.com/emojis/758356179477987339.png?size=48",
  5856.  
  5857. weirdButOkay: "https://cdn.discordapp.com/emojis/831156194247966782.gif?size=48",
  5858. pogpogpogpog: "https://cdn.discordapp.com/emojis/869580566096379974.gif?size=48",
  5859. wooyeah: "https://cdn.discordapp.com/emojis/791008461420888084.gif?size=48",
  5860. idk: "https://cdn.discordapp.com/emojis/882513306164805642.gif?size=48",
  5861. },
  5862. blockPlayer: function(name, uid) {
  5863. game.ui.components.PopupOverlay.showConfirmation(`Are you sure you want to block ${window.filterXSS(name)} (${uid})?`, 3500, () => {
  5864. this.blockedUids.push(uid);
  5865. for (let bl of Array.from(document.getElementsByClassName(`uid${uid}`))) {
  5866. bl.innerHTML = "Unblock";
  5867. bl.style.color = "blue";
  5868. bl.onclick = () => this.unblockPlayer(name, uid);
  5869. };
  5870. }, () => {});
  5871. },
  5872. unblockPlayer: function(name, uid) {
  5873. this.blockedUids.splice(this.blockedUids.indexOf(uid), 1);
  5874. for (let bl of Array.from(document.getElementsByClassName(`uid${uid}`))) {
  5875. bl.innerHTML = "Block";
  5876. bl.style.color = "red";
  5877. bl.onclick = () => this.blockPlayer(name, uid);
  5878. };
  5879. },
  5880. onMessageReceived: function(e) {
  5881. if (this.blockedUids.includes(e.uid) || window.chatDisabled) return;
  5882. let a = Game.currentGame.ui.getComponent("Chat"),
  5883. b = window.filterXSS(e.displayName),
  5884. c = window.filterXSS(e.message)
  5885. .replace(/(?:f|F)uck/gi, `<img src="https://cdn.discordapp.com/emojis/907625398832070667.png?size=80" height="16" width="18" style="margin: 1px 0 0 0;"></img>`)
  5886. .replace(/s[3e]x+/gi, `<img src="https://cdn.discordapp.com/emojis/953759638350872666.gif?size=80&quality=lossless" height="16" width="18" style="margin: 1px 0 0 0;"></img>`)
  5887. .replace(/n+[i1]+gg+[a@]+/i, `<img src="https://cdn.discordapp.com/emojis/902742239996936226.webp?size=80" height="16" width="17" style="margin: 1px 0 0 0;"></img>`);
  5888. let arr = c.split(':');
  5889.  
  5890. for (let i = 1; i < arr.length; i += 2) {
  5891. if (!this.emojiList[arr[i]]) arr = [c];
  5892. else arr[i] = `<img src="${this.emojiList[arr[i]]}" height="16" width="18" style="margin: 1px 0 0 0;"></img>`;
  5893. }
  5894.  
  5895. let d = a.ui.createElement(`<div class="hud-chat-message"><a href="javascript:void(0);" style="color: red;margin: 0 5px 0 0;display: inline-block;" class="uid${e.uid}">Block</a><strong> ${b}</strong>: ${arr.join(" ")}<small>${getClock()}</small></div>`);
  5896. d.children[0].onclick = () => game.script.chat.blockPlayer(b, e.uid);
  5897. a.messagesElem.appendChild(d);
  5898. a.messagesElem.scrollTop = a.messagesElem.scrollHeight;
  5899. },
  5900. init: function() {
  5901. Game.currentGame.network.emitter.removeListener("PACKET_RPC", Game.currentGame.network.emitter._events.PACKET_RPC[1]);
  5902. Game.currentGame.network.addRpcHandler("ReceiveChatMessage", this.onMessageReceived.bind(this));
  5903. document.addEventListener('keyup', function(e) {
  5904. if (document.activeElement.tagName.toLowerCase() !== "input" && document.activeElement.tagName.toLowerCase() !== "textarea") {
  5905. if (e.key == "Enter") {
  5906. (game.ui?.playerTick?.dead === 1) && game.ui.components.Chat.startTyping();
  5907. };
  5908. };
  5909. });
  5910. },
  5911. },
  5912. parties: {
  5913. serverPopulation: 0,
  5914.  
  5915. partyMenu: getClass("hud-menu-party")[0],
  5916. partyTabs: getClass("hud-party-tabs")[0],
  5917.  
  5918. partyMembers: getClass("hud-party-members")[0],
  5919. partyGrid: getClass("hud-party-grid")[0],
  5920. closedParties: null,
  5921. shareKeyLog: null,
  5922.  
  5923. init: function() {
  5924. this.partyMembers.style.display = "block";
  5925. this.partyGrid.style.display = "none";
  5926.  
  5927. const privateTab2 = document.createElement("a");
  5928. privateTab2.className = "hud-party-tabs-link";
  5929. privateTab2.id = "privateTab2";
  5930. privateTab2.innerHTML = "Closed Parties";
  5931.  
  5932. this.closedParties = document.createElement("div");
  5933. this.closedParties.className = "hud-private hud-party-grid";
  5934. this.closedParties.id = "privateHud2";
  5935. this.closedParties.style.display = "none";
  5936.  
  5937. this.partyTabs.appendChild(privateTab2);
  5938. this.partyMenu.insertBefore(this.closedParties, getClass("hud-party-actions")[0]);
  5939.  
  5940.  
  5941. const privateTab = document.createElement("a");
  5942. privateTab.className = "hud-party-tabs-link";
  5943. privateTab.id = "privateTab";
  5944. privateTab.innerHTML = "Key Logs";
  5945.  
  5946. this.shareKeyLog = document.createElement("div");
  5947. this.shareKeyLog.className = "hud-private hud-party-grid";
  5948. this.shareKeyLog.id = "privateHud";
  5949. this.shareKeyLog.style.display = "none";
  5950.  
  5951. this.partyTabs.appendChild(privateTab);
  5952. this.partyMenu.insertBefore(this.shareKeyLog, getClass("hud-party-actions")[0]);
  5953.  
  5954. privateTab.addEventListener("click", e => {
  5955. for (let menu of [this.partyMembers, this.partyGrid, this.closedParties, this.shareKeyLog]) {
  5956. menu.style.display == "block" && (menu.style.display = "none");
  5957. }
  5958.  
  5959. for (let i of getClass("hud-party-tabs-link")) i.className = "hud-party-tabs-link";
  5960. privateTab.className = "hud-party-tabs-link is-active";
  5961.  
  5962. this.shareKeyLog.style.display = "block";
  5963. })
  5964.  
  5965. privateTab2.addEventListener("click", e => {
  5966. for (let menu of [this.partyMembers, this.partyGrid, this.closedParties, this.shareKeyLog]) {
  5967. menu.style.display == "block" && (menu.style.display = "none");
  5968. }
  5969.  
  5970. for (let i of getClass("hud-party-tabs-link")) i.className = "hud-party-tabs-link";
  5971. privateTab2.className = "hud-party-tabs-link is-active";
  5972.  
  5973. this.closedParties.style.display = "block";
  5974. })
  5975.  
  5976. getClass("hud-party-tabs-link")[0].addEventListener("click", e => {
  5977. this.shareKeyLog.style.display = "none";
  5978. privateTab.className = "hud-party-tabs-link";
  5979.  
  5980. this.closedParties.style.display = "none";
  5981. privateTab2.className = "hud-party-tabs-link";
  5982. })
  5983.  
  5984. getClass("hud-party-tabs-link")[1].addEventListener("click", e => {
  5985. this.shareKeyLog.style.display = "none";
  5986. privateTab.className = "hud-party-tabs-link";
  5987.  
  5988. this.closedParties.style.display = "none";
  5989. privateTab2.className = "hud-party-tabs-link";
  5990. });
  5991. game.network.addRpcHandler("PartyShareKey", (e) => game.script.parties.onPartyShareKey(e));
  5992. game.network.addRpcHandler("SetPartyList", (e) => game.script.parties.onSetPartyList(e));
  5993. },
  5994. onSetPartyList: function(parties) {
  5995. this.serverPopulation = 0;
  5996. for (let party of parties) {
  5997. this.serverPopulation += party.memberCount;
  5998. }
  5999. document.getElementsByClassName("hud-party-server")[0].innerHTML = `${this.serverPopulation}/32<small id="serverRegion"></small>`;
  6000. },
  6001. onPartyShareKey: function(e) {
  6002. const psk = e.partyShareKey,
  6003. lnk = `https://zombs.io/#/${game.options.serverId}/${psk}/`;
  6004. this.shareKeyLog.innerHTML += `
  6005. <div style="display:inline-block;margin:10px 5px 0;">
  6006. <li>
  6007. <strong
  6008. style="cursor: pointer;" onclick="game.network.sendRpc({ name: 'JoinPartyByShareKey', partyShareKey: '${psk}' });">${psk}
  6009. </strong> - <a href="${lnk}" target="_blank" color="purple">
  6010. [Link]
  6011. </a>
  6012. </li>
  6013. </div>
  6014. <br />
  6015. `;
  6016. },
  6017. },
  6018. /* @NonToggle */
  6019. builder: {
  6020. buildBase: function(design) {
  6021. const goldStash = Object.values(game.ui.buildings).find(building => building.type == "GoldStash");
  6022.  
  6023. if (typeof design !== "string") throw new Error("Argument must be given as a string.");
  6024. if (goldStash === undefined) throw new Error("You must have a gold stash to be able to use this.");
  6025.  
  6026. const towers = design.split(";");
  6027.  
  6028. for (let towerStr of towers) {
  6029. const tower = towerStr.split(",");
  6030.  
  6031. if (tower[0] === "") continue;
  6032. if (tower.length < 4) throw new Error(`${JSON.stringify(tower)} contains an issue that must be fixed before this design can be replicated.`);
  6033.  
  6034. Game.currentGame.network.sendRpc({
  6035. name: "MakeBuilding",
  6036. type: towerCodes[parseInt(tower[0])],
  6037. x: goldStash.x - parseInt(tower[1]),
  6038. y: goldStash.y - parseInt(tower[2]),
  6039. yaw: parseInt(tower[3])
  6040. });
  6041. };
  6042. },
  6043.  
  6044. recordBase: function(pasteValue = true) {
  6045. const goldStash = Object.values(game.ui.buildings).find(building => building.type == "GoldStash");
  6046. let baseStr = "";
  6047. for (let i in game.ui.buildings) {
  6048. const building = game.ui.buildings[i];
  6049. if (towerCodes.indexOf(building.type) < 0) continue;
  6050.  
  6051. let yaw = 0;
  6052.  
  6053. if (["Harvester", "MeleeTower"].includes(building.type)) {
  6054. if (game.world.entities[building.uid] !== undefined) yaw = game.world.entities[building.uid].targetTick.yaw;
  6055. }
  6056. baseStr += `${towerCodes.indexOf(building.type)},${goldStash.x - building.x},${goldStash.y - building.y},${yaw};`;
  6057. }
  6058. if (pasteValue) getId('target-base-design').value = baseStr;
  6059. else return baseStr;
  6060. },
  6061. calculateResourceNeeded(design) {
  6062. const rssNeeded = {wood: 0, stone: 0};
  6063. const schema = game.ui.buildingSchema;
  6064.  
  6065. if (typeof design !== "string") throw new Error("Argument must be given as a string.");
  6066.  
  6067. const towers = design.split(";");
  6068. for (let towerStr of towers) {
  6069. const tower = towerStr.split(",");
  6070.  
  6071. if (tower[0] === "") continue;
  6072. if (tower.length < 4) throw new Error(`${JSON.stringify(tower)} contains an issue that must be fixed before this design can be calculated for resources needed.`);
  6073.  
  6074. rssNeeded.wood += schema[towerCodes[parseInt(tower[0])]].woodCosts[0];
  6075. rssNeeded.stone += schema[towerCodes[parseInt(tower[0])]].stoneCosts[0];
  6076. };
  6077. return rssNeeded;
  6078. },
  6079. calculateNeededPlayers(design) {
  6080. if (typeof design !== "string") throw new Error("Argument must be given as a string.");
  6081.  
  6082. const allTowers = {};
  6083. const schema = game.ui.buildingSchema;
  6084.  
  6085. const towers = design.split(";");
  6086. for (let towerStr of towers) {
  6087. const tower = towerStr.split(",");
  6088.  
  6089. if (tower[0] === "") continue;
  6090. if (tower.length < 4) throw new Error(`${JSON.stringify(tower)} contains an issue that must be fixed before this design can be calculated for resources needed.`);
  6091.  
  6092. allTowers[tower[0]] ||= 0;
  6093. allTowers[tower[0]]++;
  6094. };
  6095. let highestNeededAmount = 1;
  6096. for (const towerName in allTowers) {
  6097. const amount = allTowers[towerName];
  6098. const neededAmount = Math.ceil(amount / (schema[towerCodes[parseInt(towerName)]].limit / game.ui.playerPartyMembers.length));
  6099. neededAmount > highestNeededAmount && (highestNeededAmount = neededAmount);
  6100. };
  6101. return highestNeededAmount;
  6102. },
  6103. showOverlay: function (design, timeout) {
  6104. const goldStash = Object.values(game.ui.buildings).find(building => building.type == "GoldStash");
  6105.  
  6106. if (typeof design !== "string") throw new Error("Argument must be given as a string.");
  6107. if (goldStash === null) throw new Error("You must have a gold stash to be able to use this.");
  6108.  
  6109. this.overlayEntities && (this.overlayEntities.length > 0 && this.overlayEntities.map(e => game.renderer.ui.removeAttachment(e)));
  6110. this.overlayEntities = [];
  6111. this.overlayDesign = design;
  6112. this.isShowingOverlay = true;
  6113. game.renderer.follow(game.world.entities[goldStash.uid]);
  6114. setTimeout(() => {
  6115. const towers = design.split(";"),
  6116. schema = game.ui.getBuildingSchema();
  6117.  
  6118. for (let towerStr of towers) {
  6119. const towerData = towerStr.split(",");
  6120. const [type, xWorld, yWorld, yaw] = towerData;
  6121. const towerLength = towerData.length
  6122.  
  6123. if (type === "") continue;
  6124. if (towerLength.length < 4) throw new Error(`${JSON.stringify(towerLength)} contains an issue that must be fixed before this design can be replicated.`);
  6125.  
  6126. const buildingType = schema[towerCodes[parseInt(type)]],
  6127. placeholderEntity = Game.currentGame.assetManager.loadModel(buildingType.modelName, {}),
  6128. { x, y } = game.renderer.worldToUi(goldStash.x - parseInt(xWorld), goldStash.y - parseInt(yWorld));
  6129. placeholderEntity.setAlpha(0.5);
  6130. placeholderEntity.setRotation(parseInt(yaw));
  6131. placeholderEntity.setPosition(x, y);
  6132.  
  6133. Game.currentGame.renderer.ui.addAttachment(placeholderEntity);
  6134. this.overlayEntities.push(placeholderEntity);
  6135. }
  6136. timeout && setTimeout(this.hideOverlay.bind(this), timeout);
  6137. }, 50);
  6138. },
  6139.  
  6140. hideOverlay: function() {
  6141. for (let entity of this.overlayEntities) game.renderer.ui.removeAttachment(entity);
  6142. game.renderer.follow(game.world.entities[game.world.myUid]);
  6143. this.isShowingOverlay = false;
  6144. this.overlayDesign = null;
  6145. },
  6146.  
  6147. onResize: function() {
  6148. this.isShowingOverlay && this.showOverlay(this.overlayDesign);
  6149. },
  6150. init: function() {
  6151. window.addEventListener("resize", this.onResize.bind(this));
  6152. document.addEventListener("zoom", this.onResize.bind(this));
  6153. },
  6154. },
  6155. sessions: {
  6156. SESSION_CREATE_TIMEOUT: 15000,
  6157. SESSION_FETCH_TIMEOUT: 10000,
  6158.  
  6159. staticJSONs: [{name:"BuildingShopPrices",response:{json:'[{"Name":"Wall","Class":"PlayerObject","GoldCosts":[0,5,30,60,80,100,250,800],"WoodCosts":[2,0,0,0,0,0,0,0],"StoneCosts":[0,2,0,0,0,0,0,0],"TokenCosts":[0,0,0,0,0,0,0,0],"Width":47.99,"Height":47.99,"Health":[150,200,300,400,600,800,1500,2500],"MsBeforeRegen":[10000,10000,10000,10000,10000,10000,10000,10000],"HealthRegenPerSecond":[5,7,12,17,25,40,80,250]},{"Name":"GoldStash","Class":"GoldStash","GoldCosts":[0,5000,10000,16000,20000,32000,100000,400000],"WoodCosts":[0,0,0,0,0,0,0,0],"StoneCosts":[0,0,0,0,0,0,0,0],"TokenCosts":[0,0,0,0,0,0,0,0],"Width":95.99,"Height":95.99,"Health":[1500,1800,2300,3000,5000,8000,12000,20000],"MsBeforeRegen":[10000,10000,10000,10000,10000,10000,10000,10000],"HealthRegenPerSecond":[50,60,70,90,110,150,400,700]},{"Name":"GoldMine","Class":"GoldMine","GoldCosts":[0,200,300,600,800,1200,8000,30000],"WoodCosts":[5,15,25,35,45,55,700,1600],"StoneCosts":[5,15,25,35,45,55,700,1600],"TokenCosts":[0,0,0,0,0,0,0,0],"Width":95.99,"Height":95.99,"Health":[150,250,350,500,800,1400,1800,2800],"GoldPerSecond":[4,6,7,10,12,15,25,35],"MsBeforeRegen":[10000,10000,10000,10000,10000,10000,10000,10000],"HealthRegenPerSecond":[5,7,12,17,25,40,70,120]},{"Name":"Door","Class":"Door","GoldCosts":[0,10,50,70,150,200,400,800],"WoodCosts":[5,5,0,0,0,0,0,0],"StoneCosts":[5,5,0,0,0,0,0,0],"TokenCosts":[0,0,0,0,0,0,0,0],"Width":47.99,"Height":47.99,"Health":[150,200,300,500,700,1000,1500,2000],"MsBeforeRegen":[10000,10000,10000,10000,10000,10000,10000,1000],"HealthRegenPerSecond":[5,7,12,17,25,40,70,100]},{"Name":"CannonTower","Class":"Tower","GoldCosts":[0,100,200,600,1200,2000,8000,35000],"WoodCosts":[15,25,30,40,60,80,300,800],"StoneCosts":[15,25,40,50,80,120,300,800],"TokenCosts":[0,0,0,0,0,0,0,0],"TowerRadius":[500,500,500,500,600,600,600,600],"MsBetweenFires":[1000,769,625,500,400,350,250,250],"Height":95.99,"Width":95.99,"Health":[150,200,400,800,1200,1600,2200,3600],"MsBeforeRegen":[10000,10000,10000,10000,10000,10000,10000,10000],"HealthRegenPerSecond":[2,5,10,20,40,80,110,150],"DamageToZombies":[20,30,50,70,120,150,200,300],"DamageToPlayers":[5,5,6,6,7,7,8,8],"DamageToPets":[5,5,5,5,5,5,6,8],"DamageToNeutrals":[250,350,450,550,650,750,850,1000],"ProjectileLifetime":[1000,1000,1000,1000,1000,1000,1000,1000],"ProjectileVelocity":[60,65,70,70,75,80,100,140],"ProjectileName":"CannonProjectile","ProjectileAoe":[true,true,true,true,true,true,true,true],"ProjectileAoeRadius":[250,250,250,250,250,250,250,250],"ProjectileCollisionRadius":[10,10,10,10,10,10,10,10]},{"Name":"ArrowTower","Class":"ArrowTower","GoldCosts":[0,100,200,600,1200,2000,8000,35000],"WoodCosts":[5,25,30,40,50,70,300,800],"StoneCosts":[5,20,30,40,60,80,300,800],"TokenCosts":[0,0,0,0,0,0,0,0],"TowerRadius":[600,650,700,750,800,850,900,1000],"MsBetweenFires":[400,333,285,250,250,250,250,250],"Height":95.99,"Width":95.99,"Health":[150,200,400,800,1200,1600,2200,3600],"MsBeforeRegen":[10000,10000,10000,10000,10000,10000,10000,10000],"HealthRegenPerSecond":[2,5,10,20,40,80,110,150],"DamageToZombies":[20,40,70,120,180,250,400,500],"DamageToPlayers":[5,5,6,6,7,7,8,8],"DamageToPets":[5,5,5,5,5,5,6,6],"DamageToNeutrals":[250,350,450,550,650,750,850,1000],"ProjectileLifetime":[1300,1300,1300,1300,1300,1300,1300,1300],"ProjectileVelocity":[60,65,70,70,75,80,120,140],"ProjectileName":"ArrowProjectile","ProjectileAoe":[false,false,false,false,false,false,false,false],"ProjectileCollisionRadius":[10,10,10,10,10,10,10,10]},{"Name":"Harvester","Class":"Harvester","GoldCosts":[0,100,200,600,1200,2000,8000,10000],"WoodCosts":[5,25,30,40,50,70,300,600],"StoneCosts":[5,20,30,40,60,80,300,600],"TokenCosts":[0,0,0,0,0,0,0,0],"Height":95.99,"Width":95.99,"Health":[150,200,400,800,1200,1600,2200,2800],"MsBeforeRegen":[10000,10000,10000,10000,10000,10000,10000,10000],"HealthRegenPerSecond":[2,5,10,20,40,80,110,130],"HarvestAmount":[2.5,4.65,4.55,7.2,8.25,10,13.5,16],"HarvestCooldown":[1500,1400,1300,1200,1100,1000,900,800],"HarvestMax":[400,800,1200,1600,2000,2400,2800,3600],"HarvestRange":[300,300,300,300,300,300,300,300],"DepositCostPerMinute":[200,300,350,500,600,700,1200,1400],"DepositMax":[800,1200,1400,2000,2400,2800,4800,6000],"MaxYawDeviation":[70,70,70,70,70,70,70,70]},{"Name":"BombTower","Class":"Tower","GoldCosts":[0,100,200,600,1200,2000,8000,35000],"WoodCosts":[10,25,40,50,80,120,300,800],"StoneCosts":[10,25,40,50,80,120,300,800],"TokenCosts":[0,0,0,0,0,0,0,0],"TowerRadius":[1000,1000,1000,1000,1000,1000,1000,1000],"MsBetweenFires":[1000,1000,1000,1000,1000,1000,900,900],"Height":95.99,"Width":95.99,"Health":[150,200,400,800,1200,1600,2200,3600],"MsBeforeRegen":[10000,10000,10000,10000,10000,10000,10000,10000],"HealthRegenPerSecond":[2,5,10,20,40,80,110,150],"DamageToZombies":[30,60,100,140,200,600,1200,1600],"DamageToPlayers":[9,9,10,10,11,11,12,12],"DamageToPets":[10,10,10,10,10,10,10,10],"DamageToNeutrals":[250,350,450,550,650,750,850,1000],"ProjectileLifetime":[1000,1000,1000,1000,1000,1000,1000,1000],"ProjectileVelocity":[20,20,20,20,20,20,20,20],"ProjectileName":"BombProjectile","ProjectileAoe":[true,true,true,true,true,true,true,true],"ProjectileIgnoresCollisions":[true,true,true,true,true,true,true,true],"ProjectileAoeRadius":[250,250,250,250,250,250,250,250],"ProjectileCollisionRadius":[10,10,10,10,10,10,10,10],"ProjectileMaxRange":[1000,1000,1000,1000,1000,1000,1000,1000]},{"Name":"MagicTower","Class":"MagicTower","GoldCosts":[0,100,200,600,1200,2000,8000,35000],"WoodCosts":[15,25,40,50,70,100,300,800],"StoneCosts":[15,25,40,50,70,100,300,800],"TokenCosts":[0,0,0,0,0,0,0,0],"TowerRadius":[400,400,400,400,400,400,400,400],"MsBetweenFires":[800,800,700,600,500,400,300,300],"Height":95.99,"Width":95.99,"Health":[150,200,400,800,1200,1600,2200,3600],"MsBeforeRegen":[10000,10000,10000,10000,10000,10000,10000,10000],"HealthRegenPerSecond":[2,5,10,20,40,80,110,150],"DamageToZombies":[10,20,40,50,70,80,120,160],"DamageToPlayers":[5,5,5,6,6,6,7,7],"DamageToPets":[5,5,5,5,5,5,5,5],"DamageToNeutrals":[250,350,450,550,650,750,850,1000],"ProjectileLifetime":[500,500,500,500,500,500,500,500],"ProjectileVelocity":[45,45,45,45,45,45,45,45],"ProjectileName":"FireballProjectile","ProjectileAoe":[true,true,true,true,true,true,true,true],"ProjectileAoeRadius":[100,100,100,100,100,100,100,100],"ProjectileCollisionRadius":[10,10,10,10,10,10,10,10]},{"Name":"MeleeTower","Class":"MeleeTower","GoldCosts":[0,100,200,600,1200,2000,8000,35000],"WoodCosts":[10,25,30,40,50,70,300,800],"StoneCosts":[10,20,30,40,60,80,300,800],"TokenCosts":[0,0,0,0,0,0,0,0],"TowerRadius":[110,110,110,110,110,110,110,110],"MsBetweenFires":[400,333,285,250,250,250,250,250],"Height":95.99,"Width":95.99,"Health":[200,400,800,1200,1600,2200,4000,9000],"MsBeforeRegen":[10000,10000,10000,10000,10000,10000,10000,10000],"HealthRegenPerSecond":[2,5,10,20,40,80,220,350],"DamageToZombies":[80,120,200,280,500,1000,2000,3000],"DamageToPlayers":[5,6,7,8,9,10,11,12],"DamageToPets":[5,5,5,5,5,5,6,6],"DamageToNeutrals":[250,350,450,550,650,750,850,1000],"MaxYawDeviation":[30,30,30,30,30,30,30,30]},{"Name":"SlowTrap","Class":"Trap","GoldCosts":[0,100,200,400,600,800,1000,1500],"WoodCosts":[5,25,30,40,50,70,300,800],"StoneCosts":[5,20,30,40,60,80,300,800],"TokenCosts":[0,0,0,0,0,0,0,0],"Height":47.99,"Width":47.99,"Health":[150,200,400,800,1200,1600,2200,3000],"MsBeforeRegen":[10000,10000,10000,10000,10000,10000,10000,10000],"HealthRegenPerSecond":[2,5,10,20,40,80,110,150],"SlowDuration":[2500,2500,2500,3000,3000,3250,3500,4000],"SlowAmount":[0.4,0.45,0.5,0.55,0.6,0.65,0.7,0.7]}]'},opcode:9},{name:"ItemShopPrices",response:{json:'[{"Name":"Spear","Class":"MeleeWeapon","MsBetweenFires":[250,250,250,250,250,250,250],"DamageToZombies":[30,80,120,300,2000,8000,10000],"DamageToNeutrals":[50,80,100,200,250,400,600],"DamageToBuildings":[0.75,1.5,2.25,3,3.75,4.5,5.25],"DamageToPlayers":[15,16,17,18,20,22,22],"DamageToPets":[3,3.5,4,4.5,5,5.5,5.5],"GoldCosts":[1400,2800,5600,11200,22500,45000,90000],"StoneCosts":[0,0,0,0,0,0,0],"WoodCosts":[0,0,0,0,0,0,0],"TokenCosts":[0,0,0,0,0,0,0],"Range":[100,100,100,100,100,100,100],"MaxYawDeviation":[50,50,50,50,50,50,50]},{"Name":"Pickaxe","Class":"MeleeWeapon","MsBetweenFires":[300,300,285,250,200,200,200],"DamageToZombies":[20,20,20,20,20,20,20],"DamageToBuildings":[0,0,0,0,0,0,0],"DamageToPlayers":[0,0,0,0,0,0,0],"DamageToNeutrals":[10,10,10,10,10,10,10],"DamageToPets":[0,0,0,0,0,0,0],"GoldCosts":[0,1000,3000,6000,8000,24000,90000],"StoneCosts":[0,0,0,0,0,0,0],"WoodCosts":[0,0,0,0,0,0,0],"TokenCosts":[0,0,0,0,0,0,0],"Range":[100,100,100,100,100,100,100],"MaxYawDeviation":[70,70,70,70,70,70,70],"IsTool":true,"HarvestCount":[1,2,2,3,3,4,6]},{"Name":"Bow","Class":"RangedWeapon","DamageToZombies":[20,40,100,300,2400,10000,14000],"DamageToBuildings":[2,2.3,2.5,2.7,3,3,3],"DamageToPlayers":[22,24,26,28,30,32,32],"DamageToNeutrals":[50,100,150,200,250,400,700],"DamageToPets":[2,2.3,2.5,2.7,3,3,3],"GoldCosts":[100,400,2000,7000,24000,30000,90000],"StoneCosts":[0,0,0,0,0,0,0],"WoodCosts":[0,0,0,0,0,0,0],"TokenCosts":[0,0,0,0,0,0,0],"MsBetweenFires":[500,500,500,500,500,500,500],"ChargeTime":[150,150,150,150,150,150,150],"ProjectileVelocity":[100,100,100,100,100,100,100],"ProjectileName":"BowProjectile","ProjectileCollisionRadius":[10,10,10,10,10,10,10],"ProjectileLifetime":[550,550,550,550,550,550,550]},{"Name":"Bomb","Class":"RangedWeapon","GoldCosts":[100,400,3000,5000,24000,30000,90000],"DamageToNeutrals":[50,100,150,200,250,300,500],"StoneCosts":[0,0,0,0,0,0,0],"WoodCosts":[0,0,0,0,0,0,0],"TokenCosts":[0,0,0,0,0,0,0],"MsBetweenFires":[500,500,500,500,500,500,500],"DamageToZombies":[10,30,80,150,1200,6000,9000],"DamageToBuildings":[1,1,1,1,1,1,1],"DamageToPlayers":[20,22,24,26,28,30,30],"DamageToPets":[1,1,1,1,1,1,1],"ProjectileVelocity":[40,40,40,40,40,40,40],"ProjectileName":"BombProjectile","ProjectileCollisionRadius":[10,10,10,10,10,10,10],"ProjectileLifetime":[700,700,700,700,700,700,700],"ProjectileAoe":[true,true,true,true,true,true,true],"ProjectileAoeRadius":[50,50,50,50,50,50,50],"ProjectileIgnoresCollisions":[false,false,false,false,false,false,false],"ProjectileMaxRange":[700,700,700,700,700,700,700]},{"Name":"HealthPotion","Class":"HealthPotion","GoldCosts":[100],"StoneCosts":[0],"WoodCosts":[0],"TokenCosts":[0],"PurchaseCooldown":15000},{"Name":"ZombieShield","Class":"ZombieShield","GoldCosts":[1000,3000,7000,14000,18000,22000,24000,30000,45000,70000],"StoneCosts":[0,0,0,0,0,0,0,0,0,0],"WoodCosts":[0,0,0,0,0,0,0,0,0,0],"TokenCosts":[0,0,0,0,0,0,0,0,0,0],"Health":[500,1000,1800,4000,10000,20000,35000,50000,65000,85000],"RechargePerSecond":[50,100,200,400,1000,2000,3500,5000,6500,8500],"MsBeforeRecharge":[10000,9000,8000,7000,6000,6000,6000,6000,6000,6000]},{"Name":"Pause","Class":"Pause","GoldCosts":[10000],"StoneCosts":[0],"WoodCosts":[0],"TokenCosts":[0],"PurchaseCooldown":240000},{"Name":"PetMiner","Class":"Pet","GoldCosts":[0,0,0,0,0,0,0,0],"WoodCosts":[0,0,0,0,0,0,0,0],"StoneCosts":[0,0,0,0,0,0,0,0],"TokenCosts":[0,100,100,100,100,200,200,300],"CollisionRadius":25,"Health":[400,800,1500,3000,5000,8000,10000,16000],"MsBeforeRegen":[8000,8000,8000,8000,8000,8000,8000,8000],"HealthRegenPerSecond":[5,5,5,5,5,5,5,5],"Speed":[30,32,34,35,35,37,37,38],"DamageToNeutrals":[80,100,150,200,250,400,500,600],"HarvestCount":[1,1,2,2,3,3,4,4],"Ranged":[false,false,false,false,false,false,false,false],"CanAttackPlayers":[false,false,false,false,false,false,false,false],"CanMine":[true,true,true,true,true,true,true,true],"LeashRange":[500,500,500,500,500,500,500,500],"HarvestLeashRange":[0,0,0,0,0,0,0,0],"AttackRange":[80,80,80,80,80,80,80,80],"MsBetweenFires":[500,450,450,400,400,380,380,350],"EvolvesAtLevel":[0,8,16,24,32,48,64,96],"ExperienceFromMiningPerHalfSecond":[1,1,1,1,1,1,1,1]},{"Name":"PetCARL","Class":"Pet","GoldCosts":[0,0,0,0,0,0,0,0],"WoodCosts":[0,0,0,0,0,0,0,0],"StoneCosts":[0,0,0,0,0,0,0,0],"TokenCosts":[0,100,100,100,100,200,200,300],"CollisionRadius":25,"Health":[400,800,1500,3000,5000,8000,10000,16000],"MsBeforeRegen":[8000,8000,8000,8000,8000,8000,8000,8000],"HealthRegenPerSecond":[5,5,5,5,5,5,5,5],"Speed":[30,32,34,35,35,37,37,38],"DamageToNeutrals":[80,100,150,200,250,400,500,600],"Ranged":[false,false,false,false,false,false,false,false],"CanAttackPlayers":[true,true,true,true,true,true,true,true],"LeashRange":[500,500,500,500,500,500,500,500],"AttackRange":[80,80,80,80,80,80,80,80],"MsBetweenFires":[500,490,490,490,480,480,470,470],"ProjectileLifetime":[1000,1000,1000,1000,1000,1000,1000,1000],"ProjectileVelocity":[60,60,60,60,60,60,60,60],"ProjectileName":"PetCARLProjectile","ProjectileAoe":[true,true,true,true,true,true,true,true],"ProjectileAoeRadius":[250,250,250,250,250,250,250,250],"ProjectileCollisionRadius":[10,10,10,10,10,10,10,10],"DamageToZombies":[30,100,400,600,1000,3000,6000,8000],"DamageToPlayers":[30,31,32,33,34,35,36,37],"DamageToBuildings":[2,2,2,3,3,3,4,4],"EvolvesAtLevel":[0,8,16,24,32,48,64,96],"ExperienceFromZombies":[30,28,25,25,25,25,25,25],"ExperienceFromNeutrals":[30,28,25,25,25,25,25,25]},{"Name":"HatHorns","Class":"Hat","GoldCosts":[0],"WoodCosts":[0],"StoneCosts":[0],"TokenCosts":[0]},{"Name":"PetHealthPotion","Class":"PetHealthPotion","GoldCosts":[100],"StoneCosts":[0],"WoodCosts":[0],"TokenCosts":[0]},{"Name":"PetWhistle","Class":"PetWhistle","GoldCosts":[0],"StoneCosts":[0],"WoodCosts":[0],"TokenCosts":[0]},{"Name":"PetRevive","Class":"PetRevive","GoldCosts":[0],"StoneCosts":[0],"WoodCosts":[0],"TokenCosts":[0]}]'},opcode:9},{name:"Spells",response:{json:'[{"Name":"HealTowersSpell","VisualLifetime":10000,"VisualRadius":600,"Cooldown":[240000],"IsCooldownForParty":true,"Healing":[{"Type":"Tower","Amount":[50],"Over":[10000],"Radius":[600]}],"GoldCosts":[1000],"WoodCosts":[0],"StoneCosts":[0],"TokenCosts":[0]}]'},opcode:9}],
  6160. codecJSON: '{"attributeMaps":{"667546015":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"tier","type":1},{"name":"partyId","type":1},{"name":"lastPetDamage","type":3},{"name":"lastPetDamageTick","type":1},{"name":"lastPetDamageTarget","type":1},{"name":"firingTick","type":1},{"name":"experience","type":1},{"name":"stoneGain","type":3},{"name":"woodGain","type":3},{"name":"stoneGainTick","type":1},{"name":"woodGainTick","type":1}],"742594995":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"tier","type":1},{"name":"partyId","type":1}],"1059671174":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"firingTick","type":1},{"name":"lastDamagedTick","type":1}],"1372600389":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"hits","type":8}],"1496910567":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"firingTick","type":1}],"1566069472":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"tier","type":1},{"name":"partyId","type":1}],"1672634632":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1}],"1816895259":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1}],"2092990061":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"tier","type":1},{"name":"partyId","type":1}],"2093252446":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"hits","type":8}],"2347737811":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"reconnectSecret","type":4},{"name":"name","type":4},{"name":"score","type":13},{"name":"baseSpeed","type":3},{"name":"speedAttribute","type":3},{"name":"availableSkillPoints","type":2},{"name":"experience","type":3},{"name":"level","type":1},{"name":"msBetweenFires","type":3},{"name":"aimingYaw","type":2},{"name":"energy","type":3},{"name":"maxEnergy","type":3},{"name":"energyRegenerationRate","type":3},{"name":"kills","type":2},{"name":"weaponName","type":4},{"name":"weaponTier","type":1},{"name":"firingTick","type":1},{"name":"startChargingTick","type":1},{"name":"stone","type":15},{"name":"wood","type":15},{"name":"gold","type":15},{"name":"token","type":15},{"name":"wave","type":1},{"name":"partyId","type":1},{"name":"zombieShieldHealth","type":3},{"name":"zombieShieldMaxHealth","type":3},{"name":"isPaused","type":1},{"name":"isInvulnerable","type":1},{"name":"lastPetDamage","type":3},{"name":"lastPetDamageTick","type":1},{"name":"lastPetDamageTarget","type":1},{"name":"lastDamage","type":3},{"name":"lastDamageTick","type":1},{"name":"lastDamageTarget","type":1},{"name":"hatName","type":4},{"name":"petUid","type":1},{"name":"isBuildingWalking","type":10}],"2402467733":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"tier","type":1},{"name":"partyId","type":1}],"2462472648":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"tier","type":1}],"2464630638":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"tier","type":1},{"name":"partyId","type":1}],"2899981078":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"tier","type":1},{"name":"partyId","type":1},{"name":"harvestMax","type":1},{"name":"stone","type":1},{"name":"wood","type":1},{"name":"firingTick","type":1},{"name":"deposit","type":3},{"name":"depositMax","type":3},{"name":"lastHarvestedBy","type":4}],"2969697641":[{"name":"position","type":5},{"name":"yaw","type":2},{"name":"health","type":3},{"name":"maxHealth","type":3},{"name":"damage","type":3},{"name":"height","type":3},{"name":"width","type":3},{"name":"collisionRadius","type":1},{"name":"model","type":4},{"name":"entityClass","type":4},{"name":"dead","type":1},{"name":"timeDead","type":3},{"name":"slowed","type":1},{"name":"stunned","type":1},{"name":"tier","type":1},{"name":"partyId","type":1},{"name":"towerYaw","type":3},{"name":"firingTick","type":1},{"name":"healingTick","type":1}]},"entityTypeNames":{"667546015":"Pet","742594995":"GoldMine","1059671174":"Zombie","1372600389":"Stone","1496910567":"Neutral","1566069472":"PlayerObject","1672634632":"NeutralCamp","1816895259":"GameProjectile","2092990061":"Trap","2093252446":"Tree","2347737811":"GamePlayer","2402467733":"GoldStash","2462472648":"Spell","2464630638":"Door","2899981078":"Harvester","2969697641":"Tower"},"rpcMaps":[{"name":"Shutdown","parameters":[{"name":"reason","type":3},{"name":"shutdownUnix","type":0}],"isArray":false,"index":0},{"name":"ReceiveChatMessage","parameters":[{"name":"displayName","type":3},{"name":"channel","type":3},{"name":"message","type":3},{"name":"uid","type":0}],"isArray":false,"index":1},{"name":"SendChatMessage","parameters":[{"name":"channel","type":3},{"name":"message","type":3}],"isArray":false,"index":2},{"name":"Login","parameters":[{"name":"token","type":3}],"isArray":false,"index":3},{"name":"LoginResponse","parameters":[{"name":"json","type":3}],"isArray":false,"index":4},{"name":"AccountSession","parameters":[{"name":"json","type":3}],"isArray":false,"index":5},{"name":"Metrics","parameters":[{"name":"minFps","type":2},{"name":"maxFps","type":2},{"name":"currentFps","type":2},{"name":"averageFps","type":2},{"name":"framesRendered","type":2},{"name":"framesInterpolated","type":2},{"name":"framesExtrapolated","type":2},{"name":"allocatedNetworkEntities","type":2},{"name":"currentClientLag","type":2},{"name":"minClientLag","type":2},{"name":"maxClientLag","type":2},{"name":"currentPing","type":2},{"name":"minPing","type":2},{"name":"maxPing","type":2},{"name":"averagePing","type":2},{"name":"longFrames","type":2},{"name":"stutters","type":2},{"name":"group","type":0},{"name":"isMobile","type":0},{"name":"timeResets","type":2},{"name":"maxExtrapolationTime","type":2},{"name":"extrapolationIncidents","type":2},{"name":"totalExtrapolationTime","type":2},{"name":"differenceInClientTime","type":2}],"isArray":false,"index":6},{"name":"DayCycle","parameters":[{"name":"cycleStartTick","type":0},{"name":"nightEndTick","type":0},{"name":"dayEndTick","type":0},{"name":"isDay","type":0}],"isArray":false,"index":7},{"name":"MakeBuilding","parameters":[{"name":"x","type":1},{"name":"y","type":1},{"name":"type","type":3},{"name":"yaw","type":1}],"isArray":false,"index":8},{"name":"BuildingShopPrices","parameters":[{"name":"json","type":3}],"isArray":false,"index":9},{"name":"ItemShopPrices","parameters":[{"name":"json","type":3},{"name":"json","type":3}],"isArray":false,"index":10},{"name":"LocalBuilding","parameters":[{"name":"x","type":1},{"name":"y","type":1},{"name":"type","type":3},{"name":"dead","type":0},{"name":"uid","type":0},{"name":"tier","type":0}],"isArray":true,"index":11},{"name":"Dead","parameters":[{"name":"stashDied","type":0}],"isArray":false,"index":12},{"name":"Admin","parameters":[{"name":"password","type":3},{"name":"command","type":3}],"isArray":false,"index":13},{"name":"UpgradeBuilding","parameters":[{"name":"uid","type":0}],"isArray":false,"index":14},{"name":"DeleteBuilding","parameters":[{"name":"uid","type":0}],"isArray":false,"index":15},{"name":"BuyItem","parameters":[{"name":"itemName","type":3},{"name":"tier","type":0}],"isArray":false,"index":16},{"name":"SetItem","parameters":[{"name":"itemName","type":3},{"name":"tier","type":0},{"name":"stacks","type":0}],"isArray":false,"index":17},{"name":"EquipItem","parameters":[{"name":"itemName","type":3},{"name":"tier","type":0}],"isArray":false,"index":18},{"name":"SetOpenParty","parameters":[{"name":"isOpen","type":0}],"isArray":false,"index":19},{"name":"SetPartyName","parameters":[{"name":"partyName","type":3}],"isArray":false,"index":20},{"name":"SetPartyMemberCanSell","parameters":[{"name":"uid","type":0},{"name":"canSell","type":0}],"isArray":false,"index":21},{"name":"JoinParty","parameters":[{"name":"partyId","type":0}],"isArray":false,"index":22},{"name":"JoinPartyByShareKey","parameters":[{"name":"partyShareKey","type":3}],"isArray":false,"index":23},{"name":"PartyApplicant","parameters":[{"name":"displayName","type":3},{"name":"applicantUid","type":0}],"isArray":false,"index":24},{"name":"PartyApplicantDecide","parameters":[{"name":"applicantUid","type":0},{"name":"accepted","type":0}],"isArray":false,"index":25},{"name":"PartyApplicantDenied","parameters":[],"isArray":false,"index":26},{"name":"PartyApplicantExpired","parameters":[{"name":"applicantUid","type":0}],"isArray":false,"index":27},{"name":"PartyShareKey","parameters":[{"name":"partyShareKey","type":3}],"isArray":false,"index":28},{"name":"PartyInfo","parameters":[{"name":"playerUid","type":0},{"name":"displayName","type":3},{"name":"isLeader","type":0},{"name":"canSell","type":0}],"isArray":true,"index":29},{"name":"AddParty","parameters":[{"name":"partyId","type":0},{"name":"partyName","type":3},{"name":"isOpen","type":0},{"name":"memberCount","type":0}],"isArray":false,"index":30},{"name":"RemoveParty","parameters":[{"name":"partyId","type":0}],"isArray":false,"index":31},{"name":"Leaderboard","parameters":[{"name":"name","type":3},{"name":"uid","type":0},{"name":"rank","type":0},{"name":"score","type":4},{"name":"wave","type":0}],"isArray":true,"index":32},{"name":"Failure","parameters":[{"name":"category","type":3},{"name":"reason","type":3},{"name":"x","type":0},{"name":"y","type":0},{"name":"type","type":3}],"isArray":false,"index":33},{"name":"RecallPet","parameters":[],"isArray":false,"index":34},{"name":"LeaveParty","parameters":[],"isArray":false,"index":35},{"name":"KickParty","parameters":[{"name":"uid","type":0}],"isArray":false,"index":36},{"name":"AddDepositToHarvester","parameters":[{"name":"uid","type":0},{"name":"deposit","type":2}],"isArray":false,"index":37},{"name":"CollectHarvester","parameters":[{"name":"uid","type":0}],"isArray":false,"index":38},{"name":"CastSpell","parameters":[{"name":"spell","type":3},{"name":"x","type":1},{"name":"y","type":1},{"name":"tier","type":0}],"isArray":false,"index":39},{"name":"CastSpellResponse","parameters":[{"name":"spell","type":3},{"name":"cooldown","type":0},{"name":"cooldownStartTick","type":0}],"isArray":false,"index":40},{"name":"Spells","parameters":[{"name":"json","type":3}],"isArray":false,"index":41},{"name":"SetPartyList","parameters":[{"name":"partyId","type":0},{"name":"partyName","type":3},{"name":"isOpen","type":0},{"name":"memberCount","type":0}],"isArray":true,"index":42}],"rpcMapsByName":{"Shutdown":{"name":"Shutdown","parameters":[{"name":"reason","type":3},{"name":"shutdownUnix","type":0}],"isArray":false,"index":0},"ReceiveChatMessage":{"name":"ReceiveChatMessage","parameters":[{"name":"displayName","type":3},{"name":"channel","type":3},{"name":"message","type":3},{"name":"uid","type":0}],"isArray":false,"index":1},"SendChatMessage":{"name":"SendChatMessage","parameters":[{"name":"channel","type":3},{"name":"message","type":3}],"isArray":false,"index":2},"Login":{"name":"Login","parameters":[{"name":"token","type":3}],"isArray":false,"index":3},"LoginResponse":{"name":"LoginResponse","parameters":[{"name":"json","type":3}],"isArray":false,"index":4},"AccountSession":{"name":"AccountSession","parameters":[{"name":"json","type":3}],"isArray":false,"index":5},"Metrics":{"name":"Metrics","parameters":[{"name":"minFps","type":2},{"name":"maxFps","type":2},{"name":"currentFps","type":2},{"name":"averageFps","type":2},{"name":"framesRendered","type":2},{"name":"framesInterpolated","type":2},{"name":"framesExtrapolated","type":2},{"name":"allocatedNetworkEntities","type":2},{"name":"currentClientLag","type":2},{"name":"minClientLag","type":2},{"name":"maxClientLag","type":2},{"name":"currentPing","type":2},{"name":"minPing","type":2},{"name":"maxPing","type":2},{"name":"averagePing","type":2},{"name":"longFrames","type":2},{"name":"stutters","type":2},{"name":"group","type":0},{"name":"isMobile","type":0},{"name":"timeResets","type":2},{"name":"maxExtrapolationTime","type":2},{"name":"extrapolationIncidents","type":2},{"name":"totalExtrapolationTime","type":2},{"name":"differenceInClientTime","type":2}],"isArray":false,"index":6},"DayCycle":{"name":"DayCycle","parameters":[{"name":"cycleStartTick","type":0},{"name":"nightEndTick","type":0},{"name":"dayEndTick","type":0},{"name":"isDay","type":0}],"isArray":false,"index":7},"MakeBuilding":{"name":"MakeBuilding","parameters":[{"name":"x","type":1},{"name":"y","type":1},{"name":"type","type":3},{"name":"yaw","type":1}],"isArray":false,"index":8},"BuildingShopPrices":{"name":"BuildingShopPrices","parameters":[{"name":"json","type":3}],"isArray":false,"index":9},"ItemShopPrices":{"name":"ItemShopPrices","parameters":[{"name":"json","type":3},{"name":"json","type":3}],"isArray":false,"index":10},"LocalBuilding":{"name":"LocalBuilding","parameters":[{"name":"x","type":1},{"name":"y","type":1},{"name":"type","type":3},{"name":"dead","type":0},{"name":"uid","type":0},{"name":"tier","type":0}],"isArray":true,"index":11},"Dead":{"name":"Dead","parameters":[{"name":"stashDied","type":0}],"isArray":false,"index":12},"Admin":{"name":"Admin","parameters":[{"name":"password","type":3},{"name":"command","type":3}],"isArray":false,"index":13},"UpgradeBuilding":{"name":"UpgradeBuilding","parameters":[{"name":"uid","type":0}],"isArray":false,"index":14},"DeleteBuilding":{"name":"DeleteBuilding","parameters":[{"name":"uid","type":0}],"isArray":false,"index":15},"BuyItem":{"name":"BuyItem","parameters":[{"name":"itemName","type":3},{"name":"tier","type":0}],"isArray":false,"index":16},"SetItem":{"name":"SetItem","parameters":[{"name":"itemName","type":3},{"name":"tier","type":0},{"name":"stacks","type":0}],"isArray":false,"index":17},"EquipItem":{"name":"EquipItem","parameters":[{"name":"itemName","type":3},{"name":"tier","type":0}],"isArray":false,"index":18},"SetOpenParty":{"name":"SetOpenParty","parameters":[{"name":"isOpen","type":0}],"isArray":false,"index":19},"SetPartyName":{"name":"SetPartyName","parameters":[{"name":"partyName","type":3}],"isArray":false,"index":20},"SetPartyMemberCanSell":{"name":"SetPartyMemberCanSell","parameters":[{"name":"uid","type":0},{"name":"canSell","type":0}],"isArray":false,"index":21},"JoinParty":{"name":"JoinParty","parameters":[{"name":"partyId","type":0}],"isArray":false,"index":22},"JoinPartyByShareKey":{"name":"JoinPartyByShareKey","parameters":[{"name":"partyShareKey","type":3}],"isArray":false,"index":23},"PartyApplicant":{"name":"PartyApplicant","parameters":[{"name":"displayName","type":3},{"name":"applicantUid","type":0}],"isArray":false,"index":24},"PartyApplicantDecide":{"name":"PartyApplicantDecide","parameters":[{"name":"applicantUid","type":0},{"name":"accepted","type":0}],"isArray":false,"index":25},"PartyApplicantDenied":{"name":"PartyApplicantDenied","parameters":[],"isArray":false,"index":26},"PartyApplicantExpired":{"name":"PartyApplicantExpired","parameters":[{"name":"applicantUid","type":0}],"isArray":false,"index":27},"PartyShareKey":{"name":"PartyShareKey","parameters":[{"name":"partyShareKey","type":3}],"isArray":false,"index":28},"PartyInfo":{"name":"PartyInfo","parameters":[{"name":"playerUid","type":0},{"name":"displayName","type":3},{"name":"isLeader","type":0},{"name":"canSell","type":0}],"isArray":true,"index":29},"AddParty":{"name":"AddParty","parameters":[{"name":"partyId","type":0},{"name":"partyName","type":3},{"name":"isOpen","type":0},{"name":"memberCount","type":0}],"isArray":false,"index":30},"RemoveParty":{"name":"RemoveParty","parameters":[{"name":"partyId","type":0}],"isArray":false,"index":31},"Leaderboard":{"name":"Leaderboard","parameters":[{"name":"name","type":3},{"name":"uid","type":0},{"name":"rank","type":0},{"name":"score","type":4},{"name":"wave","type":0}],"isArray":true,"index":32},"Failure":{"name":"Failure","parameters":[{"name":"category","type":3},{"name":"reason","type":3},{"name":"x","type":0},{"name":"y","type":0},{"name":"type","type":3}],"isArray":false,"index":33},"RecallPet":{"name":"RecallPet","parameters":[],"isArray":false,"index":34},"LeaveParty":{"name":"LeaveParty","parameters":[],"isArray":false,"index":35},"KickParty":{"name":"KickParty","parameters":[{"name":"uid","type":0}],"isArray":false,"index":36},"AddDepositToHarvester":{"name":"AddDepositToHarvester","parameters":[{"name":"uid","type":0},{"name":"deposit","type":2}],"isArray":false,"index":37},"CollectHarvester":{"name":"CollectHarvester","parameters":[{"name":"uid","type":0}],"isArray":false,"index":38},"CastSpell":{"name":"CastSpell","parameters":[{"name":"spell","type":3},{"name":"x","type":1},{"name":"y","type":1},{"name":"tier","type":0}],"isArray":false,"index":39},"CastSpellResponse":{"name":"CastSpellResponse","parameters":[{"name":"spell","type":3},{"name":"cooldown","type":0},{"name":"cooldownStartTick","type":0}],"isArray":false,"index":40},"Spells":{"name":"Spells","parameters":[{"name":"json","type":3}],"isArray":false,"index":41},"SetPartyList":{"name":"SetPartyList","parameters":[{"name":"partyId","type":0},{"name":"partyName","type":3},{"name":"isOpen","type":0},{"name":"memberCount","type":0}],"isArray":true,"index":42}}}',
  6161.  
  6162. useSes: false,
  6163. currentSesId: null,
  6164.  
  6165. allSessions: null,
  6166. endpoints: {
  6167. localhost: {
  6168. secret: 'f07cbf563d19619ba4afe3ae1e2ec95710a72b3e',
  6169. https: false,
  6170. wss: "localhost:727",
  6171. api: "localhost:728",
  6172. },
  6173. },
  6174.  
  6175. nameInput: getClass("hud-intro-name")[0],
  6176. serverSelect: getClass("hud-intro-server")[0],
  6177. overlayElem: getId("hud-intro-overlay"),
  6178.  
  6179. sesSelect: document.createElement("select"),
  6180. delBtn: document.createElement("button"),
  6181. addBtn: document.createElement("button"),
  6182. init: async function() {
  6183. this.addBtn.id = "addBtn";
  6184. this.addBtn.innerText = "Add...";
  6185. document.querySelector("#hud-intro > div.hud-intro-wrapper > div > div").insertAdjacentElement("afterbegin", this.addBtn);
  6186.  
  6187. this.delBtn.id = "delBtn";
  6188. this.delBtn.innerText = "Delete";
  6189. document.querySelector("#hud-intro > div.hud-intro-wrapper > div > div").insertAdjacentElement("afterbegin", this.delBtn);
  6190.  
  6191. this.sesSelect.disabled = true;
  6192. this.sesSelect.id = "sesSelect";
  6193. document.querySelector("#hud-intro > div.hud-intro-wrapper > div > div").insertAdjacentElement("afterbegin", this.sesSelect);
  6194.  
  6195. getId("hud-intro-overlay").insertAdjacentHTML("beforeend", `
  6196. <div id="select-session-add">
  6197. <h2>Which one do wish to add?</h2>
  6198. <button id="add-endpoint">Add a new endpoint</button>
  6199. <button id="add-session">Add a new session</button>
  6200. </div>
  6201. <div id="endpoint-add-menu">
  6202. <h2>Endpoint info</h2>
  6203. <p>Nickname</p>
  6204. <input id="endpoint-name" placeholder="somecoolname" />
  6205. <p>Server URL</p>
  6206. <input id="endpoint-server" placeholder="domain:port" />
  6207. <p>API URL</p>
  6208. <input id="endpoint-api" placeholder="domain:port" />
  6209. <p>Secret key</p>
  6210. <input id="endpoint-secret" placeholder="0123456789abcdef" />
  6211. <p>Protocol</p>
  6212. <select id="endpoint-protocol">
  6213. <option value="http" selected>HTTP</option>
  6214. <option value="https">HTTPS</option>
  6215. </select>
  6216. <div class="session-navigator">
  6217. <button class="session-back"><i class="fa-solid fa-chevron-left"></i></button>
  6218. <button id="create-endpoint"><i class="fa-solid fa-check"></i></button>
  6219. </div>
  6220. </div>
  6221. <div id="session-add-menu">
  6222. <h2>Session creation info</h2>
  6223. <strong>You can leave the Party share key field empty.</strong>
  6224. <p>Endpoint</p>
  6225. <select id="session-endpoint">
  6226. ${Object.keys(this.endpoints).map((name) => {
  6227. return `<option value="${window.filterXSS(name)}" selected>${window.filterXSS(name)}</option>`;
  6228. }).join("\n")}
  6229. </select>
  6230. <p>Username</p>
  6231. <input id="session-nickname" placeholder="AyuLover2911" />
  6232. <p>Server</p>
  6233. <select id="session-server">${this.serverSelect.innerHTML}</select>
  6234. <p>Party share key</p>
  6235. <input id="session-psk" placeholder="abcdefghijklmnopqrstuvwxyz" />
  6236. <div class="session-navigator">
  6237. <button class="session-back"><i class="fa-solid fa-chevron-left"></i></button>
  6238. <button id="create-session"><i class="fa-solid fa-check"></i></button>
  6239. </div>
  6240. </div>
  6241. `);
  6242.  
  6243. getId("useSes").onchange = () => {
  6244. this.useSes = getId("useSes").checked;
  6245. if (this.useSes) {
  6246. this.sesSelect.style.display = "block";
  6247. this.delBtn.style.display = "inline-block";
  6248. this.addBtn.style.display = "inline-block";
  6249.  
  6250. this.nameInput.style.display = "none";
  6251. this.serverSelect.style.display = "none";
  6252.  
  6253. document.documentElement.style.setProperty('--normal-btn', 'rgb(158 74 208)');
  6254. document.documentElement.style.setProperty('--light-hover-btn', 'rgb(213 118 211)');
  6255. document.querySelector("#intro-animation > img").src = "https://cdn.glitch.global/ba7f4151-2a49-416a-985b-56301606ae3d/luna.png?v=1720346619482";
  6256. document.querySelector("#intro-animation > img").style.left = "calc(15vw - 600px)";
  6257. document.querySelector("#hud-intro").setAttribute("style", "--bg-image: url('https://cdn.glitch.global/ba7f4151-2a49-416a-985b-56301606ae3d/Eden%20Conflict.webp?v=1717298976083');");
  6258. } else {
  6259. this.sesSelect.style.display = "none";
  6260. this.delBtn.style.display = "none";
  6261. this.addBtn.style.display = "none";
  6262.  
  6263. this.nameInput.style.display = "block";
  6264. this.serverSelect.style.display = "block";
  6265.  
  6266. document.documentElement.style.setProperty('--normal-btn', 'rgb(40 152 231)');
  6267. document.documentElement.style.setProperty('--light-hover-btn', 'rgb(111 208 247)');
  6268. document.querySelector("#intro-animation > img").src = "https://cdn.glitch.global/ba7f4151-2a49-416a-985b-56301606ae3d/eto_large.png?v=1717285769725";
  6269. document.querySelector("#intro-animation > img").style.left = "calc(15vw - 300px)";
  6270. document.querySelector("#hud-intro").setAttribute("style", "--bg-image: url('https://cdn.glitch.global/ba7f4151-2a49-416a-985b-56301606ae3d/BG_eden_append_light.webp?v=1717285760533');");
  6271. };
  6272. };
  6273.  
  6274. this.delBtn.onclick = () => {
  6275. const [endpoint, sessionId] = this.sesSelect.value.split("/");
  6276. this.deleteSes(endpoint, sessionId);
  6277. };
  6278.  
  6279. this.addBtn.onclick = () => {
  6280. getId("hud-intro").style.display = "block";
  6281. game.ui.components.Intro.hideLoadingScreen();
  6282.  
  6283. this.overlayElem.style.display = "flex";
  6284. this.overlayElem.style.opacity = 1;
  6285. getId("select-session-add").style.display = "flex";
  6286. getId("endpoint-add-menu").style.display = "none";
  6287. getId("session-add-menu").style.display = "none";
  6288. };
  6289. getId("add-endpoint").onclick = () => {
  6290. getId("select-session-add").style.display = "none";
  6291. getId("endpoint-add-menu").style.display = "flex";
  6292. getId("session-add-menu").style.display = "none";
  6293. };
  6294. getId("add-session").onclick = () => {
  6295. getId("select-session-add").style.display = "none";
  6296. getId("endpoint-add-menu").style.display = "none";
  6297. getId("session-add-menu").style.display = "flex";
  6298. };
  6299. for (const backElem of getClass("session-back")) backElem.onclick = () => { this.addBtn.click(); };
  6300. getId("create-endpoint").onclick = () => this.addNewEndpoint(
  6301. getId("endpoint-name").value,
  6302. getId("endpoint-server").value,
  6303. getId("endpoint-api").value,
  6304. getId("endpoint-protocol").value,
  6305. getId("endpoint-secret").value,
  6306. );
  6307. getId("create-session").onclick = () => this.createNewSession(
  6308. getId("session-nickname").value,
  6309. getId("session-server").value,
  6310. getId("session-psk").value,
  6311. getId("session-endpoint").value,
  6312. );
  6313.  
  6314. game.network.establishSessionConnection = function() {
  6315. const [endpoint, sessionId] = game.script.sessions.sesSelect.value.split("/");
  6316. this.connectionOptions = game.script.sessions.allSessions[endpoint][sessionId].connectionOptions;
  6317. this.connected = false;
  6318. this.connecting = true;
  6319. this.codec.rpcMaps = [{
  6320. "name": "SyncData",
  6321. "parameters": [{
  6322. "name": "json",
  6323. "type": 3
  6324. }],
  6325. "isArray": false,
  6326. "index": 0
  6327. }, {
  6328. "name": "VerifyUser",
  6329. "parameters": [{
  6330. "name": "secretKey",
  6331. "type": 3,
  6332. }],
  6333. "isArray": false,
  6334. "index": 1
  6335. }, {
  6336. "name": "ConnectSession",
  6337. "parameters": [{
  6338. "name": "id",
  6339. "type": 3
  6340. }],
  6341. "isArray": false,
  6342. "index": 2
  6343. }];
  6344. this.codec.rpcMapsByName = {
  6345. "SyncData": {
  6346. "name": "SyncData",
  6347. "parameters": [{
  6348. "name": "json",
  6349. "type": 3
  6350. }],
  6351. "isArray": false,
  6352. "index": 0
  6353. },
  6354. "VerifyUser": {
  6355. "name": "VerifyUser",
  6356. "parameters": [{
  6357. "name": "secretKey",
  6358. "type": 3
  6359. }],
  6360. "isArray": false,
  6361. "index": 1
  6362. },
  6363. "ConnectSession": {
  6364. "name": "ConnectSession",
  6365. "parameters": [{
  6366. "name": "id",
  6367. "type": 3
  6368. }],
  6369. "isArray": false,
  6370. "index": 2
  6371. },
  6372. };
  6373. this.socket = new WebSocket(`ws${game.script.sessions.endpoints[endpoint].https ? "s" : ""}://${game.script.sessions.endpoints[endpoint].wss}`);
  6374. this.socket.binaryType = `arraybuffer`;
  6375. this.socket.addEventListener("open", () => {
  6376. this.socket.send(this.codec.encode(9, {
  6377. name: "VerifyUser",
  6378. secretKey: game.script.sessions.endpoints[endpoint].secret
  6379. }));
  6380. this.socket.send(this.codec.encode(9, {
  6381. name: "ConnectSession",
  6382. id: sessionId,
  6383. }));
  6384. });
  6385. this.bindEventListeners();
  6386. this.addRpcHandler("SyncData", (response) => {
  6387. try {
  6388. const data = JSON.parse(response.json);
  6389.  
  6390. this.connectionOptions = data.connectionOptions;
  6391. game.options.serverId = data.connectionOptions.id;
  6392. game.options.nickname = data.syncNeeds[0].effectiveDisplayName;
  6393.  
  6394. const staticCodecData = JSON.parse(game.script.sessions.codecJSON);
  6395. for (let i in staticCodecData) {
  6396. this.codec[i] = staticCodecData[i];
  6397. };
  6398. this.codec.sortedUidsByType = data.sortedUidsByType;
  6399. this.codec.removedEntities = data.removedEntities;
  6400. this.codec.absentEntitiesFlags = data.absentEntitiesFlags;
  6401. this.codec.updatedEntityFlags = data.updatedEntityFlags;
  6402.  
  6403. for (let i = 0; i < game.script.sessions.staticJSONs.length; i++) {
  6404. this.emitter.emit(PacketIds_1.default[game.script.sessions.staticJSONs[i].opcode], game.script.sessions.staticJSONs[i]);
  6405. };
  6406.  
  6407. for (let i = 0; i < data.syncNeeds.length; i++) {
  6408. this.emitter.emit(PacketIds_1.default[data.syncNeeds[i].opcode], data.syncNeeds[i]);
  6409. };
  6410.  
  6411. for (let i = 0; i < data.messages.length; i++) {
  6412. this.emitter.emit(PacketIds_1.default[9], {
  6413. name: "ReceiveChatMessage",
  6414. response: data.messages[i],
  6415. opcode: 9
  6416. });
  6417. };
  6418.  
  6419. if (data.castSpellResponse && data.castSpellResponse.cooldownStartTick && (data.tick - data.castSpellResponse.cooldownStartTick) * 50 < 240000) {
  6420. this.emitter.emit(PacketIds_1.default[9], {
  6421. name: 'CastSpellResponse',
  6422. response: data.castSpellResponse,
  6423. opcode: 9
  6424. });
  6425. };
  6426.  
  6427. for (let i in data.inventory) {
  6428. this.emitter.emit(PacketIds_1.default[9], {
  6429. name: "SetItem",
  6430. response: {
  6431. itemName: data.inventory[i].itemName,
  6432. tier: data.inventory[i].tier,
  6433. stacks: data.inventory[i].stacks
  6434. },
  6435. opcode: 9
  6436. });
  6437. };
  6438.  
  6439. this.emitter.emit(PacketIds_1.default[9], {
  6440. name: "LocalBuilding",
  6441. response: data.localBuildings,
  6442. opcode: 9
  6443. });
  6444.  
  6445. this.emitter.emit(PacketIds_1.default[0], {
  6446. tick: data.tick,
  6447. entities: data.entities,
  6448. byteSize: data.byteSize,
  6449. opcode: 0
  6450. });
  6451.  
  6452. this.emitter.once(PacketIds_1.default[0], () => {
  6453. const myPlayer = data.entities[data.syncNeeds[0].uid];
  6454. myPlayer?.dead && this.emitter.emit(PacketIds_1.default[9], {
  6455. name: "Dead",
  6456. response: {stashDied: 0},
  6457. opcode: 9
  6458. });
  6459. myPlayer?.isPaused && (
  6460. game.ui.onLocalItemUpdate({
  6461. itemName: 'Pause',
  6462. tier: 1,
  6463. stacks: 1
  6464. }),
  6465. game.ui.emit('wavePaused')
  6466. );
  6467. });
  6468. } catch(e) { console.log(e); };
  6469. });
  6470. };
  6471.  
  6472. game.network.connect = async function (options) {
  6473. if (!this.connecting) {
  6474. if (game.script.sessions.useSes) return this.establishSessionConnection();
  6475. this.connectionOptions = options;
  6476. this.connected = false;
  6477. this.connecting = true;
  6478. this.socket = new WebSocket('wss://' + options.hostname + ':' + options.port);
  6479. this.socket.binaryType = `arraybuffer`;
  6480. this.bindEventListeners();
  6481. };
  6482. };
  6483.  
  6484. game.network.reconnect = function () {
  6485. return this.connect(this.connectionOptions);
  6486. };
  6487.  
  6488. await this.fetchSessions();
  6489. },
  6490. fetchSessions: async function() {
  6491. for (const endpointName in this.endpoints) {
  6492. const endpointData = this.endpoints[endpointName];
  6493. try {
  6494. let data = await fetch(
  6495. `http${endpointData.https ? "s" : ""}://${endpointData.api}/sessions`,
  6496. {
  6497. signal: AbortSignal.timeout(this.SESSION_FETCH_TIMEOUT),
  6498. method: "get",
  6499. headers: new Headers({
  6500. "ngrok-skip-browser-warning": "69420",
  6501. }),
  6502. }
  6503. );
  6504. data = await data.json();
  6505.  
  6506. this.allSessions ||= {};
  6507. this.sesSelect.disabled = false;
  6508.  
  6509. this.allSessions[endpointName] = data;
  6510. } catch(e) {
  6511. console.warn(`Failed to fetch available sessions for ${endpointName}: ` + e);
  6512. };
  6513. };
  6514. this.mapSessions();
  6515. },
  6516. mapSessions() {
  6517. if (this.allSessions === null) return;
  6518. let sessionHTML = '';
  6519. for (const endpointName in this.allSessions) {
  6520. sessionHTML += `
  6521. <optgroup label="${window.filterXSS(endpointName)}">
  6522. ${Object.entries(this.allSessions[endpointName]).map(([key, data]) => {
  6523. const { connectionOptions: { id }, name } = data;
  6524. return `<option value="${endpointName}/${key}">${window.filterXSS(name)} [${id}]</option>`;
  6525. }).join("\n")}
  6526. </optgroup>
  6527. `;
  6528. };
  6529. this.sesSelect.innerHTML = sessionHTML;
  6530. getId("session-endpoint").innerHTML = Object.keys(this.endpoints).map((name) => {
  6531. return `<option value="${window.filterXSS(name)}" selected>${window.filterXSS(name)}</option>`;
  6532. }).join("\n");
  6533. },
  6534. addNewEndpoint: async function(name, server, api, protocol, secret) {
  6535. game.ui.components.Intro.showLoadingScreen();
  6536. if (name && secret && server && api && protocol) {
  6537. this.endpoints[name] = {https: protocol == "https", secret, wss: server, api};
  6538. await this.fetchSessions();
  6539. } else game.ui.components.Intro.onConnectionError("Please fill in ALL necessary details to add a new endpoint.");
  6540. game.ui.components.Intro.hideLoadingScreen();
  6541. game.world.isInitialized && (getId("hud-intro").style.display = "none");
  6542. },
  6543. createNewSession: async function(nickname, server, psk = "", endpoint) {
  6544. game.ui.components.Intro.showLoadingScreen();
  6545. try {
  6546. const {https, api} = this.endpoints[endpoint];
  6547. console.log(nickname, server, psk, endpoint);
  6548. let data = await fetch(
  6549. `http${https ? "s" : ""}://${api}/create?name=${nickname}&serverId=${server}&psk=${psk}`,
  6550. {
  6551. signal: AbortSignal.timeout(this.SESSION_CREATE_TIMEOUT),
  6552. method: "get",
  6553. headers: new Headers({
  6554. "ngrok-skip-browser-warning": "69420",
  6555. }),
  6556. }
  6557. );
  6558. data = await data.json();
  6559.  
  6560. this.allSessions ||= {};
  6561. this.sesSelect.disabled = false;
  6562.  
  6563. this.allSessions[endpoint] = data.data;
  6564. this.mapSessions();
  6565.  
  6566. this.sesSelect.value = `${endpoint}/${data.createdSession}`;
  6567. } catch(e) {
  6568. console.log(e);
  6569. game.ui.components.Intro.onConnectionError(e);
  6570. };
  6571. game.ui.components.Intro.hideLoadingScreen();
  6572. game.world.isInitialized && (getId("hud-intro").style.display = "none");
  6573. },
  6574. deleteSes: async function(endpoint, sesId) {
  6575. const { api, https } = this.endpoints[endpoint];
  6576. await fetch(
  6577. `http${https ? "s" : ""}://${api}/delete?sessionId=${sesId}`,
  6578. { signal: AbortSignal.timeout(this.SESSION_CREATE_TIMEOUT) }
  6579. );
  6580. setTimeout(this.fetchSessions.bind(this), 500);
  6581. },
  6582. },
  6583. sockets: {
  6584. statusEnum: {
  6585. "Population Full": "red",
  6586. "Failed": "red",
  6587. "Closed": "red",
  6588. "Connecting": "yellow",
  6589. "Open": "green"
  6590. },
  6591. shared: {
  6592. all: {},
  6593. uiHooks: {},
  6594. availableNames: shuffleArray([
  6595. "Hikari",
  6596. "Tairitsu",
  6597. "Kou",
  6598. "Sapphire",
  6599. "Lethe",
  6600. "Tairitsu (Axium)",
  6601. "Tairitsu (Grievous Lady)",
  6602. "Stella",
  6603. "Hikari & Fisica",
  6604. "Ilith",
  6605. "Eto",
  6606. "Luna",
  6607. "Shirabe",
  6608. "Hikari (Zero)",
  6609. "Hikari (Fracture)",
  6610. "Hikari (Summer)",
  6611. "Tairitsu (Summer)",
  6612. "Tairitsu & Trin",
  6613. "Ayu",
  6614. "Eto & Luna (Winter)",
  6615. "Hikari & Seine",
  6616. "Yume",
  6617. "Saya",
  6618. "Tairitsu (Grievous Lady) & Chuni Penguin",
  6619. "Nono Shibusawa",
  6620. "Haruna Mishima",
  6621. "Regulus (MDA-21)",
  6622. "Pandora Nemesis (MTA-XXX)",
  6623. "Chuni Penguin",
  6624. "Kanae",
  6625. "Hikari (Fantasia)",
  6626. "Tairitsu (Sonata)",
  6627. "Sia",
  6628. "DORO*C",
  6629. "Tairitsu (Tempest)",
  6630. "Brillante (E/S Primera)",
  6631. "Ilith (Summer)",
  6632. "Saya (Etude)",
  6633. "Alice & Tenniel",
  6634. "Luna & Mia",
  6635. "Areus",
  6636. "Seele Haze",
  6637. "Isabelle Yagrush",
  6638. "Mir",
  6639. "Lagrange",
  6640. "Shirahime",
  6641. "Linka",
  6642. "Nami",
  6643. "Saya & Elizabeth",
  6644. "Lily",
  6645. "Kanae (Midsummer)",
  6646. "Alice & Tenniel (Minuet)",
  6647. "Tairitsu (Elegy)",
  6648. "Marija",
  6649. "Vita",
  6650. "Hikari (Fatalis)",
  6651. "Hikari & Tairitsu (Reunion)",
  6652. "Saki",
  6653. "Setsuna",
  6654. "Amane",
  6655. "Kou (Winter)",
  6656. "Lethe (Apophenia)",
  6657. "Lagrange (Aria)",
  6658. "Milk (UNiVERSE)",
  6659. "Shama (UNiVERSE)",
  6660. "Mika Yurisaki",
  6661. "Shikoku",
  6662. "Toa Kozukata",
  6663. "Mithra Tercera",
  6664. "Nami (Twilight)",
  6665. "Ilith & Ivy",
  6666. "Hikari & Vanessa",
  6667. "Maya",
  6668. "Luin",
  6669. "Vita (Cadenza)",
  6670. "Ai-chan",
  6671. "Luna & Ilot",
  6672. "Eto & Hoppe",
  6673. "Nell",
  6674. "Lacrymira",
  6675. "Tsumugi",
  6676. "Chinatsu",
  6677. ]),
  6678. options: {
  6679. control: {
  6680. enabled: true,
  6681. },
  6682. autoFill: {
  6683. enabled: false,
  6684. onCallback: () => {
  6685. game.network.emitter.emit("PACKET_RPC", {
  6686. name: "SetPartyList",
  6687. response: Object.values(game.ui.parties),
  6688. opcode: 9
  6689. });
  6690. },
  6691. },
  6692. randomizeName: {
  6693. enabled: true,
  6694. },
  6695. },
  6696. },
  6697. init: function() {
  6698. game.network.addRpcHandler("SetPartyList", (parties) => {
  6699. if (this.shared.options.autoFill.enabled) {
  6700. let serverPopulation = 0;
  6701. for (let party of parties) {
  6702. serverPopulation += party.memberCount;
  6703. };
  6704. const emptyAmount = 32 - serverPopulation;
  6705. if (emptyAmount > 0) {
  6706. let connectedSockets = 0;
  6707. for (const socket of Object.values(this.shared.all)) {
  6708. if (socket.hasEnteredWorld && socket.ws.readyState === 1) connectedSockets++;
  6709. };
  6710. const shouldWait = ((connectedSockets + 1) % 7) === 0;
  6711. shouldWait && game.ui.components.PopupOverlay.showHint("Please change your IP Address for the auto-filling to continue.");
  6712. this.createSocket("Filler");
  6713. };
  6714. };
  6715. });
  6716. },
  6717. updateActiveSocketsAmount: function() {
  6718. let openSockets = 0;
  6719. const allSockets = Object.values(this.shared.all);
  6720. for (let i = 0; i < allSockets.length; i++) {
  6721. allSockets[i].ws.readyState == 1 && openSockets++;
  6722. };
  6723. getId("clone-amount").innerText = openSockets + " active";
  6724. },
  6725. addUiHook: function(UUID, elemSelector, event, callback) {
  6726. this.shared.uiHooks[elemSelector] ||= {};
  6727. if (!this.shared.uiHooks[elemSelector][event]) {
  6728. this.shared.uiHooks[elemSelector][event] = {};
  6729. document.querySelector(elemSelector)["on" + event] = (e) => {
  6730. for (let uuid in this.shared.uiHooks[elemSelector][event]) {
  6731. this.shared.uiHooks[elemSelector][event][uuid]();
  6732. };
  6733. };
  6734. };
  6735. this.shared.uiHooks[elemSelector][event][UUID] = callback;
  6736. },
  6737. removeUiHook: function(UUID, elemSelector, event) {
  6738. console.log(this.shared.uiHooks[elemSelector][event][UUID]);
  6739. delete this.shared.uiHooks[elemSelector][event][UUID];
  6740. },
  6741. Socket: class Socket {
  6742. constructor(url, identifiers) {
  6743. this.ws = new WebSocket(url);
  6744. this.ws.binaryType = "arraybuffer";
  6745.  
  6746. this.identifiers = identifiers;
  6747. this.player = {
  6748. uid: null,
  6749. partyShareKey: null,
  6750.  
  6751. targetTick: {},
  6752. petTick: {},
  6753.  
  6754. // entities: {},
  6755.  
  6756. inventory: {},
  6757. buildings: {},
  6758. parties: {},
  6759.  
  6760. hasHealed: false,
  6761. lastTickHealth: 100,
  6762. };
  6763. this.hasEnteredWorld = false;
  6764.  
  6765. this.parent = game.script.sockets;
  6766.  
  6767. this.pingStart = null;
  6768. this.pingCompletion = null;
  6769. this.ping = 0;
  6770.  
  6771. this.keybinds = {
  6772. keyup: {},
  6773. keydown: {},
  6774. mousedown: {},
  6775. mouseup: {},
  6776. mousemove: () => {},
  6777. };
  6778.  
  6779. /*
  6780. this.msElapsedSinceInputSent = 0;
  6781. this.currentInput = {};
  6782. this.shouldInput = false;
  6783. */
  6784.  
  6785. this.statusDisplay = getId(`alt${this.identifiers.id}`) || document.createElement("p");
  6786. this.statusDisplay.style.position = "relative";
  6787. this.statusDisplay.style.width = "100%";
  6788.  
  6789. this.minimapDisplay = document.createElement('div');
  6790.  
  6791. this.timeCreation = Date.now();
  6792.  
  6793. this.init(this.identifiers.type);
  6794. };
  6795. init(type) {
  6796. this.ws.addEventListener("open", () => {
  6797. this.updateStatus("Connecting");
  6798. this.codec = new BinCodec();
  6799. this.resetListeners(type);
  6800. this.bindKeys();
  6801. });
  6802. this.ws.addEventListener("message", this.onMessage.bind(this));
  6803. this.ws.addEventListener("close", this.onClose.bind(this));
  6804. this.ws.addEventListener("error", this.onError.bind(this));
  6805. // game.renderer.addTickCallback(this.onRendererTick.bind(this));
  6806. };
  6807. decodeData(data) {
  6808. this.data = {};
  6809. const m = new Uint8Array(data);
  6810. this.data.opcode = m[0];
  6811. switch(m[0]) {
  6812. case 5:
  6813. wasmModule(e => {
  6814. this.sendPacket(4, {
  6815. displayName: this.identifiers.name,
  6816. extra: e[5].extra
  6817. });
  6818. this.wasmModule = e;
  6819. }, m, game.network.connectionOptions.ipAddress);
  6820. break;
  6821. case 10:
  6822. this.sendPacket(10, {extra: codec.decode(data, this.wasmModule[10]).extra});
  6823. break;
  6824. default:
  6825. this.data = this.codec.decode(data);
  6826. };
  6827. if (m[0] == 4 && this.data.allowed) {
  6828. this.ws.send(this.wasmModule[6]);
  6829. this.hasEnteredWorld = true;
  6830. };
  6831. };
  6832. onError() {
  6833. game.ui.components.PopupOverlay.showHint("Socket failed to connect. Maybe switch your IP?");
  6834. };
  6835. onClose() {
  6836. this.parent.updateActiveSocketsAmount();
  6837. this.updateStatus("Closed");
  6838.  
  6839. this.minimapDisplay.remove();
  6840.  
  6841. this.wasmModule = null;
  6842.  
  6843. this.identifiers.name != game.ui.playerTick.name && this.parent.shared.availableNames.push(this.identifiers.name);
  6844.  
  6845. if (this.parent.shared.options.autoFill.enabled) {
  6846. setTimeout(() => {
  6847. game.network.emitter.emit("PACKET_RPC", {
  6848. name: "SetPartyList",
  6849. response: Object.values(game.ui.parties),
  6850. opcode: 9
  6851. });
  6852. }, 1000);
  6853. };
  6854. };
  6855. onMessage({data}) {
  6856. this.sendPingIfNecessary();
  6857. this.decodeData(data);
  6858. this.emitter.emit(PacketIds_1.default[this.data.opcode], this.data);
  6859. };
  6860. /*
  6861. onRendererTick(delta) {
  6862. this.msElapsedSinceInputSent += delta;
  6863. this.sendInputKeys();
  6864. };
  6865. */
  6866. addOnceHandler(opcode, callback) {
  6867. this.emitter.once(PacketIds_1.default[opcode], callback.bind(this));
  6868. };
  6869. addPacketHandler(opcode, callback) {
  6870. this.emitter.on(PacketIds_1.default[opcode], callback.bind(this));
  6871. };
  6872. sendPacket(e, t) {
  6873. const enc = this.codec.encode(e, t);
  6874. this.ws.readyState == 1 && this.ws.send(enc);
  6875. };
  6876. sendInput(t) {
  6877. this.sendPacket(3, t);
  6878. };
  6879. sendRpc(t) {
  6880. this.sendPacket(9, t);
  6881. };
  6882. sendPingIfNecessary() {
  6883. var pingInProgress = (this.pingStart != null);
  6884. if (pingInProgress) {
  6885. return;
  6886. }
  6887. if (this.pingCompletion != null) {
  6888. var msSinceLastPing = (new Date().getTime() - this.pingCompletion.getTime());
  6889. if (msSinceLastPing <= 5000) {
  6890. return;
  6891. }
  6892. }
  6893. this.pingStart = new Date();
  6894. this.sendPacket(7, { nonce: 0 });
  6895. };
  6896. /*
  6897. scheduleInput(data) {
  6898. this.currentInput = data;
  6899. this.shouldInput = true;
  6900. this.sendInputKeys();
  6901. };
  6902. sendInputKeys() {
  6903. const msPerTick = game.world.msPerTick;
  6904. if (!(this.msElapsedSinceInputSent < msPerTick)) {
  6905. if (this.shouldInput) {
  6906. this.sendInput(this.currentInput);
  6907. this.currentInput = {};
  6908. this.shouldInput = false;
  6909. };
  6910. };
  6911. };
  6912. */
  6913. resetListeners(type) {
  6914. this.keybinds = {
  6915. keyup: {},
  6916. keydown: {},
  6917. mousedown: {},
  6918. mouseup: {},
  6919. mousemove: () => {},
  6920. };
  6921. this.emitter = new EventEmitter();
  6922.  
  6923. this.bindDefaultListeners();
  6924. this.bindTypeHandlers(type);
  6925. };
  6926. bindDefaultListeners() {
  6927. this.addPacketHandler(0, (data) => {
  6928. try {
  6929. if (data.entities[this.player?.uid].name) {
  6930. this.player.targetTick = data.entities[this.player.uid];
  6931. };
  6932. for (let g in this.player.targetTick) {
  6933. if (this.player.targetTick[g] !== data.entities[this.player.uid][g] && data.entities[this.player.uid][g] !== undefined) {
  6934. this.player.targetTick[g] = data.entities[this.player.uid][g];
  6935. };
  6936. };
  6937. if (this.player.targetTick.petUid) {
  6938. if (data.entities?.[this.player.targetTick.petUid]?.model) {
  6939. this.player.petTick = data.entities[this.player.targetTick.petUid];
  6940. }
  6941. for (let g in this.player.petTick) {
  6942. if (this.player.petTick[g] !== data.entities?.[this.player.targetTick.petUid][g] && data.entities?.[this.player.targetTick.petUid][g] !== undefined) {
  6943. this.player.petTick[g] = data.entities[this.player.targetTick.petUid][g];
  6944. };
  6945. };
  6946. };
  6947.  
  6948. for (let i in data.entities) {
  6949. if (["Tree", "Stone", "NeutralCamp"].indexOf(data.entities[i].model) > -1) {
  6950. game.world.createEntity(data.entities[i]);
  6951. };
  6952. };
  6953. } catch {};
  6954. });
  6955. this.addPacketHandler(4, (e) => {
  6956. if (e.allowed) {
  6957. this.player.uid = e.uid;
  6958.  
  6959. this.parent.updateActiveSocketsAmount();
  6960. this.updateStatus("Open");
  6961.  
  6962. console.log(`%c [SOCKET ${this.identifiers.id}]`, 'color: #54ebd9', '\n', `${e.players + 1}/32 players`);
  6963.  
  6964. this.sendRpc({name: "BuyItem", itemName: "PetCARL", tier: 1});
  6965. this.sendRpc({name: "BuyItem", itemName: "PetMiner", tier: 1});
  6966.  
  6967. this.sendInput({left: 1, up: 1});
  6968. this.sendInput({space: 1});
  6969. } else {
  6970. console.log(`%c [SOCKET ${this.identifiers.id}]`, 'color: #54ebd9', '\n', `32/32 players`);
  6971. this.updateStatus("Population Full");
  6972. };
  6973. });
  6974. this.addPacketHandler(5, () => {
  6975. setTimeout(() => {
  6976. if (this.data.opcode === 5) this.ws.close();
  6977. }, 5000);
  6978. });
  6979. this.addPacketHandler(7, () => {
  6980. const now = new Date();
  6981. this.ping = (now.getTime() - this.pingStart.getTime()) / 2;
  6982. this.pingStart = null;
  6983. this.pingCompletion = now;
  6984. });
  6985. this.addPacketHandler(9, (e) => {
  6986. this.updateStatus("Open");
  6987. switch(e.name) {
  6988. case "PartyShareKey":
  6989. if (!this.player.partyShareKey) {
  6990. this.sendRpc({
  6991. name: "JoinPartyByShareKey",
  6992. partyShareKey: game.ui.getPlayerPartyShareKey()
  6993. });
  6994. this.minimapDisplay.classList.add('hud-map-player');
  6995. this.minimapDisplay.style.display = "block";
  6996. getClass('hud-map')[0].appendChild(this.minimapDisplay);
  6997. };
  6998. this.player.partyShareKey = e.response.partyShareKey;
  6999. this.minimapDisplay.style.display = (e.response.partyShareKey == game.ui.getPlayerPartyShareKey()) ? "none" : "block";
  7000. break;
  7001. case "SetItem":
  7002. this.player.inventory[e.response.itemName] = e.response;
  7003. if (!this.player.inventory[e.response.itemName].stacks) {
  7004. delete this.player.inventory[e.response.itemName];
  7005. };
  7006. break;
  7007. case "Leaderboard":
  7008. this.sendRpc(game.metrics.metrics);
  7009.  
  7010. this.minimapDisplay.style.left = (Math.round(this.player?.targetTick?.position?.x) / 24000 * 100) + '%';
  7011. this.minimapDisplay.style.top = (Math.round(this.player?.targetTick?.position?.y) / 24000 * 100) + '%';
  7012. break;
  7013. };
  7014. });
  7015. };
  7016. bindKeys() {
  7017. for (let event in this.keybinds) {
  7018. switch(event) {
  7019. case "keyup":
  7020. case "keydown":
  7021. document.addEventListener(event, (e) => {
  7022. if (document.activeElement.tagName.toLowerCase() !== "input" && document.activeElement.tagName.toLowerCase() !== "textarea") {
  7023. for (let keyCode in this.keybinds[event]) {
  7024. if (e.keyCode == keyCode && this.ws.readyState == 1) this.keybinds[event][keyCode].call(this, e);
  7025. };
  7026. }
  7027. });
  7028. break;
  7029. case "mouseup":
  7030. case "mousedown":
  7031. document.addEventListener(event, (e) => {
  7032. for (let which in this.keybinds[event]) {
  7033. if (e.which == which && this.ws.readyState == 1) this.keybinds[event][which].call(this, e);
  7034. };
  7035. });
  7036. break;
  7037. case "mousemove":
  7038. document.addEventListener(event, (e) => {
  7039. this.ws.readyState == 1 && this.keybinds[event].call(this, e);
  7040. });
  7041. break;
  7042. };
  7043. };
  7044. };
  7045. bindTypeHandlers(type) {
  7046. if (this.parent[type]) {
  7047. this.typeHandlers = [];
  7048. this.typeSpecificVariables = {};
  7049.  
  7050. typeof this.parent[type].init == "function" && this.parent[type].init.call(this);
  7051.  
  7052. const handlersForType = this.parent[type];
  7053. for (const handler in handlersForType) {
  7054. if (typeof handlersForType[handler] !== "function" || ["init", "deinit"].indexOf(handler) > -1) continue;
  7055. this.typeHandlers.push(handler);
  7056. };
  7057. for (const handler of this.typeHandlers) this.addPacketHandler(PacketIds_1.default[handler], (data) => { handlersForType[handler].call(this, data, handlersForType); });
  7058.  
  7059. if (this.parent[type].keybinds) {
  7060. Object.assign(this.keybinds, this.parent[type].keybinds);
  7061. };
  7062. };
  7063. };
  7064. switchType(type) {
  7065. typeof this.parent[this.identifiers.type].deinit == "function" && this.parent[this.identifiers.type].deinit.call(this);
  7066. this.identifiers.type = type;
  7067. this.resetListeners(type);
  7068. };
  7069. updateStatus(status) {
  7070. this.statusDisplay.innerHTML = `
  7071. <strong>${this.identifiers.name}</strong>
  7072. <select style="position: absolute;top: -10px;right: -5px;width: 130px;background: unset;box-shadow: none;color:white;" id="switch${this.identifiers.id}" ${status === "Open" ? "" : "disabled"}>
  7073. <option value="Multibox" ${this.identifiers.type == "Multibox" ? "selected" : ""}>Multibox</option>
  7074. <option value="Filler" ${this.identifiers.type == "Filler" ? "selected" : ""}>Filler</option>
  7075. <option value="PlayerTrick" ${this.identifiers.type == "PlayerTrick" ? "selected" : ""}>Player Trick</option>
  7076. <option value="AITO" ${this.identifiers.type == "AITO" ? "selected" : ""}>AITO</option>
  7077. </select><br>
  7078. State: <strong style="color: ${this.parent.statusEnum[status]};">[${status}]</strong>${["Population Full", "Failed", "Closed"].indexOf(status) == -1 ? `, ping: ${this.ping}ms` : `, created: ${getClock(new Date(this.timeCreation))}`}<br>
  7079. ${status === "Open" ? `
  7080. UID: ${this.player.uid}, partyId: <strong>${this.player.targetTick.partyId || 0}</strong><br>
  7081. <strong>W: ${counter(this.player?.targetTick?.wood || 0)}, S: ${counter(this.player?.targetTick?.stone || 0)}, G: ${counter(this.player?.targetTick?.gold || 0)}, T: ${counter(this.player?.targetTick?.token || 0)}</strong><br>
  7082. <a href="javascript:void(0);" style="margin: 5px 0 0 0;color: red;" onclick="game.script.sockets.shared.all['${this.identifiers.id}'].ws.close();">Delete</a>
  7083. ${this.identifiers.type == "Multibox" ? `
  7084. ${this.player.targetTick.partyId != game.ui.playerPartyId && this.player.targetTick.partyId ? `
  7085. <a href="javascript:void(0);"
  7086. style="margin: 5px 0 0 0;color: lightblue;"
  7087. onclick="game.network.sendRpc({name: 'JoinPartyByShareKey', partyShareKey: game.script.sockets.shared.all['${this.identifiers.id}'].player.partyShareKey});"
  7088. >Join Party</a>
  7089. ` : ""}
  7090. ` : ""}
  7091. <!-- Type: <select href="javascript:void(0);" style="margin: 5px 0 0 0;color: red;" onselect="game.script.sockets.shared.all['${this.identifiers.id}'].ws.close();">Switch...</select> -->
  7092. <!--
  7093. <a href="javascript:void(0);"
  7094. style="margin: 5px 0 0 0;color: lightblue;"
  7095. class="elem-is-disabled"
  7096. id="respawnAlt#${this.identifiers.id}"
  7097. onclick="
  7098. game.script.cloneSockets.allSockets[${this.identifiers.id}].network.sendInput({respawn: 1});
  7099. document.getElementById('respawnAlt#${this.identifiers.id}').classList.add('elem-is-disabled');
  7100. "
  7101. >Respawn</a> -->
  7102. ` : ""}
  7103. `;
  7104. if (status === "Connecting" && !getId(`alt${this.identifiers.id}`)) {
  7105. this.statusDisplay.id = `alt${this.identifiers.id}`;
  7106. getId("clone-status").appendChild(this.statusDisplay);
  7107. };
  7108. getId(`switch${this.identifiers.id}`).onchange = ({target}) => {
  7109. this.switchType(target.value);
  7110. };
  7111. };
  7112. },
  7113. createSocket: function(type) {
  7114. const socketId = genUUID(),
  7115. socketName = this.shared.options.randomizeName.enabled ? this.shared.availableNames.shift() : game.ui.playerTick.name;
  7116. this.shared.all[socketId] = new this.Socket(`wss://${game.network.connectionOptions.hostname}:443/`, {
  7117. id: socketId,
  7118. name: socketName,
  7119. type,
  7120. });
  7121. },
  7122. Builder: {
  7123.  
  7124. },
  7125. Multibox: {
  7126. init: function() {
  7127. this.typeSpecificVariables.mouseData = {
  7128. yaw: 1,
  7129. worldX: 1,
  7130. worldY: 1,
  7131. distance: 1,
  7132.  
  7133. mouseUp: 1,
  7134. mouseDown: 0,
  7135. mousePos: {x: 0, y: 0},
  7136. };
  7137.  
  7138. this.typeSpecificVariables.overrides = {
  7139. autoMove: false,
  7140. };
  7141.  
  7142. this.typeSpecificVariables.FOLLOW_ACCURACY = 50;
  7143. this.typeSpecificVariables.FOLLOW_TYPE = {
  7144. NONE: 0,
  7145. MOUSE: 1,
  7146. LOCK: 2,
  7147. PLAYER: 3,
  7148. };
  7149. this.typeSpecificVariables.autoMove = parseInt(getId("movementTypeOptions").value); // this.parent.shared.overridables.autoMove;
  7150. this.typeSpecificVariables.followPoint = {x: 0, y: 0};
  7151.  
  7152. const shopItems = ['Pickaxe', 'Spear', 'Bow', 'Bomb', 'ZombieShield'];
  7153. for (let i in shopItems) {
  7154. this.parent.addUiHook(this.identifiers.id, `#hud-menu-shop > div.hud-shop-grid > a:nth-child(${parseInt(i) + 1})`, "click", () => {
  7155. const item = shopItems[i];
  7156. if (this.parent.shared.options.control.enabled && this.ws.readyState == 1) {
  7157. this.sendRpc({
  7158. name: "BuyItem",
  7159. itemName: item,
  7160. tier: this.player.inventory[item] ? this.player.inventory[item].tier + 1 : 1
  7161. });
  7162. };
  7163. });
  7164. };
  7165.  
  7166. const itemArray = ['Pickaxe', 'Spear', 'Bow', 'Bomb', 'HealthPotion', 'PetHealthPotion', 'PetWhistle'];
  7167. for (let i in itemArray) {
  7168. this.parent.addUiHook(this.identifiers.id, `#hud-toolbar > div.hud-toolbar-inventory > a:nth-child(${parseInt(i) + 1})`, "click", () => {
  7169. if (this.parent.shared.options.control.enabled && this.ws.readyState == 1) {
  7170. this.player.inventory[itemArray[i]] && this.sendRpc({
  7171. name: "EquipItem",
  7172. itemName: itemArray[i],
  7173. tier: this.player.inventory[itemArray[i]].tier
  7174. });
  7175. };
  7176. });
  7177. };
  7178. },
  7179. deinit: function() {
  7180. const shopItems = ['Pickaxe', 'Spear', 'Bow', 'Bomb', 'ZombieShield'];
  7181. for (let i in shopItems) {
  7182. this.parent.removeUiHook(this.identifiers.id, `#hud-menu-shop > div.hud-shop-grid > a:nth-child(${parseInt(i) + 1})`, "click");
  7183. };
  7184.  
  7185. const itemArray = ['Pickaxe', 'Spear', 'Bow', 'Bomb', 'HealthPotion', 'PetHealthPotion', 'PetWhistle'];
  7186. for (let i in itemArray) {
  7187. this.parent.removeUiHook(this.identifiers.id, `#hud-toolbar > div.hud-toolbar-inventory > a:nth-child(${parseInt(i) + 1})`, "click");
  7188. };
  7189. },
  7190. keybinds: {
  7191. keyup: {
  7192. 87: function() {
  7193. if (this.parent.shared.options.control.enabled && !this.typeSpecificVariables.autoMove) {
  7194. this.sendInput({up: 0});
  7195. };
  7196. },
  7197. 83: function() {
  7198. if (this.parent.shared.options.control.enabled && !this.typeSpecificVariables.autoMove) {
  7199. this.sendInput({down: 0});
  7200. };
  7201. },
  7202. 68: function() {
  7203. if (this.parent.shared.options.control.enabled && !this.typeSpecificVariables.autoMove) {
  7204. this.sendInput({right: 0});
  7205. };
  7206. },
  7207. 65: function() {
  7208. if (this.parent.shared.options.control.enabled && !this.typeSpecificVariables.autoMove) {
  7209. this.sendInput({left: 0});
  7210. };
  7211. },
  7212. 81: function(data) {
  7213. if (this.parent.shared.options.control.enabled) {
  7214. let nextWeapon = 'Pickaxe',
  7215. weaponOrder = ['Pickaxe', 'Spear', 'Bow', 'Bomb'],
  7216. foundCurrent = false;
  7217. for (let i in weaponOrder) {
  7218. if (foundCurrent) {
  7219. if (this.player.inventory[weaponOrder[i]]) {
  7220. nextWeapon = weaponOrder[i];
  7221. break;
  7222. };
  7223. } else if (weaponOrder[i] == this.player.targetTick.weaponName) {
  7224. foundCurrent = true;
  7225. };
  7226. };
  7227. this.sendRpc({name: 'EquipItem', itemName: nextWeapon, tier: this.player.inventory[nextWeapon].tier});
  7228. };
  7229. },
  7230. 72: function() {
  7231. this.parent.shared.options.control.enabled && this.sendRpc({name: 'LeaveParty'});
  7232. },
  7233. 74: function() {
  7234. this.parent.shared.options.control.enabled && this.sendRpc({name: 'JoinPartyByShareKey', partyShareKey: game.ui.playerPartyShareKey});
  7235. },
  7236. 32: function() {
  7237. if (this.parent.shared.options.control.enabled) {
  7238. this.sendInput({space: 0});
  7239. };
  7240. },
  7241. 82: function() {
  7242. if (this.parent.shared.options.control.enabled) {
  7243. const buildingOverlay = game.ui.components.BuildingOverlay;
  7244. const buildings = game.ui.buildings;
  7245. if (buildingOverlay.shouldUpgradeAll) {
  7246. for (let i in buildings) {
  7247. if (buildings[i].type == buildingOverlay.buildingId && buildings[i].tier == buildingOverlay.buildingTier) {
  7248. this.sendRpc({name: "UpgradeBuilding", uid: buildings[i].uid});
  7249. };
  7250. };
  7251. } else if (buildingOverlay.buildingUid) {
  7252. this.sendRpc({name: "UpgradeBuilding", uid: buildingOverlay.buildingUid});
  7253. };
  7254. };
  7255. },
  7256. 89: function() {
  7257. if (this.parent.shared.options.control.enabled) {
  7258. const buildingOverlay = game.ui.components.BuildingOverlay;
  7259. if (buildingOverlay.buildingUid) {
  7260. this.sendRpc({name: "DeleteBuilding", uid: buildingOverlay.buildingUid});
  7261. };
  7262. };
  7263. },
  7264. 76: function() {
  7265. if (this.parent.shared.options.control.enabled) {
  7266. this.sendRpc({
  7267. name: "BuyItem",
  7268. itemName: "PetRevive",
  7269. tier: 1
  7270. });
  7271. this.sendRpc({
  7272. name: "EquipItem",
  7273. itemName: "PetRevive",
  7274. tier: 1
  7275. });
  7276. };
  7277. },
  7278. 186: function() {
  7279. if (this.parent.shared.options.control.enabled && this.player.petTick) {
  7280. this.sendRpc({name: "DeleteBuilding", uid: this.player.petTick.uid});
  7281. }
  7282. }
  7283. /*
  7284. 221: function() {
  7285. this.parent.shared.options.control.enabled && game.network.sendRpc({name: "JoinPartyByShareKey", partyShareKey: this.player.partyShareKey});
  7286. }
  7287. */
  7288. },
  7289. keydown: {
  7290. 87: function(e) {
  7291. if (e.repeat) return;
  7292. if (this.parent.shared.options.control.enabled && !this.typeSpecificVariables.autoMove) {
  7293. this.sendInput({up: 1, down: 0});
  7294. };
  7295. },
  7296. 83: function(e) {
  7297. if (e.repeat) return;
  7298. if (this.parent.shared.options.control.enabled && !this.typeSpecificVariables.autoMove) {
  7299. this.sendInput({up: 0, down: 1});
  7300. };
  7301. },
  7302. 68: function(e) {
  7303. if (e.repeat) return;
  7304. if (this.parent.shared.options.control.enabled && !this.typeSpecificVariables.autoMove) {
  7305. this.sendInput({right: 1, left: 0});
  7306. };
  7307. },
  7308. 65: function(e) {
  7309. if (e.repeat) return;
  7310. if (this.parent.shared.options.control.enabled && !this.typeSpecificVariables.autoMove) {
  7311. this.sendInput({right: 0, left: 1});
  7312. };
  7313. },
  7314. 32: function() {
  7315. if (this.parent.shared.options.control.enabled) {
  7316. this.sendInput({space: 1});
  7317. };
  7318. },
  7319. 82: function() {
  7320. if (this.parent.shared.options.control.enabled) {
  7321. this.sendRpc({name: "BuyItem", itemName: "HealthPotion", tier: 1});
  7322. this.sendRpc({name: "EquipItem", itemName: "HealthPotion", tier: 1});
  7323. };
  7324. },
  7325. 222: function() {
  7326. if (this.parent.shared.options.control.enabled) {
  7327. this.sendRpc({
  7328. name: "EquipItem",
  7329. itemName: "PetCARL",
  7330. tier: this.player.inventory.PetCARL.tier
  7331. });
  7332. this.sendRpc({
  7333. name: "BuyItem",
  7334. itemName: "PetCARL",
  7335. tier: this.player.inventory.PetCARL.tier + 1
  7336. });
  7337. };
  7338. },
  7339. },
  7340. mouseup: {
  7341. 1: function() {
  7342. if (this.parent.shared.options.control.enabled) {
  7343. this.typeSpecificVariables.mouseData.mouseDown = 0;
  7344. this.typeSpecificVariables.mouseData.mouseUp = 1;
  7345. const {worldX, worldY, distance} = this.typeSpecificVariables.mouseData;
  7346. this.sendInput({mouseUp: 1, worldX, worldY, distance});
  7347. };
  7348. },
  7349. 3: function(e) {
  7350. if (this.parent.shared.options.control.enabled) {
  7351. if (this.typeSpecificVariables.autoMove == this.typeSpecificVariables.FOLLOW_TYPE.LOCK) {
  7352. this.typeSpecificVariables.followPoint = game.renderer.screenToWorld(e.clientX, e.clientY);
  7353. };
  7354. };
  7355. },
  7356. },
  7357. mousedown: {
  7358. 3: function() {
  7359. /*
  7360. const mouseToWorld = game.renderer.screenToWorld(e.clientX, e.clientY);
  7361. const options = game.script.options;
  7362. if (!ws.isclosed && ws.local.isOnControl) {
  7363. if (e.which === 3) {
  7364. ws.local.moveaway = true;
  7365. const packet = {};
  7366. if (ws.entities.myPlayer.position.y - mouseToWorld.y > 1) {
  7367. packet.down = 0;
  7368. } else {
  7369. packet.down = 1;
  7370. }
  7371. if (-ws.entities.myPlayer.position.y + mouseToWorld.y > 1) {
  7372. packet.up = 0;
  7373. } else {
  7374. packet.up = 1;
  7375. }
  7376. if (-ws.entities.myPlayer.position.x + mouseToWorld.x > 1) {
  7377. packet.left = 0;
  7378. } else {
  7379. packet.left = 1;
  7380. }
  7381. if (ws.entities.myPlayer.position.x - mouseToWorld.x > 1) {
  7382. packet.right = 0;
  7383. } else {
  7384. packet.right = 1;
  7385. }
  7386. ws.move(packet);
  7387. }
  7388. }
  7389. */
  7390. },
  7391. 1: function() {
  7392. if (this.parent.shared.options.control.enabled) {
  7393. /*
  7394. if (options.raid) {
  7395. if (_this.nearestToCursor !== ws.player.uid) {
  7396. ws.network.sendInput({mouseUp: 0});
  7397. }
  7398. if (_this.nearestToCursor === ws.player.uid) {
  7399. ws.network.sendInput({space: 1});
  7400. ws.network.sendInput({space: 0});
  7401. ws.network.sendRpc({name: "JoinPartyByShareKey", partyShareKey: Game.currentGame.ui.getPlayerPartyShareKey() + ""});
  7402. }
  7403. if (game.ui.playerPartyShareKey === ws.player.psk.partyShareKey && ws.entities.myPlayer.dead) {
  7404. ws.network.sendRpc({name: "LeaveParty"});
  7405. ws.network.sendInput({mouseUp: 0});
  7406. } else {
  7407. ws.network.sendInput({mouseUp: 0});
  7408. }
  7409. } else {
  7410. */
  7411. this.typeSpecificVariables.mouseData.mouseDown = 1;
  7412. this.typeSpecificVariables.mouseData.mouseUp = 0;
  7413. const {yaw, worldX, worldY, distance} = this.typeSpecificVariables.mouseData;
  7414. this.sendInput({mouseDown: yaw, worldX, worldY, distance});
  7415. // }
  7416. };
  7417. }
  7418. },
  7419. mousemove: function(e) {
  7420. if (this.parent.shared.options.control.enabled) {
  7421. this.typeSpecificVariables.mouseData.mousePos = {x: e.clientX, y: e.clientY};
  7422. const worldMouse = game.renderer.screenToWorld(e.clientX, e.clientY);
  7423. if (this.typeSpecificVariables.autoMove == this.typeSpecificVariables.FOLLOW_TYPE.MOUSE) this.typeSpecificVariables.followPoint = worldMouse;
  7424.  
  7425. if (this.player?.targetTick?.position && !this.player?.targetTick?.dead) {
  7426. const xPos = (-this.player.targetTick.position.x + worldMouse.x) * 100,
  7427. yPos = (-this.player.targetTick.position.y + worldMouse.y) * 100,
  7428. yaw = game.inputPacketCreator.screenToYaw(xPos, yPos);
  7429.  
  7430. if (this.typeSpecificVariables.mouseData.yaw != yaw) {
  7431. const distance = game.inputPacketCreator.distanceToCenter(xPos, yPos) / 100;
  7432.  
  7433. this.typeSpecificVariables.mouseData.yaw = yaw;
  7434. this.typeSpecificVariables.mouseData.worldX = xPos;
  7435. this.typeSpecificVariables.mouseData.worldY = yPos;
  7436. this.typeSpecificVariables.mouseData.distance = distance;
  7437.  
  7438. if (this.typeSpecificVariables.mouseData.mouseDown) {
  7439. this.sendInput({mouseMovedWhileDown: yaw, worldX: xPos, worldY: yPos, distance});
  7440. }
  7441. if (this.typeSpecificVariables.mouseData.mouseUp) {
  7442. this.sendInput({mouseMoved: yaw, worldX: xPos, worldY: yPos, distance});
  7443. };
  7444. // game.world.entities[this.player.uid].targetTick.aimingYaw = game.world.entities[this.player.uid].fromTick.aimingYaw = yaw;
  7445. };
  7446. };
  7447. };
  7448. }
  7449. },
  7450. PACKET_ENTITY_UPDATE: function(data, parent) {
  7451. if (this.player.targetTick.dead) {
  7452. this.typeSpecificVariables.mouseData.yaw = (this.typeSpecificVariables.mouseData.yaw + 1) % 360;
  7453. this.sendInput({mouseMoved: this.typeSpecificVariables.mouseData.yaw});
  7454. }
  7455. if (game.world.localPlayer.entity.fromTick.position.x != game.world.localPlayer.entity.targetTick.position.x || game.world.localPlayer.entity.fromTick.position.y != game.world.localPlayer.entity.targetTick.position.y) {
  7456. if (this.typeSpecificVariables.autoMove == this.typeSpecificVariables.FOLLOW_TYPE.MOUSE) {
  7457. this.typeSpecificVariables.followPoint = game.renderer.screenToWorld(
  7458. this.typeSpecificVariables.mouseData.mousePos.x,
  7459. this.typeSpecificVariables.mouseData.mousePos.y
  7460. );
  7461. };
  7462. if (this.typeSpecificVariables.autoMove == this.typeSpecificVariables.FOLLOW_TYPE.PLAYER) {
  7463. this.typeSpecificVariables.followPoint = game.world.localPlayer.entity.targetTick.position;
  7464. };
  7465. };
  7466. // if (this.parent.shared.options.control.enabled) {
  7467. if (this.typeSpecificVariables.autoMove) {
  7468. const acc = this.typeSpecificVariables.FOLLOW_ACCURACY,
  7469. point = this.typeSpecificVariables.followPoint,
  7470. position = this.player.targetTick.position,
  7471. packet = {};
  7472.  
  7473. if (position.y - point.y > acc) {
  7474. packet.down = 0;
  7475. } else {
  7476. packet.down = 1;
  7477. }
  7478. if (-position.y + point.y > acc) {
  7479. packet.up = 0;
  7480. } else {
  7481. packet.up = 1;
  7482. }
  7483. if (-position.x + point.x > acc) {
  7484. packet.left = 0;
  7485. } else {
  7486. packet.left = 1;
  7487. }
  7488. if (position.x - point.x > acc) {
  7489. packet.right = 0;
  7490. } else {
  7491. packet.right = 1;
  7492. }
  7493. this.sendInput(packet);
  7494. };
  7495. // };
  7496. },
  7497. },
  7498. Filler: {
  7499. PACKET_RPC: function(data, parent) {
  7500. this.sendInput({left: 1, up: 1, right: 0, down: 0});
  7501. // this.sendInput({space: 1});
  7502.  
  7503. if (this.data.name == "Dead") this.sendInput({respawn: 1});
  7504. },
  7505. },
  7506. PlayerTrick: {
  7507. init: function() {
  7508. this.typeSpecificVariables.playerTrickTimeouts = {
  7509. inull: true,
  7510. i1: true,
  7511. i2: true,
  7512. i3: true
  7513. };
  7514. this.typeSpecificVariables.dayTicker = 0;
  7515. },
  7516. getIsZombiesActive: function () {
  7517. let isZombiesActive = false;
  7518. for (let i of game.renderer.npcs.attachments) {
  7519. if (i.fromTick.model !== "NeutralTier1") {
  7520. if (i.fromTick.entityClass == "Npc") {
  7521. isZombiesActive = true;
  7522. return isZombiesActive;
  7523. }
  7524. }
  7525. }
  7526. return isZombiesActive;
  7527. },
  7528. getIsNextWaveActive: function () {
  7529. let isNextWaveActive = false;
  7530. const allComingBossWaves = [9, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, 105, 121].map(wave => wave - 1);
  7531. for (let wave of allComingBossWaves) {
  7532. game.ui.playerTick.wave == wave && (isNextWaveActive = true);
  7533. }
  7534. return isNextWaveActive;
  7535. },
  7536. getIsWaveActive: function () {
  7537. let isWaveActive = false;
  7538. const allBossWaves = [9, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, 105, 121];
  7539. for (let wave of allBossWaves) {
  7540. game.ui.playerTick.wave == wave && (isWaveActive = true);
  7541. }
  7542. return isWaveActive;
  7543. },
  7544. PACKET_RPC: function(data, parent) {
  7545. if (this.data.name == "DayCycle") {
  7546. this.typeSpecificVariables.tickData = this.data.response;
  7547. }
  7548. },
  7549. PACKET_ENTITY_UPDATE: function(data, parent) {
  7550. this.typeSpecificVariables.currentTick = data.tick;
  7551.  
  7552. let dayRatio = 0,
  7553. nightRatio = 0,
  7554. barWidth = 130;
  7555. if (this.typeSpecificVariables.tickData) {
  7556. if (this.typeSpecificVariables.tickData.dayEndTick) {
  7557. if (this.typeSpecificVariables.tickData.dayEndTick > 0) {
  7558. var dayLength = this.typeSpecificVariables.tickData.dayEndTick - this.typeSpecificVariables.tickData.cycleStartTick;
  7559. var dayTicksRemaining = this.typeSpecificVariables.tickData.dayEndTick - this.typeSpecificVariables.currentTick;
  7560. dayRatio = 1 - dayTicksRemaining / dayLength;
  7561. }
  7562. } else if (this.typeSpecificVariables.tickData.nightEndTick > 0) {
  7563. var nightLength = this.typeSpecificVariables.tickData.nightEndTick - this.typeSpecificVariables.tickData.cycleStartTick;
  7564. var nightTicksRemaining = this.typeSpecificVariables.tickData.nightEndTick - this.typeSpecificVariables.currentTick;
  7565. dayRatio = 1;
  7566. nightRatio = 1 - nightTicksRemaining / nightLength;
  7567. }
  7568. var currentPosition = (dayRatio * 1 / 2 + nightRatio * 1 / 2) * - barWidth;
  7569. var offsetPosition = currentPosition + barWidth / 2;
  7570. if (offsetPosition) this.typeSpecificVariables.dayTicker = Math.round(offsetPosition);
  7571. }
  7572.  
  7573. // if (game.options.options.playerTrick) {
  7574. if (parent.getIsWaveActive() && parent.getIsZombiesActive() && game.ui.playerPartyMembers.length !== 1) {
  7575. if (this.typeSpecificVariables.playerTrickTimeouts.inull) {
  7576. this.typeSpecificVariables.playerTrickTimeouts.inull = false;
  7577. this.sendRpc({name: "LeaveParty"});
  7578. setTimeout(() => { this.typeSpecificVariables.playerTrickTimeouts && (this.typeSpecificVariables.playerTrickTimeouts.inull = true); }, 250);
  7579. }
  7580. }
  7581. if (this.typeSpecificVariables.dayTicker < -18 && this.typeSpecificVariables.dayTicker >= -23 && !this.typeSpecificVariables.tickData.isDay && parent.getIsZombiesActive() && game.ui.playerPartyMembers.length !== 1) {
  7582. if (this.typeSpecificVariables.playerTrickTimeouts.i1) {
  7583. this.typeSpecificVariables.playerTrickTimeouts.i1 = false;
  7584. this.sendRpc({name: "LeaveParty"});
  7585. setTimeout(() => { this.typeSpecificVariables.playerTrickTimeouts && (this.typeSpecificVariables.playerTrickTimeouts.i1 = true); }, 250);
  7586. }
  7587. }
  7588. if (!parent.getIsZombiesActive() && game.ui.playerPartyMembers.length !== 4 && !parent.getIsNextWaveActive()) {
  7589. if (this.typeSpecificVariables.playerTrickTimeouts.i2) {
  7590. this.typeSpecificVariables.playerTrickTimeouts.i2 = false;
  7591. this.sendRpc({name: "JoinPartyByShareKey", partyShareKey: Game.currentGame.ui.getPlayerPartyShareKey() + ""});
  7592. setTimeout(() => { this.typeSpecificVariables.playerTrickTimeouts && (this.typeSpecificVariables.playerTrickTimeouts.i2 = true); }, 250);
  7593. }
  7594. }
  7595. if (this.typeSpecificVariables.dayTicker > 18 && this.typeSpecificVariables.dayTicker <= 23 && parent.getIsZombiesActive() && this.typeSpecificVariables.tickData.isDay && game.ui.playerPartyMembers.length !== 4) {
  7596. if (this.typeSpecificVariables.playerTrickTimeouts.i3) {
  7597. this.typeSpecificVariables.playerTrickTimeouts.i3 = false;
  7598. this.sendRpc({name: "LeaveParty"});
  7599. setTimeout(() => { this.typeSpecificVariables.playerTrickTimeouts && (this.typeSpecificVariables.playerTrickTimeouts.i3 = true); }, 250)
  7600. }
  7601. }
  7602. // }
  7603. },
  7604. },
  7605. AITO: {
  7606. lastSocket: {},
  7607. PACKET_ENTITY_UPDATE: function(data, parent) {
  7608. if (this.player.partyShareKey) {
  7609. if (this.player.partyShareKey != game.ui.getPlayerPartyShareKey()) {
  7610. this.sendRpc({
  7611. name: "JoinPartyByShareKey",
  7612. partyShareKey: game.ui.getPlayerPartyShareKey()
  7613. });
  7614. } else if (this.player.targetTick.gold >= 10000) {
  7615. this.sendRpc({
  7616. name: "BuyItem",
  7617. itemName: "Pause",
  7618. tier: 1
  7619. });
  7620. };
  7621. };
  7622. },
  7623. PACKET_PRE_ENTER_WORLD: function(data, parent) {
  7624. parent.lastSocket[this.identifiers.id]?.ws?.readyState === 1 && parent.lastSocket[this.identifiers.id].ws.close();
  7625. },
  7626. PACKET_RPC: function(data, parent) {
  7627. this.sendInput({left: 1, up: 1, right: 0, down: 0});
  7628. // this.sendInput({space: 1});
  7629.  
  7630. if (this.data.name == "DayCycle") {
  7631. this.typeSpecificVariables.isDay = this.data.response.isDay;
  7632. if (!this.typeSpecificVariables.isDay) {
  7633. if (this.ws.readyState === 1 && this.typeSpecificVariables.verified === true) {
  7634. parent.lastSocket[this.identifiers.id] = this;
  7635. this.parent.shared.all[this.identifiers.id] = new this.parent.Socket(
  7636. `wss://${game.network.connectionOptions.hostname}:443/`,
  7637. this.identifiers
  7638. );
  7639. }
  7640. } else this.typeSpecificVariables.verified = true;
  7641. }
  7642. if (this.data.name == "Dead") this.sendInput({respawn: 1});
  7643. },
  7644. },
  7645. },
  7646. movementCopy: {
  7647. handlers: [{type: "entityUpdate", names: "onTick"}, {type: "keybind", names: "keyup"}],
  7648. targetLastPos: null,
  7649. target: null,
  7650. onTick: function({entities}) {
  7651. if (game.options.options.movementCopy) {
  7652. if (!this.target) {
  7653. const targets = [];
  7654. for (let entity of game.renderer.npcs.attachments) {
  7655. if (entity.uid === game.world.myUid || entity.targetTick.dead == 1) continue;
  7656. const { position, uid } = entity.targetTick;
  7657. entity.entityClass === "PlayerEntity" && targets.push({position, uid});
  7658. };
  7659. if (targets.length > 0) {
  7660. const myPos = game.ui.playerTick.position;
  7661. targets.sort((a, b) => {
  7662. const distThisToA = measureDistance(myPos, a.position);
  7663. const distThisToB = measureDistance(myPos, b.position);
  7664.  
  7665. if (distThisToA < distThisToB) return -1;
  7666. else if (distThisToA > distThisToB) return 1;
  7667.  
  7668. return 0;
  7669. });
  7670. this.target = targets[0].uid;
  7671. };
  7672. };
  7673.  
  7674. const targetInCurrentTick = entities[this.target];
  7675. const targetInWorldTick = game.world.entities[this.target];
  7676. const currentTargetPosition = targetInCurrentTick?.position;
  7677. const lastTargetPosition = this.targetLastPos || targetInWorldTick.targetTick.position;
  7678.  
  7679. if (currentTargetPosition) {
  7680. const nextMove = predictDirection(lastTargetPosition, currentTargetPosition);
  7681. nextMove && game.network.sendInput(nextMove);
  7682. this.targetLastPos = currentTargetPosition;
  7683. };
  7684.  
  7685. const {position: playerPos} = game.world.entities[game.world.myUid].targetTick;
  7686. const distFromPlayerToTarget = measureDistance(playerPos, targetInWorldTick.targetTick.position);
  7687. if (distFromPlayerToTarget > 48) {
  7688. const nextMove = predictDirection(playerPos, targetInWorldTick.targetTick.position, 48);
  7689. nextMove && game.network.sendInput(nextMove);
  7690. };
  7691. };
  7692. },
  7693. keyup: function(e) {
  7694. if (e.key == "[") getId("toggle-movementCopy").click();
  7695. },
  7696. },
  7697. spectate: {
  7698. handlers: [{type: "rpc", names: ["Dead"]}, {type: "keybind", names: ["keydown", "keyup"]}],
  7699. cameraPos: {x: 0, y: 0},
  7700. navigationKeys: {
  7701. // numpad
  7702. 104: "up",
  7703. 98: "down",
  7704. 102: "right",
  7705. 100: "left",
  7706. // wasd
  7707. 87: "up",
  7708. 83: "down",
  7709. 68: "right",
  7710. 65: "left",
  7711. // keypad
  7712. 38: "up",
  7713. 40: "down",
  7714. 39: "right",
  7715. 37: "left"
  7716. },
  7717. direction: {
  7718. up: { axis: "y", value: -96 },
  7719. down: { axis: "y", value: 96 },
  7720. right: { axis: "x", value: 96 },
  7721. left: { axis: "x", value: -96 }
  7722. },
  7723. moveCameraTo: function({x, y}) {
  7724. game.renderer.follow({ getPositionX: () => x, getPositionY: () => y });
  7725. },
  7726. init: function() {
  7727. this.spectatorNote = document.createElement('p');
  7728. this.spectatorNote.innerHTML = `Press Esc to stop spectating...<br>Use arrow keys or WASD to navigate.`;
  7729. this.spectatorNote.style.display = "none";
  7730. this.spectatorNote.style.color = "white";
  7731. this.spectatorNote.style.opacity = '0.5';
  7732. this.spectatorNote.style.textAlign = "center";
  7733. getClass('hud-top-center')[0].appendChild(this.spectatorNote);
  7734.  
  7735. getId('hud-spectate-btn').onclick = () => {
  7736. game.options.options.spectate = true;
  7737. this.spectatorNote.style.display = "block";
  7738. getId("hud-respawn").style.display = "none";
  7739. };
  7740. },
  7741. Dead: function() {
  7742. this.cameraPos = game.ui.playerTick.position;
  7743. },
  7744. keyup: function(e) {
  7745. if (e.key == "Escape") {
  7746. if (game.options.options.spectate) {
  7747. game.options.options.spectate = false;
  7748. this.spectatorNote.style.display = "none";
  7749. getId("hud-respawn").style.display = "block";
  7750. game.renderer.follow(game.world.entities[game.world.myUid]);
  7751. }
  7752. }
  7753. },
  7754. keydown: function(e) {
  7755. if (!game.options.options.spectate) return;
  7756. if (e.keyCode in this.navigationKeys) {
  7757. const {axis, value} = this.direction[this.navigationKeys[e.keyCode]];
  7758. this.cameraPos[axis] += value;
  7759. this.moveCameraTo(this.cameraPos);
  7760. };
  7761. },
  7762. },
  7763. dragBox: {
  7764. handlers: [{type: "keybind", names: "keydown"}],
  7765. buildingModels: ["Wall", "Door", "SlowTrap", "ArrowTower", "CannonTower", "MeleeTower", "BombTower", "MagicTower", "GoldMine", "Harvester"],
  7766. firstDragMouse: {
  7767. pos: {x: 0, y: 0},
  7768. hasDragged: false
  7769. },
  7770. mouseDragPos: {x: 0, y: 0},
  7771. staticWorldPos: undefined,
  7772. dragBoxElem: undefined,
  7773. dragBoxMenuElem: undefined,
  7774. resetData: function() {
  7775. this.firstDragMouse = {
  7776. pos: {x: 0, y: 0},
  7777. hasDragged: false
  7778. };
  7779. this.mouseDragPos = {x: 0, y: 0};
  7780. },
  7781. isWithinSelection: function({x, y}, {pos1, pos2}) {
  7782. return (x > Math.min(pos1.x, pos2.x) && x < Math.max(pos1.x, pos2.x) && y > Math.min(pos1.y, pos2.y) && y < Math.max(pos1.y, pos2.y));
  7783. },
  7784. findStash: function({pos1, pos2}) {
  7785. return game.renderer.scenery.attachments.find((entity) => {
  7786. if (entity.fromTick.model == "GoldStash") {
  7787. const building = entity.targetTick.position;
  7788. if (this.isWithinSelection(building, {pos1, pos2})) return entity;
  7789. }
  7790. });
  7791. },
  7792. cancelDragBox: function() {
  7793. this.dragBoxMenuElem.remove();
  7794. this.dragBoxElem.remove();
  7795. this.staticWorldPos = undefined;
  7796. window.disableZoom = false;
  7797. },
  7798. init: function() {
  7799. getId("hud").addEventListener("mousedown", this.onMouseDown.bind(this));
  7800. getId("hud").addEventListener("mousemove", this.onMouseMove.bind(this));
  7801. getId("hud").addEventListener("mouseup", this.onMouseUp.bind(this));
  7802. game.renderer.on("cameraUpdate", this.onCameraUpdate.bind(this));
  7803. },
  7804. onMouseDown: function(e) {
  7805. if (this.firstDragMouse.hasDragged || !game.options.options.dragBox || !game.world.inWorld) return;
  7806. window.disableZoom = true;
  7807. this.firstDragMouse = {
  7808. pos: {x: e.clientX, y: e.clientY},
  7809. hasDragged: true
  7810. };
  7811. this.dragBoxElem = document.createElement('div');
  7812. this.dragBoxElem.classList.add('dragBox');
  7813. this.dragBoxElem.style.top = `${e.clientY}px`;
  7814. this.dragBoxElem.style.left = `${e.clientX}px`;
  7815. getId("hud").appendChild(this.dragBoxElem);
  7816. },
  7817. onMouseMove: function(e) {
  7818. if (!this.firstDragMouse.hasDragged || !game.world.inWorld) return;
  7819. // clearTimeout(this.dragTimeout);
  7820. this.mouseDragPos = {x: e.clientX, y: e.clientY};
  7821. this.dragBoxElem.style.top = `${Math.min(this.mouseDragPos.y, this.firstDragMouse.pos.y)}px`;
  7822. this.dragBoxElem.style.left = `${Math.min(this.mouseDragPos.x, this.firstDragMouse.pos.x)}px`;
  7823. this.dragBoxElem.style.width = `${Math.abs(this.mouseDragPos.x - this.firstDragMouse.pos.x)}px`;
  7824. this.dragBoxElem.style.height = `${Math.abs(this.mouseDragPos.y - this.firstDragMouse.pos.y)}px`;
  7825. // this.dragTimeout = setTimeout(function() { this.onMouseUp(e); }.bind(this), 2000);
  7826. },
  7827. onMouseUp: function(e) {
  7828. if (!this.firstDragMouse.hasDragged || !game.world.inWorld) return;
  7829. // clearTimeout(this.dragTimeout);
  7830. const lastDragPos = { x: e.clientX, y: e.clientY };
  7831. const oldPos = { x: this.firstDragMouse.pos.x, y: this.firstDragMouse.pos.y };
  7832. this.staticWorldPos = game.renderer.screenToWorld(oldPos.x, oldPos.y);
  7833. if (Math.hypot(lastDragPos.x - oldPos.x, lastDragPos.y - oldPos.y) < 50) {
  7834. this.dragBoxElem.remove();
  7835. this.resetData();
  7836. this.staticWorldPos = undefined;
  7837. return;
  7838. }
  7839. this.dragBoxMenuElem = document.createElement('div');
  7840. this.dragBoxMenuElem.classList.add('dragBoxMenu');
  7841. this.dragBoxMenuElem.style.top = `${lastDragPos.y}px`;
  7842. this.dragBoxMenuElem.style.left = `${lastDragPos.x}px`;
  7843. this.dragBoxMenuElem.innerHTML = `
  7844. <button id="saveSelection">Save Towers</button>
  7845. <button id="delWithin">Delete Selection</button>
  7846. <button id="cancelDragBox">Cancel</button>
  7847. <small style="color: red; display: none;" id="selectionErrorMessage">Cannot find any base. Please try again.</small>
  7848. `;
  7849. getId("hud").appendChild(this.dragBoxMenuElem);
  7850.  
  7851. game.options.options.dragBox = false;
  7852. this.resetData();
  7853.  
  7854. const pos1 = this.staticWorldPos;
  7855. const pos2 = game.renderer.screenToWorld(lastDragPos.x, lastDragPos.y);
  7856.  
  7857. getId("cancelDragBox").onclick = this.cancelDragBox.bind(this);
  7858. getId("delWithin").onclick = function(e) {
  7859. const roundedX = Math.round(pos1.x / 48) * 48;
  7860. const roundedY = Math.round(pos1.y / 48) * 48;
  7861.  
  7862. const deltaX = Math.round(Math.abs(pos1.x - pos2.x) / 48);
  7863. const deltaY = Math.round(Math.abs(pos1.y - pos2.y) / 48);
  7864.  
  7865. const entitiesWithin = {};
  7866.  
  7867. for (let x = roundedX; x < roundedX + (deltaX * 48); x += 48) {
  7868. for (let y = roundedY; y < roundedY + (deltaX * 48); y += 48) {
  7869. Object.assign(entitiesWithin, getEntityAtPos(x, y));
  7870. };
  7871. };
  7872.  
  7873. game.script.sell.sellAllWithUids(Object.keys(entitiesWithin));
  7874.  
  7875. this.cancelDragBox();
  7876. }.bind(this);
  7877. getId("saveSelection").onclick = function(e) {
  7878. const goldStash = this.findStash({pos1, pos2})?.fromTick?.position;
  7879. let baseStr = '';
  7880. if (!goldStash) {
  7881. getId("selectionErrorMessage").style.display = "block";
  7882. return;
  7883. };
  7884. for (let uid in game.world.entities) {
  7885. const entity = game.world.entities[uid];
  7886. if (this.buildingModels.includes(entity.fromTick.model)) {
  7887. const buildingPos = entity.targetTick.position;
  7888. if (this.isWithinSelection(buildingPos, {pos1, pos2})) {
  7889. baseStr += `${this.buildingModels.indexOf(entity.fromTick.model)},${goldStash.x - buildingPos.x},${goldStash.y - buildingPos.y},${entity.targetTick.yaw};`;
  7890. };
  7891. }
  7892. };
  7893. if (baseStr.length == 0) {
  7894. getId("selectionErrorMessage").style.display = "block";
  7895. return;
  7896. };
  7897.  
  7898. this.cancelDragBox();
  7899.  
  7900. game.ui.components.MenuSettings.isVisible() || game.ui.components.MenuSettings.show();
  7901. window.isSlotEmpty(localStorage.totalSlots) && window.createBaseSlot();
  7902. setPage('0');
  7903. getId("more-baseSaver").click();
  7904. getId("base-item-" + localStorage.totalSlots).click();
  7905. getId('target-base-design').value = baseStr;
  7906. }.bind(this);
  7907. },
  7908. onCameraUpdate: function() {
  7909. if (!this.staticWorldPos) return;
  7910. const {x: realScreenX, y: realScreenY } = game.renderer.worldToScreen(this.staticWorldPos.x, this.staticWorldPos.y);
  7911. const rect = this.dragBoxElem.getBoundingClientRect();
  7912.  
  7913. this.dragBoxElem.style.top = `${realScreenY}px`;
  7914. this.dragBoxElem.style.left = `${realScreenX}px`;
  7915. this.dragBoxMenuElem.style.top = `${rect.y + rect.height}px`;
  7916. this.dragBoxMenuElem.style.left = `${rect.x + rect.width}px`;
  7917. },
  7918. onResize: function() {
  7919.  
  7920. },
  7921. keydown: function(e) {
  7922. if (!e.repeat && e.shiftKey && e.key == "Z") {
  7923. game.options.options.dragBox = true;
  7924. };
  7925. },
  7926. },
  7927. navigator: {
  7928. handlers: [{type: "keybind", names: "keyup"}],
  7929. targetDisplay: null,
  7930. reachedTargetX: false,
  7931. reachedTargetY: false,
  7932. lastX: 0,
  7933. lastY: 0,
  7934. current_action: "",
  7935. stuckPrediction: 0,
  7936. timeInMs: 0,
  7937. interval: 0,
  7938. lastStuckPosition: {x: 0, y: 0},
  7939. init() {
  7940. getId("hud-map").onclick = this.onMapClick.bind(this);
  7941. },
  7942. onMapClick: function(e) {
  7943. if (!e.shiftKey) return;
  7944. const rect = getId("hud-map").getBoundingClientRect(),
  7945. x = e.clientX - rect.left,
  7946. y = e.clientY - rect.top;
  7947. const worldX = (x / rect.width) * game.world.getWidth(),
  7948. worldY = (y / rect.height) * game.world.getHeight();
  7949.  
  7950. if (game.options.options.navigator) {
  7951. this.stop();
  7952. game.ui.components.PopupOverlay.showHint("Stopped current navigation.");
  7953. } else {
  7954. if (typeof worldX !== "number" || typeof worldY !== "number") return game.ui.components.PopupOverlay.showHint("Invalid value!");
  7955. if (worldX > 23900 || worldX < 30 || worldY > 23900 || worldY < 30) return game.ui.components.PopupOverlay.showHint("Coordinates too small / big");
  7956.  
  7957. this.targetDisplay = document.createElement("div");
  7958. this.targetDisplay.classList.add('hud-map-player');
  7959. this.targetDisplay.style.display = "block";
  7960. this.targetDisplay.style.left = x + "px";
  7961. this.targetDisplay.style.top = y + "px";
  7962. this.targetDisplay.style.background = 'var(--light-hover-btn)';
  7963. getId("hud-map").appendChild(this.targetDisplay);
  7964.  
  7965. this.navigate(worldX, worldY);
  7966. };
  7967. },
  7968. reset: function() {
  7969. this.targetDisplay?.remove?.();
  7970. this.reachedTargetX = false;
  7971. this.reachedTargetY = false;
  7972. this.lastX = 0;
  7973. this.lastY = 0;
  7974. this.current_action = '';
  7975. this.stuckPrediction = 0;
  7976. this.timeInMs = 0;
  7977. this.lastStuckPosition = {x: 0, y: 0};
  7978. },
  7979. stop: function() {
  7980. Game.currentGame.network.sendPacket(3, { up: 0, down: 0, left: 0, right: 0 });
  7981. console.log(`time took: ${this.timeInMs}ms`, {x: this.lastX, y: this.lastY});
  7982. game.options.options.navigator = false;
  7983. clearInterval(this.interval);
  7984. this.reset();
  7985. },
  7986. navigate: function(x, y) {
  7987. const options = game.options.options,
  7988. targetX = parseInt(x),
  7989. targetY = parseInt(y);
  7990.  
  7991. options.navigator = true;
  7992. // this.reset();
  7993.  
  7994. this.interval = setInterval(() => {
  7995. this.timeInMs += 100;
  7996.  
  7997. if (!options.navigator) return clearInterval(this.interval);
  7998. if (this.reachedTargetX && this.reachedTargetY) return this.stop();
  7999.  
  8000. const { x, y } = game.world.localPlayer.entity.targetTick.position;
  8001. if (inRange(this.lastX, x, 5) && inRange(this.lastY, y, 5)) {
  8002. this.stuckPrediction++;
  8003. this.lastStuckPosition = {x, y};
  8004. };
  8005.  
  8006. if (this.stuckPrediction > 200) {
  8007. console.log('looks like you got yourself in a confluffle!');
  8008. if (inRange(this.lastStuckPosition.x, x, 5) && inRange(this.lastStuckPosition.y, y, 5)) {
  8009. game.ui.components.PopupOverlay.showConfirmation(`It seems like you've been stuck at this position twice, do you want to cancel navigating?`, 5000, () => {
  8010. game.script.navigator.stop();
  8011. }, () => {});
  8012. }
  8013. switch(this.current_action) {
  8014. case 'ne':
  8015. sw();
  8016. break;
  8017. case 'se':
  8018. nw();
  8019. break;
  8020. case 'nw':
  8021. se();
  8022. break;
  8023. case 'sw':
  8024. ne();
  8025. break;
  8026. case 'n':
  8027. s();
  8028. break;
  8029. case 's':
  8030. n();
  8031. break;
  8032. case 'e':
  8033. w();
  8034. break;
  8035. case 'w':
  8036. e();
  8037. break;
  8038. }
  8039. if (!inRange(x, this.lastX, 350) && !inRange(y, this.lastY, 350)) this.stuckPrediction = 0;
  8040. return;
  8041. }
  8042.  
  8043. this.lastX = x;
  8044. this.lastY = y;
  8045.  
  8046. if (!this.reachedTargetX && inRange(x, targetX, 150)) { this.reachedTargetX = true; return stopX(); }
  8047. if (!this.reachedTargetY && inRange(y, targetY, 150)) { this.reachedTargetY = true; return stopY(); }
  8048.  
  8049. if (targetX > x && targetY < y) { this.current_action = 'ne'; return ne(); }
  8050. else if (targetX > x && targetY > y) { this.current_action = 'se'; return se(); }
  8051. else if (targetX < x && targetY < y) { this.current_action = 'nw'; return nw(); }
  8052. else if (targetX < x && targetY > y) { this.current_action = 'sw'; return sw(); }
  8053. else if (!this.reachedTargetY && targetY < y) { this.current_action = 'n'; return n(); }
  8054. else if (!this.reachedTargetX && targetX > x) { this.current_action = 'e'; return e(); }
  8055. else if (!this.reachedTargetY && targetY > y) { this.current_action = 's'; return s(); }
  8056. else if (!this.reachedTargetX && targetX < x) { this.current_action = 'w'; return w(); }
  8057. }, 100);
  8058.  
  8059. function n() {
  8060. Game.currentGame.network.sendPacket(3, { up: 1, down: 0, left: 0, right: 0 });
  8061. }
  8062.  
  8063. function ne() {
  8064. Game.currentGame.network.sendPacket(3, { up: 1, down: 0, left: 0, right: 1 });
  8065. }
  8066.  
  8067. function e() {
  8068. Game.currentGame.network.sendPacket(3, { up: 0, down: 0, left: 0, right: 1 });
  8069. }
  8070.  
  8071. function se() {
  8072. Game.currentGame.network.sendPacket(3, { up: 0, down: 1, left: 0, right: 1 });
  8073. }
  8074.  
  8075. function s() {
  8076. Game.currentGame.network.sendPacket(3, { up: 0, down: 1, left: 0, right: 0 });
  8077. }
  8078.  
  8079. function sw() {
  8080. Game.currentGame.network.sendPacket(3, { up: 0, down: 1, left: 1, right: 0 });
  8081. }
  8082.  
  8083. function w() {
  8084. Game.currentGame.network.sendPacket(3, { up: 0, down: 0, left: 1, right: 0 });
  8085. }
  8086.  
  8087. function nw() {
  8088. Game.currentGame.network.sendPacket(3, { up: 1, down: 0, left: 1, right: 0 });
  8089. }
  8090.  
  8091. function stopX() {
  8092. Game.currentGame.network.sendPacket(3, { left: 0, right: 0 });
  8093. }
  8094.  
  8095. function stopY() {
  8096. Game.currentGame.network.sendPacket(3, { up: 0, down: 0 });
  8097. }
  8098. },
  8099. keyup: function(e) {
  8100. if (e.key == "Escape") {
  8101. if (game.options.options.navigator) {
  8102. this.stop();
  8103. game.ui.components.PopupOverlay.showHint("Stopped current navigation.");
  8104. }
  8105. };
  8106. },
  8107. },
  8108. zoom: {
  8109. dimension: 1,
  8110. zoomonscroll: false,
  8111. upd: function() {
  8112. if (window.disableZoom) return;
  8113. getClass('zoom-prop')[0].innerText = `${this.dimension.toFixed(1)}x`;
  8114.  
  8115. const renderer = Game.currentGame.renderer;
  8116. let canvasWidth = window.innerWidth * window.devicePixelRatio;
  8117. let canvasHeight = window.innerHeight * window.devicePixelRatio;
  8118. let ratio = canvasHeight / (1080 * this.dimension);
  8119. renderer.scale = ratio;
  8120. renderer.entities.setScale(ratio);
  8121. renderer.ui.setScale(ratio);
  8122. renderer.renderer.resize(canvasWidth, canvasHeight);
  8123. renderer.viewport.width = renderer.renderer.width / renderer.scale + 2 * renderer.viewportPadding;
  8124. renderer.viewport.height = renderer.renderer.height / renderer.scale + 2 * renderer.viewportPadding;
  8125.  
  8126. const event = new Event("zoom");
  8127. document.dispatchEvent(event);
  8128. },
  8129. onWindowResize: function(e) {
  8130. if (this.zoomonscroll && e.deltaY) {
  8131. if (e.deltaY > 0) this.dimension *= 1.02;
  8132. else if (e.deltaY < 0) this.dimension /= 1.02;
  8133. }
  8134. this.upd();
  8135. },
  8136. zoom: function(val) {
  8137. this.dimension = val;
  8138. this.upd();
  8139. },
  8140. toggleZoomOnScroll: function() {
  8141. this.dimension /= 1.02;
  8142. this.zoomonscroll = !this.zoomonscroll;
  8143. const zoomMode = document.querySelector("#zoom-mode");
  8144. const zoomBtns = [...document.getElementsByClassName('hud-zoom-item')];
  8145. if (!this.zoomonscroll) {
  8146. this.resetZoom();
  8147. for (let i of zoomBtns) i.classList.remove('tag-is-disabled');
  8148. zoomMode.innerText = "Button";
  8149. } else {
  8150. zoomMode.innerText = "Scroll";
  8151. for (let i of zoomBtns) i.classList.add('tag-is-disabled');
  8152. }
  8153. },
  8154. zoomOut: function() {
  8155. this.dimension *= 1.25;
  8156. this.zoom(this.dimension);
  8157. },
  8158. zoomIn: function() {
  8159. this.dimension /= 1.25;
  8160. this.zoom(this.dimension);
  8161. },
  8162. resetZoom: function() {
  8163. this.dimension = 1;
  8164. this.zoom(this.dimension);
  8165. },
  8166. init: function() {
  8167. getId('hud').insertAdjacentHTML('beforeend', `
  8168. <div class="interaction-wheel">
  8169. <a class="hud-zoom-item zoom-reset" onclick="game.script.zoom.resetZoom();"><i class="fa fa-undo fa-lg" style="font-size: 30px;"></i></a>
  8170. <a class="hud-zoom-item zoom-up" onclick="game.script.zoom.zoomOut();"><i class="fa fa-arrow-up fa-2x" style="font-size: 30px;"></i></a>
  8171. <a class="hud-zoom-item zoom-down" onclick="game.script.zoom.zoomIn();"><i class="fa fa-arrow-down fa-2x" style="font-size: 30px;"></i></a>
  8172. <a class="hud-zoom-item zoom-prop">1.0x</a>
  8173. <a id="zoom-mode">Button</a>
  8174. <a id="next-wheel" onclick="game.script.zoom.toggleZoomOnScroll();"></a>
  8175. </div>
  8176. `);
  8177. document.addEventListener('keyup', function(e) {
  8178. if (document.activeElement.tagName.toLowerCase() !== "input" && document.activeElement.tagName.toLowerCase() !== "textarea") {
  8179. if (e.code == 'KeyG') {
  8180. const wheelDisplay = getClass('interaction-wheel')[0];
  8181. wheelDisplay.style.display = (wheelDisplay.style.display === 'block') ? 'none' : 'block';
  8182. }
  8183. if (e.code == "KeyN") {
  8184. game.script.zoom.zoomIn();
  8185. }
  8186. if (e.code == "KeyM") {
  8187. game.script.zoom.zoomOut();
  8188. }
  8189. if (e.key == "Escape") {
  8190. getClass('interaction-wheel')[0].style.display = 'none';
  8191. };
  8192. };
  8193. });
  8194. window.onresize = this.onWindowResize.bind(this);
  8195. window.onwheel = this.onWindowResize.bind(this);
  8196. window.onresize();
  8197. },
  8198. },
  8199. markers: {
  8200. currentIndex: 0,
  8201. allMarkers: [],
  8202. removeMarker: function(id) {
  8203. getId(id)?.remove?.();
  8204. delete this.allMarkers[id];
  8205. },
  8206. placeMarker: function({x, y, id, timeout, shouldIndicateIndex}) {
  8207. id ||= genUUID();
  8208. shouldIndicateIndex && (this.currentIndex++);
  8209. const markerLeft = parseInt(Math.round(x / game.world.getWidth() * 100)) - 4;
  8210. const markerTop = parseInt(Math.round(y / game.world.getHeight() * 100)) - 14;
  8211.  
  8212. const markerElem = document.createElement("div");
  8213. markerElem.style.left = `${markerLeft}%`;
  8214. markerElem.style.top = `${markerTop}%`;
  8215. markerElem.style.display = "block";
  8216. markerElem.style.color = "white";
  8217. markerElem.style.position = "absolute";
  8218. markerElem.classList.add("map-display");
  8219. markerElem.id = id;
  8220. markerElem.innerHTML = `<i class='fa fa-map-marker'>${shouldIndicateIndex ? this.currentIndex : ""}</i>`;
  8221. markerElem.onclick = (e) => {
  8222. e.stopPropagation();
  8223. if (e.shiftKey) return game.script.navigator.onMapClick(e);
  8224. game.ui.components.PopupOverlay.showConfirmation("Do you want to remove this marker?", 5000, (() => { this.removeMarker(id); }).bind(this));
  8225. };
  8226. getId("hud-map").insertAdjacentElement("beforeend", markerElem);
  8227.  
  8228. this.allMarkers[id] = {x, y};
  8229. timeout && setTimeout(() => {
  8230. getId(`${id}`).remove();
  8231. }, 240000);
  8232. },
  8233. init: function() {
  8234. getId("hud-map").addEventListener("click", (e) => {
  8235. if (e.shiftKey) return;
  8236. const rect = getId("hud-map").getBoundingClientRect(),
  8237. x = e.clientX - rect.left,
  8238. y = e.clientY - rect.top;
  8239. const worldX = (x / rect.width) * game.world.getWidth(),
  8240. worldY = (y / rect.height) * game.world.getHeight();
  8241.  
  8242. this.placeMarker({x: worldX, y: worldY});
  8243. });
  8244. },
  8245. },
  8246. optimize: {
  8247. zombieSprite: true,
  8248. towerSprite: true,
  8249. projectileSprite: true,
  8250. updateAnimation: true,
  8251. background: true,
  8252. init: function() {
  8253. if (window.location.hostname !== "localhost") {
  8254. getId("shouldUseOptimization").addEventListener("change", ({target}) => {
  8255. game.script.optimize.background = !target.checked;
  8256. });
  8257.  
  8258. game.world.networkEntityPool = null;
  8259. game.world._networkEntityPool = [];
  8260.  
  8261. const bsTick = { uid: 0, entityClass: null };
  8262. const poolSize = Game.currentGame.getNetworkEntityPooling();
  8263. for (let i = 0; i < poolSize; i++) {
  8264. const entity = new game.renderer.entityType(bsTick);
  8265. entity.reset();
  8266. game.world._networkEntityPool.push(entity);
  8267. };
  8268. game.world.getPooledNetworkEntityCount = function() {
  8269. return this._networkEntityPool.length;
  8270. };
  8271. } else {
  8272. getId("shouldUseOptimization").disabled = true;
  8273. getId("optimize-div").classList.add("disabled");
  8274. };
  8275. },
  8276. },
  8277. };
  8278.  
  8279. /* @Add-ons */
  8280. game.ui.components.PlacementOverlay.update = function () {
  8281. if (this.buildingId) {
  8282. var buildingSchema = this.ui.getBuildingSchema(),
  8283. building = buildingSchema[this.buildingId],
  8284. mousePos = this.ui.getMousePosition(),
  8285. world = Game.currentGame.world,
  8286. worldMousePos = Game.currentGame.renderer.screenToWorld(mousePos.x, mousePos.y),
  8287. cells = world.entityGrid.getCellIndexes(worldMousePos.x, worldMousePos.y, {
  8288. 'width': building.gridWidth,
  8289. 'height': building.gridHeight
  8290. }),
  8291. cellSize = world.entityGrid.getCellSize(),
  8292. coord = {
  8293. 'x': 0,
  8294. 'y': 0
  8295. };
  8296. for (var cell in cells) {
  8297. if (cells[cell]) {
  8298. var cellCoord = world.entityGrid.getCellCoords(cells[cell]),
  8299. _cellCoord = {
  8300. 'x': cellCoord.x * cellSize + cellSize / 2,
  8301. 'y': cellCoord.y * cellSize + cellSize / 2
  8302. },
  8303. worldToUi = Game.currentGame.renderer.worldToUi(_cellCoord.x, _cellCoord.y),
  8304. isOccupied = this.checkIsOccupied(cells[cell], cellCoord);
  8305. this.placeholderTints[cell].setPosition(worldToUi.x, worldToUi.y);
  8306. this.placeholderTints[cell].setIsOccupied(isOccupied);
  8307. this.placeholderTints[cell].setVisible(true);
  8308. coord.x += cellCoord.x;
  8309. coord.y += cellCoord.y;
  8310. } else this.placeholderTints[cell].setVisible(false);
  8311. };
  8312. coord.x = coord.x / cells.length;
  8313. coord.y = coord.y / cells.length;
  8314. var worldPos = {
  8315. 'x': coord.x * cellSize + cellSize / 2,
  8316. 'y': coord.y * cellSize + cellSize / 2
  8317. },
  8318. uiPos = Game.currentGame.renderer.worldToUi(worldPos.x, worldPos.y);
  8319. if (!this.rangeIndicator) {
  8320. var { maxStashDistance } = game.ui.components.BuildingOverlay;
  8321. if ('GoldStash' == this.buildingId) {
  8322. this.rangeIndicator = game.assetManager.models.rangeIndicatorModel({
  8323. 'width': maxStashDistance * cellSize * 2,
  8324. 'height': maxStashDistance * cellSize * 2
  8325. }, {r: 0xff, g: 0xff, b: 0xff}, {r: 0xdd, g: 0xdd, b: 0xdd});
  8326. } else if (building.rangeTiers) {
  8327. this.rangeIndicator = game.assetManager.models.rangeIndicatorModel({
  8328. 'isCircular': true,
  8329. 'radius': building.rangeTiers[0] * 0.57071
  8330. }, {r: 0xff, g: 0xff, b: 0xff}, {r: 0xdd, g: 0xdd, b: 0xdd});
  8331. };
  8332. this.rangeIndicator && Game.currentGame.renderer.ground.addAttachment(this.rangeIndicator);
  8333. };
  8334. this.placeholderEntity.setPosition(uiPos.x, uiPos.y);
  8335. this.placeholderText.setPosition(uiPos.x, uiPos.y - 110);
  8336. this.rangeIndicator && this.rangeIndicator.setPosition(worldPos.x, worldPos.y);
  8337. };
  8338. };
  8339. game.ui.components.PlacementOverlay.cancelPlacing = function () {
  8340. if (this.buildingId) {
  8341. Game.currentGame.renderer.ui.removeAttachment(this.placeholderEntity);
  8342. Game.currentGame.renderer.ground.removeAttachment(this.rangeIndicator);
  8343. for (let cell in this.placeholderTints) Game.currentGame.renderer.ui.removeAttachment(this.placeholderTints[cell]);
  8344. for (let cell in this.borderTints) Game.currentGame.renderer.ground.removeAttachment(this.borderTints[cell]);
  8345. this.placeholderText.setAlpha(0x0);
  8346. this.placeholderText.setPosition(-0x3e8, -0x3e8);
  8347. this.placeholderEntity = null;
  8348. this.rangeIndicator = null;
  8349. this.placeholderTints = [];
  8350. this.borderTints = [];
  8351. this.buildingId = null;
  8352. };
  8353. };
  8354.  
  8355. /* @Rebinds */
  8356. getId('hud-debug').style.color = 'var(--light-hover-btn)';
  8357. game.debug.onRendererTick = function () {
  8358. if (this.ticks++, this.visible && this.ticks % 0x14 === 0x0) {
  8359. let debugHTML = `Server: ` + Game.currentGame.network.connectionOptions.id + ` (` + Game.currentGame.network.connectionOptions.name + `)<br>`,
  8360. serverTime = Game.currentGame.world.replicator.getServerTime(),
  8361. clientTime = Game.currentGame.world.replicator.getClientTime(),
  8362. realClientTime = Game.currentGame.world.replicator.getRealClientTime(),
  8363. frameStutters = Game.currentGame.world.replicator.getFrameStutters(),
  8364. interpolating = Game.currentGame.world.replicator.getInterpolating(),
  8365. tickByteSize = Game.currentGame.world.replicator.getTickByteSize(),
  8366. tickEntities = Game.currentGame.world.replicator.getTickEntities(),
  8367. pooledNetworkEntityCount = (Game.currentGame.world.getLocalPlayer(), Game.currentGame.world.getPooledNetworkEntityCount()),
  8368. frameExtrapolated = Game.currentGame.metrics.getFramesExtrapolated(),
  8369. clientTimeResets = Game.currentGame.world.replicator.getClientTimeResets(),
  8370. maxExtrapolationTime = Game.currentGame.world.replicator.getMaxExtrapolationTime(),
  8371. playerPos = game.world.localPlayer.entity.getPosition(),
  8372. kilobytePerSec = tickByteSize / 1024 * 20,
  8373. isTickLarge = kilobytePerSec > 150;
  8374. debugHTML = debugHTML + `Ping: ` + Game.currentGame.network.getPing() + ` ms<br>`;
  8375. debugHTML = debugHTML + `Server time: ` + serverTime + '\x20ms<br>';
  8376. debugHTML = debugHTML + `Client time: ` + clientTime + ` ms<br>`;
  8377. debugHTML = debugHTML + `Real client time: ` + realClientTime + ` ms<br>`;
  8378. debugHTML = debugHTML + `Client lag: ` + (serverTime - clientTime) + '\x20ms<br>';
  8379. debugHTML = debugHTML + `Real client lag: ` + (serverTime - realClientTime) + ` ms<br>`;
  8380. debugHTML = debugHTML + 'Stutters:\x20' + frameStutters + `<br>`;
  8381. debugHTML = debugHTML + `Frames extrapolated: ` + frameExtrapolated + `<br>`;
  8382. debugHTML = debugHTML + `Max extrapolation time: ` + maxExtrapolationTime + '<br>';
  8383. debugHTML = debugHTML + `Client time resets: ` + clientTimeResets + `<br>`;
  8384. debugHTML = debugHTML + `Interpolating: ` + interpolating + `<br>`;
  8385. debugHTML = debugHTML + `Tick byte size: ` + (isTickLarge ? "<strong>" : "") + tickByteSize + '\x20(' + kilobytePerSec.toFixed(2) + 'KB/s)' + (isTickLarge ? "</strong>" : "") + '<br>';
  8386. debugHTML = debugHTML + `Tick entities: ` + tickEntities + '<br>';
  8387. debugHTML = debugHTML + 'Pooled\x20network\x20entities:\x20' + pooledNetworkEntityCount + '<br>';
  8388. debugHTML += `Pooled model entities:<br>`;
  8389. for (const modelName in Game.currentGame.getModelEntityPooling()) {
  8390. debugHTML = debugHTML + '- ' + modelName + ': ' + Game.currentGame.world.getPooledModelEntityCount(modelName) + '<br>';
  8391. }
  8392. debugHTML = debugHTML + 'Player\x20position:\x20<br>';
  8393. debugHTML = debugHTML + '-\x20X:\x20' + playerPos.x.toFixed(2) + '<br>';
  8394. debugHTML = debugHTML + '-\x20Y:\x20' + playerPos.y.toFixed(2) + '<br>';
  8395. this.debugElem.innerHTML = debugHTML;
  8396. }
  8397. }
  8398. game.renderer.tickCallbacks[8] = game.debug.onRendererTick.bind(game.debug);
  8399.  
  8400. game.ui.components.MenuParty.update = function () {
  8401. var parties = this.ui.getParties();
  8402. var playerIsLeader = this.ui.getPlayerPartyLeader();
  8403. var playerPartyData = parties[this.ui.getPlayerPartyId()];
  8404. var playerPartyMembers = this.ui.getPlayerPartyMembers();
  8405. var serverId = this.ui.getOption('serverId');
  8406. var staleElems = {};
  8407. var availableParties = 0;
  8408.  
  8409. this.clonedPartyElems ||= {};
  8410. this.closedGridElem ||= getId("privateHud2");
  8411.  
  8412. for (var partyId in this.partyElems) {
  8413. staleElems[partyId] = true;
  8414. }
  8415. for (var partyId in parties) {
  8416. var partyData = parties[partyId];
  8417. var partyElem = this.partyElems[partyId];
  8418. var partyNameSanitized = window.filterXSS(partyData.partyName);
  8419. delete staleElems[partyId];
  8420. if (!this.partyElems[partyId]) {
  8421. partyElem = this.ui.createElement("<div class=\"hud-party-link\"></div>");
  8422. this.clonedPartyElems[partyId] = this.ui.createElement("<div class=\"hud-party-link\"></div>");
  8423. this.partyElems[partyId] = partyElem;
  8424. this.gridElem.appendChild(partyElem);
  8425. this.closedGridElem.appendChild(this.clonedPartyElems[partyId]);
  8426. partyElem.addEventListener('click', this.onPartyJoinRequestHandler(partyData.partyId).bind(this));
  8427. }
  8428. if (partyData.isOpen) {
  8429. partyElem.style.display = 'block';
  8430. this.clonedPartyElems[partyId].style.display = "none";
  8431. availableParties++;
  8432. }
  8433. else {
  8434. partyElem.style.display = 'none';
  8435. this.clonedPartyElems[partyId].style.display = "block";
  8436. }
  8437. if (this.ui.getPlayerPartyId() === partyData.partyId) {
  8438. partyElem.classList.add('is-active');
  8439. partyElem.classList.remove('is-disabled');
  8440.  
  8441. this.clonedPartyElems[partyId].classList.add('is-active');
  8442. this.clonedPartyElems[partyId].classList.remove('is-disabled');
  8443. }
  8444. else if (partyData.memberCount === this.maxPartySize) {
  8445. partyElem.classList.remove('is-active');
  8446. partyElem.classList.add('is-disabled');
  8447.  
  8448. this.clonedPartyElems[partyId].classList.remove('is-active');
  8449. this.clonedPartyElems[partyId].classList.add('is-disabled');
  8450. }
  8451. else {
  8452. partyElem.classList.remove('is-active');
  8453. partyElem.classList.remove('is-disabled');
  8454.  
  8455. this.clonedPartyElems[partyId].classList.remove('is-active');
  8456. this.clonedPartyElems[partyId].classList.remove('is-disabled');
  8457. }
  8458. partyElem.innerHTML = "<strong>" + partyNameSanitized + "</strong><small>ID: " + partyData.partyId + "</small> <span>" + partyData.memberCount + "/" + this.maxPartySize + "</span><span>-</span>";
  8459. this.clonedPartyElems[partyId].innerHTML = "<strong>" + partyNameSanitized + "</strong><small>ID: " + partyData.partyId + "</small> <span>" + partyData.memberCount + "/" + this.maxPartySize + "</span>";
  8460. }
  8461. for (var partyId in staleElems) {
  8462. if (!this.partyElems[partyId]) {
  8463. continue;
  8464. }
  8465. this.partyElems[partyId].remove();
  8466. this.clonedPartyElems[partyId].remove();
  8467. delete this.partyElems[partyId];
  8468. delete this.clonedPartyElems[partyId];
  8469. }
  8470. for (var i in this.memberElems) {
  8471. this.memberElems[i].remove();
  8472. delete this.memberElems[i];
  8473. }
  8474. for (var i in playerPartyMembers) {
  8475. var playerName = window.filterXSS(playerPartyMembers[i].displayName);
  8476. var memberElem = this.ui.createElement(
  8477. "<div class=\"hud-member-link\">\n <strong>" + playerName + "</strong>\n <small>" + (playerPartyMembers[i].isLeader === 1 ? 'Leader' : 'Member') + "</small>\n <div class=\"hud-member-actions\">\n <a class=\"hud-member-can-sell btn" + (!playerIsLeader || playerPartyMembers[i].isLeader === 1 ? ' is-disabled' : '') + (playerPartyMembers[i].canSell === 1 ? ' is-active' : '') + "\"><span class=\"hud-can-sell-tick\"></span> Can sell buildings</a>\n <a class=\"hud-member-kick btn btn-red" + (!playerIsLeader || playerPartyMembers[i].isLeader === 1 ? ' is-disabled' : '') + "\">Kick</a>\n </div>\n </div>"
  8478. );
  8479. this.membersElem.appendChild(memberElem);
  8480. this.memberElems[i] = memberElem;
  8481. if (playerIsLeader && playerPartyMembers[i].isLeader === 0) {
  8482. var kickElem = memberElem.querySelector('.hud-member-kick');
  8483. var canSellElem = memberElem.querySelector('.hud-member-can-sell');
  8484. kickElem.addEventListener('click', this.onPartyMemberKick(i).bind(this));
  8485. canSellElem.addEventListener('click', this.onPartyMemberCanSellToggle(i).bind(this));
  8486. }
  8487. }
  8488. if (availableParties > 0) {
  8489. this.gridEmptyElem.style.display = 'none';
  8490. }
  8491. else {
  8492. this.gridEmptyElem.style.display = 'block';
  8493. }
  8494. if (!playerPartyData) {
  8495. this.tagInputElem.setAttribute('disabled', 'true');
  8496. this.tagInputElem.value = '';
  8497. this.shareInputElem.setAttribute('disabled', 'true');
  8498. this.shareInputElem.value = '';
  8499. this.visibilityElem.classList.add('is-disabled');
  8500. return;
  8501. }
  8502. if (document.activeElement !== this.tagInputElem) {
  8503. this.tagInputElem.value = playerPartyData.partyName;
  8504. }
  8505. if (playerIsLeader) {
  8506. this.tagInputElem.removeAttribute('disabled');
  8507. }
  8508. else {
  8509. this.tagInputElem.setAttribute('disabled', 'true');
  8510. }
  8511. this.shareInputElem.removeAttribute('disabled');
  8512. this.shareInputElem.value = 'https://zombs.io/#/' + serverId + '/' + this.ui.getPlayerPartyShareKey();
  8513. if (playerIsLeader) {
  8514. this.visibilityElem.classList.remove('is-disabled');
  8515. }
  8516. else {
  8517. this.visibilityElem.classList.add('is-disabled');
  8518. }
  8519. if (playerPartyData.isOpen) {
  8520. this.visibilityElem.classList.remove('is-private');
  8521. this.visibilityElem.innerText = 'Public';
  8522. }
  8523. else {
  8524. this.visibilityElem.classList.add('is-private');
  8525. this.visibilityElem.innerText = 'Private';
  8526. }
  8527. };
  8528. getClass("hud-party-actions")[0].insertAdjacentHTML("afterend", `
  8529. <div class="partydiv" style="text-align: center">
  8530. <button class="btn btn-red" style="width: 275.5px;margin: 10px 0 0 3px;box-shadow: none;" onclick="Game.currentGame.network.sendRpc({name: 'LeaveParty'});">Leave</button>
  8531. </div>`);
  8532.  
  8533. game.ui.components.Leaderboard.update = function () {
  8534. const currentGame = Game.currentGame;
  8535. // this.playerUidElems ||= {};
  8536. for (let leaderboardElem = 0; leaderboardElem < this.leaderboardData.length; leaderboardElem++) {
  8537. let playerData = this.leaderboardData[leaderboardElem],
  8538. playerName = this.playerNames[playerData.uid];
  8539. this.playerNames[playerData.uid] || (
  8540. playerName = window.filterXSS(playerData.name),
  8541. this.playerNames[playerData.uid] = playerName
  8542. );
  8543. leaderboardElem in this.playerElems || (
  8544. this.playerElems[leaderboardElem] = this.ui.createElement('<div\x20class=\x22hud-leaderboard-player\x22></div>'),
  8545. // this.playerUidElems[leaderboardElem] = this.ui.createElement('<span\x20class=\x22player-uid\x22>-</span>'),
  8546. this.playerRankElems[leaderboardElem] = this.ui.createElement(`<span class="player-rank">-</span>`),
  8547. this.playerNameElems[leaderboardElem] = this.ui.createElement(`<strong class="player-name">-</strong>`),
  8548. this.playerScoreElems[leaderboardElem] = this.ui.createElement(`<span class="player-score">-</span>`),
  8549. this.playerWaveElems[leaderboardElem] = this.ui.createElement('<span\x20class=\x22player-wave\x22>-</span>'),
  8550.  
  8551. this.playerElems[leaderboardElem].appendChild(this.playerRankElems[leaderboardElem]),
  8552. // this.playerElems[leaderboardElem].appendChild(this.playerUidElems[leaderboardElem]),
  8553. this.playerElems[leaderboardElem].appendChild(this.playerNameElems[leaderboardElem]),
  8554. this.playerElems[leaderboardElem].appendChild(this.playerScoreElems[leaderboardElem]),
  8555. this.playerElems[leaderboardElem].appendChild(this.playerWaveElems[leaderboardElem]),
  8556.  
  8557. this.playersElem.appendChild(this.playerElems[leaderboardElem])
  8558. );
  8559.  
  8560. game.world.myUid === playerData.uid
  8561. ? this.playerElems[leaderboardElem].classList.add('is-active')
  8562. : this.playerElems[leaderboardElem].classList.remove(`is-active`);
  8563.  
  8564. this.playerElems[leaderboardElem].style.display = `block`;
  8565. // this.playerUidElems[leaderboardElem].innerText = playerData.uid;
  8566. this.playerRankElems[leaderboardElem].innerText = '#' + (playerData.rank + 1);
  8567. this.playerNameElems[leaderboardElem].innerText = playerName;
  8568. this.playerScoreElems[leaderboardElem].innerText = playerData.score.toLocaleString();
  8569. this.playerWaveElems[leaderboardElem].innerHTML = (0 === playerData.wave) ? `<small>-</small>` : playerData.wave.toLocaleString();
  8570.  
  8571. }
  8572. if (this.leaderboardData.length < this.playerElems.length) {
  8573. for (let invalidEntries = this.leaderboardData.length; invalidEntries < this.playerElems.length; invalidEntries++) {
  8574. this.playerElems[invalidEntries].style.display = `none`;
  8575. }
  8576. }
  8577. }
  8578.  
  8579. game.ui.components.BuildingOverlay.createResourceCostString = function (schema, schemaTier, amountOfBuildings) {
  8580. void 0 === schemaTier && (schemaTier = 0x1);
  8581. void 0 === amountOfBuildings && (amountOfBuildings = 0x1);
  8582. var totalCost = [],
  8583. resources = {
  8584. 'wood': `wood`,
  8585. 'stone': `stone`,
  8586. 'gold': 'gold',
  8587. 'token': 'tokens'
  8588. },
  8589. playerTick = Game.currentGame.ui.getPlayerTick();
  8590. for (var resource in resources) {
  8591. var resourceCost = resource + `Costs`;
  8592. if (schema[resourceCost] && schema[resourceCost][schemaTier - 1]) {
  8593. var currentTotalCost = schema[resourceCost][schemaTier - 1] * amountOfBuildings,
  8594. canAfford = playerTick && playerTick[resource] >= currentTotalCost;
  8595. canAfford
  8596. ? totalCost.push('<span\x20class=\x22hud-resource-' + resources[resource] + '\x22>' + currentTotalCost.toLocaleString() + '\x20' + resources[resource] + `</span>`)
  8597. : totalCost.push(`<span class="hud-resource-` + resources[resource] + ` hud-resource-low">` + currentTotalCost.toLocaleString() + '\x20' + resources[resource] + `</span>`);
  8598. }
  8599. }
  8600. return totalCost.length > 0 ? totalCost.join(',\x20') : `<span class="hud-resource-free">Free</span>`;
  8601. }
  8602.  
  8603. game.ui.components.BuildingOverlay.createResourceRefundString = function (buildingType, buildingSchema, tier) {
  8604. void 0 === tier && (tier = 1);
  8605. var totalCost = [],
  8606. buildingsByTier = {},
  8607. buildings = Object.values(game.ui.buildings).filter(e => e.type == buildingType),
  8608. resources = {
  8609. 'wood': `wood`,
  8610. 'stone': `stone`,
  8611. 'gold': `gold`,
  8612. 'token': 'tokens'
  8613. };
  8614. for (let building of buildings) {
  8615. buildingsByTier[building.tier] ||= 0;
  8616. buildingsByTier[building.tier]++;
  8617. }
  8618. for (var resource in resources) {
  8619. var resourceCost = resource + `Costs`;
  8620. if (buildingSchema[resourceCost]) {
  8621. var totalTierCost = 0;
  8622. if (this.shouldUpgradeAll) {
  8623. for (let i = 1; i <= tier; i++) {
  8624. totalTierCost = Math.floor(
  8625. buildingSchema[resourceCost].slice(0, i)
  8626. .reduce((prev, curr) => prev + curr, 0) / 2
  8627. ) * buildingsByTier[i];
  8628. }
  8629. } else totalTierCost = Math.floor(buildingSchema[resourceCost].slice(0, tier).reduce((prev, curr) => prev + curr, 0) / 2);
  8630. totalTierCost && totalCost.push('<span\x20class=\x22hud-resource-' + resources[resource] + '\x22>' + totalTierCost.toLocaleString() + '\x20' + resources[resource] + `</span>`);
  8631. }
  8632. }
  8633. return totalCost.length > 0 ? totalCost.join(',\x20') : `<span class="hud-resource-free">None</span>`;
  8634. }
  8635.  
  8636.  
  8637. game.ui.components.BuildingOverlay.excludeBuilding = function() {
  8638. game.script.AHRC.excludedHarvesters.has(this.buildingUid) ? (
  8639. this.excludeElem.classList.add("btn-theme"),
  8640. this.excludeElem.classList.remove("btn-red"),
  8641. this.excludeElem.innerHTML = `Exclude Harvester<i class="fa fa-minus" style="position: absolute;right: 10px;top: 13px;"></i>`,
  8642. game.script.AHRC.excludedHarvesters.delete(this.buildingUid)
  8643. ) : (
  8644. this.excludeElem.classList.add("btn-red"),
  8645. this.excludeElem.classList.remove("btn-theme"),
  8646. this.excludeElem.innerHTML = `Include Harvester<i class="fa fa-plus" style="position: absolute;right: 10px;top: 13px;"></i>`,
  8647. game.script.AHRC.excludedHarvesters.add(this.buildingUid)
  8648. );
  8649. }
  8650.  
  8651. game.ui.components.BuildingOverlay.viewFromBuilding = function() {
  8652. const buildings = game.ui.getBuildings(),
  8653. building = game.world.entities[this.buildingUid];
  8654. if (!building) return;
  8655.  
  8656. this.isViewingFromBuilding = true;
  8657. this.componentElem.style.opacity = "0.1";
  8658. game.renderer.follow(building);
  8659. };
  8660.  
  8661. game.ui.components.BuildingOverlay.stopWatching = function () {
  8662. this.buildingUid && (
  8663. this.isViewingFromBuilding && game.renderer.follow(game.world.entities[game.world.myUid]),
  8664. this.rangeIndicator && (
  8665. Game.currentGame.renderer.ground.removeAttachment(this.rangeIndicator),
  8666. delete this.rangeIndicator
  8667. ),
  8668. this.componentElem.innerHTML = '',
  8669. this.componentElem.style.opacity = "1",
  8670. this.componentElem.style.left = `-1000px`,
  8671. this.componentElem.style.top = '-1000px',
  8672. this.buildingUid = null,
  8673. this.buildingId = null,
  8674. this.buildingTier = null,
  8675. this.hide()
  8676. );
  8677. }
  8678.  
  8679. game.ui.components.BuildingOverlay.startWatching = function(buildingId) {
  8680. this.buildingUid && this.stopWatching();
  8681. let buildings = this.ui.getBuildings(),
  8682. building = buildings[buildingId];
  8683. if (!building) return;
  8684. this.buildingUid = buildingId;
  8685. this.buildingId = building.type;
  8686. this.buildingTier = building.tier;
  8687. const schema = this.ui.getBuildingSchema(),
  8688. buildingSchema = schema[this.buildingId];
  8689. if ('GoldStash' == this.buildingId) {
  8690. var world = Game.currentGame.world,
  8691. cellSize = world.entityGrid.getCellSize();
  8692. this.rangeIndicator = game.assetManager.loadModel('RangeIndicatorModel', {
  8693. 'width': this.maxStashDistance * cellSize * 2,
  8694. 'height': this.maxStashDistance * cellSize * 2
  8695. });
  8696. Game.currentGame.renderer.ground.addAttachment(this.rangeIndicator);
  8697. } else if (buildingSchema.rangeTiers) {
  8698. this.rangeIndicator = game.assetManager.loadModel('RangeIndicatorModel', {
  8699. 'isCircular': true,
  8700. 'radius': buildingSchema.rangeTiers[this.buildingTier - 1] * 0.57071
  8701. });
  8702. Game.currentGame.renderer.ground.addAttachment(this.rangeIndicator)
  8703. };
  8704. this.componentElem.innerHTML = `<div class="hud-tooltip-building">
  8705. <h2>` + buildingSchema.name + `</h2>
  8706. <h3>Tier <span class="hud-building-tier">` + this.buildingTier + `</span> Building</h3>
  8707. <div class="hud-tooltip-health">
  8708. <span class="hud-tooltip-health-bar" style="width:100%;"></span>
  8709. </div>
  8710. <div class="hud-tooltip-body">
  8711. <div class="hud-building-stats"></div>
  8712. <p class="hud-building-actions">
  8713. <span class="hud-building-dual-btn">
  8714. <a class="btn btn-purple hud-building-deposit">Refuel</a>
  8715. <a class="btn btn-gold hud-building-collect">Collect</a>
  8716. </span>
  8717. <a class="btn btn-theme hud-building-ahrc">Exclude Harvester<i class="fa fa-minus" style="position: absolute;right: 10px;top: 13px;"></i></a>
  8718. <a class="btn btn-theme hud-building-view" style="display: none;">View From Building<i class="fas fa-eye" style="position: absolute;right: 10px;top: 13px;"></i></a>
  8719. <a class="btn btn-green hud-building-upgrade">Upgrade</a>
  8720. <a class="btn btn-red hud-building-sell">Sell</a>
  8721. </p>
  8722. </div>
  8723. </div>`;
  8724. this.tierElem = this.componentElem.querySelector(`.hud-building-tier`);
  8725. this.healthBarElem = this.componentElem.querySelector(`.hud-tooltip-health-bar`);
  8726. this.statsElem = this.componentElem.querySelector(`.hud-building-stats`);
  8727. this.actionsElem = this.componentElem.querySelector(`.hud-building-actions`);
  8728. this.depositElem = this.componentElem.querySelector(`.hud-building-deposit`);
  8729. this.dualBtnElem = this.componentElem.querySelector(`.hud-building-dual-btn`);
  8730. this.excludeElem = this.componentElem.querySelector(`.hud-building-ahrc`);
  8731. this.collectElem = this.componentElem.querySelector(`.hud-building-collect`);
  8732. this.viewElem = this.componentElem.querySelector('.hud-building-view');
  8733. this.upgradeElem = this.componentElem.querySelector('.hud-building-upgrade');
  8734. this.sellElem = this.componentElem.querySelector('.hud-building-sell');
  8735. `Harvester` !== this.buildingId && (
  8736. this.dualBtnElem.style.display = `none`,
  8737. this.excludeElem.style.display = `none`,
  8738. this.viewElem.style.display = `block`
  8739. );
  8740. game.script.AHRC.excludedHarvesters.has(this.buildingUid) ? (
  8741. this.excludeElem.classList.add("btn-red"),
  8742. this.excludeElem.classList.remove("btn-theme"),
  8743. this.excludeElem.innerHTML = `Include Harvester<i class="fa fa-plus" style="position: absolute;right: 10px;top: 13px;"></i>`
  8744. ) : (
  8745. this.excludeElem.classList.add("btn-theme"),
  8746. this.excludeElem.classList.remove("btn-red"),
  8747. this.excludeElem.innerHTML = `Exclude Harvester<i class="fa fa-minus" style="position: absolute;right: 10px;top: 13px;"></i>`
  8748. );
  8749. this.depositElem.addEventListener(`click`, this.depositIntoBuilding.bind(this));
  8750. this.collectElem.addEventListener(`click`, this.collectFromBuilding.bind(this));
  8751. this.excludeElem.addEventListener(`click`, this.excludeBuilding.bind(this));
  8752. this.viewElem.addEventListener(`click`, this.viewFromBuilding.bind(this));
  8753. this.upgradeElem.addEventListener(`click`, this.upgradeBuilding.bind(this));
  8754. this.sellElem.addEventListener(`click`, this.sellBuilding.bind(this));
  8755. this.show();
  8756. this.update();
  8757. }
  8758. game.ui.components.BuildingOverlay.update = function () {
  8759. if (this.buildingUid) {
  8760. const buildingEntity = Game.currentGame.world.getEntityByUid(this.buildingUid);
  8761. if (!buildingEntity) return void this.stopWatching();
  8762.  
  8763. let renderer = Game.currentGame.renderer,
  8764. buildingUiPosition = renderer.worldToScreen(buildingEntity.getPositionX(), buildingEntity.getPositionY()),
  8765. buildingTick = buildingEntity.getTargetTick(),
  8766. buildingsSchema = this.ui.getBuildingSchema(),
  8767. buildings = this.ui.getBuildings(),
  8768. buildingSchema = buildingsSchema[this.buildingId],
  8769. building = buildings[this.buildingUid];
  8770. if (!building) return void this.stopWatching();
  8771.  
  8772. let buildingHeight = buildingSchema.gridHeight,
  8773. buildingScale = (buildingSchema.gridWidth, buildingHeight / 2 * 48 * (renderer.getScale() / window.devicePixelRatio)),
  8774. buildingTier = building.tier,
  8775. buildingSchemaTier = 1,
  8776. isBuildingMaxed = false,
  8777. isBuildingAtMaxTier = false,
  8778. currentStats = {},
  8779. nextTierStats = {},
  8780. sameBuildings = 1,
  8781. buildingStats = {
  8782. 'health': `Health`,
  8783. 'damage': `Damage`,
  8784. 'range': 'Range',
  8785. 'gps': 'Gold/Sec',
  8786. 'harvest': `Harvest/Sec`,
  8787. 'harvestCapacity': `Capacity`,
  8788. 'msBetweenFires': `Firerate`
  8789. };
  8790.  
  8791. if (buildingSchema.tiers) {
  8792. const stashTier = this.getGoldStashTier();
  8793. building.tier < buildingSchema.tiers ? (buildingSchemaTier = building.tier + 1, isBuildingMaxed = false) : (buildingSchemaTier = building.tier, isBuildingMaxed = true);
  8794. isBuildingAtMaxTier = !isBuildingMaxed && (building.tier < stashTier || `GoldStash` === this.buildingId);
  8795. }
  8796. for (let buildingStat in buildingStats) {
  8797. let currentStat = `<small>&mdash;</small>`,
  8798. nextTierStat = '<small>&mdash;</small>';
  8799. buildingSchema[buildingStat + `Tiers`] && (
  8800. currentStat = buildingSchema[buildingStat + `Tiers`][buildingTier - 1],
  8801. buildingStat == "msBetweenFires" && (currentStat = (1000 / currentStat).toFixed(2).toLocaleString()),
  8802. isBuildingMaxed || (
  8803. nextTierStat = buildingSchema[buildingStat + 'Tiers'][buildingSchemaTier - 1],
  8804. buildingStat == "msBetweenFires" && (nextTierStat = (1000 / nextTierStat).toFixed(2).toLocaleString())
  8805. ),
  8806. currentStats[buildingStat] = '<p>' + buildingStats[buildingStat] + `: <strong class="hud-stats-current">` + currentStat + '</strong></p>',
  8807. nextTierStats[buildingStat] = `<p>` + buildingStats[buildingStat] + ':\x20<strong\x20class=\x22hud-stats-next\x22>' + nextTierStat + `</strong></p>`
  8808. );
  8809. }
  8810. if (this.shouldUpgradeAll) {
  8811. sameBuildings = 0;
  8812. for (let buildingUid in buildings) {
  8813. // parseInt(buildingUid); tf
  8814. buildings[buildingUid].type === this.buildingId && buildings[buildingUid].tier === building.tier && sameBuildings++;
  8815. }
  8816. }
  8817. let costString = this.createResourceCostString(buildingSchema, buildingSchemaTier, sameBuildings),
  8818. refundString = this.createResourceRefundString(this.buildingId, buildingSchema, building.tier),
  8819. buildingHealth = Math.round(buildingTick.health / buildingTick.maxHealth * 100);
  8820.  
  8821. buildingTick.partyId !== this.ui.getPlayerPartyId() ? this.actionsElem.style.display = `none` : this.actionsElem.style.display = 'block';
  8822. this.tierElem.innerHTML = building.tier.toString();
  8823. this.buildingTier = building.tier;
  8824. this.healthBarElem.style.width = buildingHealth + '%';
  8825. if (Object.keys(currentStats).length > 0) {
  8826. let currentStatValues = '',
  8827. nextTierStatValues = '';
  8828. for (let stat in currentStats) currentStatValues += currentStats[stat];
  8829. for (let stat in nextTierStats) nextTierStatValues += nextTierStats[stat];
  8830. this.statsElem.innerHTML = `
  8831. <div class="hud-stats-current hud-stats-values">
  8832. ` + currentStatValues + `
  8833. </div>
  8834. <div class="hud-stats-next hud-stats-values">
  8835. ` + nextTierStatValues + `
  8836. </div>
  8837. `;
  8838. } else this.statsElem.innerHTML = '';
  8839. if (`Harvester` === this.buildingId) {
  8840. let depositAmount = Math.floor(buildingTick.depositMax / 10),
  8841. isDepositPossible = buildingTick.depositMax - buildingTick.deposit < depositAmount;
  8842. isDepositPossible ? this.depositElem.classList.add('is-disabled') : this.depositElem.classList.remove(`is-disabled`);
  8843. this.shouldUpgradeAll
  8844. ? this.depositElem.innerHTML = 'Refuel\x20All\x20<small>(' + (depositAmount * sameBuildings).toLocaleString() + ` gold)</small>`
  8845. : this.depositElem.innerHTML = 'Refuel\x20<small>(' + depositAmount.toLocaleString() + ` gold)</small>`;
  8846. }
  8847. isBuildingAtMaxTier ? this.upgradeElem.classList.remove(`is-disabled`) : this.upgradeElem.classList.add('is-disabled');
  8848. this.shouldUpgradeAll ? (
  8849. this.upgradeElem.innerHTML = `Upgrade All <small>(` + costString + ')</small>',
  8850. this.sellElem.innerHTML = `Sell All <small>(` + refundString + ')</small>'
  8851. ) : (
  8852. this.upgradeElem.innerHTML = `Upgrade <small>(` + costString + `)</small>`,
  8853. this.sellElem.innerHTML = `Sell <small>(` + refundString + `)</small>`
  8854. );
  8855. `GoldStash` == this.buildingId ? (
  8856. this.sellElem.innerHTML = `Sell All Buildings`,
  8857. this.sellElem.classList.remove(`is-disabled`),
  8858. this.isSellingAll && this.sellElem.classList.add(`is-disabled`)
  8859. ) : this.ui.getPlayerPartyCanSell() ? (
  8860. this.sellElem.classList.remove(`is-disabled`)
  8861. ) : (
  8862. this.sellElem.classList.add(`is-disabled`),
  8863. this.sellElem.innerHTML = `Need Permission to Sell`
  8864. );
  8865. this.componentElem.style.left = buildingUiPosition.x - this.componentElem.offsetWidth / 0x2 + 'px';
  8866. this.componentElem.style.top = buildingUiPosition.y - buildingScale - this.componentElem.offsetHeight - 0x14 + 'px';
  8867. this.rangeIndicator && this.rangeIndicator.setPosition(buildingEntity.getPositionX(), buildingEntity.getPositionY());
  8868. }
  8869. }
  8870.  
  8871. game.ui.onBuildingSchemaUpdate = function (rawSchema) {
  8872. const schemas = JSON.parse(rawSchema.json);
  8873. for (const buildingId in schemas) {
  8874. let buildingSchema = schemas[buildingId];
  8875. for (var schema in this.buildingSchema) {
  8876. if (schema == buildingSchema.Name) {
  8877. buildingSchema.MsBetweenFires && (this.buildingSchema[schema].msBetweenFiresTiers = buildingSchema.MsBetweenFires);
  8878. buildingSchema.ProjectileAoe && (this.buildingSchema[schema].aoeTiers = buildingSchema.ProjectileAoe);
  8879. buildingSchema.ProjectileAoeRadius && (this.buildingSchema[schema].aoeRadiusTiers = buildingSchema.ProjectileAoeRadius);
  8880. buildingSchema.ProjectileLifetime && (this.buildingSchema[schema].lifetimeTiers = buildingSchema.ProjectileLifetime);
  8881. break;
  8882. }
  8883. }
  8884. }
  8885. this.emit(`buildingSchemaUpdate`, this.buildingSchema);
  8886. }
  8887. game.ui.onItemSchemaUpdate = function (rawSchema) {
  8888. var schemas = JSON.parse(rawSchema.json);
  8889. for (var item in schemas) {
  8890. var itemSchema = schemas[item];
  8891. for (var schema in this.itemSchema) {
  8892. schema == "Bow" && (this.itemSchema[schema].rangeTiers = Array(7).fill(1000));
  8893. if (schema == itemSchema.Name) {
  8894. itemSchema.MaxYawDeviation && (this.itemSchema[schema].maxYawDeviationTiers = itemSchema.MaxYawDeviation);
  8895. itemSchema.MsBetweenFires && (this.itemSchema[schema].msBetweenFiresTiers = itemSchema.MsBetweenFires);
  8896. itemSchema.ProjectileAoe && (this.itemSchema[schema].aoeTiers = itemSchema.ProjectileAoe);
  8897. itemSchema.ProjectileAoeRadius && (this.itemSchema[schema].aoeRadiusTiers = itemSchema.ProjectileAoeRadius);
  8898. itemSchema.ProjectileLifetime && (this.itemSchema[schema].lifetimeTiers = itemSchema.ProjectileLifetime);
  8899. break;
  8900. }
  8901. }
  8902. }
  8903. this.emit(`itemSchemaUpdate`, this.itemSchema);
  8904. }
  8905.  
  8906. game.network.addRpcHandler("BuildingShopPrices", game.ui.onBuildingSchemaUpdate.bind(game.ui));
  8907. game.network.addRpcHandler("ItemShopPrices", game.ui.onItemSchemaUpdate.bind(game.ui));
  8908.  
  8909. /* @CustomRenderer */
  8910. game.renderer.nodeType = class i {
  8911. constructor(e = null) {
  8912. this.attachments = [];
  8913. this.parent = null;
  8914. this.isVisible = true;
  8915. this.setNode(e || new window.PIXI.Container);
  8916. }
  8917. getNode() {
  8918. return this.node;
  8919. }
  8920. setNode(t) {
  8921. this.node = t;
  8922. }
  8923. getParent() {
  8924. return this.parent;
  8925. }
  8926. setParent(t) {
  8927. this.parent = t;
  8928. }
  8929. getAttachments() {
  8930. return this.attachments;
  8931. }
  8932. addAttachment(t, e = 0) {
  8933. t.getNode().zHack = e;
  8934. t.setParent(this);
  8935. this.node.addChild(t.getNode());
  8936. this.attachments.push(t);
  8937. this.node.children.sort(function (t, e) {
  8938. return t.zHack == e.zHack ? 0 : t.zHack < e.zHack ? -1 : 1;
  8939. });
  8940. }
  8941. removeAttachment(t) {
  8942. if (t) {
  8943. this.node.removeChild(t.getNode());
  8944. t.setParent(null);
  8945.  
  8946. var e = this.attachments.indexOf(t);
  8947. e > -1 && this.attachments.splice(e, 1);
  8948. }
  8949. }
  8950. getRotation() {
  8951. return 180 * this.node.rotation / Math.PI;
  8952. }
  8953. setRotation(t) {
  8954. this.node.rotation = t * Math.PI / 180;
  8955. }
  8956. getAlpha() {
  8957. return this.node.alpha;
  8958. }
  8959. setAlpha(t) {
  8960. this.node.alpha = t;
  8961. }
  8962. getScale() {
  8963. return this.node.scale;
  8964. }
  8965. setScale(t) {
  8966. this.node.scale.x = t;
  8967. this.node.scale.y = t;
  8968. }
  8969. getScaleX() {
  8970. return this.node.scale.x;
  8971. }
  8972. setScaleX(t) {
  8973. this.node.scale.x = t;
  8974. }
  8975. getScaleY() {
  8976. return this.node.scale.y;
  8977. }
  8978. setScaleY(t) {
  8979. this.node.scale.y = t;
  8980. }
  8981. getFilters() {
  8982. return this.node.filters;
  8983. }
  8984. setFilters(t) {
  8985. this.node.filters = t;
  8986. }
  8987. getPosition() {
  8988. return this.node.position;
  8989. }
  8990. setPosition(t, e) {
  8991. this.node.position.x = t;
  8992. this.node.position.y = e;
  8993. }
  8994. getPositionX() {
  8995. return this.getPosition().x;
  8996. }
  8997. setPositionX(t) {
  8998. this.node.position.x = t;
  8999. }
  9000. getPositionY() {
  9001. return this.getPosition().y;
  9002. }
  9003. setPositionY(t) {
  9004. this.node.position.y = t;
  9005. }
  9006. getPivotPoint() {
  9007. return this.node.pivot;
  9008. }
  9009. setPivotPoint(t, e) {
  9010. this.node.pivot.x = t;
  9011. this.node.pivot.y = e;
  9012. }
  9013. getVisible() {
  9014. return this.isVisible;
  9015. }
  9016. setVisible(t) {
  9017. this.isVisible = t;
  9018. this.node.visible = t;
  9019. }
  9020. update(t, e) {
  9021. for (let r = 0; r < this.attachments.length; r++) this.attachments[r].update(t, e);
  9022. }
  9023. };
  9024. game.renderer.spriteType = class d extends game.renderer.nodeType {
  9025. constructor(texture, tiled) {
  9026. super();
  9027. this.sprite = null;
  9028. if (typeof texture === 'string') {
  9029. texture = window.PIXI.Texture.fromImage(texture);
  9030. }
  9031. if (tiled) {
  9032. this.sprite = new window.PIXI.extras.TilingSprite(texture);
  9033. this.sprite.texture.baseTexture.scaleMode = window.PIXI.SCALE_MODES.NEAREST;
  9034. } else {
  9035. this.sprite = new window.PIXI.Sprite(texture);
  9036. }
  9037. this.sprite.anchor.x = 0.5;
  9038. this.sprite.anchor.y = 0.5;
  9039. this.setNode(this.sprite);
  9040. }
  9041. getAnchor() {
  9042. return this.sprite.anchor;
  9043. };
  9044. setAnchor(x, y) {
  9045. this.sprite.anchor.x = x;
  9046. this.sprite.anchor.y = y;
  9047. };
  9048. getTint() {
  9049. return this.node.tint;
  9050. };
  9051. setTint(tint) {
  9052. this.node.tint = tint;
  9053. };
  9054. getBlendMode() {
  9055. return this.node.tint;
  9056. };
  9057. setBlendMode(blendMode) {
  9058. this.node.blendMode = blendMode;
  9059. };
  9060. getMask() {
  9061. return this.node.mask;
  9062. };
  9063. setMask(entity) {
  9064. this.node.mask = entity.getNode();
  9065. };
  9066. setDimensions(x, y, width, height) {
  9067. this.sprite.x = x;
  9068. this.sprite.y = y;
  9069. this.sprite.width = width;
  9070. this.sprite.height = height;
  9071. };
  9072. };
  9073. game.renderer.graphicsType = class u extends game.renderer.nodeType {
  9074. constructor() {
  9075. super();
  9076. this.draw = new window.PIXI.Graphics();
  9077. this.draw.clear();
  9078. this.setNode(this.draw);
  9079. }
  9080. drawLine(thickness, xStart, yStart, xEnd, yEnd, color = 0xffffff, alpha = 1) {
  9081. this.draw.alpha = alpha;
  9082. this.draw.lineStyle(thickness, color)
  9083. .moveTo(xStart, yStart)
  9084. .lineTo(xEnd, yEnd);
  9085. }
  9086. drawTriangle(_a, _b, _c, _d, _e, _f) {
  9087. void 0x0 === _d && (_d = null);
  9088. void 0x0 === _e && (_e = null);
  9089. void 0x0 === _f && (_f = null);
  9090. _f && _f > 0x0 && this.draw.lineStyle(_f, _e.r << 0x10 | _e.g << 0x8 | _e.b, _e.a);
  9091. _d && this.draw.beginFill(_d.r << 0x10 | _d.g << 0x8 | _d.b, _d.a);
  9092. this.draw.drawPolygon([_a.x, _a.y, _b.x, _b.y, _c.x, _c.y]);
  9093. _d && this.draw.endFill();
  9094. }
  9095. drawArc(_a, _b, _c, _d, _e, _f, _g, _h, _i) {
  9096. void 0x0 === _g && (_g = null),
  9097. void 0x0 === _h && (_h = null),
  9098. void 0x0 === _i && (_i = null),
  9099. _i && _i > 0x0 && this.draw.lineStyle(_i, _h.r << 0x10 | _h.g << 0x8 | _h.b, _h.a),
  9100. _d = _d * Math.PI / 0xb4,
  9101. _e = _e * Math.PI / 0xb4,
  9102. _g && this.draw.beginFill(_g.r << 0x10 | _g.g << 0x8 | _g.b, _g.a),
  9103. this.draw.arc(_a, _b, _c, _d, _e, _f),
  9104. _g && this.draw.endFill();
  9105. };
  9106. drawCircle(_a, _b, _c, _d, _e, _f) {
  9107. void 0x0 === _d && (_d = null),
  9108. void 0x0 === _e && (_e = null),
  9109. void 0x0 === _f && (_f = null),
  9110. _f && _f > 0x0 && this.draw.lineStyle(_f, _e.r << 0x10 | _e.g << 0x8 | _e.b, _e.a),
  9111. _d && this.draw.beginFill(_d.r << 0x10 | _d.g << 0x8 | _d.b, _d.a),
  9112. this.draw.drawCircle(_a, _b, _c),
  9113. _d && this.draw.endFill();
  9114. };
  9115. drawRect(_a, _b, _c, _d, _e, _f, _g) {
  9116. void 0x0 === _e && (_e = null),
  9117. void 0x0 === _f && (_f = null),
  9118. void 0x0 === _g && (_g = null),
  9119. _g && _g > 0x0 && this.draw.lineStyle(_g, _f.r << 0x10 | _f.g << 0x8 | _f.b, _f.a),
  9120. _e && this.draw.beginFill(_e.r << 0x10 | _e.g << 0x8 | _e.b, _e.a),
  9121. this.draw.drawRect(_a, _b, _c - _a, _d - _b),
  9122. _e && this.draw.endFill();
  9123. };
  9124. drawRoundedRect(_a, _b, _c, _d, _e, _f, _g, _h) {
  9125. void 0x0 === _f && (_f = null),
  9126. void 0x0 === _g && (_g = null),
  9127. void 0x0 === _h && (_h = null),
  9128. _h && _h > 0x0 && this.draw.lineStyle(_h, _g.r << 0x10 | _g.g << 0x8 | _g.b, _g.a),
  9129. _f && this.draw.beginFill(_f.r << 0x10 | _f.g << 0x8 | _f.b, _f.a),
  9130. this.draw.drawRoundedRect(_a, _b, _c - _a, _d - _b, _e),
  9131. _f && this.draw.endFill();
  9132. };
  9133. drawEllipse(_a, _b, _c, _d, _e, _f, _g) {
  9134. void 0x0 === _e && (_e = null),
  9135. void 0x0 === _f && (_f = null),
  9136. void 0x0 === _g && (_g = null),
  9137. _g && _g > 0x0 && this.draw.lineStyle(_g, _f.r << 0x10 | _f.g << 0x8 | _f.b, _f.a),
  9138. _e && this.draw.beginFill(_e.r << 0x10 | _e.g << 0x8 | _e.b, _e.a),
  9139. this.draw.drawEllipse(_a, _b, _c, _d),
  9140. _e && this.draw.endFill();
  9141. };
  9142. getTexture() {
  9143. const renderer = Game.currentGame.renderer.getInternalRenderer();
  9144. return renderer.generateTexture(this.draw);
  9145. };
  9146. clear() {
  9147. this.draw.clear();
  9148. };
  9149. };
  9150. if (window.location.hostname !== "localhost") {
  9151. game.renderer.models = {GamePlayer:{model:"PlayerModel"},Stone:{model:"RecoilModel",gridSize:{width:3,height:3},args:{name:"/asset/image/map/map-stone.svg"}},Tree:{model:"RecoilModel",gridSize:{width:4,height:4},args:{name:"/asset/image/map/map-tree.svg"}},Wall:{model:"WallModel"},Door:{model:"DoorModel"},SlowTrap:{model:"SlowTrapModel"},ArrowTower:{model:"ArrowTowerModel",gridSize:{width:2,height:2}},CannonTower:{model:"CannonTowerModel",gridSize:{width:2,height:2}},MeleeTower:{model:"MeleeTowerModel",gridSize:{width:2,height:2}},BombTower:{model:"BombTowerModel",gridSize:{width:2,height:2}},MagicTower:{model:"MageTowerModel",gridSize:{width:2,height:2}},GoldMine:{model:"GoldMineModel",gridSize:{width:2,height:2}},Harvester:{model:"HarvesterModel",gridSize:{width:2,height:2}},GoldStash:{model:"GoldStashModel",gridSize:{width:2,height:2}},ArrowProjectile:{model:"ProjectileArrowModel"},CannonProjectile:{model:"ProjectileCannonModel"},BowProjectile:{model:"ProjectileArrowModel"},BombProjectile:{model:"ProjectileBombModel"},FireballProjectile:{model:"ProjectileMageModel"},HealTowersSpell:{model:"HealTowersSpellModel"},PetCARL:{model:"PetModel"},PetMiner:{model:"PetModel"},ZombieGreenTier1:{model:"ZombieModel"},ZombieGreenTier2:{model:"ZombieModel"},ZombieGreenTier3:{model:"ZombieModel"},ZombieGreenTier4:{model:"ZombieModel"},ZombieGreenTier5:{model:"ZombieModel"},ZombieGreenTier6:{model:"ZombieModel"},ZombieGreenTier7:{model:"ZombieModel"},ZombieGreenTier8:{model:"ZombieModel"},ZombieGreenTier9:{model:"ZombieModel"},ZombieGreenTier10:{model:"ZombieModel"},ZombieRangedGreenTier1:{model:"ZombieRangedModel"},ZombieBlueTier1:{model:"ZombieModel"},ZombieBlueTier2:{model:"ZombieModel"},ZombieBlueTier3:{model:"ZombieModel"},ZombieBlueTier4:{model:"ZombieModel"},ZombieBlueTier5:{model:"ZombieModel"},ZombieBlueTier6:{model:"ZombieModel"},ZombieBlueTier7:{model:"ZombieModel"},ZombieBlueTier8:{model:"ZombieModel"},ZombieBlueTier9:{model:"ZombieModel"},ZombieBlueTier10:{model:"ZombieModel"},ZombieRedTier1:{model:"ZombieModel"},ZombieRedTier2:{model:"ZombieModel"},ZombieRedTier3:{model:"ZombieModel"},ZombieRedTier4:{model:"ZombieModel"},ZombieRedTier5:{model:"ZombieModel"},ZombieRedTier6:{model:"ZombieModel"},ZombieRedTier7:{model:"ZombieModel"},ZombieRedTier8:{model:"ZombieModel"},ZombieRedTier9:{model:"ZombieModel"},ZombieRedTier10:{model:"ZombieModel"},ZombieYellowTier1:{model:"ZombieModel"},ZombieYellowTier2:{model:"ZombieModel"},ZombieYellowTier3:{model:"ZombieModel"},ZombieYellowTier4:{model:"ZombieModel"},ZombieYellowTier5:{model:"ZombieModel"},ZombieYellowTier6:{model:"ZombieModel"},ZombieYellowTier7:{model:"ZombieModel"},ZombieYellowTier8:{model:"ZombieModel"},ZombieYellowTier9:{model:"ZombieModel"},ZombieYellowTier10:{model:"ZombieModel"},ZombiePurpleTier1:{model:"ZombieModel"},ZombiePurpleTier2:{model:"ZombieModel"},ZombiePurpleTier3:{model:"ZombieModel"},ZombiePurpleTier4:{model:"ZombieModel"},ZombiePurpleTier5:{model:"ZombieModel"},ZombiePurpleTier6:{model:"ZombieModel"},ZombiePurpleTier7:{model:"ZombieModel"},ZombiePurpleTier8:{model:"ZombieModel"},ZombiePurpleTier9:{model:"ZombieModel"},ZombiePurpleTier10:{model:"ZombieModel"},ZombieOrangeTier1:{model:"ZombieModel"},ZombieOrangeTier2:{model:"ZombieModel"},ZombieOrangeTier3:{model:"ZombieModel"},ZombieOrangeTier4:{model:"ZombieModel"},ZombieOrangeTier5:{model:"ZombieModel"},ZombieOrangeTier6:{model:"ZombieModel"},ZombieOrangeTier7:{model:"ZombieModel"},ZombieOrangeTier8:{model:"ZombieModel"},ZombieOrangeTier9:{model:"ZombieModel"},ZombieOrangeTier10:{model:"ZombieModel"},ZombieBossTier1:{model:"ZombieBossModel"},ZombieBossTier2:{model:"ZombieBossModel"},ZombieBossTier3:{model:"ZombieBossModel"},ZombieBossTier4:{model:"ZombieBossModel"},ZombieBossTier5:{model:"ZombieBossModel"},ZombieBossTier6:{model:"ZombieBossModel"},ZombieBossTier7:{model:"ZombieBossModel"},ZombieBossTier8:{model:"ZombieBossModel"},ZombieBossTier9:{model:"ZombieBossModel"},ZombieBossTier10:{model:"ZombieBossModel"},ZombieBossTier11:{model:"ZombieBossModel"},ZombieBossTier12:{model:"ZombieBossModel"},ZombieBossTier13:{model:"ZombieBossModel"},ZombieBossTier14:{model:"ZombieBossModel"},ZombieBossTier15:{model:"ZombieBossModel"},ZombieBossTier16:{model:"ZombieBossModel"},ZombieBossTier17:{model:"ZombieBossModel"},ZombieBossTier18:{model:"ZombieBossModel"},ZombieBossTier19:{model:"ZombieBossModel"},ZombieBossTier20:{model:"ZombieBossModel"},ZombieBossTier21:{model:"ZombieBossModel"},ZombieBossTier22:{model:"ZombieBossModel"},ZombieBossTier23:{model:"ZombieBossModel"},ZombieBossTier24:{model:"ZombieBossModel"},ZombieBossTier25:{model:"ZombieBossModel"},ZombieBossTier26:{model:"ZombieBossModel"},ZombieBossTier27:{model:"ZombieBossModel"},ZombieBossTier28:{model:"ZombieBossModel"},ZombieBossTier29:{model:"ZombieBossModel"},ZombieBossTier30:{model:"ZombieBossModel"},ZombieBossTier31:{model:"ZombieBossModel"},ZombieBossTier32:{model:"ZombieBossModel"},ZombieBossTier33:{model:"ZombieBossModel"},ZombieBossTier34:{model:"ZombieBossModel"},ZombieBossTier35:{model:"ZombieBossModel"},ZombieBossTier36:{model:"ZombieBossModel"},ZombieBossTier37:{model:"ZombieBossModel"},ZombieBossTier38:{model:"ZombieBossModel"},ZombieBossTier39:{model:"ZombieBossModel"},ZombieBossTier40:{model:"ZombieBossModel"},NeutralCamp:{model:"NeutralCampModel"},NeutralTier1:{model:"NeutralModel"},PathNode:{model:"PathNodeModel"}};
  9152. game.lerp = function(t, e, r) {
  9153. return (r > 1.2 && (r = 1), t + (e - t) * r);
  9154. }
  9155. game.mod = function (_a, _b) {
  9156. return (_a % _b + _b) % _b;
  9157. }
  9158. game.interpolateYaw = function (__a, __b) {
  9159. var _game = Game.currentGame.world.getReplicator().getMsInThisTick() / Game.currentGame.world.getMsPerTick(),
  9160. delta = __a - __b;
  9161. delta = game.mod(delta + 0xb4, 0x168) - 0xb4;
  9162. delta = game.lerp(0x0, delta, _game);
  9163. var addDelta = __b + delta;
  9164. addDelta < 0x0 && (addDelta += 0x168);
  9165. addDelta >= 0x168 && (addDelta -= 0x168);
  9166. return addDelta;
  9167. }
  9168. game.renderer.entityType = class o extends game.renderer.nodeType {
  9169. constructor(t) {
  9170. super();
  9171. this.uid = t.uid;
  9172. this.setVisible(true);
  9173. this.setTargetTick(t);
  9174. }
  9175. calculateVector(t, e, r) {
  9176. return (r > 1.2 && (r = 1), t + (e - t) * r);
  9177. }
  9178. reset() {
  9179. this.uid = 0;
  9180. this.currentModel = null;
  9181. this.entityClass = null;
  9182. this.fromTick = null;
  9183. this.targetTick = null;
  9184. this.setVisible(true);
  9185. }
  9186. isLocal() {
  9187. var t = Game.currentGame.world.getLocalPlayer();
  9188. return !(!t || !t.getEntity()) && this.uid == t.getEntity().uid;
  9189. }
  9190. getTargetTick() {
  9191. return this.targetTick;
  9192. }
  9193. getFromTick() {
  9194. return this.fromTick;
  9195. }
  9196. setTargetTick(t) {
  9197. this.targetTick || (this.entityClass = t.entityClass, this.targetTick = t);
  9198. this.addMissingTickFields(t, this.targetTick);
  9199. this.fromTick = this.targetTick;
  9200. this.targetTick = t;
  9201. void 0 !== t.scale && this.setScale(t.scale);
  9202. this.fromTick.model !== this.targetTick.model && this.refreshModel(this.targetTick.model);
  9203. this.entityClass = this.targetTick.entityClass;
  9204. }
  9205. overrideFromTick(t) {
  9206. this.fromTick = t;
  9207. }
  9208. overrideTargetTick(t) {
  9209. this.targetTick = t;
  9210. }
  9211. tick(t, e) {
  9212. if (this.fromTick) {
  9213. var r = t / e;
  9214. this.isVisible || this.setVisible(true);
  9215. this.setPositionX(this.calculateVector(this.fromTick.position.x, this.targetTick.position.x, r));
  9216. this.setPositionY(this.calculateVector(this.fromTick.position.y, this.targetTick.position.y, r));
  9217. this.setRotation(((t, e) => {
  9218. let r = t - e;
  9219. r = ((r + 180) % 360 + 360) % 360 - 180;
  9220. r = this.calculateVector(0, r, Game.currentGame.world.getReplicator().getMsInThisTick() / Game.currentGame.world.getMsPerTick());
  9221.  
  9222. let i = e + r;
  9223. i < 0 && (i += 360);
  9224. i >= 360 && (i -= 360);
  9225.  
  9226. return i;
  9227. })(this.targetTick.yaw, this.fromTick.yaw));
  9228. }
  9229. }
  9230. update(t, e) {
  9231. this.fromTick && (this.fromTick.interpolatedYaw = this.getRotation());
  9232. if (this.currentModel && game.script.optimize.updateAnimation) this.currentModel.update(t, this.fromTick);
  9233. this.node.visible = this.isVisible;
  9234. }
  9235. refreshModel(t) {
  9236. const e = game.renderer.models;
  9237. if (!(t in e)) throw new Error("Attempted to create unknown model: " + t);
  9238. var r = e[t].model;
  9239.  
  9240. Game.currentGame.getModelEntityPooling(r) && (this.currentModel = Game.currentGame.world.getModelFromPool(r));
  9241. if (!this.currentModel) {
  9242. var i = {};
  9243. "args" in e[t] && (i = e[t].args);
  9244. i.modelName = t;
  9245.  
  9246. this.currentModel = Game.currentGame.assetManager.loadModel(r, i);
  9247. this.currentModel.modelName = r;
  9248. }
  9249. if (this.currentModel.modelName == 'PlayerModel') {
  9250. this.currentModel.updateSwingingWeapon = function (useThisIfUrGay, radius) {
  9251. var currentModel = this;
  9252. void 0 === radius && (radius = 100);
  9253. return function (tick, currentTick) {
  9254. var interpolatedYaw = game.interpolateYaw(currentTick.getTargetTick().aimingYaw, currentTick.getFromTick().aimingYaw);
  9255. currentModel.weapon.setRotation(interpolatedYaw - tick.interpolatedYaw);
  9256. if (tick.firingTick && (tick.firingTick !== currentModel.lastFiringTick || !currentModel.lastFiringAnimationDone)) {
  9257. currentModel.lastFiringTick = tick.firingTick;
  9258. currentModel.lastFiringAnimationDone = false;
  9259. var msSinceTick = Game.currentGame.world.replicator.getMsSinceTick(tick.firingTick),
  9260. itemSchema = game.ui.itemSchema,
  9261. _a = Math.min(msSinceTick / itemSchema[currentModel.lastWeaponName].msBetweenFiresTiers[currentModel.lastWeaponTier - 1], 1),
  9262. _b = Math.sin(_a * Math.PI) * radius // itemSchema[currentModel.lastWeaponName].maxYawDeviationTiers[currentModel.lastWeaponTier - 1];
  9263. 1 === _a && (currentModel.lastFiringAnimationDone = true);
  9264. currentModel.weapon.setRotation(interpolatedYaw - tick.interpolatedYaw - _b);
  9265. currentModel.hat && currentModel.hat.setRotation(interpolatedYaw - tick.interpolatedYaw - 0.6 * _b);
  9266. }
  9267. }
  9268. }
  9269. /*
  9270. this.currentModel.updateRotationWithLocalData = function(entity, yaw) {
  9271. if (entity.isLocal() || yaw) {
  9272. entity.getTargetTick().aimingYaw = entity.getFromTick().aimingYaw = yaw || game.inputPacketCreator.getLastAnyYaw();
  9273. }
  9274. }
  9275. */
  9276. };
  9277. this.currentModel.setParent(this);
  9278. this.setNode(this.currentModel.getNode());
  9279. }
  9280. addMissingTickFields(t, e) {
  9281. for (var r in e) {
  9282. var i = e[r];
  9283. r in t || (t[r] = i);
  9284. }
  9285. }
  9286. };
  9287. game.renderer.textSpriteType = class s extends window.PIXI.Text {
  9288. constructor() {
  9289. super();
  9290. }
  9291. renderWebGL(t) {
  9292. this.updateText(true);
  9293. this.calculateVertices();
  9294.  
  9295. t.setObjectRenderer(t.plugins[this.pluginName]);
  9296. t.plugins[this.pluginName].render(this);
  9297. }
  9298. _renderCanvas(t) {
  9299. this.updateText(true);
  9300. t.plugins[this.pluginName].render(this);
  9301. }
  9302. };
  9303. game.renderer.textType = class a extends game.renderer.nodeType {
  9304. constructor(t, e, r) {
  9305. super();
  9306. this.text = new game.renderer.textSpriteType(t, {fontFamily: e, fontSize: r, lineJoin: "round", padding: 10});
  9307. this.text.resolution = 2 * window.devicePixelRatio;
  9308. this.setNode(this.text);
  9309. }
  9310. setColor(t, e, r) {
  9311. this.text.style.fill = t << 16 | e << 8 | r;
  9312. }
  9313. setStroke(t, e, r, i) {
  9314. this.text.style.stroke = t << 16 | e << 8 | r;
  9315. this.text.style.strokeThickness = i;
  9316. }
  9317. setFontWeight(t) {
  9318. this.text.style.fontWeight = t;
  9319. }
  9320. setLetterSpacing(t) {
  9321. this.text.style.letterSpacing = t;
  9322. }
  9323. setAnchor(t, e) {
  9324. this.text.anchor.set(t, e);
  9325. }
  9326. setString(t) {
  9327. this.text.text = t;
  9328. }
  9329. }
  9330.  
  9331. Game.currentGame.world.createEntity = function(t) {
  9332. if (this.entities[t.uid]) return;
  9333.  
  9334. let e;
  9335. if (Game.currentGame.getNetworkEntityPooling() && this._networkEntityPool.length > 0) {
  9336. e = this._networkEntityPool.shift();
  9337. e.setTargetTick(t);
  9338. e.uid = t.uid;
  9339. } else {
  9340. e = new game.renderer.entityType(t);
  9341. }
  9342.  
  9343. let shouldLoadModel = true;
  9344. if (t.model.indexOf("Zombie") > -1 && !game.script.optimize.zombieSprite) shouldLoadModel = false;
  9345. if (t.model in game.ui.buildingSchema && !game.script.optimize.towerSprite) shouldLoadModel = false;
  9346. if (t.entityClass == "Projectile" && !game.script.optimize.projectileSprite) shouldLoadModel = false;
  9347. shouldLoadModel && e.refreshModel(t.model);
  9348.  
  9349. t.uid === this.myUid && (this.localPlayer.setEntity(e), this.renderer.follow(e));
  9350. this.entities[t.uid] = e;
  9351. this.renderer.add(e, t.entityClass);
  9352. this.entityGrid.updateEntity(this.entities[t.uid]);
  9353. game.script.stashIndicators.onEntityCreated(t);
  9354. };
  9355. Game.currentGame.world.removeEntity = function(t) {
  9356. if (["Tree", "Stone", "NeutralCamp"].indexOf(this.entities[t].fromTick.model) > -1) return;
  9357. game.script.showAoe.onEntityRemoved(t);
  9358. this.renderer.remove(this.entities[t]);
  9359. this.entityGrid.removeEntity(parseInt(t));
  9360. if (this.entities[t].currentModel) {
  9361. const model = this.entities[t].currentModel;
  9362. if (Game.currentGame.getModelEntityPooling(model.modelName)) {
  9363. model.reset();
  9364. this.modelEntityPool[model.modelName].push(model);
  9365. };
  9366. };
  9367. if (Game.currentGame.getNetworkEntityPooling()) {
  9368. this.entities[t].reset();
  9369. this._networkEntityPool.push(this.entities[t]);
  9370. }
  9371. delete this.entities[t];
  9372. };
  9373. Game.currentGame.renderer.add = function(t, e) {
  9374. if (t instanceof game.renderer.entityType) {
  9375. switch (e) {
  9376. case "Prop":
  9377. this.scenery.addAttachment(t);
  9378. break;
  9379. case "Projectile":
  9380. this.projectiles.addAttachment(t);
  9381. break;
  9382. case "Player":
  9383. this.players.addAttachment(t);
  9384. break;
  9385. default:
  9386. this.npcs.addAttachment(t);
  9387. }
  9388. // } else t instanceof game.renderer.textType ? this.ui.addAttachment(t) : this.ground.addAttachment(t);
  9389. } else if (!game.script.optimize.background) {
  9390. if (t instanceof game.renderer.nodeType) Game.currentGame.renderer.ground.addAttachment(t);
  9391. else {
  9392. if (!(t instanceof game.renderer.textType)) return; // throw new Error("Unhandled object: " + JSON.stringify(t));
  9393. Game.currentGame.renderer.ui.addAttachment(t);
  9394. }
  9395. } else t instanceof game.renderer.textType ? this.ui.addAttachment(t) : this.ground.addAttachment(t);
  9396. };
  9397. Game.currentGame.renderer.remove = function(t) {
  9398. if (t instanceof game.renderer.entityType) {
  9399. switch (t.entityClass) {
  9400. case "Prop":
  9401. this.scenery.removeAttachment(t);
  9402. break;
  9403. case "Projectile":
  9404. this.projectiles.removeAttachment(t);
  9405. break;
  9406. case "Player":
  9407. this.players.removeAttachment(t);
  9408. break;
  9409. default:
  9410. this.npcs.removeAttachment(t);
  9411. }
  9412. // } else t instanceof game.renderer.textType ? this.ui.removeAttachment(t) : this.ground.removeAttachment(t);
  9413. } else if (!game.script.optimize.background) {
  9414. t instanceof game.renderer.nodeType ? Game.currentGame.renderer.ground.removeAttachment(t) : t instanceof game.renderer.textType && Game.currentGame.renderer.ui.removeAttachment(t);
  9415. } else t instanceof game.renderer.textType ? this.ui.removeAttachment(t) : this.ground.removeAttachment(t);
  9416. };
  9417. Game.currentGame.renderer.tickCallbacks[7] = () => {
  9418. const t = Game.currentGame.world.replicator.getMsInThisTick();
  9419. for (const e in Game.currentGame.world.entities) {
  9420. Game.currentGame.world.entities[e].tick(t, Game.currentGame.world.replicator.msPerTick);
  9421. };
  9422. };
  9423. } else {
  9424. Game.currentGame.world._createEntity = Game.currentGame.world.createEntity;
  9425. Game.currentGame.world.createEntity = function(t) {
  9426. if (this.entities[t.uid]) return;
  9427. this._createEntity(t);
  9428. game.script.stashIndicators.onEntityCreated(t);
  9429. };
  9430. Game.currentGame.world._removeEntity = Game.currentGame.world.removeEntity;
  9431. Game.currentGame.world.removeEntity = function(t) {
  9432. if (["Tree", "Stone", "NeutralCamp"].indexOf(this.entities[t].fromTick.model) > -1) return;
  9433. game.script.showAoe.onEntityRemoved(t);
  9434. this._removeEntity(t);
  9435. };
  9436. };
  9437.  
  9438. game.assetManager.models ||= {};
  9439. game.assetManager.models.rangeIndicatorModel = function(e, innerRGB = {r: 0xc8, g: 0xa0, b: 0x0}, borderRGB = {r: 0xff, g: 0xc8, b: 0x0}, lineWidth = 8) {
  9440. const container = new game.renderer.nodeType();
  9441. container.isCircular = e.isCircular || false;
  9442. container.goldRegion = new game.renderer.graphicsType();
  9443. container.goldRegion.setAlpha(0.1);
  9444.  
  9445. if (container.isCircular) {
  9446. container.goldRegion.drawCircle(0, 0, e.radius, innerRGB, borderRGB, lineWidth);
  9447. } else {
  9448. container.goldRegion.drawRect(-e.width / 2, -e.height / 2, e.width / 2, e.height / 2, innerRGB, borderRGB, lineWidth);
  9449. };
  9450.  
  9451. container.addAttachment(container.goldRegion);
  9452. return container;
  9453. };
  9454.  
  9455. /* @Misc. */
  9456. document.getElementsByClassName('hud-party-tag')[0].setAttribute('maxlength', 49);
  9457. document.getElementsByClassName('hud-intro-name')[0].setAttribute('maxlength', 29);
  9458.  
  9459.  
  9460. /* @Bindings */
  9461. (function MapFunctionsToElem() {
  9462. for (let page in menu) {
  9463. const [optionsElem, moreElem] = document.querySelectorAll("#" + page + " > div");
  9464. for (let option in menu[page]) {
  9465. const {name, description, more, isToggle, callback, customButtonText, onCallback, offCallback} = menu[page][option];
  9466. const hasMore = !!more;
  9467. const itemElem = document.createElement("div");
  9468. itemElem.id = option + "-div";
  9469. itemElem.innerHTML = `
  9470. <h2>${name}</h2>
  9471. <span>${description}</span>
  9472. ${game.options.options[option] === undefined ? "" : `
  9473. <button id="toggle-${option}" ${game.options.options[option] ? `class="underline-red"` : ""}>
  9474. ${game.options.options[option] ? "Disable" : "Enable"}
  9475. </button>
  9476. `}
  9477. ${isToggle === false ? `<button id="${name}">${customButtonText}</button>` : ""}
  9478. ${hasMore ? `<a id="more-${option}"></a>` : ""}
  9479. `;
  9480. optionsElem.appendChild(itemElem);
  9481.  
  9482. if (hasMore) {
  9483. const {html, functions, bind} = more;
  9484. const moreContainer = document.createElement("div");
  9485. moreContainer.innerHTML = html;
  9486. moreContainer.style.display = "none";
  9487. moreElem.appendChild(moreContainer);
  9488. functions?.();
  9489.  
  9490. const toggleElem = getId("more-" + option);
  9491. toggleElem.onclick = () => {
  9492. refreshMore(page);
  9493. bind?.();
  9494. moreContainer.style.display = "block";
  9495. }
  9496. }
  9497. if (!(game.options.options[option] === undefined)) {
  9498. addFunctionToElem({id: 'toggle-' + option, option, buttonText: '', colors: "underline-red?", isToggle, callback, onCallback, offCallback});
  9499. } else if (isToggle === false) {
  9500. addFunctionToElem({id: name, option, buttonText: '', colors: "underline-red?", isToggle, callback, onCallback, offCallback});
  9501. };
  9502. };
  9503. };
  9504. })();
  9505.  
  9506. (function MapHandlers() {
  9507. for (const functionName in game.script) game.script[functionName]?.init?.();
  9508. for (const subFunctionName in game.script.sockets) {
  9509. if (typeof game.script.sockets[subFunctionName] == "object") {} // && (game.script.sockets[subFunctionName].parent = game.script.sockets);
  9510. };
  9511. const keybindListeners = {};
  9512. for (const functionName in game.options.options) {
  9513. if (!game.script[functionName] || game.script[functionName].handlers === undefined) continue;
  9514. const usesHandlers = game.script[functionName].handlers;
  9515. for (const {type, names} of usesHandlers) {
  9516. console.log(type, functionName, names);
  9517. switch(type) {
  9518. case "rpc":
  9519. for (const name of names) {
  9520. game.network.addRpcHandler(name, game.script[functionName][name].bind(game.script[functionName]));
  9521. };
  9522. break;
  9523. case "entityUpdate":
  9524. game.network.addEntityUpdateHandler(game.script[functionName][names].bind(game.script[functionName]));
  9525. break;
  9526. case "tickUpdate":
  9527. game.ui._events[names].push(game.script[functionName][names].bind(game.script[functionName][names]));
  9528. break;
  9529. case "keybind":
  9530. if (typeof names == "object") {
  9531. for (const name of names) {
  9532. keybindListeners[name] ||= [];
  9533. keybindListeners[name].push(functionName);
  9534. };
  9535. } else {
  9536. keybindListeners[names] ||= [];
  9537. keybindListeners[names].push(functionName);
  9538. };
  9539. break;
  9540. case "packetFunc":
  9541. game.network[names[0]] = function(data) {
  9542. game.script[functionName][names[1]](data);
  9543. this.sendPacket(names[2], data);
  9544. };
  9545. break;
  9546. };
  9547. };
  9548. };
  9549. for (const name in keybindListeners) {
  9550. document.addEventListener(name, function(e) {
  9551. if (document.activeElement.tagName.toLowerCase() !== "input" && document.activeElement.tagName.toLowerCase() !== "textarea") {
  9552. for (const functionName of keybindListeners[name]) game.script[functionName][name](e);
  9553. };
  9554. });
  9555. };
  9556. })();