这篇文章主要是分享和记录我通过pyautogui、JavaScript、F12开发者工具实现梅尔沃放置(Melvor Idle)这个游戏的一些辅助功能(战斗时自动舔包、自动收菜、修改游戏数据)。小声叭叭:都怪EPIC在12月22日送的这个游戏,害得我之前天天盯着我的角色去砍奶牛,浪费了我好多刷视频的时间。。。
1、下面代码用来输出鼠标在在主显示器中的(x, y)坐标
import pyautogui as pag
while True:
print(pag.position())
pag.sleep(0.3)
2、到游戏页面,把鼠标放在“拾取所有”按钮上,稍微停留一会获取到坐标(1782, 707)
3、切换到游戏页面,并在IDLE输入,每隔60秒会自动点一次主屏幕的该坐标(1782, 707):
while True:
pag.click(1782, 707)
pag.sleep(60)
1、事先截图保存按钮的图片,我放在该文件夹下“C:\Users\10479\Pictures\Screenshots”
2、在IDLE输入以下代码,每隔60秒会自动点一次该图片的中心点在主屏幕的坐标:
def f():
try:
x, y = pag.locateCenterOnScreen(r"C:\Users\10479\Pictures\Screenshots\屏幕截图 2024-01-10 203751.png", grayscale=True)
except pag.ImageNotFoundException:
print("未找到指定图片在主屏幕的坐标")
else:
while True:
pag.click(x, y)
pag.sleep(60)
3、切换到游戏页面,并在IDLE输入f(),运行脚本,注意不要将“拾取所有”按钮遮住
通过手动定位和图片定位,容易受到其他因素影响。比如,界面大小和位置、其他程序的弹窗、图片识别的准确度等等。于是改用JavaScript和油猴插件。
1、使用右键、快捷键或直接点击的方式定位“拾取所有”按钮元素
右键 | F12-点击获取元素按钮 或 直接使用快捷键Ctrl + shift + C |
![]() |
![]() |
2、复制该元素的CSS选择器
3、在F12开发者工具中元素页面,按Ctrl + F打开搜索框,粘贴刚复制的css选择器(#combat-loot > div > div > div > div:nth-child(2) > h5 > button)能够唯一定位该按钮,同时该按钮高亮显示
4、来到F12开发者工具控制台页面,输入。可以看见掉落的物品全都拾取了。
// 输出该元素
document.querySelector("#combat-loot > div > div > div > div:nth-child(2) > h5 > button")
// 点击该元素
document.querySelector("#combat-loot > div > div > div > div:nth-child(2) > h5 > button").click()
5、在油猴插件新建脚本
6、修改脚本,设置定时器1000毫秒执行一次点击“拾取所有”按钮的操作,修改完按Ctrl + S保存
// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 2024-01-10
// @description try to take over the world!
// @author Lerdo
// @match https://melvoridle.com/index_game.php
// @icon https://www.google.com/s2/favicons?sz=64&domain=melvoridle.com
// @grant none
// ==/UserScript==
(function () {
'use strict';
var t1 = setInterval(()=>{
autoLoot()
}, 1000)
function autoLoot() {
// document.querySelector("lang-string[lang-id='COMBAT_MISC_46']").parentElement.click()
document.querySelector('#combat-loot > div > div > div > div:nth-child(2) > h5 > button').click()
}
})();
7、勾选并启用刚刚编辑的脚本:New Userscript
8、F5刷新界面,重新进入游戏,查看到脚本成功执行,实际游戏界面会自动舔包,不在战斗页面也可以自动舔包
懒得写了直接上代码:
(function () {
'use strict';
var t1 = setInterval(()=>{
autoLoot()
oneKeyHarvest()
}, 1000)
function autoLoot() {
document.querySelector("lang-string[lang-id='COMBAT_MISC_46']").parentElement.click()
}
function oneKeyHarvest() {
// 1. 检查到农务在闪烁(检查到闪烁的li数量>0)
if (document.querySelectorAll('div[class="content-side content-side-full pt-1"] > ul > li > li[class="nav-main-item glow-animation"]').length) {
// 2. 农作物、草药、树木全部尝试收获一遍
// 2.1 更新农作物的farming-plot(每个种菜格子)并收获,点击a标签会触发更新农作物类farming-plot
// farming-category-button:nth-child(1) 索引从1开始而不是0,表示第1个farming-category-button
document.querySelector('div[id="farming-category-container"] > farming-category-button:nth-child(1) > a').click()
// farming-plot-container > 已解锁且不是d-done类(d-done不显示)的farming-plot > div > 第4个div > 第1个p > 不是d-done类(d-done不显示)的button
document.querySelectorAll('#farming-plot-container>farming-plot[class="col-6 col-xl-3"]>div>div:nth-child(4)>p:first-of-type>button[class="btn btn-lg btn-success mr-1"]').forEach((item) => {
item.click()
})
// 2.2 更新草药的farming-plot(每个种菜格子)并收获,点击a标签会触发更新草药类farming-plot
// farming-category-button:nth-child(2) 表示第2个farming-category-button
document.querySelector('div[id="farming-category-container"]>farming-category-button:nth-child(2)>a').click()
document.querySelectorAll('#farming-plot-container>farming-plot[class="col-6 col-xl-3"]>div>div:nth-child(4)>p:first-of-type>button[class="btn btn-lg btn-success mr-1"]').forEach((item) => {
item.click()
})
// 2.3 更新树木的farming-plot(每个种菜格子)并收获,点击a标签会触发更新树木类farming-plot
// farming-category-button:nth-child(3) 表示第3个farming-category-button
document.querySelector('div[id="farming-category-container"]>farming-category-button:nth-child(3)>a').click()
document.querySelectorAll('#farming-plot-container>farming-plot[class="col-6 col-xl-3"]>div>div:nth-child(4)>p:first-of-type>button[class="btn btn-lg btn-success mr-1"]').forEach((item) => {
item.click()
})
}
}
})();
找的流程太繁琐,懒得写了,直接上控制台js代码。建议备份存档
添加1金币 | game.gp.add(1) |
删除1金币 |
game.gp.remove(1) |
添加1个屠杀者硬币 |
game.slayerCoins.add(1) |
添加1点祝祭点 |
game.combat.player.addPrayerPoints(1) |
设置已装备的武器攻击周期为25ms |
game.combat.player.equipmentSets.forEach((equipmenSet) => {if (equipmenSet.equipment.slots.Weapon.item.equipmentStats.length > 0 ) {if (equipmenSet.equipment.slots.Weapon.item.equipmentStats[0].key === "attackSpeed") {equipmenSet.equipment.slots.Weapon.item.equipmentStats[0].value = 25}}}) |
设置所有武器攻击周期为25ms | game.items.weapons.registeredObjects.forEach((i) => {i.equipmentStats[0].value = 25}) |
设置怪物重生时间为10ms |
game.combat.player.baseSpawnInterval = 10 |
设置攻击生命偷取为2000%,怪物也会获得生命偷取 |
game.combat.player.availableAttacks[0].attack.lifesteal = 2000 |
设置当前近战风格经验倍率100,默认为4 |
game.combat.player.attackStyles.melee.experienceGain[0].ratio = 100 |
设置当前远程风格经验倍率100,默认为4 |
game.combat.player.attackStyles.ranged.experienceGain[0].ratio = 100 |
设置当前魔法风格经验倍率100,默认为4 |
game.combat.player.attackStyles.magic.experienceGain[0].ratio = 100 |
设置标准魔法符文消耗为0 |
game.standardSpells.registeredObjects.forEach((i) => {i.runesRequired.forEach((j) => {j.quantity = 0}); if (i.hasOwnProperty("runesRequiredAlt")) {i.runesRequiredAlt.forEach((j) => {j.quantity = 0})}}) |
设置古代魔法符文消耗为0 | game.ancientSpells.registeredObjects.forEach((i) => {i.runesRequired.forEach((j) => {j.quantity = 0})}) |
设置诅咒魔法符文消耗为0 | game.curseSpells.registeredObjects.forEach((i) => {i.runesRequired.forEach((j) => {j.quantity = 0})}) |
设置光环咒语符文消耗为0 | game.auroraSpells.registeredObjects.forEach((i) => {i.runesRequired.forEach((j) => {j.quantity = 0})}) |
添加1000的城镇技能经验 |
game.township._xp += 1000 |
添加1食物(更新后有效) |
game.township.resources["registeredObjects"].get("melvorF:Food").amount = 1 |
添加1木材(更新后有效) |
game.township.resources["registeredObjects"].get("melvorF:Wood").amount = 1 |
添加1石材(更新后有效) |
game.township.resources["registeredObjects"].get("melvorF:Stone").amount = 1 |
添加1矿石(更新后有效) |
game.township.resources["registeredObjects"].get("melvorF:Ore").amount = 1 |
添加1煤炭(更新后有效) |
game.township.resources["registeredObjects"].get("melvorF:Coal").amount = 1 |
添加1矿石锭(更新后有效) |
game.township.resources["registeredObjects"].get("melvorF:Bar").amount = 1 |
添加1草药(更新后有效) |
game.township.resources["registeredObjects"].get("melvorF:Herbs").amount = 1 |
添加1符文精华(更新后有效) |
game.township.resources["registeredObjects"].get("melvorF:Rune_Essence").amount = 1 |
添加1皮革(更新后有效) |
game.township.resources["registeredObjects"].get("melvorF:Leather").amount = 1 |
添加1药水(更新后有效) |
game.township.resources["registeredObjects"].get("melvorF:Potions").amount = 1 |
添加1板材(更新后有效) |
game.township.resources["registeredObjects"].get("melvorF:Planks").amount = 1 |
添加1服装(更新后有效) |
game.township.resources["registeredObjects"].get("melvorF:Clothing").amount = 1 |
所有建筑花费设置为0 | game.township.buildings.registeredObjects.forEach((i) => {i.costs.forEach((j) => {j.forEach((k) => {k.quantity = 0})})}) |
添加1000的伐木技能经验 |
game.woodcutting._xp += 1000 |
添加1000的伐木技能精通池经验 |
game.woodcutting._masteryPoolXP += 1000 |
设置所有树木的伐木间隔为10ticks | game.woodcutting.actions.registeredObjects.forEach((i) => {i.baseInterval = 10}) |
鸟巢掉落率增加100% | game.modifiers.increasedBirdNestDropRate += 100 |
添加1000的钓鱼技能经验 |
game.fishing._xp += 1000 |
添加1000的钓鱼技能精通池经验 |
game.fishing._masteryPoolXP += 1000 |
设置所有鱼的钓鱼间隔为10ticks | game.fishing.actions.registeredObjects.forEach((i) => {i.baseMaxInterval = 10; i.baseMinInterval = 10;}) |
设置所有钓鱼区域渔获率60%、垃圾掉率1%、特殊掉率39% | game.fishing.areas.registeredObjects.forEach((i) => {i.fishChance = 60; i.junkChance = 1; i.specialChance = 39}) |
设置当前钓鱼区域渔获率10%、垃圾钓率0%、特殊钓率90% | {game.fishing.activeFishingArea.fishChance = 10; game.fishing.activeFishingArea.junkChance = 0; game.fishing.activeFishingArea.specialChance = 90;} |
设置钓鱼获得各种特殊渔获的权重相同 | {game.fishing.specialItems.totalWeight = 0; game.fishing.specialItems.drops.forEach((i) => {i.weight = 1; game.fishing.specialItems.totalWeight += 1})} |
设置扒窃基础间隔为250ms |
game.thieving.baseInterval = 250 |
设置眩晕基础时长为250ms |
game.thieving.baseStunInterval = 250 |
设置扒窃到物品的几率100% |
game.thieving.itemChance = 100 |
设置所有扒窃NPC感知为1 | game.thieving.actions.registeredObjects.forEach((item) => {item.perception = 1}) |
设置扒窃到的物品数量为原来的10倍 | {ratio = 10; game.thieving.actions.registeredObjects.forEach((i) => {i.lootTable.drops.forEach((j) => {j.maxQuantity *= ratio; j.minQuantity *= ratio})})} |
设置宝箱类物品开启物品数量为原来10倍 | game.items.openables.registeredObjects.forEach((i) => {ratio = 10; i.dropTable.drops.forEach((j) => {j.maxQuantity *= ratio; j.minQuantity *= ratio})}) |
设置宝箱类物品,开启物品概率相同 | game.items.openables.registeredObjects.forEach((i) => {i.dropTable.totalWeight = 0; i.dropTable.drops.forEach((j) => {j.weight = 1; i.dropTable.totalWeight += 1})}) |