// ==UserScript== // @name wsmud_Raid // @namespace cqv // @version 0.1.8 // @date 23/12/2018 // @modified 24/12/2018 // @homepage https://greasyfork.org/zh-CN/scripts/375851 // @description 武神传说 MUD // @author Bob.cn // @match http://game.wsmud.com/* // @match http://www.wsmud.com/* // @run-at document-end // @grant unsafeWindow // @grant GM_getValue // @grant GM_setValue // @downloadURL none // ==/UserScript== (function () { 'use strict'; var WG = unsafeWindow.WG; var messageAppend = undefined; var messageClear = undefined; var Role = { id: undefined, hp: 0, maxHp: 0, mp: 0, maxMp: 0, status: [], equipments: [], init: function() { WG.add_hook("login", function(data) { Role.id = data.id; Role.status = []; }); Role._monitorHpMp(); Role._monitorStatus(); Role._monitorEquipments(); Role._monitorSkillCD(); }, hasStatus: function(s) { return Role.status.indexOf(s) != -1; }, isFree: function() { return !Role.hasStatus("busy") && !Role.hasStatus("faint"); }, renew: function(callback) { if (!Role.isFree) { window.setTimeout(function() { Role.renew(callback) }, 2000); return; } switch (Role._renewStatus) { case "resting": messageAppend("正在为角色回复状态..."); WG.go("扬州城-武庙"); if (Role._renewHookIndex) WG.remove_hook(Role._renewHookIndex); Role._renewHookIndex = WG.add_hook("text", function(data) { let patt1 = new RegExp("你运功完毕,深深吸了口气,站了起来。"); let count1 = patt1.exec(data.msg); if (count1) { Role._renewStatus = "dazuo finish"; return; } let patt2 = new RegExp("你目前气血充沛,没有受到任何伤害。|你疗伤完毕,深深吸了口气,脸色看起来好了很多。"); let count2 = patt2.exec(data.msg); if (count2) { Role._renewStatus = "liaoshang finish"; return; } }); Role._renewStatus = "liaoshang doing"; WG.Send("stopstate;liaoshang"); break; case "liaoshang finish": if (Role.mp/Role.maxMp < 0.7) { Role._lastWeapon = Role.equipments[0]; Role._renewStatus = "dazuo doing"; WG.Send("stopstate;dazuo"); } break; case "liaoshang doing": case "dazuo doing": case "dazuo finish": break; } if (Role._renewStatus == "liaoshang finish" || Role._renewStatus == "dazuo finish") { if (Role._renewStatus == "liaoshang finish") { if (callback) callback(); } else if (Role._renewStatus == "dazuo finish") { window.setTimeout(function() { WG.Send("stopstate"); Role.getDressed([Role._lastWeapon]); if (callback) callback(); }, 4500); } WG.remove_hook(Role._renewHookIndex); Role._renewHookIndex = undefined; Role._renewStatus = "resting"; return; } window.setTimeout(function() { Role.renew(callback); }, 2000); }, clearBag: function(callback) { Role._clearBag(0, callback); }, getDressed: function(equipments) { for (var i = equipments.length - 1; i >= 0; i--) { let e = equipments[i]; if (e == null) { WG.Send("uneq " + Role.equipments[i]); } else { WG.Send("eq " + e); } } }, hasCoolingSkill: function() { return Role._coolingSkills.length > 0; }, _renewHookIndex: undefined, _renewStatus: "resting", _coolingSkills: [], _monitorHpMp: function() { WG.add_hook(["items", "sc", "itemadd"], function(data) { switch (data.type) { case "items": if (data.items == undefined) break; for (var i = data.items.length - 1; i >= 0; i--) { let item = data.items[i] if (item.id == Role.id) { Role.hp = item.hp; Role.maxHp = item.max_hp; Role.mp = item.mp; Role.maxMp = item.max_mp; break; } } break; case "itemadd": case "sc": if (data.id != Role.id) break; if (data.hp != undefined) Role.hp = data.hp; if (data.max_hp != undefined) Role.maxHp = data.max_hp; if (data.mp != undefined) Role.mp = data.mp; if (data.max_mp != undefined) Role.maxMp = data.max_mp; break; } }); }, _monitorStatus: function() { WG.add_hook(["items", "status", "itemadd"], function(data) { switch (data.type) { case "items": if (data.items == undefined) break; for (var i = data.items.length - 1; i >= 0; i--) { let item = data.items[i]; if (item.id != Role.id) continue; Role.status = []; for (var j = item.status.length - 1; j >= 0; j--) { let s = item.status[j]; Role.status.push(s.sid); } break; } break; case "status": if (data.id != Role.id) break; if (data.action == "add") { Role.status.push(data.sid); } else if (data.action == "remove") { let index = Role.status.indexOf(data.sid); if (index == -1) return; Role.status.splice(index,1); } break; case "itemadd": if (data.id != Role.id) break; if (data.status == undefined) break; Role.status = []; for (var k = data.status.length - 1; k >= 0; k--) { let s = data.status[k]; Role.status.push(s.sid); } break; } }); }, _monitorEquipments: function() { WG.add_hook("dialog", function(data) { if (data.dialog != "pack") return; if (data.eqs != undefined) { for (var i = 0; i < data.eqs.length; i++) { let eq = data.eqs[i]; if (eq != null && eq.id != null) { Role.equipments.push(eq.id); } else { Role.equipments.push(null); } } } else if (data.uneq != undefined) { Role.equipments[data.uneq] = null; } else if (data.eq != undefined) { Role.equipments[data.eq] = data.id; } else { return; } }); }, _monitorSkillCD: function() { WG.add_hook("dispfm", function(data) { let timestamp = Date.parse(new Date()); let mark = data.id + "_" + timestamp; Role._coolingSkills.push(mark); window.setTimeout(function() { let index = Role._coolingSkills.indexOf(mark); if (index != -1) Role._coolingSkills.splice(index,1); }, data.distime); }); }, _clearBag: function(counter, callback) { if (counter == 0) WG.sell_all(); if (!WG.packup_listener) { window.setTimeout(callback, 2000); return; } if (counter > 5) { if (WG.packup_listener) WG.sell_all(); callback(); return; } window.setTimeout(function() { Role._clearBag(counter + 1, callback); }, 1000); }, }; var Config = { hpThresholdInRaid: function() { return GM_getValue(Role.id + "@hpThresholdInRaid", "50"); }, setHpThresholdInRaid: function(t) { GM_setValue(Role.id + "@hpThresholdInRaid", t); }, waitSkillCD: function() { return GM_getValue(Role.id + "@waitSkillCD", "no"); }, setWaitSkillCD: function(w) { GM_setValue(Role.id + "@waitSkillCD", w); }, }; var Raid = { /* public */ name: "副本名称", cmds: [], enemyNames: [], willStartRun: undefined, // optional: function() didEndRun: undefined, // optional: function() willStartOnceRun: undefined, // optional: function(number) didEndOnceRun: undefined, // optional: function(number) willExecuteCmd: undefined, // optional: function(lastCmd, cmd) didExecuteCmd: undefined, // optional: function(cmd) repeatRun: function() { let num = prompt("输入自动【" + Raid.name + "】副本次数,例如:\"1\"", '1'); if (num > 0) { Raid._repeatTotal = num; Raid._repeatCounter = 0; } else { return; } messageClear(); messageAppend("正在运行自动 " + Raid.name + "..."); messageAppend("* 自动副本期间会暂时关闭 自动Boss 和 自动婚宴。"); messageAppend("* 如需要立即中断,请刷新网页。"); WG.stopAllAuto(); Raid._cleanRepeatRun(); if (Raid.willStartRun) { Raid.willStartRun(); } Raid._indexes.push(Raid._monitorEnemy()); Raid._indexes.push(Raid._monitorAddEnemy()); Raid._indexes.push(Raid._monitorEnemyDie()); Raid._onceRun(); }, /* private */ _indexes: [], _repeatTotal: 1, _repeatCounter: 0, _cmdIndex: 0, // 下一条执行的命令的索引 _lastCmd: undefined, // 上一个执行的命令 _enemyIds: undefined, // 当前房间的敌人id _enemyCounter: 0, // 当前房间剩余的敌人 _liaoshangDoing: false, _onceRun: function() { Raid._cleanForOnceRun(); messageAppend("正在第 " + (Raid._repeatCounter + 1) + "/"+ Raid._repeatTotal +" 次运行自动 " + Raid.name + "..."); Role.renew(function() { window.setTimeout(function() { Role.clearBag(function() { messageAppend("元气满满,进入副本..."); if (Raid.willStartOnceRun) { Raid.willStartOnceRun(Raid._repeatCounter); } Raid._executeCmd(); }); }, 1000); }); }, _cleanRepeatRun: function() { for (var i = Raid._indexes.length - 1; i >= 0; i--) { let index = Raid._indexes[i]; WG.remove_hook(index); } Raid._indexes = []; WG.reSetAllAuto(); }, _cleanForOnceRun: function() { Raid._cmdIndex = 0; Raid._lastCmd = undefined; Raid._enemyIds = undefined; Raid._enemyCounter = 0; }, _overOnceRun: function() { if (Raid.didEndOnceRun) { Raid.didEndOnceRun(Raid._repeatCounter); } messageClear(); messageAppend("已完成第 " + (Raid._repeatCounter + 1) + "/"+ Raid._repeatTotal + " 次自动 " + Raid.name); Raid._repeatCounter += 1; if (Raid._repeatCounter < Raid._repeatTotal) { window.setTimeout(Raid._onceRun, 2000); } else { Raid._cleanRepeatRun(); if (Raid.didEndRun) { Raid.didEndRun(); } window.setTimeout(function() { WG.go("练功房"); WG.Send("stopstate;dazuo"); messageAppend("已经全部完成自动 " + Raid.name + "。"); }, 1000); } }, _executeCmd: function() { if (Raid._cmdIndex >= Raid.cmds.length) { WG.Send("cr;cr over"); Raid._overOnceRun(); return; } if (!Role.isFree()) { Raid._delayExecuteCmd(); return; } var cmd = Raid.cmds[Raid._cmdIndex]; if (Raid.willExecuteCmd) { let valid = Raid.willExecuteCmd(Raid._lastCmd, cmd); if (!valid) { Raid._delayExecuteCmd(); return; } cmd = valid; } if (Raid._enemyCounter > 0) { Raid._killEnemy(); Raid._delayExecuteCmd(); return; } if (Raid._liaoshangDoing) { if (Role.hp/Role.maxHp < 0.99) { Raid._delayExecuteCmd(); return; } else { Raid._liaoshangDoing = false; WG.Send("stopstate"); } } if (Role.hp/Role.maxHp < Config.hpThresholdInRaid()/100) { WG.Send("liaoshang"); Raid._liaoshangDoing = true; Raid._delayExecuteCmd(); return; } // #开头,表明执行完此命令将会遇到 Boss if (cmd.indexOf("#") != -1) { if (Config.waitSkillCD() == "yes") { if (Role.hasCoolingSkill()) { if (!Raid._waitingSkillCD) { messageAppend("前方高能,等待技能冷却再战..."); Raid._waitingSkillCD = true; } Raid._delayExecuteCmd(); return; } } cmd = cmd.substring(1); } Raid._waitingSkillCD = false; Raid._lastCmd = cmd; // @开头,虚命令,不真正执行 if (cmd.indexOf("@") == -1) { console.log("执行命令:" + cmd); WG.Send(cmd); } Raid._cmdIndex += 1; Raid._delayExecuteCmd(); if (Raid.didExecuteCmd) { Raid.didExecuteCmd(cmd); } }, _delayExecuteCmd: function() { window.setTimeout(Raid._executeCmd, 2000); }, _killEnemy: function() { if (Raid._enemyIds == undefined) { return } for (var i = 0; i < Raid._enemyIds.length; i++) { let enemyId = Raid._enemyIds[i]; WG.Send("kill " + enemyId); } }, _monitorEnemy: function() { let index = WG.add_hook("items", function(data) { if (data.items == undefined) return; var enemyIds = []; for (var i = 0; i < data.items.length; i++) { let item = data.items[i]; if (item.id == undefined || item.name == undefined) continue; if (Raid.enemyNames.indexOf(item.name) >= 0) { enemyIds.push(item.id); } } Raid._enemyIds = enemyIds; Raid._enemyCounter = enemyIds.length; }); return index; }, _monitorAddEnemy: function() { let index = WG.add_hook("itemadd", function(data) { if (data.name == undefined) return; if (Raid.enemyNames.indexOf(data.name) == -1) return; if (Raid._enemyIds) { Raid._enemyIds.push(data.id); Raid._enemyCounter += 1; } else { Raid._enemyIds = [data.id]; Raid._enemyCounter = 1; } }); return index; }, _monitorEnemyDie: function() { let index = WG.add_hook("sc", function(data) { if (data.id == undefined || !Raid._enemyIds) return; if (WG.inArray(data.id, Raid._enemyIds) && data.hp == 0) { Raid._enemyCounter -= 1; } }); return index; }, }; var ToRaid = { menu :function(){ messageClear(); var html = `