// ==UserScript==
// @name wsmud_funny
// @namespace suqing
// @version 0.1.10
// @author sq
// @match http://game.wsmud.com/*
// @match http://www.wsmud.com/*
// @homepage https://gf.qytechs.cn/zh-CN/scripts/380709
// @description WSMud three column layout UI(width:1080px) for PC, SuQing use it herself.
// @run-at document-start
// @require http://code.jquery.com/jquery-3.3.1.slim.min.js
// @grant unsafeWindow
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_getValue
// @grant GM_setClipboard
// ==/UserScript==
(function() {
'use strict';
let funny = {
scriptName: GM_info.script.name,
scriptVersion: GM_info.script.version,
scriptAuthor: GM_info.script.author,
webSocket: undefined,
onmessage_fn: undefined,
role: {
jy: 0,
qn: 0,
},
skills: {},
sleep: function(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
},
scroll: function(className) {
let a = $(`.${className}`)[0].scrollTop,
b = $(`.${className}`)[0].scrollHeight,
h = Math.ceil($(`.${className}`).height()); // 向上取整
// console.log(`scroll => scrollTop=${a} scrollHeight=${b} height=${h}`);
if (a < b - h) {
$(`.${className}`)[0].scrollTop = a + 1;
setTimeout(`funny.scroll("${className}")`, 1000/60);
}
},
// 向服务器发送消息
sendmessage: function(message) {
if (typeof message === "string") { // 1. 字符串
send(message);
} else if (message instanceof Array) { // 2. 数组
action(message);
async function action(message) {
for (const m of message) {
await funny.sleep(1000);
send(m);
}
}
}
function send(message) { // 发送
if ($("#sendmessage").attr("cmd")) {
$("#sendmessage").attr("cmd", message);
} else {
$(".container").append($(`<span id="sendmessage" cmd="${message}"><span>`));
}
$("#sendmessage").click();
}
},
// 截获到的接收的消息
onmessage: function(message) {
// 处理 data
let data = message.data || "error";
if ((data.includes("{") && data.includes("}")) || (data.includes("[") && data.includes("]"))) {
data = new Function("return " + data + ";")();
}
// 登录(不可用) & 重新连线
if (/重新连线。|欢迎登陆<HIW>武神传说<\/HIW>/.test(data)) {
funny.onmessage_fn.apply(this, arguments);
getScore();
$(".content-message pre").append(`${funny.scriptName}_${funny.scriptVersion}\n`);
async function getScore() { // 模拟点击 获取数据
$("[command=showtool]").click(); // 点击菜单
await funny.sleep(100);
$("[command=showcombat]").click(); // 点击动作
await funny.sleep(100);
funny.sendmessage("score"); // 属性 1
await funny.sleep(100);
funny.sendmessage("score2"); // 属性 2
await funny.sleep(100);
$("[command=skills]").click(); // 点击技能
await funny.sleep(100);
$(".dialog-close").click(); // 关闭窗口
};
return;
}
// 屏蔽文本
if (/.*你轻声吟道:.*/.test(data)) return;
if (/<hir>看起来.*想杀死你!<\/hir>/.test(data)) {
let array = data.split(/<hir>看起来|想杀死你!<\/hir>/);
let name = array[1];
$(".content-message pre").append(`<hir>${name} => 进入战斗!<hir>\n`);
return;
}
// {type: "room", path: "huashan/siguoya",
//name: "华山派-思过崖", desc: "这里便是华山派弟子受罚思过的地方。位于玉女峰顶,正好有一小快平地,一面是深不可测的山谷、一面是陡峭的<cmd cmd='look bi'>悬壁</cmd>,零零落落的有几快山石。", commands: []}
if (data.type === "room") {
funny.onmessage_fn.apply(this, arguments);
$(".room_desc").css("overflow", "hidden");
if (/<cmd cmd='.*'>.*<\/cmd>/.test(data.desc)) {
$(".room_desc").css("white-space", "normal");
} else {
$(".room_desc").css("white-space", "nowrap");
// $(".room_desc")[0].style.whiteSpace("nowrap");
}
return;
}
// 你对著云娣喝道:「臭贼!今日不是你死就是我活!」
//
// {type: "itemadd", id: "d62a3d9b738", name: "<hig>蒙古兵</hig> 兀颜德淏", mp: 30000, hp: 30000, …}
console.log(data);
if (data.type === "itemadd") {
if (/蒙古兵|十夫长|百夫长|千夫长|万夫长/.test(data.name)) {
if (data.id) funny.sendmessage(`kill ${data.id}`);
}
}
if (data.type === "dialog" && data.dialog === "pack") {
if (/蒙古|大宋|笠子帽/.test(data.name)) funny.sendmessage(`fenjie ${data.id}`);
}
// 经验 潜能
if (/<hig>你获得了.*点经验,.*点潜能。<\/hig>/.test(data)) {
let array = data.split(/<hig>你获得了|点经验,|点潜能。<\/hig>/);
funny.role.jy += parseInt(array[1]);
funny.role.qn += parseInt(array[2]);
$(".remove_jyqn").remove();
$(".content-message pre").append(`${data}\n`);
$(".content-message pre").append(`<span class="remove_jyqn">共计获得了${funny.role.jy}点经验,${funny.role.qn}点潜能。\n</span>`);
funny.scroll("content-message");
return;
} else if (/你从.*的尸体里拿出来.*|<hig>你获得了.*<\/hig>/.test(data)) {
$(".pickup").append(`${data}<br>`);
funny.scroll("pickup");
return;
}
// 打坐 内力
if (/你的最大内力增加了.*点。/.test(data)) {
let n = parseInt(data.toString().replace(/[^0-9]/ig, "")),
max = parseInt(funny.role.max_mp),
limit = parseInt(funny.role.limit_mp);
let time = (limit - max) / (n * 6); // X分钟 => X小时X分钟
let timeString = time < 60 ? `${parseInt(time)}分钟` : `${parseInt(time / 60)}小时${parseInt(time % 60)}分钟`;
$(".role_dazuo_time").html(timeString);
funny.onmessage_fn.apply(this, arguments);
$(".remove_dzsj").remove();
$(".content-message pre").append(`<span class="remove_dzsj">- - - - -\n当前内力: ${max}\n上限内力: ${limit}\n需要时间: ${timeString}\n- - - - -\n</span>`);
return;
}
// 状态
else if (data.type === "state" && data.state) {
funny.state = data.state;
$(".state-bar").removeClass("hide");
$(".state-bar").html(`<span class="title">${data.state}</span>`);
$("[command=stopstate]")[0].style.display = "inline";
if (data.state === "你正在练习技能") {
(async function fn() {
funny.sendmessage("score");
await funny.sleep(100);
funny.sendmessage("score2");
await funny.sleep(100);
$(".dialog-close").click();
})();
}
return;
}
// status
if (data.type === "status") {
}
// dialog = score
if (data.type === "dialog" && data.dialog === "score") {
for (const key in data) funny.role[key] = data[key];
for (const key in funny.role) $(`.role_${key}`).html(funny.role[key]);
}
// dialog = skills
if (data.type === "dialog" && data.dialog === "skills") {
if (data.items) { // 所有技能数据
funny.skills = data.items;
funny.role["skill_limit"] = data.limit; // 等级上限
} else if (data.id && data.level) { // 单个技能变动
for (const skill of funny.skills) {
if (skill.id === data.id) {
skill.level = data.level;
break;
}
}
} else if (data.id && data.exp) {
let name = "", k = 0, level = 0;
let djsx = parseInt(funny.role.skill_limit); // 等级上限
let xxxl = parseInt(funny.role.study_per); // 学习效率
let lxxl = parseInt(funny.role.lianxi_per); // 练习效率
let xtwx = parseInt(funny.role.int); // 先天悟性
let htwx = parseInt(funny.role.int_add); // 后天悟性
if (funny.skills) {
for (const skill of funny.skills) {
if (skill.id === data.id) {
name = skill.name;
level = parseInt(skill.level);
if (/<wht>.*/.test(name)) k = 1; // 白
if (/<hig>.*/.test(name)) k = 2;
if (/<hic>.*/.test(name)) k = 3;
if (/<hiy>.*/.test(name)) k = 4;
if (/<hiz>.*/.test(name)) k = 5;
if (/<hio>.*/.test(name)) k = 6; // 橙
if (/<hir>.*/.test(name)) k = 7; // 红
break;
}
}
}
let qianneng = (djsx * djsx - level * level) * 2.5 * k;
if (funny.state === "你正在练习技能") {
let time = qianneng / (xtwx + htwx) / (1 + lxxl / 100 - xtwx / 100) / 12;
let timeString = time < 60 ? `${parseInt(time)}分钟` : `${parseInt(time / 60)}小时${parseInt(time % 60)}分钟`;
$(".lx").remove();
$(".content-message pre").append(`练习${name}消耗了${parseInt(qianneng / time / 12)}点潜能。\n`);
$(".content-message pre").append(`<span class="lx">- - - - -\n角色悟性: ${xtwx}+${htwx}\n练习效率: ${lxxl}%\n等级上限: ${djsx}级\n需要潜能: ${qianneng}\n需要时间: ${timeString}\n- - - - -\n</span>`);
funny.scroll("content-message");
}
}
}
// type = msg
if (data.type === "msg") {
// 补充 => 发送表情的时候是没有 name 属性的
data.name = (data.name === "" || data.name === undefined) ? `` : `${data.name}:`;
// 世界频道
if (data.ch === "chat") {
let levels = ["<hic>闲聊</hic>", "<hic>闲聊</hic>", "<hic>闲聊</hic>", "<hiy>宗师</hiy>", "<hiz>武圣</hiz>", "<hio>武帝</hio>", "<hir>武神</hir>"];
$(".chat").append(
$(`<span cmd="look3 ${data.uid}"><hic>【${levels[data.lv]}】${data.name}${data.content}</hic><br></span>`)
.click(function() { funny.sendmessage(`${$(this).attr("cmd")}`); })
);
}
// 门派频道
if (data.ch === "fam") $(".fam").append(
$(`<span cmd="look3 ${data.uid}"><hiy>【${data.fam}】${data.name}${data.content}</hiy><br></span>`)
.click(function() { funny.sendmessage(`${$(this).attr("cmd")}`); })
);
// 帮派频道
if (data.ch === "pty") $(".pty").append(
$(`<span cmd="look3 ${data.uid}"><hiz>【帮派】${data.name}${data.content}</hiz><br></span>`)
.click(function() { funny.sendmessage(`${$(this).attr("cmd")}`); })
);
// 队伍频道
if (data.ch === "tm") $(".tm").append(`<hig>【队伍】${data.name}${data.content}</hig><br>`);
// 全区频道
if (data.ch === "es") $(".es").append(`<hio>【${data.server}】${data.name}${data.content}</hio><br>`);
// 谣言消息
// 听说武帝普贤十方闭关修炼似有所悟,你随之受益获得了42562经验,42562潜能
// 【谣言】听说有人得到了一柄血刀。
if (data.ch === "rumor") {
$(".rumor").append(`<him>【谣言】${data.content}</him><br>`);
if (/听说有人得到了.*/.test(data.content)) funny.sendmessage("chat 恭喜恭喜!!");
if (/听说武帝.*闭关修炼似有所悟.*/.test(data.content)) funny.sendmessage("chat 恭迎武帝出关!");
}
// 系统消息
if (data.ch === "sys") $(".sys").append(`<him>【系统】${data.content}</him><br>`);
funny.scroll(data.ch);
}
funny.onmessage_fn.apply(this, arguments);
},
};
// 暴露 funny
unsafeWindow.funny = funny;
// 检查 WebSocket
if (WebSocket) {
unsafeWindow.WebSocket = function(url) { funny.webSocket = new WebSocket(url); };
unsafeWindow.WebSocket.prototype = {
get url() { return funny.webSocket.url; },
get protocol() { return funny.webSocket.protocol; },
get readyState() { return funny.webSocket.readyState; },
get bufferedAmount() { return funny.webSocket.bufferedAmount; },
get extensions() { return funny.webSocket.extensions; },
get binaryType() { return funny.webSocket.binaryType; },
set binaryType(type) { funny.webSocket.binaryType = type; },
get onerror() { return funny.webSocket.onerror; },
set onerror(fn) { funny.webSocket.onerror = fn; },
get onopen() { return funny.webSocket.onopen; },
set onopen(fn) { funny.webSocket.onopen = fn; },
get onclose() { return funny.webSocket.onclose; },
set onclose(fn) { funny.webSocket.onclose = fn; },
close: function () { funny.webSocket.close(); },
get onmessage() { return funny.webSocket.onmessage; },
set onmessage(fn) { // 接收
funny.onmessage_fn = fn;
funny.webSocket.onmessage = funny.onmessage;
},
send: function (message) { // 发送
funny.webSocket.send(message);
// stopstate
if (message === "stopstate") {
$(".state-bar").addClass("hide");
$("[command=stopstate]")[0].style.display = "none";
}
$(".console").append($(`<div> >> ${message}\n</div>`));
funny.scroll("console");
},
};
} else {
console.log(`(${funny.scriptName})\nError: 无法获取 window.WebSocket!`);
}
// 操作 Document
$(document).ready(function() {
// 标记 是否移动端
let isMobile = /Android|iPhone|iPad|iPod/.test(navigator.userAgent);
// 移除游戏原聊天频道
if (!isMobile) GM_addStyle(`.channel{display:none;}`);
// 移除底部 Info
$(".signinfo").addClass("hide");
GM_addStyle(`.content-bottom{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;}`); // 屏蔽连击按钮触发复制
GM_addStyle(`.room-item>.item-name{margin-left: 14px;}`); // 角色列表左侧的外边距
$(".room_items")[0].style.maxHeight = "240px"; // 房间列表大概可以显示 20 个人物
// 隐藏部分滚动条
$(".state-bar")[0].style.overflow = "hidden";
$(".combat-commands")[0].style.overflow = "hidden";
$(".dialog-content")[0].style.overflowX = "hidden";
// 三栏布局
$("body").append($(`<div class="left box"></div>`));
$("body").append($(`<div class="right box"></div>`));
$(".container").addClass("box");
$(".login-content").addClass("box");
GM_addStyle(`
body {
width: 100%;
display: flex;
flex-flow: row no-wrap;
}
.box {
width: 360px;
flex: 0 0 auto;
}
.container, .login-content {
flex: 1 0 auto;
}
.left {
order: -1;
}
.right {
order: 1;
}
`);
// left
$(".left").append(`
<table class="role">
<tr><td colspan="4"><hiy>角色信息</hiy></td></tr>
<tr><td colspan="4" class="role_name">ROLE_NAME</td></tr>
<tr><td>ID</td><td colspan="3" class="role_id"></td></tr>
<tr><td>性别</td><td class="role_gender"></td><td>境界</td><td class="role_level"></td></tr>
<tr><td>年龄</td><td colspan="3" class="role_age"></td></tr>
<tr><td>经验</td><td colspan="3"><hig class="role_exp"></hig></td></tr>
<tr><td>潜能</td><td colspan="3"><hig class="role_pot"></hig></td></tr>
<tr><td>气血</td><td colspan="3"><span class="role_hp"></span>/<hic class="role_max_hp"></hic></td></tr>
<tr><td>内力</td><td colspan="3"><span class="role_mp"></span>/<hic class="role_max_mp"></hic></td></tr>
<tr><td>内力上限</td><td colspan="3"><hic class="role_limit_mp"></hic></td></tr>
<tr><td>臂力</td><td><hiy class="role_str"></hiy>+<span class="role_str_add"></span></td><td>根骨</td><td><hiy class="role_con"></hiy>+<span class="role_con_add"></span></td></tr>
<tr><td>身法</td><td><hiy class="role_dex"></hiy>+<span class="role_dex_add"></span></td><td>悟性</td><td><hiy class="role_int"></hiy>+<span class="role_int_add"></span></td></tr>
<tr><td>攻击</td><td><hig class="role_gj"></hig></td><td>终伤</td><td><hig class="role_add_sh"></hig></td></tr>
<tr><td>防御</td><td><hig class="role_fy"></hig></td><td>命中</td><td><hig class="role_mz"></hig></td></tr>
<tr><td>招架</td><td><hig class="role_zj"></hig></td><td>躲闪</td><td><hig class="role_ds"></hig></td></tr>
<tr><td>暴击</td><td><hig class="role_bj"></hig></td><td>攻速</td><td><hig class="role_gjsd"></hig></td></tr>
<tr><td>门派</td><td><hic class="role_family"></hic></td><td>功绩</td><td><hic class="role_gongji"></hic></td></tr>
<tr><td>忽视防御</td><td class="role_diff_fy"></td><td>伤害减免</td><td class="role_diff_sh"></td></tr>
<tr><td>暴击伤害</td><td class="role_add_bj"></td><td>暴击抵抗</td><td class="role_diff_bj"></td></tr>
<tr><td>增加忙乱</td><td class="role_busy"></td><td>忽视忙乱</td><td class="role_diff_busy"></td></tr>
<tr><td>释放速度</td><td class="role_releasetime"></td><td>冷却速度</td><td class="role_distime"></td></tr>
<tr><td>打坐效率</td><td class="role_dazuo_per"></td><td>内力减耗</td><td class="role_expend_mp"></td></tr>
<tr><td>练习效率</td><td class="role_lianxi_per"></td><td>学习效率</td><td class="role_study_per"></td></tr>
</table>
<div class="console"></div>
<div class="send_controller"><input type="text" autocomplete="off" id="send_value"><button type="button" id="send_btn">发送</button></div>
`);
$("#send_btn").click(function() { // 发送按钮
let value = $("#send_value").val();
if (value) {
funny.sendmessage(value);
$("#send_value").val("");
}
});
$("#send_value").keypress(function(key) { // 监控回车
if (key.which == 13) $("#send_btn").click();
});
GM_addStyle(`
.left {
display: flex;
flex-direction: column;
}
.role {
order: 0;
flex: 0 0 auto;
width: 100%;
flex: 0 0 auto;
table-layout: fixed;
border-collapse: collapse;
}
.role td {
width: 60px;
overflow: hidden;
text-align: center;
white-space: nowrap;
border: #008000 solid 1px;
}
.console {
order: 5;
flex: 1 0 auto;
height: 80px;
overflow: auto;
}
.send_controller {
order: 6;
flex: 0 0 auto;
height: 30px;
display: flex;
}
.send_controller input {
flex: 1 0 auto;
height: auto;
}
.send_controller button {
height: auto;
}
`);
// right
$(".right").append(`
<div class="msg chat"></div>
<div class="msg tm"></div>
<div class="msg fam"></div>
<div class="msg pty"></div>
<div class="msg es"></div>
<div class="msg sys rumor"></div>
<div class="msg pickup"></div>
`);
GM_addStyle(`
.right {
display: flex;
height: 100%;
flex-direction: column;
}
.msg {
height: auto;
flex: 0 0 auto;
font-size: 16px;
max-height: calc(16px * 8);
overflow: auto;
}
.chat {
max-height: 100%;
flex: 1 1 auto;
}
`);
console.log(navigator.userAgent);
if (/Android|iPhone|iPad|iPod/.test(navigator.userAgent)) {
$(".left").hide();
$(".right").hide();
GM_addStyle(`.channel{display:inline;}`);
}
});
})();