moomooio-client
Version:
MooMooIO-Client is a client-side wrapper API designed for the game MooMoo.io. This package aims to provide a simple yet powerful API for creating clones, mods, or plugins for MooMoo.io.
1,800 lines (1,756 loc) • 106 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __accessCheck = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
var __privateGet = (obj, member, getter) => {
__accessCheck(obj, member, "read from private field");
return getter ? getter.call(obj) : member.get(obj);
};
var __privateAdd = (obj, member, value) => {
if (member.has(obj))
throw TypeError("Cannot add the same private member more than once");
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
var __privateSet = (obj, member, value, setter) => {
__accessCheck(obj, member, "write to private field");
setter ? setter.call(obj, value) : member.set(obj, value);
return value;
};
var __privateMethod = (obj, member, method) => {
__accessCheck(obj, member, "access private method");
return method;
};
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/utils/PropertyTracker.ts
var PropertyTracker = class {
constructor(content, register = void 0) {
this.content = content;
this.register = register;
}
set(content) {
this.register = this.content;
this.content = content;
}
isDiff() {
return this.register !== this.content;
}
get current() {
return this.content;
}
get previous() {
return this.register;
}
};
// src/instance/Player.ts
import UnifyEmitter from "unify-emitter";
var _teamID, _isBestKiller, _weaponVariant, _isLeader, _isMyPlayer, _playerName, _weaponType, _buildType, _maxHealth, _playerID, _tailType, _hatType, _health, _initID, _skinID, _scale, _layer, _angle, _x, _y, _isInitialized;
var Player = class extends UnifyEmitter {
constructor() {
super(...arguments);
__privateAdd(this, _teamID, null);
__privateAdd(this, _isBestKiller, false);
__privateAdd(this, _weaponVariant, 0);
__privateAdd(this, _isLeader, false);
__privateAdd(this, _isMyPlayer, false);
__privateAdd(this, _playerName, void 0);
__privateAdd(this, _weaponType, 0);
__privateAdd(this, _buildType, -1);
__privateAdd(this, _maxHealth, 100);
__privateAdd(this, _playerID, void 0);
__privateAdd(this, _tailType, new PropertyTracker(0));
__privateAdd(this, _hatType, new PropertyTracker(0));
__privateAdd(this, _health, new PropertyTracker(100));
__privateAdd(this, _initID, void 0);
__privateAdd(this, _skinID, 0);
__privateAdd(this, _scale, 35);
__privateAdd(this, _layer, 0);
__privateAdd(this, _angle, new PropertyTracker(0));
__privateAdd(this, _x, new PropertyTracker(0));
__privateAdd(this, _y, new PropertyTracker(0));
__privateAdd(this, _isInitialized, false);
}
initialize(initializePlayer) {
__privateSet(this, _isMyPlayer, initializePlayer.isMyPlayer);
__privateSet(this, _playerName, initializePlayer.playerName);
__privateSet(this, _maxHealth, initializePlayer.maxHealth);
__privateSet(this, _playerID, initializePlayer.playerID);
__privateSet(this, _initID, initializePlayer.initID);
__privateSet(this, _skinID, initializePlayer.skinID);
__privateSet(this, _scale, initializePlayer.scale);
__privateSet(this, _health, new PropertyTracker(initializePlayer.health));
__privateSet(this, _angle, new PropertyTracker(initializePlayer.angle));
__privateSet(this, _x, new PropertyTracker(initializePlayer.x));
__privateSet(this, _y, new PropertyTracker(initializePlayer.y));
__privateSet(this, _isInitialized, true);
}
update(playerData) {
var _a, _b;
__privateSet(this, _weaponVariant, playerData.weaponVariant);
__privateSet(this, _isBestKiller, playerData.isBestKiller);
__privateSet(this, _weaponType, playerData.weaponType);
__privateGet(this, _tailType).set(playerData.tailType);
__privateSet(this, _buildType, playerData.buildType);
__privateGet(this, _hatType).set(playerData.hatType);
__privateSet(this, _isLeader, playerData.isLeader);
__privateGet(this, _angle).set(playerData.angle);
__privateSet(this, _teamID, playerData.teamID);
__privateSet(this, _layer, playerData.layer);
__privateGet(this, _x).set(playerData.x);
__privateGet(this, _y).set(playerData.y);
if (__privateGet(this, _x).isDiff() || __privateGet(this, _y).isDiff()) {
const deltaX = __privateGet(this, _x).current - (__privateGet(this, _x).previous || 0);
const deltaY = __privateGet(this, _y).current - (__privateGet(this, _y).previous || 0);
this.emit("move", {
direction: Math.atan2(deltaY, deltaX),
x: this.x,
y: this.y,
player: this
});
}
if (__privateGet(this, _hatType).isDiff()) {
this.emit("hatChange", {
previous: (_a = __privateGet(this, _hatType).previous) != null ? _a : 0,
current: __privateGet(this, _hatType).current,
player: this
});
}
if (__privateGet(this, _tailType).isDiff()) {
this.emit("tailChange", {
previous: (_b = __privateGet(this, _tailType).previous) != null ? _b : 0,
current: __privateGet(this, _tailType).current,
player: this
});
}
if (__privateGet(this, _angle).isDiff()) {
this.emit("rotate", {
angle: this.angle,
player: this
});
}
this.emit("update", this);
}
clear() {
this.emit("destroyed", null);
__privateSet(this, _isInitialized, false);
this.removeListeners();
}
/* prettier-ignore */
get weaponVariant() {
return __privateGet(this, _weaponVariant);
}
/* prettier-ignore */
get isInitialized() {
return __privateGet(this, _isInitialized);
}
/* prettier-ignore */
get isBestKiller() {
return __privateGet(this, _isBestKiller);
}
/* prettier-ignore */
get tailType() {
return __privateGet(this, _tailType).current;
}
/* prettier-ignore */
get hatType() {
return __privateGet(this, _hatType).current;
}
/* prettier-ignore */
get weaponType() {
return __privateGet(this, _weaponType);
}
/* prettier-ignore */
get isMyPlayer() {
return __privateGet(this, _isMyPlayer);
}
/* prettier-ignore */
get playerName() {
return __privateGet(this, _playerName);
}
/* prettier-ignore */
get health() {
return __privateGet(this, _health).current;
}
/* prettier-ignore */
get buildType() {
return __privateGet(this, _buildType);
}
/* prettier-ignore */
get maxHealth() {
return __privateGet(this, _maxHealth);
}
/* prettier-ignore */
get angle() {
return __privateGet(this, _angle).current;
}
/* prettier-ignore */
get isLeader() {
return __privateGet(this, _isLeader);
}
/* prettier-ignore */
get playerID() {
return __privateGet(this, _playerID);
}
/* prettier-ignore */
get teamID() {
return __privateGet(this, _teamID);
}
/* prettier-ignore */
get initID() {
return __privateGet(this, _initID);
}
/* prettier-ignore */
get skinID() {
return __privateGet(this, _skinID);
}
/* prettier-ignore */
get layer() {
return __privateGet(this, _layer);
}
/* prettier-ignore */
get scale() {
return __privateGet(this, _scale);
}
/* prettier-ignore */
get x() {
return __privateGet(this, _x).current;
}
/* prettier-ignore */
get y() {
return __privateGet(this, _y).current;
}
setHealth(health) {
var _a;
__privateGet(this, _health).set(Math.min(this.maxHealth, Math.max(health, 0)));
const prev = (_a = __privateGet(this, _health).previous) != null ? _a : 100;
const curr = __privateGet(this, _health).current;
this.emit("healthChange", {
isHealing: prev - curr < 0,
amount: Math.abs(prev - curr),
player: this
});
}
getTeam(teams) {
return this.teamID && teams.get(this.teamID) || null;
}
};
_teamID = new WeakMap();
_isBestKiller = new WeakMap();
_weaponVariant = new WeakMap();
_isLeader = new WeakMap();
_isMyPlayer = new WeakMap();
_playerName = new WeakMap();
_weaponType = new WeakMap();
_buildType = new WeakMap();
_maxHealth = new WeakMap();
_playerID = new WeakMap();
_tailType = new WeakMap();
_hatType = new WeakMap();
_health = new WeakMap();
_initID = new WeakMap();
_skinID = new WeakMap();
_scale = new WeakMap();
_layer = new WeakMap();
_angle = new WeakMap();
_x = new WeakMap();
_y = new WeakMap();
_isInitialized = new WeakMap();
// src/AntiKick.ts
var AntiKick = class _AntiKick {
constructor() {
this.observePackets = [
{
PACKET_ID: "2",
current: 0,
max: 10,
is(data) {
return data[2] == 50;
}
},
{
PACKET_ID: "c",
current: 0,
max: 20,
is(data) {
return data[2] == 99;
}
},
{
PACKET_ID: "5",
current: 0,
max: 10,
is(data) {
return data[2] == 53;
}
},
{
PACKET_ID: "13c",
current: 0,
max: 10,
is(data) {
return data[2] == 49 && data[3] == 51 && data[4] == 99;
}
},
{
PACKET_ID: "8",
current: 0,
max: 1,
is(data) {
return data[2] == 56;
}
},
{
PACKET_ID: "10",
current: 0,
max: 7,
is(data) {
return data[2] == 49 && data[3] == 48;
}
},
{
PACKET_ID: "12",
current: 0,
max: 7,
is(data) {
return data[2] == 49 && data[3] == 50;
}
},
{
PACKET_ID: "9",
current: 0,
max: 1,
is(data) {
return data[2] == 57;
}
},
{
PACKET_ID: "pp",
current: 0,
max: 1,
is(data) {
return data[2] == 112 && data[3] == 112;
}
},
{
PACKET_ID: "14",
current: 0,
max: 1,
is(data) {
return data[2] == 49 && data[3] == 52;
}
},
{
PACKET_ID: "7",
current: 0,
max: 5,
is(data) {
return data[2] == 55;
}
},
{
PACKET_ID: "6",
current: 0,
max: 10,
is(data) {
return data[2] == 54;
}
},
{
PACKET_ID: "sp",
current: 0,
max: 1,
is(data) {
return data[2] == 115 && data[3] == 112;
}
}
];
this.interval = setInterval(this.restart.bind(this), 100);
}
destroy() {
clearInterval(this.interval);
}
restart() {
for (let i = this.observePackets.length - 1; i > -1; --i) {
const observePacket = this.observePackets[i];
observePacket && _AntiKick.resetObservePacket(observePacket);
}
}
canSend(content) {
for (let i = this.observePackets.length - 1; i > -1; --i) {
const observePacket = this.observePackets[i];
if (observePacket == null ? void 0 : observePacket.is(content)) {
return _AntiKick.runObservePacket(observePacket);
}
}
return true;
}
static runObservePacket(observePacket) {
return ++observePacket.current <= observePacket.max;
}
static resetObservePacket(observePacket) {
observePacket.current = 0;
}
};
// src/ServerPackets/index.ts
import { decode as msgpackDecode } from "msgpack-lite";
// src/ServerPackets/UpdateTeamMembersList.ts
import { z } from "zod";
var schema = z.tuple([z.array(z.union([z.number(), z.string()]))]);
var chunkSchema = z.tuple([z.number(), z.string()]);
var _UpdateTeamMembersList = class _UpdateTeamMembersList {
constructor(members) {
this.members = members;
this.PACKET_NAME = "UpdateTeamMembersList";
}
static parse(data) {
const result = [];
const info = schema.parse(data)[0];
if (info)
for (let i = 0; i < info.length; i += 2) {
const content = info.slice(i, i + 2);
const chunk = chunkSchema.parse(content);
result.push({
playerName: chunk[1],
playerID: chunk[0]
});
}
return new _UpdateTeamMembersList(result);
}
};
_UpdateTeamMembersList.PACKET_ID = "sa";
_UpdateTeamMembersList.PACKET_NAME = "UpdateTeamMembersList";
var UpdateTeamMembersList = _UpdateTeamMembersList;
// src/ServerPackets/UpdateLeaderBoard.ts
import { z as z2 } from "zod";
var schema2 = z2.tuple([z2.array(z2.union([z2.number(), z2.string()]))]);
var chunkSchema2 = z2.tuple([z2.number(), z2.string(), z2.number()]);
var _UpdateLeaderBoard = class _UpdateLeaderBoard {
constructor(members) {
this.members = members;
this.PACKET_NAME = "UpdateLeaderBoard";
}
static parse(data) {
const result = [];
const info = schema2.parse(data)[0];
for (let i = 0; i < info.length; i += 3) {
const content = info.slice(i, i + 3);
const chunk = chunkSchema2.parse(content);
result.push({
name: chunk[1],
score: chunk[2],
id: chunk[0]
});
}
return new _UpdateLeaderBoard(result);
}
};
_UpdateLeaderBoard.PACKET_ID = "5";
_UpdateLeaderBoard.PACKET_NAME = "UpdateLeaderBoard";
var UpdateLeaderBoard = _UpdateLeaderBoard;
// src/ServerPackets/InitializePlayer.ts
import { z as z3 } from "zod";
var initSchema = z3.tuple([
z3.string(),
z3.number(),
z3.string(),
z3.number(),
z3.number(),
z3.number(),
z3.number(),
z3.number(),
z3.number(),
z3.unknown()
]);
var schema3 = z3.tuple([initSchema, z3.boolean()]);
var _InitializePlayer = class _InitializePlayer {
constructor(isMyPlayer, playerName, maxHealth, playerID, health, initID, skinID, scale, angle, x, y) {
this.isMyPlayer = isMyPlayer;
this.playerName = playerName;
this.maxHealth = maxHealth;
this.playerID = playerID;
this.health = health;
this.initID = initID;
this.skinID = skinID;
this.scale = scale;
this.angle = angle;
this.x = x;
this.y = y;
this.PACKET_NAME = "InitializePlayer";
}
static parse(data) {
const [
[initID, playerID, playerName, x, y, angle, health, maxHealth, scale, skinID],
isMyPlayer
] = schema3.parse(data);
return new _InitializePlayer(
isMyPlayer,
playerName,
maxHealth,
playerID,
health,
initID,
skinID,
// TODO: Not safe
scale,
angle,
x,
y
);
}
};
_InitializePlayer.PACKET_ID = "2";
_InitializePlayer.PACKET_NAME = "InitializePlayer";
var InitializePlayer = _InitializePlayer;
// src/ServerPackets/PlayerDisconnect.ts
import { z as z4 } from "zod";
var schema4 = z4.tuple([z4.string()]);
var _PlayerDisconnect = class _PlayerDisconnect {
constructor(initID) {
this.initID = initID;
this.PACKET_NAME = "PlayerDisconnect";
}
static parse(data) {
return new _PlayerDisconnect(schema4.parse(data)[0]);
}
};
_PlayerDisconnect.PACKET_ID = "4";
_PlayerDisconnect.PACKET_NAME = "PlayerDisconnect";
var PlayerDisconnect = _PlayerDisconnect;
// src/ServerPackets/TeamNotification.ts
import { z as z5 } from "zod";
var schema5 = z5.tuple([z5.number(), z5.string()]);
var _TeamNotification = class _TeamNotification {
constructor(playerID, playerName) {
this.playerID = playerID;
this.playerName = playerName;
this.PACKET_NAME = "TeamNotification";
}
static parse(data) {
return new _TeamNotification(...schema5.parse(data));
}
};
_TeamNotification.PACKET_ID = "an";
_TeamNotification.PACKET_NAME = "TeamNotification";
var TeamNotification = _TeamNotification;
// src/ServerPackets/InitializeTeams.ts
import { z as z6 } from "zod";
var teamSchema = z6.object({
owner: z6.number(),
sid: z6.string()
});
var schema6 = z6.tuple([
z6.object({
teams: z6.array(teamSchema)
})
]);
var _InitializeTeams = class _InitializeTeams {
constructor(teams) {
this.teams = teams;
this.PACKET_NAME = "InitializeTeams";
}
static parse(data) {
return new _InitializeTeams(
schema6.parse(data)[0].teams.map((team) => {
return {
ownerID: team.owner,
title: team.sid
};
})
);
}
};
_InitializeTeams.PACKET_ID = "id";
_InitializeTeams.PACKET_NAME = "InitializeTeams";
var InitializeTeams = _InitializeTeams;
// src/ServerPackets/SpawnProjectile.ts
import { z as z7 } from "zod";
var schema7 = z7.tuple([
z7.number(),
z7.number(),
z7.number(),
z7.number(),
z7.number(),
z7.number(),
z7.number(),
z7.number()
]);
var _SpawnProjectile = class _SpawnProjectile {
constructor(range, speed, layer, type, direction, projectileID, originX, originY, fireDate) {
this.range = range;
this.speed = speed;
this.layer = layer;
this.type = type;
this.direction = direction;
this.projectileID = projectileID;
this.originX = originX;
this.originY = originY;
this.fireDate = fireDate;
this.PACKET_NAME = "SpawnProjectile";
}
static parse(data) {
const [originX, originY, direction, range, speed, type, layer, id] = schema7.parse(data);
return new _SpawnProjectile(
range,
speed,
layer,
type,
direction,
id,
originX,
originY,
Date.now()
);
}
};
_SpawnProjectile.PACKET_ID = "18";
_SpawnProjectile.PACKET_NAME = "SpawnProjectile";
var SpawnProjectile = _SpawnProjectile;
// src/ServerPackets/UpdateItemStore.ts
import { z as z8 } from "zod";
var schema8 = z8.tuple([z8.number(), z8.union([z8.number(), z8.string()]), z8.number()]);
var _UpdateItemStore = class _UpdateItemStore {
constructor(method, type, itemID) {
this.method = method;
this.type = type;
this.itemID = itemID;
this.PACKET_NAME = "UpdateItemStore";
}
static parse(data) {
const [isEquip, itemID, isAccessory] = schema8.parse(data);
return new _UpdateItemStore(
isEquip ? "Equipped" : "Purchased",
isAccessory ? "Accessory" : "Hat",
Number(itemID)
);
}
};
_UpdateItemStore.PACKET_ID = "us";
_UpdateItemStore.PACKET_NAME = "UpdateItemStore";
var UpdateItemStore = _UpdateItemStore;
// src/ServerPackets/UpdateItemUsage.ts
import { z as z9 } from "zod";
var schema9 = z9.tuple([z9.number(), z9.number()]);
var _UpdateItemUsage = class _UpdateItemUsage {
constructor(itemID, count) {
this.itemID = itemID;
this.count = count;
this.PACKET_NAME = "UpdateItemUsage";
}
static parse(data) {
return new _UpdateItemUsage(...schema9.parse(data));
}
};
_UpdateItemUsage.PACKET_ID = "14";
_UpdateItemUsage.PACKET_NAME = "UpdateItemUsage";
var UpdateItemUsage = _UpdateItemUsage;
// src/ServerPackets/InitializeGame.ts
import { z as z10 } from "zod";
var schema10 = z10.tuple([z10.number()]);
var _InitializeGame = class _InitializeGame {
constructor(MyPlayerID) {
this.MyPlayerID = MyPlayerID;
this.PACKET_NAME = "InitializeGame";
}
static parse(data) {
return new _InitializeGame(schema10.parse(data)[0]);
}
};
_InitializeGame.PACKET_ID = "1";
_InitializeGame.PACKET_NAME = "InitializeGame";
var InitializeGame = _InitializeGame;
// src/ServerPackets/SetObjectsData.ts
import { z as z11 } from "zod";
var schema11 = z11.tuple([z11.array(z11.number().nullable())]);
var chunkSchema3 = z11.tuple([
z11.number(),
z11.number(),
z11.number(),
z11.number(),
z11.number(),
z11.number().nullable(),
z11.number().nullable(),
z11.number()
]);
var _SetObjectsData = class _SetObjectsData {
constructor(objects) {
this.objects = objects;
this.PACKET_NAME = "SetObjectsData";
}
static parse(data) {
const result = [];
const info = schema11.parse(data)[0];
if (info)
for (let i = 0; i < info.length; i += 8) {
const content = info.slice(i, i + 8);
const chunk = chunkSchema3.parse(content);
result.push({
ownerID: chunk[7],
scale: chunk[4],
dataIndex: chunk[6],
type: chunk[5],
rotation: chunk[3],
id: chunk[0],
x: chunk[1],
y: chunk[2]
});
}
return new _SetObjectsData(result);
}
};
_SetObjectsData.PACKET_ID = "6";
_SetObjectsData.PACKET_NAME = "SetObjectsData";
var SetObjectsData = _SetObjectsData;
// src/ServerPackets/ShutdownNotice.ts
import { z as z12 } from "zod";
var schema12 = z12.tuple([z12.number()]);
var _ShutdownNotice = class _ShutdownNotice {
constructor(minutes, seconds) {
this.minutes = minutes;
this.seconds = seconds;
this.PACKET_NAME = "ShutdownNotice";
}
static parse(data) {
const [time] = schema12.parse(data);
return new _ShutdownNotice(Math.floor(time / 60), time % 60);
}
};
_ShutdownNotice.PACKET_ID = "20";
_ShutdownNotice.PACKET_NAME = "ShutdownNotice";
var ShutdownNotice = _ShutdownNotice;
// src/ServerPackets/UpdateProgress.ts
import { z as z13 } from "zod";
var schema13 = z13.union([z13.tuple([z13.number()]), z13.tuple([z13.number(), z13.number(), z13.number()])]);
var _UpdateProgress = class _UpdateProgress {
constructor(currentAge, currentXP, maxXP) {
this.currentAge = currentAge;
this.currentXP = currentXP;
this.maxXP = maxXP;
this.PACKET_NAME = "UpdateProgress";
}
static parse(data) {
const [currentXP, maxXP, currentAge] = schema13.parse(data);
return new _UpdateProgress(currentAge, currentXP, maxXP);
}
};
_UpdateProgress.PACKET_ID = "15";
_UpdateProgress.PACKET_NAME = "UpdateProgress";
var UpdateProgress = _UpdateProgress;
// src/ServerPackets/UpdateResource.ts
import { z as z14 } from "zod";
var resourceTypeSchema = z14.union([
z14.literal("wood"),
z14.literal("food"),
z14.literal("stone"),
z14.literal("points"),
z14.literal("kills")
]);
var schema14 = z14.tuple([resourceTypeSchema, z14.number(), z14.number()]);
var _UpdateResource = class _UpdateResource {
constructor(resourceType, resourceValue) {
this.resourceType = resourceType;
this.resourceValue = resourceValue;
this.PACKET_NAME = "UpdateResource";
}
static parse(data) {
const [type, value, _updateView] = schema14.parse(data);
return new _UpdateResource(type, value);
}
};
_UpdateResource.PACKET_ID = "9";
_UpdateResource.PACKET_NAME = "UpdateResource";
var UpdateResource = _UpdateResource;
// src/ServerPackets/UpdateUpgrades.ts
import { z as z15 } from "zod";
var schema15 = z15.tuple([z15.number(), z15.number()]);
var _UpdateUpgrades = class _UpdateUpgrades {
constructor(upgradeLevel, currentUpgradeLevel) {
this.upgradeLevel = upgradeLevel;
this.currentUpgradeLevel = currentUpgradeLevel;
this.PACKET_NAME = "UpdateUpgrades";
}
static parse(data) {
const [points, upgradeAge] = schema15.parse(data);
return new _UpdateUpgrades(points + upgradeAge, upgradeAge);
}
};
_UpdateUpgrades.PACKET_ID = "16";
_UpdateUpgrades.PACKET_NAME = "UpdateUpgrades";
var UpdateUpgrades = _UpdateUpgrades;
// src/ServerPackets/AnimateGameAI.ts
import { z as z16 } from "zod";
var schema16 = z16.tuple([z16.number()]);
var _AnimateGameAI = class _AnimateGameAI {
constructor(gameAIID) {
this.gameAIID = gameAIID;
this.PACKET_NAME = "AnimateGameAI";
}
static parse(data) {
return new _AnimateGameAI(schema16.parse(data)[0]);
}
};
_AnimateGameAI.PACKET_ID = "aa";
_AnimateGameAI.PACKET_NAME = "AnimateGameAI";
var AnimateGameAI = _AnimateGameAI;
// src/ServerPackets/RemoveObjects.ts
import { z as z17 } from "zod";
var schema17 = z17.tuple([z17.number()]);
var _RemoveObjects = class _RemoveObjects {
constructor(ownerID) {
this.ownerID = ownerID;
this.PACKET_NAME = "RemoveObjects";
}
static parse(data) {
return new _RemoveObjects(schema17.parse(data)[0]);
}
};
_RemoveObjects.PACKET_ID = "13";
_RemoveObjects.PACKET_NAME = "RemoveObjects";
var RemoveObjects = _RemoveObjects;
// src/ServerPackets/UpdateMiniMap.ts
import { z as z18 } from "zod";
var schema18 = z18.tuple([z18.union([z18.array(z18.union([z18.number(), z18.string()])), z18.literal(0)])]);
var chunkSchema4 = z18.tuple([z18.number(), z18.number()]);
var _UpdateMiniMap = class _UpdateMiniMap {
constructor(points) {
this.points = points;
this.PACKET_NAME = "UpdateMiniMap";
}
static parse(data) {
const result = [];
const info = schema18.parse(data)[0];
if (info instanceof Array)
for (let i = 0; i < info.length; i += 2) {
const content = info.slice(i, i + 2);
const chunk = chunkSchema4.parse(content);
result.push({
x: chunk[0],
y: chunk[1]
});
}
return new _UpdateMiniMap(result);
}
};
_UpdateMiniMap.PACKET_ID = "mm";
_UpdateMiniMap.PACKET_NAME = "UpdateMiniMap";
var UpdateMiniMap = _UpdateMiniMap;
// src/ServerPackets/UpdatePlayers.ts
import { z as z19 } from "zod";
var chunkSchema5 = z19.tuple([
z19.number(),
z19.number(),
z19.number(),
z19.number(),
z19.number(),
z19.number(),
z19.number(),
z19.string().nullable(),
// 8
z19.union([z19.number(), z19.string()]),
z19.union([z19.number(), z19.string()]),
z19.number(),
z19.number(),
z19.number()
]);
var schema19 = z19.union([
z19.tuple([z19.array(z19.union([z19.string().nullable(), z19.number()]))]),
z19.tuple([])
]);
var _UpdatePlayers = class _UpdatePlayers {
constructor(players) {
this.players = players;
this.PACKET_NAME = "UpdatePlayers";
}
static parse(data) {
const result = [];
const info = schema19.parse(data)[0];
if (info)
for (let i = 0; i < info.length; i += 13) {
const content = info.slice(i, i + 13);
const chunk = chunkSchema5.parse(content);
result.push({
isBestKiller: !!chunk[11],
weaponVariant: chunk[6],
weaponType: chunk[5],
buildType: chunk[4],
isLeader: !!chunk[8],
tailType: Number(chunk[10]),
hatType: Number(chunk[9]),
layer: chunk[12],
teamID: chunk[7],
angle: chunk[3],
playerID: chunk[0],
x: chunk[1],
y: chunk[2]
});
}
return new _UpdatePlayers(result);
}
};
_UpdatePlayers.PACKET_ID = "33";
_UpdatePlayers.PACKET_NAME = "UpdatePlayers";
var UpdatePlayers = _UpdatePlayers;
// src/ServerPackets/ObjectStrike.ts
import { z as z20 } from "zod";
var schema20 = z20.tuple([z20.number(), z20.number()]);
var _ObjectStrike = class _ObjectStrike {
constructor(forceDirection, objectID) {
this.forceDirection = forceDirection;
this.objectID = objectID;
this.PACKET_NAME = "ObjectStrike";
}
static parse(data) {
return new _ObjectStrike(...schema20.parse(data));
}
};
_ObjectStrike.PACKET_ID = "8";
_ObjectStrike.PACKET_NAME = "ObjectStrike";
var ObjectStrike = _ObjectStrike;
// src/ServerPackets/RemoveObject.ts
import { z as z21 } from "zod";
var schema21 = z21.tuple([z21.number()]);
var _RemoveObject = class _RemoveObject {
constructor(objectID) {
this.objectID = objectID;
this.PACKET_NAME = "RemoveObject";
}
static parse(data) {
return new _RemoveObject(schema21.parse(data)[0]);
}
};
_RemoveObject.PACKET_ID = "12";
_RemoveObject.PACKET_NAME = "RemoveObject";
var RemoveObject = _RemoveObject;
// src/ServerPackets/UpdateGameAI.ts
import { z as z22 } from "zod";
var schema22 = z22.union([z22.tuple([z22.array(z22.number())]), z22.tuple([])]);
var chunkSchema6 = z22.tuple([
z22.number(),
z22.number(),
z22.number(),
z22.number(),
z22.number(),
z22.number(),
z22.number()
]);
var _UpdateGameAI = class _UpdateGameAI {
constructor(data) {
this.data = data;
this.PACKET_NAME = "UpdateGameAI";
}
static parse(data) {
const result = [];
const info = schema22.parse(data)[0];
if (info)
for (let i = 0; i < info.length; i += 7) {
const content = info.slice(i, i + 7);
const chunk = chunkSchema6.parse(content);
result.push({
health: chunk[5],
type: chunk[1],
rotation: chunk[4],
// FIXME: uniqueName is string for cows.
uniqueName: null,
// getUniqueName(chunk[6]) || null,
id: chunk[0],
x: chunk[2],
y: chunk[3]
});
}
return new _UpdateGameAI(result);
}
};
_UpdateGameAI.PACKET_ID = "a";
_UpdateGameAI.PACKET_NAME = "UpdateGameAI";
var UpdateGameAI = _UpdateGameAI;
// src/ServerPackets/UpdateHealth.ts
import { z as z23 } from "zod";
var schema23 = z23.tuple([z23.number(), z23.number()]);
var _UpdateHealth = class _UpdateHealth {
constructor(playerID, playerHealth) {
this.playerID = playerID;
this.playerHealth = playerHealth;
this.PACKET_NAME = "UpdateHealth";
}
static parse(data) {
return new _UpdateHealth(...schema23.parse(data));
}
};
_UpdateHealth.PACKET_ID = "h";
_UpdateHealth.PACKET_NAME = "UpdateHealth";
var UpdateHealth = _UpdateHealth;
// src/ServerPackets/ReceiveChat.ts
import { z as z24 } from "zod";
var schema24 = z24.tuple([z24.number(), z24.string()]);
var _ReceiveChat = class _ReceiveChat {
constructor(ownerID, message) {
this.ownerID = ownerID;
this.message = message;
this.PACKET_NAME = "ReceiveChat";
}
static parse(data) {
return new _ReceiveChat(...schema24.parse(data));
}
};
_ReceiveChat.PACKET_ID = "ch";
_ReceiveChat.PACKET_NAME = "ReceiveChat";
var ReceiveChat = _ReceiveChat;
// src/ServerPackets/TurretShoot.ts
import { z as z25 } from "zod";
var schema25 = z25.tuple([z25.number(), z25.number()]);
var _TurretShoot = class _TurretShoot {
constructor(turretID, angle) {
this.turretID = turretID;
this.angle = angle;
this.PACKET_NAME = "TurretShoot";
}
static parse(data) {
return new _TurretShoot(...schema25.parse(data));
}
};
_TurretShoot.PACKET_ID = "sp";
_TurretShoot.PACKET_NAME = "TurretShoot";
var TurretShoot = _TurretShoot;
// src/ServerPackets/UpdateItems.ts
import { z as z26 } from "zod";
var schema26 = z26.union([
z26.tuple([z26.array(z26.number()), z26.number()]),
z26.tuple([z26.array(z26.number())])
]);
var _UpdateItems = class _UpdateItems {
constructor(kit, isWeapon) {
this.kit = kit;
this.isWeapon = isWeapon;
this.PACKET_NAME = "UpdateItems";
}
static parse(data) {
const [kit, isWeapon] = schema26.parse(data);
return new _UpdateItems(kit, !!isWeapon);
}
};
_UpdateItems.PACKET_ID = "17";
_UpdateItems.PACKET_NAME = "UpdateItems";
var UpdateItems = _UpdateItems;
// src/ServerPackets/CreateTeam.ts
import { z as z27 } from "zod";
var teamSchema2 = z27.object({
owner: z27.number(),
sid: z27.string()
});
var schema27 = z27.tuple([teamSchema2]);
var _CreateTeam = class _CreateTeam {
constructor(ownerID, title) {
this.ownerID = ownerID;
this.title = title;
this.PACKET_NAME = "CreateTeam";
}
static parse(data) {
const [info] = schema27.parse(data);
return new _CreateTeam(info.owner, info.sid);
}
};
_CreateTeam.PACKET_ID = "ac";
_CreateTeam.PACKET_NAME = "CreateTeam";
var CreateTeam = _CreateTeam;
// src/ServerPackets/DeleteTeam.ts
import { z as z28 } from "zod";
var schema28 = z28.tuple([z28.string()]);
var _DeleteTeam = class _DeleteTeam {
constructor(title) {
this.title = title;
this.PACKET_NAME = "DeleteTeam";
}
static parse(data) {
return new _DeleteTeam(...schema28.parse(data));
}
};
_DeleteTeam.PACKET_ID = "ad";
_DeleteTeam.PACKET_NAME = "DeleteTeam";
var DeleteTeam = _DeleteTeam;
// src/ServerPackets/Disconnect.ts
var _Disconnect = class _Disconnect {
constructor() {
this.PACKET_NAME = "Disconnect";
}
static parse(_data2) {
return new _Disconnect();
}
};
_Disconnect.PACKET_ID = "d";
_Disconnect.PACKET_NAME = "Disconnect";
var Disconnect = _Disconnect;
// src/ServerPackets/TeamSignal.ts
import { z as z29 } from "zod";
var schema29 = z29.tuple([z29.number(), z29.number()]);
var _TeamSignal = class _TeamSignal {
constructor(x, y) {
this.x = x;
this.y = y;
this.PACKET_NAME = "TeamSignal";
}
static parse(data) {
return new _TeamSignal(...schema29.parse(data));
}
};
_TeamSignal.PACKET_ID = "p";
_TeamSignal.PACKET_NAME = "TeamSignal";
var TeamSignal = _TeamSignal;
// src/ServerPackets/ShowText.ts
import { z as z30 } from "zod";
var schema30 = z30.tuple([z30.number(), z30.number(), z30.number(), z30.number()]);
var _ShowText = class _ShowText {
constructor(type, content, x, y) {
this.type = type;
this.content = content;
this.x = x;
this.y = y;
this.PACKET_NAME = "ShowText";
}
static parse(data) {
const [x, y, content] = schema30.parse(data);
return new _ShowText(content >= 0 ? "Damage" : "Healing", content.toString(), x, y);
}
};
_ShowText.PACKET_ID = "t";
_ShowText.PACKET_NAME = "ShowText";
var ShowText = _ShowText;
// src/ServerPackets/Unknown.ts
var _Unknown = class _Unknown {
constructor(content) {
this.content = content;
this.PACKET_NAME = "Unknown";
}
static parse(data) {
return new _Unknown(data);
}
};
_Unknown.PACKET_ID = "*";
_Unknown.PACKET_NAME = "Unknown";
var Unknown = _Unknown;
// src/ServerPackets/IOInit.ts
import { z as z31 } from "zod";
var schema31 = z31.tuple([z31.string()]);
var _IOInit = class _IOInit {
constructor(initID) {
this.initID = initID;
this.PACKET_NAME = "IOInit";
}
static parse(data) {
return new _IOInit(schema31.parse(data)[0]);
}
};
_IOInit.PACKET_ID = "io-init";
_IOInit.PACKET_NAME = "IOInit";
var IOInit = _IOInit;
// src/ServerPackets/Punch.ts
import { z as z32 } from "zod";
var schema32 = z32.tuple([z32.number(), z32.number(), z32.number()]);
var _Punch = class _Punch {
constructor(ownerID, didHit, weaponType) {
this.ownerID = ownerID;
this.didHit = didHit;
this.weaponType = weaponType;
this.PACKET_NAME = "Punch";
}
static parse(data) {
const [ownerID, didHit, weaponType] = schema32.parse(data);
return new _Punch(ownerID, !!didHit, weaponType);
}
};
_Punch.PACKET_ID = "7";
_Punch.PACKET_NAME = "Punch";
var Punch = _Punch;
// src/ServerPackets/Death.ts
var _Death = class _Death {
constructor() {
this.PACKET_NAME = "Death";
}
static parse(_data2) {
return new _Death();
}
};
_Death.PACKET_ID = "11";
_Death.PACKET_NAME = "Death";
var Death = _Death;
// src/ServerPackets/Pong.ts
var _Pong = class _Pong {
constructor() {
this.PACKET_NAME = "Pong";
}
static parse(_data2) {
return new _Pong();
}
};
_Pong.PACKET_ID = "pp";
_Pong.PACKET_NAME = "Pong";
var Pong = _Pong;
// src/ServerPackets/index.ts
var ServerPackets = {
UpdateTeamMembersList,
UpdateLeaderBoard,
InitializePlayer,
PlayerDisconnect,
TeamNotification,
InitializeTeams,
SpawnProjectile,
UpdateItemStore,
UpdateItemUsage,
InitializeGame,
SetObjectsData,
ShutdownNotice,
UpdateProgress,
UpdateResource,
UpdateUpgrades,
AnimateGameAI,
RemoveObjects,
UpdateMiniMap,
UpdatePlayers,
ObjectStrike,
RemoveObject,
UpdateGameAI,
UpdateHealth,
ReceiveChat,
TurretShoot,
UpdateItems,
CreateTeam,
DeleteTeam,
Disconnect,
TeamSignal,
ShowText,
Unknown,
IOInit,
Punch,
Death,
Pong
};
function decode(raw) {
const [PACKET_ID, data] = msgpackDecode(raw instanceof Uint8Array ? raw : new Uint8Array(raw));
for (const packetName in ServerPackets) {
const Packet = ServerPackets[packetName];
if (Packet.PACKET_ID == PACKET_ID) {
let packet;
try {
packet = Packet.parse(data);
} catch (e) {
packet = ServerPackets.Unknown.parse([PACKET_ID, data]);
console.group(`Attempting to parse ${PACKET_ID} using ${Packet.PACKET_NAME} but failed`);
console.error(e);
console.info("Backup to `Unknown` Packet.");
console.info(packet);
console.groupEnd();
}
return packet;
}
}
return ServerPackets.Unknown.parse([PACKET_ID, data]);
}
// src/MooMooIOConnection.ts
import UnifyEmitter2 from "unify-emitter";
var _trusted, _socket, _initializeSocket, initializeSocket_fn;
var MooMooIOConnection = class extends UnifyEmitter2 {
constructor() {
super(...arguments);
__privateAdd(this, _initializeSocket);
__privateAdd(this, _trusted, null);
__privateAdd(this, _socket, null);
this.antiKick = new AntiKick();
}
connect(ip, token) {
const url = `wss://ip_${ip}.moomoo.io:8008/?gameIndex=0&token=${encodeURIComponent(token)}`;
this.use(new WebSocket(url));
}
disconnect() {
if (!__privateGet(this, _socket) || __privateGet(this, _socket).readyState == __privateGet(this, _socket).CLOSED)
return;
__privateGet(this, _socket).close();
}
destroy() {
__privateSet(this, _socket, null);
this.antiKick.destroy();
this.removeListeners();
}
/**
* Sends the specified data through the socket connection.
* @param data - The data to be sent as a Uint8Array.
* @returns A boolean value indicating if the request has been successfully sent.
*/
send(data) {
if (!__privateGet(this, _socket) || __privateGet(this, _socket).readyState != __privateGet(this, _socket).OPEN)
return false;
const canSend = data instanceof Uint8Array && this.antiKick.canSend(data);
if (canSend) {
__privateSet(this, _trusted, data);
__privateGet(this, _socket).send(data);
this.emit("send", data);
}
return canSend;
}
use(socket) {
this.socket = socket;
}
set socket(socket) {
if (socket instanceof WebSocket) {
__privateSet(this, _socket, socket);
__privateMethod(this, _initializeSocket, initializeSocket_fn).call(this);
}
}
isOPEN() {
return __privateGet(this, _socket) && __privateGet(this, _socket).readyState == __privateGet(this, _socket).OPEN;
}
};
_trusted = new WeakMap();
_socket = new WeakMap();
_initializeSocket = new WeakSet();
initializeSocket_fn = function() {
if (!__privateGet(this, _socket))
return;
__privateGet(this, _socket).binaryType = "arraybuffer";
__privateGet(this, _socket).addEventListener("message", (ev) => {
if (ev.data instanceof ArrayBuffer) {
this.emit("rawMessage", new Uint8Array(ev.data));
this.emit("message", decode(ev.data));
}
});
__privateGet(this, _socket).addEventListener("open", () => {
this.emit("open", null);
});
__privateGet(this, _socket).addEventListener("close", (ev) => {
this.emit("close", {
reason: ev.reason,
code: ev.code
});
});
__privateGet(this, _socket).addEventListener("error", () => {
this.emit("error", null);
});
const oldSend = __privateGet(this, _socket).send.bind(__privateGet(this, _socket));
__privateGet(this, _socket).send = (data) => {
const isTrusted = __privateGet(this, _trusted) == data;
__privateSet(this, _trusted, null);
if (data instanceof Uint8Array) {
oldSend(data);
this.emit("deepSend", { data, isTrusted });
}
};
};
// src/ClientPacketOrganizer.ts
import { encode } from "msgpack-lite";
var _requestStack;
var ClientPacketOrganizer = class {
constructor(connection) {
this.connection = connection;
__privateAdd(this, _requestStack, []);
}
destroy() {
__privateSet(this, _requestStack, []);
}
/**
* Generator function that reads and yields items from the request stack.
* @returns An iterator for the items in the request stack.
*/
*readRequestStack() {
for (let item of __privateGet(this, _requestStack)) {
yield item;
}
__privateSet(this, _requestStack, []);
}
/**
* Pushes a new request to the request stack.
* @param {Packet} input - The request to be added to the stack.
*/
requestStackPush(input) {
__privateGet(this, _requestStack).push(input);
}
parse(packet) {
return __async(this, null, function* () {
return this.connection.send(encode(packet));
});
}
parseLast() {
return __async(this, null, function* () {
const packet = __privateGet(this, _requestStack).pop();
return !!packet && (yield this.parse(packet));
});
}
parseRequestStack() {
return __async(this, null, function* () {
for (let packet of this.readRequestStack()) {
yield this.parse(packet);
}
});
}
/**
*
* @description This packet is used to respond to a join request you received as the team owner. You can either `Accept` or `Deny` the request.
* @ignored If you don't own the team, this packet will be ignored.
* @param answer Either `Accept` or `Deny`.
*
* @note The response is based on the order in which the requests were received, with the oldest request being answered first.
*/
answerJoinRequest(answer) {
this.requestStackPush(["11", [answer == "Accept" ? 1 : 0]]);
return this;
}
/**
* @description This packet is used to purchase/buy an `Accessory` or `Hat` in the game.
* @ignored if you already own the item or if you don't have enough gold to make the purchase. The packet will be ignored.
* @param itemID is the unique number that identifies the item (ID).
* @param itemType can be either `Accessory` or `Hat`.
* @note If you haven't spawned in the game yet, this packet will be ignored
*/
buy(itemID, itemType) {
this.requestStackPush(["13c", [1, itemID, itemType == "Accessory" ? 1 : 0]]);
return this;
}
/**
*
* @description this packet is used to create a team in the game.
* @ignored If you are already in a team or if the title you provide is already being used by another team. this packet will be ignored
* @param teamTitle unique title for the team.
*
* @note you can have one team at the same time.
*/
createTeam(teamTitle) {
this.requestStackPush(["8", [teamTitle]]);
return this;
}
/**
* @description This packet is used to **equip** an `Accessory` or `Hat` in the game.
* @ignored if you don't have that item yet. the packet will be ignored.
* @param itemID is the identification number for that item (ID).
* @param itemType can be either `Accessory` or `Hat`.
* @note If you haven't spawned in the game yet, this packet will be ignored.
*/
equip(itemID, itemType) {
this.requestStackPush(["13c", [0, itemID, itemType == "Accessory" ? 1 : 0]]);
return this;
}
/**
* @description This packet is used to change the item held by your player.
* @param itemID A unique code that identifies the item.
* @param isWeapon A method to categorize the type of item.
*/
holdItem(itemID, isWeapon) {
this.requestStackPush(["5", [itemID, isWeapon]]);
return this;
}
/**
*
* @description This packet is used to ask to join a team in the game.
* @ignored If you are already in a team, this packet will be ignored.
* @param teamTitle The name of the team you want to join.
* @note If the team cannot be found, this packet will be ignored.
*/
joinRequest(teamTitle) {
this.requestStackPush(["10", [teamTitle]]);
return this;
}
/**
*
* @description This packet is for removing someone from your team
* @ignored If you are not the team owner. this packet will be ignored
* @param playerID The ID of the player you want to kick from your team.
*/
kickFromTeam(playerID) {
this.requestStackPush(["12", [playerID]]);
return this;
}
/**
*
* @description this packet is used to **leave your current team.
* @ignored If you are not in a team. this packet will be ignored.
*/
leaveTeam() {
this.requestStackPush(["9", []]);
return this;
}
/**
* @description this packet is used to ping the game
* @param target either `MiniMap` or `Connection`
* @note
* > if the `target` is `MiniMap` then the server gonna responses with `UpdateMiniMap`.......
* > if the `target` is `Connection` then the server gonna responses with `Pong`
*/
ping(target) {
this.requestStackPush(target == "MiniMap" ? ["14", [1]] : ["pp", []]);
return this;
}
/**
* @description this packet is used to update your character direction in the game.
* @param direction the direction your character is facing (in radian)
*
* @note this direction may be overwritten by `setPunchState`
*/
setDirection(direction) {
this.requestStackPush(["2", [direction]]);
return this;
}
/**
* @description This packet is used to update your punch status in the game.
* @param state is an indicator of whether your player should start punching or not.
* @param direction is the direction the player should face before updating the status (in radian).
* @depth I think I need to explain this further.
* The `state` refers to whether your player is currently punching or not.
* You can make your player perform an punch by following these steps:
* > First, enable the punch by setting the `state` parameter to `true`.
* > Second, disable the punch by setting the `state` parameter to `false`.
*/
setPunchState(state, direction) {
this.requestStackPush(["c", [state, direction]]);
return this;
}
/**
* @description This packet is used to send a message for nearby players
* @param content the message content you want to send
*/
chat(message) {
this.requestStackPush(["ch", [message.slice(0, 30)]]);
return this;
}
/**
* @description This packet is used to create your character in the game.
* @param name The name of your character.
* @param skinID The skin ID of your character.
* @param haveStartPackage Determines whether your character should start with a fast start-up package (having 100 resources for each resource).
*/
spawn(name, skinID, haveStartPackage = true) {
this.requestStackPush([
"sp",
[
{
moofoll: haveStartPackage,
skin: skinID,
name
}
]
]);
return this;
}
/**
* @description this packet is used to toggle auto-punch
* @notSafe true
*/
toggleAutoPunchState() {
this.requestStackPush(["7", [1]]);
return this;
}
/**
* @description This packet is used to toggle the lock of your player facing direction.
* @note Not recommended to use. avoid use this as much as possible
*/
toggleLockDir() {
this.requestStackPush(["7", [0]]);
return this;
}
/**
* @description This packet is used to upgrade your chosen items in the game.
* @param itemID A special code that identify the item.
* @note If you do not meet the necessary conditions for the upgrade, this packet will be ignored.
*/
upgrade(itemID) {
this.requestStackPush(["6", [itemID]]);
return this;
}
};
_requestStack = new WeakMap();
// src/data/accessories.ts
var accessories_default = [
{
id: 12,
name: "Snowball",
price: 1e3,
scale: 105,
xOff: 18,
desc: "no effect"
},
{
id: 9,
name: "Tree Cape",
price: 1e3,
scale: 90,
desc: "no effect"
},
{
id: 10,
name: "Stone Cape",
price: 1e3,
scale: 90,
desc: "no effect"
},
{
id: 3,
name: "Cookie Cape",
price: 1500,
scale: 90,
desc: "no effect"
},
{
id: 8,
name: "Cow Cape",
price: 2e3,
scale: 90,
desc: "no effect"
},
{
id: 11,
name: "Monkey Tail",
price: 2e3,
scale: 97,
xOff: 25,
desc: "Super speed but reduced damage",
spdMult: 1.35,
dmgMultO: 0.2
},
{
id: 17,
name: "Apple Basket",
price: 3e3,
scale: 80,
xOff: 12,
desc: "slowly regenerates health over time",
healthRegen: 1
},
{
id: 6,
name: "Winter Cape",
price: 3e3,
scale: 90,
desc: "no effect"
},
{
id: 4,
name: "Skull Cape",
price: 4e3,
scale: 90,
desc: "no effect"
},
{
id: 5,
name: "Dash Cape",
price: 5e3,
scale: 90,
desc: "no effect"
},
{
id: 2,
name: "Dragon Cape",
price: 6e3,
scale: 90,
desc: "no effect"
},
{
id: 1,
name: "Super Cape",
price: 8e3,
scale: 90,
desc: "no effect"
},
{
id: 7,
name: "Troll Cape",
price: 8e3,
scale: 90,
desc: "no effect"
},
{
id: 14,
name: "Thorns",
price: 1e4,
scale: 115,
xOff: 20,
desc: "no effect"
},
{
id: 15,
name: "Blockades",
price: 1e4,
scale: 95,
xOff: 15,
desc: "no effect"
},
{
id: 20,
name: "Devils Tail",
price: 1e4,
scale: 95,
xOff: 20,
desc: "no effect"
},
{
id: 16,
name: "Sawblade",
price: 12e3,
scale: 90,
spin: true,
xOff: 0,
desc: "deal damage to players that damage you",
dmg: 0.15
},
{
id: 13,
name: "Angel Wings",
price: 15e3,
scale: 138,
xOff: 22,
desc: "slowly regenerates health over time",
healthRegen: 3
},
{
id: 19,
name: "Shadow Wings",
price: 15e3,
scale: 138,
xOff: 22,
desc: "increased movement speed",
spdMult: 1.1
},
{
id: 18,
name: "Blood Wings",
price: 2e4,
scale: 178,
xOff: 26,
desc: "restores health when you deal damage",
healD: 0.2
},
{
id: 21,
name: "Corrupt X Wings",
price: 2e4,
scale: 178,
xOff: 26,
desc: "deal damage to players that damage you",
dmg: