您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Combines challenges and masteries inside the game inventory with separate buttons.
// ==UserScript== // @name Challenges and Masteries Inside Inventory // @namespace http://tampermonkey.net/ // @version 1.4 // @description Combines challenges and masteries inside the game inventory with separate buttons. // @author Lucky11 // @match https://fairview.deadfrontier.com/onlinezombiemmo/DF3D/DF3D_InventoryPage.php?page=31* // @grant unsafeWindow // @grant GM_xmlhttpRequest // @license MIT // ==/UserScript== (function() { 'use strict'; // Inject challenges CSS const style = document.createElement('style'); style.type = 'text/css'; style.textContent = ` body { background-color: #1a1a1a; /* Dark background */ color: #e6e6e6; /* Light text color */ } #pageLogo { color: red; font-size: 14pt; } #invController { padding-top: 20px; overflow-y: auto; } .challengeContainer { border: 1px solid #555; margin: 10px; background-color: rgba(0, 0, 0, 0.6); padding-bottom: 8px; text-align: left; cursor: pointer; } .challengeContainer .challengeNamefield { position: relative; border-bottom: 1px solid darkgrey; background-image: linear-gradient(black, black, rgba(50, 50, 50, 0.5)); padding: 3px 5px; font-weight: 900; color: #E6CC4D; } .challengeContainer .challengeDescription { padding: 3px 5px; border-bottom: 1px solid darkgrey; } .challengeContainer .challengeHidden { max-height: 0; overflow-y: hidden; transition: max-height 0.1s; } .challengeContainer .challengeComplete { position: absolute; text-align: center; top: 0; left: 0; right: 0; color: #00ff00; font-size: 12pt; } .challengeContainer.challengeOpened .challengeHidden { max-height: 500px; } .challengeContainer .challengeNamefield::before { content: "\\25b2 "; } .challengeContainer.challengeOpened .challengeNamefield::before { content: "\\25bc "; } .challengeContainer .challengeRewards { float: right; border-left: 1px solid red; width: 160px; } .challengeContainer .challengeRewards .item_rewards { border-top: 1px solid #660000; } .challengeContainer .challengeRewards .autoPad { padding: 5px 10px; } .challengeContainer .challengeRewards .fakeItem { border-bottom: 1px solid #660000; padding: 5px 10px; } .challengeContainer .challengeObjectives { margin-right: 160px; } .challengeContainer.clanChallenge .challengeRewards { width: 200px; } .challengeContainer.clanChallenge .challengeRewards { text-align: center; } .challengeContainer.clanChallenge .challengeObjectives { margin-right: 200px; } .challengeContainer .challengeObjectives .challengeObjective { border: 1px solid #660000; border-right: 1px solid red; background-color: black; } .challengeContainer .challengeObjectives .objectiveProgress { background-color: #128800; white-space: nowrap; } .challengeContainer .challengeObjectives .objectiveProgress .pads { padding: 5px 10px; } .challengeContainer .challengeProgress { background-color: black; text-align: center; } .challengeContainer .challengeBar { background-color: #128800; white-space: nowrap; } `; document.head.appendChild(style); // Create overlay elements const overlay = document.createElement('div'); overlay.style.position = 'fixed'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'; overlay.style.zIndex = '9999'; overlay.style.display = 'none'; overlay.style.justifyContent = 'center'; overlay.style.alignItems = 'center'; const overlayContent = document.createElement('div'); overlayContent.style.backgroundColor = 'rgba(50, 50, 50, 0.9)'; // Dark background overlayContent.style.padding = '20px'; overlayContent.style.borderRadius = '8px'; overlayContent.style.maxWidth = '600px'; overlayContent.style.width = '90%'; overlayContent.style.overflowY = 'auto'; overlayContent.style.maxHeight = '80%'; const closeButton = document.createElement('button'); closeButton.innerText = '✖'; // Change text to match the style closeButton.style.marginLeft = '550px'; closeButton.style.fontFamily = 'Downcome'; // Match font family //closeButton.style.color = 'rgb(153, 0, 0)'; // Match text color closeButton.style.fontSize = '20pt'; // Match font size closeButton.style.backgroundColor = 'transparent'; // Make background transparent closeButton.style.border = 'none'; // Remove border closeButton.style.cursor = 'pointer'; // Pointer cursor closeButton.style.marginBottom = '5px'; // Maintain margin closeButton.addEventListener('click', () => { overlay.style.display = 'none'; }); overlayContent.appendChild(closeButton); overlay.appendChild(overlayContent); document.body.appendChild(overlay); // Event listener to close the overlay when clicking outside of it overlay.addEventListener('click', (event) => { if (event.target === overlay) { overlay.style.display = 'none'; // Hide the overlay } }); // Function to serialize the request parameters function serializeObject(obj) { return Object.keys(obj).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])).join('&'); } // Function to make the POST request function makeRequest() { const requestUrl = "https://fairview.deadfrontier.com/onlinezombiemmo/hotrods/load_challenge.php"; const playerLevel = unsafeWindow.userVars["DFSTATS_df_level"]; // Get player's level const requestParams = { userID: unsafeWindow.userVars["userID"], password: unsafeWindow.userVars["password"], sc: unsafeWindow.userVars["sc"], action: "get" }; // Calculate the hash const payload = serializeObject(requestParams); const hash = unsafeWindow.hash(payload); const fullPayload = "hash=" + hash + "&" + payload; // Send the POST request GM_xmlhttpRequest({ method: "POST", url: requestUrl, headers: { "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "LuckyScript" // Replace with your desired User-Agent }, data: fullPayload, onload: function(response) { //console.log('Response:', response.responseText); displayChallenges(response.responseText); }, onerror: function(error) { console.error('Error:', error); alert('Error sending POST request.'); } }); } // Function to display challenges in the overlay function displayChallenges(data) { const challenges = parseChallengeData(data); overlayContent.innerHTML = ''; // Clear existing content overlayContent.appendChild(closeButton); // Re-add close button if (challenges.length === 0) { overlayContent.innerHTML = "<p style='color: white;'>No challenges available.</p>"; overlay.style.display = 'flex'; // Show the overlay return; } challenges.forEach(challenge => { const challengeContainer = document.createElement("div"); challengeContainer.classList.add("challengeContainer"); const nameField = document.createElement("div"); nameField.classList.add("challengeNamefield"); nameField.innerHTML = `${challenge.name}<span style="float: right;">Ends: ${challenge.endTime}</span>`; challengeContainer.appendChild(nameField); const description = document.createElement("div"); description.classList.add("challengeDescription"); description.textContent = challenge.description; challengeContainer.appendChild(description); const rewards = document.createElement("div"); rewards.classList.add("challengeRewards"); let rewardsHTML = `<div class='autoPad'> <div class='cashhack redElements' style='position: relative;' data-cash='Rewards'>Rewards</div>`; if (challenge.rewardCash > 0) { rewardsHTML += `<div class='cashhack' style='position: relative;' data-cash='Cash: ${parseInt(challenge.rewardCash).toLocaleString()}'>Cash: ${parseInt(challenge.rewardCash).toLocaleString()}</div>`; } if (challenge.rewardExp > 0) { rewardsHTML += `<div class='credits cashhack' style='position: relative;' data-cash='Exp: ${parseInt(challenge.rewardExp).toLocaleString()}'>Exp: ${parseInt(challenge.rewardExp).toLocaleString()}</div>`; } rewardsHTML += `</div>`; rewards.innerHTML = rewardsHTML; challengeContainer.appendChild(rewards); const objectives = document.createElement("div"); objectives.classList.add("challengeObjectives"); challenge.objectives.forEach(obj => { const objective = document.createElement("div"); objective.classList.add("challengeObjective"); objective.innerHTML = `<div class='objectiveProgress' style='width: ${obj.progress}%;'> <div class='pads'>${obj.name}: ${obj.current}/${obj.target}</div> </div>`; objectives.appendChild(objective); }); challengeContainer.appendChild(objectives); const progress = document.createElement("div"); progress.classList.add("challengeProgress"); //progress.innerHTML = `<div class='challengeBar' style='width: ${challenge.progress}%;'>${challenge.progress}%</div>`; // Determine margin-top based on conditions let marginTopStyle = "3px"; // Default margin const hasCash = challenge.rewardCash > 0; const hasExp = challenge.rewardExp > 0; const totalObjectives = challenge.objectives.length; if (hasCash && hasExp && totalObjectives === 1) { marginTopStyle = "34px"; } else if (!hasCash && hasExp && totalObjectives === 1) { marginTopStyle = "16px"; } progress.innerHTML = ` <div class='challengeProgress' style='margin-top: ${marginTopStyle};'> <div class='challengeBar' style='width: ${challenge.progress}%;'>${challenge.progress}%</div> </div> `; challengeContainer.appendChild(progress); overlayContent.appendChild(challengeContainer); }); overlay.style.display = 'flex'; // Show the overlay } // Function to parse challenge data from the response function parseChallengeData(data) { const challenges = []; const parsedData = new URLSearchParams(data); const maxChallenges = parseInt(parsedData.get('max_challenges')) || 0; const playerLevel = unsafeWindow.userVars["DFSTATS_df_level"]; // Get player's level for (let i = 0; i < maxChallenges; i++) { const minLevel = parseInt(parsedData.get(`challenge_${i}_min_level`)) || 0; const maxLevel = parseInt(parsedData.get(`challenge_${i}_max_level`)) || 0; // Check if the player's level is within the challenge's level range if (playerLevel < minLevel || playerLevel > maxLevel) { continue; // Skip this challenge if the player's level is not appropriate } let rewardExp = parseInt(parsedData.get(`challenge_${i}_reward_exp`)) || 0; // Get rewardExp and ensure it's a number // Check if the user is a gold member and double the rewardExp if true if (unsafeWindow.userVars['DFSTATS_df_goldmember'] === '1') { rewardExp *= 2; // Double the experience reward for gold members } rewardExp *= playerLevel; // Now multiply by player level const challenge = { name: parsedData.get(`challenge_${i}_name`), description: parsedData.get(`challenge_${i}_description`), endTime: new Date(new Date(0).setUTCSeconds(parseInt(parsedData.get(`challenge_${i}_end_time`)) + 1200000000)).toLocaleString(), rewardCash: parsedData.get(`challenge_${i}_reward_cash`), rewardExp: rewardExp, objectives: [], progress: 0 }; const totalObjectives = parseInt(parsedData.get(`challenge_${i}_objectives`)) || 0; let totalProgress = 0; // To accumulate total progress for the challenge let totalTargetScore = 0; // To accumulate total target score for the challenge let totalPlayerScore = 0; // To accumulate player's score for the challenge for (let j = 1; j <= totalObjectives; j++) { const targetKey = `challenge_${i}_objectives_${j}_target`; const playerScoreKey = `challenge_${i}_objective_${j}_player_score`; const objectiveNameKey = `challenge_${i}_objectives_${j}_name`; const target = parseInt(parsedData.get(targetKey)) || 0; // Correctly retrieve target const playerScore = parseInt(parsedData.get(playerScoreKey)) || 0; const objectiveName = parsedData.get(objectiveNameKey); // Calculate progress for the objective const progress = (target > 0) ? Math.min((playerScore / target) * 100, 100) : 0; challenge.objectives.push({ name: objectiveName, target: target, // Ensure target is set correctly current: playerScore, progress: progress // Store the calculated progress }); // Accumulate total target and player scores totalTargetScore += target; totalPlayerScore += playerScore; totalProgress += progress; // Accumulate individual progress } // Calculate overall progress as the average of individual objective progress const overallProgress = (totalObjectives > 0) ? (totalProgress / totalObjectives) : 0; // Set the challenge progress based on overall progress challenge.progress = Math.min(100, parseFloat(overallProgress.toFixed(2))); // Uncomment for debugging // console.log("Specific Objective Progress: ", specificObjectiveProgress); // console.log("Overall Progress: ", overallProgress); // console.log("Challenge Progress: ", challenge.progress); challenges.push(challenge); } return challenges; } // Create the button const button = document.createElement('button'); button.innerText = 'Show Current Challenges'; button.style.position = 'absolute'; //<button class="opElem" style="left: 20px; bottom: 86px;">SlotLock?</button> //button.style.backgroundColor = '#4CAF50'; // Green button button.style.left = '20px'; button.style.bottom = '110px'; button.style.cursor = 'pointer'; //========================================================= // =================== Masteries Part =================== //========================================================= // Function to fetch and apply CSS styles function loadStylesMastery() { GM_xmlhttpRequest({ method: "GET", url: "https://fairview.deadfrontier.com/onlinezombiemmo/hotrods/hotrods_v9_0_11/HTML5/css/masteries.css", onload: function(response) { const style = document.createElement('style'); style.type = 'text/css'; style.textContent = response.responseText; document.head.appendChild(style); }, onerror: function(error) { console.error('Error loading CSS:', error); } }); } // Load the CSS styles loadStylesMastery(); // Create overlay elements const overlayM = document.createElement('div'); overlayM.style.position = 'fixed'; overlayM.style.top = '0'; overlayM.style.left = '0'; overlayM.style.width = '100%'; overlayM.style.height = '100%'; overlayM.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'; overlayM.style.zIndex = '9999'; overlayM.style.display = 'none'; overlayM.style.justifyContent = 'center'; overlayM.style.alignItems = 'center'; const overlayContentM = document.createElement('div'); overlayContentM.style.backgroundColor = 'rgba(50, 50, 50, 0.9)'; overlayContentM.style.padding = '20px'; overlayContentM.style.borderRadius = '8px'; overlayContentM.style.maxWidth = '800px'; // Set a fixed width overlayContentM.style.width = '90%'; overlayContentM.style.overflowY = 'auto'; overlayContentM.style.maxHeight = '80%'; overlayContentM.style.display = 'flex'; // Use flexbox overlayContentM.style.flexWrap = 'wrap'; // Allow wrapping of mastery containers overlayContentM.style.gap = '5px'; // Add space between containers // Close button const closeButtonM = document.createElement('button'); closeButtonM.innerText = '✖'; closeButtonM.style.marginLeft = '756.5px'; closeButtonM.style.fontSize = '20pt'; closeButtonM.style.backgroundColor = 'transparent'; closeButtonM.style.border = 'none'; closeButtonM.style.cursor = 'pointer'; closeButtonM.addEventListener('click', () => { overlayM.style.display = 'none'; }); // Append close button to overlay content overlayContentM.appendChild(closeButtonM); overlayM.appendChild(overlayContentM); document.body.appendChild(overlayM); // Event listener to close the overlay when clicking outside of it overlayM.addEventListener('click', (event) => { if (event.target === overlayM) { overlayM.style.display = 'none'; } }); // Function to serialize the request parameters function serializeObjectMastery(obj) { return Object.keys(obj).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])).join('&'); } // Function to make the POST request to load masteries function makeRequestMastery() { const requestUrl = "https://fairview.deadfrontier.com/onlinezombiemmo/hotrods/load_masteries.php"; const requestParams = { userID: unsafeWindow.userVars["userID"], password: unsafeWindow.userVars["password"], sc: unsafeWindow.userVars["sc"], action: "get" }; // Send the POST request GM_xmlhttpRequest({ method: "POST", url: requestUrl, headers: { "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "LuckyScript" // Replace with your desired User-Agent }, data: serializeObjectMastery(requestParams), onload: function(response) { displayMasteries(response.responseText); }, onerror: function(error) { console.error('Error:', error); alert('Error sending POST request.'); } }); } // Function to display masteries in the overlay function displayMasteries(data) { const masteries = parseMasteryData(data); overlayContentM.innerHTML = ''; // Clear existing content overlayContentM.appendChild(closeButtonM); // Re-add close button if (masteries.length === 0) { overlayContentM.innerHTML = "<p style='color: white;'>No masteries available.</p>"; overlayM.style.display = 'flex'; // Show the overlay return; } masteries.forEach(mastery => { const masteryContainer = document.createElement("div"); masteryContainer.classList.add("masteryContainer"); masteryContainer.style.flex = '1 1 20%'; // Allow three containers in a row masteryContainer.style.textAlign = 'center'; // Center align text const nameField = document.createElement("div"); nameField.classList.add("namefield"); nameField.textContent = mastery.name; masteryContainer.appendChild(nameField); // Add mastery icon const masteryIcon = document.createElement("img"); masteryIcon.classList.add("icon"); masteryIcon.src = `https://fairview.deadfrontier.com/onlinezombiemmo/hotrods/hotrods_v9_0_11/HTML5/images/masteries/${mastery.name}.png`; masteryContainer.appendChild(masteryIcon); const playerLevel = document.createElement("div"); playerLevel.textContent = `Level ${mastery.statLevel}`; masteryContainer.appendChild(playerLevel); const playerProgress = document.createElement("div"); playerProgress.classList.add("progress"); const nextLevel = Math.ceil(mastery.startPoint * Math.pow(mastery.scaleFactor, mastery.statLevel + 1)); const progress = mastery.statExp / nextLevel; const progressBar = document.createElement("div"); progressBar.classList.add("bar"); progressBar.style.width = (progress > 1 ? 1 : progress) * 100 + "%"; const progressText = document.createElement("div"); progressText.classList.add("pads"); progressText.textContent = `${mastery.statExp} / ${nextLevel}`; progressBar.appendChild(progressText); playerProgress.appendChild(progressBar); masteryContainer.appendChild(playerProgress); const description = document.createElement("div"); description.classList.add("description"); description.textContent = mastery.description; masteryContainer.appendChild(description); const masteryData = document.createElement("div"); masteryData.classList.add("masteryRewards"); let rewardHTML = "<div class='autoPad'>"; mastery.bonuses.forEach(bonus => { // Parse bonus scale and max as floats const bonusScale = Math.abs(parseFloat(bonus.scale)); console.log(bonusScale); const bonusMax = parseFloat(bonus.max); //let userBonusValue = bonusScale * mastery.statLevel; let userBonusValue = bonusScale * Math.abs(mastery.statLevel); userBonusValue = Math.abs(userBonusValue); // Clamp to max if max is not zero if (bonusMax !== 0 && userBonusValue > bonusMax) { userBonusValue = bonusMax; } userBonusValue = Math.abs(userBonusValue); // Format display let bonusDisplay = userBonusValue.toFixed(2) + "%"; // Check if bonus is at max (consider floating point precision) if (Math.abs(userBonusValue - bonusMax) < 0.0001 && bonusMax !== 0) { bonusDisplay += " MAX"; } else { bonusDisplay = '+' + bonusDisplay; } // Build HTML rewardHTML += `<div class='bonusType cashHack redElements' data-cash='${bonus.name}' title='${bonus.tooltip}' style='font-size: 14px; font-family: "Courier New", "Arial"; font-weight: 600;'>${bonus.name}</div>`; rewardHTML += `<div class='bonusScale' title='${bonusScale} / lvl' style='position: relative; font-size: 14px; font-family: "Courier New", "Arial"; font-weight: 600;'> <span class='cashhack greenElements' style='position: relative; font-size: 14px; font-family: "Courier New", "Arial"; font-weight: 600;' data-cash='${bonusDisplay}'>${bonusDisplay}</span><br>+${bonusScale}%/lvl </div>`; }); rewardHTML += "</div>"; // Close autoPad div masteryData.innerHTML = rewardHTML; masteryContainer.appendChild(masteryData); overlayContentM.appendChild(masteryContainer); }); overlayM.style.display = 'flex'; // Show the overlay } // Function to parse mastery data from the response function parseMasteryData(data) { const masteries = []; const parsedData = new URLSearchParams(data); const maxMasteries = parseInt(parsedData.get('max_masteries')) || 0; for (let i = 0; i < maxMasteries; i++) { const mastery = { name: parsedData.get(`mastery_${i}_name`), description: parsedData.get(`mastery_${i}_description`), startPoint: parseInt(parsedData.get(`mastery_${i}_start_point`)) || 0, scaleFactor: parseFloat(parsedData.get(`mastery_${i}_scale_factor`)) || 1, statLevel: parseInt(parsedData.get(`mastery_${i}_stat_level`)) || 0, statExp: parseInt(parsedData.get(`mastery_${i}_stat_exp`)) || 0, bonuses: [] }; const bonusCount = parseInt(parsedData.get(`mastery_${i}_bonuses`)) || 0; for (let j = 0; j < bonusCount; j++) { mastery.bonuses.push({ name: parsedData.get(`mastery_${i}_bonuses_${j}_name`), tooltip: parsedData.get(`mastery_${i}_bonuses_${j}_tooltip`), scale: parseFloat(parsedData.get(`mastery_${i}_bonuses_${j}_scale`)), max: parseFloat(parsedData.get(`mastery_${i}_bonuses_${j}_max`)), }); } masteries.push(mastery); } return masteries; } // Create the button const buttonM = document.createElement('button'); buttonM.innerText = 'Show Current Masteries'; buttonM.style.position = 'absolute'; buttonM.style.left = '20px'; buttonM.style.bottom = '130px'; buttonM.style.cursor = 'pointer'; // =================== Masteries Part =================== // Append the button to the body var invController = document.getElementById('invController'); // Select the element with ID 'invController' // Append the button to the selected element invController.appendChild(buttonM); invController.appendChild(button); // Add click event listener to the button buttonM.addEventListener('click', makeRequestMastery); // Add click event listener to the button button.addEventListener('click', makeRequest); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址