// ==UserScript==
// @name Lurkers.io, fly hack, weapon stats hack, teammate grief
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Fly, modify weapon stats, such as: reload time, fire rate, entity fired, fire speed, infinite ammo etc
// @author TENTACLES
// @match https://lurkers.io/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
let originalXg = null;
let guiCreated = false;
let gameContext = null;
let lastPlayerState = null;
let lastPlayerId = null;
let originalPeerId = null; // For spectator mode toggle
let playerSettings = {
flyMode: false,
weaponMods: {} // Will store settings for each weapon slot
};
// Game entity types for weapon customization
const entityTypes = [
"Marker", "Flag", "RectanglePhysicalEntity", "Prop", "Vehicle", "Living",
"CollapsingBlock", "Nail", "Item", "ItemSpawn", "Projectile", "Ladder",
"Shop", "Chest", "GunTurret", "Door", "Tunnel", "Zombie", "Animal",
"Human", "Pellet", "Snowball", "Bullet", "Arrow", "Explosive",
"SupplyCrate", "TrapDoor", "IronDoor", "CrabZombie", "FastZombie",
"BigZombie", "Wolf", "Fox", "Fish", "Deer", "Boar", "Sheep", "Trader",
"Bergobrine", "ThrowableWeapon", "Grenade", "IronTrapDoor", "ExplosiveZombie",
"DaddyZombie", "GrenadeLauncherGrenade", "TNT", "Rocket", "PumpkinLauncherGrenade", "HomingMissile"
];
// Function to find and proxy _xg
function findAndProxyXg() {
for (let prop in window) {
try {
if (window[prop] && typeof window[prop] === 'object' && window[prop]._xg) {
console.log('Found _xg function:', window[prop]._xg);
// Store original function and its context
originalXg = window[prop]._xg;
gameContext = window[prop];
// Display the original function contents using toString()
console.log('Original _xg function contents:', originalXg.toString());
// Get all available variables in the context
console.log('Available variables in game context:', Object.keys(window[prop]));
// Proxy the function
window[prop]._xg = function(b, c) {
// Log arguments passed to the function
console.log('Arguments passed to _xg:', b, c);
// Set up global getPlayer function
window.getPlayer = () => {
try {
// From the original function, we can see it uses V2f and YUi
if (typeof gameContext.V2f !== 'undefined' &&
typeof gameContext.YUi !== 'undefined' &&
typeof gameContext.ltf !== 'undefined' &&
typeof gameContext.etf !== 'undefined') {
console.log('Using game variables for player access');
return gameContext.ltf(gameContext.etf(gameContext.V2f, 1), gameContext.YUi, 1, 5, [c])[0];
} else {
// Try with original variables from the function body
console.log('Attempting to get player with variables from context');
// Loop through all properties to find the player
if (c && c.sb) {
console.log('Found player candidate with sb property:', c);
return c;
}
console.log('Could not find player in context');
return null;
}
} catch (e) {
console.error('Error getting player:', e);
console.log('Dumping context variables for debugging:');
for (let key in gameContext) {
try {
if (typeof gameContext[key] === 'function') {
console.log(`${key}: [Function]`);
} else if (gameContext[key] !== null && typeof gameContext[key] === 'object') {
console.log(`${key}: [Object]`);
} else {
console.log(`${key}: ${gameContext[key]}`);
}
} catch (err) {
console.log(`Error accessing ${key}: ${err.message}`);
}
}
return null;
}
};
// Create GUI if not already created
if (!guiCreated) {
createCheatGUI();
guiCreated = true;
}
// Check for player respawn (death and coming back to life)
const player = window.getPlayer();
if (player) {
// Store the player's peer ID for spectator mode toggle
if (!originalPeerId && player.R) {
originalPeerId = player.R;
console.log('Saved original peer ID:', originalPeerId);
}
const currentPlayerId = player.sb;
// Check if this is a new player (respawn or first spawn)
if (lastPlayerId !== currentPlayerId) {
console.log('Player ID changed, possible respawn detected:', lastPlayerId, '->', currentPlayerId);
lastPlayerId = currentPlayerId;
// Wait a short time for player to fully initialize after respawn
setTimeout(reapplyPlayerSettings, 500);
}
// Store current player state for future comparison
lastPlayerState = {
id: player.sb,
health: player.Fb // Assuming Fb is health, adjust if needed
};
}
// Call original function with original context
return originalXg.call(gameContext, b, c);
};
console.log('Successfully proxied _xg function');
return true;
}
} catch (e) {
// Ignore errors when checking properties
}
}
return false;
}
// Function to toggle spectator mode
window.toggleSpectatorMode = function(enabled) {
try {
const player = window.getPlayer();
if (!player) {
console.error('Player not available');
return false;
}
if (enabled) {
// Switch to spectator mode
if (player.R) {
// Save current ID if not saved already
if (!originalPeerId) {
originalPeerId = player.R;
}
// Set to undefined to enter spectator mode
player.R = undefined;
console.log('Switched to spectator mode');
return true;
}
} else {
// Return to player mode
if (originalPeerId) {
player.R = originalPeerId;
console.log('Returned to player mode, restored ID:', originalPeerId);
return true;
} else {
console.error('Original peer ID not found, cannot restore player mode');
}
}
return false;
} catch (e) {
console.error('Error toggling spectator mode:', e);
return false;
}
};
// Function to change weapon entity type
window.changeWeaponEntity = function(slotIndex, entityType) {
try {
const player = window.getPlayer();
if (!player || !player.tb || !player.tb.b || !player.tb.b[slotIndex] || !player.tb.b[slotIndex].c) {
console.error('Weapon not available in slot', slotIndex);
return false;
}
// Set the entity type
player.tb.b[slotIndex].c.f = entityType;
console.log(`Changed weapon entity in slot ${slotIndex} to:`, entityType);
// Save this setting
if (!playerSettings.weaponMods[slotIndex]) {
playerSettings.weaponMods[slotIndex] = {};
}
playerSettings.weaponMods[slotIndex].entityType = entityType;
return true;
} catch (e) {
console.error('Error changing weapon entity:', e);
return false;
}
};
// Function to reapply all player settings after respawn
function reapplyPlayerSettings() {
try {
const player = window.getPlayer();
if (!player) {
console.log('Cannot reapply settings - player not available');
return;
}
console.log('Reapplying player settings after respawn');
// Reapply fly mode if it was enabled
if (playerSettings.flyMode) {
player.P = true;
console.log('Reapplied fly mode');
// Update UI to match
const flyToggle = document.getElementById('fly-toggle');
if (flyToggle) flyToggle.checked = true;
}
// Reapply weapon modifications
if (player.tb && player.tb.b) {
for (let slotIndex in playerSettings.weaponMods) {
const slotMods = playerSettings.weaponMods[slotIndex];
const slot = parseInt(slotIndex, 10);
// Check if this slot exists in the current inventory
if (player.tb.b[slot] && player.tb.b[slot].c) {
// Apply the saved modifications
player.tb.b[slot].c.w = slotMods.fireRate;
player.tb.b[slot].c.e = slotMods.projectiles;
player.tb.b[slot].c.G = slotMods.speed;
player.tb.b[slot].c.R = !slotMods.infiniteAmmo;
player.tb.b[slot].c.t = slotMods.autoFire;
player.tb.b[slot].c.a = slotMods.knockback;
player.tb.b[slot].c.j = slotMods.spread;
// Apply entity type if saved
if (slotMods.entityType) {
player.tb.b[slot].c.f = slotMods.entityType;
}
console.log(`Reapplied weapon mods to slot ${slot}:`, slotMods);
}
}
}
// Refresh the inventory display
refreshInventory();
} catch (e) {
console.error('Error reapplying player settings:', e);
}
}
// Create the cheat GUI
function createCheatGUI() {
// Create main container
const gui = document.createElement('div');
gui.id = 'cheat-gui';
gui.style.cssText = `
position: fixed;
top: 10px;
right: 10px;
width: 350px;
max-height: 80vh;
background: rgba(0, 0, 0, 0.9);
border: 2px solid #333;
border-radius: 8px;
color: white;
font-family: Arial, sans-serif;
font-size: 12px;
z-index: 10000;
overflow-y: auto;
display: none;
`;
// Create header
const header = document.createElement('div');
header.style.cssText = `
background: #333;
padding: 10px;
cursor: move;
user-select: none;
display: flex;
justify-content: space-between;
align-items: center;
`;
header.innerHTML = `
<span>Game Cheat Menu</span>
<button id="close-gui" style="background: #f44; border: none; color: white; padding: 2px 6px; cursor: pointer;">×</button>
`;
// Create content area
const content = document.createElement('div');
content.style.padding = '10px';
// Player controls section
const playerSection = document.createElement('div');
playerSection.innerHTML = `
<h3 style="margin: 0 0 10px 0; color: #4CAF50;">Player Controls</h3>
<label style="display: flex; align-items: center; margin-bottom: 10px;">
<input type="checkbox" id="fly-toggle" style="margin-right: 8px;">
Enable Fly Mode
</label>
<label style="display: flex; align-items: center; margin-bottom: 10px;">
<input type="checkbox" id="spectator-toggle" style="margin-right: 8px;">
Spectator Team
</label>
`;
// Inventory section
const inventorySection = document.createElement('div');
inventorySection.id = 'inventory-section';
inventorySection.innerHTML = `
<h3 style="margin: 20px 0 10px 0; color: #4CAF50;">Inventory (Active Items)</h3>
<div id="inventory-slots-container"></div>
`;
// Manual refresh button
const refreshBtn = document.createElement('button');
refreshBtn.textContent = 'Refresh Inventory';
refreshBtn.style.cssText = `
background: #2196F3;
color: white;
border: none;
padding: 8px 16px;
cursor: pointer;
border-radius: 4px;
width: 100%;
margin-top: 10px;
`;
refreshBtn.onclick = refreshInventory;
// Assemble GUI
gui.appendChild(header);
content.appendChild(playerSection);
content.appendChild(inventorySection);
content.appendChild(refreshBtn);
gui.appendChild(content);
document.body.appendChild(gui);
// Add toggle button
const toggleBtn = document.createElement('button');
toggleBtn.textContent = 'Cheats';
toggleBtn.style.cssText = `
position: fixed;
top: 10px;
right: 10px;
background: #4CAF50;
color: white;
border: none;
padding: 8px 12px;
cursor: pointer;
border-radius: 4px;
z-index: 10001;
font-size: 12px;
`;
toggleBtn.onclick = () => {
if (gui.style.display === 'none') {
gui.style.display = 'block';
toggleBtn.style.display = 'none';
}
};
document.body.appendChild(toggleBtn);
// Event listeners
document.getElementById('close-gui').onclick = () => {
gui.style.display = 'none';
toggleBtn.style.display = 'block';
};
document.getElementById('fly-toggle').onchange = function() {
try {
if (window.getPlayer && window.getPlayer()) {
window.getPlayer().P = this.checked;
// Save the setting for respawn
playerSettings.flyMode = this.checked;
console.log('Fly mode:', this.checked ? 'enabled' : 'disabled');
} else {
console.warn('Player not available, try again later');
this.checked = !this.checked; // Revert toggle
}
} catch (e) {
console.error('Error toggling fly mode:', e);
this.checked = !this.checked; // Revert toggle
}
};
// Spectator mode toggle
document.getElementById('spectator-toggle').onchange = function() {
try {
const success = window.toggleSpectatorMode(this.checked);
if (!success) {
this.checked = !this.checked; // Revert if failed
}
} catch (e) {
console.error('Error toggling spectator mode:', e);
this.checked = !this.checked; // Revert toggle
}
};
// Make GUI draggable
let isDragging = false;
let dragOffset = { x: 0, y: 0 };
header.onmousedown = function(e) {
isDragging = true;
dragOffset.x = e.clientX - gui.offsetLeft;
dragOffset.y = e.clientY - gui.offsetTop;
};
document.onmousemove = function(e) {
if (isDragging) {
gui.style.left = (e.clientX - dragOffset.x) + 'px';
gui.style.top = (e.clientY - dragOffset.y) + 'px';
gui.style.right = 'auto';
}
};
document.onmouseup = function() {
isDragging = false;
};
console.log('Cheat GUI created successfully');
}
// Global function to apply weapon modifications
window.applyWeaponMods = function(slotIndex) {
try {
if (!window.getPlayer) {
console.error('getPlayer function not available');
return;
}
const player = window.getPlayer();
if (!player) {
console.error('Player is null, make sure you are in game');
return;
}
// Check if slot exists and has weapon data
if (!player.tb || !player.tb.b || !player.tb.b[slotIndex]) {
console.error('Invalid slot or player inventory not found');
return;
}
if (!player.tb.b[slotIndex].c) {
console.error('Weapon data not found in slot', slotIndex);
return;
}
// Get values from inputs
const fireRate = parseInt(document.getElementById(`fire-rate-${slotIndex}`).value);
const projectiles = parseInt(document.getElementById(`projectiles-${slotIndex}`).value);
const speed = parseFloat(document.getElementById(`speed-${slotIndex}`).value);
const infiniteAmmo = document.getElementById(`infinite-ammo-${slotIndex}`).checked;
const autoFire = document.getElementById(`auto-fire-${slotIndex}`).checked;
const knockback = parseFloat(document.getElementById(`knockback-${slotIndex}`).value);
const spread = parseFloat(document.getElementById(`spread-${slotIndex}`).value);
const entityType = document.getElementById(`entity-type-${slotIndex}`).value;
// Apply modifications directly using getPlayer() (get fresh reference each time)
window.getPlayer().tb.b[slotIndex].c.w = fireRate;
window.getPlayer().tb.b[slotIndex].c.e = projectiles;
window.getPlayer().tb.b[slotIndex].c.G = speed;
window.getPlayer().tb.b[slotIndex].c.R = !infiniteAmmo;
window.getPlayer().tb.b[slotIndex].c.t = autoFire;
window.getPlayer().tb.b[slotIndex].c.a = knockback;
window.getPlayer().tb.b[slotIndex].c.j = spread;
window.getPlayer().tb.b[slotIndex].c.f = entityType;
// Save settings for respawn
playerSettings.weaponMods[slotIndex] = {
fireRate,
projectiles,
speed,
infiniteAmmo,
autoFire,
knockback,
spread,
entityType
};
console.log(`Applied modifications to slot ${slotIndex + 1}:`, {
fireRate,
projectiles,
speed,
infiniteAmmo,
autoFire,
knockback,
spread,
entityType
});
} catch (e) {
console.error('Error applying weapon modifications:', e);
}
};
// Function to refresh inventory display
function refreshInventory() {
try {
if (!window.getPlayer) {
console.error('getPlayer function not available');
return;
}
const player = window.getPlayer();
if (!player) {
console.error('Player is null, make sure you are in game');
return;
}
if (!player.tb || !player.tb.b) {
console.error('Player inventory not found');
return;
}
const inventorySlotsContainer = document.getElementById('inventory-slots-container');
if (!inventorySlotsContainer) {
console.error('Inventory slots container not found');
return;
}
// Clear previous inventory display
inventorySlotsContainer.innerHTML = '';
// Check for items in all slots (not just the first 9)
const maxSlots = player.tb.b.length;
let hasItems = false;
for (let i = 0; i < maxSlots; i++) {
// Get fresh player reference for each slot
const currentPlayer = window.getPlayer();
if (currentPlayer && currentPlayer.tb && currentPlayer.tb.b &&
currentPlayer.tb.b[i] && currentPlayer.tb.b[i].c &&
currentPlayer.tb.b[i].c.H) {
hasItems = true;
const itemName = currentPlayer.tb.b[i].c.H;
const currentEntityType = currentPlayer.tb.b[i].c.f || "Bullet";
// Create slot div
const slotDiv = document.createElement('div');
slotDiv.style.cssText = `
border: 1px solid #555;
margin-bottom: 10px;
padding: 8px;
border-radius: 4px;
background: rgba(50, 50, 50, 0.6);
`;
// Create entity type dropdown options
let entityOptions = '';
entityTypes.forEach(entity => {
const selected = entity === currentEntityType ? 'selected' : '';
entityOptions += `<option value="${entity}" ${selected}>${entity}</option>`;
});
slotDiv.innerHTML = `
<div style="margin-bottom: 5px;">
<strong>Slot ${i + 1}: <span id="item-name-${i}">${itemName}</span></strong>
</div>
<div style="margin-bottom: 10px;">
<label>Entity Type:
<select id="entity-type-${i}" style="width: 150px; margin-left: 5px;">
${entityOptions}
</select>
</label>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5px; margin-bottom: 5px;">
<label>Fire Rate (ms):
<input type="number" id="fire-rate-${i}" value="${currentPlayer.tb.b[i].c.w || 100}" min="1" style="width: 60px; margin-left: 5px;">
</label>
<label>Projectiles:
<input type="number" id="projectiles-${i}" value="${currentPlayer.tb.b[i].c.e || 1}" min="1" style="width: 60px; margin-left: 5px;">
</label>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5px; margin-bottom: 5px;">
<label>Speed Multiplier:
<input type="number" id="speed-${i}" value="${currentPlayer.tb.b[i].c.G || 1}" min="0.1" step="0.1" style="width: 60px; margin-left: 5px;">
</label>
<div>
<label style="display: flex; align-items: center;">
<input type="checkbox" id="infinite-ammo-${i}" ${currentPlayer.tb.b[i].c.R === false ? 'checked' : ''} style="margin-right: 5px;">
Infinite Ammo
</label>
</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5px; margin-bottom: 5px;">
<label>Knockback (Recoil):
<input type="number" id="knockback-${i}" value="${currentPlayer.tb.b[i].c.a || 1}" min="0" step="0.1" style="width: 60px; margin-left: 5px;">
</label>
<label>Spread:
<input type="number" id="spread-${i}" value="${currentPlayer.tb.b[i].c.j || 0}" min="0" step="0.1" style="width: 60px; margin-left: 5px;">
</label>
</div>
<div style="margin-bottom: 5px;">
<label style="display: flex; align-items: center;">
<input type="checkbox" id="auto-fire-${i}" ${currentPlayer.tb.b[i].c.t ? 'checked' : ''} style="margin-right: 5px;">
Auto Fire
</label>
</div>
<button onclick="applyWeaponMods(${i})" style="background: #4CAF50; color: white; border: none; padding: 4px 8px; cursor: pointer; border-radius: 3px; width: 100%;">
Apply Modifications
</button>
`;
inventorySlotsContainer.appendChild(slotDiv);
}
}
if (!hasItems) {
inventorySlotsContainer.innerHTML = '<div style="color: #999; text-align: center; padding: 10px;">No items in inventory</div>';
}
} catch (e) {
console.error('Error refreshing inventory:', e);
}
}
// Try to find _xg immediately
if (!findAndProxyXg()) {
// If not found, keep trying every second
const interval = setInterval(() => {
if (findAndProxyXg()) {
clearInterval(interval);
}
}, 1000);
}
console.log('Game Cheat Script loaded');
})();