init: add workspace files
This commit is contained in:
13
.env
Normal file
13
.env
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Web 服务器端口
|
||||||
|
WEB_PORT=8088
|
||||||
|
# 游戏服务器 WebSocket 端口
|
||||||
|
WS_PORT=31300
|
||||||
|
|
||||||
|
# MD5 加密前缀(用于密码加密)
|
||||||
|
MD5_PREFIX=
|
||||||
|
|
||||||
|
# Session 会话密钥
|
||||||
|
SESSION_SECRET=
|
||||||
|
|
||||||
|
# DES 加密向量(16字节,用于数据加解密)
|
||||||
|
DESIV=
|
||||||
145
api/base.js
Normal file
145
api/base.js
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
|
||||||
|
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const desvi = __CONFIG.DESIV;
|
||||||
|
const md5add = __CONFIG.MD5;
|
||||||
|
const SessionKey = 'u';
|
||||||
|
const SessionToken = 'p';
|
||||||
|
|
||||||
|
class Apibase {
|
||||||
|
constructor(req, res) {
|
||||||
|
|
||||||
|
this.loginUser = null;
|
||||||
|
this.req = req;
|
||||||
|
this.res = res;
|
||||||
|
}
|
||||||
|
error(code = 500, message) {
|
||||||
|
return this.res.status(code).json({ error: message });
|
||||||
|
}
|
||||||
|
signIn(id, uname, pwd, level) {
|
||||||
|
if (!(id > 0)) return null;
|
||||||
|
let key = this.req.cookies[SessionKey];
|
||||||
|
if (!key) {
|
||||||
|
key = this.sessionKey();
|
||||||
|
this.res.cookie(SessionKey, key, {
|
||||||
|
maxAge: 3600000 * 24 * 180
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let cert = this.encryptUser(id, uname, pwd, key, level);
|
||||||
|
if (!cert) return null;
|
||||||
|
this.res.cookie(SessionToken, cert, {
|
||||||
|
maxAge: 3600000 * 24 * 180
|
||||||
|
});
|
||||||
|
return cert;
|
||||||
|
}
|
||||||
|
sessionKey() {
|
||||||
|
return this.req.session.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
getUser() {
|
||||||
|
if (this.loginUser) return this.loginUser;
|
||||||
|
|
||||||
|
let key = this.req.cookies[SessionKey];
|
||||||
|
if (!key) {
|
||||||
|
this.res.cookie(SessionKey, this.sessionKey(), {
|
||||||
|
maxAge: 3600000 * 24 * 180
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let str = this.req.cookies[SessionToken];
|
||||||
|
if (!str) return;
|
||||||
|
this.loginUser = this.deEncryptUser(key, str);
|
||||||
|
return this.loginUser;
|
||||||
|
}
|
||||||
|
deEncryptUser(key, cert) {
|
||||||
|
let txt = this.deEncrypt(key, cert);
|
||||||
|
let str = txt.split("%");
|
||||||
|
if (str.length !== 5) return null;
|
||||||
|
let id = parseInt(str[0]);
|
||||||
|
if (id > 0)
|
||||||
|
return {
|
||||||
|
id: id,
|
||||||
|
name: str[1],
|
||||||
|
pwd: str[2],
|
||||||
|
time: parseInt(str[3]),
|
||||||
|
level: str[4],
|
||||||
|
};
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
deEncrypt(key, str) {
|
||||||
|
|
||||||
|
if (!key || !str) return;
|
||||||
|
if (key.length > 16) key = key.substr(0, 16);
|
||||||
|
key = Buffer.from(key, 'utf8');
|
||||||
|
let decipher = crypto.createDecipheriv('aes-128-cbc', key, desvi);
|
||||||
|
//decipher.setAutoPadding(true);
|
||||||
|
let txt = decipher.update(str, 'base64', 'utf8');
|
||||||
|
txt += decipher.final('utf8');
|
||||||
|
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
MD5(str) {
|
||||||
|
let md5 = crypto.createHash('md5');
|
||||||
|
let result = md5.update(str + md5add).digest('hex');
|
||||||
|
return result.toUpperCase();
|
||||||
|
}
|
||||||
|
encrypt(str, key) {
|
||||||
|
if (!key || !str) return;
|
||||||
|
if (key.length > 16) key = key.substr(0, 16);
|
||||||
|
key = Buffer.from(key, 'utf8');
|
||||||
|
let decipher = crypto.createCipheriv('aes-128-cbc', key, desvi);
|
||||||
|
|
||||||
|
// decipher.setAutoPadding(true);
|
||||||
|
|
||||||
|
let txt = decipher.update(str, 'utf8', 'base64');
|
||||||
|
|
||||||
|
txt += decipher.final('base64');
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
encryptUser(id, uname, pwd, key, level) {
|
||||||
|
return this.encrypt([id, uname, pwd,
|
||||||
|
Date.now(), level].join('%'), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
setSession(key, value) {
|
||||||
|
this.req.session[key] = value;
|
||||||
|
}
|
||||||
|
getSession(key) {
|
||||||
|
return this.req.session[key];
|
||||||
|
}
|
||||||
|
deleteSession(key) {
|
||||||
|
delete this.req.session[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
start_sse() {
|
||||||
|
if (this.res.headersSent) {
|
||||||
|
throw new Error('已经发送响应头');
|
||||||
|
}
|
||||||
|
this.res.setHeader('Content-Type', 'text/event-stream');
|
||||||
|
this.res.setHeader('Cache-Control', 'no-cache');
|
||||||
|
this.res.setHeader('Connection', 'keep-alive');
|
||||||
|
this.res.flushHeaders(); // 发送响应头
|
||||||
|
}
|
||||||
|
sse(data) {
|
||||||
|
this.res.write(`data: ${JSON.stringify(data)}\n\n`); // 发送数据
|
||||||
|
}
|
||||||
|
end_sse() {
|
||||||
|
this.res.end();
|
||||||
|
}
|
||||||
|
guid() {
|
||||||
|
var str = [];
|
||||||
|
str.push(parseInt((Date.now() - 1598376101624) / 1000).toString(16));
|
||||||
|
let length = 32 - str[0].length;
|
||||||
|
for (var i = 0; i < length; i++) {
|
||||||
|
str.push(idstr[parseInt(Math.random() * idstr.length)]);
|
||||||
|
}
|
||||||
|
return str.join('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const idstr = "abcdefghijklmnopqrstuvwxwz0123456789";
|
||||||
|
|
||||||
|
module.exports = Apibase;
|
||||||
47
api/game.js
Normal file
47
api/game.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const APIBASE = require('./base');
|
||||||
|
let SERVERS = null;
|
||||||
|
const { DB } = __CONFIG;
|
||||||
|
class GameAPI extends APIBASE {
|
||||||
|
|
||||||
|
async servers(user) {
|
||||||
|
if (!SERVERS) {
|
||||||
|
SERVERS = await DB.getServers();
|
||||||
|
}
|
||||||
|
return SERVERS;
|
||||||
|
}
|
||||||
|
async reload() {
|
||||||
|
SERVERS = null;
|
||||||
|
}
|
||||||
|
async search_role(paras) {
|
||||||
|
const { type, value } = paras;
|
||||||
|
if (!type || !value) return { code: 0, result: "错误参数" };
|
||||||
|
if (!ALLOW_TYPES[type]) return { code: 0, result: "错误参数" };
|
||||||
|
let cond = "";
|
||||||
|
paras = [value]
|
||||||
|
if (type === "uname") {
|
||||||
|
cond = "where a.name=?";
|
||||||
|
} else if (type === 'name') cond = 'where b.name=? or b.name is null'
|
||||||
|
else if (type === 'phone') cond = 'where a.phone=?';
|
||||||
|
|
||||||
|
let result = await DB.query_role(cond, paras);
|
||||||
|
return { code: 1, result: result };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ALLOW_TYPES = {
|
||||||
|
uname: true,
|
||||||
|
name: true,
|
||||||
|
phone: true
|
||||||
|
};
|
||||||
|
module.exports = GameAPI;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
206
api/user.js
Normal file
206
api/user.js
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const APIBASE = require('./base');
|
||||||
|
const svgCaptcha = require('svg-captcha');
|
||||||
|
const { DB } = __CONFIG;
|
||||||
|
const CODEREG = /^[A-Za-z0-9_]{3,20}$/;
|
||||||
|
class UserAPI extends APIBASE {
|
||||||
|
|
||||||
|
async login(user) {
|
||||||
|
let { code, pwd } = user;
|
||||||
|
|
||||||
|
if (!code || !pwd) {
|
||||||
|
return { code: 0, result: "用户名或密码错误" };
|
||||||
|
}
|
||||||
|
code = code.toLowerCase();
|
||||||
|
if (!CODEREG.test(code))
|
||||||
|
return { code: 0, result: "用户名格式错误" };
|
||||||
|
pwd = this.MD5(pwd);
|
||||||
|
let result = await DB.getUserBy("name", code);
|
||||||
|
if (!result)
|
||||||
|
return { code: 0, result: "用户不存在" };
|
||||||
|
if (result.pwd !== pwd)
|
||||||
|
return { code: 0, result: "用户密码错误" };
|
||||||
|
let cert = this.signIn(result.id, result.name, pwd, result.level);
|
||||||
|
if (cert)
|
||||||
|
return { code: 1, p: cert, u: this.sessionKey() };
|
||||||
|
return { code: 0, result: "登陆失败" };
|
||||||
|
}
|
||||||
|
checkValCode(code) {
|
||||||
|
if (!code) return false;
|
||||||
|
let num = this.getSession("valno");
|
||||||
|
if (!num) return false;
|
||||||
|
|
||||||
|
return code.toLowerCase() == num.toLowerCase();
|
||||||
|
}
|
||||||
|
async regist(user) {
|
||||||
|
if (!user.name || !user.pwd) {
|
||||||
|
return { code: 0, result: "注册失败,缺少数据" };
|
||||||
|
}
|
||||||
|
if (user.name.length > 15 || user.name.length < 3) {
|
||||||
|
return { code: 0, result: "注册失败,缺少数据" };
|
||||||
|
}
|
||||||
|
if (user.pwd.length < 5) {
|
||||||
|
return { code: 0, result: "注册失败,缺少数据" };
|
||||||
|
}
|
||||||
|
if (!this.checkValCode(user.valno)) {
|
||||||
|
return { code: 0, result: "验证码输入错误" };
|
||||||
|
}
|
||||||
|
user.pwd = this.MD5(user.pwd);
|
||||||
|
user.name = user.name.toLowerCase();
|
||||||
|
user.phone = user.phone ?? null;
|
||||||
|
user.link_user = user.guider > 0 ? user.guider : 0;
|
||||||
|
if (await DB.getUserBy("name", user.name)) {
|
||||||
|
return { code: 0, result: "注册失败,账号已经有人使用" };
|
||||||
|
}
|
||||||
|
if (!await DB.createUser(user)) {
|
||||||
|
return { code: 0, result: "注册失败" };
|
||||||
|
}
|
||||||
|
this.deleteSession("valno");
|
||||||
|
this.signIn(user.id, user.name, user.pwd);
|
||||||
|
return { code: 1 };
|
||||||
|
}
|
||||||
|
async validimage() {
|
||||||
|
const captcha = svgCaptcha.create({
|
||||||
|
size: 4, // 验证码长度
|
||||||
|
noise: 2, // 干扰线条数量
|
||||||
|
color: true, // 文字是否彩色
|
||||||
|
background: '#337AB7', // 背景色
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setSession('valno', captcha.text)
|
||||||
|
return Buffer.from(captcha.data).toString('base64');
|
||||||
|
}
|
||||||
|
async getphone() {
|
||||||
|
const user = this.getUser();
|
||||||
|
if (!user)
|
||||||
|
return { code: 0, result: "未登录" };
|
||||||
|
let result = await DB.getUserBy("id", user.id);
|
||||||
|
if (!result) return { code: 0, result: "不存在的用户" };
|
||||||
|
return { code: 1, result: result.phone ? result.phone.substring(0, 3) + "********" : "" };
|
||||||
|
}
|
||||||
|
async bindphone(data) {
|
||||||
|
const user = this.getUser();
|
||||||
|
if (!user)
|
||||||
|
return { code: 0, result: "未登录" };
|
||||||
|
let { code, no, pwd } = data;
|
||||||
|
let result = await DB.getUserBy("id", user.id);
|
||||||
|
if (!result) return { code: 0, result: "不存在的用户" };
|
||||||
|
if (result.phone) {
|
||||||
|
if (!code || code.length !== 4)
|
||||||
|
return { code: 0, result: "手机尾号格式错误" };
|
||||||
|
if (!result.phone.endsWith(code))
|
||||||
|
return { code: 0, result: "错误的手机尾号" };
|
||||||
|
user.phone = null;
|
||||||
|
} else {
|
||||||
|
if (!no || !/^1\d{10}$/.test(no))
|
||||||
|
return { code: 0, result: "手机号格式错误" };
|
||||||
|
user.phone = no;
|
||||||
|
}
|
||||||
|
pwd = this.MD5(pwd);
|
||||||
|
if (pwd !== user.pwd)
|
||||||
|
return { code: 0, result: "密码错误" };
|
||||||
|
if (await DB.updateUser(user))
|
||||||
|
return { code: 1 };
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
async resetpwd(paras) {
|
||||||
|
let {
|
||||||
|
name, phone, vcode, pwd
|
||||||
|
} = paras;
|
||||||
|
if (!name || !phone || !pwd)
|
||||||
|
return { code: 0 };
|
||||||
|
const result = await DB.getUserBy("name", name);
|
||||||
|
if (!result)
|
||||||
|
return { code: 0, result: "账号不存在" };
|
||||||
|
if (!result.phone || result.phone !== phone) {
|
||||||
|
return { code: 0, result: "手机号验证失败" };
|
||||||
|
}
|
||||||
|
pwd = this.MD5(pwd);
|
||||||
|
result.pwd = pwd;
|
||||||
|
if (!await DB.updateUser(result)) {
|
||||||
|
return { code: 0, result: "密码重置失败。" };
|
||||||
|
}
|
||||||
|
return { code: 1 };
|
||||||
|
}
|
||||||
|
async changepassword(data) {
|
||||||
|
let { oldpwd, pwd, no } = data;
|
||||||
|
if (!oldpwd || !pwd)
|
||||||
|
return { code: 0 };
|
||||||
|
oldpwd = this.MD5(oldpwd);
|
||||||
|
pwd = this.MD5(pwd);
|
||||||
|
const user = this.getUser();
|
||||||
|
if (!user)
|
||||||
|
return { code: 0, result: "未登录" };
|
||||||
|
const result = await DB.getUserBy("id", user.id);
|
||||||
|
if (!result)
|
||||||
|
return { code: 0, result: "账号不存在" };
|
||||||
|
|
||||||
|
if (result.pwd !== oldpwd) {
|
||||||
|
return { code: 0, result: "原始密码输入错误。" };
|
||||||
|
}
|
||||||
|
if (result.phone) {
|
||||||
|
if (!no || no.length !== 4)
|
||||||
|
return { code: 0, result: "手机尾号格式错误" };
|
||||||
|
if (!result.phone.endsWith(no))
|
||||||
|
return { code: 0, result: "错误的手机尾号" };
|
||||||
|
}
|
||||||
|
user.pwd = pwd;
|
||||||
|
result.pwd = pwd;
|
||||||
|
if (!await DB.updateUser(result)) {
|
||||||
|
return { code: 0, result: "密码修改失败。" };
|
||||||
|
}
|
||||||
|
let cert = this.signIn(user.id, user.name, pwd, user.level);
|
||||||
|
if (cert)
|
||||||
|
return { code: 1, p: cert, u: this.sessionKey() };
|
||||||
|
return { code: 0, result: "登陆凭证更新失败" };
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetPhone2(paras) {
|
||||||
|
let { uid, cert } = paras; debugger
|
||||||
|
if (!uid || cert !== 'transrole_service') return;
|
||||||
|
let user = await DB.getUserByID(uid);
|
||||||
|
if (!user) return "";
|
||||||
|
return user.phone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = UserAPI;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// this.inherits('api/base');
|
||||||
|
|
||||||
|
// this.define = {
|
||||||
|
// Login: { method: "Post", paras: ["code", "pwd"] }
|
||||||
|
// }
|
||||||
|
// const DB = this.import('/lib/mysql');
|
||||||
|
// let servers = null;
|
||||||
|
|
||||||
|
// this.Login = async function (code, pwd) {
|
||||||
|
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// this.GetUser = async function (cond, pars) {
|
||||||
|
|
||||||
|
// let sql = "select ID,Name,EMAIL,PHone,State,Developer,IsFirst from users";
|
||||||
|
// if (cond) {
|
||||||
|
// sql += " where " + cond;
|
||||||
|
// }
|
||||||
|
// return await DB.query(sql, pars);
|
||||||
|
|
||||||
|
// }
|
||||||
29
config.js
Normal file
29
config.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
DB: require('./data/sql'),
|
||||||
|
init: async function () {
|
||||||
|
if (!(this.WEB_PORT > 1000)) throw new Error('缺少环境配置WEB_PORT');
|
||||||
|
if (!(this.def_server.port > 1000)) throw new Error('缺少环境配置WS_PORT');
|
||||||
|
if (!this.MD5) throw new Error('缺少环境配置md5');
|
||||||
|
if (!this.DESIV) throw new Error('缺少环境配置DESIV');
|
||||||
|
if (!this.SESSION_SECRET) throw new Error('缺少环境配置SESSION_SECRET');
|
||||||
|
await this.DB.connect('database.db');
|
||||||
|
},
|
||||||
|
WEB_PORT: parseInt(process.env.WEB_PORT),
|
||||||
|
CONNECT_LEVEL: 0,
|
||||||
|
MD5: process.env.MD5_PREFIX,
|
||||||
|
SESSION_SECRET: process.env.SESSION_SECRET,
|
||||||
|
HEARTBEAT: 5000,
|
||||||
|
|
||||||
|
DESIV: process.env.DESIV ? Buffer.from(process.env.DESIV, 'utf8') : null,
|
||||||
|
|
||||||
|
def_server: {
|
||||||
|
ip: "127.0.0.1",
|
||||||
|
port: parseInt(process.env.WS_PORT),
|
||||||
|
id: 100,
|
||||||
|
name: "本地测试",
|
||||||
|
istest: true
|
||||||
|
}
|
||||||
|
};
|
||||||
200
data/db.js
Normal file
200
data/db.js
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
const Database = require("better-sqlite3");
|
||||||
|
const path = require("path");
|
||||||
|
const fs = require("fs").promises;
|
||||||
|
const crypto = require("crypto");
|
||||||
|
|
||||||
|
const stmtCaches = new Map();
|
||||||
|
|
||||||
|
class SqliteDatabase {
|
||||||
|
db_path = null;
|
||||||
|
constructor() {
|
||||||
|
this.db = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取预编译语句(带缓存)
|
||||||
|
getStmt(sql) {
|
||||||
|
let stmt = stmtCaches.get(sql);
|
||||||
|
if (!stmt) {
|
||||||
|
stmt = this.db.prepare(sql);
|
||||||
|
stmtCaches.set(sql, stmt);
|
||||||
|
}
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化数据库
|
||||||
|
async init(db_name) {
|
||||||
|
try {
|
||||||
|
this.db_path = path.join(__dirname, db_name);
|
||||||
|
const fileExists = await this.checkDbFileExists();
|
||||||
|
|
||||||
|
if (!fileExists) {
|
||||||
|
console.log("数据库文件不存在,正在创建...");
|
||||||
|
this.db = new Database(this.db_path);
|
||||||
|
await this.executeDefaultScripts();
|
||||||
|
console.log("数据库初始化完成");
|
||||||
|
} else {
|
||||||
|
console.log("数据库文件已存在,正在连接...");
|
||||||
|
this.db = new Database(this.db_path);
|
||||||
|
await this.executeAlterScripts();
|
||||||
|
console.log("数据库连接成功");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("数据库初始化失败:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查数据库文件是否存在
|
||||||
|
async checkDbFileExists() {
|
||||||
|
try {
|
||||||
|
await fs.access(this.db_path);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行 ALTER 脚本(数据库已存在时)
|
||||||
|
async executeAlterScripts() {
|
||||||
|
for (let sql of ALTER_SCRIPTS) {
|
||||||
|
try {
|
||||||
|
await this.query(sql);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(sql, "查询失败", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行默认建表脚本(数据库新建时)
|
||||||
|
async executeDefaultScripts() {
|
||||||
|
for (let sql of DEFAULT_TABLE_SCRIPTS) {
|
||||||
|
try {
|
||||||
|
await this.query(sql);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(sql, "查询失败", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行 INSERT/UPDATE/DELETE 等操作
|
||||||
|
query(sql, params = []) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const stmt = this.getStmt(sql);
|
||||||
|
const info = stmt.run(...params);
|
||||||
|
resolve({ lastID: info.lastInsertRowid, changes: info.changes });
|
||||||
|
} catch (err) {
|
||||||
|
console.error("SQL执行错误:", err);
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询单行数据
|
||||||
|
get(sql, params = []) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const stmt = this.getStmt(sql);
|
||||||
|
const row = stmt.get(...params);
|
||||||
|
resolve(row);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("SQL查询错误:", err);
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询多行数据
|
||||||
|
all(sql, params = []) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const stmt = this.getStmt(sql);
|
||||||
|
const rows = stmt.all(...params);
|
||||||
|
resolve(rows);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("SQL查询错误:", err);
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭数据库连接
|
||||||
|
close() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
if (this.db) {
|
||||||
|
this.db.close();
|
||||||
|
this.db = null;
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
} catch (err) {
|
||||||
|
console.error("关闭数据库连接失败:", err);
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出单例
|
||||||
|
module.exports = new SqliteDatabase();
|
||||||
|
|
||||||
|
// ---------- 建表及初始脚本 ----------
|
||||||
|
const DEFAULT_TABLE_SCRIPTS = [
|
||||||
|
`CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name VARCHAR(60) NOT NULL,
|
||||||
|
pwd VARCHAR(60) NOT NULL,
|
||||||
|
phone VARCHAR(20),
|
||||||
|
state INTEGER DEFAULT 1,
|
||||||
|
level INTEGER DEFAULT 0,
|
||||||
|
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
UNIQUE (name)
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE IF NOT EXISTS servers (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name VARCHAR(60) NOT NULL,
|
||||||
|
ip VARCHAR(60) NOT NULL,
|
||||||
|
port VARCHAR(60) NOT NULL,
|
||||||
|
state INTEGER DEFAULT 1,
|
||||||
|
isdef INTEGER DEFAULT 0,
|
||||||
|
istest INTEGER DEFAULT 0,
|
||||||
|
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
start_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE IF NOT EXISTS players (
|
||||||
|
id VARCHAR(40) NOT NULL,
|
||||||
|
name VARCHAR(30) NOT NULL,
|
||||||
|
userid INTEGER NOT NULL,
|
||||||
|
sid INTEGER NOT NULL,
|
||||||
|
level INTEGER DEFAULT 0,
|
||||||
|
title VARCHAR(30) NOT NULL,
|
||||||
|
data TEXT,
|
||||||
|
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE IF NOT EXISTS players_bak (
|
||||||
|
id VARCHAR(40) NOT NULL,
|
||||||
|
name VARCHAR(30) NOT NULL,
|
||||||
|
userid INTEGER NOT NULL,
|
||||||
|
sid INTEGER NOT NULL,
|
||||||
|
level INTEGER DEFAULT 0,
|
||||||
|
title VARCHAR(30) NOT NULL,
|
||||||
|
data TEXT,
|
||||||
|
create_time TIMESTAMP,
|
||||||
|
update_time TIMESTAMP
|
||||||
|
)`,
|
||||||
|
`CREATE UNIQUE INDEX IF NOT EXISTS idx_users_name ON users (name)`,
|
||||||
|
`CREATE UNIQUE INDEX IF NOT EXISTS idx_players_id ON players (id)`,
|
||||||
|
`CREATE INDEX IF NOT EXISTS idx_players_userid ON players (userid)`,
|
||||||
|
`CREATE UNIQUE INDEX IF NOT EXISTS idx_players_name ON players (name)`,
|
||||||
|
`CREATE UNIQUE INDEX IF NOT EXISTS idx_players_bak_id ON players_bak (id)`,
|
||||||
|
`INSERT OR IGNORE INTO users(id,name,pwd,level) VALUES(1,'administrator','${MD5("123456")}',6)`,
|
||||||
|
];
|
||||||
|
|
||||||
|
function MD5(str) {
|
||||||
|
let md5 = crypto.createHash("md5");
|
||||||
|
let result = md5.update(str + process.env.MD5_PREFIX).digest("hex");
|
||||||
|
return result.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
const ALTER_SCRIPTS = [];
|
||||||
1
data/def/data.js
Normal file
1
data/def/data.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ }
|
||||||
132
data/sql.js
Normal file
132
data/sql.js
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
const db = require('./db');
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
connect: async function (path) {
|
||||||
|
await db.init(path);
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
return db.close();
|
||||||
|
},
|
||||||
|
getUserBy: function (type, value) {
|
||||||
|
return this.getUser(type + "=?", [value]);
|
||||||
|
},
|
||||||
|
getUserByID: function (id) {
|
||||||
|
return this.getUser("id=?", [id]);
|
||||||
|
},
|
||||||
|
getUser: function (cond, paras) {
|
||||||
|
let sql = "select id,name,pwd,phone,state,level from users";
|
||||||
|
|
||||||
|
if (cond) {
|
||||||
|
sql += " where " + cond;
|
||||||
|
}
|
||||||
|
return db.get(sql, paras);
|
||||||
|
},
|
||||||
|
getUsers: function (cond, paras) {
|
||||||
|
let sql = "select id,name,pwd,phone,state,create_time from users";
|
||||||
|
|
||||||
|
if (cond) {
|
||||||
|
sql += " where " + cond;
|
||||||
|
}
|
||||||
|
return db.all(sql, paras);
|
||||||
|
},
|
||||||
|
checkUserName: function (name) {
|
||||||
|
let sql = "select name,phone from users where name=?";// or phone=?
|
||||||
|
return db.get(sql, [name]);
|
||||||
|
},
|
||||||
|
updateUser: async function (user) {
|
||||||
|
let sql = "update users set name=?,phone=?,pwd=? where id=?";
|
||||||
|
let result = await db.query(sql, [user.name, user.phone, user.pwd, user.id]);
|
||||||
|
return result.changes === 1;
|
||||||
|
},
|
||||||
|
createUser: async function (user) {
|
||||||
|
|
||||||
|
let result = await db.query("insert into users(name,pwd,phone) values(?,?,?)",
|
||||||
|
[user.name, user.pwd, user.phone]);
|
||||||
|
if (!(result.lastID > 0)) return false;
|
||||||
|
user.id = result.lastID;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
getServers: function () {
|
||||||
|
let sql = "select id,name, ip,port,istest,isdef,create_time,start_time from servers";
|
||||||
|
|
||||||
|
return db.all(sql);
|
||||||
|
},
|
||||||
|
getServer: function (id) {
|
||||||
|
let sql = "select id,name, ip,port,istest,isdef from servers where id=?";
|
||||||
|
|
||||||
|
return db.get(sql, [id]);
|
||||||
|
},
|
||||||
|
saveServer: async function (data) {
|
||||||
|
let sql = "update servers set name=?, ip=?,port=?,istest=?,isdef=? where id=?";
|
||||||
|
|
||||||
|
let result = await db.query(sql, [data.name, data.ip, data.port, data.istest, data.isdef, data.id]);
|
||||||
|
|
||||||
|
return result.changes === 1;
|
||||||
|
},
|
||||||
|
addServer: async function (data) {
|
||||||
|
let sql = "insert into servers(name,ip,port,istest,isdef) values(?,?,?,?,?)";
|
||||||
|
let result = await db.query(sql,
|
||||||
|
[data.name, data.ip, data.port, data.istest, data.isdef]);
|
||||||
|
|
||||||
|
return result.lastID;
|
||||||
|
|
||||||
|
},
|
||||||
|
deleteServer: function (id) {
|
||||||
|
return db.query("delete from servers where id =?", [id]);
|
||||||
|
},
|
||||||
|
|
||||||
|
getRoles: function (uid, server) {
|
||||||
|
return db.all("select a.id,a.name,a.title,a.level from players a where a.userid=? and a.sid=?",
|
||||||
|
[uid, server]);
|
||||||
|
|
||||||
|
},
|
||||||
|
addRole: function (role) {
|
||||||
|
|
||||||
|
return db.query("insert into players(userid,id,name,title,level,sid,data) values(?,?,?,?,?,?,?)",
|
||||||
|
[role.userid, role.id, role.name, role.title, role.level, role.server, role.data]);
|
||||||
|
|
||||||
|
},
|
||||||
|
deleteRole: async function (userid, roleid) {
|
||||||
|
|
||||||
|
let sql = "insert into players_bak(id,name,userid,title,level,sid,data,create_time,update_time) select id,name,userid,title,level,sid,data,create_time,update_time from players where id=? and userid=?";
|
||||||
|
let result = await db.query(sql, [roleid, userid]);
|
||||||
|
if (result.changes != 1)
|
||||||
|
return false;
|
||||||
|
sql = "delete from players where id=? and userid=?";
|
||||||
|
result = await db.query(sql, [roleid, userid]);
|
||||||
|
if (result.changes != 1)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
},
|
||||||
|
saveRole: function (role) {
|
||||||
|
return db.query("update players set name=?,title=?,level=?,data=? where userid=? and id=?",
|
||||||
|
[role.name, role.title, role.level, role.data, role.userid, role.id]);
|
||||||
|
},
|
||||||
|
exitsRoleName: function (name) {
|
||||||
|
let sql = "select name from players where name=?";// or phone=?
|
||||||
|
return db.get(sql, [name]);
|
||||||
|
},
|
||||||
|
|
||||||
|
getData: function (id) {
|
||||||
|
return db.get("select a.id,a.name,a.title,a.level,a.data,b.pwd,b.level user_level from players a left join users b on a.userid=b.id where a.userid=?",
|
||||||
|
[id]);
|
||||||
|
},
|
||||||
|
updateRoleName: function (id, name) {
|
||||||
|
|
||||||
|
WORLD_DATA.query_db("update players set name=? where id=? ",
|
||||||
|
[name, id]);
|
||||||
|
|
||||||
|
},
|
||||||
|
updateUserid: function (id, fromuserid, touserid) {
|
||||||
|
WORLD_DATA.query_db("update player set userid=? where id=? and userid=?",
|
||||||
|
[touserid, id, fromuserid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
58
main.js
Normal file
58
main.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
globalThis['__PATH'] = {
|
||||||
|
BASE: "./os/",
|
||||||
|
WORLD: "./world/",
|
||||||
|
COMMAND: "./world/cmd/",
|
||||||
|
SKILL: "./world/skill/",
|
||||||
|
MAP: "./world/map/",
|
||||||
|
NPC: "./world/npc/",
|
||||||
|
OBJ: "./world/obj/",
|
||||||
|
TASK: "./world/task/",
|
||||||
|
AREA: "./world/area/",
|
||||||
|
FAMILY: "./world/family/",
|
||||||
|
EXTENDS: "./world/extends/",
|
||||||
|
DATA: "./data/",
|
||||||
|
DEF_DATA: "./data/def/"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
require('dotenv').config();
|
||||||
|
|
||||||
|
|
||||||
|
const fs = require("fs");
|
||||||
|
function readdir(path) {
|
||||||
|
var files = fs.readdirSync(path);
|
||||||
|
for (var i = 0; i < files.length; i++) {
|
||||||
|
var sub_path = path + files[i];
|
||||||
|
var stat = fs.statSync(sub_path);
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
readdir(sub_path + "/");
|
||||||
|
} else {
|
||||||
|
require(sub_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
globalThis['__CONFIG'] = require('./config');
|
||||||
|
async function require_os() {
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
for (var item in __PATH) {
|
||||||
|
__PATH[item] = path.join(__dirname, __PATH[item]);
|
||||||
|
}
|
||||||
|
readdir(__PATH.BASE);
|
||||||
|
await __CONFIG.init();
|
||||||
|
}
|
||||||
|
require_os().then(() => {
|
||||||
|
WORLD.startup(process.argv[2]);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
process.on('uncaughtException', (error) => {
|
||||||
|
console.error('未捕获的异常:', error);
|
||||||
|
|
||||||
|
});
|
||||||
|
process.on('unhandledRejection', (reason, promise) => {
|
||||||
|
console.error('未处理的Promise拒绝:', reason);
|
||||||
|
});
|
||||||
179
os/base.js
Normal file
179
os/base.js
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
定义当对象从文件生成时的基类,
|
||||||
|
当文件内部调用this.inherit(父类名)后,将真正继承父类的原型和实例属性。
|
||||||
|
但是文件内部不能修改this.prototype,修改将会作用到父类上面。
|
||||||
|
可以用this.XXX扩展属性和方法
|
||||||
|
*/
|
||||||
|
|
||||||
|
BASE = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BASE.prototype.set = function (pars) {
|
||||||
|
if (!pars) return;
|
||||||
|
for (var item in pars) {
|
||||||
|
this[item] = pars[item];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
该方法使用直接赋值方式继承父对象的所有原型方法,
|
||||||
|
如果子对象对原型修改,将会改变父对象的原型。
|
||||||
|
所以该方法只能获取父对象的原型不能修改它,
|
||||||
|
|
||||||
|
实际上是作为new的另外一种方式,通过apply获取实例属性,通过__proto__获取父类原型
|
||||||
|
|
||||||
|
*/
|
||||||
|
BASE.prototype.inherits = function (ctor) {
|
||||||
|
this.__proto__ = ctor.prototype;
|
||||||
|
ctor.apply(this);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
create方法由继承自base类的类自己实现,当对象被从文件创建时候调用
|
||||||
|
参数fname=该对象的文件的相对路径,ctor=构造方法
|
||||||
|
*/
|
||||||
|
BASE.prototype.create = function (fname, ctor) {
|
||||||
|
}
|
||||||
|
BASE.prototype.add_event = function (fname, func, time) {
|
||||||
|
///在time秒内用新的func替换旧的fname方法
|
||||||
|
if (!this[fname])
|
||||||
|
this[fname] = this.fire_event.bind(this, fname);
|
||||||
|
if (!this._events) this._events = {};
|
||||||
|
if (!this._events[fname]) this._events[fname] = [];
|
||||||
|
this._events[fname].push({
|
||||||
|
func: func,
|
||||||
|
time: time ? (Date.now() + time) : Number.MAX_SAFE_INTEGER
|
||||||
|
});
|
||||||
|
//var old_func = this[fname];
|
||||||
|
//this[fname] = func;
|
||||||
|
//if (time) this.call_out(() => this[fname] = old_func, time);
|
||||||
|
//return old_func;
|
||||||
|
}
|
||||||
|
BASE.prototype.remove_event = function (name, func) {
|
||||||
|
if (!this._events) return;
|
||||||
|
var evts = this._events[name];
|
||||||
|
if (!evts) return;
|
||||||
|
for (var i = 0; i < evts.length; i++) {
|
||||||
|
if (evts[i].func === func) {
|
||||||
|
evts.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!evts.length) {
|
||||||
|
this._events[name] = null;
|
||||||
|
this[name] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BASE.prototype.fire_event = function (name) {
|
||||||
|
if (!this._events) return;
|
||||||
|
var evts = this._events[name];
|
||||||
|
if (!evts) return;
|
||||||
|
var dt = Date.now();
|
||||||
|
for (var i = 0; i < evts.length; i++) {
|
||||||
|
if (evts[i].time > dt) {
|
||||||
|
if (evts[i].func.call(this) == false) return false;
|
||||||
|
} else {
|
||||||
|
evts.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!evts.length) {
|
||||||
|
this._events[name] = null;
|
||||||
|
this[name] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
生成对象标识,前8位是毫秒级时间戳的36进制形式,后4位随机码,
|
||||||
|
最起码保证每毫秒生成的标识不会重复
|
||||||
|
*/
|
||||||
|
var key = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||||
|
BASE.prototype.create_uid = function () {
|
||||||
|
var str = [];
|
||||||
|
str.push(Date.now().toString(36));
|
||||||
|
var length = key.length;
|
||||||
|
for (var i = 0; i < 4; i++) {
|
||||||
|
str.push(key[Math.floor(Math.random() * length)]);
|
||||||
|
}
|
||||||
|
return str.join("");
|
||||||
|
}
|
||||||
|
BASE.prototype.random = function (num) {
|
||||||
|
return Math.floor(Math.random() * num);
|
||||||
|
}
|
||||||
|
BASE.prototype.call_out = function (func, time, arg1, arg2) {
|
||||||
|
return setTimeout(func.bind(this, arg1, arg2), time);
|
||||||
|
}
|
||||||
|
BASE.prototype.call_interval = function (func, time, count, end_func) {
|
||||||
|
count--;
|
||||||
|
var index = 0;
|
||||||
|
if (func(index++) === false || count === 0) {
|
||||||
|
return end_func && end_func();
|
||||||
|
}
|
||||||
|
var handler = 0;
|
||||||
|
handler = setInterval(function () {
|
||||||
|
|
||||||
|
count--;
|
||||||
|
if (func(index++) === false || count === 0) {
|
||||||
|
clearInterval(handler);
|
||||||
|
end_func && end_func();
|
||||||
|
}
|
||||||
|
}, time);
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const vm = require('vm');
|
||||||
|
const fs = require("fs");
|
||||||
|
//根据文件路径new一个对象
|
||||||
|
BASE.ITEMS = {};
|
||||||
|
BASE.CREATE = function (path, fname) {
|
||||||
|
|
||||||
|
var ary = BASE.PATH_REG.exec(fname);
|
||||||
|
if (!ary) {
|
||||||
|
return console.error("path %s is incorrect:", path + fname);
|
||||||
|
}
|
||||||
|
fname = ary[1];
|
||||||
|
var paras = ary[2];
|
||||||
|
var fkey = path + fname;
|
||||||
|
var func = BASE.ITEMS[fkey];
|
||||||
|
if (func) {
|
||||||
|
return BASE.NEW(fname, func, paras);
|
||||||
|
}
|
||||||
|
const filepath = fkey + ".js";
|
||||||
|
try {
|
||||||
|
const script = fs.readFileSync(filepath);
|
||||||
|
func = vm.compileFunction(script.toString(), [],
|
||||||
|
{ filename: filepath });
|
||||||
|
|
||||||
|
BASE.ITEMS[fkey] = func;
|
||||||
|
return BASE.NEW(fname, func, paras);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("create %s%s error:", filepath, e, e.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BASE.CLONE = function (fname) {
|
||||||
|
}
|
||||||
|
BASE.PATH_REG = /^(\w+(?:\/\w+)*)(#\w+)?$/;
|
||||||
|
BASE.NEW = function (fname, func, par) {
|
||||||
|
var obj = new BASE();
|
||||||
|
func.apply(obj);
|
||||||
|
obj.path = fname;
|
||||||
|
obj.create(fname, par);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
BASE.UPDATE = function (path, fname) {
|
||||||
|
var ary = BASE.PATH_REG.exec(fname);
|
||||||
|
if (!ary) {
|
||||||
|
throw "path " + fname + " is incorrect:";
|
||||||
|
}
|
||||||
|
fname = ary[1];
|
||||||
|
var fkey = path + fname;
|
||||||
|
var data = fs.readFileSync(fkey + ".js");
|
||||||
|
var func = new Function(data);
|
||||||
|
BASE.ITEMS[fkey] = func;
|
||||||
|
var obj = new BASE();
|
||||||
|
func.apply(obj);
|
||||||
|
obj.path = fname;
|
||||||
|
obj.update && obj.update(fname, ary[2]);
|
||||||
|
}
|
||||||
234
os/char/chara_comm.js
Normal file
234
os/char/chara_comm.js
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
|
||||||
|
require("./character");
|
||||||
|
|
||||||
|
var level_descs = ["普通百姓", "武士", "武师", "宗师", "武圣", "武帝", "武神"];
|
||||||
|
var level_color = ["", "wht", "hig", "hiy", "hiz", "hio", "ord"];
|
||||||
|
CHARACTER.prototype.get_level_desc = function () {
|
||||||
|
if (!this.level) return level_descs[this.level];
|
||||||
|
var cc = level_color[this.level];
|
||||||
|
return "<" + cc + ">" + level_descs[this.level] + "</" + cc + ">";
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.get_level_color = function () {
|
||||||
|
return level_color[this.level];
|
||||||
|
}
|
||||||
|
//发送给当前对象的消息
|
||||||
|
CHARACTER.prototype.long_name = function () {
|
||||||
|
|
||||||
|
if (this.title) return this.title + " " + this.name;
|
||||||
|
return this.name;
|
||||||
|
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_title = function () {
|
||||||
|
return this.title;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_age = function () {
|
||||||
|
return this.age;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.call = function (isbad) {
|
||||||
|
return this.family.call(this, isbad);
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.callme = function (isbad) {
|
||||||
|
return this.family.call_me(this);
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.fam_call = function (target) {
|
||||||
|
let age1 = target.query_age();
|
||||||
|
let age2 = this.query_age();
|
||||||
|
if (age1 < age2) {
|
||||||
|
return this.gender === 1 ? "师兄" : "师姐";
|
||||||
|
}
|
||||||
|
return this.gender === 1 ? "师弟" : "师妹";
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.call3 = function () {
|
||||||
|
return this.gender == 1 ? "他" : "她";
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.is_hidden = function () {
|
||||||
|
return this.hp <= 0 || this.query_temp('hidden');
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.is_team = function (p) {
|
||||||
|
if (!p) return false;
|
||||||
|
if (p.team)
|
||||||
|
return this.team == p.team;
|
||||||
|
return this.family == p.family;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.send_team = function (msg, nome) {
|
||||||
|
if (!this.team) return this.send(msg);
|
||||||
|
for (var i = 0; i < this.team.length; i++) {
|
||||||
|
if (nome && this.team[i] == this) continue;
|
||||||
|
this.team[i].send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_teamid = function () {
|
||||||
|
if (this.follow_target) return this.follow_target.query_teamid();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_status = function () {
|
||||||
|
var ary = ["{type:\"status\",hp:"];
|
||||||
|
ary.push(this.hp);
|
||||||
|
ary.push(",max_hp:");
|
||||||
|
ary.push(this.max_hp);
|
||||||
|
ary.push(",mp:");
|
||||||
|
ary.push(this.mp);
|
||||||
|
ary.push(",max_mp:");
|
||||||
|
ary.push(this.max_mp);
|
||||||
|
ary.push(",name:\"");
|
||||||
|
ary.push(this.name);
|
||||||
|
ary.push("\",id:\"");
|
||||||
|
ary.push(this.id);
|
||||||
|
ary.push("\"}");
|
||||||
|
return ary.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.query_commands = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_desc = function (me, eqcmd) {
|
||||||
|
var str = [];
|
||||||
|
str.push(this.long_name());
|
||||||
|
str.push("\n");
|
||||||
|
var call3 = this == me ? "你" : this.call3();
|
||||||
|
str.push(call3, "看起来约", get_agestr(this.query_age()), "岁。\n");
|
||||||
|
str.push(call3, "长得", get_perdesc(this), "。\n");
|
||||||
|
str.push(call3, get_skill_desc(this.query_skill(this.attack_skill.id)), "。\n");
|
||||||
|
str.push(call3, get_status(this), "\n");
|
||||||
|
this.format_equipments(call3, str, eqcmd);
|
||||||
|
return str.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.format_equipments = function (call3, str, eqcmd) {
|
||||||
|
if (this.query_setting("hide_equip")) {
|
||||||
|
return str.push("看样子", call3, "不想让别人看自己的装备。");
|
||||||
|
} else if (this.equipment && this.equipment.length) {
|
||||||
|
var eqstr = [];
|
||||||
|
for (var i = 0; i < this.equipment.length; i++) {
|
||||||
|
var item = this.equipment[i];
|
||||||
|
if (!item) continue;
|
||||||
|
eqstr.push("<span cmd='", eqcmd || "look", " ", (i),
|
||||||
|
" of ", this.id, "'>◆", item.color_name, "</span>\n");
|
||||||
|
}
|
||||||
|
if (eqstr.length) {
|
||||||
|
return str.push(call3, "装备着:\n", eqstr.join(""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str.push(call3, "光着身子,什么都没穿。\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_perdesc(obj) {
|
||||||
|
var ary = obj.gender === 1 ? boy_pers : girl_pers;
|
||||||
|
var per = obj.per + obj.query_prop("per");
|
||||||
|
var index = parseInt(per / 2);
|
||||||
|
if (index < 0) index = 0;
|
||||||
|
if (index >= ary.length) index = ary.length - 1;
|
||||||
|
return ary[index];
|
||||||
|
}
|
||||||
|
function get_agestr(age) {
|
||||||
|
var index = parseInt((age || 10) / 10);
|
||||||
|
if (index >= age_strs.length) index = age_strs.length - 1;
|
||||||
|
return age_strs[index];
|
||||||
|
}
|
||||||
|
function get_skill_desc(level) {
|
||||||
|
if (!level) return "看上去似乎不会任何武功。";
|
||||||
|
|
||||||
|
if (level < 1000)
|
||||||
|
return "的武功看上去似乎" + skill_levels[parseInt(level / 50)];
|
||||||
|
var v = parseInt((level - 1000) / 500);
|
||||||
|
if (v > 6) v = 6;
|
||||||
|
return "的武功看上去似乎" + skill_levels[v + 20];
|
||||||
|
}
|
||||||
|
function get_status(obj) {
|
||||||
|
var p = parseInt(obj.hp * 10 / obj.max_hp);
|
||||||
|
if (p < 0) p = 0;
|
||||||
|
if (p >= Look_status.length) p = Look_status.length - 1;
|
||||||
|
return Look_status[p];
|
||||||
|
}
|
||||||
|
|
||||||
|
var boy_pers = [
|
||||||
|
"<BLU>眉歪眼斜,瘌头癣脚,不象人样</BLU>",
|
||||||
|
"<BLU>呲牙咧嘴,黑如锅底,奇丑无比</BLU>",
|
||||||
|
"<BLU>面如桔皮,头肿如猪,让人不想再看第二眼</BLU>",
|
||||||
|
"<HIB>贼眉鼠眼,身高三尺,宛若猴状</HIB>",
|
||||||
|
"<HIB>肥头大耳,腹圆如鼓,手脚短粗,令人发笑</HIB>",
|
||||||
|
"<NOR>面颊凹陷,瘦骨伶仃,可怜可叹</NOR>",
|
||||||
|
"<NOR>傻头傻脑,痴痴憨憨,看来倒也老实</NOR>",
|
||||||
|
"<NOR>相貌平平,不会给人留下什么印象</NOR>",
|
||||||
|
"<YEL>膀大腰圆,满脸横肉,恶形恶相</YEL>",
|
||||||
|
"<YEL>腰圆背厚,面阔口方,骨格不凡</YEL>",
|
||||||
|
"<RED>眉目清秀,端正大方,一表人才</RED>",
|
||||||
|
"<RED>双眼光华莹润,透出摄人心魄的光芒</RED>",
|
||||||
|
"<HIY>举动如行云游水,独蕴风情,吸引所有异性目光</HIY>",
|
||||||
|
"<HIY>双目如星,眉梢传情,所见者无不为之心动</HIY>",
|
||||||
|
"<HIR>粉面朱唇,身姿俊俏,举止风流无限</HIR>",
|
||||||
|
"<HIR>丰神如玉,目似朗星,令人过目难忘</HIR>",
|
||||||
|
"<MAG>面如美玉,粉妆玉琢,俊美不凡</MAG>",
|
||||||
|
"<MAG>飘逸出尘,潇洒绝伦</MAG>",
|
||||||
|
"<MAG>丰神俊朗,长身玉立,宛如玉树临风</MAG>",
|
||||||
|
"<HIM>神清气爽,骨格清奇,宛若仙人</HIM>",
|
||||||
|
"<HIM>一派神人气度,仙风道骨,举止出尘</HIM>"
|
||||||
|
];
|
||||||
|
var girl_pers = [
|
||||||
|
"<BLU>丑如无盐,状如夜叉</BLU>",
|
||||||
|
"<BLU>歪鼻斜眼,脸色灰败,直如鬼怪一般</BLU>",
|
||||||
|
"<BLU>八字眉,三角眼,鸡皮黄发,让人一见就想吐</BLU>",
|
||||||
|
"<HIB>眼小如豆,眉毛稀疏,手如猴爪,不成人样</HIB>",
|
||||||
|
"<HIB>一嘴大暴牙,让人一看就没好感</HIB>",
|
||||||
|
"<NOR>满脸疙瘩,皮色粗黑,丑陋不堪</NOR>",
|
||||||
|
"<NOR>干黄枯瘦,脸色腊黄,毫无女人味</NOR>",
|
||||||
|
"<YEL>身材瘦小,肌肤无光,两眼无神</YEL>",
|
||||||
|
"<YEL>虽不标致,倒也白净,有些动人之处</YEL>",
|
||||||
|
"<RED>肌肤微丰,雅淡温宛,清新可人</RED>",
|
||||||
|
"<RED>鲜艳妍媚,肌肤莹透,引人遐思</RED>",
|
||||||
|
"<HIR>娇小玲珑,宛如飞燕再世,楚楚动人</HIR>",
|
||||||
|
"<HIR>腮凝新荔,肌肤胜雪,目若秋水</HIR>",
|
||||||
|
"<HIW>粉嫩白至,如芍药笼烟,雾里看花</HIW>",
|
||||||
|
"<HIW>丰胸细腰,妖娆多姿,让人一看就心跳不已</HIW>",
|
||||||
|
"<MAG>娇若春花,媚如秋月,真的能沉鱼落雁</MAG>",
|
||||||
|
"<MAG>眉目如画,肌肤胜雪,真可谓闭月羞花</MAG>",
|
||||||
|
"<MAG>气质美如兰,才华馥比山,令人见之忘俗</MAG>",
|
||||||
|
"<HIM>灿若明霞,宝润如玉,恍如神妃仙子</HIM>",
|
||||||
|
"<HIM>美若天仙,不沾一丝烟尘</HIM>",
|
||||||
|
"<HIM>宛如<HIW>玉雕冰塑</HIW>,似梦似幻,已不再是凡间人物</HIM>"
|
||||||
|
];
|
||||||
|
|
||||||
|
var Look_status = [
|
||||||
|
"<HIR>受伤过重,已经有如风中残烛,随时都可能断气。</HIR>",
|
||||||
|
"<HIR>受伤过重,已经奄奄一息,命在旦夕了。</HIR>",
|
||||||
|
"<HIR>伤重之下已经难以支撑,眼看就要倒在地上。</HIR>",
|
||||||
|
"<RED>受了相当重的伤,只怕会有生命危险。</RED>",
|
||||||
|
"<RED>已经伤痕累累,正在勉力支撑著不倒下去。</RED>",
|
||||||
|
"<RED>气息粗重,动作开始散乱,看来所受的伤著实不轻。</RED>",
|
||||||
|
"<HIY>受伤不轻,看起来状况并不太好。</HIY>",
|
||||||
|
"<HIY>受了几处伤,不过似乎并不碍事。</HIY>",
|
||||||
|
"<HIY>看起来可能受了点轻伤。</HIY>",
|
||||||
|
"<HIG>似乎受了点轻伤,不过光从外表看不大出来。</HIG>",
|
||||||
|
"<HIG>看起来气血充盈,并没有受伤。</HIG>"
|
||||||
|
];
|
||||||
|
|
||||||
|
var age_strs = ["几", "十多", "二十多", "三十多", "四十多", "五十多", "六十多", "七十多", "八十多", "九十多"
|
||||||
|
, "一百多"];
|
||||||
|
var skill_levels = [
|
||||||
|
"<BLU>初学乍练</BLU>",
|
||||||
|
"<BLU>不知所以</BLU>",
|
||||||
|
"<HIB>粗通皮毛</HIB>",
|
||||||
|
"<HIB>渐有所悟</HIB>",
|
||||||
|
"<YEL>半生不熟</YEL>",
|
||||||
|
"<YEL>马马虎虎</YEL>",
|
||||||
|
"<HIY>平淡无奇</HIY>",
|
||||||
|
"<HIY>触类旁通</HIY>",
|
||||||
|
"<HIG>心领神会</HIG>",
|
||||||
|
"<HIG>挥洒自如</HIG>",
|
||||||
|
"<HIC>驾轻就熟</HIC>",
|
||||||
|
"<HIC>出类拔萃</HIC>",
|
||||||
|
"<CYN>初入佳境</CYN>",
|
||||||
|
"<CYN>神乎其技</CYN>",
|
||||||
|
"<MAG>威不可当</MAG>",
|
||||||
|
"<HIW>豁然贯通</HIW>",
|
||||||
|
"<HIW>超群绝伦</HIW>",
|
||||||
|
"<RED>登峰造极</RED>",
|
||||||
|
"<WHT>登堂入室</WHT>",
|
||||||
|
"<HIM>一代宗师</HIM>",
|
||||||
|
"<WHT>超凡入圣</WHT>",
|
||||||
|
"<HIO>出神入化</HIO>",
|
||||||
|
"<HIO>独步天下</HIO>",
|
||||||
|
"<HIR>空前绝后</HIR>",
|
||||||
|
"<HIR>旷古绝伦</HIR>",
|
||||||
|
"<HIW>深不可测</HIW>",
|
||||||
|
"<HIW>返璞归真</HIW>"];
|
||||||
175
os/char/chara_equip.js
Normal file
175
os/char/chara_equip.js
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
|
||||||
|
require("./character.js");
|
||||||
|
CHARACTER.prototype.set_objects = function () {
|
||||||
|
if (!arguments.length) return;
|
||||||
|
if (!this.items) this.items = [];
|
||||||
|
for (var i = 0; i < arguments.length; i++) {
|
||||||
|
var item = arguments[i];
|
||||||
|
var obj = OBJ.CREATE(item[0], item[1]);
|
||||||
|
if (!obj) continue;
|
||||||
|
if (item[2] && obj.is_equipment) {
|
||||||
|
if (!this.equipment) this.equipment = []
|
||||||
|
this.equipment[obj.eq_type] = obj;
|
||||||
|
} else {
|
||||||
|
this.items.push(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.unequip = function (obj, notsend, recover_time = 0) {
|
||||||
|
if (!obj || !obj.is_equipment || !this.equipment) return;
|
||||||
|
if (obj.uneq(this, notsend) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (obj != this.equipment[obj.eq_type]) return;
|
||||||
|
if (!this.items) this.items = [];
|
||||||
|
this.items.push(obj);
|
||||||
|
this.equipment[obj.eq_type] = null;
|
||||||
|
if (obj.eq_type == EQUIP_TYPE.WEAPON) {
|
||||||
|
this.remove_status('weapon', true);
|
||||||
|
if (obj.is_shortcut) {
|
||||||
|
this.send("{type:'addAction',id:'" + obj.id + "',name:'" + obj.name + "'}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.eq_type === EQUIP_TYPE.WEAPON)
|
||||||
|
this.weapon_changed(false);
|
||||||
|
this.recount();
|
||||||
|
if (recover_time > 0 && this.is_player) {
|
||||||
|
this.set_temp('eq_wea', obj.id, 60000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CHARACTER.prototype.equip = function (obj) {
|
||||||
|
if (!obj || !obj.is_equipment) return;
|
||||||
|
if (!this.equipment) this.equipment = []
|
||||||
|
var equiped = this.equipment[obj.eq_type];
|
||||||
|
if (equiped == obj) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (equiped) {
|
||||||
|
equiped.uneq(this);
|
||||||
|
this.equipment[equiped.eq_type] = null;
|
||||||
|
this.items.push(equiped);
|
||||||
|
if (equiped.eq_type == EQUIP_TYPE.WEAPON) {
|
||||||
|
this.remove_status('weapon', true);
|
||||||
|
}
|
||||||
|
if (equiped.on_use) {
|
||||||
|
equiped.notify_action(this, false);
|
||||||
|
}
|
||||||
|
if (equiped.is_shortcut) {
|
||||||
|
this.send("{type:'addAction',id:'" + equiped.id + "',name:'" + equiped.name + "'}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (obj.eq(this) == false) {
|
||||||
|
if (equiped) {
|
||||||
|
if (obj.eq_type === EQUIP_TYPE.WEAPON)
|
||||||
|
this.weapon_changed(false);
|
||||||
|
this.recount();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.items.remove(obj);
|
||||||
|
this.equipment[obj.eq_type] = obj;
|
||||||
|
if (obj.eq_type === EQUIP_TYPE.WEAPON)
|
||||||
|
this.weapon_changed(true);
|
||||||
|
this.recount();
|
||||||
|
if (obj.is_shortcut) {
|
||||||
|
this.send("{type:'removeAction',id:'" + obj.id + "'}");
|
||||||
|
}
|
||||||
|
if (obj.eq_type == EQUIP_TYPE.WEAPON) {
|
||||||
|
if (this.fight_type) {
|
||||||
|
this.release_time = 3000 + Date.now();
|
||||||
|
this.send('{type:"dispfm",rtime:3000}');
|
||||||
|
}
|
||||||
|
if (this.query_temp('jxtm')) {
|
||||||
|
this.remove_status('force');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const WEAPON_TYPES = {
|
||||||
|
"sword": true,
|
||||||
|
"blade": true,
|
||||||
|
"staff": true,
|
||||||
|
"club": true,
|
||||||
|
"whip": true
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.weapon_changed = function (iseq) {
|
||||||
|
this.attack_skill = this.query_used_skill(this.query_weapon_type());
|
||||||
|
this.on_skillchanged && this.on_skillchanged();
|
||||||
|
if (!this.auto_skills) return;
|
||||||
|
|
||||||
|
for (let item of this.auto_skills) {
|
||||||
|
if (WEAPON_TYPES[item.type]) {
|
||||||
|
item.ban_use = !iseq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.add_obj = function (obj, count) {
|
||||||
|
if (!obj) return;
|
||||||
|
if (typeof obj == "string") {
|
||||||
|
obj = OBJ.clone_to(obj, this, count);
|
||||||
|
if (!obj) return;
|
||||||
|
} else {
|
||||||
|
obj = this.push_item(obj);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.remove_obj = function (obj, count) {
|
||||||
|
if (typeof obj == "string") {
|
||||||
|
obj = this.find_obj(obj);
|
||||||
|
}
|
||||||
|
if (!obj) return;
|
||||||
|
count = count || obj.count || 1;
|
||||||
|
this.remove_item(obj, count);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_weapon = function () {
|
||||||
|
if (this.equipment) {
|
||||||
|
return this.equipment[EQUIP_TYPE.WEAPON];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_weapon_type = function () {
|
||||||
|
if (this.equipment) {
|
||||||
|
var eq = this.equipment[EQUIP_TYPE.WEAPON];
|
||||||
|
if (eq) return eq.weapon_type;
|
||||||
|
}
|
||||||
|
return WEAPON_TYPE.NONE;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.weapon_name = function () {
|
||||||
|
if (this.equipment && this.equipment[EQUIP_TYPE.WEAPON]) {
|
||||||
|
return this.equipment[EQUIP_TYPE.WEAPON].color_name;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.throwing_name = function () {
|
||||||
|
if (this.equipment && this.equipment[EQUIP_TYPE.THROWING]) {
|
||||||
|
return this.equipment[EQUIP_TYPE.THROWING].color_name;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.can_throwing = function () {
|
||||||
|
if (this.equipment) {
|
||||||
|
var th = this.equipment[EQUIP_TYPE.THROWING];
|
||||||
|
if (!th) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.get_equipment = function (type) {
|
||||||
|
return this.equipment && this.equipment[type];
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.set_drop = function () {
|
||||||
|
this.drop_list = this.drop_list || [];
|
||||||
|
for (var i = 0; i < arguments.length; i++) {
|
||||||
|
this.drop_list.push(arguments[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_drop = function () {
|
||||||
|
if (!this.drop_list) return;
|
||||||
|
return OBJ.create_by_odds(this.drop_list);
|
||||||
|
|
||||||
|
}
|
||||||
169
os/char/chara_move.js
Normal file
169
os/char/chara_move.js
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
|
||||||
|
|
||||||
|
CHARACTER.prototype.moveto = function (rm, leave_msg, in_msg, dir) {
|
||||||
|
var cur_room = this.environment;
|
||||||
|
var next_room = rm;
|
||||||
|
if (typeof rm === "string") {
|
||||||
|
next_room = ROOM.Get(rm);
|
||||||
|
if (!next_room) return false;
|
||||||
|
if (next_room.parent === cur_room.parent) {
|
||||||
|
if (cur_room.owner) {
|
||||||
|
next_room = next_room.query_copy(cur_room.owner);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var my_room = next_room.query_copy2(this);
|
||||||
|
if (my_room) {
|
||||||
|
next_room = my_room;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!next_room) return false;
|
||||||
|
|
||||||
|
if (next_room.is_full()) {
|
||||||
|
//如果房间人数过多,创建投影
|
||||||
|
next_room = next_room.create_shadow();
|
||||||
|
if (!next_room) {
|
||||||
|
//如果创建失败就返回,房间设置不允许投影,或别的原因
|
||||||
|
return this.notify("那里人太多了,你过不去。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cur_room) {
|
||||||
|
if (cur_room.do_leave(this, dir, leave_msg) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next_room.do_enter(this, true, in_msg);
|
||||||
|
this.notify_follower(dir);
|
||||||
|
if (cur_room && next_room.parent !== cur_room.parent) {
|
||||||
|
cur_room.parent.on_leaved(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.do_follow = function (target) {
|
||||||
|
if (target) {
|
||||||
|
if (target.query_setting("no_follow")) {
|
||||||
|
return this.notify(target.name + "不允许别人跟随。");
|
||||||
|
}
|
||||||
|
if (this.follow_target) {
|
||||||
|
this.follow_target.follow_targets.remove(this);
|
||||||
|
this.send_room("$N不再跟随$n一起行动。", this.follow_target);
|
||||||
|
}
|
||||||
|
this.follow_target = target;
|
||||||
|
if (!target.follow_targets) {
|
||||||
|
target.follow_targets = [];
|
||||||
|
}
|
||||||
|
target.follow_targets.push(this);
|
||||||
|
this.send_room("<hig>$N决定跟随$n一起行动。</hig>", target);
|
||||||
|
} else {
|
||||||
|
if (!this.follow_target) return this.notify("你目前没有跟随别人一起行动。");
|
||||||
|
this.follow_target.follow_targets.remove(this);
|
||||||
|
this.send_room("$N不再跟随$n一起行动。", this.follow_target);
|
||||||
|
this.follow_target = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.clear_follow = function () {
|
||||||
|
if (this.follow_target) {
|
||||||
|
this.follow_target.follow_targets.remove(this);
|
||||||
|
this.follow_target = null;
|
||||||
|
}
|
||||||
|
if (this.follow_targets) {
|
||||||
|
for (let item of this.follow_targets) {
|
||||||
|
item.follow_target = null;
|
||||||
|
}
|
||||||
|
this.follow_targets = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.notify_follower = function (dir) {
|
||||||
|
if (this.follow_targets) {
|
||||||
|
for (var i = 0; i < this.follow_targets.length; i++) {
|
||||||
|
var item = this.follow_targets[i];
|
||||||
|
if (!item.environment) continue;
|
||||||
|
if (!item.is_player) {
|
||||||
|
if (item.on_master_leave) {
|
||||||
|
if (item.on_master_leave(this, this.environment) == false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (item.environment.is_fb() != this.environment.is_fb()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if (item.state && item.set_state) {
|
||||||
|
// item.set_state(null);
|
||||||
|
//}
|
||||||
|
item.moveto(this.environment,
|
||||||
|
sendOutMessage(item, dir), sendInMessage(item));
|
||||||
|
} else {
|
||||||
|
item.moveto(this.environment,
|
||||||
|
sendOutMessage(item, dir), sendInMessage(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.do_escape = function () {
|
||||||
|
var eny = this.query_enemy();
|
||||||
|
if (!eny) return true;
|
||||||
|
if (eny.on_escape) return eny.on_escape(this);
|
||||||
|
var is_esc = this.random(this.ds / 2) + this.ds > eny.mz;
|
||||||
|
if (eny.is_faint) is_esc = true;
|
||||||
|
if (!is_esc) {
|
||||||
|
this.send_room("<cyn>$N转身想跑,$n一把拦住$P:想跑?没门!\n</cyn>", eny);
|
||||||
|
this.add_status({
|
||||||
|
id: "busy",
|
||||||
|
name: "忙乱",
|
||||||
|
duration: this.gjsd,
|
||||||
|
is_busy: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return is_esc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CHARACTER.prototype.team_out = function (msg) {
|
||||||
|
var tm = this.team;
|
||||||
|
if (!tm) return;
|
||||||
|
for (var i = 0; i < tm.length; i++) {
|
||||||
|
if (!tm[i].is_player && tm[i].master == this.id) {
|
||||||
|
tm[i].on_teamout && tm[i].on_teamout();
|
||||||
|
this.notify(tm[i].name + "退出了队伍。");
|
||||||
|
tm[i].team = null;
|
||||||
|
tm.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.team = null;
|
||||||
|
var iscap = this == tm[0];
|
||||||
|
tm.remove(this);
|
||||||
|
checkTeamfb(this);
|
||||||
|
if (!tm.length) {
|
||||||
|
this.send("你的队伍解散了。");
|
||||||
|
this.send('{"type":"dialog","dialog":"team",dismiss:true}');
|
||||||
|
} else {
|
||||||
|
var first = tm[0];
|
||||||
|
var dissmsg = '{"type":"dialog","dialog":"team",dismiss:true}';
|
||||||
|
this.send("<hic>你退出了队伍。</hic>");
|
||||||
|
|
||||||
|
|
||||||
|
if (tm.length > 1) {
|
||||||
|
if (iscap) {
|
||||||
|
first.send_team("<hic>" + this.name + msg + "," + first.name + "现在是队长。</hic>");
|
||||||
|
} else {
|
||||||
|
first.send_team("<hic>" + this.name + msg + "。</hic>");
|
||||||
|
}
|
||||||
|
first.send_team('{"type":"dialog","dialog":"team",remove:"' + this.id + '"}');
|
||||||
|
this.send(dissmsg);
|
||||||
|
} else {
|
||||||
|
if (first.team) {
|
||||||
|
checkTeamfb(first);
|
||||||
|
first.send("<hic>" + this.name + msg + ",你的队伍解散了。</hic>");
|
||||||
|
first.team.length = 0;
|
||||||
|
first.team = null;
|
||||||
|
first.send(dissmsg);
|
||||||
|
this.send(dissmsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
137
os/char/chara_prop.js
Normal file
137
os/char/chara_prop.js
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
|
||||||
|
require("./character.js");
|
||||||
|
CHARACTER.prototype.add_prop = function (p, v) {
|
||||||
|
if (!p) return;
|
||||||
|
if (!this.prop) {
|
||||||
|
this.prop = {};
|
||||||
|
}
|
||||||
|
var v1 = this.prop[p] || 0;
|
||||||
|
|
||||||
|
this.prop[p] = v1 + v;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.clear_prop = function () {
|
||||||
|
this.prop = {};
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_prop = function (name) {
|
||||||
|
if (this.prop)
|
||||||
|
return this.prop[name] || 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_force_rad = function () {
|
||||||
|
if (this.force_skill && this.force_skill.force_rad)
|
||||||
|
return this.force_skill.force_rad || 0.1;
|
||||||
|
return 0.1;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.add_maxmp = function (count) {
|
||||||
|
this.max_mp += count;
|
||||||
|
this.recount();
|
||||||
|
this.notify("<hig>你增加了" + count + "点内力。</hig>");
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_temp = function (name, def) {
|
||||||
|
if (!this.temp) return def;
|
||||||
|
var item = this.temp[name];
|
||||||
|
if (item && item.e) {
|
||||||
|
if (Date.now() <= item.e) {
|
||||||
|
return item.v;
|
||||||
|
}
|
||||||
|
this.temp[name] = null;
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
return item ?? def;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.set_temp = function (name, value, time) {
|
||||||
|
if (!this.temp) this.temp = {};
|
||||||
|
if (time) {
|
||||||
|
this.temp[name] = {
|
||||||
|
v: value,
|
||||||
|
e: Date.now() + time
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
this.temp[name] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.remove_temp = function (name) {
|
||||||
|
if (!this.temp) return;
|
||||||
|
this.temp[name] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.add_temp = function (name, value, time) {
|
||||||
|
let val = this.query_temp(name, 0) + value;
|
||||||
|
this.set_temp(name, val, time);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.change_prop = function (prop, isadd) {
|
||||||
|
if (!prop) return;
|
||||||
|
for (var item in prop) {
|
||||||
|
switch (item) {
|
||||||
|
case "desc":
|
||||||
|
break;
|
||||||
|
case "skill":
|
||||||
|
var sks = prop[item];
|
||||||
|
for (var sk in sks) {
|
||||||
|
var lv = this.query_skill(sk, 0);
|
||||||
|
if (!lv) {
|
||||||
|
this.add_prop(sk, isadd ? sks[sk] : -sks[sk]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var sk_base = SKILL.get(sk);
|
||||||
|
if (!sk_base) continue;
|
||||||
|
sk_base.release_prop(this, lv);
|
||||||
|
|
||||||
|
this.add_prop(sk, isadd ? sks[sk] : -sks[sk]);
|
||||||
|
|
||||||
|
lv = this.query_skill(sk, 0);
|
||||||
|
|
||||||
|
sk_base.attach_prop(this, lv);
|
||||||
|
if (this.is_player) {
|
||||||
|
this.notify('{type:"dialog",dialog:"skills",id:"' + sk + '",level:' + lv + '}');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.add_prop(item, isadd ? prop[item] : -prop[item]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.add_fbscore = function (v, max) {
|
||||||
|
var fb = this.environment.query_fb_first(this.query_teamid());
|
||||||
|
if (!fb) return;
|
||||||
|
fb.score = (fb.score || 0) + v;
|
||||||
|
if (max > 0 && fb.score > max) fb.score = max;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_fbscore = function (v) {
|
||||||
|
var first_room = this.environment.query_fb_first(this.query_teamid());
|
||||||
|
if (!first_room) return 0;
|
||||||
|
return first_room.score || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.add_score = function (val) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.add_combat_prop = function (name, val) {
|
||||||
|
this.add_prop(name, val);
|
||||||
|
if (!this.combat_props) this.combat_props = [];
|
||||||
|
this.combat_props.push([name, val]);
|
||||||
|
if (name === 'max_hp') {
|
||||||
|
this.max_hp += val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CHARACTER.prototype.clear_combat_prop = function (name, val) {
|
||||||
|
if (this.combat_props) {
|
||||||
|
for (let i = 0; i < this.combat_props.length; i++) {
|
||||||
|
this.add_prop(this.combat_props[i][0], -this.combat_props[i][1]);
|
||||||
|
if (this.combat_props[i][0] === 'max_hp') {
|
||||||
|
this.max_hp -= this.combat_props[i][1];
|
||||||
|
this.notify_hp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.combat_props = null;
|
||||||
|
this.recount();
|
||||||
|
}
|
||||||
|
}
|
||||||
566
os/char/chara_skill.js
Normal file
566
os/char/chara_skill.js
Normal file
@@ -0,0 +1,566 @@
|
|||||||
|
|
||||||
|
require("./character.js");
|
||||||
|
CHARACTER.prototype.query_skill = function (name, def) {
|
||||||
|
if (!this.skills || !this.skills[name]) return def || 0;
|
||||||
|
return this.skills[name].level + this.query_prop(name);
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.skill_map = function () {
|
||||||
|
//给NPC初始化技能用的,不做任何判断
|
||||||
|
this.skills = this.skills || {};
|
||||||
|
for (var i = 0; i < arguments.length; i++) {
|
||||||
|
var item = arguments[i];
|
||||||
|
if (!item) continue;
|
||||||
|
var skill_base = SKILL.get(item[0]);
|
||||||
|
if (!skill_base) {
|
||||||
|
console.log(item[0] + " not exits")
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var skill = {
|
||||||
|
level: item[1] || 1,
|
||||||
|
exp: 0
|
||||||
|
};
|
||||||
|
this.skills[skill_base.id] = skill;
|
||||||
|
if (item[2]) {
|
||||||
|
var enables = item[2];
|
||||||
|
if (typeof enables == "string") enables = [enables];
|
||||||
|
for (var j = 0; j < enables.length; j++) {
|
||||||
|
|
||||||
|
skill[enables[j]] = true;
|
||||||
|
this.skills[enables[j]].enable_skill = item[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.remove_skill = function (skillid) {
|
||||||
|
var skill = this.skills[skillid];
|
||||||
|
if (!skill) return;
|
||||||
|
var baseskill = SKILL.get(skillid);
|
||||||
|
if (!baseskill) return false;
|
||||||
|
|
||||||
|
if (baseskill.type == SKILL_TYPES.BASE) {
|
||||||
|
if (skill.enable_skill) {
|
||||||
|
var old_skill = SKILL.get(skill.enable_skill);
|
||||||
|
if (!old_skill || !this.skills[skill.enable_skill]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
old_skill.disenable(this, skillid);
|
||||||
|
this.skills[skill.enable_skill][skillid] = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var key in this.skills) {
|
||||||
|
if (this.skills[key].enable_skill == skillid) {
|
||||||
|
|
||||||
|
this.skills[key].enable_skill = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
baseskill.release_prop(this, this.query_skill(skillid));
|
||||||
|
delete this.skills[skillid];
|
||||||
|
this.init_skill();
|
||||||
|
this.recount();
|
||||||
|
this.add_score(-baseskill.query_score(skill.level, this));
|
||||||
|
baseskill.on_remove && baseskill.on_remove(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//增加技能
|
||||||
|
CHARACTER.prototype.set_skill = function (skid, level) {
|
||||||
|
if (!this.skills) this.skills = {};
|
||||||
|
var item = this.skills[skid];
|
||||||
|
var skill_base = SKILL.get(skid);
|
||||||
|
if (!skill_base) return;
|
||||||
|
if (!item) {
|
||||||
|
item = {
|
||||||
|
//id: skid,
|
||||||
|
level: level,
|
||||||
|
exp: 0
|
||||||
|
};
|
||||||
|
this.skills[skid] = item;
|
||||||
|
skill_base.attach_prop(this, level);
|
||||||
|
} else {
|
||||||
|
skill_base.release_prop(this, this.query_skill(skid));
|
||||||
|
item.level = level;
|
||||||
|
skill_base.attach_prop(this, this.query_skill(skid));
|
||||||
|
}
|
||||||
|
this.init_skill();
|
||||||
|
this.recount();
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.skill_limit = function () {
|
||||||
|
if (this.exp < 100) return 10;
|
||||||
|
switch (this.level) {
|
||||||
|
case 1: return Math.round(Math.pow(this.exp * 20, 1 / 3));
|
||||||
|
case 2: return Math.round(Math.pow(this.exp * 30, 1 / 3));
|
||||||
|
case 3: return Math.round(Math.pow(this.exp * 40, 1 / 3));
|
||||||
|
case 4: return Math.round(Math.pow(this.exp * 50, 1 / 3));
|
||||||
|
case 5: return Math.round(Math.pow(this.exp * 60, 1 / 3));
|
||||||
|
case 6: return Math.round(Math.pow(this.exp * 60, 1 / 3));
|
||||||
|
default:
|
||||||
|
return Math.round(Math.pow(this.exp * 10, 1 / 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.query_ref_skill = function (skill) {
|
||||||
|
if (!skill || !skill.ref) return;
|
||||||
|
var refs = skill.ref.split("/");
|
||||||
|
var sp_skill = SKILL.get(refs[0]);
|
||||||
|
if (sp_skill) {
|
||||||
|
return sp_skill.get_pfm(refs[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//判断某个技能是否装备到某个基本技能上
|
||||||
|
CHARACTER.prototype.is_enable_skill = function (skid, type) {
|
||||||
|
if (!this.skills) return;
|
||||||
|
var item = this.skills[skid];
|
||||||
|
if (!item) return;
|
||||||
|
return item[type];
|
||||||
|
}
|
||||||
|
//装备技能到基本技能
|
||||||
|
CHARACTER.prototype.enable_skill = function (base, skill) {
|
||||||
|
if (!this.skills) return;
|
||||||
|
var baseskill = this.skills[base];
|
||||||
|
if (!baseskill) return;
|
||||||
|
if (baseskill.enable_skill) {
|
||||||
|
var old_skill = this.skills[baseskill.enable_skill];
|
||||||
|
if (!old_skill) return;
|
||||||
|
old_skill[base] = false;
|
||||||
|
|
||||||
|
old_skill = SKILL.get(baseskill.enable_skill);
|
||||||
|
if (old_skill) {
|
||||||
|
old_skill.disenable(this, base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skill) {
|
||||||
|
var sp_skill = this.skills[skill];
|
||||||
|
|
||||||
|
if (baseskill && sp_skill) {
|
||||||
|
var sp_skill_base = SKILL.get(skill);
|
||||||
|
if (!sp_skill_base || sp_skill_base.enable(this, base) !== true)
|
||||||
|
return false;
|
||||||
|
baseskill.enable_skill = skill;
|
||||||
|
sp_skill[base] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
baseskill.enable_skill = null;
|
||||||
|
}
|
||||||
|
this.init_skill();
|
||||||
|
this.recount();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//初始化人物使用的技能
|
||||||
|
CHARACTER.prototype.init_skill = function () {
|
||||||
|
this.attack_skill = this.query_used_skill(this.query_weapon_type());
|
||||||
|
this.noweapon_skill = this.query_used_skill(WEAPON_TYPE.NONE);
|
||||||
|
this.dodge_skill = this.query_used_skill(BASE_SKILLS.DODGE);
|
||||||
|
this.parry_skill = this.query_used_skill(BASE_SKILLS.PARRY);
|
||||||
|
this.force_skill = this.query_used_skill(BASE_SKILLS.FORCE);
|
||||||
|
this.on_skillchanged && this.on_skillchanged();
|
||||||
|
this.auto_skills = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.query_used_skill = function (skname) {
|
||||||
|
if (!this.skills) {
|
||||||
|
return WORLD.DEFAULT_SKILLS[skname];
|
||||||
|
}
|
||||||
|
var skill = this.skills[skname];
|
||||||
|
if (skill) {
|
||||||
|
|
||||||
|
var skill_base = SKILL.get(skill.enable_skill || skname);
|
||||||
|
if (!skill_base) skill.enable_skill = null;
|
||||||
|
else return skill_base;
|
||||||
|
}
|
||||||
|
return WORLD.DEFAULT_SKILLS[skname];
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_status = function (sid) {
|
||||||
|
if (!this.status) return 0;
|
||||||
|
for (var i = 0; i < this.status.length; i++) {
|
||||||
|
if (this.status[i].id == sid) {
|
||||||
|
return this.status[i].count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.add_status = function (buff, from) {
|
||||||
|
if (this.hp <= 0) return false;
|
||||||
|
if (!this.status) this.status = [];
|
||||||
|
var sid = buff.id;
|
||||||
|
buff.override = buff.override || 0;
|
||||||
|
buff.count = buff.count || 1;
|
||||||
|
buff.max_count = buff.max_count || 10;
|
||||||
|
|
||||||
|
buff.start_time = Date.now();
|
||||||
|
if (buff.on_interval) {
|
||||||
|
buff.over_count = buff.over_count || 0;
|
||||||
|
}
|
||||||
|
if (this.ig_control && !buff.no_diff) {
|
||||||
|
if (buff.is_busy || buff.is_faint || buff.is_miss || buff.is_rash) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buff.downside && buff.duration && !buff.no_diff) {
|
||||||
|
//buff.duration = buff.duration - this.query_prop("diff_downside");
|
||||||
|
buff.duration = Math.round(buff.duration * (100 - this.query_prop("diff_downside_per")) / 100);
|
||||||
|
if (buff.duration <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buff.is_busy && !buff.no_diff) {
|
||||||
|
if (from) {
|
||||||
|
buff.duration = buff.duration + from.query_prop("busy");
|
||||||
|
buff.duration = buff.duration * (100 + from.query_prop("busy_per")) / 100;
|
||||||
|
}
|
||||||
|
buff.duration = buff.duration - this.query_prop("diff_busy");
|
||||||
|
buff.duration = Math.round(buff.duration * (100 - this.query_prop("diff_busy_per")) / 100);
|
||||||
|
if (buff.duration <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < this.status.length; i++) {
|
||||||
|
|
||||||
|
if (this.status[i].id == sid) {
|
||||||
|
var item = this.status[i];
|
||||||
|
if (item.override != buff.override) return false;
|
||||||
|
if (item.override == 0) {
|
||||||
|
//0不覆盖 1叠加 2覆盖替换
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (item.override == 1) {
|
||||||
|
if (item.max_count <= item.count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
item.count += buff.count;
|
||||||
|
clearTimeout(item.handler);
|
||||||
|
if (item.duration)
|
||||||
|
item.handler = this.call_out(this.remove_status, item.duration, sid);
|
||||||
|
this.change_buff(item, true, buff.count);
|
||||||
|
item.start_time = buff.start_time;
|
||||||
|
this.status_changed(item, "refresh");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
item.handler && clearTimeout(item.handler);
|
||||||
|
this.change_buff(item, false, item.count);//覆盖先移除 后添加 重新计时
|
||||||
|
this.status_changed(item, "remove");
|
||||||
|
if (buff.duration)
|
||||||
|
item.handler = this.call_out(this.remove_status, buff.duration, sid);
|
||||||
|
this.status[i] = buff;
|
||||||
|
buff.start_time = buff.start_time;
|
||||||
|
this.change_buff(buff, true, buff.count);
|
||||||
|
this.status_changed(buff, "add");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buff.duration)
|
||||||
|
buff.handler = this.call_out(this.remove_status, buff.duration, sid);
|
||||||
|
this.status.push(buff);
|
||||||
|
|
||||||
|
this.change_buff(buff, true, buff.count);
|
||||||
|
this.status_changed(buff, "add");
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.clear_downside = function (type) {
|
||||||
|
if (!this.status) return;
|
||||||
|
var removed = "0";
|
||||||
|
var count = 0;
|
||||||
|
for (var i = 0; i < this.status.length; i++) {
|
||||||
|
var item = this.status[i];
|
||||||
|
if ((item.downside || false) == type && !item.no_clear) {
|
||||||
|
|
||||||
|
this.change_buff(item, false, item.count);
|
||||||
|
item.handler && clearTimeout(item.handler);
|
||||||
|
this.status.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
removed += ',"' + item.id + '"';
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (removed.length == 1 || !this.environment) return;
|
||||||
|
var items = this.environment.items;
|
||||||
|
var msg = '{type:"status",id:"' + this.id + '",sid:[' + removed + '],action:"remove"}';
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var player = items[i];
|
||||||
|
if (player.is_player) {
|
||||||
|
player.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CHARACTER.prototype.clear_combat_status = function () {
|
||||||
|
if (!this.status || !this.status.length) return;
|
||||||
|
var removed = "0";
|
||||||
|
for (var i = this.status.length - 1; i >= 0; i--) {
|
||||||
|
var item = this.status[i];
|
||||||
|
if (item.only_combat) {
|
||||||
|
this.change_buff(item, false, item.count);
|
||||||
|
item.handler && clearTimeout(item.handler);
|
||||||
|
this.status.splice(i, 1);
|
||||||
|
removed += ',"' + item.id + '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (removed.length == 1 || !this.environment) return;
|
||||||
|
var items = this.environment.items;
|
||||||
|
var msg = '{type:"status",id:"' + this.id + '",sid:[' + removed + '],action:"remove"}';
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var player = items[i];
|
||||||
|
if (player.is_player) {
|
||||||
|
player.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.remvoe_statuses = function (func) {
|
||||||
|
if (!this.status || !this.status.length) return;
|
||||||
|
var removed = "0";
|
||||||
|
for (var i = this.status.length - 1; i >= 0; i--) {
|
||||||
|
var item = this.status[i];
|
||||||
|
if (func(item)) {
|
||||||
|
this.change_buff(item, false, item.count);
|
||||||
|
item.handler && clearTimeout(item.handler);
|
||||||
|
this.status.splice(i, 1);
|
||||||
|
removed += ',"' + item.id + '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (removed.length == 1 || !this.environment) return;
|
||||||
|
var items = this.environment.items;
|
||||||
|
var msg = '{type:"status",id:"' + this.id + '",sid:[' + removed + '],action:"remove"}';
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var player = items[i];
|
||||||
|
if (player.is_player) {
|
||||||
|
player.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.clear_status = function () {
|
||||||
|
if (!this.status || !this.status.length) return;
|
||||||
|
for (var i = 0; i < this.status.length; i++) {
|
||||||
|
var item = this.status[i];
|
||||||
|
this.change_buff(item, false, item.count);
|
||||||
|
item.handler && clearTimeout(item.handler);
|
||||||
|
}
|
||||||
|
this.status.length = 0;
|
||||||
|
if (!this.environment) return;
|
||||||
|
var msg = '{type:"status",id:"' + this.id + '",action:"clear"}';
|
||||||
|
var items = this.environment.items;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var player = items[i];
|
||||||
|
if (player.is_player) {
|
||||||
|
player.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.change_buff = function (buff, isadd, buff_count) {
|
||||||
|
if (isadd) {
|
||||||
|
if (buff.prop) {
|
||||||
|
for (var i = 0; i < buff_count; i++) {
|
||||||
|
this.change_prop(buff.prop, true);
|
||||||
|
}
|
||||||
|
this.recount();
|
||||||
|
}
|
||||||
|
if (buff.on_attach) buff.on_attach(this);
|
||||||
|
if (buff.ig_control) this.ig_control = buff.duration;
|
||||||
|
|
||||||
|
if (buff.start_msg) {
|
||||||
|
this.send_room(buff.start_msg);
|
||||||
|
}
|
||||||
|
if (buff.is_busy) this.is_busy = buff.duration;
|
||||||
|
if (buff.is_miss) this.is_miss = buff.duration;
|
||||||
|
if (buff.is_rash) this.is_rash = buff.duration;
|
||||||
|
if (buff.is_shadow) this.is_shadow = buff.duration;
|
||||||
|
if (buff.is_faint) {
|
||||||
|
this.is_faint = buff.duration;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (buff.prop) {
|
||||||
|
for (var i = 0; i < buff_count; i++) {
|
||||||
|
this.change_prop(buff.prop, false);
|
||||||
|
}
|
||||||
|
this.recount();
|
||||||
|
}
|
||||||
|
if (buff.on_expire) buff.on_expire(this);
|
||||||
|
if (buff.is_busy) this.is_busy = 0;
|
||||||
|
if (buff.is_miss) this.is_miss = 0;
|
||||||
|
if (buff.is_rash) this.is_rash = 0;
|
||||||
|
if (buff.ig_control) this.ig_control = 0;
|
||||||
|
if (buff.is_shadow) this.is_shadow = 0;
|
||||||
|
if (buff.is_faint) {
|
||||||
|
this.is_faint = 0;
|
||||||
|
}
|
||||||
|
if (this.hp > 0 && buff.finish_msg) {
|
||||||
|
this.send_room(buff.finish_msg);
|
||||||
|
}
|
||||||
|
this.remove_temp(buff.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.appdend_status = function (str) {
|
||||||
|
if (!this.status) return;
|
||||||
|
var now = Date.now();
|
||||||
|
str.push(",status:[");
|
||||||
|
for (var i = 0; i < this.status.length; i++) {
|
||||||
|
if (i > 0) str.push(",");
|
||||||
|
var item = this.status[i];
|
||||||
|
str.push('{sid:"');
|
||||||
|
str.push(item.id);
|
||||||
|
str.push('",name:"');
|
||||||
|
str.push(item.name);
|
||||||
|
str.push('",duration:');
|
||||||
|
if (item.on_interval) {
|
||||||
|
str.push(item.duration * item.duration_count);
|
||||||
|
} else {
|
||||||
|
str.push(item.duration);
|
||||||
|
}
|
||||||
|
str.push(',overtime:');
|
||||||
|
str.push(now - item.start_time);
|
||||||
|
if (item.override === 1) {
|
||||||
|
str.push(',"count":');
|
||||||
|
str.push(item.count);
|
||||||
|
}
|
||||||
|
if (item.downside) {
|
||||||
|
str.push(',downside:');
|
||||||
|
str.push(true);
|
||||||
|
}
|
||||||
|
str.push('}');
|
||||||
|
}
|
||||||
|
str.push("]");
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.notify_status = function () {
|
||||||
|
if (!this.status) return;
|
||||||
|
var str = ['{type:"status",id:\"'];
|
||||||
|
str.push(this.id);
|
||||||
|
str.push("\",action:'load',items:[");
|
||||||
|
var now = Date.now();
|
||||||
|
for (var i = 0; i < this.status.length; i++) {
|
||||||
|
if (i > 0) str.push(",");
|
||||||
|
var item = this.status[i];
|
||||||
|
str.push('{sid:"');
|
||||||
|
str.push(item.id);
|
||||||
|
str.push('",name:"');
|
||||||
|
str.push(item.name);
|
||||||
|
str.push('",duration:');
|
||||||
|
if (item.on_interval) {
|
||||||
|
str.push(item.duration * item.duration_count);
|
||||||
|
} else {
|
||||||
|
str.push(item.duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
str.push(',overtime:');
|
||||||
|
str.push(now - item.start_time);
|
||||||
|
if (item.override === 1) {
|
||||||
|
str.push(',"count":');
|
||||||
|
str.push(item.count);
|
||||||
|
}
|
||||||
|
if (item.downside) {
|
||||||
|
str.push(',downside:');
|
||||||
|
str.push(true);
|
||||||
|
}
|
||||||
|
str.push('}');
|
||||||
|
}
|
||||||
|
str.push("]}");
|
||||||
|
this.send(str.join(""));
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.status_changed = function (item, type) {
|
||||||
|
var str = [];
|
||||||
|
str.push('{type:"status","action":"');
|
||||||
|
str.push(type);
|
||||||
|
str.push('",id:"');
|
||||||
|
str.push(this.id);
|
||||||
|
str.push('",sid:"');
|
||||||
|
str.push(item.id);
|
||||||
|
str.push('"');
|
||||||
|
if (type === "add") {
|
||||||
|
str.push(',"name":"');
|
||||||
|
str.push(item.name);
|
||||||
|
str.push('","duration":');
|
||||||
|
if (item.on_interval) {
|
||||||
|
str.push(item.duration * item.duration_count);
|
||||||
|
} else {
|
||||||
|
str.push(item.duration);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (item.override === 1) {
|
||||||
|
str.push(',"count":');
|
||||||
|
str.push(item.count);
|
||||||
|
}
|
||||||
|
if (item.downside) {
|
||||||
|
str.push(',downside:');
|
||||||
|
str.push(true);
|
||||||
|
}
|
||||||
|
} else if (type === "refresh") {
|
||||||
|
str.push(',count:');
|
||||||
|
str.push(item.count);
|
||||||
|
}
|
||||||
|
str.push('}');
|
||||||
|
if (!this.environment) return;
|
||||||
|
var msg = str.join("");
|
||||||
|
var items = this.environment.items;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var player = items[i];
|
||||||
|
if (player.is_player) {
|
||||||
|
player.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.remove_status = function (sid, isall) {
|
||||||
|
if (!this.status) return;
|
||||||
|
for (var i = this.status.length - 1; i >= 0; i--) {
|
||||||
|
if (this.status[i].id === sid) {
|
||||||
|
var item = this.status[i];
|
||||||
|
if (item.handler) clearTimeout(item.handler);
|
||||||
|
item.handler = null;
|
||||||
|
|
||||||
|
|
||||||
|
if (item.on_interval && !isall) {
|
||||||
|
item.over_count++;
|
||||||
|
if (item.on_interval) {
|
||||||
|
if (item.on_interval(this, item.over_count) === false) {
|
||||||
|
item.duration_count = item.duration_count || 2;
|
||||||
|
item.over_count = item.duration_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item.duration_count === 0 || (item.duration_count > 1 && item.duration_count > item.over_count)) {
|
||||||
|
if (item.duration)
|
||||||
|
item.handler = this.call_out(this.remove_status, item.duration, sid);
|
||||||
|
// item.start_time = Date.now();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.change_buff(item, false, 1);
|
||||||
|
|
||||||
|
if (item.override === 1) {
|
||||||
|
item.count--;
|
||||||
|
if (item.count === 0 || isall) {
|
||||||
|
|
||||||
|
this.change_buff(item, false, item.count);
|
||||||
|
|
||||||
|
this.status_changed(item, "remove");
|
||||||
|
this._splice_status(i, item);
|
||||||
|
} else {
|
||||||
|
if (item.duration)
|
||||||
|
item.handler = this.call_out(this.remove_status, item.duration, sid);
|
||||||
|
item.start_time = Date.now();
|
||||||
|
this.status_changed(item, "refresh");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//覆盖和不覆盖的都直接移除
|
||||||
|
this.status_changed(item, "remove");
|
||||||
|
this._splice_status(i, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype._splice_status = function (index, item) {
|
||||||
|
if (this.status[index] === item) {
|
||||||
|
return this.status.splice(index, 1);
|
||||||
|
}
|
||||||
|
for (var i = 0; i < this.status.length; i++) {
|
||||||
|
if (this.status[i] === item) {
|
||||||
|
return this.status.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
351
os/char/character.js
Normal file
351
os/char/character.js
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
require("../item");
|
||||||
|
/*global CHARACTER ROOM ITEM*/
|
||||||
|
CHARACTER = function () {
|
||||||
|
this.name = "生物";
|
||||||
|
this.hp = this.max_hp = 100;
|
||||||
|
this.mp = this.max_mp = 100;
|
||||||
|
this.str = this.con = this.dex = this.int = 20;
|
||||||
|
this.money = 0;
|
||||||
|
}
|
||||||
|
CHARACTER.inherits(ITEM);
|
||||||
|
CHARACTER.prototype.send = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.notify = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.send_commands = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.notify_fail = function () {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.is_living = function () {
|
||||||
|
return this.hp > 0;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.is_in = function (path) {
|
||||||
|
if (!this.environment) return false;
|
||||||
|
return this.environment.path === path;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.is_here = function (obj) {
|
||||||
|
if (!this.environment || !obj.environment) return false;
|
||||||
|
return this.environment === obj.environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.find_obj = function (oid, parent) {
|
||||||
|
var items = this.items;
|
||||||
|
if (parent) items = parent.items;
|
||||||
|
return this.find_obj_byid(items, oid);
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.send_message = function (msg, include_me) {
|
||||||
|
if (!msg || !this.environment) return;
|
||||||
|
var list = this.environment.items;
|
||||||
|
for (var i = 0; i < list.length; i++) {
|
||||||
|
if (list[i].is_player) {
|
||||||
|
if (list[i] === this && !include_me) continue;
|
||||||
|
if (!list[i].no_message)
|
||||||
|
list[i].notify(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.send_combat = function (text, target) {
|
||||||
|
if (!this.environment || !text) return;
|
||||||
|
var list = this.environment.items;
|
||||||
|
var th_vision, item;
|
||||||
|
for (var i = 0; i < list.length; i++) {
|
||||||
|
item = list[i];
|
||||||
|
if (item.is_player) {
|
||||||
|
if (item === this) {
|
||||||
|
if (!item.query_setting("no_mcmsg"))
|
||||||
|
item.notify(splitmessage(this, text, 1, target));
|
||||||
|
} else if (item === target) {
|
||||||
|
if (!item.query_setting("no_mcmsg"))
|
||||||
|
item.notify(splitmessage(this, text, 2, target));
|
||||||
|
} else if (!item.no_message && !item.query_setting("no_combatmsg")) {
|
||||||
|
if (!th_vision) th_vision = splitmessage(this, text, 3, target);
|
||||||
|
item.notify(th_vision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.send_room = function (text, target, excludeself) {
|
||||||
|
if (!this.environment || !text) return;
|
||||||
|
var list = this.environment.items;
|
||||||
|
var th_vision;
|
||||||
|
for (var i = 0; i < list.length; i++) {
|
||||||
|
if (list[i].is_player) {
|
||||||
|
if (list[i] === this) {
|
||||||
|
!excludeself && list[i].notify(splitmessage(this, text, 1, target));
|
||||||
|
} else if (list[i] === target) {
|
||||||
|
list[i].notify(splitmessage(this, text, 2, target));
|
||||||
|
} else if (!list[i].no_message) {
|
||||||
|
if (!th_vision) th_vision = splitmessage(this, text, 3, target);
|
||||||
|
list[i].notify(th_vision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_setting = function (name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function splitmessage(me, text, type, target) {
|
||||||
|
if (text.length < 3) return text;
|
||||||
|
var str = [];
|
||||||
|
var start = 0;
|
||||||
|
for (var i = 0; i < text.length; i++) {
|
||||||
|
if (text[i] === "$") {
|
||||||
|
start < i && str.push(text.substring(start, i));
|
||||||
|
var ch = text[++i];
|
||||||
|
start = i + 1;
|
||||||
|
//type 1本人视角 2目标视角 3第三人称视角
|
||||||
|
switch (ch) {
|
||||||
|
case "N"://本人
|
||||||
|
str.push(type === 1 ? "你" : me.name);
|
||||||
|
break;
|
||||||
|
case "n"://目标
|
||||||
|
str.push(type === 2 ? "你" : target.name);
|
||||||
|
break;
|
||||||
|
case "P":
|
||||||
|
str.push(type === 1 ? "你" : me.call3());
|
||||||
|
break;
|
||||||
|
case "p":
|
||||||
|
str.push(type === 2 ? "你" : target.call3());
|
||||||
|
break;
|
||||||
|
case "l":
|
||||||
|
str.push(me.attack_part ? me.attack_part.name : "");
|
||||||
|
break;
|
||||||
|
case "W":
|
||||||
|
case "w":
|
||||||
|
str.push(me.weapon_name() || "手");
|
||||||
|
break;
|
||||||
|
case "i":
|
||||||
|
str.push(target.weapon_name() || "手");
|
||||||
|
break;
|
||||||
|
case "T":
|
||||||
|
str.push(me.throwing_name());
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
start < i && str.push(text.substring(start, i));
|
||||||
|
return str.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
//执行一串命令
|
||||||
|
CHARACTER.prototype.command = function (req) {
|
||||||
|
|
||||||
|
if (this.wait_input) { //如果用户等待输入
|
||||||
|
this.wait_input.apply(this, [this, req]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var cmd = null, pars = null, start = 0, i = 0;
|
||||||
|
for (; i < req.length; i++) {
|
||||||
|
if (req[i] === ' ') {
|
||||||
|
if (start < i) {
|
||||||
|
cmd = req.substring(start, i);
|
||||||
|
pars = req.substring(i + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
start = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!cmd) cmd = req;
|
||||||
|
this.do_command(cmd, pars);
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.do_command = function (cmdName, str) {
|
||||||
|
|
||||||
|
var cmd = WORLD.COMMANDS[cmdName];
|
||||||
|
var pars;
|
||||||
|
if (cmd && cmd.regex && str) {
|
||||||
|
pars = cmd.regex.exec(str);
|
||||||
|
pars ? pars[0] = this : pars = [this, str];
|
||||||
|
} else {
|
||||||
|
pars = [this, str];
|
||||||
|
}
|
||||||
|
if (this.do_item_action(this.environment, cmdName, pars)) {
|
||||||
|
//如果环境触发这个命令就返回
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmd = cmd || WORLD.DEFAULT_COMMAND;
|
||||||
|
if (cmd) {
|
||||||
|
if (!this.check_command(cmd))
|
||||||
|
return;//不允许执行
|
||||||
|
if (cmd.enter.apply(cmd, pars) !== false) {
|
||||||
|
|
||||||
|
return;//命令执行完成。
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (str) {
|
||||||
|
//如果有参数,尝试找下这个物件
|
||||||
|
if (this.do_item_action(this.find_obj(str, this.environment), cmdName, pars)) {
|
||||||
|
//如果物件触发这个命令就返回
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.send("什么?");
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.do_item_action = function (item, cmd, pars) {
|
||||||
|
if (!item || !item.actions) return;
|
||||||
|
var cmdItem = item.actions[cmd];
|
||||||
|
if (!cmdItem || !cmdItem.action) return;
|
||||||
|
if (!this.check_command(cmdItem))
|
||||||
|
return true;//返回true 不允许执行
|
||||||
|
if (cmdItem.action.apply(item, pars) !== false)
|
||||||
|
return true; //返回true表示不继续执行该命令
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.check_command = function (cmd) {
|
||||||
|
if (cmd.allow_level > this.user_level) {
|
||||||
|
this.send("什么?");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.hp <= 0 && !cmd.allow_die) {
|
||||||
|
//死亡状态,除了一些特殊指令都不能做
|
||||||
|
return this.notify_fail("你现在是灵魂状态,不能那么做。");
|
||||||
|
}
|
||||||
|
if (!cmd.allow_faint && this.is_faint) {
|
||||||
|
this.send("你正在昏迷中!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!cmd.allow_state && this.state) {
|
||||||
|
return this.notify_fail("你正在" + this.state.title + ",没时间这么做。");
|
||||||
|
}
|
||||||
|
if (!cmd.allow_fight && this.fight_type > 0) {
|
||||||
|
return this.notify_fail("你正在战斗,待会再说。");
|
||||||
|
}
|
||||||
|
if (!cmd.allow_busy && this.is_busy) {
|
||||||
|
return this.notify_fail("你现在正忙。");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.create = function (path, par) {
|
||||||
|
//模板被创建,实际上没真正用
|
||||||
|
if (par) this.path = path + par;
|
||||||
|
this.on_create && this.on_create(path, par);
|
||||||
|
|
||||||
|
WORLD.NPC_STROE.set(this.path, this);
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.update = function (path, par) {
|
||||||
|
this.create(path, par);
|
||||||
|
}
|
||||||
|
|
||||||
|
//真正被复制到房间
|
||||||
|
CHARACTER.prototype.clone = function () {
|
||||||
|
if (this.temp) this.temp = Object.create(this.temp);
|
||||||
|
if (this.prop) this.prop = Object.create(this.prop);
|
||||||
|
if (this.equipment) {
|
||||||
|
let eqs = [];
|
||||||
|
for (let i = 0; i < this.equipment.length; i++) {
|
||||||
|
let item = this.equipment[i];
|
||||||
|
if (item) {
|
||||||
|
eqs[i] = OBJ.CREATE(item.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.equipment = eqs;
|
||||||
|
}
|
||||||
|
//装备和道具只保留引用应该没事,2个相同NPC的装备和背包是同一个道具
|
||||||
|
//好像随从不行
|
||||||
|
if (this.items) {
|
||||||
|
let items = [];
|
||||||
|
for (let i = 0; i < this.items.length; i++) {
|
||||||
|
items[i] = OBJ.CREATE(this.items[i].path);
|
||||||
|
}
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
this.create_id();
|
||||||
|
this.init();
|
||||||
|
|
||||||
|
this.recount();
|
||||||
|
this.hp = this.max_hp;
|
||||||
|
this.mp = this.max_mp;
|
||||||
|
this.on_clone && this.on_clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CHARACTER.prototype.init = function () {
|
||||||
|
if (this.equipment) {
|
||||||
|
let groups = {};
|
||||||
|
for (let i = 0; i < this.equipment.length; i++) {
|
||||||
|
let item = this.equipment[i];
|
||||||
|
if (item) {
|
||||||
|
item.change_prop(this, true);
|
||||||
|
item.on_eq && item.on_eq(this);
|
||||||
|
if (item && item.group_name) {
|
||||||
|
groups[item.group_name] = (groups[item.group_name] || 0) + 1;
|
||||||
|
var prop = item.group_prop(groups[item.group_name]);
|
||||||
|
if (prop) {
|
||||||
|
this.change_prop(prop, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.is_player) this.score = 0;
|
||||||
|
if (this.skills) {
|
||||||
|
for (let item in this.skills) {
|
||||||
|
var base_skill = SKILL.get(item);
|
||||||
|
if (!base_skill) {
|
||||||
|
delete this.skills[item];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
base_skill.attach_prop(this, this.query_skill(item));
|
||||||
|
if (this.is_player) {
|
||||||
|
this.score += base_skill.query_score(this.skills[item].level, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.init_skill();
|
||||||
|
}
|
||||||
|
CHARACTER.EXP_LIMIT = [300000, 3000000, 20000000];
|
||||||
|
CHARACTER.prototype.add_exp = function (exp, pot, money) {
|
||||||
|
if (exp) {
|
||||||
|
exp += this.query_temp("exp_up", 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (pot) {
|
||||||
|
pot += this.query_temp("pot_up", 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
var str = ["<hig>你获得了"];
|
||||||
|
if (exp) {
|
||||||
|
this.exp += exp;
|
||||||
|
str.push(exp);
|
||||||
|
str.push("点经验");
|
||||||
|
}
|
||||||
|
if (pot) {
|
||||||
|
this.pot += pot;
|
||||||
|
if (exp) str.push(",");
|
||||||
|
str.push(pot);
|
||||||
|
str.push("点潜能");
|
||||||
|
}
|
||||||
|
if (money) {
|
||||||
|
|
||||||
|
this.money += money;
|
||||||
|
if (exp || pot) str.push(",");
|
||||||
|
str.push(UTIL.moneyToStr(money));
|
||||||
|
}
|
||||||
|
if (str.length === 1) return;
|
||||||
|
str.push("。</hig>");
|
||||||
|
this.send(str.join(""));
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.add_money = function (val) {
|
||||||
|
this.money += val;
|
||||||
|
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.check_groupeq = function () {
|
||||||
|
var eqs = {};
|
||||||
|
for (var i = 0; i < this.equipment.length; i++) {
|
||||||
|
var item = this.equipment[i];
|
||||||
|
if (item && item.group_name) {
|
||||||
|
eqs[item.group_name] = (eqs[item.group_name] || 0) + 1;
|
||||||
|
var prop = item.group_prop(eqs[item.group_name]);
|
||||||
|
if (prop) {
|
||||||
|
this.change_prop(prop, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
250
os/char/combat.js
Normal file
250
os/char/combat.js
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
|
||||||
|
require("./character.js");
|
||||||
|
CHARACTER.prototype.begin_attack = function (target, type) {
|
||||||
|
|
||||||
|
if (!target || target === this) return;
|
||||||
|
if (!this.attack_skill) {
|
||||||
|
return this.send("error skill");
|
||||||
|
}
|
||||||
|
this.add_enemy(target);
|
||||||
|
this.fight_type = this.fight_type || 0;
|
||||||
|
if (type > this.fight_type) {
|
||||||
|
if (this.force_skill && this.force_skill.on_beginfight) {
|
||||||
|
this.force_skill.on_beginfight(this, target);
|
||||||
|
}
|
||||||
|
if (this.attack_skill && this.attack_skill.on_beginfight) {
|
||||||
|
this.attack_skill.on_beginfight(this, target);
|
||||||
|
}
|
||||||
|
if (!this.fight_type) {
|
||||||
|
|
||||||
|
if (this.attack_handler) clearTimeout(this.attack_handler);
|
||||||
|
this.attack_handler = this.call_out(this.auto_attack, Math.random() * this.gjsd);
|
||||||
|
this.send('{type:"combat",start:1}');
|
||||||
|
|
||||||
|
}
|
||||||
|
this.fight_type = type; //1fight hp<30% 2 kill 0
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.do_fight = function (target) {
|
||||||
|
this.begin_attack(target, 1);
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.do_kill = function (target) {
|
||||||
|
if (this.fight_type == 2 && this.query_enemy() == target) return;
|
||||||
|
this.begin_attack(target, 2);
|
||||||
|
target.begin_attack(this, 2);
|
||||||
|
target.notify("<hir>看起来" + this.name + "想杀死你!</hir>\n");
|
||||||
|
this.notify("<hir>看起来" + target.name + "想杀死你!</hir>\n");
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.add_enemy = function (target) {
|
||||||
|
if (!this.enemy) {
|
||||||
|
this.enemy = [];
|
||||||
|
}
|
||||||
|
this.enemy.push(target);
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.notify_hp = function (type, val) {
|
||||||
|
if (!this.environment) return;
|
||||||
|
|
||||||
|
var items = this.environment.items;
|
||||||
|
var str = null;
|
||||||
|
if (type) {
|
||||||
|
str = "{type:\"sc\",id:\"" + this.id + "\"," + type + ":" + val + "";
|
||||||
|
} else {
|
||||||
|
var ary = ["{type:\"sc\",id:\""];
|
||||||
|
ary.push(this.id);
|
||||||
|
ary.push("\",hp:");
|
||||||
|
ary.push(this.hp);
|
||||||
|
ary.push(",max_hp:");
|
||||||
|
ary.push(this.max_hp);
|
||||||
|
ary.push(",mp:");
|
||||||
|
ary.push(this.mp);
|
||||||
|
ary.push(",max_mp:");
|
||||||
|
ary.push(this.max_mp);
|
||||||
|
str = ary.join("");
|
||||||
|
}
|
||||||
|
var showdamage = type ? type === "hp" : false;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var player = items[i];
|
||||||
|
if (player.is_player) {
|
||||||
|
if (showdamage && this.damages && player.query_setting('show_damage')) {
|
||||||
|
player.send(str + ",damage:" + (this.damages[player.id] || 0) + "}");
|
||||||
|
} else {
|
||||||
|
player.send(str + "}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.add_hp = function (v) {
|
||||||
|
|
||||||
|
if (v > this.max_hp - this.hp) v = this.max_hp - this.hp;
|
||||||
|
else if (v < -this.hp) v = -this.hp;
|
||||||
|
if (!v) return 0;
|
||||||
|
|
||||||
|
this.hp += v;
|
||||||
|
this.notify_hp("hp", this.hp);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.add_mp = function (v) {
|
||||||
|
var mp = this.mp + v;
|
||||||
|
if (mp > this.max_mp) mp = this.max_mp;
|
||||||
|
if (mp < 0) mp = 0;
|
||||||
|
if (mp === this.mp) return;
|
||||||
|
this.mp = mp;
|
||||||
|
this.notify_hp("mp", this.mp);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.is_fighting = function (p) {
|
||||||
|
if (!this.fight_type) return false;
|
||||||
|
if (!this.enemy || !this.enemy.length) {
|
||||||
|
this.fight_type = 0;
|
||||||
|
this.clear_combat_status();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (p) {
|
||||||
|
if (p.environment !== this.environment) return false;
|
||||||
|
return this.enemy.contain(p);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.end_fight = function () {
|
||||||
|
if (this.enemy) this.enemy.length = 0;
|
||||||
|
this.release_time = 0;
|
||||||
|
if (!this.fight_type) return;
|
||||||
|
|
||||||
|
this.send('{type:"combat",end:1}');
|
||||||
|
if (this.record_damage && this.hp > 0) this.damages = null;
|
||||||
|
this.fight_type = 0;
|
||||||
|
if (this.attack_handler) clearTimeout(this.attack_handler);
|
||||||
|
this.attack_handler = null;
|
||||||
|
this.clear_combat_status();
|
||||||
|
this.clear_combat_prop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_enemy = function () {
|
||||||
|
if (!this.enemy) return;
|
||||||
|
for (var i = 0; i < this.enemy.length; i++) {
|
||||||
|
if (this.enemy[i].hp <= 0 || !this.is_here(this.enemy[i])
|
||||||
|
|| !this.enemy[i].fight_type) {
|
||||||
|
this.enemy.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.enemy[0];
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.can_attack = function () {
|
||||||
|
return this.hp > 0 && this.fight_type > 0 && !this.is_faint && !this.is_busy;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.end_attack = function (target) {
|
||||||
|
if (!target) return;
|
||||||
|
if (!this.fight_type) return;
|
||||||
|
if (this.attack_skill.on_end_attack) {
|
||||||
|
this.attack_skill.on_end_attack(this, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.fight_type === 1 && target.hp / target.max_hp < 0.3) {
|
||||||
|
if (target.hp <= 0) target.hp = 1;
|
||||||
|
if (target.is_faint) {
|
||||||
|
this.send_room(WINNER_MSG[this.random(4)], target);
|
||||||
|
} else {
|
||||||
|
this.send_room(WINNER_MSG.random(), target);
|
||||||
|
}
|
||||||
|
target.on_fight_over && target.on_fight_over(this, false);
|
||||||
|
this.on_fight_over && this.on_fight_over(target, true);
|
||||||
|
target.end_fight();
|
||||||
|
return this.end_fight();
|
||||||
|
} else if (target.hp <= 0 && target.die(this) !== false) {
|
||||||
|
target.end_fight();
|
||||||
|
|
||||||
|
this.enemy.remove(target);
|
||||||
|
|
||||||
|
if (!this.enemy.length) {
|
||||||
|
if (this.hp <= 0) {
|
||||||
|
this.hp = 1;
|
||||||
|
}
|
||||||
|
return this.end_fight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;//是否继续攻击
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.query_part = function () {
|
||||||
|
return CHARACTER_PARTS.random();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CHARACTER.prototype.full = function () {
|
||||||
|
|
||||||
|
this.hp = this.max_hp;
|
||||||
|
this.mp = this.max_mp;
|
||||||
|
this.clear_distime();
|
||||||
|
this.release_time = 0;
|
||||||
|
this.notify_hp();
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTER.prototype.clear_distime = function (pfmid) {
|
||||||
|
if (this.auto_skills) {
|
||||||
|
if (!pfmid) {
|
||||||
|
for (let i = 0; i < this.auto_skills.length; i++) {
|
||||||
|
let item = this.auto_skills[i];
|
||||||
|
item.release_time = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < this.auto_skills.length; i++) {
|
||||||
|
let item = this.auto_skills[i];
|
||||||
|
if (item.pfm.id === pfmid) {
|
||||||
|
item.release_time = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHARACTER.prototype.do_attacks = function (par) {
|
||||||
|
|
||||||
|
var targets = par.targets;
|
||||||
|
if (!targets) {
|
||||||
|
targets = new Array(this.enemy.length);
|
||||||
|
for (var i = 0; i < this.enemy.length; i++) {
|
||||||
|
targets[i] = this.enemy[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!targets.length) return;
|
||||||
|
var attack_msg = par.attack_msg;
|
||||||
|
if (attack_msg === undefined) attack_msg = (par.no_weapon ? this.noweapon_skill : this.attack_skill).query_attack_action(this, targets[0]);
|
||||||
|
if (attack_msg !== "") this.send_combat(attack_msg, targets[0]);
|
||||||
|
par.attack_msg = "";
|
||||||
|
for (let i = 0; i < targets.length; i++) {
|
||||||
|
par.target = targets[i];
|
||||||
|
this.do_attack(par);
|
||||||
|
this.end_attack(targets[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var CHARACTER_PARTS = [
|
||||||
|
{ name: "左脚", hert: 0.8, crit: 0 },
|
||||||
|
{ name: "右脚", hert: 0.8, crit: 0 },
|
||||||
|
{ name: "左腿", hert: 0.85, crit: 0 },
|
||||||
|
{ name: "右腿", hert: 0.85, crit: 0 },
|
||||||
|
{ name: "小腹", hert: 0.91, crit: 3 },
|
||||||
|
{ name: "胸前", hert: 0.95, crit: 4 },
|
||||||
|
{ name: "后背", hert: 0.97, crit: 4 },
|
||||||
|
{ name: "头部", hert: 1.2, crit: 10 },
|
||||||
|
{ name: "颈部", hert: 1.1, crit: 5 },
|
||||||
|
{ name: "后心", hert: 1, crit: 4 },
|
||||||
|
{ name: "左肩", hert: 0.85, crit: 1 },
|
||||||
|
{ name: "右肩", hert: 0.89, crit: 1 },
|
||||||
|
{ name: "左手", hert: 0.85, crit: 0 },
|
||||||
|
{ name: "左手", hert: 0.85, crit: 0 },
|
||||||
|
{ name: "腰间", hert: 0.99, crit: 5 }
|
||||||
|
];
|
||||||
|
|
||||||
|
var WINNER_MSG = [
|
||||||
|
"<CYN>$N哈哈大笑,愉快地说道:承让了!</CYN>",
|
||||||
|
"<CYN>$N双手一拱,笑著说道:知道我的厉害了吧!</CYN>",
|
||||||
|
"<CYN>$N哈哈大笑,双手一拱,笑著说道:承让!</CYN>",
|
||||||
|
"<CYN>$N胜了这招,向后跃开三尺,笑道:承让!</CYN>",
|
||||||
|
"<CYN>$n脸色微变,说道:佩服,佩服!</CYN>",
|
||||||
|
"<CYN>$n向后退了几步,说道:这场比试算我输了,佩服,佩服!</CYN>",
|
||||||
|
"<CYN>$n向后一纵,躬身做揖说道:阁下武艺不凡,果然高明!</CYN>",
|
||||||
|
];
|
||||||
485
os/char/follower.js
Normal file
485
os/char/follower.js
Normal file
@@ -0,0 +1,485 @@
|
|||||||
|
require("../util/util.js");
|
||||||
|
require("./user.js");
|
||||||
|
FOLLOWER = function () {
|
||||||
|
this.hp = this.max_hp = 100;
|
||||||
|
this.mp = this.max_mp = 100;
|
||||||
|
this.str = this.con = this.dex = this.int = this.per = this.age = 20;
|
||||||
|
this.family = FAMILIES.NONE;
|
||||||
|
this.auto_pfm = true;
|
||||||
|
this.master = null;
|
||||||
|
this.level = 3;
|
||||||
|
this.master_name = null;
|
||||||
|
this.max_item_count = 10;
|
||||||
|
this.settings = {
|
||||||
|
auto_kill: 1,
|
||||||
|
auto_dice: 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
FOLLOWER.inherits(CHARACTER);
|
||||||
|
FOLLOWER.prototype.query_setting = function (name) {
|
||||||
|
if (!this.settings) return 0;
|
||||||
|
return this.settings[name] || 0;
|
||||||
|
}
|
||||||
|
FOLLOWER.prototype.set_setting = function (name, value) {
|
||||||
|
if (!this.settings) this.settings = {};
|
||||||
|
if (!value || value == "0") {
|
||||||
|
delete this.settings[name];
|
||||||
|
} else {
|
||||||
|
if (value == "1") value = 1;
|
||||||
|
this.settings[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.login_message = null;
|
||||||
|
}
|
||||||
|
FOLLOWER.prototype.send = function (text) {
|
||||||
|
if (this.listener) {
|
||||||
|
text = text.replace('你', this.name);
|
||||||
|
this.listener.send(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOLLOWER.prototype.notify_fail = function (text) {
|
||||||
|
this.send(text);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FOLLOWER.prototype.notify = function (text) {
|
||||||
|
this.send(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
FOLLOWER.prototype.set_listener = function (me, target) {
|
||||||
|
if (me.id == this.master) this.listener = target;
|
||||||
|
}
|
||||||
|
FOLLOWER.STORES = new Map();
|
||||||
|
FOLLOWER.CLEAR = function (me) {
|
||||||
|
if (!me.follower) return;
|
||||||
|
for (var i = 0; i < me.follower.length; i++) {
|
||||||
|
var npc = FOLLOWER.STORES.get(me.id + "_" + me.follower[i].id);
|
||||||
|
if (npc) {
|
||||||
|
FOLLOWER.STORES.delete(me.id + "_" + me.follower[i].id);
|
||||||
|
npc.set_state(null);
|
||||||
|
npc.environment && npc.environment.item_changed(npc, false);
|
||||||
|
npc.clear_status();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FOLLOWER.RESET = function (me) {
|
||||||
|
if (!me.follower) return;
|
||||||
|
for (var i = 0; i < me.follower.length; i++) {
|
||||||
|
var npc = FOLLOWER.STORES.get(me.id + "_" + me.follower[i].id);
|
||||||
|
if (npc) {
|
||||||
|
npc.set_state(null);
|
||||||
|
npc.environment && npc.environment.item_changed(npc, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOLLOWER.INIT_FROM_USER = function (me, datas) {
|
||||||
|
|
||||||
|
for (var j = 0; j < datas.length; j++) {
|
||||||
|
var data = datas[j];
|
||||||
|
var my_npc = FOLLOWER.STORES.get(me.id + "_" + data.id);
|
||||||
|
if (my_npc) continue;
|
||||||
|
if (!datas[j].id) continue;
|
||||||
|
my_npc = new FOLLOWER();
|
||||||
|
var obj = NPC.CLONE(data.path);
|
||||||
|
for (var i = 0; i < SAVE_NUMPROP.length; i++) {
|
||||||
|
my_npc[SAVE_NUMPROP[i]] = data.prop[i] || 0;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < SAVE_STRPROP.length; i++) {
|
||||||
|
my_npc[SAVE_STRPROP[i]] = data[SAVE_STRPROP[i]] || obj[SAVE_STRPROP[i]];
|
||||||
|
}
|
||||||
|
my_npc.on_makelove = obj ? obj.on_makelove : null;
|
||||||
|
my_npc.on_master_enter = obj ? obj.on_master_enter : null;
|
||||||
|
my_npc.equipment = data.temp;
|
||||||
|
my_npc.settings = data.settings;
|
||||||
|
my_npc.skills = data.skills;
|
||||||
|
my_npc.path = obj.path;
|
||||||
|
my_npc.items = me.read_items(data.items);
|
||||||
|
my_npc.equipment = me.read_items(data.eq);
|
||||||
|
my_npc.level = my_npc.level || obj.level || 3;
|
||||||
|
my_npc.init();
|
||||||
|
my_npc.recount();
|
||||||
|
my_npc.hp = my_npc.max_hp;
|
||||||
|
my_npc.mp = my_npc.max_mp;
|
||||||
|
FOLLOWER.STORES.set(me.id + "_" + my_npc.id, my_npc);
|
||||||
|
my_npc.master = me.id;
|
||||||
|
my_npc.master_name = me.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOLLOWER.INIT = function (me, par) {
|
||||||
|
if (!par || !par.path) return;
|
||||||
|
var npc;
|
||||||
|
var id = me.id + "_" + par.id;
|
||||||
|
if (par.id) {
|
||||||
|
npc = FOLLOWER.STORES.get(id);
|
||||||
|
if (npc) return npc;
|
||||||
|
}
|
||||||
|
var obj = NPC.CLONE(par.path);
|
||||||
|
if (!obj) return;
|
||||||
|
npc = new FOLLOWER();
|
||||||
|
for (var i = 0; i < SAVE_NUMPROP.length; i++) {
|
||||||
|
npc[SAVE_NUMPROP[i]] = obj[SAVE_NUMPROP[i]] || 0;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < SAVE_STRPROP.length; i++) {
|
||||||
|
npc[SAVE_STRPROP[i]] = obj[SAVE_STRPROP[i]] || "";
|
||||||
|
}
|
||||||
|
npc.on_makelove = obj.on_makelove;
|
||||||
|
npc.on_master_enter = obj.on_master_enter;
|
||||||
|
npc.equipment = obj.equipment;
|
||||||
|
npc.skills = obj.skills;
|
||||||
|
npc.items = obj.items;
|
||||||
|
npc.id = par.id;
|
||||||
|
npc.path = obj.path;
|
||||||
|
npc.level = obj.level || 3;
|
||||||
|
npc.init();
|
||||||
|
npc.recount();
|
||||||
|
FOLLOWER.STORES.set(id, npc);
|
||||||
|
npc.master = me.id;
|
||||||
|
npc.master_name = me.name;
|
||||||
|
return npc;
|
||||||
|
}
|
||||||
|
FOLLOWER.REPLACE = function (me, old, npc) {
|
||||||
|
if (!old || !npc) return;
|
||||||
|
var copys = ["str", "con", "dex", "int", "gender", "kar", "per", "name", "title", "desc", "on_master_learn", "on_master_enter"];
|
||||||
|
for (var i = 0; i < copys.length; i++) {
|
||||||
|
old[copys[i]] = npc[copys[i]];
|
||||||
|
}
|
||||||
|
if (!old.skills) old.skills = {};
|
||||||
|
if (!old.equipment) old.equipment = [];
|
||||||
|
if (npc.equipment && npc.equipment[0]) {
|
||||||
|
if (old.equipment[0]) {
|
||||||
|
npc.items.push(npc.equipment[0]);
|
||||||
|
} else {
|
||||||
|
old.equipment[0] = npc.equipment[0];
|
||||||
|
}
|
||||||
|
npc.equipment[0] = null;
|
||||||
|
}
|
||||||
|
if (!old.items) old.items = [];
|
||||||
|
if (npc.items && npc.items.length) {
|
||||||
|
for (var i = 0; i < npc.items.length; i++) {
|
||||||
|
old.items.push(npc.items[i]);
|
||||||
|
}
|
||||||
|
npc.items.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var sk in npc.skills) {
|
||||||
|
var oldSkill = old.skills[sk];
|
||||||
|
if (oldSkill && oldSkill.addin && oldSkill.addin.length)
|
||||||
|
continue;//已经进阶的不覆盖
|
||||||
|
if (!oldSkill || oldSkill.level < npc.skills[sk].level) {
|
||||||
|
old.skills[sk] = npc.skills[sk];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (npc.exp > old.exp) old.exp = npc.exp;
|
||||||
|
if (npc.pot > old.pot) old.pot = npc.pot;
|
||||||
|
if (npc.max_mp > old.max_mp) old.max_mp = npc.max_mp;
|
||||||
|
|
||||||
|
|
||||||
|
old.prop = {};
|
||||||
|
old.init();
|
||||||
|
if (old.status) {
|
||||||
|
for (var j = old.status.length - 1; j >= 0; j--) {
|
||||||
|
var item = old.status[j];
|
||||||
|
old.change_buff(item, true, item.count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
old.recount();
|
||||||
|
old.master_json = null;
|
||||||
|
old.color_name = null;
|
||||||
|
old.on_master_enter = npc.on_master_enter;
|
||||||
|
old.on_makelove = npc.on_makelove;
|
||||||
|
old.path = npc.path;
|
||||||
|
old.level = npc.level > old.level ? npc.level : old.level;
|
||||||
|
if (old.environment) {
|
||||||
|
old.environment.item_changed(old, true);
|
||||||
|
}
|
||||||
|
for (var i = 0; i < me.follower.length; i++) {
|
||||||
|
if (me.follower[i].id == old.id) {
|
||||||
|
me.follower[i].path = npc.path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOLLOWER.GET = function (me, par) {
|
||||||
|
var id = me.id + "_" + par.id;
|
||||||
|
return FOLLOWER.STORES.get(id);
|
||||||
|
}
|
||||||
|
FOLLOWER.CREATE = function (me, par, callback) {
|
||||||
|
if (!par || !par.path) return;
|
||||||
|
var id = me.id + "_" + par.id;
|
||||||
|
var npc = FOLLOWER.STORES.get(id);
|
||||||
|
if (npc) return callback(npc);
|
||||||
|
|
||||||
|
}
|
||||||
|
var SAVE_NUMPROP = ["str", "con", "dex", "int", "gender", "max_mp", "limit_mp", "exp", "pot", "kar", "per"
|
||||||
|
, "hp", "mp", "max_item_count", "money", 'level'];
|
||||||
|
var SAVE_STRPROP = ["id", "name", "title", "desc"];
|
||||||
|
FOLLOWER.prototype.save = function (me) {
|
||||||
|
var str = ["prop:["];
|
||||||
|
for (var i = 0; i < SAVE_NUMPROP.length; i++) {
|
||||||
|
str.push(this[SAVE_NUMPROP[i]] || 0);
|
||||||
|
str.push(",");
|
||||||
|
}
|
||||||
|
str.push("0],");
|
||||||
|
var items = this.items || [];
|
||||||
|
str.push("items:[");
|
||||||
|
if (items) {
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
if (i > 0) str.push(",");
|
||||||
|
items[i].save_db(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str.push("]");
|
||||||
|
if (this.skills) {
|
||||||
|
str.push(",skills:");
|
||||||
|
str.push(JSON.stringify(this.skills));
|
||||||
|
}
|
||||||
|
if (this.temp) {
|
||||||
|
str.push(",temp:", this.format_temp(this.temp));
|
||||||
|
}
|
||||||
|
if (this.settings) {
|
||||||
|
str.push(",settings:");
|
||||||
|
str.push(JSON.stringify(this.settings));
|
||||||
|
}
|
||||||
|
if (this.equipment) {
|
||||||
|
str.push(",eq:[");
|
||||||
|
for (var i = 0; i < this.equipment.length; i++) {
|
||||||
|
if (i > 0) str.push(",");
|
||||||
|
if (this.equipment[i]) this.equipment[i].save_db(str);
|
||||||
|
else str.push("null");
|
||||||
|
}
|
||||||
|
str.push("]");
|
||||||
|
}
|
||||||
|
return str.join("");
|
||||||
|
}
|
||||||
|
FOLLOWER.SAVE = function (me) {
|
||||||
|
if (!me.follower) return "[]";
|
||||||
|
var str = ["["];
|
||||||
|
for (var i = 0; i < me.follower.length; i++) {
|
||||||
|
var item = me.follower[i];
|
||||||
|
if (str.length > 1) str.push(",");
|
||||||
|
str.push('{path:"');
|
||||||
|
str.push(me.follower[i].path);
|
||||||
|
str.push('",id:"');
|
||||||
|
str.push(me.follower[i].id);
|
||||||
|
str.push('"');
|
||||||
|
var npc = FOLLOWER.STORES.get(me.id + "_" + item.id);
|
||||||
|
if (npc) {
|
||||||
|
str.push(",");
|
||||||
|
str.push(npc.save(me));
|
||||||
|
}
|
||||||
|
str.push('}');
|
||||||
|
|
||||||
|
}
|
||||||
|
str.push("]");
|
||||||
|
return str.join("");
|
||||||
|
}
|
||||||
|
var DIE_MSG = ["\n$N扑在地上挣扎了几下,腿一伸,口中喷出几口<HIR>鲜血</HIR>,死了!\n",
|
||||||
|
"\n$N大叫一声倒在地上,挣扎了几下,<HIR>死了</HIR>!\n",
|
||||||
|
"\n$N口中喷出几口<HIR>鲜血</HIR>,倒在地上,死了!\n"];
|
||||||
|
FOLLOWER.prototype.die = function (killer) {
|
||||||
|
if (!this.environment) return;
|
||||||
|
if (this.on_die && this.on_die(killer) == false) {
|
||||||
|
this.hp = 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.clear_status();
|
||||||
|
this.send_room(DIE_MSG.random());
|
||||||
|
var corpse = new CORPSE();
|
||||||
|
corpse.init(this, false);
|
||||||
|
this.environment.item_changed(corpse, true);
|
||||||
|
this.environment.item_changed(this, false);
|
||||||
|
this.environment = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
FOLLOWER.prototype.heart_beat = function (dt) {
|
||||||
|
if (!this.hp) return;
|
||||||
|
// this.add_exp(this.grow_level, this.grow_level);
|
||||||
|
if (!this.fight_type) {
|
||||||
|
if (this.hp < this.max_hp) {
|
||||||
|
this.add_hp(parseInt(this.max_hp / 3));
|
||||||
|
}
|
||||||
|
if (this.mp < this.max_mp) {
|
||||||
|
this.add_mp(parseInt(this.max_mp / 3));
|
||||||
|
}
|
||||||
|
if (this.chat_msg) {
|
||||||
|
var r = this.random(10);
|
||||||
|
if (r > 7)
|
||||||
|
this.send_message(this.chat_msg.random());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.state && (!this.fight_type || this.state.allow_fight)) {
|
||||||
|
this.state.heat_count += 1;
|
||||||
|
if (this.state.heat_count >= this.state.rate) {
|
||||||
|
this.state.heat_count = 0;
|
||||||
|
if (this.state.on_enter(this) === false) {
|
||||||
|
this.set_state(null, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOLLOWER.prototype.set_state = function (state, isauto) {
|
||||||
|
if (this.state && !state) {
|
||||||
|
if (this.state.on_stop) {
|
||||||
|
if (this.state.on_stop(this, isauto) == false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.state = state;
|
||||||
|
if (state) {
|
||||||
|
state.rate = state.rate || 1;
|
||||||
|
state.heat_count = 0;
|
||||||
|
state.start_time = Date.now();
|
||||||
|
}
|
||||||
|
this.color_name = null;
|
||||||
|
this.environment && this.environment.item_changed(this, true);
|
||||||
|
this.master_json = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
FOLLOWER.prototype.query_mastercommands = function () {
|
||||||
|
if (this.master_json) return this.master_json;
|
||||||
|
var json = {};
|
||||||
|
json.type = "item";
|
||||||
|
json.desc = this.desc;
|
||||||
|
json.id = this.id;
|
||||||
|
json.name = this.name;
|
||||||
|
json.commands = [];
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "look " + this.id,
|
||||||
|
name: "查看"
|
||||||
|
});
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "fight " + this.id,
|
||||||
|
name: "比试"
|
||||||
|
});
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "score " + this.id,
|
||||||
|
name: "属性"
|
||||||
|
});
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "pack " + this.id,
|
||||||
|
name: "背包"
|
||||||
|
});
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "cha " + this.id,
|
||||||
|
name: "技能"
|
||||||
|
});
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "team with " + this.id,
|
||||||
|
name: "组队"
|
||||||
|
});
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "trade " + this.id,
|
||||||
|
name: "给" + this.call3() + "东西"
|
||||||
|
});
|
||||||
|
if (this.state) {
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "dc " + this.id + " stopstate",
|
||||||
|
name: "停止" + this.state.title.replace('中', "")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.actions) {
|
||||||
|
for (var i = 0; i < this.actions.length; i++) {
|
||||||
|
json.commands.push({
|
||||||
|
cmd: this.actions[i].cmd,
|
||||||
|
name: this.actions[i].name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.master_json = JSON.stringify(json)
|
||||||
|
return this.master_json;
|
||||||
|
}
|
||||||
|
FOLLOWER.prototype.query_commands = function (player) {
|
||||||
|
if (player.id == this.master) {
|
||||||
|
return this.query_mastercommands(player);
|
||||||
|
}
|
||||||
|
if (this.json) return this.json;
|
||||||
|
var json = {};
|
||||||
|
json.type = "item";
|
||||||
|
json.desc = this.desc;
|
||||||
|
json.id = this.id;
|
||||||
|
json.follower = true;
|
||||||
|
json.commands = [];
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "look " + this.id,
|
||||||
|
name: "查看"
|
||||||
|
});
|
||||||
|
if (!this.no_fight)
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "fight " + this.id,
|
||||||
|
name: "比试"
|
||||||
|
});
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "kill " + this.id,
|
||||||
|
name: "击杀"
|
||||||
|
});
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "ask " + this.id + " about 主人",
|
||||||
|
name: "询问主人"
|
||||||
|
});
|
||||||
|
this.json = JSON.stringify(json)
|
||||||
|
return this.json;
|
||||||
|
}
|
||||||
|
FOLLOWER.prototype.on_ask = function (me, par) {
|
||||||
|
switch (par) {
|
||||||
|
case "主人":
|
||||||
|
me.notify(this.name + "说道:我的主人就是" + this.master_name + "呀。");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOLLOWER.prototype.on_teamin = function (me) {
|
||||||
|
if (!this.team) return;
|
||||||
|
for (var i = 0; i < this.team.length; i++) {
|
||||||
|
var tm = this.team[i];
|
||||||
|
if (this.master == tm.id) {
|
||||||
|
this.do_follow(tm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOLLOWER.prototype.on_teamout = function (me) {
|
||||||
|
if (!this.team) return;
|
||||||
|
for (var i = 0; i < this.team.length; i++) {
|
||||||
|
var tm = this.team[i];
|
||||||
|
if (this.master == tm.id) {
|
||||||
|
this.do_follow(null);
|
||||||
|
if (this.environment && this.environment.is_fb()) {
|
||||||
|
this.environment.item_changed(this, false, this.name + "离开了。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOLLOWER.prototype.long_name = function () {
|
||||||
|
if (this.color_name) return this.color_name;
|
||||||
|
var str = [];
|
||||||
|
if (this.title) {
|
||||||
|
str.push(this.title);
|
||||||
|
str.push(" "); this.name;
|
||||||
|
}
|
||||||
|
str.push(this.name);
|
||||||
|
if (this.state) {
|
||||||
|
str.push("<hig><" + this.state.title + "></hig>");
|
||||||
|
}
|
||||||
|
return this.color_name = str.join("");
|
||||||
|
|
||||||
|
}
|
||||||
|
FOLLOWER.prototype.on_enter = function (me) {
|
||||||
|
if (me.id == this.master) {
|
||||||
|
this.on_master_enter && this.on_master_enter(me);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOLLOWER.prototype.on_master_leave = function (me, nextrm) {
|
||||||
|
if (this.state || !this.team || this.team != me.team) return false;
|
||||||
|
if (this.hp <= 0) return false;
|
||||||
|
if (me.environment === this.environment) return false;
|
||||||
|
|
||||||
|
//如果去副本或者家里就跟
|
||||||
|
if (nextrm.is_fb() || nextrm.parent.id == "home") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//如果当前是副本就自己回去
|
||||||
|
//if (this.environment.is_fb())
|
||||||
|
// this.environment.item_changed(this, false, this.name + "离开了。");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
114
os/char/monster.js
Normal file
114
os/char/monster.js
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
|
||||||
|
require("../util/util.js");
|
||||||
|
require("./character");
|
||||||
|
MONSTER = function () {
|
||||||
|
this.hp = this.max_hp = 100;
|
||||||
|
this.mp = this.max_mp = 100; this.auto_pfm = true;
|
||||||
|
this.family = FAMILIES.MONSTER;
|
||||||
|
this.str = this.con = this.dex = this.int = 20;
|
||||||
|
}
|
||||||
|
MONSTER.inherits(CHARACTER);
|
||||||
|
MONSTER.prototype.can_speek = false;
|
||||||
|
MONSTER.prototype.init_skill = function () {
|
||||||
|
this.attack_skill = this.query_used_skill(BASE_SKILLS.BITE);
|
||||||
|
this.dodge_skill = this.query_used_skill(BASE_SKILLS.DODGE);
|
||||||
|
this.parry_skill = this.query_used_skill(BASE_SKILLS.PARRY);
|
||||||
|
this.force_skill = this.query_used_skill(BASE_SKILLS.FORCE);
|
||||||
|
this.noweapon_skill = this.attack_skill;
|
||||||
|
}
|
||||||
|
MONSTER.prototype.query_desc = function (me) {
|
||||||
|
return this.query_commands(me);
|
||||||
|
}
|
||||||
|
MONSTER.prototype.query_commands = function (player) {
|
||||||
|
|
||||||
|
if (this.json) return this.json;
|
||||||
|
var json = {};
|
||||||
|
json.type = "item";
|
||||||
|
json.desc = this.name + "\n" + this.desc;
|
||||||
|
json.id = this.id;
|
||||||
|
json.commands = [];
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "kill " + this.id,
|
||||||
|
name: "击杀"
|
||||||
|
});
|
||||||
|
if (this.actions) {
|
||||||
|
for (var cmd in this.actions) {
|
||||||
|
if (!this.actions[cmd].name) continue;
|
||||||
|
json.commands.push({
|
||||||
|
cmd: cmd + " " + this.id,
|
||||||
|
name: this.actions[cmd].name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.json = JSON.stringify(json)
|
||||||
|
return this.json;
|
||||||
|
}
|
||||||
|
MONSTER.prototype.call3 = function () {
|
||||||
|
return "它";
|
||||||
|
}
|
||||||
|
|
||||||
|
MONSTER.prototype.destroy = function (msg) {
|
||||||
|
if (this.environment) {
|
||||||
|
this.environment.item_changed(this, false, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MONSTER.prototype.die = function (killer) {
|
||||||
|
|
||||||
|
if (!this.environment) return;
|
||||||
|
if (this.on_die && this.on_die(killer) === false) {
|
||||||
|
this.hp = 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.hp = 0;
|
||||||
|
this.clear_status();
|
||||||
|
this.send_message(this.name + "惨嚎一声,死了!");
|
||||||
|
var corpse = new CORPSE();
|
||||||
|
var isinfb = this.environment.is_fb();
|
||||||
|
corpse.init(this, isinfb);
|
||||||
|
this.die_room = this.environment;
|
||||||
|
this.environment.item_changed(corpse, true);
|
||||||
|
this.environment.item_changed(this, false);
|
||||||
|
if (isinfb && this.score && killer) {
|
||||||
|
//副本分数
|
||||||
|
killer.add_fbscore(this.score);
|
||||||
|
}
|
||||||
|
this.on_died && this.on_died(killer, corpse);
|
||||||
|
WORLD.auto_get(killer, corpse, this);
|
||||||
|
if (killer && killer.attack_skill && killer.attack_skill.on_enemy_die) {
|
||||||
|
killer.attack_skill.on_enemy_die(killer, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MONSTER.prototype.query_part = function () {
|
||||||
|
return MONSTER_PARTS.random();
|
||||||
|
}
|
||||||
|
MONSTER.prototype.heart_beat = function (dt) {
|
||||||
|
if (!this.fight_type && this.hp > 0) {
|
||||||
|
if (this.hp < this.max_hp) {
|
||||||
|
this.add_hp(parseInt(this.max_hp / 2));
|
||||||
|
}
|
||||||
|
if (this.mp < this.max_mp) {
|
||||||
|
this.add_mp(parseInt(this.max_mp / 2));
|
||||||
|
}
|
||||||
|
if (this.chat_msg) {
|
||||||
|
var r = this.random(10);
|
||||||
|
if (r > 5)
|
||||||
|
this.send_message(this.chat_msg.random());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
var MONSTER_PARTS = [
|
||||||
|
{ name: "左爪", hert: 0.8, crit: 0 },
|
||||||
|
{ name: "右爪", hert: 0.8, crit: 0 },
|
||||||
|
{ name: "后腿", hert: 0.85, crit: 0 },
|
||||||
|
{ name: "小腹", hert: 0.91, crit: 3 },
|
||||||
|
{ name: "胸前", hert: 0.95, crit: 4 },
|
||||||
|
{ name: "背部", hert: 0.97, crit: 4 },
|
||||||
|
{ name: "头部", hert: 1.2, crit: 10 },
|
||||||
|
{ name: "颈部", hert: 1.1, crit: 5 },
|
||||||
|
{ name: "前肢", hert: 0.85, crit: 1 },
|
||||||
|
{ name: "腰间", hert: 0.99, crit: 5 },
|
||||||
|
];
|
||||||
|
|
||||||
227
os/char/npc.js
Normal file
227
os/char/npc.js
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
|
||||||
|
NPC = function () {
|
||||||
|
this.hp = this.max_hp = 100;
|
||||||
|
this.mp = this.max_mp = 100;
|
||||||
|
this.str = this.con = this.dex = this.int = this.per = this.age = 20;
|
||||||
|
this.family = FAMILIES.NONE;
|
||||||
|
this.auto_pfm = true;
|
||||||
|
}
|
||||||
|
NPC.inherits(CHARACTER);
|
||||||
|
NPC.prototype.set_chat_msg = function (items, chance) {
|
||||||
|
if (items) {
|
||||||
|
this.chat_msg = items;
|
||||||
|
//this.chat_chance = chance || 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NPC.prototype.do_chat_msg = function () {
|
||||||
|
if (!this.is_fighting() && this.is_living && this.chat_msg) {
|
||||||
|
this.do_say(this.chat_msg.random());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NPC.prototype.format_equipments = function (call3, str, eqcmd) {
|
||||||
|
if (this.equipment && this.equipment.length) {
|
||||||
|
var eqstr = [];
|
||||||
|
for (var i = 0; i < this.equipment.length; i++) {
|
||||||
|
var item = this.equipment[i];
|
||||||
|
if (!item) continue;
|
||||||
|
eqstr.push("<span cmd='", eqcmd || "look", " ", (i),
|
||||||
|
" of ", this.id, "'>◆", item.color_name, "</span>\n");
|
||||||
|
}
|
||||||
|
if (eqstr.length) {
|
||||||
|
return str.push(call3, "装备着:\n", eqstr.join(""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str.push(call3, "穿着一件<wht>布衣</wht>。\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
NPC.prototype.set_goods = function () {
|
||||||
|
if (!arguments.length) return;
|
||||||
|
this.sell_list = [];
|
||||||
|
for (var i = 0; i < arguments.length; i++) {
|
||||||
|
var item = arguments[i];
|
||||||
|
var obj = OBJ.CREATE(item);
|
||||||
|
if (!obj) continue;
|
||||||
|
obj.count = -1;
|
||||||
|
this.sell_list.push(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NPC.prototype.query_commands = function (player) {
|
||||||
|
|
||||||
|
if (this.json) return this.json;
|
||||||
|
|
||||||
|
this.json = this.query_commands_json(player, false);
|
||||||
|
return this.json;
|
||||||
|
}
|
||||||
|
|
||||||
|
NPC.prototype.query_commands_json = function (player, isyb) {
|
||||||
|
var json = {};
|
||||||
|
json.type = "item";
|
||||||
|
json.desc = this.desc;
|
||||||
|
json.id = this.id;
|
||||||
|
json.name = this.name;
|
||||||
|
json.commands = [];
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "look " + this.id,
|
||||||
|
name: "查看"
|
||||||
|
});
|
||||||
|
if (!this.no_fight)
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "fight " + this.id,
|
||||||
|
name: "比试"
|
||||||
|
});
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "kill " + this.id,
|
||||||
|
name: "击杀"
|
||||||
|
});
|
||||||
|
if (this.on_master) {
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "bai " + this.id,
|
||||||
|
name: "拜师"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.on_checkskill || this.on_master) {
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "cha " + this.id,
|
||||||
|
name: "学习"
|
||||||
|
});
|
||||||
|
json.master = true;
|
||||||
|
}
|
||||||
|
if (this.sell_list) {
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "list " + this.id,
|
||||||
|
name: "购买"
|
||||||
|
});
|
||||||
|
json.trader = true;
|
||||||
|
}
|
||||||
|
if (this.question) {
|
||||||
|
for (var cmd in this.question) {
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "ask " + this.id + " about " + cmd,
|
||||||
|
name: "询问" + cmd
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.actions) {
|
||||||
|
for (var cmd in this.actions) {
|
||||||
|
if (!this.actions[cmd].name) continue;
|
||||||
|
json.commands.push({
|
||||||
|
cmd: cmd + " " + this.id,
|
||||||
|
name: this.actions[cmd].name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return JSON.stringify(json);
|
||||||
|
}
|
||||||
|
NPC.prototype.update_action = function (acts) {
|
||||||
|
this.json = null;
|
||||||
|
this.actions = acts;
|
||||||
|
}
|
||||||
|
|
||||||
|
var DIE_MSG = ["\n$N扑在地上挣扎了几下,腿一伸,口中喷出几口<HIR>鲜血</HIR>,死了!\n",
|
||||||
|
"\n$N大叫一声倒在地上,挣扎了几下,<HIR>死了</HIR>!\n",
|
||||||
|
"\n$N口中喷出几口<HIR>鲜血</HIR>,倒在地上,死了!\n"];
|
||||||
|
NPC.prototype.die = function (killer) {
|
||||||
|
if (!this.environment) return;
|
||||||
|
if (this.on_die && this.on_die(killer) == false) {
|
||||||
|
this.hp = 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.hp = 0;
|
||||||
|
this.clear_status();
|
||||||
|
this.send_room(DIE_MSG.random());
|
||||||
|
this.clear_follow();
|
||||||
|
var corpse = new CORPSE();
|
||||||
|
|
||||||
|
var isinfb = this.environment.is_fb();
|
||||||
|
corpse.init(this, isinfb);
|
||||||
|
this.die_room = this.environment;
|
||||||
|
this.environment.item_changed(corpse, true);
|
||||||
|
this.environment.item_changed(this, false);
|
||||||
|
if (isinfb && this.score && killer && killer.add_fbscore) {
|
||||||
|
//副本分数
|
||||||
|
killer.add_fbscore(this.score);
|
||||||
|
}
|
||||||
|
if (!isinfb && !this.no_refresh && !this.master && !this.die_room.is_shadow) {
|
||||||
|
this.call_out(this.relive, this.on_master ? 60000 : 300000);
|
||||||
|
}
|
||||||
|
this.on_died && this.on_died(killer, corpse);
|
||||||
|
WORLD.auto_get(killer, corpse, this);
|
||||||
|
if (killer && killer.attack_skill && killer.attack_skill.on_enemy_die) {
|
||||||
|
killer.attack_skill.on_enemy_die(killer, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NPC.prototype.relive = function () {
|
||||||
|
if (!this.die_room) return;
|
||||||
|
var room = ROOM.Get(this.die_room.path);
|
||||||
|
var obj = room.find_obj_bypath(this.path);
|
||||||
|
if (obj) return;
|
||||||
|
obj = NPC.CLONE(this.path);
|
||||||
|
room.item_changed(obj, true);
|
||||||
|
this.die_room = null;
|
||||||
|
this.equipment = null;
|
||||||
|
this.items = null;
|
||||||
|
this.skills = null;
|
||||||
|
}
|
||||||
|
NPC.prototype.destroy = function (msg) {
|
||||||
|
if (this.environment) {
|
||||||
|
this.environment.item_changed(this, false, msg);
|
||||||
|
}
|
||||||
|
this.clear_follow();
|
||||||
|
|
||||||
|
}
|
||||||
|
NPC.prototype.heart_beat = function (dt) {
|
||||||
|
|
||||||
|
if (!this.fight_type) {
|
||||||
|
if (this.hp < this.max_hp) {
|
||||||
|
this.add_hp(parseInt(this.max_hp / 2));
|
||||||
|
}
|
||||||
|
if (this.mp < this.max_mp) {
|
||||||
|
this.add_mp(parseInt(this.max_mp / 2));
|
||||||
|
}
|
||||||
|
if (this.chat_msg) {
|
||||||
|
if (this.random(10) > 8)
|
||||||
|
this.send_message(this.chat_msg.random());
|
||||||
|
}
|
||||||
|
this.on_heart_beat && this.on_heart_beat(dt);
|
||||||
|
} else if (this.hp <= 0) {
|
||||||
|
var eny = this.query_enemy();
|
||||||
|
if (!eny) {
|
||||||
|
this.hp = 1;
|
||||||
|
this.fight_type = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NPC.CREATE = function (path, env, oncreate, count) {
|
||||||
|
if (!path || !env) return;
|
||||||
|
|
||||||
|
|
||||||
|
if (env.environment) env = env.environment;
|
||||||
|
count = count || 1;
|
||||||
|
let obj = null;
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
obj = NPC.CLONE(path);
|
||||||
|
env.item_changed(obj, true);
|
||||||
|
if (oncreate) oncreate(obj);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
NPC.CLONE = function (path) {
|
||||||
|
let base = NPC.GET(path);
|
||||||
|
let item = Object.create(base);
|
||||||
|
item.clone();
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
NPC.GET = function (path) {
|
||||||
|
let base = WORLD.NPC_STROE.get(path);
|
||||||
|
if (!base) {
|
||||||
|
base = BASE.CREATE(__PATH.NPC, path);
|
||||||
|
if (!base) throw new Error('没有人物' + path + "的定义。");
|
||||||
|
//这里会自己调用create方法存储到NPC_STROE,记住了吗
|
||||||
|
}
|
||||||
|
return base;
|
||||||
|
}
|
||||||
845
os/char/user.js
Normal file
845
os/char/user.js
Normal file
@@ -0,0 +1,845 @@
|
|||||||
|
require("./character.js");
|
||||||
|
USER = function () {
|
||||||
|
this.socket = null;
|
||||||
|
this.family = FAMILIES.NONE;
|
||||||
|
this.max_item_count = 20;
|
||||||
|
this.max_store_count = 20;
|
||||||
|
this.money = 0;
|
||||||
|
this.request_count = 0;
|
||||||
|
this.cash_money = 0;
|
||||||
|
this.score = 0;
|
||||||
|
this.follower = null;
|
||||||
|
this.password = "";
|
||||||
|
this.loginTime = 0;
|
||||||
|
this.id_address = null;
|
||||||
|
this.user_level = 0;
|
||||||
|
this.eq_group = 0;
|
||||||
|
};
|
||||||
|
USER.inherits(CHARACTER);
|
||||||
|
USER.prototype.is_player = true;
|
||||||
|
|
||||||
|
USER.prototype.notify = function (text) {
|
||||||
|
//玩家不能接收消息的状态 不发送
|
||||||
|
if (this.socket && !this.is_faint && text && text.length < 30240)
|
||||||
|
this.socket.send(text);
|
||||||
|
}
|
||||||
|
USER.prototype.send = function (text) {
|
||||||
|
//直接发送消息 不管玩家状态
|
||||||
|
if (this.socket && text && text.length < 30240) {
|
||||||
|
this.socket.send(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
USER.prototype.notify_fail = function (text) {
|
||||||
|
if (this.socket && !this.is_faint)
|
||||||
|
this.socket.send(text);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
USER.prototype.send_warn = function (content, cmds, time) {
|
||||||
|
var str = ["{type:\"warn\",content:\""];
|
||||||
|
str.push(content);
|
||||||
|
str.push("\"");
|
||||||
|
if (time) {
|
||||||
|
str.push(",time:");
|
||||||
|
str.push(time);
|
||||||
|
}
|
||||||
|
str.push(",cmds:[");
|
||||||
|
for (var i = 0; i < cmds.length; i += 2) {
|
||||||
|
if (i > 0) str.push(",");
|
||||||
|
str.push("{cmd:\"");
|
||||||
|
str.push(cmds[i]);
|
||||||
|
str.push("\",name:\"");
|
||||||
|
str.push(cmds[i + 1]);
|
||||||
|
str.push("\"}");
|
||||||
|
}
|
||||||
|
str.push("]}");
|
||||||
|
this.send(str.join(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
USER.prototype.send_commands = function () {
|
||||||
|
var str = ["{type:\"cmds\",items:["];
|
||||||
|
for (var i = 0; i < arguments.length; i += 2) {
|
||||||
|
if (i > 0) str.push(",");
|
||||||
|
str.push("{cmd:\"");
|
||||||
|
str.push(arguments[i]);
|
||||||
|
str.push("\",name:\"");
|
||||||
|
str.push(arguments[i + 1]);
|
||||||
|
str.push("\"}");
|
||||||
|
}
|
||||||
|
str.push("]}");
|
||||||
|
this.send(str.join(""));
|
||||||
|
}
|
||||||
|
USER.prototype.is_connect = function () {
|
||||||
|
return this.socket !== null;
|
||||||
|
}
|
||||||
|
USER.prototype.send_loginmessage = function () {
|
||||||
|
if (!this.login_message) {
|
||||||
|
var str = ['{type:"login"'];
|
||||||
|
if (this.settings) {
|
||||||
|
str.push(",setting:")
|
||||||
|
str.push(JSON.stringify(this.settings));
|
||||||
|
this.no_message = this.settings['no_message'] == 1;
|
||||||
|
}
|
||||||
|
str.push(",id:\"");
|
||||||
|
str.push(this.id, '",level:', this.level);
|
||||||
|
str.push("}");
|
||||||
|
this.login_message = str.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.send(this.login_message)
|
||||||
|
}
|
||||||
|
USER.prototype.relogin = function (newUser) {
|
||||||
|
if (!newUser.socket) return;
|
||||||
|
newUser.socket.user = null;
|
||||||
|
this.socket = newUser.socket;
|
||||||
|
newUser.socket = null;
|
||||||
|
this.socket.user = this;
|
||||||
|
this.send_loginmessage();
|
||||||
|
|
||||||
|
if (!this.environment) {
|
||||||
|
var rm = ROOM.Get(this.quit_room);
|
||||||
|
if (!rm) {
|
||||||
|
return this.send("出现错误,请联系管理员报告BUG,谢谢!");
|
||||||
|
}
|
||||||
|
this.environment = rm;
|
||||||
|
}
|
||||||
|
this.send(this.environment.to_json());
|
||||||
|
this.environment.send_exits(this);
|
||||||
|
this.send(this.environment.items_to_json());
|
||||||
|
// if (!WORLD.is_end_cross(this)) {
|
||||||
|
this.send_room(this.name + "重新连线。");
|
||||||
|
if (this.environment.on_relogin) {
|
||||||
|
this.environment.on_relogin(this);
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
this.disconnect_time = 0;
|
||||||
|
this.check_state();
|
||||||
|
this.on_skillchanged();
|
||||||
|
}
|
||||||
|
USER.prototype.ip = function () {
|
||||||
|
return this.socket.remoteAddress;
|
||||||
|
}
|
||||||
|
USER.prototype.port = function () {
|
||||||
|
return this.socket.remotePort;
|
||||||
|
}
|
||||||
|
USER.prototype.quit = function () {
|
||||||
|
var rm = this.environment;
|
||||||
|
if (this.environment) {
|
||||||
|
|
||||||
|
this.team_out("离开了游戏,自动退出队伍");
|
||||||
|
this.environment.item_changed(this, false, this.name + "离开了游戏。");
|
||||||
|
this.environment = rm;
|
||||||
|
this.clear_follow();
|
||||||
|
this.environment.clear_copy(this);
|
||||||
|
this.environment.parent.on_leaved(this);
|
||||||
|
}
|
||||||
|
this.environment = null;
|
||||||
|
this.clear_status();
|
||||||
|
this.environment = rm;
|
||||||
|
WORLD.login_out(this);
|
||||||
|
this.environment = null;
|
||||||
|
|
||||||
|
this.clear_home();
|
||||||
|
if (this.socket) {
|
||||||
|
this.socket.user = null;
|
||||||
|
this.socket = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
USER.prototype.in_world = function () {
|
||||||
|
//判断是否连线进入过游戏,
|
||||||
|
return !!this.environment && !!this.socket;
|
||||||
|
}
|
||||||
|
USER.prototype.disconnect = function (isreplace) {
|
||||||
|
if (this.environment && this.socket) {
|
||||||
|
// this.send_message(this.name + "断线了。");
|
||||||
|
if (isreplace)
|
||||||
|
this.send("<RED>有人使用你的角色从别的地址登陆游戏,请重新登陆</RED>");
|
||||||
|
}
|
||||||
|
this.disconnect_time = Date.now();
|
||||||
|
if (this.socket) {
|
||||||
|
let socket = this.socket;
|
||||||
|
this.socket = null;
|
||||||
|
socket.user = null;
|
||||||
|
socket.end();
|
||||||
|
//if (!socket.destroyed)
|
||||||
|
// socket.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
USER.prototype.loadData = function (role) {
|
||||||
|
this.id = role.id;
|
||||||
|
this.name = role.name;
|
||||||
|
this.level = role.level;
|
||||||
|
//this.title = role.title;de
|
||||||
|
//role.data = role.data.toString();
|
||||||
|
var data = JSON.toObject(role.data);
|
||||||
|
for (var i = 0; i < SAVE_NUMPROP.length; i++) {
|
||||||
|
this[SAVE_NUMPROP[i]] = data.prop[i] || 0;
|
||||||
|
}
|
||||||
|
this.quit_room = data.quit_room;
|
||||||
|
this.items = this.read_items(data.items);
|
||||||
|
this.stores = this.read_items(data.stores);
|
||||||
|
this.books = data.books ?? [];
|
||||||
|
this.equipment = this.read_items(data.eq);
|
||||||
|
this.settings = data.settings;
|
||||||
|
|
||||||
|
this.skills = data.skills ?? {};
|
||||||
|
this.eq_groups = data.eq_groups;
|
||||||
|
this.sk_groups = data.sk_groups ?? [null, [], []];
|
||||||
|
this.temp = data.temp;
|
||||||
|
this.read_titles(data.titles);
|
||||||
|
if (data.follower) {
|
||||||
|
this.follower = [];
|
||||||
|
FOLLOWER.INIT_FROM_USER(this, data.follower);
|
||||||
|
for (var i = 0; i < data.follower.length; i++) {
|
||||||
|
this.follower.push({
|
||||||
|
id: data.follower[i].id,
|
||||||
|
path: data.follower[i].path
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var fam = this.query_temp("family");
|
||||||
|
if (fam) {
|
||||||
|
this.family = FAMILIES[fam] || FAMILIES.NONE;
|
||||||
|
}
|
||||||
|
this.user_level = role.user_level;
|
||||||
|
}
|
||||||
|
USER.prototype.read_titles = function (titles) {
|
||||||
|
this.titles = [];
|
||||||
|
if (!titles) return;
|
||||||
|
for (let item of titles) {
|
||||||
|
this.titles.push({
|
||||||
|
title: item[0], type: item[1],
|
||||||
|
use: item[2] === 1
|
||||||
|
});
|
||||||
|
if (item[2]) {
|
||||||
|
this.title = item[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
USER.prototype.read_items = function (items) {
|
||||||
|
var objs = [];
|
||||||
|
if (!items) return objs;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var item = items[i];
|
||||||
|
if (!item) {
|
||||||
|
objs.push(null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var obj = OBJ.CREATE(item[0]);
|
||||||
|
if (obj) {
|
||||||
|
obj.load_db(item);
|
||||||
|
obj.on_load(this);
|
||||||
|
objs.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return objs;
|
||||||
|
}
|
||||||
|
USER.prototype.do_login = function () {
|
||||||
|
this.init();
|
||||||
|
this.recount();
|
||||||
|
this.long_name();
|
||||||
|
WORLD.STATS.checkStats(this);
|
||||||
|
this.send_loginmessage();
|
||||||
|
if (this.family) this.family.on_login(this);
|
||||||
|
var rm = ROOM.Get(this.query_temp("new") ? "new/new1" : this.quit_room);
|
||||||
|
if (!rm || rm.is_fb()) rm = ROOM.Get(DEFAULT_ROOM);
|
||||||
|
if (rm.is_copy()) {
|
||||||
|
var copy_room = rm.query_copy2(this);
|
||||||
|
if (copy_room) {
|
||||||
|
this.moveto(copy_room, null, this.name + "连线进入这个世界。");
|
||||||
|
} else {
|
||||||
|
if (this.query_temp("new")) {
|
||||||
|
//还没完成新手教程的,从头开始
|
||||||
|
this.set_temp("new", 1);
|
||||||
|
this.items = [];//清理掉之前的物品
|
||||||
|
this.exp = this.pot = this.money = 0;
|
||||||
|
}
|
||||||
|
copy_room = rm.create_copy2(this);
|
||||||
|
this.moveto(copy_room);
|
||||||
|
}
|
||||||
|
//如果在副本副本下线,不可能
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.moveto(rm, null, this.name + "连线进入这个世界。");
|
||||||
|
}
|
||||||
|
this.check_state();
|
||||||
|
}
|
||||||
|
var DEFAULT_ROOM = "yz/wumiao";
|
||||||
|
|
||||||
|
|
||||||
|
var SAVE_NUMPROP = ["str", "con", "dex", "int", "gender", "max_mp", "limit_mp", "exp", "pot", "kar", "per"
|
||||||
|
, "hp", "mp", "max_item_count", "money", "reg_time",
|
||||||
|
"max_store_count", "cash_money", 'eq_group'];
|
||||||
|
|
||||||
|
USER.prototype.getData = function () {
|
||||||
|
var str = ["{prop:["];
|
||||||
|
for (var i = 0; i < SAVE_NUMPROP.length; i++) {
|
||||||
|
str.push(this[SAVE_NUMPROP[i]]);
|
||||||
|
str.push(",");
|
||||||
|
}
|
||||||
|
str.push(0);
|
||||||
|
str.push("],quit_room:\"");
|
||||||
|
if (this.environment) {
|
||||||
|
if (this.environment.is_fb() || this.environment.no_save
|
||||||
|
|| this.environment.parent.no_save) {
|
||||||
|
str.push(this.query_temp("enter_room"));
|
||||||
|
} else {
|
||||||
|
str.push(this.environment.path);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str.push(this.query_temp("enter_room", DEFAULT_ROOM));
|
||||||
|
}
|
||||||
|
str.push("\"");
|
||||||
|
var items = this.items;
|
||||||
|
if (items) {
|
||||||
|
str.push(",items:[");
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
if (i > 0) str.push(",");
|
||||||
|
items[i].save_db(str);
|
||||||
|
}
|
||||||
|
str.push("]");
|
||||||
|
}
|
||||||
|
items = this.stores;
|
||||||
|
if (items) {
|
||||||
|
str.push(",stores:[");
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
if (i > 0) str.push(",");
|
||||||
|
items[i].save_db(str);
|
||||||
|
}
|
||||||
|
str.push("]");
|
||||||
|
}
|
||||||
|
items = this.books;
|
||||||
|
if (items && items.length > 0) {
|
||||||
|
str.push(',books:["', items.join('", "'), '"]');
|
||||||
|
}
|
||||||
|
if (this.skills) {
|
||||||
|
str.push(",skills:");
|
||||||
|
str.push(JSON.stringify(this.skills));
|
||||||
|
}
|
||||||
|
str.push(",temp:", this.format_temp(this.temp));
|
||||||
|
if (this.settings) {
|
||||||
|
str.push(",settings:");
|
||||||
|
str.push(JSON.stringify(this.settings));
|
||||||
|
}
|
||||||
|
if (this.equipment) {
|
||||||
|
str.push(",eq:[");
|
||||||
|
for (var i = 0; i < this.equipment.length; i++) {
|
||||||
|
if (i > 0) str.push(",");
|
||||||
|
if (this.equipment[i]) this.equipment[i].save_db(str);
|
||||||
|
else str.push("null");
|
||||||
|
}
|
||||||
|
str.push("]");
|
||||||
|
}
|
||||||
|
if (this.titles) {
|
||||||
|
str.push(",titles:[");
|
||||||
|
for (var i = 0; i < this.titles.length; i++) {
|
||||||
|
if (i > 0) str.push(",");
|
||||||
|
var item = this.titles[i];
|
||||||
|
str.push('["', item.title, '","', item.type, '"');
|
||||||
|
if (item.use) str.push(',1');
|
||||||
|
str.push(']');
|
||||||
|
}
|
||||||
|
str.push("]");
|
||||||
|
}
|
||||||
|
if (this.follower) {
|
||||||
|
str.push(",follower:");
|
||||||
|
str.push(FOLLOWER.SAVE(this));
|
||||||
|
}
|
||||||
|
str.push(',eq_groups:[');
|
||||||
|
for (let i = 0; i < this.eq_groups.length; i++) {
|
||||||
|
if (i > 0) str.push(',');
|
||||||
|
if (i === this.eq_group || !this.eq_groups[i]) str.push('[]');
|
||||||
|
else str.push('["', this.eq_groups[i].join('","'), '"]');
|
||||||
|
}
|
||||||
|
str.push('],sk_groups:[');
|
||||||
|
for (let i = 0; i < this.sk_groups.length; i++) {
|
||||||
|
if (i > 0) str.push(',');
|
||||||
|
if (!this.sk_groups[i]) str.push('0');
|
||||||
|
else str.push('["', this.sk_groups[i].join('","'), '"]');
|
||||||
|
}
|
||||||
|
|
||||||
|
str.push("]}");
|
||||||
|
|
||||||
|
var role = {};
|
||||||
|
role.id = this.id;
|
||||||
|
role.userid = this.userid;
|
||||||
|
role.name = this.name;
|
||||||
|
role.level = this.level;
|
||||||
|
role.title = this.title || this.get_level_desc();
|
||||||
|
role.data = str.join("");
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
USER.prototype.save = function () {
|
||||||
|
|
||||||
|
WORLD.DB.saveRole(this.getData());
|
||||||
|
}
|
||||||
|
USER.prototype.die = function (killer) {
|
||||||
|
if (this.on_die && this.on_die(killer) === false) {
|
||||||
|
this.hp = 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.clear_status();
|
||||||
|
|
||||||
|
this.hp = 0;
|
||||||
|
this.mp = 0;
|
||||||
|
|
||||||
|
this.send_room(DIE_MSG.random());
|
||||||
|
var env = this.environment;
|
||||||
|
if (env.items.length < 10) {
|
||||||
|
var corpse = new CORPSE();
|
||||||
|
corpse.init(this);
|
||||||
|
env.item_changed(corpse, true);
|
||||||
|
}
|
||||||
|
env.item_changed(this, false);
|
||||||
|
this.environment = env;
|
||||||
|
this.check_state();
|
||||||
|
WORLD.on_user_die(this, killer);
|
||||||
|
this.on_died(killer);
|
||||||
|
}
|
||||||
|
USER.prototype.on_died = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
USER.prototype.check_state = function () {
|
||||||
|
if (this.hp <= 0) {
|
||||||
|
if (this.state) this.set_state(null);
|
||||||
|
this.send('{type:"die",commands:[{cmd:"relive",name:"去武庙复活"},{cmd:"relive locale",name:"原地复活"}]}');
|
||||||
|
} else {
|
||||||
|
if (this.state) this.set_state(this.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
USER.prototype.query_commands = function (player) {
|
||||||
|
if (this.commands_json) return this.commands_json;
|
||||||
|
var json = {};
|
||||||
|
json.type = "item";
|
||||||
|
json.desc = this.long_name();
|
||||||
|
json.id = this.id;
|
||||||
|
json.commands = [];
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "look " + this.id,
|
||||||
|
name: "查看"
|
||||||
|
});
|
||||||
|
if (player != this) {
|
||||||
|
if (!this.no_fight)
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "fight " + this.id,
|
||||||
|
name: "比试"
|
||||||
|
});
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "kill " + this.id,
|
||||||
|
name: "击杀"
|
||||||
|
});
|
||||||
|
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "team add " + this.id,
|
||||||
|
name: "邀请组队"
|
||||||
|
});
|
||||||
|
if (this.level > 1 && !this.query_setting("ban_master") && !this.query_temp("tudi") && !this.query_temp("shifu")) {
|
||||||
|
json.commands.push({
|
||||||
|
cmd: "baishi " + this.id,
|
||||||
|
name: "拜师"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.commands_json = JSON.stringify(json)
|
||||||
|
return this.commands_json;
|
||||||
|
}
|
||||||
|
USER.prototype.query_title = function (type) {
|
||||||
|
if (!this.titles) return null;
|
||||||
|
for (var i = 0; i < this.titles.length; i++) {
|
||||||
|
if (this.titles[i].type == type) {
|
||||||
|
return this.titles[i].title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
USER.prototype.add_title = function (title, type) {
|
||||||
|
if (!this.titles) this.titles = [];
|
||||||
|
var obj = { title: title, type: type };
|
||||||
|
for (var i = 0; i < this.titles.length; i++) {
|
||||||
|
if (this.titles[i].type == type) {
|
||||||
|
obj.use = this.titles[i].use;
|
||||||
|
this.titles.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (obj.title) {
|
||||||
|
if (!this.titles.length) obj.use = true;
|
||||||
|
this.titles.push(obj);
|
||||||
|
}
|
||||||
|
if (obj.use) {
|
||||||
|
if (!title) {
|
||||||
|
if (this.titles.length) {
|
||||||
|
this.titles[0].use = true;
|
||||||
|
title = this.titles[0].title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.title = title;
|
||||||
|
this.color_name = null;
|
||||||
|
if (this.environment)
|
||||||
|
this.environment.item_changed(this, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
USER.prototype.query_setting = function (name) {
|
||||||
|
if (!this.settings) return 0;
|
||||||
|
return this.settings[name] || 0;
|
||||||
|
}
|
||||||
|
USER.prototype.set_setting = function (name, value) {
|
||||||
|
if (!this.settings) this.settings = {};
|
||||||
|
|
||||||
|
if (!value || value == "0") {
|
||||||
|
delete this.settings[name];
|
||||||
|
} else {
|
||||||
|
if (value == "1") value = 1;
|
||||||
|
this.settings[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.login_message = null;
|
||||||
|
}
|
||||||
|
USER.prototype.heart_beat = function (dt) {
|
||||||
|
this.request_count = 0;
|
||||||
|
if (this.state && (!this.fight_type || this.state.allow_fight)) {
|
||||||
|
this.state.heat_count += 1;
|
||||||
|
if (this.state.heat_count >= this.state.rate) {
|
||||||
|
this.state.heat_count = 0;
|
||||||
|
if (this.state.on_enter(this, dt) === false) {
|
||||||
|
this.set_state(null, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.on_heart_beat && this.on_heart_beat(dt);
|
||||||
|
if (this.disconnect_time) {
|
||||||
|
//如果断线 在挂机就一天,没有就5分钟下线
|
||||||
|
if (dt - this.disconnect_time > (this.state ? 86400000 : 3600000)) {
|
||||||
|
return this.quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
USER.prototype.set_state = function (state, isauto) {
|
||||||
|
if (this.state && !state) {
|
||||||
|
if (this.state.on_stop) {
|
||||||
|
if (this.state.on_stop(this, isauto) == false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.send("{type:\"state\"}");
|
||||||
|
}
|
||||||
|
this.state = state;
|
||||||
|
if (state) {
|
||||||
|
state.rate = state.rate || 1;
|
||||||
|
state.heat_count = 0;
|
||||||
|
state.start_time = Date.now();
|
||||||
|
var msg = "{type:\"state\",state:\"你正在" + state.title + "\"";
|
||||||
|
if (state.desc) {
|
||||||
|
msg += ",desc:" + state.desc;
|
||||||
|
}
|
||||||
|
if (state.no_stop) {
|
||||||
|
msg += ",no_stop:true";
|
||||||
|
}
|
||||||
|
if (state.commands) {
|
||||||
|
msg += ",commands:" + state.commands;
|
||||||
|
}
|
||||||
|
this.send(msg + "}");
|
||||||
|
}
|
||||||
|
this.color_name = null;
|
||||||
|
if (this.environment)
|
||||||
|
this.environment.item_changed(this, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
USER.prototype.get_state = function () {
|
||||||
|
var str = "";
|
||||||
|
if (!this.socket) str += "<red><断线中></red>";
|
||||||
|
if (this.state) str += ("<hig><" + this.state.title + "></hig>");
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
const LEVELS_TITLES = ["普通百姓", "武士", "武师", "宗师", "武圣", "武帝", "武神"];
|
||||||
|
USER.prototype.long_name = function () {
|
||||||
|
if (!this.color_name) {
|
||||||
|
var cc = this.get_level_color();
|
||||||
|
var str = [];
|
||||||
|
if (cc) {
|
||||||
|
str.push("<");
|
||||||
|
str.push(cc);
|
||||||
|
str.push(">");
|
||||||
|
}
|
||||||
|
if (this.title) {
|
||||||
|
str.push(this.title);
|
||||||
|
str.push(" ");
|
||||||
|
}
|
||||||
|
if (!this.title || this.level > 0) {
|
||||||
|
str.push(LEVELS_TITLES[this.level]);
|
||||||
|
str.push(" ");
|
||||||
|
}
|
||||||
|
str.push(this.name);
|
||||||
|
if (cc) {
|
||||||
|
str.push("</");
|
||||||
|
str.push(cc);
|
||||||
|
str.push(">");
|
||||||
|
}
|
||||||
|
this.color_name = str.join("");
|
||||||
|
this.commands_json = null;
|
||||||
|
}
|
||||||
|
return this.color_name + this.get_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
USER.prototype.init_tasks = function () {
|
||||||
|
for (var i = 0; i < WORLD.TASKS.length; i++) {
|
||||||
|
var task = WORLD.TASKS[i];
|
||||||
|
task.on_start && task.on_start(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
USER.prototype.query_jingli = function () {
|
||||||
|
var expend = this.query_temp("ex_jl") || 0;
|
||||||
|
return 200 - expend + (this.query_temp("add_jl") || 0);
|
||||||
|
}
|
||||||
|
const jclimits = [1000, 2000, 3000, 5000, 7000, 10000, 15000];
|
||||||
|
USER.prototype.query_jclimit = function () {
|
||||||
|
return jclimits[this.level] || 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
USER.prototype.add_obj = function (obj, count) {
|
||||||
|
if (!obj) return;
|
||||||
|
if (typeof obj == "string") {
|
||||||
|
obj = OBJ.clone_to(obj, this, count);
|
||||||
|
if (!obj) return;
|
||||||
|
} else {
|
||||||
|
obj = this.push_item(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.items_changed(obj);
|
||||||
|
|
||||||
|
obj.notify_action(this, true);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
USER.prototype.remove_obj = function (obj, count) {
|
||||||
|
if (typeof obj == "string") {
|
||||||
|
obj = this.find_obj(obj);
|
||||||
|
}
|
||||||
|
if (!obj) return;
|
||||||
|
count = count || obj.count || 1;
|
||||||
|
var newobj = this.remove_item(obj, count);
|
||||||
|
if (newobj == obj) {
|
||||||
|
|
||||||
|
obj.notify_action(this, false);
|
||||||
|
}
|
||||||
|
this.items_changed(obj, count);
|
||||||
|
return newobj;
|
||||||
|
}
|
||||||
|
USER.prototype.items_changed = function (item, drop_count) {
|
||||||
|
|
||||||
|
if (drop_count) {
|
||||||
|
this.send('{type:"dialog",dialog:"pack",id:"' + item.id + '",remove:' + drop_count + ',money:' + this.money + '}');
|
||||||
|
} else {
|
||||||
|
if (item.is_money) {
|
||||||
|
return this.send('{type:"dialog",dialog:"pack",money:' + this.money + '}');
|
||||||
|
}
|
||||||
|
var str = ['{type:"dialog",dialog:"pack",'];
|
||||||
|
|
||||||
|
|
||||||
|
str.push('name:"');
|
||||||
|
str.push(item.color_name);
|
||||||
|
str.push('",id:"');
|
||||||
|
str.push(item.id);
|
||||||
|
str.push('",count:');
|
||||||
|
str.push(item.count);
|
||||||
|
str.push(',grade:');
|
||||||
|
str.push(item.grade);
|
||||||
|
str.push(',unit:"');
|
||||||
|
str.push(item.unit);
|
||||||
|
str.push('"');
|
||||||
|
if (item.is_equipment) {
|
||||||
|
str.push(',can_eq:1');
|
||||||
|
}
|
||||||
|
if (item.on_use) {
|
||||||
|
str.push(',can_use:1');
|
||||||
|
}
|
||||||
|
if (item.on_study) {
|
||||||
|
str.push(',can_study:1');
|
||||||
|
}
|
||||||
|
if (item.on_open) {
|
||||||
|
str.push(',can_open:1');
|
||||||
|
}
|
||||||
|
if (item.combine_count) {
|
||||||
|
str.push(',can_combine:' + item.combine_count);
|
||||||
|
}
|
||||||
|
str.push(',value:');
|
||||||
|
str.push(item.transable ? item.value : 0);
|
||||||
|
str.push(",money:");
|
||||||
|
str.push(this.money);
|
||||||
|
str.push('}');
|
||||||
|
this.send(str.join(""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//初始化人物使用的技能
|
||||||
|
USER.prototype.on_skillchanged = function () {
|
||||||
|
var str = ["{type:\"perform\",skills:["];
|
||||||
|
if (this.skills) {
|
||||||
|
var bases = ["", "force", "unarmed", "dodge", "parry", "throwing"];
|
||||||
|
var weapon = this.query_weapon_type(), base_type = null;
|
||||||
|
if (weapon != WEAPON_TYPE.NONE) bases[0] = weapon;
|
||||||
|
for (var i = 0; i < bases.length; i++) {
|
||||||
|
base_type = bases[i];
|
||||||
|
if (!base_type) continue;
|
||||||
|
var base_skill = this.skills[base_type];
|
||||||
|
if (base_skill) {
|
||||||
|
var sp_skill = SKILL.get(base_skill.enable_skill || base_type), pfmitem = null;
|
||||||
|
if (sp_skill && sp_skill.pfm) {
|
||||||
|
let sk_level = this.query_skill(base_skill.enable_skill || base_type, 0);
|
||||||
|
for (var p in sp_skill.pfm) {
|
||||||
|
pfmitem = sp_skill.pfm[p];
|
||||||
|
if (pfmitem.check && !pfmitem.check(this,
|
||||||
|
sk_level, base_type)) continue;
|
||||||
|
if (pfmitem.enable_skill && pfmitem.enable_skill != base_type) continue;
|
||||||
|
if (str.length > 1) str.push(",");
|
||||||
|
str.push("{id:\"");
|
||||||
|
str.push(base_type + "." + p);
|
||||||
|
str.push("\",name:\"");
|
||||||
|
str.push(pfmitem.query_name(this, base_type));
|
||||||
|
str.push("\"");
|
||||||
|
if (pfmitem.distime) {
|
||||||
|
str.push(",distime:");
|
||||||
|
str.push(pfmitem.query_distime(this));
|
||||||
|
}
|
||||||
|
str.push("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pfmitem = this.query_ref_skill(this.skills[base_skill.enable_skill]);
|
||||||
|
if (pfmitem && pfmitem.enable_skill && pfmitem.enable_skill == bases[i]) {
|
||||||
|
if (str.length > 1) str.push(",");
|
||||||
|
str.push("{id:\"");
|
||||||
|
str.push(bases[i] + ".ref");
|
||||||
|
str.push("\",name:\"");
|
||||||
|
str.push(pfmitem.query_name(this, base_type));
|
||||||
|
str.push("\"");
|
||||||
|
if (pfmitem.distime) {
|
||||||
|
str.push(",distime:");
|
||||||
|
str.push(pfmitem.query_distime(this, this.query_skill(base_skill.enable_skill), true));
|
||||||
|
}
|
||||||
|
str.push("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str.push("]");
|
||||||
|
str.push("}");
|
||||||
|
this.send(str.join(""));
|
||||||
|
}
|
||||||
|
USER.prototype.go_home = function () {
|
||||||
|
let my_room = this.query_home();
|
||||||
|
this.moveto(my_room, this.name + "向里面走去。");
|
||||||
|
}
|
||||||
|
USER.prototype.query_home = function (rm_name) {
|
||||||
|
let home = this.query_temp("home");
|
||||||
|
if (!home) return null;
|
||||||
|
if (!rm_name) rm_name = home == 1 ? "home/danjian" : "home/yuanzi";
|
||||||
|
let rm = ROOM.Get(rm_name);
|
||||||
|
let my_room = rm.query_copy2(this);
|
||||||
|
if (!my_room) {
|
||||||
|
my_room = rm.create_copy2(this);
|
||||||
|
}
|
||||||
|
return my_room;
|
||||||
|
}
|
||||||
|
|
||||||
|
USER.prototype.add_score = function (val) {
|
||||||
|
if (!val) return;
|
||||||
|
this.score += val;
|
||||||
|
WORLD.STATS.updateScore(this);
|
||||||
|
}
|
||||||
|
USER.prototype.add_money = function (val) {
|
||||||
|
let money = parseInt(this.money + val);
|
||||||
|
if (!(money >= 0)) return false;
|
||||||
|
this.money = money;
|
||||||
|
//this.send(`{"type":"dialog","dialog":"pack","money":${money}}`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
USER.prototype.add_cash = function (count, desc) {
|
||||||
|
if (!(count > 0 || count < 0)) return;
|
||||||
|
this.cash_money += count;
|
||||||
|
WORLD.log(this, count, desc);
|
||||||
|
if (count >= 0) {
|
||||||
|
this.notify("<hio>你获得了" + count + "元宝。</hio>");
|
||||||
|
}
|
||||||
|
this.send(`{"type":"dialog","dialog":"shop","money":[${this.money},${this.cash_money}]}`);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
USER.prototype.query_cash = function (is_cash) {
|
||||||
|
return this.cash_money;
|
||||||
|
}
|
||||||
|
USER.prototype.can_follow = function (npc) {
|
||||||
|
if (!this.follower) this.follower = [];
|
||||||
|
var max = this.query_temp("max_follower") || 3;
|
||||||
|
if (this.follower.length >= max) return false;
|
||||||
|
for (var i = 0; i < this.follower.length; i++) {
|
||||||
|
if (this.follower[i].path == npc.path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
USER.prototype.add_follower = function (npc) {
|
||||||
|
if (!this.can_follow(npc)) return false;
|
||||||
|
var item = {
|
||||||
|
path: npc.path,
|
||||||
|
id: npc.id
|
||||||
|
};
|
||||||
|
this.follower.push(item);
|
||||||
|
FOLLOWER.INIT(this, item);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
USER.prototype.clear_home = function (clear_follower = true) {
|
||||||
|
var home = ROOM.Get("home/yuanzi");
|
||||||
|
if (home) {
|
||||||
|
home = home.query_copy(this.id)
|
||||||
|
if (home)
|
||||||
|
home.clear_copy(this);
|
||||||
|
}
|
||||||
|
if (clear_follower)
|
||||||
|
FOLLOWER.CLEAR(this);
|
||||||
|
else
|
||||||
|
FOLLOWER.RESET(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
USER.prototype.clear_distime = function (pfmid) {
|
||||||
|
if (!this.temp) return;
|
||||||
|
if (pfmid) {
|
||||||
|
this.temp["pfm/" + pfmid] = null;
|
||||||
|
this.send('{type:"clearDistime",id:"' + pfmid + '"}');
|
||||||
|
} else {
|
||||||
|
for (var key in this.temp) {
|
||||||
|
if (key.startsWith("pfm/")) {
|
||||||
|
this.temp[key] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.send('{type:"clearDistime"}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var DIE_MSG = ["\n$N扑在地上挣扎了几下,腿一伸,口中喷出几口<HIR>鲜血</HIR>,死了!\n",
|
||||||
|
"\n$N大叫一声倒在地上,挣扎了几下,<HIR>死了</HIR>!\n",
|
||||||
|
"\n$N口中喷出几口<HIR>鲜血</HIR>,倒在地上,死了!\n"];
|
||||||
|
|
||||||
|
USER.prototype.add_combat_prop = function (name, val) {
|
||||||
|
this.add_prop(name, val);
|
||||||
|
if (!this.combat_props) this.combat_props = [];
|
||||||
|
this.combat_props.push([name, val]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
USER.prototype.clear_combat_prop = function (name, val) {
|
||||||
|
if (this.combat_props) {
|
||||||
|
for (let i = 0; i < this.combat_props.length; i++) {
|
||||||
|
this.add_prop(this.combat_props[i][0], -this.combat_props[i][1]);
|
||||||
|
}
|
||||||
|
this.combat_props = null;
|
||||||
|
this.recount();
|
||||||
|
this.notify_hp();
|
||||||
|
}
|
||||||
|
}
|
||||||
47
os/command.js
Normal file
47
os/command.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
所有命令的基类,
|
||||||
|
自动加载所有定义在__COMMAND文件夹下的命令文件
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
COMMAND = function () {
|
||||||
|
this.allow_fight = true;
|
||||||
|
this.allow_level = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMAND.inherits(BASE);
|
||||||
|
//将命令绑定到某些对象上 调用obj.do_commandname();
|
||||||
|
COMMAND.prototype.for_item = function (item, name) {
|
||||||
|
if (this.exec) {
|
||||||
|
name = name || this.command;
|
||||||
|
item.prototype["do_" + name] = this.exec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
COMMAND.prototype.create = function (fname) {
|
||||||
|
// console.error("command %s success", fname);
|
||||||
|
if (this.command) {
|
||||||
|
var str = this.command.split(',');
|
||||||
|
for (var i = 0; i < str.length; i++) {
|
||||||
|
if (WORLD.COMMANDS[str[i]]) console.error("command %s 重复", fname);
|
||||||
|
WORLD.COMMANDS[str[i]] = this;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error("command %s not have command name", fname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
COMMAND.prototype.update = function () {
|
||||||
|
if (this.command) {
|
||||||
|
var str = this.command.split(',');
|
||||||
|
for (var i = 0; i < str.length; i++) {
|
||||||
|
WORLD.COMMANDS[str[i]] = this;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error("command %s not have command name", fname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
COMMAND.DO = function (cmd, par1, par2, par3) {
|
||||||
|
var cmd = WORLD.COMMANDS[cmd];
|
||||||
|
if (cmd) {
|
||||||
|
cmd.enter(null, par1, par2, par3);
|
||||||
|
}
|
||||||
|
}
|
||||||
116
os/const.js
Normal file
116
os/const.js
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
SKILL_TYPES = {
|
||||||
|
BASE: 0,
|
||||||
|
SKILL: 1,
|
||||||
|
KNOWLEDGE: 2
|
||||||
|
};
|
||||||
|
BASE_SKILLS = {
|
||||||
|
FORCE: "force",
|
||||||
|
DODGE: "dodge",
|
||||||
|
PARRY: "parry",
|
||||||
|
BITE: "bite"
|
||||||
|
};
|
||||||
|
|
||||||
|
EQUIP_TYPE = {
|
||||||
|
WEAPON: 0,
|
||||||
|
CLOTH: 1,
|
||||||
|
SHOES: 2,
|
||||||
|
HEAD: 3,
|
||||||
|
CAPE: 4,
|
||||||
|
RING: 5,
|
||||||
|
NECKLACE: 6,//项链
|
||||||
|
JEWELS: 7,//饰品
|
||||||
|
WRIST: 8,//护腕
|
||||||
|
WAIST: 9,//腰带
|
||||||
|
THROWING: 10//
|
||||||
|
}
|
||||||
|
WEAPON_TYPE = {
|
||||||
|
NONE: "unarmed",
|
||||||
|
SWORD: "sword",
|
||||||
|
BLADE: "blade",
|
||||||
|
STAFF: "staff",
|
||||||
|
CLUB: "club",
|
||||||
|
WHIP: "whip",
|
||||||
|
THROWING: "throwing"
|
||||||
|
}
|
||||||
|
PROPERTIES = {
|
||||||
|
"con1": "先天根骨",
|
||||||
|
"dex1": "先天身法",
|
||||||
|
"int1": "先天悟性",
|
||||||
|
"str1": "先天臂力",
|
||||||
|
"con": "根骨",
|
||||||
|
"dex": "身法",
|
||||||
|
"int": "悟性",
|
||||||
|
"str": "臂力",
|
||||||
|
"fy": "防御",
|
||||||
|
"per": "容貌",
|
||||||
|
"age": "年龄",
|
||||||
|
gj: "攻击",
|
||||||
|
ds: "躲闪",
|
||||||
|
zj: "招架",
|
||||||
|
mz: "命中",
|
||||||
|
bj_per: "暴击",
|
||||||
|
limit_mp: "内力上限",
|
||||||
|
gjsd: "攻击速度",
|
||||||
|
gjsd_per: "攻击速度",
|
||||||
|
mz_per: "命中",
|
||||||
|
max_hp: "气血",
|
||||||
|
max_mp: "内力",
|
||||||
|
releasetime: "绝招释放时间",
|
||||||
|
distime: "绝招冷却时间",
|
||||||
|
expend_mp: "内力消耗",
|
||||||
|
releasetime_per: "绝招释放时间",
|
||||||
|
distime_per: "绝招冷却时间",
|
||||||
|
expend_mp_per: "内力消耗",
|
||||||
|
add_sh_per: "最终伤害",
|
||||||
|
add_bjsh_per: "暴击伤害",
|
||||||
|
diff_sh_per: "伤害减免",
|
||||||
|
diff_sh: "受到的伤害减少",
|
||||||
|
diff_fy_per: "忽视对方防御",
|
||||||
|
fy_per: "防御",
|
||||||
|
zj_per: "招架",
|
||||||
|
gj_per: "攻击",
|
||||||
|
ds_per: "躲闪",
|
||||||
|
hp_per: "气血",
|
||||||
|
study_per: "学习效率",
|
||||||
|
dazuo_per: "打坐效率",
|
||||||
|
lianxi_per: "练习效率",
|
||||||
|
busy: "忙乱时间",
|
||||||
|
busy_per: "忙乱时间",
|
||||||
|
diff_busy: "忽视忙乱",
|
||||||
|
diff_busy_per: "忽视忙乱",
|
||||||
|
diff_bj: "暴击抵抗",
|
||||||
|
add_sh: "伤害增加",
|
||||||
|
diff_downside: "负面状态抵抗",
|
||||||
|
diff_downside_per: "负面状态抵抗",
|
||||||
|
dazuo: "打坐效率",
|
||||||
|
|
||||||
|
diff_sh_per2: "伤害减免",
|
||||||
|
diff_fy_per2: "伤害减免",
|
||||||
|
recover_per: "疗伤效果",
|
||||||
|
|
||||||
|
lianyao1: "炼药效率",
|
||||||
|
lianyao2: "丹药产出",
|
||||||
|
|
||||||
|
lianyao_exp_per: "炼药获得经验",
|
||||||
|
no_fy: "无法防御",
|
||||||
|
no_pfm: "禁止绝招",
|
||||||
|
kuang_exp: "挖矿经验",
|
||||||
|
kuang_pot: "挖矿潜能",
|
||||||
|
|
||||||
|
diaoyu_exp: "钓鱼经验",
|
||||||
|
diaoyu_pot: "钓鱼潜能",
|
||||||
|
|
||||||
|
diaoyu1: "钓鱼效率",
|
||||||
|
kuang1: "挖矿效率",
|
||||||
|
caiyao1: "采药效率",
|
||||||
|
|
||||||
|
caiyao_exp: "采药经验",
|
||||||
|
caiyao_pot: "采药潜能",
|
||||||
|
|
||||||
|
|
||||||
|
xiulian_exp: "闭关经验",
|
||||||
|
shuangxiu: "双修效率",
|
||||||
|
fenjie: "分解获得的玄晶",
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
123
os/data.js
Normal file
123
os/data.js
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
|
||||||
|
module.exports = {
|
||||||
|
parties: new Map(),
|
||||||
|
PAIMAI: new Map(),
|
||||||
|
temp: {},
|
||||||
|
save: function () {
|
||||||
|
|
||||||
|
let str = ["{"];
|
||||||
|
this.save_temp(str);
|
||||||
|
this.on_save(str);
|
||||||
|
str.push('}');
|
||||||
|
return WORLD.DB.saveData(str.join(""));
|
||||||
|
},
|
||||||
|
temp_replacer: function (key, value) {
|
||||||
|
if (value.e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
save_temp: function (str) {
|
||||||
|
str.push('temp:', JSON.stringify(this.temp));
|
||||||
|
},
|
||||||
|
load: async function () {
|
||||||
|
const data = await WORLD.DB.readData(__PATH.DATA + "data.js");
|
||||||
|
this.temp = data.temp ?? {};
|
||||||
|
this.on_load(data);
|
||||||
|
},
|
||||||
|
query_temp: function (name, def) {
|
||||||
|
if (!this.temp) return;
|
||||||
|
let item = this.temp[name];
|
||||||
|
if (item && item.e) {
|
||||||
|
if (Date.now() <= item.e) {
|
||||||
|
return item.v;
|
||||||
|
}
|
||||||
|
delete this.temp[name];
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
return item || def;
|
||||||
|
},
|
||||||
|
set_temp: function (name, value, time) {
|
||||||
|
if (!this.temp) this.temp = {};
|
||||||
|
if (time) {
|
||||||
|
this.temp[name] = {
|
||||||
|
v: value,
|
||||||
|
e: Date.now() + time
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
this.temp[name] = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
remove_temp: function (name) {
|
||||||
|
if (!this.temp) return;
|
||||||
|
this.temp[name] = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
add_temp: function (name, value, time) {
|
||||||
|
if (!this.temp) this.temp = {};
|
||||||
|
let old = this.temp[name];
|
||||||
|
if (time) {
|
||||||
|
if (old && old.e) {
|
||||||
|
time = Date.now() + time;
|
||||||
|
if (old.e < Date.now()) {
|
||||||
|
old.e = time;
|
||||||
|
old.v = value;
|
||||||
|
} else {
|
||||||
|
if (old.e < time) old.e = time;
|
||||||
|
old.v += value;
|
||||||
|
}
|
||||||
|
return old.v;
|
||||||
|
} else {
|
||||||
|
let v = value + (old || 0);
|
||||||
|
this.temp[name] = {
|
||||||
|
v: v,
|
||||||
|
e: Date.now() + time
|
||||||
|
};
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let v = value + (old || 0);
|
||||||
|
this.temp[name] = v;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
temp_data: {},
|
||||||
|
clear_data: function () {
|
||||||
|
this.temp_data = {};
|
||||||
|
}
|
||||||
|
,
|
||||||
|
add_data: function (key, user, val) {
|
||||||
|
if (!val) return;
|
||||||
|
let data = this.temp_data[key];
|
||||||
|
if (!data) data = this.temp_data[key] = {};
|
||||||
|
let user_data = data[user.id];
|
||||||
|
if (!user_data) user_data = data[user.id] = { name: user.name, value: 0 };
|
||||||
|
user_data.value += val;
|
||||||
|
}, query_max_data: function (key) {
|
||||||
|
let data = this.temp_data[key];
|
||||||
|
if (!data) return;
|
||||||
|
let userData = null;
|
||||||
|
for (let key in data) {
|
||||||
|
let item = data[key];
|
||||||
|
if (!userData) userData = item;
|
||||||
|
else if (item.value > userData.value) {
|
||||||
|
userData = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return userData;
|
||||||
|
}, query_min_data: function (key) {
|
||||||
|
let data = this.temp_data[key];
|
||||||
|
if (!data) return;
|
||||||
|
let userData = null;
|
||||||
|
for (let key in data) {
|
||||||
|
let item = data[key];
|
||||||
|
if (!userData) userData = item;
|
||||||
|
else if (item.value < userData.value) {
|
||||||
|
userData = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return userData;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
250
os/item.js
Normal file
250
os/item.js
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
require("./util/util");
|
||||||
|
ITEM = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
ITEM.inherits(BASE);
|
||||||
|
|
||||||
|
|
||||||
|
ITEM.prototype.heart_beat = function (dt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
ITEM.prototype.init = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
//物件对命令的反应有几种方式实现
|
||||||
|
//1. 直接实现ON_XXXX,cmd里定义的有直接对象的命令推荐这种,比如on_accept是当别人给你东西时候,on_checkskill当别人学你技能时,适合目标明确的操作
|
||||||
|
//2. add_action方式,房间里的指令推荐用这种,虽然也可以实现1,但是因为调用add_action时候还没ID,适合房间的自定义命令和已定义的有目标的命令
|
||||||
|
//3. on(xxx)方式,对房间里的命令的反映,适合回应目标不是当前对象,或没有目标的命令
|
||||||
|
//actions里定义的动作会作为对象的可用操作发送出去
|
||||||
|
//添加物件可以接收的命令,目标是当前对象的
|
||||||
|
ITEM.prototype.add_action = function (cmd, name, func) {
|
||||||
|
if (!cmd) return;
|
||||||
|
if (!this.actions) this.actions = {};
|
||||||
|
var act = this.actions[cmd];
|
||||||
|
if (act) {
|
||||||
|
if (!name) {
|
||||||
|
act.action = func;
|
||||||
|
} else {
|
||||||
|
act.name = name;
|
||||||
|
}
|
||||||
|
if (!func) {
|
||||||
|
act.name = name;
|
||||||
|
} else {
|
||||||
|
act.action = func;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
act = {
|
||||||
|
name: name,
|
||||||
|
action: func
|
||||||
|
};
|
||||||
|
this.actions[cmd] = act;
|
||||||
|
}
|
||||||
|
this.json = null;
|
||||||
|
return act;
|
||||||
|
}
|
||||||
|
//移除物件可以接收的命令
|
||||||
|
ITEM.prototype.remove_action = function (name, func) {
|
||||||
|
if (!this.actions) this.actions = {};
|
||||||
|
if (typeof (name) === "string") {
|
||||||
|
delete this.actions[name];
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < name.length; i++) {
|
||||||
|
delete this.actions[name[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.json = null;
|
||||||
|
}
|
||||||
|
//执行命令 返回true表示已经完成命令,后续不需要执行
|
||||||
|
ITEM.prototype.exec = function (cmdName, pars) {
|
||||||
|
if (this.actions) {
|
||||||
|
var cmd = this.actions[cmdName];
|
||||||
|
if (cmd && cmd.action) {
|
||||||
|
return cmd.action.apply(this, pars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ITEM.prototype.max_item_count = 10;
|
||||||
|
ITEM.prototype.item_count = function () {
|
||||||
|
return this.items ? this.items.length : 0;
|
||||||
|
}
|
||||||
|
ITEM.prototype.is_full = function (val) {
|
||||||
|
if (!this.items) return false;
|
||||||
|
if (val) return this.items.length + val > this.max_item_count;
|
||||||
|
|
||||||
|
return this.items.length >= this.max_item_count;
|
||||||
|
}
|
||||||
|
ITEM.prototype.find_obj = function (id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ITEM.prototype.find_obj_bypath = function (path, parent) {
|
||||||
|
parent = parent || this;
|
||||||
|
if (!parent.items) return;
|
||||||
|
for (var i = 0; i < parent.items.length; i++) {
|
||||||
|
if (parent.items[i].path === path) {
|
||||||
|
return parent.items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ITEM.prototype.each_item = function (func, parent) {
|
||||||
|
if (!func) return;
|
||||||
|
parent = parent || this;
|
||||||
|
var l = parent.items.length;
|
||||||
|
for (var i = 0; i < l; i++) {
|
||||||
|
var item = parent.items[i];
|
||||||
|
if (!item) continue;
|
||||||
|
if (func(item) === false) return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ITEM.prototype.is = function (obj) {
|
||||||
|
if (!obj) return false;
|
||||||
|
if (typeof obj === "string")
|
||||||
|
return this.path === obj;
|
||||||
|
return this.path === obj.path;
|
||||||
|
}
|
||||||
|
ITEM.prototype.remove_item_byid = function (obj, count = 0) {
|
||||||
|
if (!obj || !this.items) return;
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
var item = this.items[i];
|
||||||
|
if (item.id === obj) {
|
||||||
|
if (item.combined && count > 0) {
|
||||||
|
var subitem = item.uncombine(count);
|
||||||
|
if (!subitem) return;
|
||||||
|
if (subitem === item) {
|
||||||
|
this.items.splice(i, 1);
|
||||||
|
}
|
||||||
|
return subitem;
|
||||||
|
} else {
|
||||||
|
this.items.splice(i, 1);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ITEM.prototype.remove_item = function (obj, count) {
|
||||||
|
if (!obj || !this.items) return;
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
var item = this.items[i];
|
||||||
|
if (item === obj) {
|
||||||
|
if (item.combined) {
|
||||||
|
var subitem = item.uncombine(count);
|
||||||
|
if (!subitem) return;
|
||||||
|
if (subitem === item) {
|
||||||
|
this.items.splice(i, 1);
|
||||||
|
}
|
||||||
|
return subitem;
|
||||||
|
} else {
|
||||||
|
this.items.splice(i, 1);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ITEM.prototype.move_item_to = function (obj, count, target) {
|
||||||
|
if (!obj || !this.items) return;
|
||||||
|
var moved_obj = this.remove_item(obj, count);
|
||||||
|
if (!target) return;
|
||||||
|
return target.push_item(moved_obj);
|
||||||
|
}
|
||||||
|
ITEM.prototype.push_item = function (moved_obj) {
|
||||||
|
if (!moved_obj) return;
|
||||||
|
if (!this.items) this.items = [];
|
||||||
|
if (moved_obj.is_money && this.money !== undefined) {
|
||||||
|
|
||||||
|
this.money += moved_obj.value * moved_obj.count;
|
||||||
|
} else if (moved_obj.combined) {
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].is(moved_obj)) {
|
||||||
|
this.items[i].combine(moved_obj);
|
||||||
|
return this.items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.items.push(moved_obj);
|
||||||
|
} else {
|
||||||
|
this.items.push(moved_obj);
|
||||||
|
}
|
||||||
|
return moved_obj;
|
||||||
|
}
|
||||||
|
ITEM.prototype.create_id = function () {
|
||||||
|
this.id = UTIL.create_id();
|
||||||
|
|
||||||
|
}
|
||||||
|
ITEM.prototype.refresh = function () {
|
||||||
|
this.json = null;
|
||||||
|
}
|
||||||
|
ITEM.prototype.is_hidden = function () {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ITEM.prototype.query_create_time = function () {
|
||||||
|
var id = this.id;
|
||||||
|
if (!id) return;
|
||||||
|
var time = parseInt(id.substr(4), 16);
|
||||||
|
|
||||||
|
return new Date(time * 1000 + UTIL.begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
ITEM.prototype.find_obj_byid = function (items, oid) {
|
||||||
|
if (!items) return;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].id === oid) {
|
||||||
|
return items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ITEM.prototype.long_name = function () {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ITEM.prototype.create = function (file, ctor) {
|
||||||
|
this.uid = this.create_uid();
|
||||||
|
}
|
||||||
|
ITEM.prototype.destroy = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ITEM.prototype.format_temp = function (temp, timeout = 120000) {
|
||||||
|
if (!temp) return "{}";
|
||||||
|
var dt = Date.now() + timeout;
|
||||||
|
var tmp = ["{"];
|
||||||
|
for (var key in temp) {
|
||||||
|
var v = temp[key];
|
||||||
|
if (!v) continue;
|
||||||
|
if (v.e) {
|
||||||
|
if (dt > v.e || !v.v) continue;
|
||||||
|
if (tmp.length > 1) tmp.push(",");
|
||||||
|
tmp.push("\"");
|
||||||
|
tmp.push(key);
|
||||||
|
tmp.push("\":{e:");
|
||||||
|
tmp.push(v.e);
|
||||||
|
tmp.push(",v:");
|
||||||
|
if (typeof v.v == "string") {
|
||||||
|
tmp.push("\"");
|
||||||
|
tmp.push(v.v);
|
||||||
|
tmp.push("\"");
|
||||||
|
} else {
|
||||||
|
tmp.push(v.v);
|
||||||
|
}
|
||||||
|
tmp.push("}");
|
||||||
|
} else {
|
||||||
|
if (tmp.length > 1) tmp.push(",");
|
||||||
|
tmp.push("\"");
|
||||||
|
tmp.push(key);
|
||||||
|
tmp.push("\":");
|
||||||
|
if (typeof v == "string") {
|
||||||
|
tmp.push("\"");
|
||||||
|
tmp.push(v);
|
||||||
|
tmp.push("\"");
|
||||||
|
} else {
|
||||||
|
tmp.push(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp.push("}");
|
||||||
|
return tmp.join("");
|
||||||
|
}
|
||||||
69
os/item/container.js
Normal file
69
os/item/container.js
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
require("./obj.js");
|
||||||
|
CONTAINER = function () {
|
||||||
|
this.count = 1;
|
||||||
|
this.combined = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
CONTAINER.inherits(OBJ);
|
||||||
|
CONTAINER.prototype.is_container = true;
|
||||||
|
CONTAINER.prototype.on_get = function () {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CONTAINER.prototype.set_items = function () {
|
||||||
|
for (var i = 0; i < arguments.length; i++) {
|
||||||
|
var item = arguments[i];
|
||||||
|
if (item) {
|
||||||
|
if (typeof item == "string") {
|
||||||
|
OBJ.clone_to(item, this);
|
||||||
|
} else if (item.length) {
|
||||||
|
OBJ.clone_to(item[0], this,item[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CONTAINER.prototype.query_items = function () {
|
||||||
|
return this.items;
|
||||||
|
}
|
||||||
|
//这个单纯的字符串描述
|
||||||
|
CONTAINER.prototype.get_desc = function (me) {
|
||||||
|
var str = [this.color_name, this.desc];
|
||||||
|
var items = this.query_items(me);
|
||||||
|
if (items && items.length) {
|
||||||
|
str.push("它里面有:");
|
||||||
|
for (var i = 0; i <items.length; i++) {
|
||||||
|
var item = items[i];
|
||||||
|
str.push("\t" + UTIL.to_c(item.count) + item.unit + item.color_name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str.push("它里面什么都没有。");
|
||||||
|
}
|
||||||
|
return str.join("\n");
|
||||||
|
}
|
||||||
|
CONTAINER.prototype.clear_items = function (me) {
|
||||||
|
this.items.length = 0;
|
||||||
|
}
|
||||||
|
//这个提供给LOOK SELECT命令的
|
||||||
|
CONTAINER.prototype.query_desc = function (me) {
|
||||||
|
if (this.json) return this.json;
|
||||||
|
var obj = {};
|
||||||
|
obj.type = "item";
|
||||||
|
obj.id = this.id;
|
||||||
|
obj.desc = this.get_desc(me);
|
||||||
|
obj.commands = [];
|
||||||
|
obj.commands.push({
|
||||||
|
cmd: "get all from " + this.id,
|
||||||
|
name: "全部拾取"
|
||||||
|
});
|
||||||
|
|
||||||
|
this.json = JSON.stringify(obj)
|
||||||
|
return this.json;
|
||||||
|
}
|
||||||
|
CONTAINER.CREATE = function (name,desc,lv,odds) {
|
||||||
|
var obj = OBJ.CREATE("sp/box#lv");
|
||||||
|
obj.items = OBJ.create_by_odds(odds);
|
||||||
|
obj.name = name;
|
||||||
|
obj.desc = desc || obj.desc;
|
||||||
|
obj.grade = lv;
|
||||||
|
obj.create();
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
71
os/item/corpse.js
Normal file
71
os/item/corpse.js
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
require("../item/obj.js");
|
||||||
|
CORPSE = function () {
|
||||||
|
this.unit = "具";
|
||||||
|
this.count = 1;
|
||||||
|
this.no_alloc = false;
|
||||||
|
}
|
||||||
|
CORPSE.inherits(CONTAINER);
|
||||||
|
CORPSE.prototype.on_get = function (player) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CORPSE.prototype.init = function (player, iskeep) {
|
||||||
|
this.create_id();
|
||||||
|
this.fromid = player.id;
|
||||||
|
this.name = player.name + "的尸体";
|
||||||
|
this.color_name = "<wht>" + this.name + "</wht>";
|
||||||
|
this.environment = player.environment;
|
||||||
|
this.desc = "然而" + player.call3() + "已经死了,只剩下一具尸体静静地躺在这里。";
|
||||||
|
this.items = player.query_drop();
|
||||||
|
if (!iskeep) this.call_out(this.disappear, 60000);
|
||||||
|
|
||||||
|
}
|
||||||
|
CORPSE.prototype.query_items = function (player) {
|
||||||
|
if (this.environment.is_fb() && player.team) {
|
||||||
|
if (!this.no_drops) {
|
||||||
|
this.no_drops = [];
|
||||||
|
for (var i = 0; i < player.team.length; i++) {
|
||||||
|
if (!this.environment.query_temp(player, player.team[i].id)) {
|
||||||
|
this.no_drops.push(player.team[i].id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.on_getitem = this.check_get;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.items;
|
||||||
|
}
|
||||||
|
CORPSE.prototype.clear_items = function (me, noget) {
|
||||||
|
this.items.length = 0;
|
||||||
|
if (noget && noget.length) this.items = noget;
|
||||||
|
}
|
||||||
|
CORPSE.prototype.check_get = function (player, item) {
|
||||||
|
if (!this.no_drops) return true;
|
||||||
|
if (this.no_drops.indexOf(player.id) == -1) return true;
|
||||||
|
player.notify('你不可以拾取' + item.color_name + "。");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CORPSE.prototype.disappear = function () {
|
||||||
|
if (this.items) this.items.length = 0;
|
||||||
|
if (this.environment) {
|
||||||
|
this.environment.notify("一阵风吹去," + this.name + "已经不见了。");
|
||||||
|
this.environment.item_changed(this, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CORPSE.prototype.query_desc = function (me) {
|
||||||
|
if (this.json) return this.json;
|
||||||
|
var obj = {};
|
||||||
|
obj.type = "item";
|
||||||
|
obj.desc = this.get_desc(me);
|
||||||
|
obj.id = this.id;
|
||||||
|
obj.commands = [];
|
||||||
|
obj.commands.push({
|
||||||
|
cmd: "get all from " + this.id,
|
||||||
|
name: "全部拾取"
|
||||||
|
});
|
||||||
|
if (this.no_alloc) {
|
||||||
|
return JSON.stringify(obj);
|
||||||
|
}
|
||||||
|
this.json = JSON.stringify(obj);
|
||||||
|
return this.json;
|
||||||
|
}
|
||||||
|
|
||||||
450
os/item/equipment.js
Normal file
450
os/item/equipment.js
Normal file
@@ -0,0 +1,450 @@
|
|||||||
|
|
||||||
|
require("../util/util.js");
|
||||||
|
EQUIPMENT = function () {
|
||||||
|
this.eq_type = EQUIP_TYPE.WEAPON;
|
||||||
|
this.level = 0;
|
||||||
|
this.exp = 0;
|
||||||
|
this.grade = 0;
|
||||||
|
this.count = 1;
|
||||||
|
this.combined = false;
|
||||||
|
this.showAction = true;
|
||||||
|
this.allow_fight = true;
|
||||||
|
this.otype = 4;
|
||||||
|
}
|
||||||
|
EQUIPMENT.inherits(OBJ);
|
||||||
|
EQUIPMENT.prototype.is_equipment = true;
|
||||||
|
EQUIPMENT.prototype.transable = true;
|
||||||
|
//EQUIPMENT.prototype.eq_msg = "$N装备上$n。";
|
||||||
|
//EQUIPMENT.prototype.uneq_msg = "$N脱下$n。";
|
||||||
|
EQUIPMENT.prototype.change_prop = function (me, is_attach) {
|
||||||
|
me.change_prop(this.prop, is_attach);
|
||||||
|
if (this.st_prop) {
|
||||||
|
for (var i = 0; i < this.st_prop.length; i++) {
|
||||||
|
me.change_prop(this.st_prop[i].prop, is_attach);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EQUIPMENT.prototype.notify_action = function (me, isadd) {
|
||||||
|
if (!this.on_use) return;
|
||||||
|
isadd = me.equipment[this.eq_type] == this;
|
||||||
|
if (isadd)
|
||||||
|
me.send("{type:'addAction',id:'" + this.id + "',name:'" + this.name + "',distime:" + (this.distime || 0) + "}");
|
||||||
|
else
|
||||||
|
me.send("{type:'removeAction',id:'" + this.id + "'}");
|
||||||
|
}
|
||||||
|
EQUIPMENT.prototype.check = function (me) {
|
||||||
|
if (!this.condition) return true;
|
||||||
|
for (var key in this.condition) {
|
||||||
|
var val = this.condition[key];
|
||||||
|
switch (key) {
|
||||||
|
case "skill":
|
||||||
|
for (var sk in val) {
|
||||||
|
if (me.query_skill(sk, 0) < val[sk]) {
|
||||||
|
var sk_base = SKILL.get(sk);
|
||||||
|
|
||||||
|
return me.notify_fail("你的" + sk_base.color_name + "等级不够" + val[sk] + ",无法装备" + this.color_name + "。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "str1":
|
||||||
|
case "con1":
|
||||||
|
case "dex1":
|
||||||
|
case "int1":
|
||||||
|
if (me[key.replace("1", "")] < val) {
|
||||||
|
return me.notify_fail("你的先天" + PROPERTIES[key] + "不够" + val + ",无法装备" + this.color_name + "。");;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "str":
|
||||||
|
case "con":
|
||||||
|
case "dex":
|
||||||
|
case "int":
|
||||||
|
if (me[key] + me.query_prop(key) < val) {
|
||||||
|
return me.notify_fail("你的" + PROPERTIES[key] + "不够" + val + ",无法装备" + this.color_name + "。");;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "gender":
|
||||||
|
if (me.gender != val) return me.notify_fail("你不是" + (val == 1 ? "男性" : "女性") + ",无法装备" + this.color_name + "。");
|
||||||
|
break;
|
||||||
|
case "desc":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
var me_val = me[key] || 0;
|
||||||
|
me_val = me_val + me.query_prop(key);
|
||||||
|
if (!me_val || me_val < val) {
|
||||||
|
|
||||||
|
return me.notify_fail("你的" + PROPERTIES[key] + "不够" + val + ",无法装备" + this.color_name + "。");;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EQUIPMENT.prototype.eq = function (me, notsend) {
|
||||||
|
if (this.check(me) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.on_eq && this.on_eq(me) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.change_prop(me, true);
|
||||||
|
this.check_group(me, true);
|
||||||
|
//me.add_score(this.query_score());
|
||||||
|
if (!notsend) {
|
||||||
|
if (this.eq_msg)
|
||||||
|
me.send_room(this.eq_msg, this);
|
||||||
|
else {
|
||||||
|
var msg;
|
||||||
|
switch (this.eq_type) {
|
||||||
|
case EQUIP_TYPE.WEAPON:
|
||||||
|
msg = "$N抽出一" + this.unit + this.color_name + "拿在手上。";
|
||||||
|
break;
|
||||||
|
case EQUIP_TYPE.CLOTH:
|
||||||
|
case EQUIP_TYPE.SHOES:
|
||||||
|
case EQUIP_TYPE.PANTS:
|
||||||
|
msg = "$N穿上一" + this.unit + this.color_name + "。";
|
||||||
|
break;
|
||||||
|
case EQUIP_TYPE.RING:
|
||||||
|
msg = "$N拿出一" + this.unit + this.color_name + "戴在手上。";
|
||||||
|
break;
|
||||||
|
case EQUIP_TYPE.NECKLACE:
|
||||||
|
case EQUIP_TYPE.JEWELS:
|
||||||
|
case EQUIP_TYPE.WRIST:
|
||||||
|
msg = "$N戴上一" + this.unit + this.color_name + "。";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
msg = "$N装备上一" + this.unit + this.color_name + "。";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
me.send_room(msg, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
me.send('{type:"dialog",dialog:"pack",id:"' + this.id + '",eq:' + this.eq_type + '}');
|
||||||
|
}
|
||||||
|
EQUIPMENT.prototype.uneq = function (me, notsend) {
|
||||||
|
this.on_uneq && this.on_uneq(me);
|
||||||
|
this.change_prop(me, false);
|
||||||
|
this.check_group(me, false);
|
||||||
|
//me.add_score(-this.query_score());
|
||||||
|
|
||||||
|
if (!notsend) {
|
||||||
|
if (this.uneq_msg)
|
||||||
|
me.send_room(this.uneq_msg, this);
|
||||||
|
else {
|
||||||
|
var msg;
|
||||||
|
switch (this.eq_type) {
|
||||||
|
case EQUIP_TYPE.WEAPON:
|
||||||
|
msg = "$N收回手中的" + this.color_name + "。";
|
||||||
|
break;
|
||||||
|
case EQUIP_TYPE.CLOTH:
|
||||||
|
case EQUIP_TYPE.SHOES:
|
||||||
|
case EQUIP_TYPE.PANTS:
|
||||||
|
case EQUIP_TYPE.WRIST:
|
||||||
|
msg = "$N将" + this.color_name + "脱了下来。";
|
||||||
|
break;
|
||||||
|
case EQUIP_TYPE.RING:
|
||||||
|
case EQUIP_TYPE.NECKLACE:
|
||||||
|
case EQUIP_TYPE.JEWELS:
|
||||||
|
msg = "$N将" + this.color_name + "取了下来。";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
msg = "$N脱下一" + this.unit + this.color_name + "。";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
me.send_room(msg, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
me.send('{type:"dialog",dialog:"pack",id:"' + this.id + '",uneq:' + this.eq_type + '}');
|
||||||
|
}
|
||||||
|
|
||||||
|
EQUIPMENT.prototype.condition_tostring = function (str) {
|
||||||
|
if (!this.condition) return;
|
||||||
|
for (var key in this.condition) {
|
||||||
|
var val = this.condition[key];
|
||||||
|
switch (key) {
|
||||||
|
case "skill":
|
||||||
|
for (var sk in val) {
|
||||||
|
var sk_base = SKILL.get(sk);
|
||||||
|
str.push(sk_base.name + "要求:" + val[sk] + "级");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "desc":
|
||||||
|
str.push(desc);
|
||||||
|
break;
|
||||||
|
case "gender":
|
||||||
|
str.push("性别要求:" + (val == 1 ? "男" : "女"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str.push(PROPERTIES[key] + "要求:" + val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
str.push("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EQUIPMENT.prototype.parts = ['武器', '衣服', '鞋', '头部', '披风', '戒指', '项链', '饰品', '护腕', '腰带', '暗器'];
|
||||||
|
EQUIPMENT.prototype.qualities = ["普通", "精良", "高级", "稀有", "绝世", "传说", "神器"];
|
||||||
|
|
||||||
|
EQUIPMENT.prototype.get_desc = function (me) {
|
||||||
|
var str = [this.color_name];
|
||||||
|
str.push("\n");
|
||||||
|
str.push(this.parts[this.eq_type]);
|
||||||
|
//str.push("\n");
|
||||||
|
//str.push(this.query_quality());
|
||||||
|
str.push("\n");
|
||||||
|
this.condition_tostring(str);
|
||||||
|
|
||||||
|
if (this.desc) str.push(this.desc);
|
||||||
|
str.push("\n");
|
||||||
|
if (this.prop) {
|
||||||
|
str.push("<");
|
||||||
|
str.push(this.query_grade_color());
|
||||||
|
str.push(">");
|
||||||
|
str.push(UTIL.prop_toString(this.prop));
|
||||||
|
|
||||||
|
str.push("</");
|
||||||
|
str.push(this.query_grade_color());
|
||||||
|
str.push(">\n");
|
||||||
|
}
|
||||||
|
if (this.st_prop) {
|
||||||
|
for (var i = 0; i < this.st_prop.length; i++) {
|
||||||
|
str.push(this.st_prop[i].name);
|
||||||
|
str.push("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.hole_count) {
|
||||||
|
for (var i = 0; i < this.hole_count; i++) {
|
||||||
|
str.push("◇");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.query_group_desc(me, str);
|
||||||
|
return str.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EQUIPMENT.prototype.query_quality = function () {
|
||||||
|
return this.qualities[this.grade];
|
||||||
|
}
|
||||||
|
const level_desc = ["", "☆", "★", "★☆", "★★", "★★☆", "★★★",
|
||||||
|
"★★★☆", "★★★★", "★★★★☆", "★★★★★", "★★★★★☆", "★★★★★★"];
|
||||||
|
EQUIPMENT.prototype.level_up = function (lev) {
|
||||||
|
var cc = this.query_grade_color();
|
||||||
|
|
||||||
|
this.prop = {};
|
||||||
|
this.level = lev;
|
||||||
|
this.levelchange_prop();
|
||||||
|
this.color_name = "<" + cc + ">" + level_desc[this.level] + this.name + "</" + cc + ">";
|
||||||
|
this.json = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EQUIPMENT.prototype.levelData = [
|
||||||
|
0, 10, 20, 40, 70, 110, 160, 220, 290, 370, 460, 560, 670
|
||||||
|
];
|
||||||
|
EQUIPMENT.prototype.levelchange_prop = function () {
|
||||||
|
if (!(this.level >= 0 && this.level < 13)) return;
|
||||||
|
const base_props = this.original_prop ?? Object.getPrototypeOf(this).prop;
|
||||||
|
var val = this.levelData[this.level];
|
||||||
|
for (var key in base_props) {
|
||||||
|
var value = base_props[key];
|
||||||
|
switch (key) {
|
||||||
|
case "desc":
|
||||||
|
case "str1":
|
||||||
|
case "con1":
|
||||||
|
case "dex1":
|
||||||
|
case "int1":
|
||||||
|
case "per":
|
||||||
|
case "kar":
|
||||||
|
case "skill":
|
||||||
|
this.prop[key] = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "fy_per":
|
||||||
|
case "zj_per":
|
||||||
|
case "mz_per":
|
||||||
|
case "hp_per":
|
||||||
|
case "ds_per":
|
||||||
|
case "gj_per":
|
||||||
|
case "diff_busy":
|
||||||
|
case "busy_per":
|
||||||
|
case "caiyao1":
|
||||||
|
case "diaoyu1":
|
||||||
|
case "kuang1":
|
||||||
|
case "lianyao1":
|
||||||
|
case "diff_sh":
|
||||||
|
case "expend_mp":
|
||||||
|
this.prop[key] = value + parseInt(value * val / 1000);
|
||||||
|
break;
|
||||||
|
case "diff_downside_per":
|
||||||
|
case "gjsd":
|
||||||
|
case "releasetime":
|
||||||
|
case "distime":
|
||||||
|
case "diff_downside":
|
||||||
|
case "distime_per":
|
||||||
|
case "releasetime_per":
|
||||||
|
case "gjsd_per":
|
||||||
|
|
||||||
|
case "bj_per":
|
||||||
|
case "diff_bj":
|
||||||
|
case "add_bjsh_per":
|
||||||
|
|
||||||
|
case "add_sh_per":
|
||||||
|
case "diff_busy_per":
|
||||||
|
case "diff_sh_per":
|
||||||
|
case "diff_fy_per":
|
||||||
|
case "expend_mp_per":
|
||||||
|
case "busy":
|
||||||
|
this.prop[key] = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (PROPERTIES[key])
|
||||||
|
this.prop[key] = value + parseInt(value * val / 100);
|
||||||
|
else
|
||||||
|
this.prop[key] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EQUIPMENT.prototype.clear_stone = function () {
|
||||||
|
if (!this.st_prop) return;
|
||||||
|
|
||||||
|
this.hole_count += (this.st_prop.length);
|
||||||
|
this.st_prop.length = 0;
|
||||||
|
}
|
||||||
|
EQUIPMENT.prototype.push_stone = function (stone) {
|
||||||
|
if (!stone || !stone.prop) return false;
|
||||||
|
if (!this.hole_count) return false;
|
||||||
|
|
||||||
|
if (!this.st_prop) this.st_prop = [];
|
||||||
|
this.hole_count--;
|
||||||
|
var cc = stone.query_grade_color();
|
||||||
|
var str = ["<", cc, ">◆", stone.name, " "];
|
||||||
|
str.push(UTIL.prop_toString(stone.prop, " "));
|
||||||
|
str.push("</");
|
||||||
|
str.push(cc);
|
||||||
|
str.push(">");
|
||||||
|
|
||||||
|
this.json = null;
|
||||||
|
this.st_prop.push({
|
||||||
|
id: stone.id,
|
||||||
|
path: stone.path,
|
||||||
|
name: str.join(""),
|
||||||
|
prop: stone.prop,
|
||||||
|
grade: stone.grade
|
||||||
|
});
|
||||||
|
}
|
||||||
|
EQUIPMENT.prototype.clone = function (me) {
|
||||||
|
var obj = OBJ.CREATE(this.path);
|
||||||
|
if (this.temp) {
|
||||||
|
obj.temp = {};
|
||||||
|
for (var key in this.temp) {
|
||||||
|
obj.temp[key] = this.temp[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
obj.on_reload && obj.on_reload(me);
|
||||||
|
obj.level_up(this.level);
|
||||||
|
obj.st_prop = this.st_prop;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EQUIPMENT.prototype.save_db = function (str) {
|
||||||
|
str.push('["', this.path, '","', this.id, '",', this.level);
|
||||||
|
if (this.st_prop && this.st_prop.length) {
|
||||||
|
str.push(",[");
|
||||||
|
for (var i = 0; i < this.st_prop.length; i++) {
|
||||||
|
if (i > 0) str.push(",");
|
||||||
|
str.push('"', this.st_prop[i].path, '"');
|
||||||
|
}
|
||||||
|
str.push("]");
|
||||||
|
}
|
||||||
|
// else {
|
||||||
|
// str.push(',[]');
|
||||||
|
// }
|
||||||
|
if (this.is_locked)
|
||||||
|
str.push(',1');
|
||||||
|
if (this.temp)
|
||||||
|
str.push(",", this.format_temp(this.temp));
|
||||||
|
str.push("]");
|
||||||
|
}
|
||||||
|
EQUIPMENT.prototype.load_db = function (data) {
|
||||||
|
//const [path, id, level, sts, locked,temp] = data;
|
||||||
|
this.id = data[1];
|
||||||
|
if (data[2] > 0) {
|
||||||
|
this.level = data[2];
|
||||||
|
}
|
||||||
|
for (let i = 3; i < data.length; i++) {
|
||||||
|
let value = data[i];
|
||||||
|
if (value === 1) this.is_locked = true;
|
||||||
|
else if (Array.isArray(value)) {
|
||||||
|
for (var j = 0; j < value.length; j++) {
|
||||||
|
var st_item = OBJ.CREATE(value[j]);
|
||||||
|
if (st_item) {
|
||||||
|
this.push_stone(st_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (typeof value === 'object') {
|
||||||
|
this.temp = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
EQUIPMENT.prototype.on_load = function (me) {
|
||||||
|
this.on_reload && this.on_reload(me);
|
||||||
|
if (this.level > 0) {
|
||||||
|
this.level_up(this.level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EQUIPMENT.prototype.VALUES = [100, 1000, 2000, 10000, 100000, 1000000, 100000000];
|
||||||
|
EQUIPMENT.prototype.on_create = function (path, par) {
|
||||||
|
this.value = this.VALUES[this.grade];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EQUIPMENT.prototype.query_group_desc = function (me, str) {
|
||||||
|
if (!this.group_prop || !this.group_name) return;
|
||||||
|
var count = 0;
|
||||||
|
if (me && me.equipment) {
|
||||||
|
for (var i = 0; i < me.equipment.length; i++) {
|
||||||
|
if (me.equipment[i] && me.equipment[i].group_name == this.group_name) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 2; i < 8; i++) {
|
||||||
|
var prop = this.group_prop(i);
|
||||||
|
if (prop) {
|
||||||
|
var cc = i <= count ? this.query_grade_color() : "blk";
|
||||||
|
|
||||||
|
str.push("<");
|
||||||
|
str.push(cc);
|
||||||
|
str.push(">");
|
||||||
|
str.push("\n");
|
||||||
|
str.push(UTIL.to_c(i));
|
||||||
|
str.push("件套:");
|
||||||
|
str.push(UTIL.prop_toString(prop, " "));
|
||||||
|
str.push("</");
|
||||||
|
str.push(cc);
|
||||||
|
str.push(">");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EQUIPMENT.prototype.check_group = function (me, isadd) {
|
||||||
|
if (!this.group_prop || !this.group_name) return;
|
||||||
|
var count = isadd ? 1 : 0;
|
||||||
|
for (var i = 0; i < me.equipment.length; i++) {
|
||||||
|
if (me.equipment[i] && me.equipment[i].group_name == this.group_name) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var prop = this.group_prop(count);
|
||||||
|
if (prop) {
|
||||||
|
me.change_prop(prop, isadd);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
25
os/item/money.js
Normal file
25
os/item/money.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
require("../item/obj.js");
|
||||||
|
MONEY = function () {
|
||||||
|
this.is_cash = false;
|
||||||
|
this.combined = true;
|
||||||
|
this.count = 1;
|
||||||
|
}
|
||||||
|
MONEY.inherits(OBJ);
|
||||||
|
MONEY.prototype.is_money = true;
|
||||||
|
MONEY.prototype.transable = true;
|
||||||
|
|
||||||
|
MONEY.prototype.create = function () {
|
||||||
|
this.create_id();
|
||||||
|
if (this.is_cash) {
|
||||||
|
this.color_name = "<hio>" + this.name + "</hio>";
|
||||||
|
} else {
|
||||||
|
if (this.value == 1)
|
||||||
|
this.color_name = "<yel>" + this.name + "</yel>";
|
||||||
|
else if (this.value == 100)
|
||||||
|
this.color_name = "<hiw>" + this.name + "</hiw>";
|
||||||
|
else
|
||||||
|
this.color_name = "<hiy>" + this.name + "</hiy>";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
228
os/item/obj.js
Normal file
228
os/item/obj.js
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
|
||||||
|
OBJ = function () {
|
||||||
|
this.unit = "个";
|
||||||
|
this.path = null;
|
||||||
|
this.count = 1;
|
||||||
|
this.combined = true;
|
||||||
|
this.grade = 0;
|
||||||
|
this.otype = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBJ.inherits(ITEM);
|
||||||
|
OBJ.prototype.transable = false;
|
||||||
|
OBJ.prototype.init = function (me) {
|
||||||
|
this.on_init && this.on_init(me);
|
||||||
|
}
|
||||||
|
OBJ.prototype.long_name = function () {
|
||||||
|
if (this.combined) return UTIL.to_c(this.count) + this.unit + this.color_name;
|
||||||
|
return this.color_name;
|
||||||
|
}
|
||||||
|
OBJ.prototype.unit_name = function (count) {
|
||||||
|
return UTIL.to_c(count || this.count) + this.unit + this.color_name;
|
||||||
|
|
||||||
|
}
|
||||||
|
OBJ.prototype.item_to_json = function () {
|
||||||
|
return `["${this.name}","${this.id}",${this.count},${this.grade},"${this.unit}",${parseInt(this.value / 10)},${this.is_equipment ? 1 : 0},${this.on_use ? 1 : 0},${this.on_study ? 1 : 0},${this.on_open ? 1 : 0},${this.combine_count > 0 ? this.combine_count : 0}]`;
|
||||||
|
}
|
||||||
|
OBJ.prototype.query_commands = function (me) {
|
||||||
|
return this.query_desc(me);
|
||||||
|
}
|
||||||
|
OBJ.prototype.query_desc = function (me) {
|
||||||
|
if (this.json) return this.json;
|
||||||
|
var obj = {};
|
||||||
|
obj.type = "item";
|
||||||
|
obj.id = this.id;
|
||||||
|
obj.desc = this.get_desc(me);
|
||||||
|
obj.commands = [];
|
||||||
|
obj.commands.push({
|
||||||
|
cmd: "get " + this.id,
|
||||||
|
name: "捡起"
|
||||||
|
});
|
||||||
|
|
||||||
|
this.json = JSON.stringify(obj)
|
||||||
|
return this.json;
|
||||||
|
}
|
||||||
|
OBJ.prototype.get_desc = function () {
|
||||||
|
return this.color_name + "\n" + this.desc;
|
||||||
|
}
|
||||||
|
OBJ.prototype.uncombine = function (spcount) {
|
||||||
|
if (!spcount || spcount === this.count) return this;
|
||||||
|
if (spcount < this.count) {
|
||||||
|
var item = this.clone();
|
||||||
|
item.count = spcount;
|
||||||
|
this.count -= spcount;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OBJ.prototype.clone = function () {
|
||||||
|
var item = OBJ.CREATE(this.path);
|
||||||
|
if (this.temp) {
|
||||||
|
item.temp = Object.assign({}, this.temp);
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
OBJ.prototype.combineTemp = function (target, source) {
|
||||||
|
if (!source) return target;
|
||||||
|
if (!target) return source;
|
||||||
|
for (let key in source) {
|
||||||
|
let val = source[key];
|
||||||
|
if (val && typeof val === "number") {
|
||||||
|
let thisVal = target[key];
|
||||||
|
if (!thisVal) {
|
||||||
|
target[key] = val;
|
||||||
|
} else if (typeof thisVal === "number") {
|
||||||
|
target[key] = thisVal > val ? thisVal : val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
OBJ.prototype.combine = function (obj) {
|
||||||
|
if (this.is(obj)) {
|
||||||
|
if (obj.temp || this.temp) {
|
||||||
|
this.temp = this.combineTemp(this.temp, obj.temp);
|
||||||
|
}
|
||||||
|
this.count += (obj.count || 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OBJ.clone_to = function (otype, to, count) {
|
||||||
|
if (!otype || !to) return;
|
||||||
|
var item = OBJ.CREATE(otype);
|
||||||
|
if (!item) return;
|
||||||
|
count = count || 1;
|
||||||
|
if (item.is_money && to.money != undefined) {
|
||||||
|
item.count = count;
|
||||||
|
to.money += item.value * item.count;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
if (!to.items) to.items = [];
|
||||||
|
if (item.combined) {
|
||||||
|
for (var i = 0; i < to.items.length; i++) {
|
||||||
|
if (to.items[i].is(item)) {
|
||||||
|
to.items[i].count += count;
|
||||||
|
return to.items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item.count = count;
|
||||||
|
to.items.push(item);
|
||||||
|
} else {
|
||||||
|
to.items.push(item);
|
||||||
|
for (var i = 0; i < count - 1; i++) {
|
||||||
|
item = OBJ.CREATE(otype, 1);
|
||||||
|
to.items.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
OBJ.prototype.save_db = function (str) {
|
||||||
|
str.push('["', this.path, '","', this.id, '",', this.count);
|
||||||
|
if (this.is_locked) {
|
||||||
|
str.push(',1');
|
||||||
|
}
|
||||||
|
if (this.temp)
|
||||||
|
str.push(",", this.format_temp(this.temp));
|
||||||
|
str.push(']');
|
||||||
|
|
||||||
|
}
|
||||||
|
OBJ.prototype.load_db = function (data) {
|
||||||
|
//path, id, count, temp or lock
|
||||||
|
|
||||||
|
this.id = data[1];
|
||||||
|
if (data[2] > 1) this.count = data[2];
|
||||||
|
if (data[3]) {
|
||||||
|
if (data[3] === 1) {
|
||||||
|
this.is_locked = true;
|
||||||
|
} else if (typeof data[3] === 'object') {
|
||||||
|
this.temp = data[3];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data[4]) this.temp = data[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
OBJ.prototype.on_load = function (me) {
|
||||||
|
this.on_reload && this.on_reload(me);
|
||||||
|
}
|
||||||
|
|
||||||
|
OBJ.prototype.on_clone = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
OBJ.CREATE = function (otype, count) {
|
||||||
|
let base = WORLD.OBJ_STROE.get(otype);
|
||||||
|
if (!base) {
|
||||||
|
base = BASE.CREATE(__PATH.OBJ, otype);
|
||||||
|
if (!base) throw new Error('没有物品' + otype + "的定义。");
|
||||||
|
//这里会自己调用create方法存储到OBJ_STROE,记住了吗
|
||||||
|
}
|
||||||
|
|
||||||
|
// var item = BASE.CREATE(__PATH.OBJ, otype);
|
||||||
|
// if (!item) return;
|
||||||
|
let item = Object.create(base);
|
||||||
|
item.create_id();
|
||||||
|
item.on_clone();
|
||||||
|
if (count > 1)
|
||||||
|
item.count = count;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
var grade_color = ["wht", "hig", "hic", "hiy", "HIZ", "hio", "ord"];
|
||||||
|
|
||||||
|
OBJ.prototype.create = function (path, par) {
|
||||||
|
if (par) this.path = path + par;
|
||||||
|
this.create_id();
|
||||||
|
this.on_create && this.on_create(path, par);
|
||||||
|
var cc = grade_color[this.grade];
|
||||||
|
this.color_name = "<" + cc + ">" + this.name + "</" + cc + ">";
|
||||||
|
WORLD.OBJ_STROE.set(this.path, this);
|
||||||
|
}
|
||||||
|
OBJ.prototype.update = function (path, par) {
|
||||||
|
this.create(path, par);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
OBJ.prototype.query_grade_color = function () {
|
||||||
|
return grade_color[this.grade];
|
||||||
|
}
|
||||||
|
|
||||||
|
OBJ.prototype.notify_action = function (me, isadd) {
|
||||||
|
if (!this.on_use) return;
|
||||||
|
if (!this.showAction) return;
|
||||||
|
if (isadd)
|
||||||
|
me.send("{type:'addAction',id:'" + this.id + "',name:'" + this.name + "',distime:" + (this.distime || 0) + "}");
|
||||||
|
else
|
||||||
|
me.send("{type:'removeAction',id:'" + this.id + "'}");
|
||||||
|
}
|
||||||
|
|
||||||
|
OBJ.prototype.query_temp = CHARACTER.prototype.query_temp;
|
||||||
|
OBJ.prototype.set_temp = CHARACTER.prototype.set_temp;
|
||||||
|
OBJ.prototype.remove_temp = CHARACTER.prototype.remove_temp;
|
||||||
|
|
||||||
|
OBJ.prototype.add_temp = CHARACTER.prototype.add_temp;
|
||||||
|
OBJ.create_by_odds = function (args) {
|
||||||
|
var items = [];
|
||||||
|
if (!args) return items;
|
||||||
|
let drop = null, per = null,
|
||||||
|
obj = null;
|
||||||
|
for (var i = 0; i < args.length; i++) {
|
||||||
|
drop = args[i];
|
||||||
|
if (!drop) continue;
|
||||||
|
|
||||||
|
per = Math.random() * 10000;
|
||||||
|
obj = (drop.odds || 10000) > per ? drop.obj : drop.fall_obj;
|
||||||
|
if (obj) {
|
||||||
|
if (drop.min_count) hit_count = 0;
|
||||||
|
var count = drop.count || 1;
|
||||||
|
if (drop.min && drop.max) {
|
||||||
|
count = Math.floor(Math.random() * (drop.max - drop.min + 1)) + drop.min;
|
||||||
|
}
|
||||||
|
if (count > 0) {
|
||||||
|
if (obj instanceof Array) obj = obj.random();
|
||||||
|
items.push(OBJ.CREATE(obj, count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
38
os/login.js
Normal file
38
os/login.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
var crypto = require('crypto');
|
||||||
|
module.exports = {
|
||||||
|
max_idcount: 10,
|
||||||
|
max_ipcount: 12,
|
||||||
|
login_error: function (user, msg, close = true) {
|
||||||
|
user.send(`{type:'loginerror',msg:'${msg}'}`);
|
||||||
|
if (close)
|
||||||
|
user.socket?.end();
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
encryptUser: function (key, session) {
|
||||||
|
if (!key || !session) return null;
|
||||||
|
if (key.length >= 16) key = key.substr(0, 16);
|
||||||
|
try {
|
||||||
|
key = Buffer.from(key, 'utf8');
|
||||||
|
var decipher = crypto.createDecipheriv('aes-128-cbc', key, __CONFIG.DESIV);
|
||||||
|
var txt = decipher.update(session, 'base64', 'utf8');
|
||||||
|
txt += decipher.final('utf8');
|
||||||
|
var str = txt.split("%");
|
||||||
|
if (str.length !== 5) return null;
|
||||||
|
var id = parseInt(str[0]);
|
||||||
|
if (id > 0)
|
||||||
|
return {
|
||||||
|
id: id,
|
||||||
|
name: str[1],
|
||||||
|
pwd: str[2],
|
||||||
|
loginTime: parseInt(str[3]),
|
||||||
|
level: parseInt(str[4])
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
340
os/net-ws.js
Normal file
340
os/net-ws.js
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
"use strict";
|
||||||
|
var crypto = require('crypto');
|
||||||
|
var fs = require("fs");
|
||||||
|
function wsServer(options) {
|
||||||
|
var evt = ["Close", "Error", "SocketIn", "Connect", "Receive",
|
||||||
|
"ClientError", "ClientClose", "ClientTimeout"];
|
||||||
|
for (var i = 0; i < evt.length; i++) {
|
||||||
|
this["on" + evt[i]] = function () {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.options = options.SSL ? {
|
||||||
|
key: fs.readFileSync(options.KEY),
|
||||||
|
cert: fs.readFileSync(options.CERT),
|
||||||
|
requestCert: true,
|
||||||
|
rejectUnauthorized: true,
|
||||||
|
passphrase: options.PASSWORD,
|
||||||
|
ca: [fs.readFileSync(options.CERT)]
|
||||||
|
} : null;
|
||||||
|
this.ssl = options.SSL;
|
||||||
|
}
|
||||||
|
wsServer.prototype.listen = function (port, func) {
|
||||||
|
|
||||||
|
var net = require(this.ssl ? 'tls' : 'net');
|
||||||
|
var tcpserver = net.createServer(this.options, onClientConnect.bind(this));
|
||||||
|
tcpserver.listen(port, func);
|
||||||
|
tcpserver.on('close', this.onClose.bind(this));
|
||||||
|
tcpserver.on('error', this.onError.bind(this));
|
||||||
|
this.tcpServer = tcpserver;
|
||||||
|
}
|
||||||
|
wsServer.prototype.send = function (msg, socket) {
|
||||||
|
socket.send(msg);
|
||||||
|
}
|
||||||
|
wsServer.prototype.close = function () {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.tcpServer.close(resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = wsServer;
|
||||||
|
function onClientConnect(socket) {
|
||||||
|
|
||||||
|
socket.send = function (msg) {
|
||||||
|
if (msg)
|
||||||
|
this.protocol.sendData(msg, socket);
|
||||||
|
}
|
||||||
|
socket.on('close', this.onClientClose.bind(this, socket));
|
||||||
|
socket.on('error', this.onClientError.bind(this, socket));
|
||||||
|
var $this = this;
|
||||||
|
socket.setTimeout(3000);
|
||||||
|
socket.on('timeout', this.onClientTimeout.bind(this, socket));
|
||||||
|
$this.onSocketIn(socket);
|
||||||
|
socket.on('data', function (data) {
|
||||||
|
if (socket.protocol) {
|
||||||
|
socket.protocol.readData(data, socket, $this);
|
||||||
|
} else {
|
||||||
|
var header = readHeader(data);
|
||||||
|
socket.requestHeader = header;
|
||||||
|
if (header["Sec-WebSocket-Key"]) {
|
||||||
|
socket.protocol = protocols.var1;
|
||||||
|
} else if (header["Sec-WebSocket-Key1"]) {
|
||||||
|
socket.protocol = protocols.var2;
|
||||||
|
} else {
|
||||||
|
socket.protocol = protocols.tcp;
|
||||||
|
socket.protocol.readData(data, socket, $this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
socket.protocol.handShake(header, socket, data);
|
||||||
|
$this.onConnect(socket);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var protocols = {
|
||||||
|
var1: {
|
||||||
|
handShake: function (header, socket) {
|
||||||
|
var hasher = crypto.createHash("sha1");
|
||||||
|
hasher.update(header["Sec-WebSocket-Key"] + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
||||||
|
var hashmsg = hasher.digest().toString('base64');
|
||||||
|
var origin = header.Origin;
|
||||||
|
var protocol = header['sec-websocket-protocol'];
|
||||||
|
if (protocol)
|
||||||
|
protocol.split(/, */);
|
||||||
|
var respon = ["HTTP/1.1 101 Switching Protocols",
|
||||||
|
"Connection: Upgrade",
|
||||||
|
"Upgrade: WebSocket",
|
||||||
|
`Sec-WebSocket-Accept:${hashmsg}`,
|
||||||
|
`Sec-WebSocket-Origin:${origin}`];
|
||||||
|
if (protocol) respon.push(`Sec-WebSocket-Protocol: ${protocol}`);
|
||||||
|
//var extens = header["Sec-Websocket-Extensions"];
|
||||||
|
//if (extens) {
|
||||||
|
// respon.push(`Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits`);
|
||||||
|
//}
|
||||||
|
respon.push("\r\n");
|
||||||
|
socket.write(respon.join("\r\n"));
|
||||||
|
},
|
||||||
|
readData: function (data, socket, server) {
|
||||||
|
var start = 0;
|
||||||
|
while (start < data.length) {
|
||||||
|
var iseof = (data[start] >> 7) > 0;
|
||||||
|
var frameType = data[start++] & 0xF;
|
||||||
|
var hasMask = (data[start] >> 7) > 0;
|
||||||
|
var length = (data[start++] & 0x7F);
|
||||||
|
if (length == 126) {
|
||||||
|
length = data.readUInt16BE(start);
|
||||||
|
start = start + 2;
|
||||||
|
}
|
||||||
|
else if (length == 127) {
|
||||||
|
length = data.readUInt32BE(start);
|
||||||
|
start = start + 4;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var markIndex = start;
|
||||||
|
start = start + 4;
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
data[start] = data[start] ^ data[markIndex + (i % 4)];
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
switch (frameType) {
|
||||||
|
case FrameTypes.Close:
|
||||||
|
socket.end();
|
||||||
|
// server.onClientClose(socket);
|
||||||
|
break;
|
||||||
|
case FrameTypes.Binary:
|
||||||
|
break;
|
||||||
|
case FrameTypes.Ping:
|
||||||
|
break;
|
||||||
|
case FrameTypes.Pong:
|
||||||
|
break;
|
||||||
|
case FrameTypes.Text:
|
||||||
|
var msg = data.toString("utf8", markIndex + 4, markIndex + 4 + length);
|
||||||
|
server.onReceive(msg, socket);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sendData: function (text, socket) {
|
||||||
|
var textBuffer = Buffer.from(text);
|
||||||
|
var length = textBuffer.length;
|
||||||
|
var data;
|
||||||
|
if (length < 126) {
|
||||||
|
data = Buffer.alloc(length + 2);
|
||||||
|
data[0] = 129;
|
||||||
|
data.writeUInt8(length, 1);
|
||||||
|
textBuffer.copy(data, 2);
|
||||||
|
}
|
||||||
|
else if (length >= 126 && length < 65536) {
|
||||||
|
data = Buffer.alloc(length + 4);
|
||||||
|
data[0] = 129;
|
||||||
|
data.writeUInt8(126, 1);
|
||||||
|
data.writeUInt16BE(length, 2);
|
||||||
|
textBuffer.copy(data, 4);
|
||||||
|
} else {
|
||||||
|
data = Buffer.alloc(length + 10);
|
||||||
|
data[0] = 0x81;
|
||||||
|
data[1] = 127;
|
||||||
|
data.writeUInt32BE(0, 2);
|
||||||
|
data.writeUInt32BE(length, 6);
|
||||||
|
textBuffer.copy(data, 10);
|
||||||
|
}
|
||||||
|
socket.write(data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
var2: {
|
||||||
|
handShake: function (header, socket, buffer) {
|
||||||
|
var key1 = header["Sec-WebSocket-Key1"];
|
||||||
|
var key2 = header["Sec-WebSocket-Key2"];
|
||||||
|
|
||||||
|
var origin = header["Origin"];
|
||||||
|
|
||||||
|
var n1 = getNumber(key1);
|
||||||
|
n1 = parseInt(n1);
|
||||||
|
n1 = n1 / getSpace(key1);
|
||||||
|
|
||||||
|
var n2 = getNumber(key2);
|
||||||
|
n2 = parseInt(n2);
|
||||||
|
n2 = n2 / getSpace(key2);
|
||||||
|
|
||||||
|
var buf = Buffer.alloc(16);
|
||||||
|
|
||||||
|
buf.writeIntBE(n1, 0, 4, true);
|
||||||
|
|
||||||
|
buf.writeIntBE(n2, 4, 4, true);
|
||||||
|
|
||||||
|
buffer.copy(buf, 8, buffer.length - 8, buffer.length);
|
||||||
|
|
||||||
|
var hasherbs = crypto.createHash("md5");
|
||||||
|
hasherbs = hasherbs.update(buf);
|
||||||
|
hasherbs = hasherbs.digest();
|
||||||
|
|
||||||
|
var host = "ws://" + header["Host"] + "/";
|
||||||
|
var headers = [
|
||||||
|
"HTTP/1.1 101 WebSocket Protocol Handshake",
|
||||||
|
"Upgrade: WebSocket",
|
||||||
|
"Connection: Upgrade",
|
||||||
|
"Sec-WebSocket-Origin:" + origin,
|
||||||
|
"Sec-WebSocket-Location:" + host
|
||||||
|
, "\r\n"
|
||||||
|
];
|
||||||
|
socket.write(headers.join("\r\n"));
|
||||||
|
socket.write(hasherbs);
|
||||||
|
},
|
||||||
|
buffer: null
|
||||||
|
,
|
||||||
|
readData: function (data, socket, server) {
|
||||||
|
var start = 0;
|
||||||
|
while (start < data.length) {
|
||||||
|
if (data[start] != 0) {
|
||||||
|
break;//error
|
||||||
|
}
|
||||||
|
var end = start + 1;
|
||||||
|
while (data[end] != 255 && end < data.length) {
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
var msg = data.toString("utf8", start + 1, end);
|
||||||
|
server.onReceive(msg, socket);
|
||||||
|
start = end + 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sendData: function (text, socket) {
|
||||||
|
var textBuffer = Buffer.from(text, "utf-8");
|
||||||
|
var length = textBuffer.length;
|
||||||
|
|
||||||
|
var wrappedBytes = Buffer.alloc(length + 2);
|
||||||
|
wrappedBytes[0] = 0;
|
||||||
|
textBuffer.copy(wrappedBytes, 1);
|
||||||
|
wrappedBytes[wrappedBytes.length - 1] = 255;
|
||||||
|
socket.write(wrappedBytes);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tcp: {
|
||||||
|
|
||||||
|
readData: function (data, socket, server) {
|
||||||
|
|
||||||
|
var start = 0;
|
||||||
|
if (socket.unread_data) {
|
||||||
|
data = Buffer.concat([socket.unread_data, data], socket.unread_data.length + data.length);
|
||||||
|
socket.unread_data = null;
|
||||||
|
}
|
||||||
|
let isread = false;
|
||||||
|
while (start < data.length) {
|
||||||
|
let length = data.readUInt8(start);
|
||||||
|
let index = start + 1;
|
||||||
|
if (length === 254) {
|
||||||
|
//不够读长度咋办
|
||||||
|
length = data.readUInt16BE(index);
|
||||||
|
index += 2;
|
||||||
|
} else if (length === 255) {
|
||||||
|
length = data.readUInt32BE(index);
|
||||||
|
index += 4;
|
||||||
|
}
|
||||||
|
if (data.length < index + length) {
|
||||||
|
socket.unread_data = isread ? data.slice(start) : data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let msg = data.toString("utf8", index, index + length);
|
||||||
|
|
||||||
|
isread = true;
|
||||||
|
|
||||||
|
server.onTcpReceive(msg, socket);
|
||||||
|
|
||||||
|
start = index + length;
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sendData: function (text, socket) {
|
||||||
|
var textBuffer = Buffer.from(text);
|
||||||
|
var length = textBuffer.length;
|
||||||
|
var data;
|
||||||
|
if (length < 254) {
|
||||||
|
data = Buffer.alloc(length + 1);
|
||||||
|
data.writeUInt8(length);
|
||||||
|
textBuffer.copy(data, 1);
|
||||||
|
}
|
||||||
|
else if (length >= 254 && length < 65536) {
|
||||||
|
data = Buffer.alloc(length + 3);
|
||||||
|
data.writeUInt8(254);
|
||||||
|
data.writeUInt16BE(length, 1);
|
||||||
|
textBuffer.copy(data, 3);
|
||||||
|
} else {
|
||||||
|
data = Buffer.alloc(length + 5);
|
||||||
|
data.writeUInt8(255);
|
||||||
|
data.writeUInt32BE(length, 1);
|
||||||
|
textBuffer.copy(data, 5);
|
||||||
|
}
|
||||||
|
socket.write(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function getNumber(str) {
|
||||||
|
return str.replace(/\D/g, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
function getSpace(str) {
|
||||||
|
return str.replace(/\S/g, "").length;
|
||||||
|
}
|
||||||
|
function readHeader(data) {
|
||||||
|
var header = {}, key, flag = 0;
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
switch (data[i]) {
|
||||||
|
case 0x0D://\r
|
||||||
|
key && (header[key] = data.toString("utf8", flag, i));
|
||||||
|
break;
|
||||||
|
case 0x0A://\n
|
||||||
|
key = null;
|
||||||
|
flag = i + 1;
|
||||||
|
break;
|
||||||
|
case 0x3A://:
|
||||||
|
if (!key) {
|
||||||
|
key = data.toString("utf8", flag, i);
|
||||||
|
data[i + 1] == 0x20 ? flag = i + 2 : flag = i + 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flag < data.length) {
|
||||||
|
header.CONTENT = data.toString("utf8", flag);
|
||||||
|
|
||||||
|
}
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
var FrameTypes =
|
||||||
|
{
|
||||||
|
Continuation: 0,
|
||||||
|
Text: 1,
|
||||||
|
Binary: 2,
|
||||||
|
Close: 8,
|
||||||
|
Ping: 9,
|
||||||
|
Pong: 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
//%x0 代表一个继续帧
|
||||||
|
//%x1 代表一个文本帧
|
||||||
|
//%x2 代表一个二进制帧
|
||||||
|
//%x3-7 保留用于未来的非控制帧
|
||||||
|
//%x8 代表连接关闭
|
||||||
|
//%x9 代表ping
|
||||||
|
//%xA 代表pong
|
||||||
|
//%xB-F 保留用于未来的控制帧
|
||||||
135
os/room/area.js
Normal file
135
os/room/area.js
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
AREA = function () {
|
||||||
|
this.rooms = [];
|
||||||
|
this.map = [];
|
||||||
|
this.name = "";
|
||||||
|
this.is_area = false;
|
||||||
|
this.first = null;
|
||||||
|
this.is_show = true;
|
||||||
|
this.is_copy = false;
|
||||||
|
this.expend = 10;
|
||||||
|
this.is_multi = false;
|
||||||
|
this.index = 0;
|
||||||
|
this.exp = 1000;
|
||||||
|
this.pot = 1000;
|
||||||
|
}
|
||||||
|
AREA.inherits(BASE);
|
||||||
|
AREA.prototype.create = function (path) {
|
||||||
|
WORLD.AREAS.push(this);
|
||||||
|
if (this.family) {
|
||||||
|
FAMILIES[this.family].area = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AREA.Get = function (id) {
|
||||||
|
if (!WORLD.AREAS) return;
|
||||||
|
for (var i = 0; i < WORLD.AREAS.length; i++) {
|
||||||
|
if (WORLD.AREAS[i].id == id) return WORLD.AREAS[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AREA.prototype.on_leaved = function (me) {
|
||||||
|
//离开后
|
||||||
|
}
|
||||||
|
AREA.prototype.on_leave = function (me) {
|
||||||
|
//进入前
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
AREA.prototype.on_enterd = function (me) {
|
||||||
|
//进入后
|
||||||
|
}
|
||||||
|
AREA.prototype.on_enter = function (me) {
|
||||||
|
//进入前
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
AREA.prototype.find_area = function (path) {
|
||||||
|
}
|
||||||
|
AREA.prototype.is_record = function (diff) {
|
||||||
|
return this["record_" + diff];
|
||||||
|
}
|
||||||
|
AREA.prototype.query_exp = function () {
|
||||||
|
var lv = this.fb_index || 0;
|
||||||
|
return 1000 + lv * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
AREA.prototype.query_desc = function () {
|
||||||
|
return this.desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
AREA.prototype.clear = function () {
|
||||||
|
this.json = null;
|
||||||
|
this.drop_list = null;
|
||||||
|
this.diff_drop_list = null;
|
||||||
|
}
|
||||||
|
AREA.prototype.query_drops = function (isdiff) {
|
||||||
|
if (isdiff) return this.query_diff_drops();
|
||||||
|
if (this.drop_list) return this.drop_list;
|
||||||
|
var items = [];
|
||||||
|
for (var i = 0; i < this.rooms.length; i++) {
|
||||||
|
var rm = this.rooms[i];
|
||||||
|
for (var j = 0; j < rm.items.length; j++) {
|
||||||
|
if (rm.items[j].drop_list) {
|
||||||
|
items.push(rm.items[j].drop_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.query_npc_drops(this.drop_npcs0, items);
|
||||||
|
this.drop_list = items;
|
||||||
|
return this.drop_list;
|
||||||
|
}
|
||||||
|
AREA.prototype.query_npc_drops = function (npcs, items) {
|
||||||
|
if (!npcs || !npcs.length) return;
|
||||||
|
for (var i = 0; i < npcs.length; i++) {
|
||||||
|
var npc = NPC.GET(npcs[i]);
|
||||||
|
if (!npc || !npc.drop_list) continue;
|
||||||
|
items.push(npc.drop_list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AREA.prototype.query_diff_drops = function (isdiff) {
|
||||||
|
if (this.diff_drop_list) return this.diff_drop_list;
|
||||||
|
var items = [];
|
||||||
|
for (var i = 0; i < this.rooms.length; i++) {
|
||||||
|
var rm = this.rooms[i];
|
||||||
|
for (var j = 0; j < rm.items.length; j++) {
|
||||||
|
if (rm.items[j].drop_list) {
|
||||||
|
items.push(rm.items[j].drop_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.query_npc_drops(this.drop_npcs1, items);
|
||||||
|
this.diff_drop_list = items;
|
||||||
|
return this.diff_drop_list;
|
||||||
|
}
|
||||||
|
AREA.prototype.update = function (path) {
|
||||||
|
WORLD.COMMANDS["jh"].map_json = null;
|
||||||
|
for (var i = 0; i < WORLD.AREAS.length; i++) {
|
||||||
|
if (WORLD.AREAS[i].path == path) {
|
||||||
|
var old_area = WORLD.AREAS[i];
|
||||||
|
WORLD.AREAS[i] = this;
|
||||||
|
this.rooms = old_area.rooms;
|
||||||
|
if (this.rooms) {
|
||||||
|
for (let room of this.rooms) {
|
||||||
|
room.parent = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
old_area.rooms = null;
|
||||||
|
if (this.family) {
|
||||||
|
FAMILIES[this.family].area = this;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.create(path);
|
||||||
|
}
|
||||||
|
AREA.Get = function (id) {
|
||||||
|
for (var i = 0; i < WORLD.AREAS.length; i++) {
|
||||||
|
if (WORLD.AREAS[i].id == id) {
|
||||||
|
return WORLD.AREAS[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AREA.prototype.query_drop_items = function () {
|
||||||
|
return this.drop_items;
|
||||||
|
}
|
||||||
|
AREA.prototype.query_actions = function () {
|
||||||
|
return this.actions;
|
||||||
|
}
|
||||||
|
|
||||||
5
os/room/fam_area.js
Normal file
5
os/room/fam_area.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
FAMILY_AREA = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
FAMILY_AREA.inherits(AREA);
|
||||||
|
|
||||||
692
os/room/room.js
Normal file
692
os/room/room.js
Normal file
@@ -0,0 +1,692 @@
|
|||||||
|
|
||||||
|
ROOM = function () {
|
||||||
|
this.name = "房间";
|
||||||
|
this.desc = "";
|
||||||
|
this.items = [];
|
||||||
|
this.parent = null;
|
||||||
|
}
|
||||||
|
ROOM.inherits(ITEM);
|
||||||
|
ROOM.prototype.max_item_count = 50;
|
||||||
|
|
||||||
|
ROOM.prototype.do_leave = function (obj, dir, leave_msg) {
|
||||||
|
if (this.on_leave && this.on_leave(obj, dir) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.item_changed(obj, false, leave_msg, dir) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ROOM.prototype.do_enter = function (obj, isshow, in_msg) {
|
||||||
|
this.on_before_enter && this.on_before_enter(obj);
|
||||||
|
if (obj.is_player) {
|
||||||
|
obj.send(this.to_json());
|
||||||
|
this.send_exits(obj);
|
||||||
|
}
|
||||||
|
this.item_changed(obj, true, in_msg);
|
||||||
|
this.on_enter && this.on_enter(obj);
|
||||||
|
}
|
||||||
|
ROOM.prototype.item_changed = function (obj, isin, changed_msg, dir) {
|
||||||
|
if (!obj) return;
|
||||||
|
var msg;
|
||||||
|
var obj_index = -1, isshow = !obj.query_temp('hidden');
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
var item = this.items[i];
|
||||||
|
if (item == obj) {
|
||||||
|
obj_index = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (item.is_player && isshow) {
|
||||||
|
if (!msg) msg = this.item_json(obj, isin);
|
||||||
|
item.send(msg);
|
||||||
|
|
||||||
|
if (changed_msg && item != obj && !item.query_setting("off_move")) {
|
||||||
|
item.send(changed_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (obj.hp) {
|
||||||
|
if (isin && item.on_enter) {
|
||||||
|
item.on_enter(obj);
|
||||||
|
} else if (!isin && item.on_leave) {
|
||||||
|
if (item.on_leave(obj, dir) == false) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isin) {
|
||||||
|
obj.environment = this;
|
||||||
|
if (obj_index == -1) {
|
||||||
|
this.items.push(obj);
|
||||||
|
if (obj.is_player) obj.send(this.items_to_json());
|
||||||
|
|
||||||
|
} else if (obj.is_player) {
|
||||||
|
if (!msg) msg = this.item_json(obj, isin);
|
||||||
|
obj.send(msg);
|
||||||
|
}
|
||||||
|
} else if (obj_index > -1) {
|
||||||
|
this.items.splice(obj_index, 1);
|
||||||
|
obj.environment = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.item_json = function (item, isin) {
|
||||||
|
if (!item) return "";
|
||||||
|
var str = [];
|
||||||
|
if (isin) {
|
||||||
|
str.push('{"type":"itemadd",');
|
||||||
|
str.push("id:\"");
|
||||||
|
str.push(item.id);
|
||||||
|
str.push("\",name:\"");
|
||||||
|
str.push(item.long_name());
|
||||||
|
str.push("\"");
|
||||||
|
if (item.is_player) {
|
||||||
|
str.push(",p:1");
|
||||||
|
}
|
||||||
|
if (item.appdend_status) {
|
||||||
|
str.push(",mp:");
|
||||||
|
str.push(item.mp);
|
||||||
|
str.push(",hp:");
|
||||||
|
str.push(item.hp);
|
||||||
|
str.push(",max_mp:");
|
||||||
|
str.push(item.max_mp);
|
||||||
|
str.push(",max_hp:");
|
||||||
|
str.push(item.max_hp);
|
||||||
|
item.appdend_status(str);
|
||||||
|
}
|
||||||
|
str.push("}");
|
||||||
|
} else {
|
||||||
|
str.push('{"type":"itemremove",id:"');
|
||||||
|
str.push(item.id);
|
||||||
|
str.push('"}');
|
||||||
|
}
|
||||||
|
return str.join("");
|
||||||
|
}
|
||||||
|
ROOM.prototype.items_to_json = function () {
|
||||||
|
var str = ['{"type":"items","items":['];
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
var item = this.items[i];
|
||||||
|
if (!item.is_hidden()) {
|
||||||
|
str.push("{id:\"");
|
||||||
|
str.push(item.id);
|
||||||
|
str.push("\",name:\"");
|
||||||
|
str.push(item.long_name());
|
||||||
|
str.push("\"");
|
||||||
|
if (item.is_player) {
|
||||||
|
str.push(",p:1");
|
||||||
|
} else {
|
||||||
|
if (!item.item_types) {
|
||||||
|
item.item_types = item.hp > 0 ? `,m:${(item.on_checkskill || item.on_master) ? 1 : 0},l:${item.sell_list ? 1 : 0},f:${item.master ? 1 : 0}` : ",o:1";
|
||||||
|
}
|
||||||
|
str.push(item.item_types);
|
||||||
|
}
|
||||||
|
if (item.appdend_status) {
|
||||||
|
str.push(",mp:");
|
||||||
|
str.push(item.mp);
|
||||||
|
str.push(",hp:");
|
||||||
|
str.push(item.hp);
|
||||||
|
str.push(",max_mp:");
|
||||||
|
str.push(item.max_mp);
|
||||||
|
str.push(",max_hp:");
|
||||||
|
str.push(item.max_hp);
|
||||||
|
|
||||||
|
item.appdend_status(str);
|
||||||
|
}
|
||||||
|
str.push("},");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str.push("0]}");
|
||||||
|
return str.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
ROOM.prototype.set_npc = function () {
|
||||||
|
|
||||||
|
for (var i = 0; i < arguments.length; i++) {
|
||||||
|
var name = arguments[i];
|
||||||
|
if (typeof name == "string") name = [name, 1];
|
||||||
|
var obj_path = name[0];
|
||||||
|
if (!obj_path) continue;
|
||||||
|
for (var j = 0; j < name[1]; j++) {
|
||||||
|
var obj = NPC.CLONE(obj_path);
|
||||||
|
if (obj) {
|
||||||
|
this.items.push(obj);
|
||||||
|
obj.environment = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.set_obj = function (names) {
|
||||||
|
|
||||||
|
for (var i = 0; i < arguments.length; i++) {
|
||||||
|
var name = arguments[i];
|
||||||
|
if (typeof name == "string") name = [name, 1];
|
||||||
|
var obj = OBJ.CREATE(name[0], name[1]);
|
||||||
|
if (obj) {
|
||||||
|
this.items.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ROOM.prototype.set_item = function (id, name, desc, commands) {
|
||||||
|
this.hidden_items = this.hidden_items || [];
|
||||||
|
|
||||||
|
if (commands && typeof commands[0] == "string") {
|
||||||
|
commands = [commands];
|
||||||
|
}
|
||||||
|
let hidden_item = {
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
desc: desc,
|
||||||
|
commands: commands,
|
||||||
|
query_desc: on_look_hidden_item,
|
||||||
|
environment: this
|
||||||
|
};
|
||||||
|
|
||||||
|
this.hidden_items.push(hidden_item);
|
||||||
|
if (commands) {
|
||||||
|
for (var j = 0; j < commands.length; j++) {
|
||||||
|
this.add_action(commands[j][0], null, commands[j][2]);
|
||||||
|
}
|
||||||
|
//添加隐藏物品的命令到房间的actions,命令不能重复
|
||||||
|
}
|
||||||
|
return hidden_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
function on_look_hidden_item(player) {
|
||||||
|
if (this.json) return this.json;
|
||||||
|
var json = {};
|
||||||
|
json.type = "item";
|
||||||
|
json.desc = this.desc;
|
||||||
|
if (this.commands) {
|
||||||
|
json.commands = [];
|
||||||
|
for (var i = 0; i < this.commands.length; i++) {
|
||||||
|
if (this.commands[i][1])
|
||||||
|
json.commands.push({
|
||||||
|
cmd: this.commands[i][0] + " " + this.id,
|
||||||
|
name: this.commands[i][1]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.json = JSON.stringify(json)
|
||||||
|
return this.json;
|
||||||
|
}
|
||||||
|
ROOM.prototype.find_obj = function (oid) {
|
||||||
|
var items = this.items;
|
||||||
|
if (!items) return;
|
||||||
|
var item = this.find_obj_byid(items, oid);
|
||||||
|
if (item) return item;
|
||||||
|
if (!this.hidden_items) return;
|
||||||
|
for (var i = 0; i < this.hidden_items.length; i++) {
|
||||||
|
if (this.hidden_items[i].id == oid) return this.hidden_items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.find_by_path = function (path) {
|
||||||
|
var items = this.items;
|
||||||
|
if (!items) return;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].path == path) {
|
||||||
|
return items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.is_here = function (path) {
|
||||||
|
var items = this.items;
|
||||||
|
if (!items) return;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].path == path) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.notify = function (msg) {
|
||||||
|
if (!this.items) return;
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].is_player) {
|
||||||
|
this.items[i].notify(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.query_exits = function (dir) {
|
||||||
|
if (this.exits && this.exits[dir]) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ROOM.prototype.add_exit = function (dir, rm) {
|
||||||
|
this.exits = this.exits || {};
|
||||||
|
this.exits[dir] = rm;
|
||||||
|
this.exits_changed();
|
||||||
|
}
|
||||||
|
ROOM.prototype.remove_exit = function (dir) {
|
||||||
|
this.exits = this.exits || {};
|
||||||
|
delete this.exits[dir];
|
||||||
|
this.exits_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
ROOM.prototype.exits_changed = function () {
|
||||||
|
this.room_exits_json = null;
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].is_player)
|
||||||
|
this.send_exits(this.items[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.send_exits = function (player) {
|
||||||
|
player.send(this.exitsto_roomjson());
|
||||||
|
}
|
||||||
|
ROOM.prototype.exitsto_roomjson = function () {
|
||||||
|
if (this.room_exits_json) return this.room_exits_json;
|
||||||
|
var obj = {};
|
||||||
|
obj.type = "exits";
|
||||||
|
obj.items = {};
|
||||||
|
if (this.exits) {
|
||||||
|
for (var dir in this.exits) {
|
||||||
|
if (!this.exits[dir]) continue;
|
||||||
|
var rm = ROOM.Get(this.exits[dir]);
|
||||||
|
if (!rm) continue;
|
||||||
|
obj.items[dir] = rm.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.room_exits_json = JSON.stringify(obj);
|
||||||
|
return this.room_exits_json;
|
||||||
|
}
|
||||||
|
ROOM.prototype.to_json = function () {
|
||||||
|
if (this.json) return this.json;
|
||||||
|
var obj = {};
|
||||||
|
obj.type = "room";
|
||||||
|
obj.path = this.path;
|
||||||
|
obj.name = this.long_name;
|
||||||
|
obj.desc = this.desc;
|
||||||
|
obj.commands = [];
|
||||||
|
if (this.actions) {
|
||||||
|
for (var cmd in this.actions) {
|
||||||
|
var name = this.actions[cmd].name;
|
||||||
|
if (name)
|
||||||
|
obj.commands.push({
|
||||||
|
cmd: cmd,
|
||||||
|
name: name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.is_copy_room && !this.parent.not_fb) {
|
||||||
|
obj.commands.push({
|
||||||
|
cmd: "cr",
|
||||||
|
name: "完成副本"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.json = JSON.stringify(obj);
|
||||||
|
return this.json;
|
||||||
|
|
||||||
|
}
|
||||||
|
ROOM.prototype.query_commands = function () {
|
||||||
|
if (this.commands_json) return this.commands_json;
|
||||||
|
var json = {};
|
||||||
|
json.type = "command";
|
||||||
|
|
||||||
|
json.commands = [];
|
||||||
|
if (this.actions) {
|
||||||
|
for (var cmd in this.actions) {
|
||||||
|
json.commands.push({
|
||||||
|
name: this.actions[cmd].name,
|
||||||
|
cmd: cmd
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.commands_json = JSON.stringify(json)
|
||||||
|
return this.commands_json;
|
||||||
|
}
|
||||||
|
ROOM.prototype.refresh = function (obj) {
|
||||||
|
this.json = null;
|
||||||
|
this.commands_json = null;
|
||||||
|
this.room_exits_json = null;
|
||||||
|
var rmname = this.parent.name + "-" + this.name;
|
||||||
|
if (this.parent.not_fb || !this.parent.is_copy) {
|
||||||
|
this.long_name = rmname;
|
||||||
|
} else {
|
||||||
|
this.long_name = rmname + "(副本区域)";
|
||||||
|
}
|
||||||
|
if (obj) {
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].is_player) {
|
||||||
|
this.items[i].send(this.to_json());
|
||||||
|
this.send_exits(this.items[i]);
|
||||||
|
this.items[i].send(this.items_to_json());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// this.send_exits(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ROOM.prototype.get_path = function () {
|
||||||
|
if (this.path) return this.path;
|
||||||
|
var str = this.name;
|
||||||
|
var area = this.area;
|
||||||
|
while (area) {
|
||||||
|
str = area.name + "-" + str;
|
||||||
|
area = area.parent;
|
||||||
|
}
|
||||||
|
this.path = str;
|
||||||
|
return this.path;
|
||||||
|
}
|
||||||
|
ROOM.prototype.query_recover_room = function () {
|
||||||
|
var area = this.parent;
|
||||||
|
while (area) {
|
||||||
|
if (area.recover_room) {
|
||||||
|
return area.recover_room;
|
||||||
|
}
|
||||||
|
area = area.parent;
|
||||||
|
}
|
||||||
|
return "yz/wumiao";
|
||||||
|
}
|
||||||
|
ROOM.prototype.create = function (file) {
|
||||||
|
var base_room = WORLD.ROOMS[file];
|
||||||
|
|
||||||
|
if (base_room) {
|
||||||
|
this.parent = base_room.parent;
|
||||||
|
if (this.parent.is_copy) {
|
||||||
|
//副本区域
|
||||||
|
if (this.parent.not_fb) {
|
||||||
|
this.long_name = base_room.long_name;
|
||||||
|
} else {
|
||||||
|
this.long_name = base_room.long_name + "(副本区域)";
|
||||||
|
}
|
||||||
|
this.create_time = Date.now();
|
||||||
|
this.is_copy_room = true;
|
||||||
|
} else {
|
||||||
|
//投影区域 房间人满了后
|
||||||
|
this.is_shadow = true;
|
||||||
|
this.long_name = base_room.long_name;//+ "(" + UTIL.to_c(base_room.shadow_rooms.length + 1) + "号)";
|
||||||
|
|
||||||
|
}
|
||||||
|
WORLD.RUN_ROOMS.push(this);
|
||||||
|
} else {
|
||||||
|
this.initBaseRoom(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.on_create && this.on_create();
|
||||||
|
}
|
||||||
|
ROOM.prototype.initBaseRoom = function (file) {
|
||||||
|
WORLD.ROOMS[file] = this;
|
||||||
|
|
||||||
|
var area = getAreaByPath(this.path);
|
||||||
|
|
||||||
|
this.parent = area;
|
||||||
|
if (!area || !area.is_copy) {
|
||||||
|
//如果是副本,第一个被创建的不放在运行的房间
|
||||||
|
WORLD.RUN_ROOMS.push(this);
|
||||||
|
}
|
||||||
|
if (area) {
|
||||||
|
if (!area.rooms) area.rooms = [];
|
||||||
|
for (var i = 0; i < area.rooms.length; i++) {
|
||||||
|
if (area.rooms[i].path == this.path) {
|
||||||
|
area.rooms.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
area.rooms.push(this);
|
||||||
|
this.long_name = area.name + "-" + this.name;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
this.long_name = this.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.update = function (file) {
|
||||||
|
this.on_create && this.on_create();
|
||||||
|
var oldroom = WORLD.ROOMS[file];
|
||||||
|
this.initBaseRoom(file);
|
||||||
|
if (!oldroom) return;
|
||||||
|
if (oldroom.copy_rooms) {
|
||||||
|
this.copy_rooms = {};
|
||||||
|
for (var key in oldroom.copy_rooms) {
|
||||||
|
var rm = oldroom.copy_rooms[key];
|
||||||
|
var newRm = BASE.CREATE(__PATH.MAP, this.path);
|
||||||
|
this.replaceRoom(rm, newRm);
|
||||||
|
newRm.owner = key;
|
||||||
|
this.copy_rooms[key] = newRm;
|
||||||
|
}
|
||||||
|
oldroom.copy_rooms = null;
|
||||||
|
} else {
|
||||||
|
if (ROOM.public_rooms) {
|
||||||
|
for (var i = 0; i < ROOM.public_rooms.length; i++) {
|
||||||
|
if (ROOM.public_rooms[i] == oldroom) {
|
||||||
|
ROOM.public_rooms[i] = this;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.replaceRoom = function (oldroom, newRoom) {
|
||||||
|
var items = oldroom.items;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].is_player || items[i].master) {
|
||||||
|
newRoom.items.push(items[i]);
|
||||||
|
items[i].environment = newRoom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oldroom.destroy();
|
||||||
|
}
|
||||||
|
ROOM.prototype.destroy = function () {
|
||||||
|
this.items.length = 0;
|
||||||
|
this.owner = null;
|
||||||
|
}
|
||||||
|
ROOM.prototype.heart_beat = function (dt) {
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
if (!this.items[i].is_player)
|
||||||
|
this.items[i].heart_beat(dt);
|
||||||
|
}
|
||||||
|
this.on_heart_beat && this.on_heart_beat(dt);
|
||||||
|
}
|
||||||
|
ROOM.prototype.is_copy = function () {
|
||||||
|
if (!this.parent) return false;
|
||||||
|
return this.parent.is_copy;
|
||||||
|
}
|
||||||
|
ROOM.prototype.is_fb = function () {
|
||||||
|
if (!this.parent) return false;
|
||||||
|
return this.parent.is_copy && !this.parent.not_fb;
|
||||||
|
}
|
||||||
|
ROOM.prototype.is_enter = function () {
|
||||||
|
if (!this.parent) return false;
|
||||||
|
return this.parent.first == this.path;
|
||||||
|
}
|
||||||
|
ROOM.prototype.query_fb_first = function (id) {
|
||||||
|
//查询副本入口
|
||||||
|
if (!this.parent || !this.parent.is_copy || !this.parent.rooms) return;
|
||||||
|
return this.parent.rooms[0].query_copy(id);
|
||||||
|
}
|
||||||
|
ROOM.prototype.query_copy = function (id) {
|
||||||
|
|
||||||
|
if (!this.copy_rooms) this.copy_rooms = {};
|
||||||
|
return this.copy_rooms[id];
|
||||||
|
}
|
||||||
|
ROOM.prototype.query_copy2 = function (user) {
|
||||||
|
var id = this.parent.query_owner(user);
|
||||||
|
if (!id) return this;
|
||||||
|
return this.query_copy(id);
|
||||||
|
}
|
||||||
|
ROOM.prototype.clear_copy = function (me) {
|
||||||
|
//清除复制的副本,四个位置,换地图,完成副本,复活,彻底掉线
|
||||||
|
//但是又不能清除不是自己的副本,比如帮派
|
||||||
|
if (!this.owner) return;
|
||||||
|
let id = this.parent.query_owner(me);
|
||||||
|
if (id !== this.owner) return;//只能清除自己或队伍创建的副本
|
||||||
|
var name = "fb/";
|
||||||
|
for (var key in me.temp) {
|
||||||
|
if (key.startsWith(name)) {
|
||||||
|
me.temp[key] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (me.team) {
|
||||||
|
for (var i = 0; i < me.team.length; i++) {
|
||||||
|
let tm = me.team[i];
|
||||||
|
if (tm !== me && tm.environment && tm.environment.parent === this.parent
|
||||||
|
&& tm.environment.owner == this.owner) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.clear_by_area(this.parent, this.owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
ROOM.prototype.create_copy2 = function (me, diff_type) {
|
||||||
|
|
||||||
|
var id = this.parent.query_owner(me);
|
||||||
|
if (!id) return;
|
||||||
|
return this.create_copy(id, diff_type || 0);
|
||||||
|
}
|
||||||
|
ROOM.prototype.create_copy = function (id, diff_type) {
|
||||||
|
//第一次创建副本,从入口开始创建,把所在区域所有房间都创建一遍
|
||||||
|
if (!this.parent) return;
|
||||||
|
// var rooms = [];
|
||||||
|
this.create_by_area(this.parent, id, diff_type);
|
||||||
|
//this.add_fbroom(rooms);
|
||||||
|
return this.query_copy(id);
|
||||||
|
}
|
||||||
|
ROOM.prototype.create_by_area = function (area, id, diff_type) {
|
||||||
|
if (area.rooms) {
|
||||||
|
for (var i = 0; i < area.rooms.length; i++) {
|
||||||
|
var base_room = area.rooms[i];
|
||||||
|
var copy_room = BASE.CREATE(__PATH.MAP, base_room.path);
|
||||||
|
if (!copy_room) continue;
|
||||||
|
copy_room.set_difficulty(diff_type);
|
||||||
|
if (!base_room.copy_rooms) base_room.copy_rooms = {};
|
||||||
|
base_room.copy_rooms[id] = copy_room;
|
||||||
|
copy_room.owner = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (area.areas) {
|
||||||
|
for (var i = 0; i < area.areas.length; i++) {
|
||||||
|
this.create_by_area(area.areas[i], id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.create_shadow = function () {
|
||||||
|
//当房间人满了后 进入房间就另外创建一个房间投影,这种类型的房间最好不要放NPC,物品
|
||||||
|
//这种房间创建了不销毁,重复使用
|
||||||
|
if (this.is_copy_room || this.no_shadow) return;
|
||||||
|
|
||||||
|
if (!this.shadow_rooms) this.shadow_rooms = [];
|
||||||
|
for (var i = 0; i < this.shadow_rooms.length; i++) {
|
||||||
|
if (!this.shadow_rooms[i].is_full()) {
|
||||||
|
return this.shadow_rooms[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var shadow = BASE.CREATE(__PATH.MAP, this.path);
|
||||||
|
if (shadow) {
|
||||||
|
this.shadow_rooms.push(shadow);
|
||||||
|
}
|
||||||
|
return shadow;
|
||||||
|
}
|
||||||
|
ROOM.prototype.clear_by_area = function (area, id) {
|
||||||
|
if (area.rooms) {
|
||||||
|
for (var i = 0; i < area.rooms.length; i++) {
|
||||||
|
var base_room = area.rooms[i];
|
||||||
|
if (base_room.copy_rooms) {
|
||||||
|
var rm = base_room.copy_rooms[id];
|
||||||
|
if (rm) {
|
||||||
|
WORLD.RUN_ROOMS.remove(rm);
|
||||||
|
rm.destroy();
|
||||||
|
delete base_room.copy_rooms[id];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (area.areas) {
|
||||||
|
for (var i = 0; i < area.areas.length; i++) {
|
||||||
|
this.clear_by_area(area.areas[i], id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAreaByPath(path) {
|
||||||
|
var index = path.lastIndexOf("/");
|
||||||
|
path = path.substr(0, index + 1);
|
||||||
|
var items = WORLD.AREAS;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].room_path == path) return items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.Get = function (path) {
|
||||||
|
var rm = WORLD.ROOMS[path];
|
||||||
|
|
||||||
|
if (!rm) return console.log("room %s is not exist", path);
|
||||||
|
// if (!rm) throw new Error(path + "is not exist");
|
||||||
|
return rm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//房间存储数据,存在当前用户或队伍的房间区域的第一个房间里面,在副本销毁时候会释放
|
||||||
|
ROOM.prototype.query_temp = function (me, name, def) {
|
||||||
|
var first = this.query_fb_first(me.query_teamid());
|
||||||
|
if (!first) return;
|
||||||
|
if (!first.temp) return;
|
||||||
|
var item = first.temp[name];
|
||||||
|
if (item && item.e) {
|
||||||
|
if (Date.now() <= item.e) {
|
||||||
|
return item.v;
|
||||||
|
}
|
||||||
|
first.temp[name] = null;
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
return item || def;
|
||||||
|
}
|
||||||
|
ROOM.prototype.set_temp = function (me, name, value, time) {
|
||||||
|
var first = this.query_fb_first(me.query_teamid());
|
||||||
|
if (!first) return;
|
||||||
|
if (!first.temp) first.temp = {};
|
||||||
|
if (time) {
|
||||||
|
first.temp[name] = {
|
||||||
|
v: value,
|
||||||
|
e: Date.now() + time
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
first.temp[name] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.add_temp = function (me, name, value, time) {
|
||||||
|
let val = this.query_temp(me, name, 0) + value;
|
||||||
|
this.set_temp(me, name, val, time);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
ROOM.RANDOM = function () {
|
||||||
|
if (!this.public_rooms) {
|
||||||
|
this.public_rooms = [];
|
||||||
|
for (var i = 0; i < WORLD.AREAS.length; i++) {
|
||||||
|
if (WORLD.AREAS[i].is_area && !WORLD.AREAS[i].is_public) {
|
||||||
|
var rms = WORLD.AREAS[i].rooms;
|
||||||
|
|
||||||
|
for (var j = 0; j < rms.length; j++) {
|
||||||
|
if (rms[j].max_item_count > 1)
|
||||||
|
this.public_rooms.push(rms[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.public_rooms.random();
|
||||||
|
}
|
||||||
|
ROOM.prototype.set_difficulty = function (type) {
|
||||||
|
this.on_set_difficulty && this.on_set_difficulty(type);
|
||||||
|
}
|
||||||
|
ROOM.prototype.send = function (msg) {
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].is_player) {
|
||||||
|
this.items[i].send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.find_me = function () {
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].is_player) {
|
||||||
|
return this.items[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ROOM.prototype.query = function (id) {
|
||||||
|
let room = ROOM.Get(id);
|
||||||
|
if (!room) return null;
|
||||||
|
if (this.owner) {
|
||||||
|
return room.query_copy(this.owner);
|
||||||
|
}
|
||||||
|
return room;
|
||||||
|
}
|
||||||
94
os/skill/family.js
Normal file
94
os/skill/family.js
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
FAMILY = function () {
|
||||||
|
this.titles = [];
|
||||||
|
this.npcs = [];
|
||||||
|
this.battle_family = null;
|
||||||
|
//this.scores = new Map();
|
||||||
|
this.battle_score = 0;
|
||||||
|
this.battle_gift = 0;
|
||||||
|
this.can_battle = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FAMILY.inherits(BASE);
|
||||||
|
FAMILIES = {};
|
||||||
|
FAMILY.prototype.set_titles = function () {
|
||||||
|
for (var i = 0; i < arguments.length; i++) {
|
||||||
|
this.titles.push(arguments[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FAMILY.prototype.create = function (path) {
|
||||||
|
FAMILIES[this.id] = this;
|
||||||
|
|
||||||
|
}
|
||||||
|
FAMILY.prototype.update = function (path) {
|
||||||
|
FAMILIES[this.id] = this;
|
||||||
|
}
|
||||||
|
FAMILY.prototype.query_title = function (level) {
|
||||||
|
return this.titles[level];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FAMILY.prototype.query_temp = CHARACTER.prototype.query_temp;
|
||||||
|
FAMILY.prototype.set_temp = CHARACTER.prototype.set_temp;
|
||||||
|
FAMILY.prototype.remove_temp = CHARACTER.prototype.remove_temp;
|
||||||
|
FAMILY.prototype.add_temp = CHARACTER.prototype.add_temp;
|
||||||
|
|
||||||
|
FAMILY.prototype.send = function (str) {
|
||||||
|
for (var i = 0; i < WORLD.USERS.length; i++) {
|
||||||
|
if (WORLD.USERS[i].family == this) {
|
||||||
|
WORLD.USERS[i].send(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FAMILY.prototype.is_battle = function (fam) {
|
||||||
|
return this.battle_family == fam.id;
|
||||||
|
}
|
||||||
|
FAMILY.prototype.add_score = function (me, sc) {
|
||||||
|
this.battle_score += sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CHARACTER.prototype.send_fam = function (str) {
|
||||||
|
this.family.send(str);
|
||||||
|
}
|
||||||
|
FAMILY.prototype.create_name = function () {
|
||||||
|
return UTIL.random_name(this.gender);
|
||||||
|
}
|
||||||
|
FAMILY.prototype.query_skill = function (grade) {
|
||||||
|
if (!this.skill_levels) {
|
||||||
|
this.skill_levels = [];
|
||||||
|
for (var i = 0; i < this.skills.length; i++) {
|
||||||
|
if (!this.skill_levels[this.skills[i].grade]) {
|
||||||
|
this.skill_levels[this.skills[i].grade] = [];
|
||||||
|
}
|
||||||
|
this.skill_levels[this.skills[i].grade].push(this.skills[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (grade >= this.skill_levels.length) grade = this.skill_levels.length - 1;
|
||||||
|
return this.skill_levels[grade].random();
|
||||||
|
}
|
||||||
|
FAMILY.prototype.query_skills = function (grade) {
|
||||||
|
if (!this.skill_levels) {
|
||||||
|
this.skill_levels = [];
|
||||||
|
for (var i = 0; i < this.skills.length; i++) {
|
||||||
|
if (!this.skill_levels[this.skills[i].grade]) {
|
||||||
|
this.skill_levels[this.skills[i].grade] = [];
|
||||||
|
}
|
||||||
|
this.skill_levels[this.skills[i].grade].push(this.skills[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (grade >= this.skill_levels.length) grade = this.skill_levels.length - 1;
|
||||||
|
return this.skill_levels[grade];
|
||||||
|
}
|
||||||
|
FAMILY.prototype.add_gongji = function (me, count) {
|
||||||
|
if (!count) return;
|
||||||
|
me.add_temp("gongji", count);
|
||||||
|
if (count < 0) return;
|
||||||
|
if (!this.tops) this.tops = {};
|
||||||
|
var old = this.tops[me.id];
|
||||||
|
if (!old) this.tops[me.id] = { name: me.name, score: count };
|
||||||
|
else {
|
||||||
|
old.score += count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
648
os/skill/skill.js
Normal file
648
os/skill/skill.js
Normal file
@@ -0,0 +1,648 @@
|
|||||||
|
/*global SKILL_TYPES SKILL BASE PROPERTIES WORLD FAMILIES*/
|
||||||
|
|
||||||
|
require("../util/util.js");
|
||||||
|
SKILL = function () {
|
||||||
|
this.id = "";
|
||||||
|
this.name = "";
|
||||||
|
this.type = SKILL_TYPES.SKILL;
|
||||||
|
this.grade = 1;
|
||||||
|
this.score = 0;
|
||||||
|
}
|
||||||
|
SKILL.inherits(BASE);
|
||||||
|
SKILL.prototype.query_attack_action = function (me, target) {
|
||||||
|
if (this.attack_actions)
|
||||||
|
return this.attack_actions.random();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
SKILL.prototype.query_dodge_action = function () {
|
||||||
|
if (!this.dodge_actions) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return this.dodge_actions.random();
|
||||||
|
}
|
||||||
|
SKILL.prototype.query_parry_action = function (me, target, w2) {
|
||||||
|
var w1 = me.query_weapon();
|
||||||
|
w2 = w2 || target.query_weapon();
|
||||||
|
var act;
|
||||||
|
if (w1 && w2) {
|
||||||
|
act = this.weapon_vs_weapon_actions || this.parry_actions;
|
||||||
|
} else if (w1) {
|
||||||
|
act = this.weapon_vs_unarmed_actions || this.parry_actions;
|
||||||
|
} else if (w2) {
|
||||||
|
act = this.unarmed_vs_weapon_actions || this.parry_actions;
|
||||||
|
} else {
|
||||||
|
act = this.parry_actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!act) {
|
||||||
|
act = this.parry_actions = SKILL.get("parry").parry_actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (act) {
|
||||||
|
return act.random();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SKILL.prototype.level_exp = function (lv, me) {
|
||||||
|
var grd = this.query_grade(me);
|
||||||
|
return (lv + 1) * (grd + 1) * 5;
|
||||||
|
}
|
||||||
|
SKILL.prototype.query_needexp = function (level, me) {
|
||||||
|
if (level > 100) {
|
||||||
|
var grd = this.query_grade(me);
|
||||||
|
var exp = (100 + level) * (level - 100) / 2;
|
||||||
|
return exp * (grd + 1) * 5;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SKILL.prototype.set_default = function (type) {
|
||||||
|
WORLD.DEFAULT_SKILLS[type] = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SKILL.prototype.release_prop = function (me, lv) {
|
||||||
|
if (!lv) return;
|
||||||
|
var prop = this.query_prop(lv, me);
|
||||||
|
if (prop) {
|
||||||
|
me.change_prop(prop, false);
|
||||||
|
}
|
||||||
|
prop = this.query_enable_prop(lv, me);
|
||||||
|
if (prop) {
|
||||||
|
for (var item in prop) {
|
||||||
|
if (me.is_enable_skill(this.id, item)) {
|
||||||
|
me.change_prop(prop[item], false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prop = this.query_addin_prop(me, lv);
|
||||||
|
if (prop) {
|
||||||
|
if (this.is_enable(me)) {
|
||||||
|
me.change_prop(prop, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SKILL.prototype.attach_prop = function (me, lv) {
|
||||||
|
if (!lv) return;
|
||||||
|
var prop = this.query_prop(lv, me);
|
||||||
|
if (prop) {
|
||||||
|
me.change_prop(prop, true);
|
||||||
|
}
|
||||||
|
prop = this.query_enable_prop(lv, me);
|
||||||
|
if (prop) {
|
||||||
|
for (var item in prop) {
|
||||||
|
if (me.is_enable_skill(this.id, item)) {
|
||||||
|
me.change_prop(prop[item], true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prop = this.query_addin_prop(me, lv);
|
||||||
|
if (prop) {
|
||||||
|
if (this.is_enable(me)) {
|
||||||
|
me.change_prop(prop, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SKILL.prototype.query_enable_prop = function (lv) {
|
||||||
|
|
||||||
|
}
|
||||||
|
SKILL.prototype.query_prop = function (lv) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SKILL.prototype.query_grade = function (me) {
|
||||||
|
var sk = me.skills[this.id];
|
||||||
|
var lv = this.grade;
|
||||||
|
if (sk) {
|
||||||
|
if (sk.addin)
|
||||||
|
lv += sk.addin.length;
|
||||||
|
if (sk.ref)
|
||||||
|
lv += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lv;
|
||||||
|
}
|
||||||
|
SKILL.prototype.query_color_name = function (me) {
|
||||||
|
|
||||||
|
var desc = level_color[this.query_grade(me)];
|
||||||
|
return "<" + desc + ">" + this.name + "</" + desc + ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
SKILL.prototype.query_addin_prop = function (me, lv) {
|
||||||
|
var sk = me.skills[this.id];
|
||||||
|
if (sk.addin && sk.addin.length) {
|
||||||
|
var prop = {};
|
||||||
|
var grd = this.grade + sk.addin.length;
|
||||||
|
for (let slot of sk.addin) {
|
||||||
|
let item = this.query_slot(slot);
|
||||||
|
if (!item) continue;
|
||||||
|
if (item.prop) {
|
||||||
|
prop[item.prop] = (prop[item.prop] ?? 0)
|
||||||
|
+ parseInt(item.value(lv, grd));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
SKILL.prototype.is_enable = function (me) {
|
||||||
|
if (this.type !== SKILL_TYPES.SKILL) return true;
|
||||||
|
var skill = me.skills[this.id];
|
||||||
|
for (var i = 0; i < this.can_enables.length; i++) {
|
||||||
|
if (skill[this.can_enables[i]]) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SKILL.prototype.is_enable2 = function (me, baseskill) {
|
||||||
|
var skill = me.skills[this.id];
|
||||||
|
|
||||||
|
return skill ? skill[baseskill] : false;
|
||||||
|
}
|
||||||
|
//激活技能,附加装备的部分属性
|
||||||
|
SKILL.prototype.enable = function (me, type) {
|
||||||
|
if (!this.can_enables || !this.can_enables.contain(type)) return false;
|
||||||
|
if (this.on_enable && this.on_enable(me, type) === false) return false;
|
||||||
|
var lv = me.query_skill(this.id);
|
||||||
|
var prop = this.query_enable_prop(lv);
|
||||||
|
if (prop) {
|
||||||
|
var enable_prop = prop[type];
|
||||||
|
if (enable_prop) {
|
||||||
|
me.change_prop(enable_prop, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//附加进阶属性
|
||||||
|
prop = this.query_addin_prop(me, lv);
|
||||||
|
if (prop) {
|
||||||
|
if (!this.is_enable(me)) {
|
||||||
|
me.change_prop(prop, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//取消激活技能,解除装备的部分属性
|
||||||
|
SKILL.prototype.disenable = function (me, type) {
|
||||||
|
this.on_disenable && this.on_disenable(me, type);
|
||||||
|
var lv = me.query_skill(this.id);
|
||||||
|
var prop = this.query_enable_prop(lv);
|
||||||
|
if (prop) {
|
||||||
|
var enable_prop = prop[type];
|
||||||
|
if (enable_prop) {
|
||||||
|
me.change_prop(enable_prop, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//附加进阶属性
|
||||||
|
prop = this.query_addin_prop(me, lv);
|
||||||
|
if (prop) {
|
||||||
|
if (!this.is_enable(me)) {
|
||||||
|
|
||||||
|
me.change_prop(prop, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
SKILL.prototype.do_learn = function (me) {
|
||||||
|
if (this.on_learn && this.on_learn(me) === false) return false;
|
||||||
|
if (this.learn_condition) {
|
||||||
|
for (var key in this.learn_condition) {
|
||||||
|
var val = this.learn_condition[key];
|
||||||
|
switch (key) {
|
||||||
|
case "skill":
|
||||||
|
for (var sk in val) {
|
||||||
|
if (me.query_skill(sk, 0) < val[sk] && me.query_skill(sk + "2", 0) < val[sk]) {
|
||||||
|
var sk_base = SKILL.get(sk);
|
||||||
|
|
||||||
|
return me.notify_fail("你的" + sk_base.color_name + "等级不够" + val[sk] + ",无法学习" + this.color_name + "。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "str1":
|
||||||
|
case "con1":
|
||||||
|
case "dex1":
|
||||||
|
case "int1":
|
||||||
|
if (me.is_player && me[key.replace("1", "")] < val) {
|
||||||
|
return me.notify_fail("你的" + PROPERTIES[key] + "不够" + val + ",无法学习" + this.color_name + "。");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "str":
|
||||||
|
case "con":
|
||||||
|
case "dex":
|
||||||
|
case "int":
|
||||||
|
if (me[key] + me.query_prop(key) < val) {
|
||||||
|
return me.notify_fail("你的" + PROPERTIES[key] + "不够" + val + ",无法学习" + this.color_name + "。");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "gender":
|
||||||
|
if (me.gender !== val) return me.notify_fail("你不是" + (val === 1 ? "男性" : val === 2 ? "女性" : "无性") + ",无法学习" + this.color_name + "。");
|
||||||
|
break;
|
||||||
|
case "desc":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
var me_val = me[key] || 0;
|
||||||
|
me_val = me_val + me.query_prop(key);
|
||||||
|
if (!me_val || me_val < val) {
|
||||||
|
|
||||||
|
return me.notify_fail("你的" + PROPERTIES[key] + "不够" + val + ",无法学习" + this.color_name + "。");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.type === SKILL_TYPES.SKILL && this.can_enables) {
|
||||||
|
for (var i = 0; i < this.can_enables.length; i++) {
|
||||||
|
if (!me.query_skill(this.can_enables[i], 0)) {
|
||||||
|
var skill = SKILL.get(this.can_enables[i]);
|
||||||
|
return me.notify_fail("你还不会" + skill.color_name + ",无法学习" + this.color_name + "。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SKILL.prototype.condition_tostring = function (me) {
|
||||||
|
if (this.learn_condition_string) return this.learn_condition_string;
|
||||||
|
var str = [];
|
||||||
|
if (this.learn_condition) {
|
||||||
|
for (var key in this.learn_condition) {
|
||||||
|
var val = this.learn_condition[key];
|
||||||
|
switch (key) {
|
||||||
|
case "skill":
|
||||||
|
for (var sk in val) {
|
||||||
|
var sk_base = SKILL.get(sk);
|
||||||
|
str.push(sk_base.name + ":" + val[sk] + "级");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "desc":
|
||||||
|
str.push(val);
|
||||||
|
break;
|
||||||
|
case "gender":
|
||||||
|
str.push("性别:" + (val === 1 ? "男" : (val === 2 ? "女" : "无性")));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str.push(PROPERTIES[key] + ":" + val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.learn_condition_string = str.join("\n");
|
||||||
|
return this.learn_condition_string;
|
||||||
|
}
|
||||||
|
SKILL.prototype.item_to_json = function (str, skill_item, me) {
|
||||||
|
str.push('{"id":"');
|
||||||
|
str.push(this.id);
|
||||||
|
|
||||||
|
str.push('","name":"');
|
||||||
|
str.push(this.query_color_name(me));
|
||||||
|
str.push('",grade:', this.query_grade(me));
|
||||||
|
str.push(',"level":');
|
||||||
|
str.push(me.query_skill(this.id));
|
||||||
|
str.push(',"exp":');
|
||||||
|
skill_item.exp = skill_item.exp || 0;
|
||||||
|
str.push(parseInt(skill_item.exp * 100 / this.level_exp(skill_item.level, me)));
|
||||||
|
if (this.can_enables) {
|
||||||
|
str.push(',"can_enables":[');
|
||||||
|
for (var i = 0; i < this.can_enables.length; i++) {
|
||||||
|
if (i > 0) str.push(",");
|
||||||
|
str.push('"');
|
||||||
|
str.push(this.can_enables[i]);
|
||||||
|
str.push('"');
|
||||||
|
}
|
||||||
|
str.push(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skill_item.enable_skill) {
|
||||||
|
str.push(',"enable_skill":"');
|
||||||
|
str.push(skill_item.enable_skill);
|
||||||
|
str.push('"');
|
||||||
|
}
|
||||||
|
str.push('}');
|
||||||
|
}
|
||||||
|
SKILL.prototype.add_exp = function (me, exp) {
|
||||||
|
var skill = me.skills[this.id];
|
||||||
|
if (!skill) {
|
||||||
|
skill = {
|
||||||
|
// id: this.id,
|
||||||
|
level: 0,
|
||||||
|
exp: 0
|
||||||
|
};
|
||||||
|
var str = ['{type:"dialog",dialog:"skills",item:'];
|
||||||
|
this.item_to_json(str, skill, me);
|
||||||
|
str.push("}");
|
||||||
|
me.notify(str.join(""));
|
||||||
|
me.skills[this.id] = skill;
|
||||||
|
if (this.type === SKILL_TYPES.BASE) {
|
||||||
|
me.init_skill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var need_exp = this.level_exp(skill.level, me);
|
||||||
|
skill.exp += exp;
|
||||||
|
if (skill.exp >= need_exp) {
|
||||||
|
this.release_prop(me, me.query_skill(this.id));
|
||||||
|
var sum_score = 0;
|
||||||
|
var color_name = this.query_color_name(me);
|
||||||
|
var one_score = this.query_one_score(me);
|
||||||
|
while (skill.exp >= need_exp) {
|
||||||
|
skill.exp -= need_exp;
|
||||||
|
need_exp = this.level_exp(skill.level, me);
|
||||||
|
me.notify("<hiy>你的" + color_name + "等级提升了!</hiy>");
|
||||||
|
skill.level++;
|
||||||
|
if (skill.level > 100)
|
||||||
|
sum_score += one_score;
|
||||||
|
}
|
||||||
|
var lv = me.query_skill(this.id);
|
||||||
|
this.attach_prop(me, lv);
|
||||||
|
me.notify('{type:"dialog",dialog:"skills",id:"' + this.id + '",level:' + lv + ',exp:' + parseInt(skill.exp * 100 / need_exp) + '}');
|
||||||
|
me.recount();
|
||||||
|
me.add_score(sum_score);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
me.notify('{type:"dialog",dialog:"skills",id:"' + this.id + '",exp:' + parseInt(skill.exp * 100 / need_exp) + '}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SKILL.prototype.query_score = function (lv, me) {
|
||||||
|
if (lv <= 100) return 0;
|
||||||
|
return (lv - 100) * this.query_one_score(me);
|
||||||
|
}
|
||||||
|
|
||||||
|
SKILL.prototype.query_one_score = function (me) {
|
||||||
|
var sc = 0;
|
||||||
|
if (this.type === SKILL_TYPES.SKILL) {
|
||||||
|
sc = this.query_grade(me);
|
||||||
|
} else if (this.type === SKILL_TYPES.BASE) {
|
||||||
|
sc = 1;
|
||||||
|
}
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
SKILL.prototype.grade_up = function (me, target_skill) {
|
||||||
|
var skill = me.skills[this.id];
|
||||||
|
if (!skill || !(skill.level >= 1000)) return false;
|
||||||
|
|
||||||
|
if (me.remove_skill(this.id) === false) return false;
|
||||||
|
me.notify('{type:"dialog",dialog:"skills",remove:"' + this.id + '"}');
|
||||||
|
var pot = this.query_needexp(skill.level, me);
|
||||||
|
var lv = pot * 2 / 5 / (target_skill.grade + 1);
|
||||||
|
skill = {
|
||||||
|
level: parseInt(Math.pow(lv, 0.5)),
|
||||||
|
exp: 0
|
||||||
|
};
|
||||||
|
me.skills[target_skill.id] = skill;
|
||||||
|
var str = ['{type:"dialog",dialog:"skills",item:'];
|
||||||
|
target_skill.item_to_json(str, skill, me);
|
||||||
|
str.push("}");
|
||||||
|
me.notify(str.join(""));
|
||||||
|
me.add_score(target_skill.query_score(skill.level, me));
|
||||||
|
target_skill.attach_prop(me, skill.level);
|
||||||
|
me.recount();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
SKILL.prototype.get_pfm = function (name) {
|
||||||
|
if (this.pfm) {
|
||||||
|
return this.pfm[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SKILL.prototype.set_pfm = function (name, obj) {
|
||||||
|
if (!this.pfm) {
|
||||||
|
this.pfm = {};
|
||||||
|
}
|
||||||
|
this.pfm[name] = obj;
|
||||||
|
}
|
||||||
|
var level_color = ["wht", "hig", "hic", "hiy", "hiz", "hio", "ord"];
|
||||||
|
var level_desc = ["基本技能", "普通技能", "高级技能", "稀有武技", "绝世武功", "绝世神功", "无上神武"];
|
||||||
|
|
||||||
|
SKILL.prototype.create = function (fname) {
|
||||||
|
if (WORLD.SKILLS[this.id]) {
|
||||||
|
console.log("%s [%s] is repeated ", this.id, fname);
|
||||||
|
}
|
||||||
|
this.update(fname);
|
||||||
|
}
|
||||||
|
SKILL.prototype.store = function () {
|
||||||
|
if (this.type === SKILL_TYPES.KNOWLEDGE
|
||||||
|
|| this.type === SKILL_TYPES.BASE
|
||||||
|
) return;
|
||||||
|
for (var i = 0; i < this.can_enables.length; i++) {
|
||||||
|
if (!SKILL[this.can_enables[i]]) SKILL[this.can_enables[i]] = new Array(7);
|
||||||
|
if (!SKILL[this.can_enables[i]][this.grade]) SKILL[this.can_enables[i]][this.grade] = [];
|
||||||
|
SKILL[this.can_enables[i]][this.grade].push(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SKILL.prototype.update = function (fname) {
|
||||||
|
WORLD.SKILLS[this.id] = this;
|
||||||
|
var fam = this.family || FAMILIES.NONE;
|
||||||
|
if (!fam.skills2) fam.skills2 = [];
|
||||||
|
if (!fam.skills) fam.skills = [];
|
||||||
|
if (!fam.skills3) fam.skills3 = [];
|
||||||
|
if (!fam.skills4) fam.skills4 = [];
|
||||||
|
var isAddIn = false;
|
||||||
|
var ary = this.source_skill ?
|
||||||
|
(this.is_ultimate ? fam.skills3 : fam.skills2) :
|
||||||
|
(this.is_ultimate ? fam.skills4 : fam.skills);
|
||||||
|
if (this.type === SKILL_TYPES.KNOWLEDGE || this.is_hidden) {
|
||||||
|
if (!fam.skills0) fam.skills0 = [];
|
||||||
|
ary = fam.skills0;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < ary.length; i++) {
|
||||||
|
if (ary[i].id === this.id) {
|
||||||
|
ary[i] = this;
|
||||||
|
isAddIn = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ary[i].grade > this.grade) {
|
||||||
|
ary.splice(i, 0, this);
|
||||||
|
isAddIn = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isAddIn) {
|
||||||
|
ary.push(this);
|
||||||
|
}
|
||||||
|
this.store();
|
||||||
|
|
||||||
|
var desc = level_color[this.grade];
|
||||||
|
this.color_name = "<" + desc + ">" + this.name + "</" + desc + ">";
|
||||||
|
if (this.pfm) {
|
||||||
|
for (var key in this.pfm) {
|
||||||
|
var pfm = this.pfm[key];
|
||||||
|
if (pfm.enable_skill === 'sword' || pfm.enable_skill === 'blade' || pfm.enable_skill === 'whip'
|
||||||
|
|| pfm.enable_skill === 'staff' || pfm.enable_skill === 'club') {
|
||||||
|
pfm.is_weapon = true;
|
||||||
|
}
|
||||||
|
pfm.id = this.id + "/" + key;
|
||||||
|
pfm.pid = key;
|
||||||
|
pfm.__proto__ = PERFORM.prototype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SKILL.get = function (id) {
|
||||||
|
return WORLD.SKILLS[id];
|
||||||
|
}
|
||||||
|
SKILL.prototype.query_desc = function (me, lv) {
|
||||||
|
var str = [];
|
||||||
|
var grd = this.query_grade(me);
|
||||||
|
var cc = level_color[grd];
|
||||||
|
str.push("<" + cc + ">" + this.name + "</" + cc + ">");
|
||||||
|
str.push("\n");
|
||||||
|
if (this.family) {
|
||||||
|
str.push(this.family.name);
|
||||||
|
} else {
|
||||||
|
str.push("公共");
|
||||||
|
}
|
||||||
|
str.push(level_desc[grd]);
|
||||||
|
str.push("\n");
|
||||||
|
|
||||||
|
str.push(this.desc);
|
||||||
|
str.push("\n");
|
||||||
|
var prop = this.query_prop(lv, me);
|
||||||
|
if (prop) {
|
||||||
|
str.push("<");
|
||||||
|
str.push(cc);
|
||||||
|
str.push(">");
|
||||||
|
str.push(UTIL.prop_toString(prop));
|
||||||
|
str.push("</");
|
||||||
|
str.push(cc);
|
||||||
|
str.push(">\n");
|
||||||
|
}
|
||||||
|
prop = this.query_enable_prop(lv, me);
|
||||||
|
var isEnable = this.type === SKILL_TYPES.KNOWLEDGE;
|
||||||
|
if (prop) {
|
||||||
|
for (var item in prop) {
|
||||||
|
var is_enable = me.is_enable_skill(this.id, item);
|
||||||
|
if (is_enable) isEnable = true;
|
||||||
|
str.push("<");
|
||||||
|
str.push(is_enable ? cc : "blk");
|
||||||
|
str.push(">当装备为");
|
||||||
|
str.push(SKILL.get(item).name);
|
||||||
|
str.push("时:\n");
|
||||||
|
str.push(UTIL.prop_toString(prop[item]));
|
||||||
|
str.push("</");
|
||||||
|
str.push(is_enable ? cc : "blk");
|
||||||
|
str.push(">\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var sk = me.skills[this.id];
|
||||||
|
if (sk && sk.addin && sk.addin.length) {
|
||||||
|
str.push("\n<");
|
||||||
|
str.push(isEnable ? cc : "blk");
|
||||||
|
str.push(">");
|
||||||
|
|
||||||
|
let grd = this.grade + sk.addin.length;
|
||||||
|
for (let slot of sk.addin) {
|
||||||
|
let item = this.query_slot(slot);
|
||||||
|
if (item) {
|
||||||
|
str.push("◆");
|
||||||
|
if (item.name) {
|
||||||
|
str.push(item.name);
|
||||||
|
str.push(" ");
|
||||||
|
}
|
||||||
|
str.push(item.format(parseInt(item.value(lv, grd))));
|
||||||
|
str.push("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str.push("</");
|
||||||
|
str.push(isEnable ? cc : "blk");
|
||||||
|
str.push(">\n");
|
||||||
|
}
|
||||||
|
if (this.pfm) {
|
||||||
|
str.push("<line>绝招</line>\n");
|
||||||
|
for (let item in this.pfm) {
|
||||||
|
var p_item = this.pfm[item];
|
||||||
|
if (!p_item.name) continue;
|
||||||
|
this.query_pfm_desc(me, p_item, str, lv);
|
||||||
|
str.push("\n\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sk && sk.ref) {
|
||||||
|
var refs = sk.ref.split("/");
|
||||||
|
var sp_skill = SKILL.get(refs[0]);
|
||||||
|
if (sp_skill) {
|
||||||
|
var pfm = sp_skill.get_pfm(refs[1]);
|
||||||
|
if (pfm) {
|
||||||
|
this.query_pfm_desc(me, pfm, str, lv, sp_skill.name);
|
||||||
|
str.push("\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return str.join("");
|
||||||
|
}
|
||||||
|
SKILL.prototype.query_slot = function (index) {
|
||||||
|
if (index < 500) {
|
||||||
|
return SKILL.PROPERTIES[index];
|
||||||
|
} else {
|
||||||
|
return this.slots ? this.slots[index - 500] : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SKILL.REF_CD = 2;
|
||||||
|
SKILL.SLOTS = {};
|
||||||
|
SKILL.prototype.query_pfm_desc = function (me, p_item, str, lv, pname) {
|
||||||
|
var canuse = !p_item.check || p_item.check(me, lv) === true;
|
||||||
|
var color = canuse ? "hic" : "red";
|
||||||
|
if (pname) color = 'hir';
|
||||||
|
str.push("<");
|
||||||
|
str.push(color);
|
||||||
|
str.push(">【");
|
||||||
|
if (pname) {
|
||||||
|
str.push(pname);
|
||||||
|
str.push("•");
|
||||||
|
|
||||||
|
}
|
||||||
|
str.push(p_item.name);
|
||||||
|
str.push("】");
|
||||||
|
if (!canuse) {
|
||||||
|
str.push(p_item.use_condition || "");
|
||||||
|
}
|
||||||
|
str.push("</");
|
||||||
|
str.push(color);
|
||||||
|
str.push(">");
|
||||||
|
if (pname) lv = parseInt(lv / 2);
|
||||||
|
str.push("\n内力消耗:");
|
||||||
|
str.push(p_item.query_mp(me, lv));
|
||||||
|
str.push("\t出招时间:");
|
||||||
|
str.push(p_item.query_releasetime(me, lv) / 1000);
|
||||||
|
str.push("秒\t冷却时间:");
|
||||||
|
str.push(p_item.query_distime(me, lv, pname) / 1000);
|
||||||
|
str.push("秒\n");
|
||||||
|
str.push(p_item.query_desc(me, lv));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PERFORM = function () {
|
||||||
|
this.name = "";
|
||||||
|
}
|
||||||
|
PERFORM.inherits(BASE);
|
||||||
|
|
||||||
|
PERFORM.prototype.query_name = function (me) {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
PERFORM.prototype.change_distime = function (me, id, add_time) {
|
||||||
|
if (me.is_player) {
|
||||||
|
var dis_time = me.temp["pfm/" + id];
|
||||||
|
if (dis_time) {
|
||||||
|
if (add_time)
|
||||||
|
dis_time.e += add_time;
|
||||||
|
else {
|
||||||
|
add_time = -dis_time.time;
|
||||||
|
dis_time.e = 1;
|
||||||
|
}
|
||||||
|
me.notify('{type:"changepfm",id:"' + id + '",time:' + add_time + '}');
|
||||||
|
}
|
||||||
|
} else if (me.auto_skills) {
|
||||||
|
for (var i = 0; i < me.auto_skills.length; i++) {
|
||||||
|
var item = me.auto_skills[i];
|
||||||
|
if (item.pfm === this) {
|
||||||
|
if (add_time)
|
||||||
|
item.release_time += add_time;
|
||||||
|
else
|
||||||
|
item.release_time = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
49
os/task/events.js
Normal file
49
os/task/events.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
EVENTS = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
EVENTS.inherits(BASE);
|
||||||
|
|
||||||
|
EVENTS.add = function (item) {
|
||||||
|
if (!item || !item.id) return;
|
||||||
|
Object.setPrototypeOf(item, EVENT_BASE);
|
||||||
|
const items = WORLD.USER_EVENTS;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].id == item.id) {
|
||||||
|
items[i] = item;
|
||||||
|
return this.notify(item, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
items.push(item);
|
||||||
|
this.notify(item, 0);
|
||||||
|
}
|
||||||
|
EVENTS.ACTIONS = ['add', 'update', 'finish'];
|
||||||
|
EVENTS.notify = function (item, act) {
|
||||||
|
let users = WORLD.USERS;
|
||||||
|
let msg = `{type: "dialog", dialog: "events",${EVENTS.ACTIONS[act]}:1}`;
|
||||||
|
for (let user of users) {
|
||||||
|
if (!user.socket) continue;
|
||||||
|
if (item.check && !item.check(user))
|
||||||
|
continue;
|
||||||
|
user.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EVENTS.remove = function (id) {
|
||||||
|
if (!id) return;
|
||||||
|
const items = WORLD.USER_EVENTS;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].id == id) {
|
||||||
|
EVENTS.notify(items[i], 2);
|
||||||
|
return items.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const EVENT_BASE = {
|
||||||
|
query_desc: function () {
|
||||||
|
return this.desc;
|
||||||
|
},
|
||||||
|
query_grade: function () {
|
||||||
|
return this.grade;
|
||||||
|
}
|
||||||
|
};
|
||||||
48
os/task/playertask.js
Normal file
48
os/task/playertask.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
require("../util/util");
|
||||||
|
USERTASK = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
USERTASK.inherits(BASE);
|
||||||
|
|
||||||
|
USERTASK.prototype.create = function (path) {
|
||||||
|
WORLD.TASKS.push(this);
|
||||||
|
|
||||||
|
this.on_create && this.on_create();
|
||||||
|
}
|
||||||
|
USERTASK.prototype.update = function (path) {
|
||||||
|
this.on_create && this.on_create();
|
||||||
|
for (var i = 0; i < WORLD.TASKS.length; i++) {
|
||||||
|
if (WORLD.TASKS[i].path == path) {
|
||||||
|
WORLD.TASKS[i] = this;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WORLD.TASKS.push(this);
|
||||||
|
}
|
||||||
|
USERTASK.prototype.query_title = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
USERTASK.prototype.start = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
USERTASK.prototype.query_desc = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
USERTASK.prototype.query_state = function () {
|
||||||
|
//0 不显示 1,进行中,2.可领取 3.已完成
|
||||||
|
}
|
||||||
|
USERTASK.RUN = function (id, player) {
|
||||||
|
for (var i = 0; i < WORLD.TASKS.length; i++) {
|
||||||
|
if (WORLD.TASKS[i].id == id) {
|
||||||
|
return WORLD.TASKS[i].start(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
USERTASK.GET = function (id) {
|
||||||
|
for (var i = 0; i < WORLD.TASKS.length; i++) {
|
||||||
|
if (WORLD.TASKS[i].id == id) {
|
||||||
|
return WORLD.TASKS[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
os/task/task.js
Normal file
36
os/task/task.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
TASK = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
TASK.inherits(BASE);
|
||||||
|
TASK.prototype.create = function () {
|
||||||
|
WORLD.SYSTEMTASKS.push(this);
|
||||||
|
this.startup();
|
||||||
|
}
|
||||||
|
TASK.GET = function (id) {
|
||||||
|
for (var i = 0; i < WORLD.SYSTEMTASKS.length; i++) {
|
||||||
|
if (WORLD.SYSTEMTASKS[i].id == id) {
|
||||||
|
return WORLD.SYSTEMTASKS[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TASK.prototype.update = function (path) {
|
||||||
|
var oldtask = null;
|
||||||
|
for (var i = 0; i < WORLD.SYSTEMTASKS.length; i++) {
|
||||||
|
if (WORLD.SYSTEMTASKS[i].path == path) {
|
||||||
|
WORLD.SYSTEMTASKS[i].stop();
|
||||||
|
oldtask = WORLD.SYSTEMTASKS[i];
|
||||||
|
WORLD.SYSTEMTASKS[i] = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!oldtask) {
|
||||||
|
WORLD.SYSTEMTASKS.push(this);
|
||||||
|
}
|
||||||
|
this.startup(oldtask);
|
||||||
|
}
|
||||||
|
TASK.prototype.startup = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
TASK.prototype.stop = function () {
|
||||||
|
|
||||||
|
}
|
||||||
154
os/util/data.js
Normal file
154
os/util/data.js
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
|
||||||
|
const fs_sync = require("fs");
|
||||||
|
const fs = fs_sync.promises;
|
||||||
|
|
||||||
|
const DB = __CONFIG.DB;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
close: function () {
|
||||||
|
return DB.close();
|
||||||
|
},
|
||||||
|
getRoles: function (userid, server) {
|
||||||
|
return DB.getRoles(userid, server);
|
||||||
|
},
|
||||||
|
addRole: async function (role) {
|
||||||
|
return await DB.addRole(role);
|
||||||
|
},
|
||||||
|
deleteRole: function (userid, roleid) {
|
||||||
|
return DB.deleteRole(userid, roleid);
|
||||||
|
},
|
||||||
|
saveRole: function (role) {
|
||||||
|
return DB.saveRole(role);
|
||||||
|
},
|
||||||
|
saveRoles: async function (roles) {
|
||||||
|
const dt = new Date();
|
||||||
|
const path = __PATH.DATA + "bak/data" + dt.getFullYear() + "-" + (dt.getMonth() + 1) + "-" + dt.getDate() + "-" + dt.getHours() + ".js";
|
||||||
|
const stream = fs_sync.createWriteStream(path, { flags: 'a' });
|
||||||
|
try {
|
||||||
|
stream.write('[');
|
||||||
|
for (let role of roles) {
|
||||||
|
await DB.saveRole(role);
|
||||||
|
this.localBak(stream, role);
|
||||||
|
|
||||||
|
}
|
||||||
|
stream.write('0]');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('备份数据失败:', error);
|
||||||
|
} finally {
|
||||||
|
stream.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
localBak: function (stream, role) {
|
||||||
|
stream.write('{id:"');
|
||||||
|
stream.write(role.id);
|
||||||
|
stream.write('",name:"');
|
||||||
|
stream.write(role.name);
|
||||||
|
stream.write('",userid:');
|
||||||
|
stream.write(role.userid.toString());
|
||||||
|
stream.write(',title:"');
|
||||||
|
stream.write(role.title);
|
||||||
|
stream.write('",level:');
|
||||||
|
stream.write(role.level.toString());
|
||||||
|
stream.write(',data:');
|
||||||
|
stream.write(role.data);
|
||||||
|
stream.write('},');
|
||||||
|
},
|
||||||
|
saveRequest: function (recs) {
|
||||||
|
var dt = new Date();
|
||||||
|
var f = dt.getFullYear() + "-" + (dt.getMonth() + 1) + "-" + dt.getDate();
|
||||||
|
var path = __PATH.DATA + "req/request" + f + ".txt";
|
||||||
|
var ary = [];
|
||||||
|
for (var i = 0; i < recs.length; i++) {
|
||||||
|
var r = recs[i];
|
||||||
|
ary.push(r.time);
|
||||||
|
ary.push(" ");
|
||||||
|
ary.push(r.user);
|
||||||
|
ary.push(" ");
|
||||||
|
ary.push(r.cmd);
|
||||||
|
ary.push("\r\n");
|
||||||
|
}
|
||||||
|
return fs.appendFile(path, ary.join(""));
|
||||||
|
},
|
||||||
|
saveLogs: function (logs) {
|
||||||
|
var dt = new Date();
|
||||||
|
var f = dt.getFullYear() + "-" + (dt.getMonth() + 1) + "-" + dt.getDate();
|
||||||
|
var path = __PATH.DATA + "log/log" + f + ".txt";
|
||||||
|
var ary = [];
|
||||||
|
for (var i = 0; i < logs.length; i++) {
|
||||||
|
var r = logs[i];
|
||||||
|
ary.push(r.time);
|
||||||
|
ary.push(" ");
|
||||||
|
ary.push(r.user);
|
||||||
|
ary.push(" ");
|
||||||
|
ary.push(r.cmd);
|
||||||
|
ary.push(" ");
|
||||||
|
ary.push(r.msg);
|
||||||
|
ary.push("\r\n");
|
||||||
|
}
|
||||||
|
return fs.appendFile(path, ary.join(""));
|
||||||
|
},
|
||||||
|
saveData: async function (content) {
|
||||||
|
let path = __PATH.DATA + "data.js";
|
||||||
|
let dt = new Date();
|
||||||
|
var f = dt.getFullYear() + "-" + (dt.getMonth() + 1) + "-" + dt.getDate();
|
||||||
|
let _dst = __PATH.DATA + "/temp/temp" + f + ".js";
|
||||||
|
await fs.copyFile(path, _dst);
|
||||||
|
return fs.writeFile(path, content);
|
||||||
|
}, readData: async function () {
|
||||||
|
let path = __PATH.DATA + "data.js";
|
||||||
|
try {
|
||||||
|
const data = await fs.readFile(path);
|
||||||
|
return JSON.toObject(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('数据读取失败', path, error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getRoleData: function (userid, id) {
|
||||||
|
|
||||||
|
return DB.getData(userid, id);
|
||||||
|
},
|
||||||
|
change_name: function (id, name) {
|
||||||
|
return DB.updateRoleName(id, name);
|
||||||
|
},
|
||||||
|
change_userid: function (id, fromuserid, touserid) {
|
||||||
|
return DB.updateUserid(id, fromuserid, touserid);
|
||||||
|
},
|
||||||
|
check_file: async function (path) {
|
||||||
|
try {
|
||||||
|
await fs.access(path)
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
initDataDir: async function () {
|
||||||
|
__PATH.BASE_DATA = __PATH.DATA;
|
||||||
|
__PATH.DATA = __PATH.DATA + WORLD.SERVERID + "/";
|
||||||
|
|
||||||
|
if (!await this.check_file(__PATH.DATA)) {
|
||||||
|
console.log('创建备份文件夹....');
|
||||||
|
await fs.mkdir(__PATH.DATA);
|
||||||
|
}
|
||||||
|
var paths = await fs.readdir(__PATH.DEF_DATA);
|
||||||
|
for (var i = 0; i < paths.length; i++) {
|
||||||
|
var _src = __PATH.DEF_DATA + paths[i];
|
||||||
|
var _dst = __PATH.DATA + paths[i];
|
||||||
|
if (!await this.check_file(_dst)) {
|
||||||
|
var stat = await fs.stat(_src);
|
||||||
|
if (stat.isFile()) {
|
||||||
|
await fs.copyFile(_src, _dst);
|
||||||
|
console.log('创建备份文件 ', _dst, "....");
|
||||||
|
} else {
|
||||||
|
await fs.mkdir(_dst);
|
||||||
|
console.log('创建备份文件夹 ', _dst, "....");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getServers: function () {
|
||||||
|
return DB.getServers();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
406
os/util/util.js
Normal file
406
os/util/util.js
Normal file
@@ -0,0 +1,406 @@
|
|||||||
|
|
||||||
|
|
||||||
|
const util = require('util');
|
||||||
|
const JSON5 = require('json5');
|
||||||
|
//nodejs自带的原型继承方法
|
||||||
|
Function.prototype.inherits = function (superCtor) {
|
||||||
|
|
||||||
|
util.inherits(this, superCtor);
|
||||||
|
}
|
||||||
|
Array.prototype.remove = function (item) {
|
||||||
|
for (var i = 0; i < this.length; i++) {
|
||||||
|
if (this[i] == item) {
|
||||||
|
this.splice(i, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Array.prototype.contain = function (item) {
|
||||||
|
for (var i = 0; i < this.length; i++) {
|
||||||
|
if (this[i] === item) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Array.prototype.random = function (index) {
|
||||||
|
index = index || this.length;
|
||||||
|
return this[Math.floor(Math.random() * this.length)];
|
||||||
|
}
|
||||||
|
JSON.toObject = function (str) {
|
||||||
|
return JSON5.parse(str);
|
||||||
|
|
||||||
|
}
|
||||||
|
UTIL = {
|
||||||
|
empty: function () {
|
||||||
|
},
|
||||||
|
require: function (str) {
|
||||||
|
return require(str);
|
||||||
|
},
|
||||||
|
is_gift: function () {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
wrandom: function (me, max, rate = 86400000) {
|
||||||
|
let key = parseInt(me.id[0], 36);
|
||||||
|
if (!(key >= 0)) key = 1;
|
||||||
|
let time = Math.floor(Date.now() / rate) + key;
|
||||||
|
return time % max;
|
||||||
|
},
|
||||||
|
moneyToStr: function (value) {
|
||||||
|
if (!value) return "";
|
||||||
|
var str = [];
|
||||||
|
if (value >= 10000) {
|
||||||
|
str.push(parseInt(value / 10000) + "两<hiy>黄金</hiy>");
|
||||||
|
value = value % 10000;
|
||||||
|
}
|
||||||
|
if (value > 100) {
|
||||||
|
str.push(parseInt(value / 100) + "两<wht>白银</wht>");
|
||||||
|
value = value % 100;
|
||||||
|
}
|
||||||
|
if (value > 0) {
|
||||||
|
str.push(value + "个<yel>铜板</yel>");
|
||||||
|
}
|
||||||
|
return str.join("");
|
||||||
|
},
|
||||||
|
timeSpan: function (time) {
|
||||||
|
let str = [];
|
||||||
|
if (time > 86400000) {
|
||||||
|
str.push(Math.floor(time / 86400000), '天');
|
||||||
|
time = time % 86400000;
|
||||||
|
}
|
||||||
|
if (time > 3600000) {
|
||||||
|
str.push(Math.floor(time / 3600000), '小时');
|
||||||
|
time = time % 3600000;
|
||||||
|
}
|
||||||
|
if (time > 60000) {
|
||||||
|
str.push(Math.floor(time / 60000), '分钟');
|
||||||
|
time = time % 60000;
|
||||||
|
}
|
||||||
|
str.push(Math.floor(time / 1000), '秒');
|
||||||
|
return str.join("");
|
||||||
|
},
|
||||||
|
C_STR: "零一二三四五六七八九",
|
||||||
|
C_STR2: ["", "十", "百", "千", "万", "亿"],
|
||||||
|
C_STR3: ["", "万", "亿"],
|
||||||
|
to_c: function (num) {
|
||||||
|
if (!num) return "";
|
||||||
|
var str = "";
|
||||||
|
var count = 0;
|
||||||
|
var add = 0;//0=0,1=数 2=百十千 3=万亿
|
||||||
|
while (num) {
|
||||||
|
var d = num % 10;
|
||||||
|
if (count) {
|
||||||
|
if (count % 4 == 0 && add != 3) {
|
||||||
|
str = UTIL.C_STR3[count / 4] + str;
|
||||||
|
add = 3;
|
||||||
|
} else if (d && add != 2) {
|
||||||
|
str = UTIL.C_STR2[count % 4] + str;
|
||||||
|
add = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d) {
|
||||||
|
if (d != 1 || num > 10 || count % 4 != 1)
|
||||||
|
str = UTIL.C_STR[d] + str;
|
||||||
|
add = 1;
|
||||||
|
} else if (add == 1) {
|
||||||
|
str = UTIL.C_STR[d] + str;
|
||||||
|
add = 0;
|
||||||
|
}
|
||||||
|
num = parseInt(num / 10);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
htmlEncode: function (str) {
|
||||||
|
if (!str) return str;
|
||||||
|
return str.replace(/>/g, ">")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
},
|
||||||
|
prop_toString: function (prop, sp, count) {
|
||||||
|
if (!prop) return "";
|
||||||
|
var str = [];
|
||||||
|
count = count || 1;
|
||||||
|
for (var item in prop) {
|
||||||
|
switch (item) {
|
||||||
|
case "desc":
|
||||||
|
case "desc1":
|
||||||
|
case "desc2":
|
||||||
|
case "desc3":
|
||||||
|
case "desc4":
|
||||||
|
case "desc5":
|
||||||
|
str.push(prop[item]);
|
||||||
|
break;
|
||||||
|
case "releasetime":
|
||||||
|
case "distime":
|
||||||
|
prop[item] > 0 ?
|
||||||
|
str.push(PROPERTIES[item] + ":-" + (prop[item] * count / 1000) + "秒")
|
||||||
|
:
|
||||||
|
str.push(PROPERTIES[item] + ":+" + (-prop[item] * count / 1000) + "秒");
|
||||||
|
break;
|
||||||
|
case "diff_busy":
|
||||||
|
case "busy":
|
||||||
|
case "gjsd":
|
||||||
|
case "diff_downside":
|
||||||
|
prop[item] > 0 ?
|
||||||
|
str.push(PROPERTIES[item] + ":+" + (prop[item] * count / 1000) + "秒")
|
||||||
|
:
|
||||||
|
str.push(PROPERTIES[item] + ":" + (prop[item] * count / 1000) + "秒");
|
||||||
|
break;
|
||||||
|
case "expend_mp_per":
|
||||||
|
case "distime_per":
|
||||||
|
case "releasetime_per":
|
||||||
|
prop[item] > 0 ?
|
||||||
|
str.push(PROPERTIES[item] + ":-" + (prop[item] * count) + "%")
|
||||||
|
:
|
||||||
|
str.push(PROPERTIES[item] + ":+" + (prop[item] * -count) + "%");
|
||||||
|
break;
|
||||||
|
case "lianxi_per":
|
||||||
|
case "dazuo_per":
|
||||||
|
case "study_per":
|
||||||
|
case "add_sh_per":
|
||||||
|
case "add_bjsh_per":
|
||||||
|
case "busy_per":
|
||||||
|
case "gjsd_per":
|
||||||
|
case "bj_per":
|
||||||
|
case "zj_per":
|
||||||
|
case "ds_per":
|
||||||
|
case "fy_per":
|
||||||
|
case "diff_sh_per":
|
||||||
|
case "diff_sh_per2":
|
||||||
|
case "diff_fy_per":
|
||||||
|
case "diff_fy_per2":
|
||||||
|
case "diff_busy_per":
|
||||||
|
case "mz_per":
|
||||||
|
case "gj_per":
|
||||||
|
case "diff_bj":
|
||||||
|
case "hp_per":
|
||||||
|
case "money_per":
|
||||||
|
case "diff_downside_per":
|
||||||
|
case "recover_per":
|
||||||
|
prop[item] > 0 ?
|
||||||
|
str.push(PROPERTIES[item] + ":+" + (prop[item] * count) + "%")
|
||||||
|
:
|
||||||
|
str.push(PROPERTIES[item] + ":" + (prop[item] * count) + "%");
|
||||||
|
break;
|
||||||
|
case "skill":
|
||||||
|
var skills = prop[item];
|
||||||
|
for (var sk in skills) {
|
||||||
|
var sk_base = SKILL.get(sk);
|
||||||
|
if (sk_base)
|
||||||
|
str.push(sk_base.name + ":+" + skills[sk] + "级");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "age":
|
||||||
|
prop[item] > 0 ?
|
||||||
|
str.push(PROPERTIES[item] + ":-" + prop[item] * count + "岁")
|
||||||
|
:
|
||||||
|
str.push(PROPERTIES[item] + ":+" + (-prop[item]) * count + "岁");
|
||||||
|
break;
|
||||||
|
case "expend_mp":
|
||||||
|
prop[item] > 0 ?
|
||||||
|
str.push(PROPERTIES[item] + ":-" + prop[item] * count)
|
||||||
|
:
|
||||||
|
str.push(PROPERTIES[item] + ":+" + (-prop[item]) * count);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
let p = PROPERTIES[item];
|
||||||
|
if (p) {
|
||||||
|
prop[item] > 0 ?
|
||||||
|
str.push(PROPERTIES[item] + ":+" + prop[item] * count)
|
||||||
|
:
|
||||||
|
str.push(PROPERTIES[item] + ":" + prop[item] * count);
|
||||||
|
} else {
|
||||||
|
p = SKILL.SLOTS[item];
|
||||||
|
if (p) {
|
||||||
|
str.push(p.format(prop[item] * count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str.join(sp || "\n");
|
||||||
|
},
|
||||||
|
diff_time: function (next_hour) {
|
||||||
|
//到清理临时temp( 明天5点)的时间
|
||||||
|
next_hour = next_hour || 5;
|
||||||
|
var dt = new Date();
|
||||||
|
var hour = dt.getHours();
|
||||||
|
var day = dt.getDate();
|
||||||
|
if (hour >= next_hour) day = day + 1;
|
||||||
|
dt = new Date(dt.getFullYear(), dt.getMonth(), day, next_hour);
|
||||||
|
return dt - Date.now();
|
||||||
|
},
|
||||||
|
diff_week_time: function (next_hour) {
|
||||||
|
//到清理临时temp( 每周一5点)的时间
|
||||||
|
next_hour = next_hour || 5;
|
||||||
|
var date = new Date();
|
||||||
|
var week = date.getDay();
|
||||||
|
week = week == 0 ? 1 : 8 - week;
|
||||||
|
if (week == 7 && date.getHours() < next_hour) {
|
||||||
|
week = 0;
|
||||||
|
}
|
||||||
|
var next_date = new Date(date.getFullYear(), date.getMonth(), date.getDate() + week, next_hour);
|
||||||
|
|
||||||
|
|
||||||
|
return next_date - Date.now();
|
||||||
|
}, diff_month_time: function (next_hour) {
|
||||||
|
|
||||||
|
//到清理临时temp( 每周一5点)的时间
|
||||||
|
next_hour = next_hour || 5;
|
||||||
|
var date = new Date();
|
||||||
|
|
||||||
|
if (date.getDate() > 1 || date.getHours() >= next_hour) {
|
||||||
|
date = new Date(date.setMonth(date.getMonth() + 1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
var next_date = new Date(date.getFullYear(), date.getMonth(), 1, next_hour);
|
||||||
|
// me.send(next_date.getFullYear() + "年" + (date.getMonth() + 1)+ "月" + 1 + "日" + next_hour);
|
||||||
|
|
||||||
|
return next_date - Date.now();
|
||||||
|
},
|
||||||
|
logs: [],
|
||||||
|
log: function (msg) {
|
||||||
|
|
||||||
|
this.logs.push({
|
||||||
|
dt: Date.now,
|
||||||
|
content: msg
|
||||||
|
});
|
||||||
|
},
|
||||||
|
saveLog: function () {
|
||||||
|
if (!this.logs) return;
|
||||||
|
|
||||||
|
var fs = require("fs");
|
||||||
|
var dt = new Date();
|
||||||
|
var path = __PATH.DATA + "log/";
|
||||||
|
if (!fs.existsSync(path)) {
|
||||||
|
fs.mkdirSync(path);
|
||||||
|
}
|
||||||
|
var file = path + (dt.getMonth() + 1) + "-" + dt.getDate() + "-" + dt.getHours() + ".log";
|
||||||
|
fs.writeFileSync(path, JSON.stringify(this.logs));
|
||||||
|
},
|
||||||
|
idstr: "0123456789abcdefghijklmnopqrstuvwxwz",
|
||||||
|
begin: 1490276099978,
|
||||||
|
create_id: function () {
|
||||||
|
var str = [];
|
||||||
|
for (var i = 0; i < 4; i++) {
|
||||||
|
str.push(this.idstr[parseInt(Math.random() * this.idstr.length)]);
|
||||||
|
}
|
||||||
|
str.push(parseInt((Date.now() - this.begin) / 1000).toString(16));
|
||||||
|
return str.join("");
|
||||||
|
},
|
||||||
|
random_name: function (s, t) {
|
||||||
|
t = t || (parseInt(Math.random() * 2) + 1);
|
||||||
|
var str = [];
|
||||||
|
if (t == 2) {
|
||||||
|
var key = parseInt(Math.random() * this.name0.length);
|
||||||
|
if (key % 2 == 1) key -= 1;
|
||||||
|
str.push(this.name0[key++]);
|
||||||
|
str.push(this.name0[key]);
|
||||||
|
} else {
|
||||||
|
str.push(this.name1[parseInt(Math.random() * this.name1.length)]);
|
||||||
|
}
|
||||||
|
if (s == 0) {
|
||||||
|
str.push(this.name2[parseInt(Math.random() * this.name2.length)]);
|
||||||
|
} else {
|
||||||
|
str.push(this.name3[parseInt(Math.random() * this.name3.length)]);
|
||||||
|
}
|
||||||
|
if (parseInt(Math.random() * 4) > 1) {
|
||||||
|
if (s == 0) {
|
||||||
|
str.push(this.name2[parseInt(Math.random() * this.name2.length)]);
|
||||||
|
} else {
|
||||||
|
str.push(this.name3[parseInt(Math.random() * this.name3.length)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str.join("");
|
||||||
|
},
|
||||||
|
name0: "万俟司马上官欧阳夏侯诸葛闻人东方赫连皇甫尉迟公羊澹台公冶宗政濮阳淳于单于太叔申屠公孙仲孙轩辕令狐锺离宇文长孙慕容鲜于闾丘司徒司空丌官司寇子车颛孙端木巫马公西乐正公良拓拔夹谷谷梁梁丘左丘东门西门",
|
||||||
|
name1: "赵钱孙李周吴郑王冯陈楮卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛奚范彭郎",
|
||||||
|
|
||||||
|
name2: "世舜丞主产仁仇仓仕仞任伋众伸佐佺侃侪促俟信俣修倝倡倧偿储僖僧僳儒俊伟列则刚创前剑助劭势勘参叔吏嗣士壮孺守宽宾宋宗宙宣实宰尊峙峻崇崈川州巡帅庚战才承拯操斋昌晁暠曹曾珺玮珹琒琛琩琮琸瑎玚璟璥瑜生畴矗矢石磊砂碫示社祖祚祥禅稹穆竣竦综缜绪舱舷船蚩襦轼辑轩子杰榜碧葆莱蒲天乐东钢铎铖铠铸铿锋镇键镰馗旭骏骢骥驹驾骄诚诤赐慕端征坚建弓强彦御悍擎攀旷昂晷健冀凯劻啸柴木林森朴骞寒函高魁魏鲛鲲鹰丕乒候冕勰备宪宾密封山峰弼彪彭旁日明昪昴胜汉涵汗浩涛淏清澜浦澉澎澔瀚瀛灏沧虚豪豹辅辈迈邶合部阔雄霆震韩俯颁颇频颔风飒飙飚马亮仑仝代儋利力劼勒卓哲喆展帝弛弢弩彰征律德志忠思振挺掣旲旻昊昮晋晟晸朕朗段殿泰滕炅炜煜煊炎选玄勇君稼黎利贤谊金鑫辉墨欧有友闻问",
|
||||||
|
|
||||||
|
name3: "筠柔竹霭凝晓欢霄枫芸菲寒伊亚宜姬舒影荔枝思丽秀娟英华慧巧美娜静淑惠珠翠雅芝玉萍红娥玲芬芳燕彩春菊勤珍贞莉兰凤洁梅琳素云莲真环雪荣妹霞香月莺媛艳瑞凡佳嘉琼桂娣叶璧璐娅琦晶妍茜秋珊莎锦黛青倩婷姣婉娴瑾颖露瑶怡婵雁蓓纨仪荷丹蓉眉君琴蕊薇菁梦岚苑婕馨瑗琰韵融园艺咏卿聪澜纯毓悦昭冰爽琬茗羽希宁欣飘育滢馥",
|
||||||
|
|
||||||
|
getLunar: function (date) {
|
||||||
|
date = date || new Date();
|
||||||
|
//农历函数开始
|
||||||
|
var lunarInfo = new Array(0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, //1990
|
||||||
|
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, 0x14b63);
|
||||||
|
function lYearDays(y) {
|
||||||
|
var i, sum = 348;
|
||||||
|
for (i = 0x8000; i > 0x8; i >>= 1) sum += (lunarInfo[y - 1900] & i) ? 1 : 0;
|
||||||
|
return (sum + leapDays(y));
|
||||||
|
}
|
||||||
|
function leapDays(y) {
|
||||||
|
if (leapMonth(y)) return ((lunarInfo[y - 1900] & 0x10000) ? 30 : 29);
|
||||||
|
else return (0);
|
||||||
|
}
|
||||||
|
function leapMonth(y) {
|
||||||
|
return (lunarInfo[y - 1900] & 0xf);
|
||||||
|
}
|
||||||
|
function monthDays(y, m) {
|
||||||
|
return ((lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29);
|
||||||
|
}
|
||||||
|
function Lunar(y, m, d) {
|
||||||
|
var i, leap = 0,
|
||||||
|
temp = 0;
|
||||||
|
var offset = (Date.UTC(y, m, d) - Date.UTC(1900, 0, 31)) / 86400000;
|
||||||
|
for (i = 1900; i < 2050 && offset > 0; i++) {
|
||||||
|
temp = lYearDays(i);
|
||||||
|
offset -= temp;
|
||||||
|
}
|
||||||
|
if (offset < 0) {
|
||||||
|
offset += temp;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
this.year = i;
|
||||||
|
leap = leapMonth(i);
|
||||||
|
this.isLeap = false;
|
||||||
|
for (i = 1; i < 13 && offset > 0; i++) {
|
||||||
|
if (leap > 0 && i == (leap + 1) && this.isLeap == false) {
|
||||||
|
--i;
|
||||||
|
this.isLeap = true;
|
||||||
|
temp = leapDays(this.year);
|
||||||
|
} else {
|
||||||
|
temp = monthDays(this.year, i);
|
||||||
|
}
|
||||||
|
if (this.isLeap == true && i == (leap + 1)) this.isLeap = false;
|
||||||
|
offset -= temp;
|
||||||
|
}
|
||||||
|
if (offset == 0 && leap > 0 && i == leap + 1) if (this.isLeap) {
|
||||||
|
this.isLeap = false;
|
||||||
|
} else {
|
||||||
|
this.isLeap = true; --i;
|
||||||
|
}
|
||||||
|
if (offset < 0) {
|
||||||
|
offset += temp; --i;
|
||||||
|
}
|
||||||
|
this.month = i;
|
||||||
|
this.day = offset + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Lunar(date.getFullYear(), date.getMonth(), date.getDate());
|
||||||
|
},
|
||||||
|
isLunar15: function (dt) {
|
||||||
|
let issuc = WORLD.DATA.query_temp('lunar15', 0);
|
||||||
|
if (issuc === 0) {
|
||||||
|
let now = dt || new Date();
|
||||||
|
let hour = now.getHours();
|
||||||
|
var lunar = UTIL.getLunar(now);
|
||||||
|
if ((lunar.day === 14 && hour >= 5) || lunar.day === 15
|
||||||
|
|| (lunar.day === 16 && hour < 5)) {
|
||||||
|
|
||||||
|
WORLD.DATA.set_temp('lunar15', 1, UTIL.diff_time());
|
||||||
|
issuc = 1;
|
||||||
|
} else {
|
||||||
|
WORLD.DATA.set_temp('lunar15', -1, UTIL.diff_time());
|
||||||
|
issuc = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return issuc > 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
341
os/world.js
Normal file
341
os/world.js
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
|
||||||
|
require("./util/util");
|
||||||
|
const db = require("./util/data");
|
||||||
|
WORLD = {
|
||||||
|
USERS: [],
|
||||||
|
COMMANDS: {},
|
||||||
|
SKILLS: {},
|
||||||
|
ROOMS: {},
|
||||||
|
RUN_ROOMS: [],
|
||||||
|
DEFAULT_SKILLS: {},
|
||||||
|
AREAS: [],
|
||||||
|
TASKS: [],
|
||||||
|
SYSTEMTASKS: [],
|
||||||
|
USER_EVENTS: [],
|
||||||
|
OBJ_STROE: new Map(),
|
||||||
|
NPC_STROE: new Map(),
|
||||||
|
HEARTBEATCOUNT: 0,
|
||||||
|
RECEIVED: [],
|
||||||
|
LOGS: [],
|
||||||
|
SERVERID: 0,
|
||||||
|
SERVERS: [],
|
||||||
|
CONNECT_COUNT: 0,
|
||||||
|
DATA: require('./data'),
|
||||||
|
USERLOGIN: require('./login'),
|
||||||
|
DB: db,
|
||||||
|
SocketCount: 0,
|
||||||
|
LISTENER: require("./ws"),
|
||||||
|
max_connect_count: 1100,
|
||||||
|
max_user_count: 5100,
|
||||||
|
MESSAGE: {
|
||||||
|
stores: new Map(),
|
||||||
|
NOTICES: [],
|
||||||
|
},
|
||||||
|
STATS: {
|
||||||
|
TOPS: [],
|
||||||
|
EXP: [],
|
||||||
|
SCORE: [],
|
||||||
|
WEAPON: [],
|
||||||
|
},
|
||||||
|
status: -1,//-1关闭 0正常 >1 用户等级>连接
|
||||||
|
SocketIn: function () {
|
||||||
|
this.SocketCount++;
|
||||||
|
},
|
||||||
|
connect: function (socket) {
|
||||||
|
if (WORLD.status < 0)
|
||||||
|
return socket.end();
|
||||||
|
if (!WORLD.check_connect(socket))
|
||||||
|
return socket.end();
|
||||||
|
|
||||||
|
socket.user = new USER();
|
||||||
|
|
||||||
|
socket.user.socket = socket;
|
||||||
|
socket.user.wait_input = this.USERLOGIN.check_session.bind(this.USERLOGIN);
|
||||||
|
|
||||||
|
socket.setTimeout(60000);
|
||||||
|
},
|
||||||
|
check_connect: function (socket) {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
before_login: function (user) {
|
||||||
|
if (this.status < 0) return false;
|
||||||
|
if (this.status === 0) return true;
|
||||||
|
return this.status <= user.user_level;
|
||||||
|
},
|
||||||
|
disconnect: function (socket) {
|
||||||
|
if (socket.user) {
|
||||||
|
socket.user.socket = null;
|
||||||
|
socket.user.disconnect();
|
||||||
|
}
|
||||||
|
this.SocketCount--;
|
||||||
|
if (socket.oserver) {
|
||||||
|
socket.oserver.disconnect();
|
||||||
|
socket.oserver = null;
|
||||||
|
}
|
||||||
|
}, request: function (request, socket) {
|
||||||
|
if (!request) return;
|
||||||
|
var user = socket.user;
|
||||||
|
if (!user) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (user.request_count > 20) {
|
||||||
|
return user.send("不要急,慢慢来。");
|
||||||
|
}
|
||||||
|
user.request_count = user.request_count + 1;
|
||||||
|
var time = Date.now();
|
||||||
|
try {
|
||||||
|
user.command(request);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(user.name, "命令错误:", request, e.message, e.stack);
|
||||||
|
WORLD.log(user, request, e.message + e.stack);
|
||||||
|
}
|
||||||
|
WORLD.RECEIVED.push({
|
||||||
|
time: time,
|
||||||
|
cmd: request + " " + (Date.now() - time).toString(),
|
||||||
|
user: user.id
|
||||||
|
});
|
||||||
|
if (WORLD.RECEIVED.length > 1000) {
|
||||||
|
WORLD.saveRequest();
|
||||||
|
}
|
||||||
|
}, saveRequest: function () {
|
||||||
|
db.saveRequest(WORLD.RECEIVED);
|
||||||
|
WORLD.RECEIVED.length = 0;
|
||||||
|
},
|
||||||
|
startup: async function (sid) {
|
||||||
|
if (sid) {
|
||||||
|
sid = parseInt(sid);
|
||||||
|
this.SERVERS = await db.getServers();
|
||||||
|
this.SERVER = this.getServer(sid);
|
||||||
|
} else {
|
||||||
|
this.SERVER = __CONFIG.def_server;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.SERVER) throw "服务器设置错误,无法启动";
|
||||||
|
this.SERVERID = this.SERVER.id;
|
||||||
|
|
||||||
|
await db.initDataDir();
|
||||||
|
loadResource();
|
||||||
|
await this.DATA.load();
|
||||||
|
await this.LISTENER.start(this.SERVER.port);
|
||||||
|
console.log("服务", this.SERVER.name, "(" + this.SERVERID + ")启动");
|
||||||
|
console.log("ws://" + this.SERVER.ip + ":" + this.SERVER.port);
|
||||||
|
this.heart_beat_service = setInterval(WORLD.heart_beat, __CONFIG.HEARTBEAT);
|
||||||
|
|
||||||
|
this.status = __CONFIG.CONNECT_LEVEL ?? 0;
|
||||||
|
this.on_startup();
|
||||||
|
if (this.status > 0)
|
||||||
|
console.log('当前允许级别' + this.status + "账号登陆");
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
sendAll: function (msg) {
|
||||||
|
for (var i = 0; i < WORLD.USERS.length; i++) {
|
||||||
|
WORLD.USERS[i].send(msg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getUser: function (id) {
|
||||||
|
if (!id) return;
|
||||||
|
for (var i = 0; i < WORLD.USERS.length; i++) {
|
||||||
|
if (WORLD.USERS[i].id == id) return WORLD.USERS[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
}, find_user: function (name) {
|
||||||
|
if (!name) return;
|
||||||
|
for (var i = 0; i < WORLD.USERS.length; i++) {
|
||||||
|
if (WORLD.USERS[i].name == name) return WORLD.USERS[i];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
on_user_login: function (user) {
|
||||||
|
|
||||||
|
},
|
||||||
|
on_user_cross_login: function (user) {
|
||||||
|
|
||||||
|
},
|
||||||
|
on_startup: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
on_user_quit: function (user) {
|
||||||
|
|
||||||
|
},
|
||||||
|
on_user_relogin: function (user) {
|
||||||
|
|
||||||
|
}
|
||||||
|
,
|
||||||
|
on_heart_beat: function (user) {
|
||||||
|
|
||||||
|
},
|
||||||
|
heart_beat: function () {
|
||||||
|
var avtived_obj = null;
|
||||||
|
try {
|
||||||
|
const dt = Date.now();
|
||||||
|
WORLD.CONNECT_COUNT = 0;
|
||||||
|
for (let i = 0; i < WORLD.USERS.length; i++) {
|
||||||
|
avtived_obj = WORLD.USERS[i];
|
||||||
|
if (avtived_obj.socket) WORLD.CONNECT_COUNT++;
|
||||||
|
avtived_obj.heart_beat(dt);
|
||||||
|
}
|
||||||
|
WORLD.on_heart_beat(dt);
|
||||||
|
for (let i = 0; i < WORLD.RUN_ROOMS.length; i++) {
|
||||||
|
avtived_obj = WORLD.RUN_ROOMS[i];
|
||||||
|
avtived_obj.heart_beat(dt);
|
||||||
|
}
|
||||||
|
WORLD.HEARTBEATCOUNT++;
|
||||||
|
if (WORLD.HEARTBEATCOUNT > 720) {
|
||||||
|
WORLD.HEARTBEATCOUNT = 0;
|
||||||
|
WORLD.save();
|
||||||
|
console.log("数据已备份%d", Date.now() - dt);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(avtived_obj ? (avtived_obj.path ?? avtived_obj.name) : "", "心跳错误:", e, e.stack);
|
||||||
|
WORLD.log(null, e.message, e.stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
login_out: function (user) {
|
||||||
|
this.on_user_quit(user);
|
||||||
|
if (user.serverid === WORLD.SERVERID) {
|
||||||
|
user.save();
|
||||||
|
}
|
||||||
|
WORLD.USERS.remove(user);
|
||||||
|
|
||||||
|
if (user.socket) {
|
||||||
|
try {
|
||||||
|
user.socket.end();
|
||||||
|
user.socket.destroy();
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.message, e.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, send: function (text) {
|
||||||
|
for (var i = 0; i < this.USERS.length; i++) {
|
||||||
|
this.USERS[i].send(text);
|
||||||
|
}
|
||||||
|
}, log: function (user, cmd, msg) {
|
||||||
|
WORLD.LOGS.push({
|
||||||
|
time: Date.now(),
|
||||||
|
cmd: cmd,
|
||||||
|
user: user ? user.name : "",
|
||||||
|
msg: msg
|
||||||
|
});
|
||||||
|
if (WORLD.LOGS.length > 500) {
|
||||||
|
db.saveLogs(WORLD.LOGS);
|
||||||
|
WORLD.LOGS.length = 0;
|
||||||
|
}
|
||||||
|
}, saveLog: function () {
|
||||||
|
db.saveLogs(WORLD.LOGS);
|
||||||
|
WORLD.LOGS.length = 0;
|
||||||
|
}
|
||||||
|
,
|
||||||
|
is_server: function (user) {
|
||||||
|
return user.serverid == WORLD.SERVERID;
|
||||||
|
},
|
||||||
|
save: async function () {
|
||||||
|
|
||||||
|
var roles = [];
|
||||||
|
for (var i = 0; i < WORLD.USERS.length; i++) {
|
||||||
|
if (WORLD.USERS[i].serverid != WORLD.SERVERID) continue;
|
||||||
|
roles.push(WORLD.USERS[i].getData());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
console.time('saved');
|
||||||
|
await db.saveRoles(roles);
|
||||||
|
console.log('玩家数据已保存');
|
||||||
|
await this.DATA.save();
|
||||||
|
console.log('全局数据已经保存');
|
||||||
|
await this.saveLog();
|
||||||
|
await this.saveRequest();
|
||||||
|
console.log('日志数据已经保存');
|
||||||
|
console.timeEnd('saved');
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('玩家数据保存失败', error.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
writeHeapSnapshot: function () {
|
||||||
|
let v8 = UTIL.require('v8');
|
||||||
|
let dt = new Date();
|
||||||
|
let fname = __PATH.DATA + "/" + dt.getFullYear() + "_" + dt.getMonth() + "_"
|
||||||
|
+ dt.getDate() + "_" + dt.getHours() + "_" + dt.getMinutes() + ".heapsnapshot";
|
||||||
|
v8.writeHeapSnapshot(fname);
|
||||||
|
console.log('快照保存到', fname);
|
||||||
|
}
|
||||||
|
,
|
||||||
|
loadLocalData: function () {
|
||||||
|
let data = db.getLocalRoles();
|
||||||
|
if (!data || !data.length) return;
|
||||||
|
console.log("加载上次未保存的本地用户%d", data.length);
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
let user = new USER();
|
||||||
|
user.loadData(data[i]);
|
||||||
|
this.USERS.push(user);
|
||||||
|
}
|
||||||
|
db.deleteLocalRoles();
|
||||||
|
},
|
||||||
|
on_cross_response: function (id, sid) {
|
||||||
|
//允许跨服
|
||||||
|
},
|
||||||
|
can_cross: function (id) {
|
||||||
|
//允许跨服
|
||||||
|
}, on_user_die: function (me, killer, corpse) {
|
||||||
|
|
||||||
|
}, on_resource_loaded: function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function loadResource() {
|
||||||
|
let fs = require("fs");
|
||||||
|
function readdir(basePath, path) {
|
||||||
|
path = path || basePath;
|
||||||
|
let files = fs.readdirSync(path);
|
||||||
|
let count = 0;
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
let sub_path = path + files[i];
|
||||||
|
let stat = fs.statSync(sub_path);
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
count += readdir(basePath, sub_path + "/");
|
||||||
|
} else {
|
||||||
|
let fname = sub_path.replace(basePath, "").replace(".js", "");
|
||||||
|
BASE.CREATE(basePath, fname);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
let sum = 0;
|
||||||
|
let count = readdir(__PATH.EXTENDS);
|
||||||
|
console.log("%s %d ", __PATH.EXTENDS, count);
|
||||||
|
sum += count;
|
||||||
|
count = readdir(__PATH.COMMAND);
|
||||||
|
console.log("%s%d ", __PATH.COMMAND, count);
|
||||||
|
sum += count;
|
||||||
|
count = readdir(__PATH.FAMILY);
|
||||||
|
console.log("%s %d ", __PATH.FAMILY, count);
|
||||||
|
sum += count;
|
||||||
|
|
||||||
|
|
||||||
|
count = readdir(__PATH.OBJ);
|
||||||
|
console.log("%s %d ", __PATH.OBJ, count);
|
||||||
|
sum += count;
|
||||||
|
|
||||||
|
count = readdir(__PATH.AREA);
|
||||||
|
console.log("%s %d ", __PATH.AREA, count);
|
||||||
|
sum += count;
|
||||||
|
|
||||||
|
count = readdir(__PATH.SKILL);
|
||||||
|
console.log("%s %d ", __PATH.SKILL, count);
|
||||||
|
sum += count;
|
||||||
|
|
||||||
|
count = readdir(__PATH.MAP);
|
||||||
|
console.log("%s %d ", __PATH.MAP, count);
|
||||||
|
sum += count;
|
||||||
|
count = readdir(__PATH.TASK);
|
||||||
|
console.log("%s %d ", __PATH.TASK, count);
|
||||||
|
sum += count;
|
||||||
|
console.log('资源脚本加载%d', sum);
|
||||||
|
WORLD.on_resource_loaded();
|
||||||
|
} catch (e) {
|
||||||
|
console.log("error: ", e, e.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
49
os/ws.js
Normal file
49
os/ws.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
const ws = require("./net-ws");
|
||||||
|
const server = new ws({
|
||||||
|
SSL: false,
|
||||||
|
KEY: "",
|
||||||
|
CERT: "",
|
||||||
|
PASSWORD: ""
|
||||||
|
});
|
||||||
|
server.start = async function (port) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.listen(port, resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// WORLD.LISTENER = server;
|
||||||
|
server.onConnect = function (socket) {
|
||||||
|
WORLD.connect(socket);
|
||||||
|
}
|
||||||
|
server.onSocketIn = function (socket) {
|
||||||
|
|
||||||
|
WORLD.SocketIn(socket);
|
||||||
|
|
||||||
|
}
|
||||||
|
server.onReceive = function (msg, socket) {
|
||||||
|
WORLD.request(msg, socket);
|
||||||
|
}
|
||||||
|
server.onClose = function (msg, socket) {
|
||||||
|
console.log("server closed");
|
||||||
|
}
|
||||||
|
server.onClientClose = function (socket, e) {
|
||||||
|
|
||||||
|
WORLD.disconnect(socket);
|
||||||
|
if (!socket.destroyed) {
|
||||||
|
socket.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
server.onClientTimeout = function (socket, e) {
|
||||||
|
if (socket && (!socket.user || !socket.user.id)) {
|
||||||
|
socket.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
server.onClientError = function (socket, e) {
|
||||||
|
if (socket && socket.user) {
|
||||||
|
if (!socket.destroyed) {
|
||||||
|
socket.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = server;
|
||||||
38
package.json
Normal file
38
package.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "msmud",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "",
|
||||||
|
"main": "web.js",
|
||||||
|
"bin": "web.js",
|
||||||
|
"scripts": {
|
||||||
|
"web": "node web.js",
|
||||||
|
"web-debug": "node --inspect-brk web.js",
|
||||||
|
"mix": "node pack.js",
|
||||||
|
"os": "node main.js",
|
||||||
|
"os-debug": "node --inspect-brk main.js",
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"start": "concurrently \"npm run web\" \"npm run os\"",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"better-sqlite3": "^12.10.0",
|
||||||
|
"cookie-parser": "^1.4.7",
|
||||||
|
"dotenv": "^17.4.2",
|
||||||
|
"express": "^5.1.0",
|
||||||
|
"express-session": "^1.18.1",
|
||||||
|
"jquery": "^4.0.0",
|
||||||
|
"json5": "^2.2.3",
|
||||||
|
"pino": "^9.7.0",
|
||||||
|
"pino-http": "^10.5.0",
|
||||||
|
"pino-roll": "^3.1.0",
|
||||||
|
"svg-captcha": "^1.4.0",
|
||||||
|
"vite": "^8.0.14"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"concurrently": "^9.1.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
64
src/api.js
Normal file
64
src/api.js
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import Util from './utils/util.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
Login: function (code, pwd, cb) {
|
||||||
|
return Util.Post('api/user/login', { code: code, pwd: pwd }, cb);
|
||||||
|
},
|
||||||
|
IsRegistValidation: function (cb) {
|
||||||
|
return Util.Get('UserAPI/IsRegistValidation', cb);
|
||||||
|
},
|
||||||
|
ValidationImage: function (cb) {
|
||||||
|
return Util.Get('api/user/validimage', cb);
|
||||||
|
},
|
||||||
|
Regist: function (user, cb) {
|
||||||
|
return Util.Post('api/user/regist', user, cb);
|
||||||
|
},
|
||||||
|
Enter: function (guider, cb) {
|
||||||
|
return Util.Get('e', [guider], cb);
|
||||||
|
},
|
||||||
|
ChangePassword: function (oldpwd, pwd, no, cb) {
|
||||||
|
return Util.Post('api/user/changepassword', { oldpwd: oldpwd, pwd: pwd, no: no }, cb);
|
||||||
|
},
|
||||||
|
LoginOut: function (cb) {
|
||||||
|
return Util.Get('UserAPI/LoginOut', cb);
|
||||||
|
},
|
||||||
|
GetRoles: function (userid, cb) {
|
||||||
|
return Util.Get('UserAPI/GetRoles', [userid], cb);
|
||||||
|
},
|
||||||
|
AddRole: function (player, cb) {
|
||||||
|
return Util.Post('UserAPI/AddRole', { player: player }, cb);
|
||||||
|
},
|
||||||
|
GetUser: function (cb) {
|
||||||
|
return Util.Get('UserAPI/GetUser', cb);
|
||||||
|
},
|
||||||
|
Search: function (userid, key, type, cb) {
|
||||||
|
return Util.Get('UserAPI/Search', [userid, key, type], cb);
|
||||||
|
},
|
||||||
|
ResetPassword: function (userid, cb) {
|
||||||
|
return Util.Get('UserAPI/ResetPassword', [userid], cb);
|
||||||
|
},
|
||||||
|
RecoverUser: function (pid, cb) {
|
||||||
|
return Util.Get('UserAPI/RecoverUser', [pid], cb);
|
||||||
|
},
|
||||||
|
LoadPlayer: function (pid, isDelete, cb) {
|
||||||
|
return Util.Get('UserAPI/LoadPlayer', [pid, isDelete], cb);
|
||||||
|
},
|
||||||
|
GetPhone: function (cb) {
|
||||||
|
return Util.Get('api/user/getphone', cb);
|
||||||
|
},
|
||||||
|
BindPhone: function (code, no, pwd, cb) {
|
||||||
|
return Util.Post('api/user/bindphone', { code: code, no: no, pwd: pwd }, cb);
|
||||||
|
},
|
||||||
|
SendValidateCode: function (no, cb) {
|
||||||
|
return Util.Get('UserAPI/SendValidateCode', [no], cb);
|
||||||
|
},
|
||||||
|
ResetPasswordByPhone: function (name, phone, vcode, pwd, cb) {
|
||||||
|
return Util.Post('api/user/resetpwd', { name: name, phone: phone, vcode: vcode, pwd: pwd }, cb);
|
||||||
|
},
|
||||||
|
NewServer: function (cb) {
|
||||||
|
return Util.Get('UserAPI/NewServer', cb);
|
||||||
|
},
|
||||||
|
GetServer: function (cb) {
|
||||||
|
return Util.Get('api/game/servers', cb);
|
||||||
|
}
|
||||||
|
};
|
||||||
139
src/base/page.js
Normal file
139
src/base/page.js
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
export class Page {
|
||||||
|
constructor(filePath) {
|
||||||
|
this._filePath = filePath;
|
||||||
|
this.$children = null;
|
||||||
|
this.$parent = null;
|
||||||
|
this.$el = null;
|
||||||
|
this.id = null;
|
||||||
|
this.template = '';
|
||||||
|
this.css = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath() {
|
||||||
|
return this._filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
mount(parent, options) {
|
||||||
|
const tpl = document.createElement('template');
|
||||||
|
tpl.innerHTML = this.render(options);
|
||||||
|
parent.append(tpl.content);
|
||||||
|
this.$el = parent.lastElementChild;
|
||||||
|
if (this.on_mount) this.on_mount(this.$el);
|
||||||
|
if (this.$children) {
|
||||||
|
this.$children.forEach(com => {
|
||||||
|
if (com.on_mount) com.on_mount(com.id ? document.getElementById(com.id) : this.$el);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(options) {
|
||||||
|
return this.template;
|
||||||
|
}
|
||||||
|
|
||||||
|
_injectStyle() {
|
||||||
|
if (!this.css || this._style_dom) return;
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.textContent = this.css;
|
||||||
|
document.head.append(style);
|
||||||
|
this._style_dom = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
unmount() {
|
||||||
|
if (this.$el) this.$el.remove();
|
||||||
|
this.$el = null;
|
||||||
|
if (this.on_unmount) this.on_unmount();
|
||||||
|
if (this.$children) this.$children.forEach(com => { if (com.on_unmount) com.on_unmount(); });
|
||||||
|
if (this.$parent && this.$parent.$children) {
|
||||||
|
this.$parent.$children = this.$parent.$children.filter(com => com !== this);
|
||||||
|
}
|
||||||
|
this.$parent = null;
|
||||||
|
this.$children = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
if (this.on_destroy) this.on_destroy();
|
||||||
|
if (this._style_dom) this._style_dom.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
insert(options) {
|
||||||
|
if (!options) throw new Error('选项不能为空');
|
||||||
|
if (typeof options === 'string') options = { url: options };
|
||||||
|
const ComClass = options.Class;
|
||||||
|
if (!ComClass) throw new Error(`组件类不存在`);
|
||||||
|
const com = new ComClass();
|
||||||
|
if (!this.$children) this.$children = [];
|
||||||
|
this.$children.push(com);
|
||||||
|
com.$parent = this;
|
||||||
|
if (options.id) {
|
||||||
|
this['$' + options.id] = com;
|
||||||
|
com.id = options.id;
|
||||||
|
}
|
||||||
|
return com.render(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
onCompile() {
|
||||||
|
this._injectStyle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function EventsMixin(target) {
|
||||||
|
target.prototype.handlers = Object.create(null);
|
||||||
|
target.prototype.on = function (type, func, ctx) {
|
||||||
|
return this._addListener(type, func, ctx, false);
|
||||||
|
};
|
||||||
|
target.prototype.once = function (type, func, ctx) {
|
||||||
|
return this._addListener(type, func, ctx, true);
|
||||||
|
};
|
||||||
|
target.prototype._addListener = function (type, func, ctx, once) {
|
||||||
|
if (typeof func !== 'function') {
|
||||||
|
console.warn('事件注册失败:回调必须是函数');
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
if (!this.handlers[type]) {
|
||||||
|
this.handlers[type] = { listeners: [], cache: [] };
|
||||||
|
}
|
||||||
|
const handler = this.handlers[type];
|
||||||
|
handler.listeners.push({ fn: func, ctx, once });
|
||||||
|
if (handler.cache.length) {
|
||||||
|
handler.cache.forEach(data => this._runListeners(handler, data));
|
||||||
|
handler.cache = [];
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
target.prototype.emit = function (type, data, delay = true, clear = false) {
|
||||||
|
const handler = this.handlers[type];
|
||||||
|
if (!handler) {
|
||||||
|
if (delay) this.handlers[type] = { listeners: [], cache: [data] };
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
if (!handler.listeners.length) {
|
||||||
|
if (delay) handler.cache.push(data);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
this._runListeners(handler, data);
|
||||||
|
if (clear) delete this.handlers[type];
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
target.prototype._runListeners = function (handler, data) {
|
||||||
|
for (let i = handler.listeners.length - 1; i >= 0; i--) {
|
||||||
|
const { fn, ctx, once } = handler.listeners[i];
|
||||||
|
if (fn.call(ctx, data) === false || once) handler.listeners.splice(i, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
target.prototype.off = function (type, func) {
|
||||||
|
const handler = this.handlers[type];
|
||||||
|
if (!handler) return this;
|
||||||
|
if (typeof func !== 'function') {
|
||||||
|
delete this.handlers[type];
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
handler.listeners = handler.listeners.filter(item => item.fn !== func);
|
||||||
|
if (!handler.listeners.length) delete this.handlers[type];
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
target.prototype.removeAll = function (type) {
|
||||||
|
if (type) delete this.handlers[type];
|
||||||
|
else this.handlers = Object.create(null);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
}
|
||||||
192
src/client.js
Normal file
192
src/client.js
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
|
||||||
|
import * as Util from './utils/util.js';
|
||||||
|
|
||||||
|
let IsConnecting = false;
|
||||||
|
let ChangeServer = false;
|
||||||
|
export let GameClient = null;
|
||||||
|
export let SelectedServer = null;
|
||||||
|
export let LastCommand = null;
|
||||||
|
const SessionKey = "u";
|
||||||
|
const SessionToken = "p";
|
||||||
|
|
||||||
|
export function connectServer(server, pid) {
|
||||||
|
if (IsConnecting) return;
|
||||||
|
|
||||||
|
SelectedServer = server;
|
||||||
|
console.log("重新连接", GameClient == null ? "未连接" : "已连接");
|
||||||
|
closeServer();
|
||||||
|
GameClient = new WSClient(server.ip, server.port);
|
||||||
|
IsConnecting = true;
|
||||||
|
GameClient.OnError = (err) => {
|
||||||
|
IsConnecting = false;
|
||||||
|
if (err) {
|
||||||
|
if (err.isTrusted) err = "服务器没有响应,请稍后重试";
|
||||||
|
showLoader("<strong>连接失败:</strong>" + err + "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GameClient.OnConnect = () => {
|
||||||
|
IsConnecting = false;
|
||||||
|
if (!pid && !Process.player) {
|
||||||
|
showLoader('正在获取角色列表...');
|
||||||
|
SendCommand(Util.GetUserCookie(SessionKey) + " " + Util.GetUserCookie(SessionToken));
|
||||||
|
} else {
|
||||||
|
if (pid) {
|
||||||
|
SendCommand(Util.GetUserCookie(SessionKey) + " " + Util.GetUserCookie(SessionToken) + " " + pid + " " + server.ID);
|
||||||
|
} else {
|
||||||
|
SendCommand(Util.GetUserCookie(SessionKey) + " " + Util.GetUserCookie(SessionToken) + " " + Process.player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameClient.OnClose = () => {
|
||||||
|
IsConnecting = false;
|
||||||
|
if (ChangeServer) {
|
||||||
|
ChangeServer = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (GameClient.Connected()) return;
|
||||||
|
|
||||||
|
if (Process.player) {
|
||||||
|
Process.clear();
|
||||||
|
ReceiveMessage("<red>你的连接中断了...</red>");
|
||||||
|
} else {
|
||||||
|
setTimeout(() => {
|
||||||
|
hide2show($("#slist_panel"));
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GameClient.OnData = ReceiveData;
|
||||||
|
GameClient.OnMessage = ReceiveMessage;
|
||||||
|
GameClient.Connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isConnected() {
|
||||||
|
if (!GameClient) return false;
|
||||||
|
return GameClient.Connected();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SendCommand(cmd) {
|
||||||
|
if (IsConnecting) return;
|
||||||
|
if (!GameClient || !GameClient.Connected()) {
|
||||||
|
LastCommand = cmd;
|
||||||
|
ReceiveMessage("<red>连接中断,正在重新连线...</red>");
|
||||||
|
return connectServer(SelectedServer);
|
||||||
|
}
|
||||||
|
Dialog.extend.record(cmd);
|
||||||
|
GameClient.Send(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onLogin() {
|
||||||
|
if (LastCommand) {
|
||||||
|
SendCommand(LastCommand);
|
||||||
|
LastCommand = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ReceiveMessage(x) {
|
||||||
|
if (Dialog.extend.message_filter(x)) return;
|
||||||
|
Process.message.push(x);
|
||||||
|
Process.message.scroll2end();
|
||||||
|
Dialog.extend.trigger(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ReceiveData(data) {
|
||||||
|
if (Dialog.extend.data_filter(data)) return;
|
||||||
|
var func = Process[data.type];
|
||||||
|
func && func(data);
|
||||||
|
Dialog.extend.process(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function closeServer() {
|
||||||
|
if (GameClient && GameClient.Connected()) {
|
||||||
|
GameClient.Destroy();
|
||||||
|
}
|
||||||
|
GameClient = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showInputError(inp, msg) {
|
||||||
|
$(inp).focus().parent().find(".input-error").remove();
|
||||||
|
$("<div class='input-error'>" + msg + "</div>").insertAfter(inp);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hide2show(elem2, callback) {
|
||||||
|
var elem1;
|
||||||
|
var p = $(".login-content").children();
|
||||||
|
for (var i = 0; i < p.length; i++) {
|
||||||
|
if ($(p[i]).css("display") != "none") {
|
||||||
|
elem1 = $(p[i]); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!elem1) elem1 = $("#login_panel");
|
||||||
|
elem1.animate({ opacity: 0 }, "fast", function () {
|
||||||
|
elem1.hide();
|
||||||
|
if (elem2 == ".container") $(".login-content").hide();
|
||||||
|
else $(".login-content").show();
|
||||||
|
if (elem2) {
|
||||||
|
elem2 = $(elem2);
|
||||||
|
elem2.show();
|
||||||
|
elem2.css("opacity", "0");
|
||||||
|
elem2.animate({ opacity: 1 }, "slow", callback);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showLoader(msg, elem) {
|
||||||
|
var p = $(".login-content").children();
|
||||||
|
for (var i = 0; i < p.length; i++) {
|
||||||
|
if ($(p[i]).css("display") != "none"
|
||||||
|
&& !$(p[i]).is(".signinfo")) {
|
||||||
|
$(p[i]).hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var loader = $("#loader").css("opacity", 1).show();
|
||||||
|
loader.find("#loader_msg").html(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
let wsindex = 0;
|
||||||
|
export class WSClient {
|
||||||
|
constructor(ip, port) {
|
||||||
|
this.IP = ip;
|
||||||
|
this.Port = port;
|
||||||
|
}
|
||||||
|
Connect(callback) {
|
||||||
|
try {
|
||||||
|
var pol = location.protocol == "http:" ? "ws" : "wss";
|
||||||
|
this.ws = new WebSocket('ws://' + this.IP + ':' + this.Port);
|
||||||
|
this.ws.onopen = this.OnConnect;
|
||||||
|
this.ws.onclose = this.OnClose.bind(this);
|
||||||
|
this.ws.onerror = this.OnError;
|
||||||
|
this.ws.onmessage = this.OnReceived.bind(this);
|
||||||
|
this.index = wsindex++;
|
||||||
|
} catch (e) {
|
||||||
|
this.OnError && this.OnError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OnReceived(evt) {
|
||||||
|
if (!evt || !evt.data) return;
|
||||||
|
var data = evt.data;
|
||||||
|
if (data[0] == '{' || data[0] == '[') {
|
||||||
|
var func = new Function("return " + data + ";");
|
||||||
|
this.OnData(func());
|
||||||
|
} else {
|
||||||
|
this.OnMessage(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Send(text) {
|
||||||
|
try {
|
||||||
|
this.ws.send(text);
|
||||||
|
} catch (e) {
|
||||||
|
ReceiveMessage(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Destroy() {
|
||||||
|
this.ws.onclose = null;
|
||||||
|
this.ws.close();
|
||||||
|
}
|
||||||
|
Close() {
|
||||||
|
this.ws.close();
|
||||||
|
}
|
||||||
|
Connected() {
|
||||||
|
return this.ws && this.ws.readyState == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
400
src/combat.js
Normal file
400
src/combat.js
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
|
||||||
|
import Setting from './setting.js';
|
||||||
|
|
||||||
|
const Combat = {
|
||||||
|
IsShow: false,
|
||||||
|
Skills: null,
|
||||||
|
actions: null,
|
||||||
|
room_actions: null,
|
||||||
|
object_actions: null,
|
||||||
|
Scroll: function (e) {
|
||||||
|
let div = $(this)[0];
|
||||||
|
div.scrollLeft += e.originalEvent.deltaY;
|
||||||
|
},
|
||||||
|
Show: function () {
|
||||||
|
if (Combat.IsShow) return Combat.Hide();
|
||||||
|
if (!this.object_actions) SendCommand("actions");
|
||||||
|
Combat.IsShow = true;
|
||||||
|
if (!Setting.off_hp) {
|
||||||
|
$(".room-item>.item-status").show();
|
||||||
|
}
|
||||||
|
$(".combat-panel").removeClass("hide");
|
||||||
|
this.refActions();
|
||||||
|
Process.message.scroll2end();
|
||||||
|
// $(".right-bar")[0].style.bottom = ($(".combat-panel").height() + $(".bottom-bar").height()) + "px";
|
||||||
|
},
|
||||||
|
Hide: function () {
|
||||||
|
Combat.IsShow = false;
|
||||||
|
if (!Setting.off_hp) {
|
||||||
|
$(".room-item>.item-status").hide();
|
||||||
|
}
|
||||||
|
$(".combat-panel").addClass("hide");
|
||||||
|
// $(".right-bar")[0].style.bottom = null;
|
||||||
|
}, ShowRoomCommands: function (room) {
|
||||||
|
|
||||||
|
this.room = room;
|
||||||
|
this.room_actions = room.commands;
|
||||||
|
if (!Combat.IsShow) return;
|
||||||
|
this.refActions();
|
||||||
|
// let panel = $(".room-commands");
|
||||||
|
// if (this.room_actions) {
|
||||||
|
// for (let item of this.room_actions) {
|
||||||
|
// panel.find('[cmd="' + item.cmd + '"]').remove();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// let cmds = room.commands ?? [];
|
||||||
|
// Dialog.extend.append(cmds, 'action', room);
|
||||||
|
// this.room = room;
|
||||||
|
// this.room_actions = cmds;
|
||||||
|
// if (!Combat.IsShow) return;
|
||||||
|
// this.append_items(cmds, panel);
|
||||||
|
},
|
||||||
|
def_actions: [{ cmd: "dazuo", name: "打坐" },
|
||||||
|
{ cmd: "liaoshang", name: "疗伤" }],
|
||||||
|
|
||||||
|
refActions: function () {
|
||||||
|
let actions = [...this.def_actions];
|
||||||
|
this.actions = actions;
|
||||||
|
if (this.room) {
|
||||||
|
Dialog.extend.append(actions, 'action', this.room);
|
||||||
|
}
|
||||||
|
this.create_actions();
|
||||||
|
},
|
||||||
|
ShowActions: function (data) {
|
||||||
|
this.object_actions = data.actions ?? [];
|
||||||
|
this.refActions();
|
||||||
|
if (data.skills)
|
||||||
|
this.ShowPFM(data);
|
||||||
|
},
|
||||||
|
ShowPFM: function (data) {
|
||||||
|
this.Skills = data.skills || [];
|
||||||
|
this.create_skillItems(data.skills);
|
||||||
|
},
|
||||||
|
append_items: function (items, parent) {
|
||||||
|
if (!items) return;
|
||||||
|
for (let item of items) {
|
||||||
|
item.elem =
|
||||||
|
$(`<span class='act-item' cmd='${item.cmd}'>${item.name}</span>`)
|
||||||
|
.appendTo(parent);
|
||||||
|
if (item.disper > 0) {
|
||||||
|
item.elem.css("backgroundSize", item.disper + "% 100%");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, create_actions: function (items) {
|
||||||
|
var panel = $(".room-commands").empty();
|
||||||
|
this.append_items(this.actions, panel);
|
||||||
|
this.append_items(this.object_actions, panel);
|
||||||
|
this.append_items(this.room_actions, panel);
|
||||||
|
|
||||||
|
}, DisObj: function (data) {
|
||||||
|
if (!this.object_actions) return;
|
||||||
|
var cmd = data.act ? data.id : "use " + data.id;
|
||||||
|
for (var i = 0; i < this.object_actions.length; i++) {
|
||||||
|
var item = this.object_actions[i];
|
||||||
|
if (item.cmd === cmd) {
|
||||||
|
if (data.remove) {
|
||||||
|
this.object_actions.splice(i, 1);
|
||||||
|
return item.elem.remove();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.ANI_OBJ(item, data.time, data.time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, AddObj: function (id, name) {
|
||||||
|
if (!this.object_actions) return;
|
||||||
|
var cmd = "use " + id;
|
||||||
|
for (var i = 0; i < this.object_actions.length; i++) {
|
||||||
|
var item = this.object_actions[i];
|
||||||
|
if (item.cmd == cmd) return;
|
||||||
|
}
|
||||||
|
this.object_actions.push({
|
||||||
|
cmd: "use " + id,
|
||||||
|
name: name.replace(/\<.+?\>/g, "")
|
||||||
|
});
|
||||||
|
this.create_actions();
|
||||||
|
}
|
||||||
|
, ANI_OBJ: function (obj, time, ani_time) {
|
||||||
|
|
||||||
|
let elem = obj.elem;
|
||||||
|
if (!elem) return;
|
||||||
|
var cur_per = ani_time * 100 / time;
|
||||||
|
if (cur_per > 0) {
|
||||||
|
elem.css("backgroundSize", cur_per + "% 100%");
|
||||||
|
} else {
|
||||||
|
if (cur_per < 0) cur_per = 0;
|
||||||
|
elem.css("backgroundSize", "0% 100%");
|
||||||
|
}
|
||||||
|
obj.disper = cur_per;
|
||||||
|
setTimeout(Combat.ANI_OBJ, 1000, obj, time, ani_time - 1000);
|
||||||
|
}
|
||||||
|
, create_skillItems: function (items) {
|
||||||
|
var elem = $(".combat-commands").empty();
|
||||||
|
if (!items.length) return;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var html = [];
|
||||||
|
html.push("<span class='pfm-item' pid='" + items[i].id + "'>");
|
||||||
|
html.push(items[i].name);
|
||||||
|
// html.push("<span class='shadow'></span>");
|
||||||
|
html.push("</span>");
|
||||||
|
// items[i].shadow = $(html.join("")).appendTo(elem).find(".shadow")[0];
|
||||||
|
items[i].elem = $(html.join("")).appendTo(elem);
|
||||||
|
}
|
||||||
|
}, ChangeDistime: function (data) {
|
||||||
|
var pfmid = data.id.replace("/", ".");
|
||||||
|
for (var j = 0; j < Combat.dis_pfms.length; j++) {
|
||||||
|
if (Combat.dis_pfms[j].id == pfmid) {
|
||||||
|
Combat.dis_pfms[j].ani_time += data.time;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, ClearDistime: function (data) {
|
||||||
|
if (!Combat.dis_pfms) return;
|
||||||
|
var pfmid = data.id ? data.id.replace("/", ".") : data.id;
|
||||||
|
for (var j = 0; j < Combat.dis_pfms.length; j++) {
|
||||||
|
if (!pfmid || Combat.dis_pfms[j].id == pfmid) {
|
||||||
|
Combat.dis_pfms[j].ani_time = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}, redisable: function () {
|
||||||
|
Combat.dis_pfms = [];
|
||||||
|
for (var i = 0; i < Combat.Skills.length; i++) {
|
||||||
|
var skill = Combat.Skills[i];
|
||||||
|
Combat.dis_pfms.push({
|
||||||
|
id: skill.id,
|
||||||
|
distime: skill.distime,
|
||||||
|
ani_time: skill.distime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!Combat.time_handler) {
|
||||||
|
Combat.ANI_PFM();
|
||||||
|
}
|
||||||
|
}, On_Perform: function (data) {
|
||||||
|
if (!this.Skills) return;
|
||||||
|
if (data.id === 'all' && !data.rtime) return this.redisable();
|
||||||
|
if (data.id)
|
||||||
|
data.id = data.id.replace('/', '.');
|
||||||
|
data.rtime = data.rtime || 0;
|
||||||
|
data.distime = data.distime || 0;
|
||||||
|
if (!this.dis_pfms) this.dis_pfms = [];
|
||||||
|
for (var i = 0; i < this.dis_pfms.length; i++) {
|
||||||
|
|
||||||
|
if (this.dis_pfms[i].id == data.id) {
|
||||||
|
data.id = null;
|
||||||
|
this.dis_pfms[i].distime = data.distime;
|
||||||
|
this.dis_pfms[i].ani_time = data.distime;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (this.dis_pfms[i].ani_time < data.rtime) {
|
||||||
|
this.dis_pfms[i].ani_time = data.rtime;
|
||||||
|
this.dis_pfms[i].distime = data.rtime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.id) {
|
||||||
|
this.dis_pfms.push({
|
||||||
|
id: data.id,
|
||||||
|
distime: data.distime,
|
||||||
|
ani_time: data.distime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Combat.ani_time = Combat.ani_time ?? 0;
|
||||||
|
if (data.rtime > Combat.ani_time) {
|
||||||
|
Combat.distime = data.rtime;
|
||||||
|
Combat.ani_time = data.rtime;
|
||||||
|
}
|
||||||
|
if (!this.time_handler) {
|
||||||
|
Combat.ANI_PFM();
|
||||||
|
}
|
||||||
|
}, PFM_INTERVAL: 300
|
||||||
|
, ANI_PFM: function () {
|
||||||
|
var p = 0;
|
||||||
|
if (Combat.distime > 0)
|
||||||
|
p = Combat.ani_time * 100 / Combat.distime;
|
||||||
|
for (var i = 0; i < Combat.Skills.length; i++) {
|
||||||
|
var skill = Combat.Skills[i];
|
||||||
|
var cur_per = p;
|
||||||
|
for (var j = 0; j < Combat.dis_pfms.length; j++) {
|
||||||
|
if (Combat.dis_pfms[j].id == skill.id && Combat.dis_pfms[j].distime) {
|
||||||
|
cur_per = Combat.dis_pfms[j].ani_time * 100 / Combat.dis_pfms[j].distime;
|
||||||
|
if (cur_per < 0) {
|
||||||
|
Combat.dis_pfms.splice(j, 1);
|
||||||
|
} else {
|
||||||
|
Combat.dis_pfms[j].ani_time -= Combat.PFM_INTERVAL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cur_per > 0) {
|
||||||
|
if (cur_per < 0) cur_per = 0;
|
||||||
|
skill.elem.css("backgroundSize", cur_per + "% 100%");
|
||||||
|
} else {
|
||||||
|
skill.elem.css("backgroundSize", "0% 100%");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Combat.ani_time > 0 || Combat.dis_pfms.length) {
|
||||||
|
Combat.time_handler = setTimeout(Combat.ANI_PFM, Combat.PFM_INTERVAL);
|
||||||
|
} else {
|
||||||
|
Combat.time_handler = null;
|
||||||
|
}
|
||||||
|
Combat.ani_time -= Combat.PFM_INTERVAL;
|
||||||
|
},
|
||||||
|
StatusChanged: function (data) {
|
||||||
|
var items = $(".room-item");
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var item = $(items[i]);
|
||||||
|
if (item.attr("itemid") == data.id) {
|
||||||
|
this.UpdaeBar(data, "mp", item);
|
||||||
|
this.UpdaeBar(data, "hp", item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, UpdaeBar: function (data, type, item) {
|
||||||
|
var val = data[type], max = 0;
|
||||||
|
if (val == undefined) return;
|
||||||
|
|
||||||
|
var bar = item.find("." + type + ">.progress-bar");
|
||||||
|
if (data["max_" + type]) {
|
||||||
|
max = data["max_" + type];
|
||||||
|
bar.attr("max", max);
|
||||||
|
} else {
|
||||||
|
max = parseInt(bar.attr("max"));
|
||||||
|
}
|
||||||
|
if (Setting.show_hpnum && type == "hp") {
|
||||||
|
|
||||||
|
item.find(".progress-num").html("[" + Process.get_hpnum(val, max) + "<nor>/</nor><hiy>" + max + '</hiy>]');
|
||||||
|
}
|
||||||
|
bar.css("width", Combat.CountWidth(val, max) + "%");
|
||||||
|
if (Setting.show_damage && data.damage && data.id != Process.player) {
|
||||||
|
var per = 0;
|
||||||
|
if (data.damage == -1) {
|
||||||
|
per = parseInt((max - val) * 1000 / max) / 10;
|
||||||
|
} else {
|
||||||
|
per = parseInt(data.damage * 1000 / max) / 10;
|
||||||
|
}
|
||||||
|
bar = item.find(".item-damage");
|
||||||
|
if (!bar.length) {
|
||||||
|
bar = $('<span class="item-damage">[<hiy>0%</hiy>]<span>').appendTo(item.find('.item-name'));
|
||||||
|
}
|
||||||
|
bar.html("[<hiy>" + per + '%</hiy>]');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
, CountWidth: function (d1, d2) {
|
||||||
|
if (d2 == 0) return 0;
|
||||||
|
var d = d1 * 100 / d2;
|
||||||
|
if (d >= 100) return 100;
|
||||||
|
if (d < 0) return 0;
|
||||||
|
return d;
|
||||||
|
}, Perform: function () {
|
||||||
|
var elem = $(this);
|
||||||
|
if (elem.is("disable")) return;
|
||||||
|
var pfmid = elem.attr("pid");
|
||||||
|
if (!pfmid) return;
|
||||||
|
SendCommand("perform " + pfmid);
|
||||||
|
// Combat.On_Perform({ id: pfmid });
|
||||||
|
},
|
||||||
|
STATUS: {},
|
||||||
|
AppendStatusItem: function (id, elem, status) {
|
||||||
|
var stitem = { elem: elem, items: {} };
|
||||||
|
if (status) {
|
||||||
|
for (var i = 0; i < status.length; i++) {
|
||||||
|
this.StatusItem_add(stitem, status[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.STATUS[id] = stitem;
|
||||||
|
}
|
||||||
|
, StatusItemChanged: function (data) {
|
||||||
|
|
||||||
|
var func = Combat["StatusItem_" + data.action];
|
||||||
|
func && func.call(Combat, this.STATUS[data.id], data);
|
||||||
|
|
||||||
|
}, StatusItem_add: function (statu_item, item) {
|
||||||
|
if (!statu_item) return;
|
||||||
|
var str = [];
|
||||||
|
str.push('<span class="status-item');
|
||||||
|
if (item.downside) {
|
||||||
|
str.push(" downside");
|
||||||
|
}
|
||||||
|
str.push('" sid="');
|
||||||
|
str.push(item.sid);
|
||||||
|
str.push('">');
|
||||||
|
str.push(item.name);
|
||||||
|
if (item.count != undefined) {
|
||||||
|
str.push("x");
|
||||||
|
str.push(item.count);
|
||||||
|
}
|
||||||
|
str.push('<span class="shadow"></span></span>');
|
||||||
|
statu_item.items[item.sid] = {
|
||||||
|
elem: $(str.join("")).appendTo(statu_item.elem)[0],
|
||||||
|
name: item.name,
|
||||||
|
count: item.count,
|
||||||
|
duration: item.duration,
|
||||||
|
anitime: item.duration - (item.overtime || 0)
|
||||||
|
};
|
||||||
|
if (item.duration > 0)
|
||||||
|
Combat.StatusItemANI(statu_item.items[item.sid]);
|
||||||
|
},
|
||||||
|
StatusItem_remove: function (player_status, data) {
|
||||||
|
if (!player_status) return;
|
||||||
|
var ids = data.sid;
|
||||||
|
if (typeof ids == "string") ids = [ids];
|
||||||
|
for (var i = 0; i < ids.length; i++) {
|
||||||
|
var item = player_status.items[ids[i]];
|
||||||
|
if (item) {
|
||||||
|
$(item.elem).remove();
|
||||||
|
item.handler && clearTimeout(item.handler);
|
||||||
|
delete player_status.items[ids[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
StatusItem_refresh: function (player_status, data) {
|
||||||
|
if (!player_status) return;
|
||||||
|
var item = player_status.items[data.sid];
|
||||||
|
if (!item) return;
|
||||||
|
var text = item.elem.firstChild;
|
||||||
|
var shadow = item.elem.lastChild;
|
||||||
|
item.count = data.count;
|
||||||
|
item.elem.innerHTML = item.name + "x" + item.count + shadow.outerHTML;
|
||||||
|
item.handler && clearTimeout(item.handler);
|
||||||
|
item.anitime = item.duration;
|
||||||
|
Combat.StatusItemANI(item);
|
||||||
|
}, StatusItem_override: function (player_status, data) {
|
||||||
|
|
||||||
|
var item = player_status.items[data.sid];
|
||||||
|
if (!item) return;
|
||||||
|
item.handler && clearTimeout(item.handler);
|
||||||
|
item.anitime = item.duration;
|
||||||
|
Combat.StatusItemANI(item);
|
||||||
|
},
|
||||||
|
StatusItem_clear: function (player_status, data) {
|
||||||
|
if (!player_status) return;
|
||||||
|
for (var sid in player_status.items) {
|
||||||
|
var item = player_status.items[sid];
|
||||||
|
if (item) {
|
||||||
|
$(item.elem).remove();
|
||||||
|
clearTimeout(item.handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player_status.items = {};
|
||||||
|
},
|
||||||
|
StatusItemANI: function (item) {
|
||||||
|
var shadow = item.elem.lastChild;
|
||||||
|
var p = item.anitime * 100 / item.duration;
|
||||||
|
if (p < 0) p = 0;
|
||||||
|
shadow.style.right = p + "%";
|
||||||
|
item.anitime = item.anitime - 1000;
|
||||||
|
if (p > 0) {
|
||||||
|
item.handler = setTimeout(Combat.StatusItemANI, 1000, item);
|
||||||
|
} else {
|
||||||
|
//elem.parent().remove();
|
||||||
|
item.handler = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
export default Combat;
|
||||||
315
src/confirm.js
Normal file
315
src/confirm.js
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export const Confirm = {
|
||||||
|
DEFAULT: {
|
||||||
|
|
||||||
|
onOK: function () { },
|
||||||
|
footer: true,
|
||||||
|
|
||||||
|
btn_text: "确认"
|
||||||
|
},
|
||||||
|
Show: function (par) {
|
||||||
|
this.Init();
|
||||||
|
|
||||||
|
|
||||||
|
this.Parameter = Object.assign({}, this.DEFAULT, par);
|
||||||
|
this.content.empty().append(this.Parameter.content);
|
||||||
|
this.element.show();
|
||||||
|
if (this.Parameter.footer) {
|
||||||
|
this.btn.show();
|
||||||
|
this.btn.find(".btn-text").html(this.Parameter.btn_text);
|
||||||
|
} else {
|
||||||
|
this.btn.hide();
|
||||||
|
}
|
||||||
|
this.isShow = true;
|
||||||
|
}, Close: function (isok) {
|
||||||
|
if (!Confirm.isShow) return;
|
||||||
|
Confirm.element.hide();
|
||||||
|
Confirm.isShow = false;
|
||||||
|
if (!isok && this.Parameter.onCancle)
|
||||||
|
this.Parameter.onCancle();
|
||||||
|
},
|
||||||
|
Init: function () {
|
||||||
|
if (this._init) return;
|
||||||
|
this.element = $(`<div class="dialog-confirm" style="display:none;">
|
||||||
|
<div class="dialog-content"></div>
|
||||||
|
<span class="dialog-btn btn-ok"><span class="glyphicon glyphicon-ok-circle btn-icon"></span><span
|
||||||
|
class="btn-text">确认</span></span>
|
||||||
|
</div>`).appendTo(document.body);
|
||||||
|
this.content = this.element.find(".dialog-content");
|
||||||
|
this.btn = this.element.find(".dialog-btn");
|
||||||
|
this.element.on("click", ".btn-ok", function (e) {
|
||||||
|
if (Confirm.Parameter.content === Confirm.count_element) {
|
||||||
|
var text = Confirm.count_element.find("input");
|
||||||
|
var v = parseInt(text.val());
|
||||||
|
if (v.toString() == "NaN") v = 0;
|
||||||
|
if (v > Confirm.max_count) v = Confirm.max_count;
|
||||||
|
Confirm.Parameter.onOK(v);
|
||||||
|
} else {
|
||||||
|
Confirm.Parameter.onOK();
|
||||||
|
}
|
||||||
|
Confirm.Close(true);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
this.element.on("click", ".btn", function (e) {
|
||||||
|
var count = Confirm.max_count || 1000;
|
||||||
|
var elem = $(e.target);
|
||||||
|
var type = parseInt(elem.attr("ac"));
|
||||||
|
var text = elem.parent().find("input");
|
||||||
|
var v = parseInt(text.val());
|
||||||
|
if (v.toString() == "NaN") v = 0;
|
||||||
|
if (type == -10) {
|
||||||
|
v -= 10;
|
||||||
|
} else if (type == 10) {
|
||||||
|
if (v == 1) v = 0;
|
||||||
|
v += 10;
|
||||||
|
} else if (type == 1) {
|
||||||
|
v = count;
|
||||||
|
} else {
|
||||||
|
v = 1;
|
||||||
|
}
|
||||||
|
if (v < 1) v = 1;
|
||||||
|
else if (v > count) v = count;
|
||||||
|
text.val(v);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
this._init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
, Process: function (pars) {
|
||||||
|
var cmd = pars[1];
|
||||||
|
var npc = "";
|
||||||
|
if (cmd == "dc") {
|
||||||
|
cmd = pars[3];
|
||||||
|
npc = pars.splice(1, 2);
|
||||||
|
npc = npc[0] + " " + npc[1] + " ";
|
||||||
|
}
|
||||||
|
var func = this["Show_" + cmd];
|
||||||
|
func && func.call(this, pars, npc);
|
||||||
|
}, get_countelement: function (count, maxcount) {
|
||||||
|
if (!this.count_element) {
|
||||||
|
this.count_element = $('<div class="confirm-count"><span class="btn" ac="0">最少</span><span ac="-10" class="btn">减10</span><input type="text" value="1" /><span class="btn" ac="10" >加10</span><span class="btn" ac="1" >最多</span></div>');
|
||||||
|
|
||||||
|
}
|
||||||
|
if (count) this.count_element.find("input").val(count);
|
||||||
|
else this.count_element.find("input").val(1);
|
||||||
|
if (maxcount) maxcount = parseInt(maxcount);
|
||||||
|
this.max_count = maxcount || 1000;
|
||||||
|
return this.count_element;
|
||||||
|
}, Show_shop: function (p, maxcount) {
|
||||||
|
var objid = p[2];
|
||||||
|
if (!objid) return;
|
||||||
|
var obj = Dialog.shop.get_item(objid);
|
||||||
|
if (!obj) return;
|
||||||
|
let count = p[3] ? parseInt(p[3]) : -1;
|
||||||
|
this.Show({
|
||||||
|
content: this.get_countelement(1, count == -1 ? 9999 : count),
|
||||||
|
btn_text: "购买" + obj.name,
|
||||||
|
onOK: function (v) {
|
||||||
|
if (!(v > 0)) return;
|
||||||
|
SendCommand("shop " + objid + " " + v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
Show_buy: function (p) {
|
||||||
|
var objid = p[3];
|
||||||
|
if (!objid) return;
|
||||||
|
var count = parseInt(p[2]);
|
||||||
|
|
||||||
|
this.Show({
|
||||||
|
content: this.get_countelement(1, count == -1 ? 9999 : count),
|
||||||
|
btn_text: "购买",
|
||||||
|
onOK: function (v) {
|
||||||
|
if (!(v > 0)) return;
|
||||||
|
SendCommand("buy " + v + " " + objid + " from " + p[5]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
Show_greet: function (p) {
|
||||||
|
this.Show({
|
||||||
|
content: this.get_countelement(1, 99),
|
||||||
|
btn_text: "送花",
|
||||||
|
onOK: function (v) {
|
||||||
|
if (!(v > 0)) return;
|
||||||
|
SendCommand("greet " + v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, Show_sell: function (p) {
|
||||||
|
var objid = p[3];
|
||||||
|
if (!objid) return;
|
||||||
|
|
||||||
|
this.Show({
|
||||||
|
content: this.get_countelement(p[2], p[2]),
|
||||||
|
btn_text: "卖出",
|
||||||
|
onOK: function (v) {
|
||||||
|
if (!(v > 0)) return;
|
||||||
|
SendCommand("sell " + v + " " + objid + " to " + p[5]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, Show_store: function (p) {
|
||||||
|
var objid = p[3];
|
||||||
|
if (!objid) return;
|
||||||
|
if (p[2] == 1) {
|
||||||
|
return SendCommand((Dialog.list.is_bookshelf ? "sj " : "") + "store " + objid);
|
||||||
|
}
|
||||||
|
this.Show({
|
||||||
|
content: this.get_countelement(p[2], p[2]),
|
||||||
|
btn_text: "存入",
|
||||||
|
onOK: function (v) {
|
||||||
|
if (!(v > 0)) return;
|
||||||
|
SendCommand((Dialog.list.is_bookshelf ? "sj " : "") + "store " + v + " " + objid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, Show_fenjie: function (p, npc) {
|
||||||
|
var objid = p[2];
|
||||||
|
if (!objid) return;
|
||||||
|
var obj = Dialog.pack.isShow ? Dialog.pack.get_item(objid) : Dialog.pack2.get_item(objid);
|
||||||
|
if (!obj) return;
|
||||||
|
if (obj.name.indexOf("★") == -1) return SendCommand("fenjie " + objid);
|
||||||
|
this.Show({
|
||||||
|
content: "是否确认分解" + obj.name + "?",
|
||||||
|
btn_text: "确认分解",
|
||||||
|
onOK: function () {
|
||||||
|
SendCommand(npc + "fenjie " + objid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}, Show_qu: function (p) {
|
||||||
|
var objid = p[2];
|
||||||
|
if (!objid) return;
|
||||||
|
var obj = Dialog.list.find_item(3, objid);
|
||||||
|
if (!obj) return;
|
||||||
|
if (obj.count === 1) {
|
||||||
|
return SendCommand((Dialog.list.is_bookshelf ? "sj " : "") + "qu 1 " + objid);
|
||||||
|
}
|
||||||
|
this.Show({
|
||||||
|
content: this.get_countelement(obj.count, obj.count),
|
||||||
|
btn_text: "取出",
|
||||||
|
onOK: function (v) {
|
||||||
|
if (!(v > 0)) return;
|
||||||
|
SendCommand((Dialog.list.is_bookshelf ? "sj " : "") + "qu " + v + " " + objid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, Show_drop: function (p, npc) {
|
||||||
|
var objid = p[3];
|
||||||
|
if (!objid) return;
|
||||||
|
var obj = Dialog.pack.isShow ? Dialog.pack.get_item(objid) : Dialog.pack2.get_item(objid);
|
||||||
|
if (!obj) return;
|
||||||
|
this.Show({
|
||||||
|
content: p[2] == 1 ? "是否确认丢掉" + obj.name + "?" : this.get_countelement(p[2], p[2]),
|
||||||
|
btn_text: "丢掉",
|
||||||
|
onOK: function (v) {
|
||||||
|
if (p[2] == 1) {
|
||||||
|
return SendCommand(npc + "drop " + objid);
|
||||||
|
}
|
||||||
|
if (!(v > 0)) return;
|
||||||
|
SendCommand(npc + "drop " + v + " " + objid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, Show_give: function (p, npc) {
|
||||||
|
var objid = p[4];
|
||||||
|
if (!objid) return;
|
||||||
|
var obj = Dialog.pack2.get_item(objid);
|
||||||
|
if (!obj) return;
|
||||||
|
if (obj.count == 1) return SendCommand(npc + "give " + Process.player + " 1 " + objid);
|
||||||
|
this.Show({
|
||||||
|
content: this.get_countelement(obj.count, obj.count),
|
||||||
|
btn_text: "拿来",
|
||||||
|
onOK: function (v) {
|
||||||
|
if (!(v > 0)) return;
|
||||||
|
SendCommand(npc + "give " + Process.player + " " + v + " " + objid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, Show_trade_add: function (obj) {
|
||||||
|
if (!obj) return;
|
||||||
|
this.Show({
|
||||||
|
content: this.get_countelement(obj.count, obj.count),
|
||||||
|
btn_text: "确定",
|
||||||
|
onOK: function (v) {
|
||||||
|
if (!(v > 0)) return;
|
||||||
|
var moveobj = Util.Clone(obj);
|
||||||
|
moveobj.count = v;
|
||||||
|
Dialog.trade.add_trade(moveobj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, Show_fangqi: function (p, npc) {
|
||||||
|
var objid = p[2];
|
||||||
|
if (!objid) return;
|
||||||
|
var skill = npc ? Dialog.master.skills[objid] : Dialog.skills.skills[objid];
|
||||||
|
if (!skill) return;
|
||||||
|
this.Show({
|
||||||
|
content: "是否确认放弃技能" + skill.name + "?",
|
||||||
|
onOK: function () {
|
||||||
|
SendCommand(npc + "fangqi " + objid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, Show_combine: function (p, npc) {
|
||||||
|
var objid = p[2];
|
||||||
|
if (!objid) return;
|
||||||
|
var obj = Dialog.pack.get_item(objid);
|
||||||
|
if (!obj) return;
|
||||||
|
var com = parseInt(p[3]);
|
||||||
|
if (!com) return;
|
||||||
|
var max_count = parseInt(obj.count / com);
|
||||||
|
if (max_count == 1) {
|
||||||
|
return SendCommand("combine " + objid);
|
||||||
|
}
|
||||||
|
this.Show({
|
||||||
|
content: this.get_countelement(max_count),
|
||||||
|
btn_text: "合成",
|
||||||
|
onOK: function (v) {
|
||||||
|
if (!(v > 0)) return;
|
||||||
|
SendCommand(npc + "combine " + objid + " " + v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
, Show_pay: function () {
|
||||||
|
|
||||||
|
SendCommand('pay 0 ' + (/mobile/i.test(navigator.userAgent) ? "m" : "c"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const Warn = {
|
||||||
|
Elemes: [],
|
||||||
|
Show: function (data) {
|
||||||
|
var html = ["<div class='warn-dialog'>"];
|
||||||
|
|
||||||
|
html.push("<div class='warn-content'>");
|
||||||
|
html.push(data.content);
|
||||||
|
html.push("</div>");
|
||||||
|
html.push("<div class='item-commands'>");
|
||||||
|
for (var i = 0; i < data.cmds.length; i++) {
|
||||||
|
var cmd = data.cmds[i];
|
||||||
|
html.push("<span cmd='");
|
||||||
|
html.push(cmd.cmd);
|
||||||
|
html.push("'>");
|
||||||
|
html.push(cmd.name);
|
||||||
|
html.push("</span>");
|
||||||
|
}
|
||||||
|
html.push("</div>");
|
||||||
|
var elem = $(html.join("")).appendTo(".bottom-bar");
|
||||||
|
this.Elemes.push(elem);
|
||||||
|
this.Settop();
|
||||||
|
var func = this.Close.bind(this, elem);
|
||||||
|
if (data.time) {
|
||||||
|
window.setTimeout(func, data.time);
|
||||||
|
}
|
||||||
|
elem.on("click", "span", func);
|
||||||
|
}
|
||||||
|
, Close: function (elem) {
|
||||||
|
if (this.Elemes.indexOf(elem) > -1) {
|
||||||
|
elem.remove();
|
||||||
|
this.Elemes.Remove(elem);
|
||||||
|
this.Settop();
|
||||||
|
}
|
||||||
|
}, Settop: function () {
|
||||||
|
var height = $('.bottom-bar').height() + 8;
|
||||||
|
for (var i = 0; i < Warn.Elemes.length; i++) {
|
||||||
|
var elem = Warn.Elemes[i];
|
||||||
|
elem.css("bottom", height);
|
||||||
|
height += elem.height() + 14;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
137
src/dialog/base.js
Normal file
137
src/dialog/base.js
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
|
||||||
|
import DialogScore from './score.js';
|
||||||
|
import DialogMap from './map.js';
|
||||||
|
import DialogKeys from './keys.js';
|
||||||
|
import DialogSetting from './setting.js';
|
||||||
|
import DialogExtend from './extend.js';
|
||||||
|
import DialogChannel from './channel.js';
|
||||||
|
import DialogPack from './packet.js';
|
||||||
|
import DialogSkills from './skills.js';
|
||||||
|
import DialogTasks from './tasks.js';
|
||||||
|
import DialogShop from './shop.js';
|
||||||
|
import DialogMessage from './message.js';
|
||||||
|
import DialogStats from './stats.js';
|
||||||
|
import DialogJh from './jh.js';
|
||||||
|
import DialogRelation from './relation.js';
|
||||||
|
import DialogTeam from './team.js';
|
||||||
|
import DialogParty from './party.js';
|
||||||
|
import DialogTrade from './trade.js';
|
||||||
|
import DialogEvents from './events.js';
|
||||||
|
import DialogPm from './paimai.js';
|
||||||
|
import DialogPack2 from './packet2.js';
|
||||||
|
import DialogMaster from './master.js';
|
||||||
|
import DialogList from './list.js';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const Dialog = {
|
||||||
|
isShow: false,
|
||||||
|
curItem: null,
|
||||||
|
score: DialogScore,
|
||||||
|
map: DialogMap,
|
||||||
|
keys: DialogKeys,
|
||||||
|
setting: DialogSetting,
|
||||||
|
extend: DialogExtend,
|
||||||
|
channel: DialogChannel,
|
||||||
|
pack: DialogPack,
|
||||||
|
skills: DialogSkills,
|
||||||
|
tasks: DialogTasks,
|
||||||
|
shop: DialogShop,
|
||||||
|
message: DialogMessage,
|
||||||
|
stats: DialogStats,
|
||||||
|
jh: DialogJh,
|
||||||
|
relation: DialogRelation,
|
||||||
|
team: DialogTeam,
|
||||||
|
party: DialogParty,
|
||||||
|
trade: DialogTrade,
|
||||||
|
events: DialogEvents,
|
||||||
|
pm: DialogPm,
|
||||||
|
pack2: DialogPack2,
|
||||||
|
master: DialogMaster,
|
||||||
|
list: DialogList,
|
||||||
|
|
||||||
|
show: function (name, data) {
|
||||||
|
if (!name) return;
|
||||||
|
const dialog = this[name];
|
||||||
|
if (!dialog) throw new Error('没有' + name);
|
||||||
|
if (!dialog.created) {
|
||||||
|
dialog.init();
|
||||||
|
dialog.created = true;
|
||||||
|
}
|
||||||
|
if (!data) {
|
||||||
|
if (this.isShow && name == this.curItem) return this.hide();
|
||||||
|
if (this.curItem && name != this.curItem) {
|
||||||
|
Dialog[Dialog.curItem].close && Dialog[Dialog.curItem].close();
|
||||||
|
Dialog[Dialog.curItem].isShow = false;
|
||||||
|
Dialog.contentElement.empty();
|
||||||
|
}
|
||||||
|
this.init();
|
||||||
|
this.curItem = name;
|
||||||
|
dialog.show(data);
|
||||||
|
Process.message.scroll2end();
|
||||||
|
} else {
|
||||||
|
dialog.onData(data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
select: function (name) {
|
||||||
|
if (this.isShow && name == this.curItem) return this.hide();
|
||||||
|
if (this.curItem && name != this.curItem) {
|
||||||
|
Dialog[Dialog.curItem].close && Dialog[Dialog.curItem].close();
|
||||||
|
Dialog[Dialog.curItem].isShow = false;
|
||||||
|
Dialog.contentElement.empty();
|
||||||
|
}
|
||||||
|
this.init();
|
||||||
|
this.curItem = name;
|
||||||
|
},
|
||||||
|
init: function () {
|
||||||
|
if (this.isShow) return;
|
||||||
|
if (!this.isInit) {
|
||||||
|
this.contentElement = $(".dialog>.dialog-content");
|
||||||
|
this.titleElement = $(".dialog>.dialog-header>.dialog-title");
|
||||||
|
this.iconElement = $(".dialog>.dialog-header>.dialog-icon");
|
||||||
|
this.footerElement = $(".dialog>.dialog-footer")
|
||||||
|
.on("click", ".footer-item", Dialog.footerClick);
|
||||||
|
this.hiddenElement = $(".hidden-item");
|
||||||
|
this.element = $(".dialog");
|
||||||
|
$(".dialog>.dialog-header>.dialog-close").on("click", Dialog.hide);
|
||||||
|
this.isInit = true;
|
||||||
|
}
|
||||||
|
$(".content-room").addClass("hide");
|
||||||
|
this.element.removeClass("hide");
|
||||||
|
this.isShow = true;
|
||||||
|
},
|
||||||
|
hide: function () {
|
||||||
|
if (Dialog[Dialog.curItem].hide && Dialog[Dialog.curItem].hide() == false) return;
|
||||||
|
Dialog.close();
|
||||||
|
},
|
||||||
|
footerClick: function () {
|
||||||
|
var elem = $(this);
|
||||||
|
if (elem.is(".select")) return;
|
||||||
|
var cmd = elem.attr("for");
|
||||||
|
elem.parent().find(".footer-item.select").removeClass("select");
|
||||||
|
elem.addClass("select");
|
||||||
|
Dialog[Dialog.curItem].footerChanged(cmd, elem);
|
||||||
|
},
|
||||||
|
title: function (title) {
|
||||||
|
Dialog.titleElement.html(title);
|
||||||
|
},
|
||||||
|
icon: function (css) {
|
||||||
|
this.iconElement.attr("class", "dialog-icon glyphicon glyphicon-" + css);
|
||||||
|
},
|
||||||
|
footer: function (html) {
|
||||||
|
html ? this.footerElement.html(html) : this.footerElement.empty();
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
if (!Dialog.isShow) return;
|
||||||
|
Dialog.isShow = false;
|
||||||
|
$(".content-room").removeClass("hide");
|
||||||
|
Dialog.element.addClass("hide");
|
||||||
|
},
|
||||||
|
injectStyle: function (css) {
|
||||||
|
const style = document.createElement("style");
|
||||||
|
style.textContent = css;
|
||||||
|
document.head.append(style);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Dialog;
|
||||||
118
src/dialog/channel.js
Normal file
118
src/dialog/channel.js
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
footer: [["全部", ""], ["世界", "chat"], ["队伍", "tm"], ["门派", "fam"], ["全区", "es"], ["帮派", "pty"], ["系统", "sys"]],
|
||||||
|
isScroll: true,
|
||||||
|
last_click: 0,
|
||||||
|
show: function () {
|
||||||
|
if (Date.now() - this.last_click > 500) {
|
||||||
|
this.last_click = Date.now();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Dialog.channel.isShow) return;
|
||||||
|
Dialog.select("channel");
|
||||||
|
Dialog.icon("comment");
|
||||||
|
Dialog.title("");
|
||||||
|
Dialog.footer("");
|
||||||
|
for (var i = 0; i < Dialog.channel.footer.length; i++) {
|
||||||
|
var elem = $("<span class='footer-item channel-item' for='" + Dialog.channel.footer[i][1] + "'>"
|
||||||
|
+ Dialog.channel.footer[i][0] + "</span>").appendTo(Dialog.footerElement);
|
||||||
|
if (i == 0) elem.addClass("select");
|
||||||
|
}
|
||||||
|
Dialog.contentElement.html("").append(Process.ChannelElement.addClass("channel-dialog"));
|
||||||
|
|
||||||
|
Dialog.channel.isShow = true;
|
||||||
|
Dialog.channel.scrollBottom();
|
||||||
|
|
||||||
|
}, hide: function () {
|
||||||
|
Dialog.channel.footerChanged("");
|
||||||
|
Process.ChannelElement.removeClass("channel-dialog").insertBefore(".content-message");
|
||||||
|
|
||||||
|
this.scrollBottom();
|
||||||
|
this.isShow = false;
|
||||||
|
}, close: function () {
|
||||||
|
this.hide();
|
||||||
|
}, scrollBottom: function () {
|
||||||
|
Process.channel.scroll2end();
|
||||||
|
},
|
||||||
|
footerChanged: function (type) {
|
||||||
|
if (Dialog.channel.select_item == type) return;
|
||||||
|
Dialog.channel.select_item = type;
|
||||||
|
|
||||||
|
Process.channel.clear();
|
||||||
|
for (var i = 0; i < this.datas.length; i++) {
|
||||||
|
var item = this.datas[i];
|
||||||
|
if (!type || item[0] == type) {
|
||||||
|
Process.channel.push(item[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Process.channel.scroll2end();
|
||||||
|
}, datas: [],
|
||||||
|
createElement: function (data, isTop) {
|
||||||
|
var color = "hic";
|
||||||
|
var name = "";
|
||||||
|
switch (data.ch) {
|
||||||
|
case "tm":
|
||||||
|
color = "hig";
|
||||||
|
name = "队伍";
|
||||||
|
break;
|
||||||
|
case "fam":
|
||||||
|
color = "hiy";
|
||||||
|
name = data.fam || "门派";
|
||||||
|
break;
|
||||||
|
case "rumor":
|
||||||
|
color = "him";
|
||||||
|
name = "谣言";
|
||||||
|
data.name = "某人";
|
||||||
|
break;
|
||||||
|
case "sys":
|
||||||
|
color = "hir";
|
||||||
|
name = "系统";
|
||||||
|
data.name = "";
|
||||||
|
break;
|
||||||
|
case "es":
|
||||||
|
color = "hio";
|
||||||
|
name = data.server;
|
||||||
|
data.uid = null;
|
||||||
|
break;
|
||||||
|
case "pty":
|
||||||
|
color = "hiz";
|
||||||
|
name = "帮派";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
name = ["闲聊", "闲聊", "闲聊", "<hiy>宗师</hiy>", "<HIZ>武圣</HIZ>", "<hio>武帝</hio>", "<ord>武神</ord>"][data.lv];
|
||||||
|
if (data.lv6) {
|
||||||
|
name = ["<ord>武神</ord>", "<ord>剑神</ord>", "<ord>刀皇</ord>", "<ord>兵主</ord>", "<ord>战神</ord>"][data.lv6];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var html = ["<", color, ">【"];
|
||||||
|
html.push(name);
|
||||||
|
html.push("】");
|
||||||
|
if (data.name) {
|
||||||
|
html.push("<span");
|
||||||
|
if (data.uid) html.push(" cmd='look3 " + data.uid + "'");
|
||||||
|
html.push(">");
|
||||||
|
html.push(data.name);
|
||||||
|
html.push("</span>:");
|
||||||
|
}
|
||||||
|
html.push(data.content);
|
||||||
|
// if (isTop) {
|
||||||
|
// html.push("\n");
|
||||||
|
// }
|
||||||
|
var str = html.join("");
|
||||||
|
if (this.datas.length > 800) {
|
||||||
|
this.datas.length = 0;
|
||||||
|
this.datas.splice(0, 200);
|
||||||
|
}
|
||||||
|
if (data.ch == "rumor") data.ch = "sys";
|
||||||
|
this.datas.push([
|
||||||
|
data.ch, str
|
||||||
|
]);
|
||||||
|
if (this.select_item && this.select_item != data.ch) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
136
src/dialog/events.js
Normal file
136
src/dialog/events.js
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
|
||||||
|
import { showFlag } from '../game/tool.js';
|
||||||
|
|
||||||
|
const events_css = `
|
||||||
|
|
||||||
|
.dialog-events {
|
||||||
|
max-height: 32em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-events>.empty {
|
||||||
|
text-align: center;
|
||||||
|
color: gray;
|
||||||
|
margin-bottom: 3em;
|
||||||
|
margin-top: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-events>.event-item {
|
||||||
|
border-radius: 6px;
|
||||||
|
background-color: #111111;
|
||||||
|
border-left-width: 4px;
|
||||||
|
border-left-style: solid;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-item h3 {
|
||||||
|
margin: 0px;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
color: var(--border-color)
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-item .event-desc {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
margin: 0;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-item>.event-btn {
|
||||||
|
width: 7em;
|
||||||
|
border-left: 1px solid var(--border-color);
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: transparent;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
unRead: 0,
|
||||||
|
init: function () {
|
||||||
|
Dialog.injectStyle(events_css);
|
||||||
|
},
|
||||||
|
hide: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
}, onData: function (data) {
|
||||||
|
if (data.close) return Dialog.hide();
|
||||||
|
if (!data.items) {
|
||||||
|
if (data.finish) this.unRead--;
|
||||||
|
else this.unRead++;
|
||||||
|
return this.showUnread();
|
||||||
|
}
|
||||||
|
this.items = data.items;
|
||||||
|
this.create_items();
|
||||||
|
}, showUnread: function () {
|
||||||
|
showFlag("events", this.unRead);
|
||||||
|
},
|
||||||
|
show: function () {
|
||||||
|
if (!this.element)
|
||||||
|
this.element = $("<div class='dialog-events'></div>");
|
||||||
|
SendCommand("events");
|
||||||
|
if (this.isShow) return;
|
||||||
|
|
||||||
|
Dialog.title("活动");
|
||||||
|
Dialog.icon("dashboard");
|
||||||
|
this.unRead = 0;
|
||||||
|
this.showUnread();
|
||||||
|
Dialog.footer("");
|
||||||
|
this.element.appendTo(Dialog.contentElement);
|
||||||
|
this.isShow = true;
|
||||||
|
},
|
||||||
|
create_items: function () {
|
||||||
|
let str = [];
|
||||||
|
for (let i = 0; i < this.items.length; i++) {
|
||||||
|
const [id, title, desc, grade, time, command] = this.items[i];
|
||||||
|
str.push("<div class='event-item flex-row ");
|
||||||
|
str.push('grade', grade);
|
||||||
|
str.push("'><div class='flex-1'><h3>");
|
||||||
|
str.push(title)
|
||||||
|
str.push("</h3>");
|
||||||
|
str.push("<pre class='event-desc'>");
|
||||||
|
str.push(desc);
|
||||||
|
if (time > 0)
|
||||||
|
str.push('\n<mem>', this.format_time(time), '</mem>');
|
||||||
|
str.push("</pre></div>");
|
||||||
|
|
||||||
|
str.push("<span class='event-btn flex-0'");
|
||||||
|
if (command) str.push(" cmd='events ", id, "' >", command);
|
||||||
|
else str.push(">进行中");
|
||||||
|
str.push("</span>");
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
if (!str.length) str.push('<div class="empty">暂无活动</div>');
|
||||||
|
this.element.html(str.join(""));
|
||||||
|
Dialog.footer('<span class="obj-money">共有' + this.items.length + '项活动正在进行</span>');
|
||||||
|
|
||||||
|
}, format_time: function (time) {
|
||||||
|
let dt = new Date(time);
|
||||||
|
let now = new Date();
|
||||||
|
let day = dt.getDate();
|
||||||
|
let hour = dt.getHours();
|
||||||
|
let minu = dt.getMinutes();
|
||||||
|
let str = ['持续到'];
|
||||||
|
if (now.getFullYear() !== dt.getFullYear())
|
||||||
|
str.push(dt.getFullYear(), '年');
|
||||||
|
if (now.getMonth() !== dt.getMonth())
|
||||||
|
str.push(this.format_num(dt.getMonth() + 1), '月', this.format_num(day), '日');
|
||||||
|
else if (day !== now.getDate())
|
||||||
|
str.push(this.format_num(day), '日');
|
||||||
|
str.push(this.format_num(hour), ':', this.format_num(minu));
|
||||||
|
|
||||||
|
return str.join("");
|
||||||
|
|
||||||
|
}, format_num: function (num) {
|
||||||
|
return num > 9 ? num.toString() : "0" + num.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
629
src/dialog/extend.js
Normal file
629
src/dialog/extend.js
Normal file
@@ -0,0 +1,629 @@
|
|||||||
|
|
||||||
|
import Util from '../utils/util.js';
|
||||||
|
import { ReceiveMessage } from '../client.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
name: "自定义快捷操作", value: "button", for: [
|
||||||
|
{ name: "动作栏", value: "action" },
|
||||||
|
{ name: "地图", value: "map" },
|
||||||
|
{ name: "背包道具", value: "pack" },
|
||||||
|
{ name: "技能", value: "skill" },
|
||||||
|
{ name: "师父/随从技能", value: "mskill" },
|
||||||
|
{ name: "房间物体", value: "item" },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
// , {
|
||||||
|
// name: "触发", value: "trigger",
|
||||||
|
// for: [
|
||||||
|
// { name: "文本触发", value: "message" },
|
||||||
|
// { name: "事件处理", value: "data" },
|
||||||
|
// ]
|
||||||
|
// }, {
|
||||||
|
// name: "过滤", value: "filter",
|
||||||
|
// for: [
|
||||||
|
// { name: "文本过滤", value: "fmessage" },
|
||||||
|
// { name: "事件过滤", value: "fdata" },
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
],
|
||||||
|
init: function (elem) {
|
||||||
|
elem.on('click', '[ecmd]', this.onButtonClick);
|
||||||
|
elem.on('click', '.setting-item', this.onClickRow);
|
||||||
|
elem.on("click", ".switch", this.switchClick);
|
||||||
|
elem.on("change", "select", this.selectChanged);
|
||||||
|
if (this.element) return;
|
||||||
|
this.element = elem;
|
||||||
|
let html = [];
|
||||||
|
html.push('<div class="extend-list">');
|
||||||
|
this.append_settings(html);
|
||||||
|
html.push("</div>");
|
||||||
|
this.append_edit(html);
|
||||||
|
elem.html(html.join(""));
|
||||||
|
this.edit_elem = this.element.find('.extend-add');
|
||||||
|
this.list_elem = this.element.find('.extend-list');
|
||||||
|
},
|
||||||
|
refresh_list: function () {
|
||||||
|
let html = [];
|
||||||
|
this.append_settings(html);
|
||||||
|
this.list_elem.html(html.join(""));
|
||||||
|
},
|
||||||
|
append_settings: function (html) {
|
||||||
|
let items = this.setting, index = 0;
|
||||||
|
for (let item of items) {
|
||||||
|
html.push(this.create_item(item, index++));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
action_types: {
|
||||||
|
button: "快捷操作",
|
||||||
|
trigger: "触发器",
|
||||||
|
filter: "过滤器"
|
||||||
|
},
|
||||||
|
regex: {
|
||||||
|
message: true,
|
||||||
|
fmessage: true
|
||||||
|
},
|
||||||
|
for_types: {
|
||||||
|
map: "地图",
|
||||||
|
action: "动作栏",
|
||||||
|
pack: "背包道具",
|
||||||
|
skill: "技能",
|
||||||
|
item: "房间物体",
|
||||||
|
mskill: "师父/随从技能",
|
||||||
|
message: "文本",
|
||||||
|
data: "事件",
|
||||||
|
fmessage: "文本",
|
||||||
|
fdata: "事件"
|
||||||
|
},
|
||||||
|
create_item: function (item, index) {
|
||||||
|
let html = [];
|
||||||
|
html.push('<div class="setting-item" sid="', index++, '">');
|
||||||
|
html.push('<div class="title">');
|
||||||
|
html.push(this.for_types[item.for], this.action_types[item.type], '【', item.name, '】');
|
||||||
|
html.push('</div>');
|
||||||
|
let isopend = false;
|
||||||
|
if (item.on && item.on[Process.player]) isopend = true;
|
||||||
|
|
||||||
|
html.push('<span class="switch ', isopend ? "on" : "",
|
||||||
|
'"><span class="switch-button"></span><span class="switch-text">开</span></span>');
|
||||||
|
|
||||||
|
html.push('</div>');
|
||||||
|
return html.join("");
|
||||||
|
},
|
||||||
|
selectChanged: function () {
|
||||||
|
let elem = $(this);
|
||||||
|
if (elem.attr('prop') !== 'type') {
|
||||||
|
const fortype = elem.val();
|
||||||
|
elem.parent().next().find('.extend-row-header').html(
|
||||||
|
Dialog.extend.regex[fortype] ? "正则表达式" : "可选参数"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let type = elem.val()
|
||||||
|
let items = null;
|
||||||
|
for (let item of Dialog.extend.types) {
|
||||||
|
if (type === item.value) {
|
||||||
|
items = item.for;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!items) return;
|
||||||
|
elem = elem.parent().next().find('select');
|
||||||
|
let html = [];
|
||||||
|
for (let item of items) {
|
||||||
|
html.push('<option value="', item.value, '">', item.name, '</option>');
|
||||||
|
}
|
||||||
|
elem.html(html.join(""));
|
||||||
|
},
|
||||||
|
switchClick: function () {
|
||||||
|
let elem = $(this);
|
||||||
|
let text_elem = elem.find(".switch-text");
|
||||||
|
let text = text_elem.text();
|
||||||
|
let is_open = text !== "开始记录";
|
||||||
|
let is_selected = false;
|
||||||
|
if (elem.is(".on")) {
|
||||||
|
elem.removeClass("on");
|
||||||
|
is_open && text_elem.html("关");
|
||||||
|
} else {
|
||||||
|
elem.addClass("on");
|
||||||
|
is_open && text_elem.html("开");
|
||||||
|
is_selected = true;
|
||||||
|
}
|
||||||
|
if (!is_open) {
|
||||||
|
if (is_selected) {
|
||||||
|
Dialog.close();
|
||||||
|
Dialog.extend.start_record();
|
||||||
|
} else {
|
||||||
|
Dialog.extend.stop_record();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let item = Dialog.extend.setting[elem.parent().attr("sid")];
|
||||||
|
if (item) {
|
||||||
|
if (!item.on) item.on = {};
|
||||||
|
if (is_selected) {
|
||||||
|
item.on[Process.player] = 1;
|
||||||
|
} else {
|
||||||
|
delete item.on[Process.player];
|
||||||
|
}
|
||||||
|
Dialog.extend.save_extend(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
start_record: function () {
|
||||||
|
if (this.is_record) return;
|
||||||
|
this.is_record = true;
|
||||||
|
this.prev_time = 0;
|
||||||
|
this.record_cmds = [];
|
||||||
|
ReceiveMessage('<hic>开始记录你的操作命令。</hic>');
|
||||||
|
Process.state({ state: "正在记录你的操作命令" });
|
||||||
|
},
|
||||||
|
excluded: {
|
||||||
|
score: true, score2: true, pack: true, cha: true, tasks: true,
|
||||||
|
message: true, relation: true, shop: true, team: true, jh: true
|
||||||
|
},
|
||||||
|
excluded_check: [
|
||||||
|
(x) => x.startsWith('jh') && x.indexOf('start') < 0,
|
||||||
|
(x) => x.startsWith('stats'),
|
||||||
|
(x) => x.startsWith('map'),
|
||||||
|
(x) => x.startsWith('look')
|
||||||
|
],
|
||||||
|
record: function (cmd) {
|
||||||
|
if (!this.is_record) return;
|
||||||
|
if (this.excluded[cmd]) return;
|
||||||
|
for (let check of this.excluded_check) {
|
||||||
|
if (check(cmd)) return;
|
||||||
|
}
|
||||||
|
let now = Date.now();
|
||||||
|
if (this.prev_time > 0) {
|
||||||
|
this.record_cmds.push('#wait ' + (now - this.prev_time));
|
||||||
|
}
|
||||||
|
this.record_cmds.push(cmd);
|
||||||
|
this.prev_time = now;
|
||||||
|
},
|
||||||
|
stop_record: function () {
|
||||||
|
if (!this.is_record) return;
|
||||||
|
this.is_record = false;
|
||||||
|
ReceiveMessage('<cyn>已停止记录你的操作命令。</cyn>');
|
||||||
|
this.edit_elem.find('.switch').removeClass('on');
|
||||||
|
if (this.record_cmds.length > 0) {
|
||||||
|
Dialog.show('setting');
|
||||||
|
Dialog.setting.footerChanged(3);
|
||||||
|
this.edit_elem.show();
|
||||||
|
this.list_elem.hide();
|
||||||
|
this.edit_elem.find('textarea').val(this.record_cmds.join(";"));
|
||||||
|
Process.state();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
helper: "<li ecmd='show_actions'>可用命令参考</li><li ecmd='show_vars'>可用变量参考</li><li ecmd='show_paras'>参数用法参考</li>",
|
||||||
|
append_edit: function (html) {
|
||||||
|
html.push('<div class="extend-add hide">');
|
||||||
|
html.push('<div class="extend-row">');
|
||||||
|
html.push('<input prop="name" class="extend-input"/>');
|
||||||
|
html.push("<div class='extend-row-header'>提示/描述/说明</div>");
|
||||||
|
html.push("</div>");
|
||||||
|
|
||||||
|
html.push('<div class="extend-row">');
|
||||||
|
html.push('<select prop="type" class="extend-input">');
|
||||||
|
for (let item of this.types) {
|
||||||
|
html.push('<option value="', item.value, '">', item.name, '</option>');
|
||||||
|
}
|
||||||
|
html.push("</select><div class='extend-row-header'>扩展类型</div>");
|
||||||
|
html.push("</div>");
|
||||||
|
let item1 = this.types[0];
|
||||||
|
html.push('<div class="extend-row">');
|
||||||
|
html.push('<select prop="for" class="extend-input">');
|
||||||
|
for (let item of item1.for) {
|
||||||
|
html.push('<option value="', item.value, '">', item.name, '</option>');
|
||||||
|
}
|
||||||
|
html.push("</select><div class='extend-row-header'>可用选项</div>");
|
||||||
|
html.push("</div>");
|
||||||
|
|
||||||
|
html.push('<div class="extend-row">');
|
||||||
|
html.push('<input prop="paras" class="extend-input"/>');
|
||||||
|
html.push("<div class='extend-row-header'>可选参数</div>");
|
||||||
|
html.push("</div>");
|
||||||
|
|
||||||
|
html.push('<div class="extend-row flex-1">');
|
||||||
|
html.push('<textarea prop="content" class="extend-input"></textarea>');
|
||||||
|
html.push("<div class='extend-row-header extend-menus'>");
|
||||||
|
html.push('<span class="switch"> <span class="switch-button"> </span><span class="switch-text">开始记录</span></span>');
|
||||||
|
html.push("<ul class='extend-help'>");
|
||||||
|
html.push(this.helper);
|
||||||
|
html.push("</ul><button ecmd='save'>保存</button>");
|
||||||
|
|
||||||
|
html.push("</div></div>");
|
||||||
|
|
||||||
|
html.push("</div>");
|
||||||
|
}, onClickRow: function () {
|
||||||
|
var elem = $(this);
|
||||||
|
var item = Dialog.extend.setting[elem.attr("sid")];
|
||||||
|
if (!item) return;
|
||||||
|
Dialog.extend.selected_item = item;
|
||||||
|
if (!Dialog.extend.edit_button) {
|
||||||
|
Dialog.extend.edit_button =
|
||||||
|
$('<div class="buttons"><button ecmd="edit">编辑</button><button ecmd="up">上移</button><button ecmd="down">下移</button><button ecmd="remove">移除</button></div>');
|
||||||
|
}
|
||||||
|
Dialog.extend.edit_button.insertAfter(elem);
|
||||||
|
},
|
||||||
|
show: function (elem) {
|
||||||
|
this.init(elem);
|
||||||
|
if (!this.footer_buttons) {//<button ecmd="add">添加新的扩展</button>
|
||||||
|
this.footer_buttons = $('<div class="obj-money"><span for="import" class="footer-item">导入</span><span for="export" class="footer-item">导出</span><span for="add" class="footer-item">添加扩展</span></div>');
|
||||||
|
}
|
||||||
|
Dialog.footerElement.append(this.footer_buttons);
|
||||||
|
},
|
||||||
|
command: function (cmd) {
|
||||||
|
const func = this['cmd_' + cmd];
|
||||||
|
if (func) func.call(this);
|
||||||
|
},
|
||||||
|
cmd_import: function () {
|
||||||
|
if (!this.fileinput) {
|
||||||
|
let elem = $('<input type="file" style="display:none" accept=".json" />')[0];
|
||||||
|
document.body.appendChild(elem);
|
||||||
|
this.fileinput = elem;
|
||||||
|
elem.addEventListener('change', function (e) {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (!file) {
|
||||||
|
return ReceiveMessage('<red>未选择扩展文件。</red>');
|
||||||
|
}
|
||||||
|
const fileExt = file.name.split('.').pop().toLowerCase();
|
||||||
|
const validMimeTypes = ['application/json', 'text/json', 'text/plain'];
|
||||||
|
if (fileExt !== 'json' && !validMimeTypes.includes(file.type)) {
|
||||||
|
e.target.value = '';
|
||||||
|
return ReceiveMessage('<red>请选择有效的JSON文件!</red>');
|
||||||
|
}
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = function (event) {
|
||||||
|
try {
|
||||||
|
const jsonObj = JSON.parse(event.target.result);
|
||||||
|
Dialog.extend.setting = jsonObj.items;
|
||||||
|
Dialog.extend.refresh_list();
|
||||||
|
Dialog.extend.save_extend();
|
||||||
|
ReceiveMessage("<cyn>扩展文件加载成功。</cyn>");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("JSON解析错误:", error);
|
||||||
|
ReceiveMessage('<red>扩展文件加载失败。</red>');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.onerror = function () {
|
||||||
|
console.error("文件读取错误:", reader.error);
|
||||||
|
ReceiveMessage('<red>扩展文件读取失败。</red>');
|
||||||
|
};
|
||||||
|
reader.readAsText(file, 'utf-8');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.fileinput.click();
|
||||||
|
|
||||||
|
},
|
||||||
|
cmd_export: function () {
|
||||||
|
try {
|
||||||
|
let jsonObj = {
|
||||||
|
id: Process.player,
|
||||||
|
version: "0.1",
|
||||||
|
items: Dialog.extend.setting,
|
||||||
|
};
|
||||||
|
const jsonStr = JSON.stringify(jsonObj, null, 2);
|
||||||
|
if (window.android && typeof window.android.saveJsonFile === "function") {
|
||||||
|
// 传递文件名和JSON内容给安卓
|
||||||
|
window.android.saveJsonFile("武神扩展.json", jsonStr);
|
||||||
|
ReceiveMessage(`<cyn>扩展导出为本地文件【武神扩展.json】。</cyn>`);
|
||||||
|
} else {
|
||||||
|
const blob = new Blob([jsonStr], { type: "application/json;charset=utf-8" });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.style.display = "none ";
|
||||||
|
a.download = '武神扩展.json';
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
ReceiveMessage(`<cyn>扩展导出为本地文件【武神扩展.json】。</cyn>`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("保存JSON文件失败:", error);
|
||||||
|
alert("文件保存失败,请重试!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hide: function () {
|
||||||
|
if (this.is_record) {
|
||||||
|
this.stop_record();
|
||||||
|
}
|
||||||
|
if (this.list_elem.is('.hide')) {
|
||||||
|
this.list_elem.removeClass('hide');
|
||||||
|
this.edit_elem.addClass('hide');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.footer_buttons.remove(); 59
|
||||||
|
}, close: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
default_extend: [
|
||||||
|
{
|
||||||
|
name: "<red>全部击杀</red>",
|
||||||
|
type: "button", for: "action",
|
||||||
|
content: "kill @npc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "<gre>全部拾取</gre>",
|
||||||
|
type: "button", for: "action",
|
||||||
|
content: "get all from @item(尸体)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "<gre>返回武庙</gre>",
|
||||||
|
type: "button", for: "map",
|
||||||
|
paras: "name(扬州)",
|
||||||
|
content: "jh fam 0 start;go north;go north;go west"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "练习到指定等级",
|
||||||
|
type: "button", for: "skill",
|
||||||
|
content: "lianxi @id @input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "学习到指定等级",
|
||||||
|
type: "button", for: "mskill",
|
||||||
|
content: "xue @input @id from @master"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
init_extend: function () {
|
||||||
|
if (!this.setting)
|
||||||
|
this.setting = Util.storage.getItem('extends') ?? this.default_extend;
|
||||||
|
this.init_extend_group();
|
||||||
|
},
|
||||||
|
init_extend_group: function () {
|
||||||
|
this.groups = {};
|
||||||
|
for (let item of this.setting) {
|
||||||
|
this.init_extend_item(item);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
save_extend: function () {
|
||||||
|
Util.storage.setItem('extends', this.setting);
|
||||||
|
this.init_extend_group();
|
||||||
|
Combat.refActions();
|
||||||
|
},
|
||||||
|
init_extend_item: function (item) {
|
||||||
|
let group = this.groups[item.for];
|
||||||
|
if (!group) group = this.groups[item.for] = [];
|
||||||
|
let cmd = item.content;
|
||||||
|
if (item.on === true) {
|
||||||
|
item.on = {};
|
||||||
|
item.on[Process.player] = 1;
|
||||||
|
}
|
||||||
|
if (!cmd || !item.on || !item.on[Process.player]) return;
|
||||||
|
if (cmd[0] !== '#') cmd = '#' + cmd;
|
||||||
|
|
||||||
|
group.push({
|
||||||
|
name: item.name,
|
||||||
|
extend: true,
|
||||||
|
check: this.regex[item.for] ?
|
||||||
|
this.match(item.paras) : this.condtion(item.paras),
|
||||||
|
cmd: cmd
|
||||||
|
});
|
||||||
|
},
|
||||||
|
match: function (paras) {
|
||||||
|
try {
|
||||||
|
if (!paras) return null;
|
||||||
|
return this.express.match.bind(this, new RegExp(paras));
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
exp_reg: /(\w+)\((>=|<=|!=|>|<)?(.+?)\)/g,
|
||||||
|
condtion: function (paras) {
|
||||||
|
if (!paras) return null;
|
||||||
|
let match = null;
|
||||||
|
let funcs = [];
|
||||||
|
while (match = this.exp_reg.exec(paras)) {
|
||||||
|
let prop = match[1];
|
||||||
|
let oper = match[2];
|
||||||
|
let para = match[3];
|
||||||
|
if (!prop || !para) return null;
|
||||||
|
if (oper) {
|
||||||
|
let func = this.express[oper];
|
||||||
|
if (!func) return null;
|
||||||
|
funcs.push(func.bind(this, prop, para));
|
||||||
|
} else {
|
||||||
|
if (para[0] === '/' && para[para.length - 1] === '/')
|
||||||
|
funcs.push(this.express.match_prop.bind(this, prop, new RegExp(para.substring(1, para.length - 1))));
|
||||||
|
else
|
||||||
|
funcs.push(this.express.def.bind(this, prop, para));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return funcs.length > 0 ? funcs : null;
|
||||||
|
}, express: {
|
||||||
|
">=": function (prop, value, obj) {
|
||||||
|
return obj[prop] >= parseInt(value);
|
||||||
|
}, ">": function (prop, value, obj) {
|
||||||
|
return obj[prop] > parseInt(value);
|
||||||
|
}, "<": function (prop, value, obj) {
|
||||||
|
return obj[prop] < parseInt(value);
|
||||||
|
}, "<=": function (prop, value, obj) {
|
||||||
|
return obj[prop] <= parseInt(value);
|
||||||
|
}, "=": function (prop, value, obj) {
|
||||||
|
return obj[prop] = parseInt(value);
|
||||||
|
}, "!=": function (prop, value, obj) {
|
||||||
|
return obj[prop] != parseInt(value);
|
||||||
|
},
|
||||||
|
match: function (regex, text) {
|
||||||
|
let result = regex.exec(text);
|
||||||
|
if (!result) return false;
|
||||||
|
SCRIPT.lAST_MATCHES = result;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
match_prop: function (prop, regex, obj) {
|
||||||
|
let str = obj[prop];
|
||||||
|
if (!str || !regex) return false;
|
||||||
|
return regex.test(str);
|
||||||
|
},
|
||||||
|
def: function (prop, value, obj) {
|
||||||
|
let str = obj[prop];
|
||||||
|
if (typeof str === 'number')
|
||||||
|
return str === parseInt(value);
|
||||||
|
else if (typeof str === 'boolean')
|
||||||
|
return str && str.toString() === value;
|
||||||
|
return str && str.indexOf(value) > -1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
query: function (type, para) {
|
||||||
|
let cmds = [];
|
||||||
|
this.append(cmds, type, para);
|
||||||
|
return cmds;
|
||||||
|
},
|
||||||
|
append: function (cmds, type, para) {
|
||||||
|
let items = this.groups[type];
|
||||||
|
if (!items) return;
|
||||||
|
for (let item of items) {
|
||||||
|
if (this.check_para(item, para)) {
|
||||||
|
cmds.push(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
message_filter: function (mes) {
|
||||||
|
|
||||||
|
},
|
||||||
|
data_filter: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
trigger: function (msg) {
|
||||||
|
if (!this.groups) return;
|
||||||
|
let items = this.groups.message;
|
||||||
|
if (!items) return;
|
||||||
|
for (let item of items) {
|
||||||
|
if (!item.check) continue;
|
||||||
|
if (item.check(msg)) {
|
||||||
|
SCRIPT.run(item.cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
process: function (data) {
|
||||||
|
if (!this.groups) return;
|
||||||
|
let items = this.groups.data;
|
||||||
|
if (!items) return;
|
||||||
|
for (let item of items) {
|
||||||
|
if (this.check_para(item, data)) {
|
||||||
|
SCRIPT.LAST_DATA = data;
|
||||||
|
SCRIPT.run(item.cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
check_para: function (item, para) {
|
||||||
|
if (!item.check) return true;
|
||||||
|
for (let func of item.check) {
|
||||||
|
if (!func(para)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
onButtonClick: function () {
|
||||||
|
let paras = $(this).attr('ecmd').split('_');
|
||||||
|
let cmd = paras[0];
|
||||||
|
paras[0] = $(this);
|
||||||
|
let func = Dialog.extend['cmd_' + cmd];
|
||||||
|
func && func.apply(Dialog.extend, paras);
|
||||||
|
}, cmd_add: function () {
|
||||||
|
this.edit_elem.removeClass('hide');
|
||||||
|
this.list_elem.addClass('hide');
|
||||||
|
this.edit_elem.attr("sid", '-1');
|
||||||
|
let elems = this.edit_elem.find('input, textarea');
|
||||||
|
for (let elem of elems) {
|
||||||
|
$(elem).val("");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cmd_up: function () {
|
||||||
|
this.cmd_move(-1);
|
||||||
|
},
|
||||||
|
cmd_down: function () {
|
||||||
|
this.cmd_move(1);
|
||||||
|
},
|
||||||
|
cmd_move: function (mv) {
|
||||||
|
let item = this.selected_item;
|
||||||
|
if (!item) return;
|
||||||
|
let index = this.setting.indexOf(item);
|
||||||
|
let index2 = this.setting.indexOf(item) + mv;
|
||||||
|
if (index2 < 0 || index2 >= this.setting.length)
|
||||||
|
return;
|
||||||
|
this.setting.splice(index, 1);
|
||||||
|
this.setting.splice(index2, 0, item);
|
||||||
|
this.refresh_list();
|
||||||
|
this.save_extend();
|
||||||
|
|
||||||
|
},
|
||||||
|
cmd_edit: function () {
|
||||||
|
let item = this.selected_item;
|
||||||
|
if (!item) return;
|
||||||
|
this.edit_elem.show();
|
||||||
|
this.list_elem.hide();
|
||||||
|
this.edit_elem.attr("sid", this.setting.indexOf(item));
|
||||||
|
let elems = this.edit_elem.find('input, textarea, select');
|
||||||
|
for (let elem of elems) {
|
||||||
|
let val = $(elem).val();
|
||||||
|
let val2 = item[elem.getAttribute('prop')];
|
||||||
|
if (val2 !== val) {
|
||||||
|
$(elem).val(val2).change();;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
cmd_save: function () {
|
||||||
|
let index = parseInt(this.edit_elem.attr('sid'));
|
||||||
|
|
||||||
|
let elems = this.edit_elem.find('input, textarea, select');
|
||||||
|
let item = {};
|
||||||
|
for (let elem of elems) {
|
||||||
|
item[elem.getAttribute("prop")] = elem.value;
|
||||||
|
}
|
||||||
|
if (!item.name) return this.show_error('name');
|
||||||
|
if (!item.type) return this.show_error('type');
|
||||||
|
if (!item.content) return this.show_error('content');
|
||||||
|
if (item.paras) {
|
||||||
|
if (Dialog.extend.regex[item.for]) {
|
||||||
|
item.check = this.match(item.paras);
|
||||||
|
} else {
|
||||||
|
item.check = this.condtion(item.paras);
|
||||||
|
}
|
||||||
|
if (!item.check) return this.show_error('paras');
|
||||||
|
}
|
||||||
|
this.hide();
|
||||||
|
$(this.create_item(item, this.setting.length)).appendTo(this.list_elem);
|
||||||
|
|
||||||
|
if (index < 0) {
|
||||||
|
this.setting.push(item);
|
||||||
|
} else {
|
||||||
|
item.on = this.setting[index].on;
|
||||||
|
this.setting[index] = item;
|
||||||
|
this.refresh_list();
|
||||||
|
}
|
||||||
|
this.save_extend();
|
||||||
|
|
||||||
|
}, cmd_remove: function () {
|
||||||
|
let item = this.selected_item;
|
||||||
|
if (!item) return;
|
||||||
|
this.setting.Remove(item);
|
||||||
|
this.refresh_list();
|
||||||
|
this.save_extend();
|
||||||
|
},
|
||||||
|
show_error: function (key) {
|
||||||
|
let elem = this.element.find('[prop="' + key + '"]').parent();
|
||||||
|
elem.addClass('error-shake');
|
||||||
|
setTimeout(() => {
|
||||||
|
elem.removeClass('error-shake');
|
||||||
|
}, 1500);
|
||||||
|
}, cmd_show: function (elem, t) {
|
||||||
|
let infos = SCRIPT.helper[t];
|
||||||
|
if (!infos) return;
|
||||||
|
let html = [];
|
||||||
|
for (let i = 0; i < infos.length; i++) {
|
||||||
|
html.push('<li>', infos[i], '</li>');
|
||||||
|
}
|
||||||
|
let ul = elem.parent();
|
||||||
|
ul.html(html.join(""));
|
||||||
|
ul.next().html('返回').attr('ecmd', 'return');
|
||||||
|
},
|
||||||
|
cmd_return: function (elem) {
|
||||||
|
elem.html('保存').attr('ecmd', 'save').prev().html(this.helper);
|
||||||
|
}
|
||||||
|
};
|
||||||
530
src/dialog/jh.js
Normal file
530
src/dialog/jh.js
Normal file
@@ -0,0 +1,530 @@
|
|||||||
|
|
||||||
|
|
||||||
|
const jh_fam = {
|
||||||
|
name: "门派",
|
||||||
|
items: null,
|
||||||
|
selected_index: 0,
|
||||||
|
type: "fam",
|
||||||
|
onDetail: function (data) {
|
||||||
|
var fb = this.items[data.index];
|
||||||
|
if (!fb) return;
|
||||||
|
fb.type = '门派';
|
||||||
|
fb.desc = data.desc;
|
||||||
|
fb.sp = data.sp;
|
||||||
|
fb.actions = data.actions;
|
||||||
|
fb.skills = data.skills;
|
||||||
|
return this.showDetail(fb);
|
||||||
|
},
|
||||||
|
showDetail: function (fb) {
|
||||||
|
var html = ["<pre><hig>"];
|
||||||
|
html.push(fb.name);
|
||||||
|
html.push("</hig>\n");
|
||||||
|
html.push(fb.desc);
|
||||||
|
if (fb.sp) {
|
||||||
|
html.push("\n<hig>特点:");
|
||||||
|
html.push(fb.sp);
|
||||||
|
html.push("</hig>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.append_actions(html, fb);
|
||||||
|
html.push('<div class="item-commands"><span cmd="jh fam ' + fb.index + ' start">进入地图</span>');
|
||||||
|
let cmds = [];
|
||||||
|
Dialog.extend.append(cmds, 'map', fb);
|
||||||
|
for (let item of cmds) {
|
||||||
|
html.push('<span cmd="', item.cmd, '">', item.name, '</span>');
|
||||||
|
}
|
||||||
|
html.push('</div>');
|
||||||
|
if (fb.skills) {
|
||||||
|
html.push(fb.skills);
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push("</pre>");
|
||||||
|
this.descElement.html(html.join(""));
|
||||||
|
this.select(fb.index);
|
||||||
|
},
|
||||||
|
append_actions: function (html, fb) {
|
||||||
|
let actions = fb.actions ?? [];
|
||||||
|
html.push('<div class="fb-actions">');
|
||||||
|
for (let item of actions) {
|
||||||
|
html.push('<div class="fb-action">');
|
||||||
|
html.push('<span class="action-desc">', item[2] ?? "", "</span>");
|
||||||
|
if (item[1])
|
||||||
|
html.push('<span class="action-name" cmd="', item[0], '">', item[1], "</span>");
|
||||||
|
html.push('</div>');
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push('</div>');
|
||||||
|
},
|
||||||
|
show: function (left_panel, right_panel) {
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
var fb = this.items[i];
|
||||||
|
html.push('<div class="fam-item');
|
||||||
|
html.push('" index="', i, '">', fb.name, "</div>");
|
||||||
|
fb.index = i;
|
||||||
|
}
|
||||||
|
left_panel.html(html.join(""));
|
||||||
|
this.listElement = left_panel;
|
||||||
|
this.descElement = right_panel;
|
||||||
|
this.onClickItem(this.selected_index);
|
||||||
|
}, select: function (index) {
|
||||||
|
var elem = this.listElement.find("div[index='" + index + "']");
|
||||||
|
if (elem.length && !elem.is(".selected")) {
|
||||||
|
var top = elem[0].offsetTop;
|
||||||
|
var height = this.listElement.height();
|
||||||
|
if (top > height / 2) {
|
||||||
|
top = (height - elem.height()) / 2;
|
||||||
|
this.listElement[0].scrollTop = top;
|
||||||
|
}
|
||||||
|
if (this.selectedItem) this.selectedItem.removeClass("selected");
|
||||||
|
this.selectedItem = elem;
|
||||||
|
this.selectedItem.addClass("selected");
|
||||||
|
this.selected_index = index;
|
||||||
|
}
|
||||||
|
}, onClickItem: function (index) {
|
||||||
|
const item = this.items[index];
|
||||||
|
if (!item.desc) SendCommand("jh " + this.type + " " + index);
|
||||||
|
else this.showDetail(item);
|
||||||
|
this.select(index);
|
||||||
|
},
|
||||||
|
append_footer: function () {
|
||||||
|
let fb = this.items[this.selected_index];
|
||||||
|
Dialog.footerElement.find('.item-commands').
|
||||||
|
html(`<span cmd="jh fam ${fb.index} start">进入地图</span>`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const jh_fb = {
|
||||||
|
name: "副本",
|
||||||
|
type: "fb",
|
||||||
|
items: null,
|
||||||
|
selected_index: -1,
|
||||||
|
select: jh_fam.select,
|
||||||
|
onClickItem: jh_fam.onClickItem,
|
||||||
|
onDetail: function (data) {
|
||||||
|
var fb = this.items[data.index];
|
||||||
|
if (!fb) return;
|
||||||
|
fb.type = '副本';
|
||||||
|
fb.desc = data.desc;
|
||||||
|
fb.reward = data.reward;
|
||||||
|
fb.diffs = data.diffs;
|
||||||
|
fb.status = data.status;
|
||||||
|
return this.showDetail(fb);
|
||||||
|
}, update_unlock: function (unlock) {
|
||||||
|
this.unlock = unlock;
|
||||||
|
for (let i = 0; i < this.items.length; i++) {
|
||||||
|
this.items[i].unlock = unlock >= i;
|
||||||
|
}
|
||||||
|
if (this.selected_index < 0)
|
||||||
|
this.selected_index = unlock;
|
||||||
|
|
||||||
|
}, show: function (left_panel, right_panel) {
|
||||||
|
this.listElement = left_panel;
|
||||||
|
this.descElement = right_panel;
|
||||||
|
var html = ["<div class='fb-content'>"];
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
var fb = this.items[i];
|
||||||
|
html.push('<div class="fb-item');
|
||||||
|
if (!fb.unlock) {
|
||||||
|
html.push(" lock");
|
||||||
|
}
|
||||||
|
fb.index = i;
|
||||||
|
html.push('" index="', i, '">', fb.name, "</div>");
|
||||||
|
}
|
||||||
|
html.join("</div>");
|
||||||
|
this.listElement.html(html.join(""));
|
||||||
|
this.onClickItem(this.selected_index);
|
||||||
|
},
|
||||||
|
show_first: function (elem) {
|
||||||
|
let text = elem.prev().html();
|
||||||
|
text && ReceiveMessage(text);
|
||||||
|
},
|
||||||
|
fb_models: ['普通', '<red>困难</red>', '<cyn>组队</cyn>'],
|
||||||
|
showDetail: function (fb) {
|
||||||
|
var html = ["<pre>"];
|
||||||
|
html.push(fb.name);
|
||||||
|
if (fb.unlock) {
|
||||||
|
html.push("\n<hig>已解锁</hig>\n");
|
||||||
|
} else {
|
||||||
|
html.push("\n<red>未解锁</red>\n");
|
||||||
|
}
|
||||||
|
html.push(fb.desc);
|
||||||
|
this.append_status(html, fb);
|
||||||
|
if (fb.unlock && fb.diffs) {
|
||||||
|
html.push('<div class="item-commands">');
|
||||||
|
for (let i = 0; i < fb.diffs.length; i++) {
|
||||||
|
if (fb.diffs[i])
|
||||||
|
html.push('<span cmd="jh fb ',
|
||||||
|
fb.index, ' start', i + 1, '">', this.fb_buttons[i], '</span>');
|
||||||
|
}
|
||||||
|
let cmds = [];
|
||||||
|
Dialog.extend.append(cmds, 'map', fb);
|
||||||
|
for (let item of cmds) {
|
||||||
|
html.push('<span cmd="', item.cmd, '">', item.name, '</span>');
|
||||||
|
}
|
||||||
|
html.push('</div>');
|
||||||
|
}
|
||||||
|
html.push(fb.reward);
|
||||||
|
html.push("</pre>");
|
||||||
|
this.descElement.html(html.join(""));
|
||||||
|
this.select(fb.index);
|
||||||
|
|
||||||
|
}, append_status: function (html, fb) {
|
||||||
|
const sts = fb.status ?? [];
|
||||||
|
if (!sts.length) return;
|
||||||
|
html.push('<div class="fb-actions">');
|
||||||
|
for (let i = 0; i < sts.length; i++) {
|
||||||
|
let status = sts[i];
|
||||||
|
if (!status) continue;
|
||||||
|
if (status[0] === 1) {
|
||||||
|
html.push('<div class="fb-action finshed">');
|
||||||
|
html.push('<span class="action-desc">由', status[1], "首次通过", "</span>");
|
||||||
|
html.push('<span class="action-name" cmd="cr2 ', fb.index, ' ', i, '">', this.fb_models[i], "</span>");
|
||||||
|
html.push('</div>');
|
||||||
|
} else {
|
||||||
|
html.push('<div class="fb-action">');
|
||||||
|
html.push('<span class="action-desc">该模式尚未完成首杀',
|
||||||
|
status[1] ? ",称号奖励:" + status[1] : "",
|
||||||
|
"</span>");
|
||||||
|
html.push('<span class="action-name" cmd="cr2 ', fb.index, ' ', i, '">', this.fb_models[i], "</span>");
|
||||||
|
html.push('</div>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html.push('</div>');
|
||||||
|
},
|
||||||
|
fb_buttons: ['进入副本', '困难模式', '组队进入'],
|
||||||
|
append_footer: function () {
|
||||||
|
let fb = this.items[this.selected_index];
|
||||||
|
let html = [];
|
||||||
|
if (fb.unlock) {
|
||||||
|
for (let i = 0; i < fb.diffs.length; i++) {
|
||||||
|
if (fb.diffs[i])
|
||||||
|
html.push('<span cmd="jh fb ',
|
||||||
|
fb.index, ' start', i + 1, '">', this.fb_buttons[i], '</span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dialog.footerElement.find('.item-commands').html(html.join(""));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const jh_ar = {
|
||||||
|
name: "禁地",
|
||||||
|
items: null,
|
||||||
|
type: "ar",
|
||||||
|
selected_index: 0,
|
||||||
|
select: jh_fam.select,
|
||||||
|
onClickItem: jh_fam.onClickItem,
|
||||||
|
append_status: jh_fb.append_status,
|
||||||
|
append_actions: jh_fam.append_actions,
|
||||||
|
fb_models: ['普通', '普通', '组队'],
|
||||||
|
onDetail: function (data) {
|
||||||
|
var fb = this.items[data.index];
|
||||||
|
if (!fb) return;
|
||||||
|
fb.type = '禁地';
|
||||||
|
fb.desc = data.desc;
|
||||||
|
fb.actions = data.actions;
|
||||||
|
fb.status = data.status;
|
||||||
|
fb.reward = data.reward;
|
||||||
|
return this.showDetail(fb);
|
||||||
|
}, update_unlock: function (unlock) {
|
||||||
|
for (let i = 0; i < this.items.length; i++) {
|
||||||
|
this.items[i].unlock = (unlock & Math.pow(2, i)) !== 0;
|
||||||
|
}
|
||||||
|
}, show: function (left_panel, right_panel) {
|
||||||
|
var html = ["<div class='fb-content'>"];
|
||||||
|
let count = Math.max(this.items.length, 10);
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
var fb = this.items[i];
|
||||||
|
html.push('<div class="fb-item');
|
||||||
|
if (fb) {
|
||||||
|
if (!fb.unlock) {
|
||||||
|
html.push(" lock");
|
||||||
|
}
|
||||||
|
html.push('" index="', i, '">', fb.name, "</div>");
|
||||||
|
fb.index = i;
|
||||||
|
} else {
|
||||||
|
html.push('"> </div>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html.join("</div>");
|
||||||
|
this.listElement = left_panel;
|
||||||
|
this.descElement = right_panel;
|
||||||
|
this.listElement.html(html.join(""));
|
||||||
|
this.onClickItem(this.selected_index);
|
||||||
|
|
||||||
|
}, showDetail: function (fb) {
|
||||||
|
var html = ["<pre>"];
|
||||||
|
html.push(fb.name);
|
||||||
|
if (fb.unlock) {
|
||||||
|
html.push("\n<hig>已解锁</hig>\n");
|
||||||
|
} else {
|
||||||
|
html.push("\n<red>未解锁</red>\n");
|
||||||
|
}
|
||||||
|
html.push(fb.desc, '\n');
|
||||||
|
this.append_status(html, fb);
|
||||||
|
this.append_actions(html, fb);
|
||||||
|
if (fb.unlock) {
|
||||||
|
html.push('<div class="item-commands">');
|
||||||
|
html.push(`<span cmd="jh ar ${fb.index} start">进入地图</span>`);
|
||||||
|
let cmds = [];
|
||||||
|
Dialog.extend.append(cmds, 'map', fb);
|
||||||
|
for (let item of cmds) {
|
||||||
|
html.push('<span cmd="', item.cmd, '">', item.name, '</span>');
|
||||||
|
}
|
||||||
|
html.push('</div>');
|
||||||
|
}
|
||||||
|
html.push(fb.reward);
|
||||||
|
html.push("</pre>");
|
||||||
|
this.descElement.html(html.join(""));
|
||||||
|
this.select(fb.index);
|
||||||
|
|
||||||
|
},
|
||||||
|
append_footer: function () {
|
||||||
|
let fb = this.items[this.selected_index];
|
||||||
|
if (fb.unlock)
|
||||||
|
Dialog.footerElement.find('.item-commands').
|
||||||
|
html(`<span cmd="jh ar ${fb.index} start">进入地图</span>`);
|
||||||
|
else
|
||||||
|
Dialog.footerElement.find('.item-commands').empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const MAP_TYPES = {
|
||||||
|
fb: jh_fb,
|
||||||
|
fam: jh_fam,
|
||||||
|
ar: jh_ar
|
||||||
|
};
|
||||||
|
export default {
|
||||||
|
init: function () {
|
||||||
|
Dialog.injectStyle(jh_css);
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
},
|
||||||
|
onData: function (data) {
|
||||||
|
if (data.close) {
|
||||||
|
return Dialog.isShow && Dialog.hide();
|
||||||
|
}
|
||||||
|
if (data.desc) return this.selected_item.onDetail(data);
|
||||||
|
|
||||||
|
if (data.unlock !== undefined || data.unlock2 !== undefined) {
|
||||||
|
return this.update_lock(data);
|
||||||
|
}
|
||||||
|
if (data.refresh !== undefined && this.isLoad) {
|
||||||
|
let dialog = MAP_TYPES[data.t];
|
||||||
|
let item = dialog.items[data.refresh];
|
||||||
|
if (item && item.desc) {
|
||||||
|
item.desc = null;
|
||||||
|
let index = dialog.items.indexOf(item);
|
||||||
|
if (dialog.selected_index == index) {
|
||||||
|
dialog.onClickItem(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!data.fbs) return;
|
||||||
|
jh_fam.items = data.families.map(function (x) { return { name: x, unlock: false }; });
|
||||||
|
jh_fb.items = data.fbs.map(function (x) { return { name: x }; });
|
||||||
|
jh_ar.items = data.areas.map(function (x) { return { name: x, unlock: false }; });
|
||||||
|
this.selected_item.show(this.listElement, this.descElement);
|
||||||
|
},
|
||||||
|
show: function () {
|
||||||
|
if (this.isShow) return;
|
||||||
|
if (!this.element)
|
||||||
|
this.element = $("<div class='dialog-fb'><div class='fb-left'></div><div class='fb-right'></div></div>");
|
||||||
|
this.listElement = this.element.find(".fb-left").on("click",
|
||||||
|
".fb-item,.fam-item", this.item_click);
|
||||||
|
this.descElement = this.element.find(".fb-right");
|
||||||
|
Dialog.title("江湖");
|
||||||
|
Dialog.icon("home");
|
||||||
|
this.element.appendTo(Dialog.contentElement);
|
||||||
|
this.isShow = true;
|
||||||
|
if (this.isLoad) {
|
||||||
|
SendCommand("jh fb lock");
|
||||||
|
} else {
|
||||||
|
SendCommand("jh");
|
||||||
|
this.isLoad = true;
|
||||||
|
this.selected_item = this.footers[0];
|
||||||
|
}
|
||||||
|
this.create_footer();
|
||||||
|
},
|
||||||
|
selected_item: null,
|
||||||
|
footers: [jh_fam, jh_fb, jh_ar],
|
||||||
|
create_footer: function () {
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < this.footers.length; i++) {
|
||||||
|
let item = this.footers[i];
|
||||||
|
html.push("<span class='footer-item" +
|
||||||
|
(item == this.selected_item ? " select" : "") + "' for='" + i + "'>"
|
||||||
|
+ this.footers[i].name + "</span>");
|
||||||
|
}
|
||||||
|
html.push('<div class="item-commands"></div>');
|
||||||
|
Dialog.footerElement.html(html.join(""));
|
||||||
|
}, item_click: function () {
|
||||||
|
var elem = $(this);
|
||||||
|
if (elem.is(".selected")) return;
|
||||||
|
let index = elem.attr("index");
|
||||||
|
if (index !== undefined)
|
||||||
|
Dialog.jh.selected_item.onClickItem(index);
|
||||||
|
},
|
||||||
|
update_lock: function (data) {
|
||||||
|
if (data.unlock >= 0 && jh_fb.items) {
|
||||||
|
jh_fb.update_unlock(data.unlock);
|
||||||
|
if (this.selected_item === jh_fb)
|
||||||
|
jh_fb.show(this.listElement, this.descElement);
|
||||||
|
}
|
||||||
|
if (data.unlock2 >= 0 && jh_ar.items) {
|
||||||
|
jh_ar.update_unlock(data.unlock2);
|
||||||
|
if (this.selected_item === jh_ar)
|
||||||
|
jh_ar.show(this.listElement, this.descElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
footerChanged: function (index) {
|
||||||
|
let item = this.footers[index];
|
||||||
|
if (item == this.selected_item) return;
|
||||||
|
this.selected_item = item;
|
||||||
|
Dialog.footerElement.find('.item-commands').empty();
|
||||||
|
item.show(this.listElement, this.descElement);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const jh_css = `
|
||||||
|
|
||||||
|
|
||||||
|
.dialog-fb {
|
||||||
|
height: 25.5em;
|
||||||
|
overflow-y: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-fb>.fb-left {
|
||||||
|
width: 12.5em;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-fb>.fb-right {
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fb-actions {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fb-actions>.fb-action {
|
||||||
|
line-height: 2em;
|
||||||
|
padding-left: 1em;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-color: gray;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fb-actions>.fb-action>.action-desc {
|
||||||
|
flex: 1;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: gray;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fb-actions>.fb-action>.action-name {
|
||||||
|
flex: 0;
|
||||||
|
background-color: #222;
|
||||||
|
padding-left: 1em;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fb-actions>.fb-action>.action-name:hover {
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fb-actions>.finshed {
|
||||||
|
border-left-color: #00FF00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fb-actions>.finshed>.action-desc {
|
||||||
|
color: #00FF00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-fb>.fb-right>pre {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
margin: 0.5em 0.5em 2em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-fb>.fb-left>.fb-content {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-fb>.fb-left>.fb-content>.fb-item {
|
||||||
|
line-height: 2em;
|
||||||
|
padding-left: 1.5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-color: gray;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.dialog-fb>.fb-left>.fam-item {
|
||||||
|
line-height: 2em;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-color: gray;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-fb>.fb-left>.fb-content>.line {
|
||||||
|
height: 1.25em;
|
||||||
|
width: 0px;
|
||||||
|
border-left: 1px solid #343434;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-top: -1em;
|
||||||
|
margin-bottom: -1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-fb>.fb-left>.fb-content>.lock {
|
||||||
|
border-color: #bebebe;
|
||||||
|
color: #bebebe !important;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-fb>.fb-left>.fb-content .selected,
|
||||||
|
.dialog-fb>.fb-left>.selected {
|
||||||
|
border-color: #00ff00;
|
||||||
|
color: #00ff00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-fb>.fb-left>.fb-content>.lock:before {
|
||||||
|
font-family: 'Glyphicons Halflings';
|
||||||
|
content: "\\e033";
|
||||||
|
float: left;
|
||||||
|
margin-left: 0.25em;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
`;
|
||||||
194
src/dialog/keys.js
Normal file
194
src/dialog/keys.js
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
|
||||||
|
import Util from '../utils/util.js';
|
||||||
|
import SCRIPT from '../script.js';
|
||||||
|
|
||||||
|
const Keys = {
|
||||||
|
groups: [{
|
||||||
|
name: "移动",
|
||||||
|
items: [
|
||||||
|
{ name: "左", key: null, cmd: "#go @dir(left)" },
|
||||||
|
{ name: "右", key: null, cmd: "#go @dir(right)" },
|
||||||
|
{ name: "上", key: null, cmd: "#go @dir(up)" },
|
||||||
|
{ name: "下", key: null, cmd: "#go @dir(down)" },
|
||||||
|
{ name: "左上", key: null, cmd: "#go @dir(leftup)" },
|
||||||
|
{ name: "左下", key: null, cmd: "#go @dir(leftdown)" },
|
||||||
|
{ name: "右上", key: null, cmd: "#go @dir(rightup)" },
|
||||||
|
{ name: "右下", key: null, cmd: "#go @dir(rightdown)" }
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
name: "菜单",
|
||||||
|
items: [
|
||||||
|
{ name: "属性", key: null, cmd: "#menu score" },
|
||||||
|
{ name: "背包", key: null, cmd: "#menu pack" },
|
||||||
|
{ name: "技能", key: null, cmd: "#menu skills" },
|
||||||
|
{ name: "任务", key: null, cmd: "#menu tasks" },
|
||||||
|
{ name: "商城", key: null, cmd: "#menu shop" },
|
||||||
|
{ name: "社交", key: null, cmd: "#menu message" },
|
||||||
|
{ name: "排行", key: null, cmd: "#menu stats" },
|
||||||
|
{ name: "设置", key: null, cmd: "#menu setting" },
|
||||||
|
{ name: "动作", key: null, cmd: "#menu showcombat" },
|
||||||
|
{ name: "活动", key: null, cmd: "#menu events" },
|
||||||
|
{ name: "聊天", key: null, cmd: "#menu showchat" },
|
||||||
|
{ name: "停止", key: null, cmd: "#menu stopstate" },
|
||||||
|
{ name: "江湖", key: null, cmd: "#menu jh" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
setting: null,
|
||||||
|
show: function (elem) {
|
||||||
|
this.element = elem;
|
||||||
|
this.init();
|
||||||
|
elem.on('click', '.skey-item', this.item_clicked);
|
||||||
|
document.body.addEventListener('keydown', this.record_press);
|
||||||
|
}, hide: function () {
|
||||||
|
document.body.removeEventListener('keydown', this.record_press);
|
||||||
|
}, close: function () {
|
||||||
|
document.body.removeEventListener('keydown', this.record_press);
|
||||||
|
},
|
||||||
|
record_press: function (e) {
|
||||||
|
let item = Dialog.keys.select_item;
|
||||||
|
if (!item) return;
|
||||||
|
let keyitem = Dialog.keys.get_item(item.attr("sid"));
|
||||||
|
if (!keyitem) return;
|
||||||
|
if (e.keyCode === 8 || e.keyCode === 27) {
|
||||||
|
Dialog.keys.save_setting(keyitem, null);
|
||||||
|
return item.find('.skey-key').html('');
|
||||||
|
}
|
||||||
|
let code = Dialog.keys.get_key_code(e);
|
||||||
|
Dialog.keys.save_setting(keyitem, code);
|
||||||
|
item.find('.skey-key').html(keyitem.key);
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}, get_key_code: function (e) {
|
||||||
|
let code = e.code;
|
||||||
|
if (e.ctrlKey) {
|
||||||
|
if (e.key === "Control") return;
|
||||||
|
code = "Ctrl+" + code;
|
||||||
|
}
|
||||||
|
if (e.altKey) {
|
||||||
|
if (e.key === "Alt") return;
|
||||||
|
code = "Alt+" + code;
|
||||||
|
}
|
||||||
|
if (e.shiftKey) {
|
||||||
|
if (e.key === "Shift") return;
|
||||||
|
code = "Shift+" + code;
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
|
||||||
|
}, save_setting: function (item, key) {
|
||||||
|
item.key = key;
|
||||||
|
if (!this.setting) this.setting = {};
|
||||||
|
if (!key) {
|
||||||
|
key = this.id2keys[item.id];
|
||||||
|
if (key) delete this.setting[key];
|
||||||
|
delete this.id2keys[item.id];
|
||||||
|
}
|
||||||
|
else if (key) {
|
||||||
|
if (this.setting[key]) {
|
||||||
|
if (this.setting[key] === item.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let old_item = this.get_item(this.setting[key]);
|
||||||
|
if (old_item) {
|
||||||
|
old_item.key = null;
|
||||||
|
this.element.find('.skey-item[sid="'
|
||||||
|
+ old_item.id + '"]>.skey-key').html("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.setting[key] = item.id;
|
||||||
|
}
|
||||||
|
Util.storage.setItem('keys', this.setting);
|
||||||
|
}, get_item: function (id) {
|
||||||
|
if (this.groups.length === 2) this.init();
|
||||||
|
let sid = id.split('_');
|
||||||
|
let group = Dialog.keys.groups[parseInt(sid[0])];
|
||||||
|
if (!group) return;
|
||||||
|
let keyitem = group.items[parseInt(sid[1])];
|
||||||
|
return keyitem;
|
||||||
|
},
|
||||||
|
default_keys: {
|
||||||
|
"KeyW": "0_2", "KeyA": "0_0", "KeyR": "0_6",
|
||||||
|
"KeyD": "0_1", "KeyS": "0_3", "KeyQ": "0_4"
|
||||||
|
},
|
||||||
|
init_key: function () {
|
||||||
|
if (this.load_storage) return;
|
||||||
|
if (Util.isMobile) return;
|
||||||
|
this.load_storage = true;
|
||||||
|
this.setting = Util.storage.getItem('keys');
|
||||||
|
window.addEventListener('keydown', this.keypress);
|
||||||
|
this.id2keys = {};
|
||||||
|
if (!this.setting) return;
|
||||||
|
for (let key in this.setting) {
|
||||||
|
this.id2keys[this.setting[key]] = key;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
keypress: function (e) {
|
||||||
|
if (e.target !== document.body) return;
|
||||||
|
let setting = Dialog.keys.setting;
|
||||||
|
if (!setting) return;
|
||||||
|
let code = Dialog.keys.get_key_code(e);
|
||||||
|
if (setting[code]) {
|
||||||
|
let item = Dialog.keys.get_item(setting[code]);
|
||||||
|
if (item) {
|
||||||
|
SCRIPT.run(item.cmd);
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
item_clicked: function () {
|
||||||
|
let item = Dialog.keys.select_item;
|
||||||
|
if (item) item.removeClass('selected');
|
||||||
|
Dialog.keys.select_item = $(this).addClass('selected');
|
||||||
|
|
||||||
|
},
|
||||||
|
init: function () {
|
||||||
|
if (this.groups.length > 2) return;
|
||||||
|
let setting = this.id2keys || {}, id = null, j = 0;
|
||||||
|
for (let group of this.groups) {
|
||||||
|
for (let i = 0; i < group.items.length; i++) {
|
||||||
|
id = j + "_" + i;
|
||||||
|
group.items[i].id = id;
|
||||||
|
group.items[i].key = setting[id];
|
||||||
|
} j++;
|
||||||
|
}
|
||||||
|
let group = { name: "动作栏", items: [] };
|
||||||
|
for (let i = 0; i < 12; i++) {
|
||||||
|
|
||||||
|
id = "2_" + i;
|
||||||
|
group.items.push({
|
||||||
|
name: "栏位" + (i + 1), id: id,
|
||||||
|
cmd: "#action " + i, key: setting[id]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.groups.push(group);
|
||||||
|
group = { name: "技能栏", items: [] };
|
||||||
|
for (let i = 0; i < 12; i++) {
|
||||||
|
id = "3_" + i;
|
||||||
|
group.items.push({
|
||||||
|
name: "栏位"
|
||||||
|
+ (i + 1), id: id, cmd: "#pfm " + i, key: setting[id]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.groups.push(group);
|
||||||
|
this.element && this.create_html();
|
||||||
|
},
|
||||||
|
create_html: function () {
|
||||||
|
let html = [];
|
||||||
|
let i = 0, j = 0;
|
||||||
|
for (let group of this.groups) {
|
||||||
|
html.push('<h3>', group.name, '</h3>');
|
||||||
|
j = 0;
|
||||||
|
for (let item of group.items) {
|
||||||
|
html.push('<div class="skey-item" sid="', item.id, '">');
|
||||||
|
html.push('<div class="skey-name">', item.name, '</div>');
|
||||||
|
html.push('<div class="skey-key">', item.key, '</div>');
|
||||||
|
html.push('</div>');
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
this.element.html(html.join(""));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Keys;
|
||||||
274
src/dialog/list.js
Normal file
274
src/dialog/list.js
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
|
||||||
|
import Util from '../utils/util.js';
|
||||||
|
export default {
|
||||||
|
init: function () {
|
||||||
|
Dialog.pack.init();
|
||||||
|
},
|
||||||
|
hide: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.hide();
|
||||||
|
},
|
||||||
|
updateitem: function (data) {
|
||||||
|
if (data.store) {
|
||||||
|
if (!this.stores || !this.isShow)
|
||||||
|
return Dialog.pack.onData({ remove: data.store, id: data.id });
|
||||||
|
var item = this.find_item(1, data.id);
|
||||||
|
var store_item = this.find_item(3, data.storeid);
|
||||||
|
if (!item) {
|
||||||
|
item = Object.assign({}, store_item);
|
||||||
|
item.id = data.id; item.count = (-data.store);
|
||||||
|
Dialog.pack.items.push(item);
|
||||||
|
} else {
|
||||||
|
item.count -= data.store;
|
||||||
|
}
|
||||||
|
if (!store_item) {
|
||||||
|
store_item = Object.assign({}, item);
|
||||||
|
store_item.id = data.storeid; store_item.count = data.store;
|
||||||
|
this.stores.push(store_item);
|
||||||
|
} else {
|
||||||
|
store_item.count += data.store;
|
||||||
|
}
|
||||||
|
this.store_count = data.sum ?? this.stores.length;
|
||||||
|
if (store_item.count == 0) this.stores.Remove(store_item);
|
||||||
|
if (item.count == 0) Dialog.pack.items.Remove(item);
|
||||||
|
|
||||||
|
} else if (data.sell) {
|
||||||
|
var item = this.find_item(2, data.id);
|
||||||
|
if (item) {
|
||||||
|
item.count -= data.sell;
|
||||||
|
return this.create_items(this.selllist, this.leftElement, 2, this.selllist.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.isstore && this.isShow) {
|
||||||
|
this.create_items(this.stores, this.leftElement, 3,
|
||||||
|
Math.max(this.max_store_count, 100));// this.max_store_count
|
||||||
|
|
||||||
|
Dialog.title("你的仓库中有" + this.store_count + "/" + this.max_store_count + "件物品");
|
||||||
|
}
|
||||||
|
this.update_pack();
|
||||||
|
if (data.money != undefined) this.show_footer(data.money);
|
||||||
|
}, find_item: function (otype, id) {
|
||||||
|
var items = Dialog.pack.items;
|
||||||
|
if (otype == 2) items = this.selllist;
|
||||||
|
else if (otype == 3) items = this.stores;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].id == id) { return items[i]; }
|
||||||
|
}
|
||||||
|
}, formatItems: function (data) {
|
||||||
|
let items = [];
|
||||||
|
for (let item of data) {
|
||||||
|
items.push({
|
||||||
|
name: item[0], id: item[1],
|
||||||
|
count: item[2], grade: item[3],
|
||||||
|
unit: item[4], value: item[5]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}, onData: function (data) {
|
||||||
|
if (data.id) {
|
||||||
|
return this.updateitem(data);
|
||||||
|
}
|
||||||
|
var gongji = data.gongji ?? data.jungong ?? data.yaoyuan ?? data.mvalue;
|
||||||
|
if (data.selllist) {
|
||||||
|
this.show();
|
||||||
|
this.isstore = false;
|
||||||
|
this.gongji = gongji;
|
||||||
|
this.money_name = null;
|
||||||
|
this.typeElement.hide();
|
||||||
|
this.selllist = this.formatItems(data.selllist);
|
||||||
|
if (data.gongji >= 0) this.money_name = '门派功绩';
|
||||||
|
else if (data.jungong >= 0) this.money_name = "军功";
|
||||||
|
else if (data.yaoyuan >= 0) this.money_name = "<ord>妖元</ord>";
|
||||||
|
else this.money_name = data.mtype;
|
||||||
|
this.create_items(this.selllist, this.leftElement, 2, this.selllist.length);
|
||||||
|
Dialog.titleElement.html(data.title);
|
||||||
|
Dialog.icon("shopping-cart");
|
||||||
|
if (data.seller) this.seller = data.seller;
|
||||||
|
this.update_pack();
|
||||||
|
} else if (data.stores) {
|
||||||
|
this.show();
|
||||||
|
this.typeElement.show();
|
||||||
|
this.isstore = true;
|
||||||
|
this.stores = Dialog.pack.formatItems(data.stores);
|
||||||
|
if (data.sum > 0) {
|
||||||
|
this.typeElement.show();
|
||||||
|
this.store_count = data.sum;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.typeElement.hide();
|
||||||
|
this.store_count = data.stores.length;
|
||||||
|
}
|
||||||
|
this.create_items(this.stores, this.leftElement, 3,
|
||||||
|
Math.max(data.max_store_count, 100));
|
||||||
|
this.leftElement[0].scrollTop = 0;
|
||||||
|
Dialog.titleElement.html("你的仓库中有" + this.store_count + "/"
|
||||||
|
+ data.max_store_count + "件物品");
|
||||||
|
this.max_store_count = data.max_store_count;
|
||||||
|
Dialog.icon("lock");
|
||||||
|
this.update_pack();
|
||||||
|
}
|
||||||
|
if (gongji >= 0) {
|
||||||
|
this.gongji = gongji;
|
||||||
|
this.show_footer(gongji);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
show: function (data) {
|
||||||
|
if (!Dialog.isShow || Dialog.curItem != "list")
|
||||||
|
Dialog.show("list");
|
||||||
|
if (this.rightElement) {
|
||||||
|
this.rightElement.show();
|
||||||
|
if (Dialog.pack.objelement) Dialog.pack.objelement.remove();
|
||||||
|
}
|
||||||
|
if (this.isShow) return;
|
||||||
|
if (!this.element) {
|
||||||
|
this.element = $('<div class="dialog-list"><div class="otype-list"><div class="otype-item select" otype="0">道具</div><div class="otype-item" otype="1">秘籍</div><div class="otype-item" otype="2">宝石</div><div class="otype-item" otype="3">资源</div><div class="otype-item" otype="4">装备</div></div><div class="trade-list"></div><div class="obj-list"></div></div >');
|
||||||
|
var children = this.element.children();
|
||||||
|
this.typeElement = $(children[0])
|
||||||
|
this.typeElement.hide();
|
||||||
|
this.leftElement = $(children[1]);
|
||||||
|
this.rightElement = $(children[2]);
|
||||||
|
}
|
||||||
|
this.element.on("click", ".obj-item", Dialog.list.item_click);
|
||||||
|
this.element.on("click", ".otype-item", Dialog.list.otype_click);
|
||||||
|
this.element.appendTo(Dialog.contentElement.empty());
|
||||||
|
this.isShow = true;
|
||||||
|
|
||||||
|
},
|
||||||
|
selected_type: 0,
|
||||||
|
otype_click: function () {
|
||||||
|
let type = $(this).attr('otype');
|
||||||
|
let index = parseInt(type);
|
||||||
|
let store = Dialog.list;
|
||||||
|
if (!store.stores) return;
|
||||||
|
if (index === store.selected_type) return;
|
||||||
|
let type_elems = store.typeElement.children();
|
||||||
|
$(type_elems[store.selected_type]).removeClass('select');
|
||||||
|
store.selected_type = parseInt(type);
|
||||||
|
$(type_elems[index]).addClass('select');
|
||||||
|
SendCommand('store ' + index);
|
||||||
|
},
|
||||||
|
show_footer: function (money) {
|
||||||
|
money = this.money_name ? this.gongji : money;
|
||||||
|
let cmd = this.isstore ? "store" : "sell";
|
||||||
|
if (this.isstore) {
|
||||||
|
var str = this.money_name ? ("你目前有" + money + "<hiy>"
|
||||||
|
+ this.money_name + "</hiy>") : ("你身上有" + Util.moneyToStr(money));
|
||||||
|
Dialog.footerElement.html("<div class='obj-money'>" + str + "<span cmd='" + cmd + " all'>存仓库</span></div>");
|
||||||
|
} else {
|
||||||
|
var str = this.money_name ? ("你目前有" + money + "<hiy>"
|
||||||
|
+ this.money_name + "</hiy>") : ("你身上有" + Util.moneyToStr(money));
|
||||||
|
Dialog.footerElement.html("<div class='obj-money'>" + str + "<span cmd='" + cmd + " all'>清理杂物</span></div>");
|
||||||
|
}
|
||||||
|
}, update_pack: function () {
|
||||||
|
var items = Dialog.pack.items;
|
||||||
|
if (!items) SendCommand("pack");
|
||||||
|
else {
|
||||||
|
this.create_items(items, this.rightElement, 1, Dialog.pack.max_count);
|
||||||
|
this.show_footer(Dialog.pack.money);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
create_items: function (items, elem, otype, max_count) {
|
||||||
|
var html = [];
|
||||||
|
//otype 1自己的物品 2,贩卖的物品
|
||||||
|
var list = items;
|
||||||
|
if (otype === 1 || otype === 3) {
|
||||||
|
list = Dialog.pack.sort_items(items);
|
||||||
|
}
|
||||||
|
for (var i = 0; i < max_count; i++) {
|
||||||
|
var item = list[i];
|
||||||
|
// if (otype === 3 && item
|
||||||
|
// && item.otype !== this.selected_type) continue;
|
||||||
|
html.push('<div class="obj-item');
|
||||||
|
if (item) {
|
||||||
|
html.push(item.is_lock ? " lock" : "", ' grade', item.grade);
|
||||||
|
html.push('" obj="');
|
||||||
|
html.push(item.id);
|
||||||
|
html.push('" otype="')
|
||||||
|
html.push(otype);
|
||||||
|
html.push('">');
|
||||||
|
if (otype === 1) {
|
||||||
|
html.push('<span class="grade', item.grade, '">');
|
||||||
|
html.push(item.name);
|
||||||
|
html.push('</span>');
|
||||||
|
} else {
|
||||||
|
html.push(item.name);
|
||||||
|
}
|
||||||
|
html.push("<span class='obj-value'>");
|
||||||
|
if (otype == 2) {
|
||||||
|
html.push("每");
|
||||||
|
html.push(item.unit);
|
||||||
|
html.push(this.money_name ? (item.value + "<hiy>" + this.money_name + "</hiy>")
|
||||||
|
: Util.moneyToStr(item.value));
|
||||||
|
if (item.count == -1) {
|
||||||
|
html.push(":大量现货");
|
||||||
|
} else {
|
||||||
|
html.push(":剩余");
|
||||||
|
html.push(item.count);
|
||||||
|
html.push(item.unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (otype === 1 && !this.isstore) {
|
||||||
|
if (item.value) {
|
||||||
|
html.push("每");
|
||||||
|
html.push(item.unit);
|
||||||
|
html.push(Util.moneyToStr(item.value));
|
||||||
|
html.push(":");
|
||||||
|
html.push(item.count);
|
||||||
|
html.push(item.unit);
|
||||||
|
} else {
|
||||||
|
html.push("不可出售");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (item.count > 1) {
|
||||||
|
html.push(item.count);
|
||||||
|
html.push(item.unit);
|
||||||
|
}
|
||||||
|
html.push('</span>');
|
||||||
|
} else {
|
||||||
|
html.push('">');
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push('</div>');
|
||||||
|
}
|
||||||
|
elem.html(html.join(""));
|
||||||
|
|
||||||
|
}
|
||||||
|
, item_click: function () {
|
||||||
|
var elem = $(this);
|
||||||
|
var obj = elem.attr("obj");
|
||||||
|
var otype = elem.attr("otype");
|
||||||
|
var item = Dialog.list.find_item(otype, obj);
|
||||||
|
if (!item) return;
|
||||||
|
var html = ["<div class='item-commands'>"];
|
||||||
|
if (Dialog.list.isstore) {
|
||||||
|
if (otype == 3) {
|
||||||
|
html.push('<span cmd="checkobj ' + obj + ' from ' + "store" + '">查看</span>');
|
||||||
|
html.push('<span cmd="_confirm qu ' + obj + '">取出</span>');
|
||||||
|
} else if (otype == 1) {
|
||||||
|
html.push('<span cmd="checkobj ' + obj + ' from item">查看</span>');
|
||||||
|
html.push('<span cmd="_confirm store ' + item.count + ' ' + obj + '">存到仓库</span>');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (otype == 2) {
|
||||||
|
html.push('<span cmd="checkobj ' + obj + ' from ' + Dialog.list.seller + '">查看</span>');
|
||||||
|
if (item.count)
|
||||||
|
html.push('<span cmd="_confirm buy ' + item.count + ' ' + obj + ' from ' + Dialog.list.seller + '">购买</span>');
|
||||||
|
} else if (otype == 1) {
|
||||||
|
|
||||||
|
html.push('<span cmd="checkobj ' + obj + ' from item">查看</span>');
|
||||||
|
html.push('<span cmd="_confirm sell ' + item.count + ' ' + obj + ' to ' + Dialog.list.seller + '">卖掉</span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
html.push("</div>");
|
||||||
|
Dialog.list.element.find(".item-commands").remove();
|
||||||
|
|
||||||
|
elem = $(html.join("")).insertAfter(elem);
|
||||||
|
Util.checkScroll(elem);
|
||||||
|
}
|
||||||
|
};
|
||||||
35
src/dialog/map.js
Normal file
35
src/dialog/map.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
import MAP from '../map.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
onData: function (data) {
|
||||||
|
Dialog.title(data.title || "地图");
|
||||||
|
},
|
||||||
|
init: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
show: function () {
|
||||||
|
Dialog.init();
|
||||||
|
var rm = MAP.Room.name;
|
||||||
|
var index = rm.indexOf('-');
|
||||||
|
if (index > -1) {
|
||||||
|
rm = rm.substr(0, index);
|
||||||
|
}
|
||||||
|
Dialog.title(rm);
|
||||||
|
Dialog.footer("");
|
||||||
|
this.element = $(".map");
|
||||||
|
Dialog.contentElement.append(this.element);
|
||||||
|
Dialog.icon("map-marker");
|
||||||
|
Dialog.iconElement.attr("class", "dialog-icon glyphicon glyphicon-map-marker");
|
||||||
|
|
||||||
|
},
|
||||||
|
hide: function () {
|
||||||
|
this.element.remove();
|
||||||
|
if ($(".map-panel").children().length == 0)
|
||||||
|
this.element.appendTo(".map-panel");
|
||||||
|
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
156
src/dialog/master.js
Normal file
156
src/dialog/master.js
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
|
||||||
|
import Util from '../utils/util.js';
|
||||||
|
import SCRIPT from '../script.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
isShow: false,
|
||||||
|
init: function () {
|
||||||
|
Dialog.skills.init();
|
||||||
|
this.createSkillItems = Dialog.skills.createSkillItems;
|
||||||
|
this.createSkillItem = Dialog.skills.createSkillItem;
|
||||||
|
this.updateSkill = Dialog.skills.updateSkill;
|
||||||
|
this.updateSkillItem = Dialog.skills.updateSkillItem;
|
||||||
|
this.showdesc = Dialog.skills.showdesc;
|
||||||
|
this.isEnable = Dialog.skills.isEnable;
|
||||||
|
this.close = Dialog.skills.close;
|
||||||
|
},
|
||||||
|
hide: function () {
|
||||||
|
if (this.skill_element) {
|
||||||
|
this.skill_element.remove();
|
||||||
|
this.skill_element = null;
|
||||||
|
this.element.removeClass("hide-item");
|
||||||
|
Dialog.footer("");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.isShow = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
onData: function (data) {
|
||||||
|
if (data.desc) {
|
||||||
|
return this.showdesc(data);
|
||||||
|
}
|
||||||
|
if (data.id) {
|
||||||
|
//更新技能状态
|
||||||
|
return this.updateSkill(data);
|
||||||
|
}
|
||||||
|
if (data.books) {
|
||||||
|
return this.showBooks();
|
||||||
|
}
|
||||||
|
if (data.remove && data.from === this.master) {
|
||||||
|
this.items.Remove(this.skills[data.remove]);
|
||||||
|
var skill = this.skills[data.remove];
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].enable_skill == data.remove) {
|
||||||
|
this.items[i].enable_skill = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete this.skills[data.remove];
|
||||||
|
return this.createSkillItems(this.items);
|
||||||
|
}
|
||||||
|
if (!data.master && !data.follower) return;
|
||||||
|
Dialog.show("master");
|
||||||
|
this.master = data.master || data.follower;
|
||||||
|
this.is_follower = !!data.follower;
|
||||||
|
var skills = {};
|
||||||
|
for (var i = 0; i < data.items.length; i++) {
|
||||||
|
var item = data.items[i];
|
||||||
|
skills[item.id] = item;
|
||||||
|
}
|
||||||
|
this.skills = skills;
|
||||||
|
this.items = data.items;
|
||||||
|
Dialog.title(data.title);
|
||||||
|
Dialog.icon("book");
|
||||||
|
this.createSkillItems(data.items, skills);
|
||||||
|
if (data.limit) {
|
||||||
|
if (this.is_follower) {
|
||||||
|
let str = ['<div class="footer-item select" for="0">', '技能</div>'];
|
||||||
|
str.push('<div class="footer-item" for="1">书架</div>');
|
||||||
|
str.push("<span class='obj-money'>", data.target, "目前的技能上限为<HIC>", data.limit, "</HIC>级</span>");
|
||||||
|
Dialog.footer(str.join(""));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Dialog.footer("<span class='obj-money'>你目前的技能上限为<HIC>" + data.limit + "</HIC>级</span>");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
create_footer: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
selectedItem: 0,
|
||||||
|
footerChanged: function (index) {
|
||||||
|
index = parseInt(index);
|
||||||
|
if (index === this.selectedItem) return;
|
||||||
|
this.selectedItem = index;
|
||||||
|
if (index === 0) {
|
||||||
|
this.element.removeClass("dialog-books");
|
||||||
|
this.createSkillItems(this.items, this.skills);
|
||||||
|
} else {
|
||||||
|
if (!Dialog.skills.books) SendCommand('sbook');
|
||||||
|
else this.showBooks();
|
||||||
|
return this.element.addClass("dialog-books");
|
||||||
|
}
|
||||||
|
}, showBooks: function () {
|
||||||
|
if (!this.isShow || !this.is_follower) return;
|
||||||
|
var html = [];
|
||||||
|
var books = Dialog.skills.sort_items(Dialog.skills.books);
|
||||||
|
for (let item of books) {
|
||||||
|
html.push('<div class="book-item ');
|
||||||
|
html.push('grade', item.grade, '" >');
|
||||||
|
html.push('<div class="book-name">', item.name, '</div>');
|
||||||
|
html.push('<div class="book-action border-right" cmd="sbook ', item.id, '">查看</div>');
|
||||||
|
html.push('<div class="book-action" cmd="dc ',
|
||||||
|
Dialog.master.master, ' study ', item.id, '">学习</div>');
|
||||||
|
html.push('</div>');
|
||||||
|
}
|
||||||
|
this.element.html(html.join(""));
|
||||||
|
},
|
||||||
|
show: function () {
|
||||||
|
if (this.isShow) return;
|
||||||
|
if (!this.element) {
|
||||||
|
this.element = $('<div class="dialog-skills"></div >');
|
||||||
|
}
|
||||||
|
this.element.on("click", ".skill-item", this.item_click);
|
||||||
|
this.element.appendTo(Dialog.contentElement);
|
||||||
|
this.element.removeClass("hide-item");
|
||||||
|
this.isShow = true;
|
||||||
|
}, item_click: function () {
|
||||||
|
var elem = $(this);
|
||||||
|
var item = Dialog.master.skills[elem.attr("skid")];
|
||||||
|
if (!item) return;
|
||||||
|
var html = ["<div class='item-commands'>"];
|
||||||
|
html.push('<span cmd="checkskill ' + item.id + ' ' + Dialog.master.master + '">查看详细</span>');
|
||||||
|
html.push('<span cmd="xue ' + elem.attr("skid") + ' from ' + Dialog.master.master + '">学习</span>');
|
||||||
|
|
||||||
|
item.master = 1;
|
||||||
|
if (Dialog.master.is_follower) {
|
||||||
|
var bf = 'dc ' + Dialog.master.master;
|
||||||
|
html.push('<span cmd="_confirm ' + bf + ' fangqi ' + elem.attr("skid") + '">遗忘</span>');
|
||||||
|
html.push('<span cmd="' + bf + ' lianxi ' + elem.attr("skid") + '">练习</span>');
|
||||||
|
if (item.can_enables) {
|
||||||
|
for (var i = 0; i < item.can_enables.length; i++) {
|
||||||
|
var baseSkill = Dialog.master.skills[item.can_enables[i]];
|
||||||
|
if (!baseSkill) continue;
|
||||||
|
if (baseSkill.enable_skill != item.id)
|
||||||
|
html.push('<span cmd="' + bf + ' enable ' + baseSkill.id + ' ' + item.id + '">装备' + baseSkill.name + '</span>');
|
||||||
|
else {
|
||||||
|
html.push('<span cmd="' + bf + ' enable ' + baseSkill.id + ' none">取消装备' + baseSkill.name + '</span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item.enable_skill) {
|
||||||
|
var sp_skill = Dialog.master.skills[item.enable_skill];
|
||||||
|
if (sp_skill) html.push('<span cmd="' + bf + ' enable ' + item.id + ' none">取消装备' + sp_skill.name + '</span>');
|
||||||
|
else item.enable_skill = null;
|
||||||
|
}
|
||||||
|
item.master = 0;
|
||||||
|
}
|
||||||
|
SCRIPT.LAST_OBJ = item;
|
||||||
|
let commands = Dialog.extend.query('mskill', item);
|
||||||
|
for (let item of commands) {
|
||||||
|
html.push('<span cmd="', item.cmd, '">', item.name, '</span>');
|
||||||
|
}
|
||||||
|
html.push("</div>");
|
||||||
|
Dialog.master.element.find(".item-commands").remove();
|
||||||
|
$(html.join("")).insertAfter(elem);
|
||||||
|
Util.checkScroll(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
456
src/dialog/message.js
Normal file
456
src/dialog/message.js
Normal file
@@ -0,0 +1,456 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import { showFlag } from '../game/tool.js';
|
||||||
|
export default {
|
||||||
|
init: function () {
|
||||||
|
|
||||||
|
Dialog.injectStyle(message_css);
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
}, hide: function () {
|
||||||
|
if (this.detailID) {
|
||||||
|
this.hide_detail();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}, hide_detail: function () {
|
||||||
|
this.element.removeClass("detail");
|
||||||
|
this.detailID = null;
|
||||||
|
Dialog.footerElement.find('.item-commands').empty();
|
||||||
|
},
|
||||||
|
selected_item: 0,
|
||||||
|
messages: [],
|
||||||
|
isLoad: false,
|
||||||
|
unRead: 0,
|
||||||
|
onData: function (data) {
|
||||||
|
if (data.receive) return this.updateMessageState(data.receive, data.index);
|
||||||
|
if (data.items) {
|
||||||
|
return this.createMessageDetail(data.id, data.items);
|
||||||
|
}
|
||||||
|
if (data.clear) return this.clear_message(data.clear);
|
||||||
|
|
||||||
|
if (data.unRead != undefined) {
|
||||||
|
this.unRead = data.unRead;
|
||||||
|
}
|
||||||
|
if (data.messages) {
|
||||||
|
for (var i = 0; i < data.messages.length; i++) {
|
||||||
|
this.addMessage(data.messages[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.message) {
|
||||||
|
if (!this.isShow) this.unRead++;
|
||||||
|
if (this.messages)
|
||||||
|
this.addMessage(data.message);
|
||||||
|
if (data.message.id == "notice") {
|
||||||
|
this.showNotice(data.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.element)
|
||||||
|
this.showMessages();
|
||||||
|
if (this.isShow) {
|
||||||
|
if (data.message && this.element.is(".detail")
|
||||||
|
& this.detailID == data.message.id) {
|
||||||
|
this.detailElement.prepend($(this.createMessageDetailItem(data.message.id,
|
||||||
|
data.message.name, data.message)));
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
this.showUnread();
|
||||||
|
|
||||||
|
}, showUnread: function () {
|
||||||
|
if (this.unRead) showFlag("message", this.unRead);
|
||||||
|
else showFlag("message", 0);
|
||||||
|
},
|
||||||
|
addMessage: function (msg) {
|
||||||
|
for (let i = 0; i < this.messages.length; i++) {
|
||||||
|
if (this.messages[i].id == msg.id) {
|
||||||
|
this.messages[i] = msg;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.messages.push(msg);
|
||||||
|
}, clear_message: function (type) {
|
||||||
|
for (let i = 0; i < this.messages.length; i++) {
|
||||||
|
let from = this.messages[i].id;
|
||||||
|
if ((type === true && from !== 'notice') || from == type) {
|
||||||
|
this.messages.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.showMessages();
|
||||||
|
if (!this.isShow) return;
|
||||||
|
if (this.element.is(".detail")
|
||||||
|
& (type === true || this.detailID == type)) {
|
||||||
|
this.hide_detail();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
show: function (data) {
|
||||||
|
this.unRead = 0;
|
||||||
|
this.showUnread();
|
||||||
|
if (this.isShow) return;
|
||||||
|
this.isShow = true;
|
||||||
|
Dialog.title("消息");
|
||||||
|
Dialog.icon("envelope");
|
||||||
|
this.create_footer();
|
||||||
|
this.footerChanged(this.selected_item);
|
||||||
|
if (this.isLoad) return;
|
||||||
|
SendCommand("message");
|
||||||
|
this.isLoad = true;
|
||||||
|
|
||||||
|
// this.element.on("click", ".detail-item", this.showDetailCommand);
|
||||||
|
},
|
||||||
|
inner_show: function () {
|
||||||
|
|
||||||
|
Dialog.title("消息");
|
||||||
|
Dialog.icon("envelope");
|
||||||
|
this.element.on("click",
|
||||||
|
".message-item", this.showMessageDetail);
|
||||||
|
},
|
||||||
|
inner_close: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
},
|
||||||
|
footers: ["消息", "队伍", "关系", "帮派"],
|
||||||
|
footerElements: ["message", "team", "relation", "party"],
|
||||||
|
create_footer: function () {
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < this.footers.length; i++) {
|
||||||
|
html.push("<span class='footer-item" + (i == this.selected_item ? " select" : "") + "' for='" + i + "''>"
|
||||||
|
+ this.footers[i] + "</span>");
|
||||||
|
}
|
||||||
|
html.push('<dic class="item-commands"></div>');
|
||||||
|
Dialog.footer(html.join(""));
|
||||||
|
|
||||||
|
|
||||||
|
}, footerChanged: function (index) {
|
||||||
|
//if (index == this.selected_item) return;
|
||||||
|
this.selected_item = index;
|
||||||
|
Dialog.footerElement.find('.item-commands').empty();
|
||||||
|
this.showChild();
|
||||||
|
}, showChild: function () {
|
||||||
|
var child = Dialog[this.footerElements[this.selected_item]];
|
||||||
|
//if (this.selectedChild == child) return;
|
||||||
|
if (this.selectedChild) this.selectedChild.inner_close();
|
||||||
|
if (!child.element) child.element = child.createElement();
|
||||||
|
Dialog.contentElement.html(child.element);
|
||||||
|
child.inner_show();
|
||||||
|
|
||||||
|
this.selectedChild = child;
|
||||||
|
}, showNotice: function (nt) {
|
||||||
|
var str = ["\n<hiy>系统公告</hiy>\n"];
|
||||||
|
var dt = new Date(nt.time);
|
||||||
|
str.push(dt.getFullYear());
|
||||||
|
str.push("年");
|
||||||
|
str.push(dt.getMonth() + 1);
|
||||||
|
str.push("月");
|
||||||
|
str.push(dt.getDate());
|
||||||
|
str.push("日 ");
|
||||||
|
str.push(dt.getHours());
|
||||||
|
str.push("时");
|
||||||
|
str.push(dt.getMinutes());
|
||||||
|
str.push("分\n<hic>");
|
||||||
|
str.push(nt.content);
|
||||||
|
str.push("\n</hic>");
|
||||||
|
ReceiveMessage(str.join(""));
|
||||||
|
}, showMessages: function (newmsg) {
|
||||||
|
var str = [];
|
||||||
|
for (var i = 0; i < this.messages.length; i++) {
|
||||||
|
var msg = this.messages[i];
|
||||||
|
str.push("<div class='message-item' fromid=\"");
|
||||||
|
str.push(msg.id);
|
||||||
|
str.push("\"><div class='message-title'>");
|
||||||
|
str.push(msg.name);
|
||||||
|
|
||||||
|
str.push("<span class='message-time'>");
|
||||||
|
str.push(this.getTimedesc(msg.time));
|
||||||
|
str.push("</span>");
|
||||||
|
str.push("</div>");
|
||||||
|
str.push("<div class='message-content'>");
|
||||||
|
str.push(msg.content);
|
||||||
|
str.push("</div>");
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
if (!str.length) str.push('<div class="empty">暂无新消息</div>');
|
||||||
|
if (!this.listElement) this.listElement = this.element.find(".message-list");
|
||||||
|
this.listElement.html(str.join(""));
|
||||||
|
|
||||||
|
}, getTimedesc: function (long) {
|
||||||
|
var now = new Date();
|
||||||
|
var time = new Date(long);
|
||||||
|
var dt = (now - time) / 1000;
|
||||||
|
if (dt < 60) return "刚刚";
|
||||||
|
else if (dt < 3600) return parseInt(dt / 60) + "分钟前";
|
||||||
|
else if (time.getFullYear() == now.getFullYear() && time.getMonth() == now.getMonth()) {
|
||||||
|
var diff_day = time.getDate() - now.getDate();
|
||||||
|
var msg = "今天 " + this.add_zero(time.getHours()) + ":" + this.add_zero(time.getMinutes());
|
||||||
|
if (diff_day == 0) return msg;
|
||||||
|
else if (diff_day == 1) return "昨天 " + msg;
|
||||||
|
else if (diff_day == 2) return "前天 " + msg;
|
||||||
|
|
||||||
|
}
|
||||||
|
var str = (time.getMonth() + 1) + "月" + time.getDate() + "日 " + this.add_zero(time.getHours()) + ":" + this.add_zero(time.getMinutes());
|
||||||
|
if (now - time > 2332800000) {
|
||||||
|
str += "<mem>即将过期</mem>";
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
|
||||||
|
}, add_zero: function (num) {
|
||||||
|
if (num < 10) return "0" + num;
|
||||||
|
return num;
|
||||||
|
}, showMessageDetail: function () {
|
||||||
|
var id = $(this).attr("fromid");
|
||||||
|
if (!id) return;
|
||||||
|
SendCommand("message " + id);
|
||||||
|
Dialog.message.element.addClass("detail");
|
||||||
|
|
||||||
|
}, getMessageitem: function (id) {
|
||||||
|
for (var i = 0; i < this.messages.length; i++) {
|
||||||
|
if (this.messages[i].id == id) return this.messages[i];
|
||||||
|
}
|
||||||
|
}, createMessageDetail: function (id, items) {
|
||||||
|
if (!this.detailElement) {
|
||||||
|
this.detailElement = this.element.find(".detail-list");
|
||||||
|
}
|
||||||
|
var msg = this.getMessageitem(id);
|
||||||
|
if (!msg) return;
|
||||||
|
var str = [];
|
||||||
|
this.detailID = id;
|
||||||
|
let has_rec = false;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var item = items[i];
|
||||||
|
str.push(this.createMessageDetailItem(id, msg.name, item));
|
||||||
|
if (item.attach && !item.rec) {
|
||||||
|
has_rec = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.detailElement.html(str.join(""));
|
||||||
|
let cmds = "";
|
||||||
|
if (id !== 'notice') {
|
||||||
|
cmds = `<span cmd="message delete ${id}">删除</span><span cmd="receive ${id}">领取全部</span>`;
|
||||||
|
}
|
||||||
|
Dialog.footerElement.find('.item-commands').html(cmds);
|
||||||
|
|
||||||
|
}, createMessageDetailItem: function (id, name, item) {
|
||||||
|
var str = [];
|
||||||
|
str.push("<div class='detail-item' rec='",
|
||||||
|
item.attach && !item.rec ? 1 : 0,
|
||||||
|
"' fid='", id, "' index='" + item.index + "'>");
|
||||||
|
str.push("<span class='detail-name'>");
|
||||||
|
str.push(name);
|
||||||
|
str.push("</span>");
|
||||||
|
str.push("<span class='detail-time'>");
|
||||||
|
str.push(this.getTimedesc(item.time));
|
||||||
|
str.push("</span>");
|
||||||
|
str.push("<pre class='detail-content'>");
|
||||||
|
str.push(item.content);
|
||||||
|
str.push("</pre>");
|
||||||
|
if (item.attach) {
|
||||||
|
for (var j = 0; j < item.attach.length; j++) {
|
||||||
|
str.push("<div class='detail-attach'>");
|
||||||
|
str.push(item.attach[j].name);
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
if (item.rec) {
|
||||||
|
str.push("<div class='detail-rec'>已领取</div>");
|
||||||
|
} else {
|
||||||
|
str.push("<div class='detail-rec' cmd='receive " + id
|
||||||
|
+ " " + item.index + "'><hig>领取</hig></div>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str.push("</div>");
|
||||||
|
return str.join("");
|
||||||
|
},
|
||||||
|
createElement: function () {
|
||||||
|
return $('<div class="dialog-message"><div class="message-list"></div><div class="detail-list"></div></div>');
|
||||||
|
}, updateMessageState: function (rec, index) {
|
||||||
|
if (this.detailID != rec) return;
|
||||||
|
const elem = this.detailElement.find(".detail-item[index='" + index + "']>.detail-rec");
|
||||||
|
elem.html("已领取").removeAttr('cmd');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const message_css = `
|
||||||
|
|
||||||
|
.dialog-message{
|
||||||
|
height: 25em;
|
||||||
|
max-height: 30em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-message>.message-list>.empty{
|
||||||
|
color: #505050;
|
||||||
|
padding-top: 1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-message>.message-list>.message-item {
|
||||||
|
|
||||||
|
padding-left: 1em;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-color: gray;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-message>.message-list>.message-item>.message-title {
|
||||||
|
color: #FFFF00;
|
||||||
|
line-height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-message>.message-list>.message-item>.message-content {
|
||||||
|
white-space: break-spaces;
|
||||||
|
word-wrap: break-word;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-message>.message-list>.message-item>.message-title>.message-time {
|
||||||
|
float: right;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail {
|
||||||
|
min-height: 25em;
|
||||||
|
max-height: 25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail>.message-list {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-message>.detail-list {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail>.detail-list {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.dialog-team,
|
||||||
|
.dialog-party,
|
||||||
|
.dialog-relation {
|
||||||
|
height: 25em;
|
||||||
|
max-height: 30em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-team>.empty {
|
||||||
|
color: #505050;
|
||||||
|
padding-top: 1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-team>.team-item {
|
||||||
|
padding-left: 0.5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-color: gray;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
line-height: 2em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-team>.team-item>.item-commands {
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-team>.team-item>.team-flag {
|
||||||
|
width: 2em;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
color: #FFFF00
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-team>.team-item>.team-name {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-relation>.relation-item {
|
||||||
|
padding-left: 0.5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-color: gray;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
line-height: 2em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-relation>.relation-item>.relation-desc {
|
||||||
|
flex: 1;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-relation>.relation-item>.relation-cmd {
|
||||||
|
flex: 0;
|
||||||
|
background-color: #222;
|
||||||
|
padding-left: 1em;
|
||||||
|
padding-right: 1em;
|
||||||
|
cursor: pointer;
|
||||||
|
border-left: 2px solid #111;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
padding: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
padding-left: 1em;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-top-width: 2px;
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-color: gray;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item>.detail-name {
|
||||||
|
color: #FFFF00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item>.detail-time {
|
||||||
|
margin-left: 1em;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item>.detail-content {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item>.detail-rec {
|
||||||
|
margin-top: 1em;
|
||||||
|
background-color: #222;
|
||||||
|
color: gray;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 0.8em;
|
||||||
|
padding-left: 1em;
|
||||||
|
padding-right: 1em;
|
||||||
|
border-radius: 1em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
`;
|
||||||
701
src/dialog/packet.js
Normal file
701
src/dialog/packet.js
Normal file
@@ -0,0 +1,701 @@
|
|||||||
|
import Setting from '../setting.js';
|
||||||
|
import Util from '../utils/util.js';
|
||||||
|
import SCRIPT from '../script.js';
|
||||||
|
import Combat from '../combat.js';
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
close: function () {
|
||||||
|
this.hide();
|
||||||
|
this.element.remove();
|
||||||
|
//Dialog.footerElement.addClass("hide");
|
||||||
|
this.isShow = false;
|
||||||
|
this.skill_element_id = null;
|
||||||
|
this.element.removeClass("hide-item");
|
||||||
|
},
|
||||||
|
hide: function () { },
|
||||||
|
init: function () {
|
||||||
|
if (!this.created) {
|
||||||
|
Dialog.injectStyle(packet_css);
|
||||||
|
Dialog.injectStyle(list_css);
|
||||||
|
}
|
||||||
|
this.created = true;
|
||||||
|
},
|
||||||
|
command_before: '',
|
||||||
|
updateitem: function (data) {
|
||||||
|
if (data.money != undefined) {
|
||||||
|
this.money = data.money;
|
||||||
|
this.show_moeny();
|
||||||
|
}
|
||||||
|
if (data.eq_group !== undefined) {
|
||||||
|
this.eq_group = data.eq_group;
|
||||||
|
this.show_moeny();
|
||||||
|
}
|
||||||
|
else if (data.eq != undefined && this.items) {
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].id == data.id) {
|
||||||
|
this.eqs[data.eq] = this.items[i];
|
||||||
|
this.items.splice(i, 1);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.show_items();
|
||||||
|
} else if (data.uneq != undefined && this.items) {
|
||||||
|
var item = this.eqs[data.uneq];
|
||||||
|
item.can_eq = 1;
|
||||||
|
item.count = 1;
|
||||||
|
this.items.push(item);
|
||||||
|
this.eqs[data.uneq] = null;
|
||||||
|
|
||||||
|
this.show_items();
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (data.locked >= 0) {
|
||||||
|
let item = this.get_item(data.id);
|
||||||
|
if (item) {
|
||||||
|
item.is_lock = data.locked;
|
||||||
|
let elem = this.packElement.find('[oindex="' + data.id + '"]');
|
||||||
|
item.is_lock ? elem.addClass('lock') : elem.removeClass('lock');
|
||||||
|
}
|
||||||
|
} else if (data.jldesc) {
|
||||||
|
var str = [];
|
||||||
|
str.push(data.jldesc);
|
||||||
|
str.push("<span class='item-commands'>");
|
||||||
|
str.push('<span cmd="' + this.command_before + 'jinglian ' + data.id + ' ok">精炼</span>');
|
||||||
|
str.push('<span cmd="' + this.command_before + 'jinglian ' + data.id + ' full">精炼到满级</span>');
|
||||||
|
str.push("</span>");
|
||||||
|
this.show_sub(str.join(""));
|
||||||
|
} else if (data.xqdesc) {
|
||||||
|
var str = [];
|
||||||
|
str.push(data.xqdesc);
|
||||||
|
str.push("<span class='item-commands'>");
|
||||||
|
for (var i = 0; i < data.stones.length; i++) {
|
||||||
|
var st = data.stones[i];
|
||||||
|
str.push('<span cmd="' + this.command_before + 'xiangqian ' + data.id + ' '
|
||||||
|
+ st.id + '">镶嵌' + st.name + '</span><br/>');
|
||||||
|
}
|
||||||
|
str.push("</span>");
|
||||||
|
this.show_sub(str.join(""));
|
||||||
|
}
|
||||||
|
else if (data.desc) {
|
||||||
|
var str = [];
|
||||||
|
str.push(data.desc);
|
||||||
|
str.push("<span class='item-commands'>");
|
||||||
|
var from = data.from;
|
||||||
|
if (from == "eq") {
|
||||||
|
str.push('<span cmd="' + this.command_before + 'uneq ' + data.id + '">取消装备</span>');
|
||||||
|
} else if (from == "item") {
|
||||||
|
var obj = this.get_item(data.id);
|
||||||
|
SCRIPT.LAST_OBJ = obj;
|
||||||
|
if (obj) {
|
||||||
|
this.create_item_command(obj, str, data.commands);
|
||||||
|
}
|
||||||
|
} else if (from == "store") {
|
||||||
|
str.push('<span cmd="_confirm qu ' + data.id + '">取出</span>');
|
||||||
|
} else if (from == "sj") {
|
||||||
|
str.push('<span cmd="_confirm qu ' + data.id + '">取出</span>');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str.push('<span cmd="_confirm buy 1 ' + data.id + ' from ' + Dialog.list.seller + '">购买</span>');
|
||||||
|
}
|
||||||
|
str.push("</span>");
|
||||||
|
this.show_sub(str.join(""));
|
||||||
|
} else if (data.remove && this.items) {//丢掉的
|
||||||
|
var items = this.items;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].id == data.id) {
|
||||||
|
if (data.remove >= items[i].count) {
|
||||||
|
items.splice(i, 1);
|
||||||
|
Combat.DisObj(data);
|
||||||
|
} else {
|
||||||
|
items[i].count -= data.remove;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.isShow)
|
||||||
|
this.show_items();
|
||||||
|
else return false;
|
||||||
|
|
||||||
|
} else if (data.name && this.items) {//更新的
|
||||||
|
var item = this.get_item(data.id);
|
||||||
|
if (item) {
|
||||||
|
item.count = data.count;
|
||||||
|
item.name = data.name;
|
||||||
|
} else {
|
||||||
|
this.items.push(data);
|
||||||
|
}
|
||||||
|
if (this.isShow)
|
||||||
|
this.show_items();
|
||||||
|
else return false;
|
||||||
|
} else if (data.max_item_count) {
|
||||||
|
this.max_count = data.max_item_count;
|
||||||
|
ReceiveMessage((Dialog.pack2.isShow ? Dialog.pack2.target_name : "你") + "的背包容量扩充为" + this.max_count + "。");
|
||||||
|
this.show_items();
|
||||||
|
} else return false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
get_item: function (id, items) {
|
||||||
|
items = items || this.items;
|
||||||
|
if (!items) return;
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
if (items[i] && items[i].id == id) return items[i];
|
||||||
|
}
|
||||||
|
}, show_sub: function (str) {
|
||||||
|
if (this.objelement) this.objelement.remove();
|
||||||
|
var parent = this.packElement;
|
||||||
|
|
||||||
|
if (Dialog.list.isShow) {
|
||||||
|
parent = Dialog.list.rightElement;
|
||||||
|
}
|
||||||
|
this.objelement = $("<pre class='obj-desc'>" + str + "</pre>").appendTo(
|
||||||
|
parent.parent()).on("click", function () {
|
||||||
|
this.objelement.remove();
|
||||||
|
this.objelement = null;
|
||||||
|
parent.show();
|
||||||
|
}.bind(this));
|
||||||
|
parent.hide();
|
||||||
|
}, onData: function (data) {
|
||||||
|
if (data.items) {
|
||||||
|
this.eqs = this.formatEqs(data.eqs || []);
|
||||||
|
this.money = data.money;
|
||||||
|
this.eq_group = data.eq_group;
|
||||||
|
this.items = this.formatItems(data.items);
|
||||||
|
this.max_count = data.max_item_count;
|
||||||
|
if (this.isShow) {
|
||||||
|
this.show_items();
|
||||||
|
this.show_moeny();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Dialog.pack2.isShow && !data.name) return Dialog.pack2.onData(data);
|
||||||
|
if (this.updateitem(data)) return;
|
||||||
|
}
|
||||||
|
if (!this.isShow) {
|
||||||
|
if (Dialog.list.isShow) {
|
||||||
|
return Dialog.list.update_pack(data);
|
||||||
|
}
|
||||||
|
if (Dialog.trade.isShow) {
|
||||||
|
return Dialog.trade.update_pack(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
formatPackItem: function (item) {
|
||||||
|
return {
|
||||||
|
name: item[0], id: item[1],
|
||||||
|
count: item[2], grade: item[3],
|
||||||
|
unit: item[4], value: item[5],
|
||||||
|
can_eq: item[6], can_use: item[7],
|
||||||
|
can_study: item[8], can_open: item[9],
|
||||||
|
can_combine: item[10], is_lock: item[11],
|
||||||
|
otype: item[12]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
, formatItems: function (data) {
|
||||||
|
let items = [];
|
||||||
|
for (let item of data) {
|
||||||
|
items.push(this.formatPackItem(item));
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}, formatEqs: function (data) {
|
||||||
|
let items = [];
|
||||||
|
for (let item of data) {
|
||||||
|
if (!item) items.push(item);
|
||||||
|
else items.push({
|
||||||
|
name: item[0], id: item[1],
|
||||||
|
grade: item[2], can_use: item[3], is_lock: item[4]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
show_moeny: function () {
|
||||||
|
if (!this.isShow) return;//+ "<span cmd='sell all'>清理包裹</span></div>"
|
||||||
|
let mstr = Util.moneyToStr(this.money);
|
||||||
|
let str = [];
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
str.push('<span class="footer-item eq-group',
|
||||||
|
i === this.eq_group ? " select" : "", '" for="', i + 1, '">', i + 1, '</span>');
|
||||||
|
}
|
||||||
|
str.push("<div class='obj-money'>");
|
||||||
|
if (this.packElement.is('.cleanup')) {
|
||||||
|
|
||||||
|
str.push("<span for='cancle' class='footer-item'>取消</span>");
|
||||||
|
str.push("<span for='store' class='footer-item'>自动存仓</span>");
|
||||||
|
str.push("<span for='sell' class='footer-item'>清理杂物</span>");
|
||||||
|
str.push("<span for='cleanup' class='footer-item'>确定</span></div>");
|
||||||
|
} else {
|
||||||
|
str.push("你", (mstr ? "身上有"
|
||||||
|
+ mstr : "身上没有任何银两"));
|
||||||
|
str.push("<span for='cleanup' class='footer-item'>整理包裹</span></div>");
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog.footer(str.join(""));
|
||||||
|
|
||||||
|
}, cleanup_cmds: { cleanup: true, cancle: true, store: true, sell: true },
|
||||||
|
footerChanged: function (cmd, elem) {
|
||||||
|
if (this.cleanup_cmds[cmd])
|
||||||
|
return this.cleanup(cmd, elem);
|
||||||
|
let index = parseInt(cmd) - 1;
|
||||||
|
if (!(index >= 0 && index < 3)) return;
|
||||||
|
SendCommand('eqgroup ' + index);
|
||||||
|
},
|
||||||
|
cleanup: function (cmd, elem) {
|
||||||
|
let pack = this;
|
||||||
|
elem.removeClass('select');
|
||||||
|
if (pack.packElement.is('.cleanup')) {
|
||||||
|
if (cmd == 'cleanup') {
|
||||||
|
pack.packElement.find('.obj-item>.selected').
|
||||||
|
each(this.cleanup_item);
|
||||||
|
} else if (cmd == 'store') {
|
||||||
|
SendCommand((this.command_before ?? "") + 'store all');
|
||||||
|
} else if (cmd == 'sell') {
|
||||||
|
SendCommand((this.command_before ?? "") + 'sell all');
|
||||||
|
}
|
||||||
|
pack.packElement.removeClass("cleanup");
|
||||||
|
this.show_moeny();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pack.packElement.find(".item-commands").remove();
|
||||||
|
pack.packElement.addClass("cleanup");
|
||||||
|
pack.show_items();
|
||||||
|
this.show_moeny();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cleanup_item: function (x, y) {
|
||||||
|
let elem = $(y);
|
||||||
|
let item = elem.parent().attr('oindex');
|
||||||
|
let cmd = elem.attr('cmd');
|
||||||
|
SendCommand(cmd + " " + item);
|
||||||
|
},
|
||||||
|
show_items: function () {
|
||||||
|
if (!this.packElement) return;
|
||||||
|
this.createItems();
|
||||||
|
this.create_eqs();
|
||||||
|
Dialog.icon("briefcase");
|
||||||
|
var name = this.target_name || "你";
|
||||||
|
Dialog.title((this.items && this.items.length) ? (name + "身上共有" + this.items.length + "/" + this.max_count + "件物品") : (name + "身上没有任何东西"));
|
||||||
|
|
||||||
|
},
|
||||||
|
init_element: function () {
|
||||||
|
if (!this.element) {
|
||||||
|
this.element = $('<div class="dialog-pack"><div class="eq-list"><div class="eq-item"><span class="eq-type">武器</span><span class="eq-name"></span></div><div class="eq-item"><span class="eq-type">衣服</span><span class="eq-name"></span>' +
|
||||||
|
'</div > <div class="eq-item"><span class="eq-type">鞋</span><span class="eq-name"></span></div> <div class="eq-item"><span class="eq-type">头部</span><span class="eq-name"></span></div> <div class="eq-item">' +
|
||||||
|
'<span class="eq-type">披风</span><span class="eq-name"></span></div> <div class="eq-item"><span class="eq-type">戒指</span><span class="eq-name"></span></div> <div class="eq-item"><span class="eq-type">项链</span><span class="eq-name"></span>' +
|
||||||
|
'</div> <div class="eq-item"><span class="eq-type">饰品</span><span class="eq-name"></span></div> <div class="eq-item"><span class="eq-type">护腕</span><span class="eq-name"></span></div>' +
|
||||||
|
'<div class="eq-item"><span class="eq-type">腰带</span><span class="eq-name"></span></div><div class="eq-item"><span class="eq-type">暗器</span><span class="eq-name"></span></div></div><div class="obj-list"></div></div>');
|
||||||
|
this.packElement = this.element.find(".obj-list");
|
||||||
|
this.eqElement = this.element.find(".eq-list");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
show: function () {
|
||||||
|
if (!Dialog.isShow) Dialog.show();
|
||||||
|
if (this.objelement) {
|
||||||
|
this.objelement.remove();
|
||||||
|
this.objelement = null;
|
||||||
|
this.packElement && this.packElement.show();
|
||||||
|
}
|
||||||
|
if (this.isShow) return SendCommand(this.items ? "pack none" : "pack");
|
||||||
|
this.isShow = true;
|
||||||
|
this.init_element();
|
||||||
|
this.packElement.on("click", ".obj-item", Dialog.pack.item_click)
|
||||||
|
this.eqElement.on("click", ".eq-item", Dialog.pack.eqitem_click);
|
||||||
|
this.packElement.removeClass('cleanup');
|
||||||
|
this.element.appendTo(Dialog.contentElement);
|
||||||
|
|
||||||
|
if (!this.items) SendCommand("pack");
|
||||||
|
else {
|
||||||
|
SendCommand("pack none");
|
||||||
|
this.show_items();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
create_eqs: function () {
|
||||||
|
var items = this.eqElement.children();
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var eq = this.eqs[i];
|
||||||
|
if (eq) {
|
||||||
|
$(items[i]).attr('class',
|
||||||
|
'eq-item grade' + eq.grade).attr("oindex", i).find('.eq-name').html(eq.name);
|
||||||
|
} else {
|
||||||
|
$(items[i]).attr('class',
|
||||||
|
"eq-item empty").attr("oindex", "").find('.eq-name').html("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, levels: {
|
||||||
|
"wht": 0, "hig": 1, "hic": 2, "hiy": 3, "hiz": 4, "hio": 5, "ord": 6
|
||||||
|
},
|
||||||
|
sort_items: function (items) {
|
||||||
|
if (!items || !Setting.auto_sortitem) return items;
|
||||||
|
var list = [];
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var item = items[i];
|
||||||
|
var isok = false;
|
||||||
|
for (var j = 0; j < list.length; j++) {
|
||||||
|
if (item.grade < list[j].grade) {
|
||||||
|
list.splice(j, 0, item);
|
||||||
|
isok = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isok) {
|
||||||
|
list.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
},
|
||||||
|
createItems: function () {
|
||||||
|
if (!this.items) return;
|
||||||
|
var items = Dialog.pack.sort_items(this.items);
|
||||||
|
var html = [];
|
||||||
|
let is_cleanup = this.packElement?.is('.cleanup');
|
||||||
|
for (var i = 0; i < this.max_count; i++) {
|
||||||
|
var item = items[i];
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
html.push('<div class="obj-item ', item.is_lock ? "lock " : "", 'grade', item.grade, '" oindex="');
|
||||||
|
html.push(item.id);
|
||||||
|
html.push('">');
|
||||||
|
html.push(item.name);
|
||||||
|
if (this.show_type == 1) {
|
||||||
|
html.push("<span class='obj-value'>");
|
||||||
|
html.push("每");
|
||||||
|
html.push(item.unit);
|
||||||
|
html.push(Util.moneyToStr(item.value));
|
||||||
|
html.push(":");
|
||||||
|
html.push(item.count);
|
||||||
|
html.push(item.unit);
|
||||||
|
html.push('</span>');
|
||||||
|
} else if (item.count > 1) {
|
||||||
|
html.push("<span class='obj-value'>");
|
||||||
|
html.push(item.count);
|
||||||
|
html.push(item.unit);
|
||||||
|
html.push('</span>');
|
||||||
|
}
|
||||||
|
if (is_cleanup) {
|
||||||
|
if (item.grade > 0) {
|
||||||
|
html.push("<span cmd='store' class='obj-oper"
|
||||||
|
, (item.can_study ? " selected" : " "), "'>存仓库</span>");
|
||||||
|
}
|
||||||
|
if (item.can_combine && item.count >= item.can_combine) {
|
||||||
|
html.push("<span cmd='combine' class='obj-oper'>合成</span>");
|
||||||
|
}
|
||||||
|
if (this.target_name) {
|
||||||
|
html.push("<span cmd='give ", Process.player,
|
||||||
|
' ', item.count, "' class='obj-oper'>拿来</span>");
|
||||||
|
}
|
||||||
|
if (item.can_eq && item.grade > 0) {
|
||||||
|
html.push("<span cmd='sell' class='obj-oper'>卖掉</span>");
|
||||||
|
html.push("<span cmd='fenjie' class='obj-oper'>分解</span>");
|
||||||
|
} else if (item.value > 0) {
|
||||||
|
html.push("<span cmd='sell' class='obj-oper'>卖掉</span>");
|
||||||
|
} else if (!item.grade) {
|
||||||
|
html.push("<span cmd='drop' class='obj-oper'>丢掉</span>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
html.push('<div class="obj-item" oindex="">');
|
||||||
|
}
|
||||||
|
html.push('</div>');
|
||||||
|
}
|
||||||
|
this.packElement.html(html.join(""));
|
||||||
|
|
||||||
|
}, create_item_command: function (item, html, commands) {
|
||||||
|
html.push('<span cmd="_confirm ' + this.command_before + 'drop ' + item.count + ' ' + item.id + '">丢掉</span>');
|
||||||
|
//if (item.count > 1) {
|
||||||
|
// html.push('<span cmd="drop ' + item.count + " " + item.id + '">全部丢掉</span>');
|
||||||
|
//}
|
||||||
|
html.push('<span cmd="lockobj ' + item.id + '">', item.is_lock ? "解锁" : "锁定", '</span>');
|
||||||
|
if (item.can_eq) {
|
||||||
|
html.push('<span cmd="' + this.command_before + 'eq ' + item.id + '">装备</span>');
|
||||||
|
if (!this.command_before) {
|
||||||
|
html.push('<span cmd="jinglian ' + item.id + '">精炼</span>');
|
||||||
|
html.push('<span cmd="xiangqian ' + item.id + '">镶嵌</span>');
|
||||||
|
html.push('<span cmd="shortcut ' + item.id + '">设置快速装备</span>');
|
||||||
|
}
|
||||||
|
html.push('<span cmd="' + this.command_before + 'fenjie ' + item.id + '">分解</span>');
|
||||||
|
|
||||||
|
}
|
||||||
|
if (item.can_use) {
|
||||||
|
html.push('<span cmd="' + this.command_before + 'use ' + item.id + '">使用</span>');
|
||||||
|
if (!item.can_eq && !this.command_before) {
|
||||||
|
html.push('<span cmd="shortcut ' + item.id + '">设置快速使用</span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item.can_open) {
|
||||||
|
html.push('<span cmd="' + this.command_before + 'open ' + item.id + '">打开</span>');
|
||||||
|
}
|
||||||
|
if (item.can_study) {
|
||||||
|
html.push('<span cmd="' + this.command_before + 'study ' + item.id + '">学习</span>');
|
||||||
|
}
|
||||||
|
if (item.can_combine && item.count >= item.can_combine) {
|
||||||
|
html.push('<span cmd="_confirm ' + this.command_before + 'combine ' + item.id + ' ' + item.can_combine + '">合成</span>');
|
||||||
|
}
|
||||||
|
if (this.command_before) {
|
||||||
|
html.push('<span cmd="_confirm ' + this.command_before + 'give ' + Process.player + ' ' + item.count + ' ' + item.id + '">拿来</span>');
|
||||||
|
}
|
||||||
|
commands = commands || [];
|
||||||
|
Dialog.extend.append(commands, 'pack', item);
|
||||||
|
for (var i = 0; i < commands.length; i++) {
|
||||||
|
if (commands[i].extend)
|
||||||
|
html.push('<span cmd="', commands[i].cmd, '">', commands[i].name, '</span>');
|
||||||
|
else
|
||||||
|
html.push('<span cmd="packitem ', commands[i].cmd, ' ', item.id, '">', commands[i].name, '</span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, item_click: function (e) {
|
||||||
|
let elem = $(e.target);
|
||||||
|
let is_cleanup = Dialog.pack.packElement.is('.cleanup');
|
||||||
|
if (is_cleanup && elem.is('.obj-oper'))
|
||||||
|
return Dialog.pack.item_cleanup(elem);
|
||||||
|
elem = $(this);
|
||||||
|
var obj = elem.attr("oindex");
|
||||||
|
if (!obj) return;
|
||||||
|
var item = Dialog.pack.get_item(obj);
|
||||||
|
Dialog.pack.packElement.find(".item-commands").remove();
|
||||||
|
if (!item) return;
|
||||||
|
SCRIPT.LAST_OBJ = item;
|
||||||
|
var html = ["<span class='item-commands'>"];
|
||||||
|
html.push('<span cmd="checkobj ' + item.id + ' from item">查看</span>');
|
||||||
|
Dialog.pack.create_item_command(item, html);
|
||||||
|
html.push("</span>");
|
||||||
|
elem = $(html.join("")).insertAfter(elem);
|
||||||
|
Util.checkScroll(elem);
|
||||||
|
},
|
||||||
|
eqitem_click: function () {
|
||||||
|
var item = Dialog.pack.eqs[$(this).attr("oindex")];
|
||||||
|
if (!item) return;
|
||||||
|
SendCommand("checkobj " + item.id + " from eq");
|
||||||
|
}, item_cleanup: function (elem) {
|
||||||
|
if (elem.is('.selected')) elem.removeClass('selected');
|
||||||
|
else {
|
||||||
|
elem.parent().find('.selected').removeClass('selected');
|
||||||
|
elem.addClass('selected');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const packet_css = `
|
||||||
|
|
||||||
|
.dialog-pack {
|
||||||
|
min-width: 360px;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.dialog-pack>.obj-list {
|
||||||
|
width: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 25.625em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.obj-list>.obj-item {
|
||||||
|
|
||||||
|
margin-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-pack>.obj-desc {
|
||||||
|
padding: 0.25em;
|
||||||
|
margin: 0px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
width: 45%;
|
||||||
|
height: 25.625em;
|
||||||
|
display: inline-block;
|
||||||
|
float: left;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.eq-list {
|
||||||
|
width: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eq-list>.eq-item {
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-style: solid;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eq-list>.empty {
|
||||||
|
border-color: gray;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eq-list>.eq-item>.eq-name {
|
||||||
|
white-space: nowrap;
|
||||||
|
padding-left: 0.3125em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eq-list>.eq-item>.eq-type {
|
||||||
|
background-color: #333;
|
||||||
|
color: gray;
|
||||||
|
line-height: 1.875em;
|
||||||
|
display: inline-block;
|
||||||
|
height: 1.875em;
|
||||||
|
width: 3em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.obj-list>.obj-item {
|
||||||
|
background-color: #111;
|
||||||
|
line-height: 1.875em;
|
||||||
|
min-height: 1.875em;
|
||||||
|
padding-left: 0.3125em;
|
||||||
|
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.obj-list>.lock:before {
|
||||||
|
content: "\e033";
|
||||||
|
font-family: 'Glyphicons Halflings';
|
||||||
|
font-size: 0.8em;
|
||||||
|
margin-right: 0.2em;
|
||||||
|
color: var(--border-color);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.obj-item>.obj-oper {
|
||||||
|
float: right;
|
||||||
|
margin-right: 0.625em;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
line-height: 1.5em;
|
||||||
|
background-color: #222;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
margin-top: 0.2em;
|
||||||
|
color: gray;
|
||||||
|
display: none;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cleanup>.obj-item>.obj-oper {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cleanup>.obj-item>.selected {
|
||||||
|
color: #00FF00;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.obj-item>.obj-count,
|
||||||
|
.obj-item>.obj-value {
|
||||||
|
float: right;
|
||||||
|
margin-right: 0.625em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cleanup>.obj-item>.obj-value,
|
||||||
|
.cleanup>.obj-item>.obj-count {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.obj-list>.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
const list_css = `
|
||||||
|
|
||||||
|
.dialog-list {
|
||||||
|
width: 100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-list>.otype-list {
|
||||||
|
width: 6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-list>.otype-list>.otype-item {
|
||||||
|
white-space: nowrap;
|
||||||
|
line-height: 2em;
|
||||||
|
width: 5em;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #111;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
margin-left: 0.5em;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-list>.otype-list>.select {
|
||||||
|
background-color: #222;
|
||||||
|
color: #00ff00;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-color: #00ff00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-list>.trade-list,
|
||||||
|
.dialog-list>.obj-list {
|
||||||
|
|
||||||
|
height: 21.25em;
|
||||||
|
display: inline-block;
|
||||||
|
overflow-y: auto;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.dialog-list>.obj-desc {
|
||||||
|
padding: 0.25em;
|
||||||
|
margin: 0px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-list>.trade-list {
|
||||||
|
|
||||||
|
height: 21.25em;
|
||||||
|
display: inline-block;
|
||||||
|
overflow-y: auto;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.trade-list>.obj-item {
|
||||||
|
background-color: #111;
|
||||||
|
line-height: 1.875em;
|
||||||
|
min-height: 1.875em;
|
||||||
|
padding-left: 0.3125em;
|
||||||
|
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trade-list>.lock:before {
|
||||||
|
content: "\e033";
|
||||||
|
font-family: 'Glyphicons Halflings';
|
||||||
|
font-size: 0.8em;
|
||||||
|
margin-right: 0.2em;
|
||||||
|
color: var(--border-color);
|
||||||
|
|
||||||
|
}`;
|
||||||
111
src/dialog/packet2.js
Normal file
111
src/dialog/packet2.js
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import SCRIPT from '../script.js';
|
||||||
|
import Util from '../utils/util.js';
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
init: function () {
|
||||||
|
Dialog.pack.init();
|
||||||
|
// this.cleanup_cmds = Dialog.pack.cleanup_cmds;
|
||||||
|
// this.formatEqs = Dialog.pack.formatEqs;
|
||||||
|
// this.formatItems = Dialog.pack.formatItems;
|
||||||
|
// this.formatPackItem = Dialog.pack.formatPackItem;
|
||||||
|
// this.createItems = Dialog.pack.createItems;
|
||||||
|
// this.create_eqs = Dialog.pack.create_eqs;
|
||||||
|
// this.init_element = Dialog.pack.init_element;
|
||||||
|
// this.show_items = Dialog.pack.show_items;
|
||||||
|
// this.updateitem = Dialog.pack.updateitem;
|
||||||
|
// this.footerChanged = Dialog.pack.footerChanged;
|
||||||
|
// this.cleanup = Dialog.pack.cleanup;
|
||||||
|
|
||||||
|
this.show_sub = Dialog.pack.show_sub;
|
||||||
|
this.close = Dialog.pack.close;
|
||||||
|
this.get_item = Dialog.pack.get_item;
|
||||||
|
this.create_item_command = Dialog.pack.create_item_command;
|
||||||
|
},
|
||||||
|
onData: function (data) {
|
||||||
|
|
||||||
|
this.show();
|
||||||
|
if (data.items) {
|
||||||
|
this.eqs = this.formatEqs(data.eqs || []);
|
||||||
|
this.money = data.money;
|
||||||
|
this.id = data.id;
|
||||||
|
this.command_before = "dc " + this.id + " ";
|
||||||
|
this.items = this.formatItems(data.items);
|
||||||
|
this.target_name = data.name;
|
||||||
|
this.max_count = data.max_item_count;
|
||||||
|
this.show_items();
|
||||||
|
this.show_moeny();
|
||||||
|
} else {
|
||||||
|
this.updateitem(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
show_moeny: function () {
|
||||||
|
if (!this.isShow) return;//+ "<span cmd='sell all'>清理包裹</span></div>"
|
||||||
|
let mstr = Util.moneyToStr(this.money);
|
||||||
|
let str = [];
|
||||||
|
str.push("<div class='obj-money'>");
|
||||||
|
if (this.packElement.is('.cleanup')) {
|
||||||
|
|
||||||
|
str.push("<span for='cancle' class='footer-item'>取消</span>");
|
||||||
|
str.push("<span for='store' class='footer-item'>自动存仓</span>");
|
||||||
|
str.push("<span for='sell' class='footer-item'>清理杂物</span>");
|
||||||
|
str.push("<span for='cleanup' class='footer-item'>确定</span></div>");
|
||||||
|
} else {
|
||||||
|
str.push(this.target_name, (mstr ? "身上有"
|
||||||
|
+ mstr : "身上没有任何银两"));
|
||||||
|
str.push("<span for='cleanup' class='footer-item'>整理</span></div>");
|
||||||
|
}
|
||||||
|
Dialog.footer(str.join(""));
|
||||||
|
|
||||||
|
},
|
||||||
|
cleanup_item: function (x, y) {
|
||||||
|
let elem = $(y);
|
||||||
|
let item = elem.parent().attr('oindex');
|
||||||
|
let cmd = elem.attr('cmd');
|
||||||
|
SendCommand(Dialog.pack2.command_before + " " + cmd + " " + item);
|
||||||
|
},
|
||||||
|
hide: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
},
|
||||||
|
show: function () {
|
||||||
|
if (!Dialog.isShow) Dialog.show("pack2");
|
||||||
|
if (this.objelement) {
|
||||||
|
this.objelement.remove();
|
||||||
|
this.objelement = null;
|
||||||
|
this.packElement && this.packElement.show();
|
||||||
|
}
|
||||||
|
if (this.isShow) return;
|
||||||
|
this.isShow = true;
|
||||||
|
this.init_element();
|
||||||
|
this.packElement.on("click", ".obj-item", this.item_click)
|
||||||
|
this.eqElement.on("click", ".eq-item", this.eqitem_click);
|
||||||
|
this.element.appendTo(Dialog.contentElement);
|
||||||
|
}
|
||||||
|
, item_click: function (e) {
|
||||||
|
let elem = $(e.target);
|
||||||
|
let is_cleanup = Dialog.pack2.packElement.is('.cleanup');
|
||||||
|
if (is_cleanup && elem.is('.obj-oper'))
|
||||||
|
return Dialog.pack.item_cleanup(elem);
|
||||||
|
elem = $(this);
|
||||||
|
var obj = elem.attr("oindex");
|
||||||
|
if (!obj) return;
|
||||||
|
var item = Dialog.pack2.get_item(obj);
|
||||||
|
Dialog.pack2.element.find(".item-commands").remove();
|
||||||
|
if (!item) return;
|
||||||
|
SCRIPT.LAST_OBJ = item;
|
||||||
|
var html = ["<span class='item-commands'>"];
|
||||||
|
html.push('<span cmd="' + Dialog.pack2.command_before + ' checkobj ' + item.id + ' from item">查看</span>');
|
||||||
|
Dialog.pack2.create_item_command(item, html);
|
||||||
|
html.push("</span>");
|
||||||
|
elem = $(html.join("")).insertAfter(elem);
|
||||||
|
Util.checkScroll(elem);
|
||||||
|
|
||||||
|
}, eqitem_click: function () {
|
||||||
|
var item = Dialog.pack2.eqs[$(this).attr("oindex")];
|
||||||
|
if (!item) return;
|
||||||
|
SendCommand(Dialog.pack2.command_before + " checkobj " + item.id + " from eq");
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
156
src/dialog/paimai.js
Normal file
156
src/dialog/paimai.js
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
|
||||||
|
|
||||||
|
const paimai_css = `
|
||||||
|
.dialog-pms {
|
||||||
|
max-height: 32em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-pms>.empty {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 3em;
|
||||||
|
margin-bottom: 3em;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-pms>.pm-item {
|
||||||
|
border-radius: 6px;
|
||||||
|
background-color: #111111;
|
||||||
|
border-left-width: 4px;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-color: gray;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
line-height: 2em;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-pms>.selected {
|
||||||
|
border-left-color: #00ff00;
|
||||||
|
background-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-pms>.pm-item>.pm-title {
|
||||||
|
width: 10em;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-pms>.pm-item>.pm-desc {
|
||||||
|
min-width: 10em;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-pms>.pm-item>.pm-mem {
|
||||||
|
|
||||||
|
padding-right: 1em;
|
||||||
|
color: gray;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-pms>.pm-item>.pm-add {
|
||||||
|
width: 4em;
|
||||||
|
border-left: 1px solid #343434;
|
||||||
|
text-align: center;
|
||||||
|
color: #008080
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-pms>.pm-item>.pm-add:hover {
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
function format_time_span(time) {
|
||||||
|
let diff = Math.floor((time) / 1000);
|
||||||
|
if (diff < 0) diff = 0;
|
||||||
|
if (diff > 3600) {
|
||||||
|
let str = Math.floor(diff / 3600) + "小时";
|
||||||
|
diff = diff % 3600;
|
||||||
|
str += Math.floor(diff / 60) + "分";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
let str = Math.floor(diff / 60) + "分";
|
||||||
|
diff = diff % 60;
|
||||||
|
|
||||||
|
return str + diff + "秒";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
init: function () {
|
||||||
|
Dialog.injectStyle(paimai_css);
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
}, onData: function (data) {
|
||||||
|
if (data.list) {
|
||||||
|
this.show();
|
||||||
|
this.create_items(data.list);
|
||||||
|
} else if (data.item) {
|
||||||
|
this.update_item(data.item);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
show: function () {
|
||||||
|
if (!Dialog.isShow || Dialog.curItem != "pm")
|
||||||
|
Dialog.show("pm");
|
||||||
|
if (!this.element)
|
||||||
|
this.element = $("<div class='dialog-pms'></div>");
|
||||||
|
if (this.isShow) return;
|
||||||
|
Dialog.title("拍卖行");
|
||||||
|
Dialog.icon("shopping-cart");
|
||||||
|
Dialog.footer("");
|
||||||
|
this.element.appendTo(Dialog.contentElement);
|
||||||
|
this.element.on('click', '.pm-item', this.select_item);
|
||||||
|
this.isShow = true;
|
||||||
|
},
|
||||||
|
select_item: function () {
|
||||||
|
let elem = $(this);
|
||||||
|
let dialog = Dialog.pm;
|
||||||
|
if (dialog.selected_item)
|
||||||
|
dialog.selected_item.removeClass('selected');
|
||||||
|
dialog.selected_item = elem;
|
||||||
|
dialog.selected_item.addClass('selected');
|
||||||
|
}, update_item: function (item) {
|
||||||
|
let elem = this.element.find('.pm-item[oid="' + item[0] + '"]');
|
||||||
|
if (elem) elem.replaceWith(this.create_item(item));
|
||||||
|
},
|
||||||
|
create_items: function (list) {
|
||||||
|
let str = [];
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
str.push(this.create_item(list[i]));
|
||||||
|
}
|
||||||
|
if (!str.length) str.push('<div class="empty">暂无拍卖</div>');
|
||||||
|
this.element.html(str.join(""));
|
||||||
|
Dialog.footer('<span class="obj-money">共有'
|
||||||
|
+ list.length + '项道具正在拍卖</span>');
|
||||||
|
|
||||||
|
}, create_item: function (item) {
|
||||||
|
let str = [];
|
||||||
|
const [id, name, money, time, uname] = item;
|
||||||
|
str.push("<div class='pm-item grade0 flex-row' oid='", id, "'>");
|
||||||
|
str.push("<div class='pm-title' cmd='pm show ", id, "'>");
|
||||||
|
str.push(name);
|
||||||
|
str.push("</div>");
|
||||||
|
|
||||||
|
str.push("<div class='pm-desc flex-1'>");
|
||||||
|
if (uname) {
|
||||||
|
str.push(uname, '最后出价', moneyToStr(money),);
|
||||||
|
} else {
|
||||||
|
str.push('当前价格', moneyToStr(money),);
|
||||||
|
}
|
||||||
|
str.push("</div>");
|
||||||
|
|
||||||
|
str.push("<div class='pm-mem'>");
|
||||||
|
str.push('剩余:', format_time_span(time), '');
|
||||||
|
str.push("</div>");
|
||||||
|
str.push("<div class='pm-add' cmd='pm add ", id, "'>");
|
||||||
|
str.push('出价');
|
||||||
|
str.push("</div>");
|
||||||
|
str.push("</div>");
|
||||||
|
return str.join("");
|
||||||
|
},
|
||||||
|
format_num: function (num) {
|
||||||
|
return num > 9 ? num.toString() : "0" + num.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
268
src/dialog/party.js
Normal file
268
src/dialog/party.js
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
|
||||||
|
|
||||||
|
const party_css = `
|
||||||
|
.dialog-party>wht {
|
||||||
|
display: inline-block;
|
||||||
|
height: 15rem;
|
||||||
|
line-height: 15rem;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.dialog-party-add {
|
||||||
|
margin-top: 2em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.dialog-party-add>input {
|
||||||
|
border: 1px solid gray;
|
||||||
|
background-color: transparent;
|
||||||
|
color: unset;
|
||||||
|
resize: none;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
line-height: 2em;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-title {
|
||||||
|
font-size: 2rem;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
height: 2rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
opacity: 0.7;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-notice {
|
||||||
|
padding-top: 0.25em;
|
||||||
|
padding-bottom: 0.25em;
|
||||||
|
color: #00FFFF;
|
||||||
|
line-height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-notice>*>span {
|
||||||
|
|
||||||
|
width: 3em;
|
||||||
|
display: inline-block;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-title>.party-count {
|
||||||
|
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-title>*>.glyphicon {
|
||||||
|
|
||||||
|
padding-right: 0.5em;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-roles {
|
||||||
|
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-roles>.party-role,
|
||||||
|
.dialog-party>.party-item {
|
||||||
|
|
||||||
|
padding-left: 0.5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-color: gray;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
line-height: 2em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-item {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-item>.party-item-name {
|
||||||
|
padding-left: 0.5em;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-item>.party-item-sc {
|
||||||
|
|
||||||
|
flex: 0;
|
||||||
|
margin-left: 1em;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-item>.party-item-cmd {
|
||||||
|
flex: 0;
|
||||||
|
background-color: #222;
|
||||||
|
padding-left: 1em;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-roles>.party-role>.role-level {
|
||||||
|
|
||||||
|
width: 3em;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-roles>.party-role>.role-name {
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-party>.party-roles>.party-role>.role-sc {
|
||||||
|
float: right;
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
init: function () {
|
||||||
|
Dialog.injectStyle(party_css);
|
||||||
|
},
|
||||||
|
createElement: function () {
|
||||||
|
return $('<div class="dialog-party"></div>');
|
||||||
|
},
|
||||||
|
inner_show: function () {
|
||||||
|
//需要优化
|
||||||
|
SendCommand("party load");
|
||||||
|
this.isShow = true;
|
||||||
|
Dialog.title("");
|
||||||
|
this.element.on("click", '.party-role', this.show_commands);
|
||||||
|
Dialog.icon("flag");
|
||||||
|
},
|
||||||
|
levels: ["", "<hio>帮主<hio>", "<hiz>副帮主</hiz>", "<hiy>长老</hiy>", "<hic>堂主</hic>", "帮众"],
|
||||||
|
level_roles: [1, 20, 30, 40, 50, 60],
|
||||||
|
level: 5,
|
||||||
|
get_role: function (id) {
|
||||||
|
if (!this.roles) return;
|
||||||
|
for (var i = 0; i < this.roles.length; i++) {
|
||||||
|
if (this.roles[i].id == id) return this.roles[i];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
command: function (type) {
|
||||||
|
if (type === 'create') {
|
||||||
|
|
||||||
|
let str = ['<div class="dialog-party-add">'];
|
||||||
|
str.push('<div>创建帮派需要500两<hiy>黄金</hiy>,请输入帮派名称(2-5字中文):</div>');
|
||||||
|
|
||||||
|
str.push('<input type="text" ></input>');
|
||||||
|
|
||||||
|
str.push("<div class='item-commands'><span cmd='_party cancle'>取消</span><span cmd='_party create2'>确定</span></div>");
|
||||||
|
str.push('</div>');
|
||||||
|
this.element.html(str.join(""));
|
||||||
|
} else if (type === 'cancle') {
|
||||||
|
this.empty('你还没有加入帮派');
|
||||||
|
} else if (type === 'create2') {
|
||||||
|
let val = $('.dialog-party-add>input').val();
|
||||||
|
if (!val || val.length > 5 || val.length < 2)
|
||||||
|
return ReceiveMessage("帮派名字需要是2-5中文字符。");
|
||||||
|
SendCommand('party create2 ' + val);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, empty: function (str) {
|
||||||
|
this.element.html("<wht>" + str + "</wht><div class='item-commands'><span cmd='_party create'>创建帮派</span><span cmd='party list'>加入帮派</span></div>");
|
||||||
|
|
||||||
|
},
|
||||||
|
show_list: function (data) {
|
||||||
|
if (!data.list.length) return this.empty('现在没有已经创建的帮派');
|
||||||
|
var str = [];
|
||||||
|
for (let item of data.list) {
|
||||||
|
str.push("<div class='party-item'>");
|
||||||
|
str.push("<span class='party-item-name'>");
|
||||||
|
str.push(item[0]);
|
||||||
|
str.push("</span>");
|
||||||
|
str.push("<span class='party-item-sc'>人数:");
|
||||||
|
str.push(item[1]);
|
||||||
|
str.push("</span>");
|
||||||
|
str.push("<span class='party-item-cmd' cmd='party join ", item[0], "'>加入</span>");
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
this.element.html(str.join(""));
|
||||||
|
},
|
||||||
|
onData: function (data) {
|
||||||
|
if (data.list) return this.show_list(data);
|
||||||
|
if (!data.name) {
|
||||||
|
return this.empty('你还没有加入帮派');
|
||||||
|
}
|
||||||
|
var party = data;
|
||||||
|
|
||||||
|
Dialog.title('帮派【' + party.name + '】 <nor>' + data.roles.length + "/" + this.level_roles[data.level] + "</nor>");
|
||||||
|
var str = [];
|
||||||
|
// str.push("<div class='party-title'><hio>");
|
||||||
|
// str.push(party.name);
|
||||||
|
// str.push("</hio><span class='party-count'><nor>(" + data.roles.length + "/" + this.level_roles[data.level] + ")</nor></span>");
|
||||||
|
// str.push("</div>");
|
||||||
|
if (party.notice) {
|
||||||
|
str.push("<div class='party-notice'>");
|
||||||
|
str.push(party.notice);
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
str.push("<div class='party-roles'>");
|
||||||
|
for (var i = 0; i < party.roles.length; i++) {
|
||||||
|
var role = party.roles[i];
|
||||||
|
if (role.id == Process.player) {
|
||||||
|
this.level = role.level;
|
||||||
|
}
|
||||||
|
str.push("<div class='party-role' roleid='" + role.id + "'>");
|
||||||
|
str.push("<span class='role-level'>");
|
||||||
|
str.push(this.levels[role.level]);
|
||||||
|
str.push("</span>");
|
||||||
|
str.push("<span class='role-name'>");
|
||||||
|
str.push(role.name);
|
||||||
|
str.push("</span>");
|
||||||
|
str.push("<span class='role-sc'>");
|
||||||
|
str.push(role.sc);
|
||||||
|
str.push("</span>");
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
str.push("</div>");
|
||||||
|
this.roles = data.roles;
|
||||||
|
this.element.html(str.join(""));
|
||||||
|
}, show_commands: function () {
|
||||||
|
var role = Dialog.party.get_role($(this).attr("roleid"));
|
||||||
|
if (!role) return;
|
||||||
|
var html = ["<div class='item-commands'>"];
|
||||||
|
|
||||||
|
|
||||||
|
if (role.id == Process.player) {
|
||||||
|
html.push('<span cmd="party out">退出帮派</span>');
|
||||||
|
if (Dialog.party.level == 1) {
|
||||||
|
html.push('<span cmd="party dissmiss">解散</span>');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (role.level > Dialog.party.level - 1 && role.level > 2)
|
||||||
|
html.push('<span cmd="party uplevel ' + role.id + '">提升为' + (Dialog.party.levels[role.level - 1]) + '</span>');
|
||||||
|
if (role.level > Dialog.party.level && role.level < 5) {
|
||||||
|
html.push('<span cmd="party downlevel ' + role.id + '">降级为' + (Dialog.party.levels[role.level + 1]) + '</span>');
|
||||||
|
}
|
||||||
|
if (Dialog.party.level == 1 && role.level == 2) {
|
||||||
|
html.push('<span cmd="party trans ' + role.id + '">让位</span>');
|
||||||
|
}
|
||||||
|
if (role.level > Dialog.party.level)
|
||||||
|
html.push('<span cmd="party remove ' + role.id + '">开除</span>');
|
||||||
|
if (role.online) {
|
||||||
|
html.push('<span cmd="team add ' + role.id + '">邀请组队</span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (html.length == 1) return;
|
||||||
|
html.push("</div>");
|
||||||
|
Dialog.party.element.find(".item-commands").remove();
|
||||||
|
$(html.join("")).insertAfter(this);
|
||||||
|
},
|
||||||
|
inner_close: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
94
src/dialog/relation.js
Normal file
94
src/dialog/relation.js
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
init: function () { },
|
||||||
|
createElement: function () {
|
||||||
|
return $('<div class="dialog-relation"></div>');
|
||||||
|
},
|
||||||
|
inner_show: function () {
|
||||||
|
SendCommand("relation");
|
||||||
|
this.isShow = true;
|
||||||
|
Dialog.title("关系");
|
||||||
|
Dialog.icon("heart");
|
||||||
|
},
|
||||||
|
onData: function (data) {
|
||||||
|
var str = [];
|
||||||
|
str.push("<div class='relation-item'>");
|
||||||
|
str.push("<div class='relation-desc'>");
|
||||||
|
if (data.husband) {
|
||||||
|
str.push("你的丈夫:");
|
||||||
|
str.push(data.husband);
|
||||||
|
} else if (data.wife) {
|
||||||
|
str.push("你的妻子:");
|
||||||
|
str.push(data.wife);
|
||||||
|
} else {
|
||||||
|
str.push("你目前没有结婚。");
|
||||||
|
}
|
||||||
|
str.push("</div>");
|
||||||
|
if (data.wife || data.husband) {
|
||||||
|
str.push("<div class='relation-cmd' cmd='_confirm greet wife'><him>❀送花❀</him></div>");
|
||||||
|
str.push("<div class='relation-cmd' cmd='rel marry'>解除关系</div>");
|
||||||
|
}
|
||||||
|
str.push("</div>");
|
||||||
|
|
||||||
|
str.push("<div class='relation-item'>");
|
||||||
|
str.push("<div class='relation-desc'>");
|
||||||
|
if (data.shifu) {
|
||||||
|
str.push("你的师父:");
|
||||||
|
str.push(data.shifu);
|
||||||
|
} else if (data.tudi) {
|
||||||
|
str.push("你的徒弟:");
|
||||||
|
str.push(data.tudi);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
str.push("你目前没有拜师,也没有收徒。");
|
||||||
|
}
|
||||||
|
str.push("</div>");
|
||||||
|
if (data.shifu) {
|
||||||
|
str.push("<div class='relation-cmd' cmd='greet master'><hig>请安</hig></div>");
|
||||||
|
str.push("<div class='relation-cmd' cmd='rel st'>出师</div>");
|
||||||
|
|
||||||
|
str.push("</div>");
|
||||||
|
} else if (data.tid) {
|
||||||
|
str.push("<div class='relation-cmd' cmd='rel st'>解除关系</div>");
|
||||||
|
}
|
||||||
|
str.push("</div>");
|
||||||
|
|
||||||
|
if (data.st != undefined) {
|
||||||
|
str.push("<div class='relation-item'><div class='relation-desc'>");
|
||||||
|
str.push("当师徒组队完成副本后将获得额外奖励,本周已完成" + data.st + "/10。", '</div>');
|
||||||
|
str.push("<div class='relation-cmd' cmd='team add ",
|
||||||
|
data.tid ?? data.shifu, "'>邀请组队</div>");
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
if (data.reward) {
|
||||||
|
str.push("<div class='relation-item'>");
|
||||||
|
str.push(data.reward)
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
str.push("</div>");
|
||||||
|
if (data.fls) {
|
||||||
|
for (let item of data.fls) {
|
||||||
|
if (!item) continue;
|
||||||
|
str.push("<div class='relation-item'>");
|
||||||
|
str.push("<div class='relation-desc'>你的家人:", item[0]);
|
||||||
|
if (item[2]) {
|
||||||
|
str.push(',已', item[2], format_time_span(item[3]));
|
||||||
|
str.push('</div>');
|
||||||
|
str.push("<div class='relation-cmd' cmd='rel ", item[1], " stop'>停止</div>");
|
||||||
|
} else {
|
||||||
|
str.push('空闲中</div>');
|
||||||
|
str.push("<div class='relation-cmd' cmd='rel ", item[1], " caiyao'><hic>采药</hic></div>");
|
||||||
|
str.push("<div class='relation-cmd' cmd='rel ", item[1], " diaoyu'><hic>钓鱼</hic></div>");
|
||||||
|
str.push("<div class='relation-cmd' cmd='rel ", item[1], " wk'><hic>挖矿</hic></div>");
|
||||||
|
}
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.element.html(str.join(""));
|
||||||
|
},
|
||||||
|
inner_close: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
333
src/dialog/score.js
Normal file
333
src/dialog/score.js
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
footer: [["属性", null],
|
||||||
|
["详细", null], ["称号", null]],
|
||||||
|
|
||||||
|
selectIndex: 0,
|
||||||
|
onData: function (data) {
|
||||||
|
console.log(data);
|
||||||
|
this.data = data;
|
||||||
|
this.init_elem();
|
||||||
|
Dialog.titleElement.html(data.name);
|
||||||
|
Dialog.icon("user");
|
||||||
|
if (data.titles) {
|
||||||
|
this.titles = data.titles;
|
||||||
|
this.create_titles();
|
||||||
|
} else {
|
||||||
|
if (data.id && data.id != this.uid) {
|
||||||
|
this.uid = data.id;
|
||||||
|
if (this.uid != Process.player) {
|
||||||
|
Dialog.footerElement.find(".footer-item:eq(2)").hide();
|
||||||
|
} else {
|
||||||
|
Dialog.footerElement.find(".footer-item:eq(2)").show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var panel = $(data.name ? this.footer[0][1] : this.footer[1][1]);
|
||||||
|
var elems = panel.find("span");
|
||||||
|
for (var i = 0; i < elems.length; i++) {
|
||||||
|
var elem = $(elems[i]);
|
||||||
|
var prop = elem.attr("data-prop");
|
||||||
|
if (prop) {
|
||||||
|
elem.html(data[prop] || 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
init: function () {
|
||||||
|
this.footer[0][1] = $(this.template_score);
|
||||||
|
this.footer[1][1] = $(this.template_score2);
|
||||||
|
this.footer[2][1] = $(this.template_title);
|
||||||
|
Dialog.injectStyle(this.css);
|
||||||
|
},
|
||||||
|
init_elem: function () {
|
||||||
|
Dialog.init();
|
||||||
|
Dialog.curItem = "score";
|
||||||
|
if (this.isShow) return;
|
||||||
|
Dialog.footer("");
|
||||||
|
|
||||||
|
for (var i = 0; i < this.footer.length; i++) {
|
||||||
|
$("<span class='footer-item " + (this.selectIndex == i ? "select" : "") + "' for='" + i + "'>"
|
||||||
|
+ this.footer[i][0] + "</span>").appendTo(Dialog.footerElement);
|
||||||
|
}
|
||||||
|
this.isShow = true;
|
||||||
|
this.footerChanged(this.selectIndex);
|
||||||
|
|
||||||
|
},
|
||||||
|
show: function (nosend) {
|
||||||
|
if (nosend) return;
|
||||||
|
if (!this.selectIndex) SendCommand("score");
|
||||||
|
else if (this.selectIndex == 1) SendCommand("score2");
|
||||||
|
else SendCommand("score title");
|
||||||
|
this.init_elem();
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.footer[this.selectIndex][1].remove();
|
||||||
|
Dialog.footer("");
|
||||||
|
this.isShow = false;
|
||||||
|
},
|
||||||
|
footerChanged: function (item) {
|
||||||
|
item = parseInt(item);
|
||||||
|
this.footer[this.selectIndex][1].remove();
|
||||||
|
this.selectIndex = item;
|
||||||
|
|
||||||
|
var panel = $(this.footer[this.selectIndex][1]).appendTo(Dialog.contentElement.empty());
|
||||||
|
if (item == 1) {
|
||||||
|
if (this.uid && Process.player != this.uid)
|
||||||
|
SendCommand("score2 " + this.uid);
|
||||||
|
else
|
||||||
|
SendCommand("score2");
|
||||||
|
}
|
||||||
|
else if (item == 2) {
|
||||||
|
if (!this.titles)
|
||||||
|
SendCommand("score title");
|
||||||
|
panel.on("click", ".btn-noused", function (e) {
|
||||||
|
var elem = $(e.target);
|
||||||
|
if (elem.is("red")) elem = elem.parent();
|
||||||
|
var index = parseInt(elem.attr("index"));
|
||||||
|
for (var i = 0; i < this.titles.length; i++) {
|
||||||
|
if (i == index) this.titles[i].use = this.titles[i].use ? false : true;
|
||||||
|
else this.titles[i].use = false;
|
||||||
|
}
|
||||||
|
SendCommand("title " + index);
|
||||||
|
this.create_titles();
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
create_titles: function () {
|
||||||
|
var panel = $(".dialog-titles");
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < this.titles.length; i++) {
|
||||||
|
html.push("<div class='title-item", this.titles[i].use ? " selected" : "", "'>");
|
||||||
|
html.push(this.titles[i].title);
|
||||||
|
html.push("<span class='btn-noused' index='");
|
||||||
|
html.push(i);
|
||||||
|
html.push("'>");
|
||||||
|
html.push(this.titles[i].use ? "<red>取消</red>" : "使用");
|
||||||
|
html.push("</span>");
|
||||||
|
|
||||||
|
html.push("</div>");
|
||||||
|
}
|
||||||
|
panel.html(html.length ? html.join("") : "<div class='empty'>你还没有获得任何称号</div>");
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
template_score: `
|
||||||
|
<div class="dialog-score" cellpadding="0" cellspacing="1">
|
||||||
|
<div class="score-section">
|
||||||
|
<span class="title">
|
||||||
|
<hic>【性别】</hic>
|
||||||
|
</span><span data-prop="gender" class="value"></span>
|
||||||
|
<span class="title">
|
||||||
|
<hic>【等级】</hic>
|
||||||
|
</span><span data-prop="level" class="value"></span><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【年龄】</hic>
|
||||||
|
</span><span data-prop="age" style="width:10em;" class="value">14</span><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【经验】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="exp" class="value">0</span></hic>
|
||||||
|
<span class="title">
|
||||||
|
<hic>【潜能】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="pot" class="value">0</span></hic>
|
||||||
|
</div>
|
||||||
|
<div class="score-section">
|
||||||
|
<div><span class="title">
|
||||||
|
<hig>【气血】</hig>
|
||||||
|
</span>
|
||||||
|
<hig><span data-prop="hp" class="value"
|
||||||
|
style="text-align:right">0</span><span> / </span><span class="value"
|
||||||
|
data-prop="max_hp">0</span></hig>
|
||||||
|
</div>
|
||||||
|
<div><span class="title">
|
||||||
|
<hig>【内力】</hig>
|
||||||
|
</span>
|
||||||
|
<hig><span data-prop="mp" class="value"
|
||||||
|
style="text-align:right">0</span><span> / </span><span class="value"
|
||||||
|
data-prop="max_mp">0</span></hig>
|
||||||
|
</div>
|
||||||
|
<span class="title" style="width:6em;">
|
||||||
|
<hic>【内力上限】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="limit_mp" class="value">0</span></hic><br />
|
||||||
|
<span class="title" style="width:6em;">
|
||||||
|
<hic>【精力】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="jingli" class="value">0</span></hic>
|
||||||
|
</div>
|
||||||
|
<div class="score-section">
|
||||||
|
<span class="title">
|
||||||
|
<hiy>【臂力】</hiy>
|
||||||
|
</span><span class="value">
|
||||||
|
<hiy><span data-prop="str">0</span></hiy>
|
||||||
|
<NOR> (+<span data-prop="str_add">0</span>)</NOR>
|
||||||
|
</span>
|
||||||
|
<span class="title">
|
||||||
|
<hiy>【根骨】</hiy>
|
||||||
|
</span><span class="value">
|
||||||
|
<hiy><span data-prop="con">0</span></hiy>
|
||||||
|
<NOR>(+<span data-prop="con_add">0</span>)</NOR>
|
||||||
|
</span><br />
|
||||||
|
<span class="title">
|
||||||
|
<hiy>【身法】</hiy>
|
||||||
|
</span><span class="value">
|
||||||
|
<hiy><span data-prop="dex">0</span></hiy>
|
||||||
|
<NOR>(+<span data-prop="dex_add">0</span>)</NOR>
|
||||||
|
</span>
|
||||||
|
<span class="title">
|
||||||
|
<hiy>【悟性】</hiy>
|
||||||
|
</span><span class="value">
|
||||||
|
<hiy><span data-prop="int">0</span></hiy>
|
||||||
|
<NOR>(+<span data-prop="int_add">0</span>)</NOR>
|
||||||
|
</span><br />
|
||||||
|
<span class="title">
|
||||||
|
<hiy>【容貌】</hiy>
|
||||||
|
</span><span class="value">
|
||||||
|
<hiy><span data-prop="per">0</span></hiy>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="score-section">
|
||||||
|
<span class="title">
|
||||||
|
<hic>【攻击】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="gj" class="value">0</span></hic>
|
||||||
|
<span class="title">
|
||||||
|
<hic>【防御】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="fy" class="value">0</span></hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【命中】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="mz" class="value">0</span></hic>
|
||||||
|
<span class="title">
|
||||||
|
<hic>【躲闪】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="ds" class="value">0</span></hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【招架】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="zj" class="value">0</span></hic>
|
||||||
|
<span class="title">
|
||||||
|
<hic>【暴击】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="bj" class="value">0</span></hic><br />
|
||||||
|
<span class="title" style="width:6em;">
|
||||||
|
<hic>【攻击速度】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="gjsd" class="value">0</span></hic>
|
||||||
|
</div>
|
||||||
|
<div class="score-section">
|
||||||
|
<span class="title">
|
||||||
|
<hic>【门派】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="family" class="value">无门无派</span></hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【师傅】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="master" class="value">无</span></hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【功绩】</hic>
|
||||||
|
</span>
|
||||||
|
<hic><span data-prop="gongji" class="value">0</span></hic><br />
|
||||||
|
</div>
|
||||||
|
</div>`,
|
||||||
|
template_score2: ` <div class="dialog-score2">
|
||||||
|
<span class="title">
|
||||||
|
<hic>【最终伤害】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="add_sh" class="value">0</span>
|
||||||
|
</hic>
|
||||||
|
<br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【忽视防御】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="diff_fy" class="value">0</span>
|
||||||
|
</hic><br />
|
||||||
|
|
||||||
|
<span class="title">
|
||||||
|
<hic>【暴击伤害】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="add_bj" class="value">0</span>
|
||||||
|
</hic>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span class="title">
|
||||||
|
<hic>【伤害减免】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="diff_sh" class="value">0</span>
|
||||||
|
</hic>
|
||||||
|
<br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【暴击抵抗】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="diff_bj" class="value">0</span>
|
||||||
|
</hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【释放时间减少】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="releasetime" class="value">0</span>
|
||||||
|
</hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【忙乱时间】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="busy" class="value">0</span>
|
||||||
|
</hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【忽视忙乱】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="diff_busy" class="value">0</span>
|
||||||
|
</hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【冷却时间减少】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="distime" class="value">0</span>
|
||||||
|
</hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【内力消耗减少】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="expend_mp" class="value">0</span>
|
||||||
|
</hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【负面抵抗】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="downside_per" class="value">0</span>
|
||||||
|
</hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【打坐效率】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="dazuo_per" class="value">0</span>
|
||||||
|
</hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【学习效率】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="study_per" class="value">0</span>
|
||||||
|
</hic><br />
|
||||||
|
<span class="title">
|
||||||
|
<hic>【练习效率】</hic>
|
||||||
|
</span>
|
||||||
|
<hic>
|
||||||
|
<span data-prop="lianxi_per" class="value">0</span>
|
||||||
|
</hic>
|
||||||
|
</div>`,
|
||||||
|
template_title: ` <div class="dialog-titles">
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
1087
src/dialog/setting.js
Normal file
1087
src/dialog/setting.js
Normal file
File diff suppressed because it is too large
Load Diff
274
src/dialog/shop.js
Normal file
274
src/dialog/shop.js
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import Util from '../utils/util.js';
|
||||||
|
export default {
|
||||||
|
init: function () {
|
||||||
|
Dialog.injectStyle(shop_css);
|
||||||
|
},
|
||||||
|
selected_item: 0,
|
||||||
|
close: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
}, onData: function (data) {
|
||||||
|
if (data.money) {
|
||||||
|
let ms = data.money ?? [0, 0];
|
||||||
|
this.money = ms[0];
|
||||||
|
this.cash_money = ms[1];
|
||||||
|
if (ms.length > 2) {
|
||||||
|
this.footers = ["黄金", "元宝", '活动'];
|
||||||
|
this.act_money = ms[2];
|
||||||
|
this.act_name = data.mtype ?? "<hic>积分</hic>";
|
||||||
|
}
|
||||||
|
this.create_footer();
|
||||||
|
}
|
||||||
|
if (data.remove) {
|
||||||
|
let item = this.get_item(data.remove);
|
||||||
|
if (item) item.removed = true;
|
||||||
|
return this.show_items();
|
||||||
|
}
|
||||||
|
if (data.item) {
|
||||||
|
let [id, count] = data.item;
|
||||||
|
let item = this.get_item(id);
|
||||||
|
if (item) {
|
||||||
|
item.count = count;
|
||||||
|
this.show_items();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.idx) return;
|
||||||
|
this.idx = data.idx;
|
||||||
|
this.list0 = this.format_items(data.selllist[0], 0);
|
||||||
|
this.list1 = this.format_items(data.selllist[1], 1);
|
||||||
|
if (data.selllist.length > 2)
|
||||||
|
this.list2 = this.format_items(data.selllist[2], 2);
|
||||||
|
|
||||||
|
this.show_items();
|
||||||
|
},
|
||||||
|
footerChanged: function (index) {
|
||||||
|
|
||||||
|
this.selected_item = parseInt(index);
|
||||||
|
this.show_items();
|
||||||
|
this.create_footer();
|
||||||
|
}, footers: ["黄金", "元宝"],
|
||||||
|
create_footer: function () {
|
||||||
|
if (!this.isShow) return;
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < this.footers.length; i++) {
|
||||||
|
html.push("<span class='footer-item" + (i == this.selected_item
|
||||||
|
? " select" : "") + "' for='" + i + "''>"
|
||||||
|
+ this.footers[i] + "</span>");
|
||||||
|
}
|
||||||
|
if (this.selected_item === 0) {
|
||||||
|
html.push('<div class="obj-money">',
|
||||||
|
this.money > 0 ? "你身上有" + Util.moneyToStr(this.money) : "你身上没有银两"
|
||||||
|
, '</div>');
|
||||||
|
} else if (this.selected_item === 1) {
|
||||||
|
html.push('<div class="obj-money">',
|
||||||
|
this.cash_money > 0 ? "你身上有" + this.cash_money
|
||||||
|
+ "<hij>元宝</hij>" : "你身上没有元宝"
|
||||||
|
, '<span cmd="transmoney">账号转入</span></div>');
|
||||||
|
} else if (this.selected_item === 2) {
|
||||||
|
html.push('<div class="obj-money">',
|
||||||
|
"你身上有", this.act_money > 0 ? this.act_money : 0
|
||||||
|
, this.act_name);
|
||||||
|
}
|
||||||
|
Dialog.footer(html.join(""));
|
||||||
|
},
|
||||||
|
format_items: function (ary, mtype) {
|
||||||
|
let items = [];
|
||||||
|
for (let data of ary) {
|
||||||
|
if (!data) continue;
|
||||||
|
let item = {
|
||||||
|
id: data[0], name: data[1],
|
||||||
|
desc: data[2], value: data[3], grade: data[4],
|
||||||
|
discount: data[5]
|
||||||
|
};
|
||||||
|
if (data[6]) {
|
||||||
|
item.limit = data[6];
|
||||||
|
item.count = data[7];
|
||||||
|
}
|
||||||
|
if (item.discount < 1) {
|
||||||
|
if (mtype === 0)
|
||||||
|
item.price0 = "<del>" + item.value + "两黄金</del>";
|
||||||
|
else if (mtype === 1)
|
||||||
|
item.price0 = "<del>" + item.value + "元宝</del>";
|
||||||
|
else if (mtype === 2)
|
||||||
|
item.price0 = "<del>" + item.value + this.act_name + "</del>";
|
||||||
|
item.value = item.value * item.discount;
|
||||||
|
}
|
||||||
|
if (mtype === 0) {
|
||||||
|
if (item.value >= 1)
|
||||||
|
item.price = "<hiy>" + item.value + "两黄金</hiy>";
|
||||||
|
else
|
||||||
|
item.price = "<wht>" + (item.value * 100) + "两白银</wht>";
|
||||||
|
} else if (mtype === 1) {
|
||||||
|
item.price = "<hij>" + item.value + "元宝</hij>";
|
||||||
|
} else if (mtype === 2) {
|
||||||
|
item.price = item.value + this.act_name;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
items.push(item);
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
, show_items: function () {
|
||||||
|
if (!this.isShow) return;
|
||||||
|
this.create_items([this.list0, this.list1, this.list2][this.selected_item]);
|
||||||
|
}, get_item: function (id) {
|
||||||
|
|
||||||
|
if (this.list0) for (let item of this.list0) if (item.id === id) return item;
|
||||||
|
if (this.list1) for (let item of this.list1) if (item.id === id) return item;
|
||||||
|
if (this.list2) for (let item of this.list2) if (item.id === id) return item;
|
||||||
|
},
|
||||||
|
show: function (data) {
|
||||||
|
if (!this.element) {
|
||||||
|
this.element = $("<div class='dialog-shop-content'><div class='dialog-shop'></div></div>");
|
||||||
|
}
|
||||||
|
Dialog.title("商品列表");
|
||||||
|
Dialog.icon("shopping-cart");
|
||||||
|
this.isShow = true;
|
||||||
|
this.element.appendTo(Dialog.contentElement);
|
||||||
|
if (!this.idx) SendCommand("shop");
|
||||||
|
else SendCommand("shop " + this.idx);
|
||||||
|
}, create_items: function (items) {
|
||||||
|
let str = [];
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
let item = items[i];
|
||||||
|
if (item.removed) {
|
||||||
|
items.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
str.push("<div class='shop-item");
|
||||||
|
str.push(' grade', item.grade);
|
||||||
|
str.push("'><div class='flex-1'><div class='shop-item-title'>");
|
||||||
|
|
||||||
|
str.push('<div class="shop-item-name">', item.name, '</div>');
|
||||||
|
if (item.limit > 0)
|
||||||
|
str.push("(", item.count, "/", item.limit, ")");
|
||||||
|
|
||||||
|
str.push("</div>");
|
||||||
|
str.push("<pre class='shop-desc'>");
|
||||||
|
str.push(item.desc)
|
||||||
|
str.push("</pre></div>");
|
||||||
|
str.push("<div class='shop-btn' ");
|
||||||
|
str.push('cmd="_confirm shop ', item.id);
|
||||||
|
if (item.limit > 0) {
|
||||||
|
str.push(' ', item.limit - item.count);
|
||||||
|
}
|
||||||
|
str.push('">');
|
||||||
|
if (item.price0) {
|
||||||
|
str.push(' ', item.price0, ' ');
|
||||||
|
}
|
||||||
|
str.push(item.price);
|
||||||
|
str.push("</div>");
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
this.element.find('.dialog-shop').html(str.join(""));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const shop_css = `
|
||||||
|
|
||||||
|
.dialog-shop-content {
|
||||||
|
height: 25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-shop {
|
||||||
|
max-height: 32em;
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-shop>.shop-item {
|
||||||
|
border-radius: 6px;
|
||||||
|
background-color: #111111;
|
||||||
|
border-left-width: 4px;
|
||||||
|
border-left-style: solid;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-item-title {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
line-height: 2em;
|
||||||
|
place-items: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-item-title>.shop-item-name {
|
||||||
|
margin: 0px;
|
||||||
|
color: var(--border-color);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-item-title>.discount-tag {
|
||||||
|
|
||||||
|
background: linear-gradient(135deg, #ff3e3e 0%, #ff9100 100%);
|
||||||
|
color: white;
|
||||||
|
width: 4em;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.dialog-shop>.shop-item .shop-desc {
|
||||||
|
margin: 0;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-shop>.shop-item .shop-label {
|
||||||
|
background: linear-gradient(110deg, transparent 0%, rgba(255, 159, 28, 0.8) 50%, transparent 100%);
|
||||||
|
|
||||||
|
animation: shine 3s infinite linear;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.dialog-shop>.shop-item>.shop-btn {
|
||||||
|
width: 8em;
|
||||||
|
display: inline-block;
|
||||||
|
border-left: 1px solid var(--border-color);
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: transparent;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #222;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-shop-footer {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-shop-footer>span {
|
||||||
|
line-height: 1.8em;
|
||||||
|
margin-left: 1em;
|
||||||
|
color: #808000;
|
||||||
|
display: inline-block;
|
||||||
|
padding-right: 1em;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: underline;
|
||||||
|
border-right: 1px solid #808000;
|
||||||
|
}
|
||||||
|
|
||||||
|
`;
|
||||||
534
src/dialog/skills.js
Normal file
534
src/dialog/skills.js
Normal file
@@ -0,0 +1,534 @@
|
|||||||
|
import Setting from '../setting.js';
|
||||||
|
import Util from '../utils/util.js';
|
||||||
|
import SCRIPT from '../script.js';
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
isShow: false,
|
||||||
|
selectItem: ".dialog-skills",
|
||||||
|
init: function () {
|
||||||
|
if (!this.created)
|
||||||
|
Dialog.injectStyle(skills_css);
|
||||||
|
this.created = true;
|
||||||
|
},
|
||||||
|
hide: function () {
|
||||||
|
if (this.skill_element) {
|
||||||
|
this.skill_element.remove();
|
||||||
|
this.skill_element = null;
|
||||||
|
this.element.removeClass("hide-item");
|
||||||
|
this.create_footer();
|
||||||
|
this.skill_element_id = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.hide();
|
||||||
|
this.element.remove();
|
||||||
|
//Dialog.footerElement.addClass("hide");
|
||||||
|
this.isShow = false;
|
||||||
|
this.skill_element_id = null;
|
||||||
|
this.element.removeClass("hide-item");
|
||||||
|
},
|
||||||
|
limit: 0,
|
||||||
|
selected_item: -1,
|
||||||
|
showdesc: function (data) {
|
||||||
|
if (!this.isShow) return;
|
||||||
|
this.element.find(".item-commands").remove();
|
||||||
|
if (this.skill_element) this.skill_element.remove();
|
||||||
|
this.skill_element = $("<pre></pre>").html(data.desc).appendTo(this.element);
|
||||||
|
// Dialog.title(data.title);
|
||||||
|
this.skill_element_id = data.id;
|
||||||
|
this.element.addClass("hide-item");
|
||||||
|
let html = ['<div class="item-commands">'];
|
||||||
|
|
||||||
|
if (this.master) {
|
||||||
|
html.push('<span cmd="xue ', data.id, ' from ', this.master, '">学习</span>');
|
||||||
|
if (this.is_follower) {
|
||||||
|
html.push('<span cmd="dc ', this.master, ' lingwu ', data.id, '">进阶</span>');
|
||||||
|
html.push('<span cmd="dc ', this.master, ' fangqi ', data.id, '">遗忘</span>');
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (data.is_custom)
|
||||||
|
html.push('<span cmd="zc ', data.id, '">推演</span>');
|
||||||
|
html.push('<span cmd="lingwu ', data.id, '">进阶</span>');
|
||||||
|
html.push('<span cmd="lingwu2 ', data.id, '">融合</span>');
|
||||||
|
html.push('<span cmd="fangqi ', data.id, '">遗忘</span>');
|
||||||
|
}
|
||||||
|
html.push('</div>');
|
||||||
|
Dialog.footer(html.join(""));
|
||||||
|
|
||||||
|
},
|
||||||
|
footerChanged: function (index, ref) {
|
||||||
|
if (index == this.selected_item && !ref) return;
|
||||||
|
this.selected_item = index;
|
||||||
|
Dialog.skills.element.find(".item-commands").remove();
|
||||||
|
if (index == 2) {
|
||||||
|
if (!this.books) SendCommand('sbook');
|
||||||
|
else this.showBooks();
|
||||||
|
return this.element.addClass("dialog-books");
|
||||||
|
}
|
||||||
|
if (this.element.is('.dialog-books')) {
|
||||||
|
this.element.removeClass('dialog-books');
|
||||||
|
this.create_footer();
|
||||||
|
return this.createSkillItems(this.items);
|
||||||
|
}
|
||||||
|
if (index == 0) {
|
||||||
|
this.element.find('.base').removeClass('hide');
|
||||||
|
this.element.find(".skill").addClass('hide');
|
||||||
|
} else if (index == 1) {
|
||||||
|
this.element.find('.base').addClass('hide');
|
||||||
|
this.element.find(".skill").removeClass('hide');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
footers: ["基础", "特殊", "书架"],
|
||||||
|
eq_group: 0,
|
||||||
|
create_footer: function (isbook) {
|
||||||
|
var footers = this.footers;
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < footers.length; i++) {
|
||||||
|
html.push("<span class='footer-item" +
|
||||||
|
(i == this.selected_item ? " select" : "") + "' for='" + i + "''>"
|
||||||
|
+ footers[i] + "</span>");
|
||||||
|
}
|
||||||
|
// if (isbook)
|
||||||
|
// html.push("<span class='obj-money'>你的书架目前有<HIC>" + this.books.length + "</HIC>本秘籍</span>");
|
||||||
|
// else
|
||||||
|
// html.push("<span class='obj-money'>你目前的技能上限为<HIC>" + this.limit + "</HIC>级</span>");
|
||||||
|
if (!isbook) {
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
html.push('<span class="sk-group',
|
||||||
|
2 - i === this.sk_group ? " select" : "",
|
||||||
|
'" group="', 2 - i, '">', 3 - i, '</span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dialog.footer(html.join(""));
|
||||||
|
},
|
||||||
|
eq_group_click: function () {
|
||||||
|
let group = parseInt($(this).attr('group'));
|
||||||
|
if (group >= 0) SendCommand('skgroup ' + group);
|
||||||
|
},
|
||||||
|
updateSkill: function (data) {
|
||||||
|
if (!this.skills) return;
|
||||||
|
var item = this.skills[data.id];
|
||||||
|
if (!item) {
|
||||||
|
|
||||||
|
return this.addSkill(item);
|
||||||
|
}
|
||||||
|
if (data.name)
|
||||||
|
item.name = data.name;
|
||||||
|
if (data.grade >= 0 && data.grade !== item.grade) {
|
||||||
|
item.grade = data.grade;
|
||||||
|
if (item.can_enables) {
|
||||||
|
for (let sk of item.can_enables) {
|
||||||
|
let base_skill = this.skills[sk];
|
||||||
|
if (base_skill && base_skill.enable_skill === data.id) {
|
||||||
|
this.updateSkillItem(base_skill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.enable) {
|
||||||
|
if (item.enable_skill) {
|
||||||
|
var old_skill = item.enable_skill;
|
||||||
|
item.enable_skill = null;
|
||||||
|
this.skills[old_skill][data.id] = false;
|
||||||
|
this.updateSkillItem(this.skills[old_skill]);
|
||||||
|
}
|
||||||
|
this.skills[data.enable][data.id] = true;
|
||||||
|
item.enable_skill = data.enable;
|
||||||
|
this.updateSkillItem(this.skills[data.enable]);
|
||||||
|
this.updateSkillItem(this.skills[data.id]);
|
||||||
|
} else if (data.exp != undefined || data.level != undefined) {
|
||||||
|
if (data.level >= 0) item.level = data.level;
|
||||||
|
if (data.exp >= 0) item.exp = data.exp;
|
||||||
|
if (data.can_enables) item.can_enables = data.can_enables;
|
||||||
|
this.updateSkillItem(item);
|
||||||
|
}
|
||||||
|
else if (data.enable == false) {
|
||||||
|
if (item.enable_skill) {
|
||||||
|
var old_skill = item.enable_skill;
|
||||||
|
this.skills[old_skill][data.id] = false;
|
||||||
|
item.enable_skill = null;
|
||||||
|
this.updateSkillItem(this.skills[old_skill]);
|
||||||
|
this.updateSkillItem(this.skills[data.id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, updateSkillItem: function (item) {
|
||||||
|
var sk_elem = this.element.find(".skill-item[skid='" + item.id + "']");
|
||||||
|
if (sk_elem) {
|
||||||
|
let hide = sk_elem.css('display') === 'none';
|
||||||
|
sk_elem.replaceWith(this.createSkillItem(item));
|
||||||
|
if (hide) sk_elem.hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addSkill: function (item) {
|
||||||
|
|
||||||
|
if (!this.items || !item) return;
|
||||||
|
if (this.skills[item.id]) {
|
||||||
|
return this.updateSkill(item);
|
||||||
|
}
|
||||||
|
this.items.push(item);
|
||||||
|
this.skills[item.id] = item;
|
||||||
|
this.items = this.sort_items(this.items);
|
||||||
|
this.createSkillItems(this.items);
|
||||||
|
}, format_books: function (data) {
|
||||||
|
let books = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
books.push({
|
||||||
|
name: data[i][0],
|
||||||
|
grade: data[i][1],
|
||||||
|
id: i
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return books;
|
||||||
|
},
|
||||||
|
onData: function (data) {
|
||||||
|
if (data.book) {
|
||||||
|
if (!this.books) return;
|
||||||
|
this.books.push({ name: data.book[0], grade: data.book[1], id: data.book[2] });
|
||||||
|
if (this.isShow && this.selected_item == 2) {
|
||||||
|
return this.showBooks();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data.books) {
|
||||||
|
this.books = this.format_books(data.books);
|
||||||
|
if (this.isShow || !Dialog.master.isShow)
|
||||||
|
return this.showBooks();
|
||||||
|
else
|
||||||
|
return Dialog.master.showBooks();
|
||||||
|
}
|
||||||
|
if (data.id && !data.desc) {
|
||||||
|
if (data.from)
|
||||||
|
return this.updateSkill.call(Dialog.master, data);
|
||||||
|
return this.updateSkill(data);
|
||||||
|
}
|
||||||
|
if (data.item) {
|
||||||
|
if (Dialog.master.isShow && Dialog.master.is_follower) {
|
||||||
|
return this.addSkill.call(Dialog.master, data.item);
|
||||||
|
}
|
||||||
|
return this.addSkill(data.item);
|
||||||
|
}
|
||||||
|
if (!this.isShow) {
|
||||||
|
if (Dialog.master.isShow)
|
||||||
|
return Dialog.master.onData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.desc) {
|
||||||
|
if (data.id) this.updateSkill(data);
|
||||||
|
return this.showdesc(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (data.remove && this.items) {
|
||||||
|
if (data.from && data.from !== Process.player) return;
|
||||||
|
this.items.Remove(this.skills[data.remove]);
|
||||||
|
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].enable_skill == data.remove) {
|
||||||
|
this.items[i].enable_skill = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete this.skills[data.remove];
|
||||||
|
if (this.skill_element && this.skill_element_id === data.remove) {
|
||||||
|
this.hide();
|
||||||
|
}
|
||||||
|
return this.createSkillItems(this.items);
|
||||||
|
}
|
||||||
|
if (data.items) {
|
||||||
|
this.title = data.title;
|
||||||
|
Dialog.title(this.title + ",等级上限" + data.limit + "级");
|
||||||
|
Dialog.icon("book");
|
||||||
|
this.items = this.sort_items(data.items);
|
||||||
|
this.skills = {};
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
var item = this.items[i];
|
||||||
|
this.skills[item.id] = item;
|
||||||
|
}
|
||||||
|
if (this.items.length > 10 && this.selected_item < 0) {
|
||||||
|
this.footerChanged(0);
|
||||||
|
}
|
||||||
|
this.createSkillItems(this.items);
|
||||||
|
}
|
||||||
|
if (data.sk_group >= 0) {
|
||||||
|
this.sk_group = data.sk_group;
|
||||||
|
this.limit = data.limit;
|
||||||
|
this.create_footer();
|
||||||
|
}
|
||||||
|
if (data.limit >= 0) {
|
||||||
|
this.limit = data.limit;
|
||||||
|
Dialog.title(this.title + ",等级上限" + this.limit + "级");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
show: function () {
|
||||||
|
if (this.isShow) return;
|
||||||
|
this.isShow = true;
|
||||||
|
if (!this.element) {
|
||||||
|
// this.container = $('<div class="skill-container"><div class="skill-sider"><div class="skill-sider-item select">1</div><div class="skill-sider-item">2</div><div class="skill-sider-item">3</div></div></div>');
|
||||||
|
this.element = $('<div class="dialog-skills"></div>');
|
||||||
|
Dialog.footerElement
|
||||||
|
.on("click", ".sk-group", Dialog.skills.eq_group_click);
|
||||||
|
}
|
||||||
|
this.element.on("click", ".skill-item", Dialog.skills.item_click);
|
||||||
|
//Dialog.footerElement.remveClass("hide");
|
||||||
|
this.element.appendTo(Dialog.contentElement);
|
||||||
|
//this.container.appendTo(Dialog.contentElement);
|
||||||
|
this.element.removeClass("hide-item");
|
||||||
|
if (!this.items) SendCommand("cha");
|
||||||
|
else {
|
||||||
|
SendCommand("cha none");
|
||||||
|
Dialog.icon("book");
|
||||||
|
this.create_footer();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isEnable: function (item, skills) {
|
||||||
|
if (!item.can_enables) return false;
|
||||||
|
for (var i = 0; i < item.can_enables.length; i++) {
|
||||||
|
var base_skill = skills[item.can_enables[i]];
|
||||||
|
if (base_skill && base_skill.enable_skill == item.id) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
showBooks: function () {
|
||||||
|
var html = [];
|
||||||
|
var books = this.sort_items(this.books);
|
||||||
|
for (let item of books) {
|
||||||
|
html.push('<div class="book-item ');
|
||||||
|
html.push('grade', item.grade, '" >');
|
||||||
|
html.push('<div class="book-name">', item.name, '</div>');
|
||||||
|
html.push('<div class="book-action border-right" cmd="sbook ', item.id, '">查看</div>');
|
||||||
|
html.push('<div class="book-action" cmd="study ', item.id, '">学习</div>');
|
||||||
|
html.push('</div>');
|
||||||
|
}
|
||||||
|
this.element.html(html.join(""));
|
||||||
|
this.create_footer(true);
|
||||||
|
},
|
||||||
|
createSkillItem: function (item, skills) {
|
||||||
|
skills = skills || this.skills;
|
||||||
|
var html = [];
|
||||||
|
html.push('<div class="skill-item ');
|
||||||
|
html.push('grade' + item.grade);
|
||||||
|
if (!this.master) {
|
||||||
|
if (item.can_enables) {
|
||||||
|
html.push(' skill');
|
||||||
|
if (this.selected_item == 0) html.push(' hide');
|
||||||
|
} else {
|
||||||
|
html.push(' base');
|
||||||
|
if (this.selected_item == 1) html.push(' hide');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var is_enable = this.isEnable(item, skills);
|
||||||
|
if (is_enable) {
|
||||||
|
html.push(' enable');
|
||||||
|
}
|
||||||
|
html.push('" skid="' + item.id + '">');
|
||||||
|
|
||||||
|
html.push('<span class="glyphicon glyphicon-ok enable-flag"></span>');
|
||||||
|
html.push(item.name);
|
||||||
|
// html.push('</', lvcolor, '>');
|
||||||
|
if (item.enable_skill && skills) {
|
||||||
|
var sp_skill = skills[item.enable_skill];
|
||||||
|
if (sp_skill) {
|
||||||
|
html.push('<span class="enable_skill">已装备:');
|
||||||
|
html.push(wrap_name(sp_skill));
|
||||||
|
html.push("</span>");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push('<span class="skill-level">');
|
||||||
|
// var lv_desc = this.get_lvdesc(item.level);
|
||||||
|
//push(lv_desc.replace(">", ">" + item.level + '级 / ' + item.exp + "%" + ' '));
|
||||||
|
html.push(item.level);
|
||||||
|
html.push('级 / ');
|
||||||
|
html.push(item.exp);
|
||||||
|
html.push("%");
|
||||||
|
html.push(' ');
|
||||||
|
html.push(Dialog.skills.get_lvdesc(item.level));
|
||||||
|
html.push('</span></div>');
|
||||||
|
return html.join("");
|
||||||
|
},
|
||||||
|
sort_items: function (items) {
|
||||||
|
if (!items || !Setting.auto_sortitem) return items;
|
||||||
|
var list = [];
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
var item = items[i];
|
||||||
|
var isok = false;
|
||||||
|
for (var j = 0; j < list.length; j++) {
|
||||||
|
if (item.grade > list[j].grade) {
|
||||||
|
list.splice(j, 0, item);
|
||||||
|
isok = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isok) {
|
||||||
|
list.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
},
|
||||||
|
createSkillItems: function (items, skills) {
|
||||||
|
let html = [];
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
html.push(this.createSkillItem(items[i], skills));
|
||||||
|
}
|
||||||
|
this.element.html(html.join(""));
|
||||||
|
|
||||||
|
}, level_color: ["wht", "hig", "hic", "hij", "hiz", "hio", "ord"]
|
||||||
|
, get_lvdesc: function (level) {
|
||||||
|
if (level < 1000)
|
||||||
|
return Dialog.skills.skill_levels[parseInt(level / 50)];
|
||||||
|
var v = parseInt((level - 1000) / 500);
|
||||||
|
if (v > 6) v = 6;
|
||||||
|
return Dialog.skills.skill_levels[v + 20];
|
||||||
|
},
|
||||||
|
skill_levels: [
|
||||||
|
"<BLU>初学乍练</BLU>", "<BLU>不知所以</BLU>", "<HIB>粗通皮毛</HIB>", "<HIB>渐有所悟</HIB>",
|
||||||
|
"<YEL>半生不熟</YEL>", "<YEL>马马虎虎</YEL>", "<HIY>平淡无奇</HIY>", "<HIY>触类旁通</HIY>",
|
||||||
|
"<HIG>心领神会</HIG>", "<HIG>挥洒自如</HIG>", "<HIC>驾轻就熟</HIC>", "<HIC>出类拔萃</HIC>",
|
||||||
|
"<CYN>初入佳境</CYN>", "<CYN>神乎其技</CYN>", "<MAG>威不可当</MAG>",
|
||||||
|
"<HIW>豁然贯通</HIW>", "<HIW>超群绝伦</HIW>", "<RED>登峰造极</RED>", "<WHT>登堂入室</WHT>",
|
||||||
|
"<HIM>一代宗师</HIM>", "<WHT>超凡入圣</WHT>", "<HIO>出神入化</HIO>", "<HIO>独步天下</HIO>",
|
||||||
|
"<HIR>空前绝后</HIR>", "<HIR>旷古绝伦</HIR>", "<HIW>深不可测</HIW>", "<HIW>返璞归真</HIW>"]
|
||||||
|
,
|
||||||
|
item_click: function () {
|
||||||
|
var elem = $(this);
|
||||||
|
var html = ["<div class='item-commands'>"];
|
||||||
|
var item = Dialog.skills.skills[elem.attr("skid")];
|
||||||
|
if (!item) return;
|
||||||
|
html.push('<span cmd="checkskill ' + item.id + '">查看详细</span>');
|
||||||
|
if (item.can_enables) {
|
||||||
|
for (var i = 0; i < item.can_enables.length; i++) {
|
||||||
|
var baseSkill = Dialog.skills.skills[item.can_enables[i]];
|
||||||
|
if (!baseSkill) continue;
|
||||||
|
if (baseSkill.enable_skill != item.id)
|
||||||
|
html.push('<span cmd="enable ' + baseSkill.id + ' ' + item.id + '">装备' + baseSkill.name + '</span>');
|
||||||
|
else {
|
||||||
|
html.push('<span cmd="enable ' + baseSkill.id + ' none">取消装备' + baseSkill.name + '</span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item.enable_skill) {
|
||||||
|
var sp_skill = Dialog.skills.skills[item.enable_skill];
|
||||||
|
if (sp_skill) html.push('<span cmd="enable ' + item.id + ' none">取消装备' + sp_skill.name + '</span>');
|
||||||
|
else item.enable_skill = null;
|
||||||
|
}
|
||||||
|
html.push('<span cmd="_confirm fangqi ' + item.id + '">遗忘</span>');
|
||||||
|
html.push('<span cmd="lianxi ' + item.id + '">练习</span>');
|
||||||
|
SCRIPT.LAST_OBJ = item;
|
||||||
|
let commands = Dialog.extend.query('skill', item);
|
||||||
|
for (let item of commands) {
|
||||||
|
html.push('<span cmd="', item.cmd, '">', item.name, '</span>');
|
||||||
|
}
|
||||||
|
html.push("</div>");
|
||||||
|
Dialog.skills.element.find(".item-commands").remove();
|
||||||
|
$(html.join("")).insertAfter(elem);
|
||||||
|
Util.checkScroll(elem.next());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const level_desc = ["wht", "hig", "hic", "hiy", "him", "hio", 'ord'];
|
||||||
|
function wrap_name(obj) {
|
||||||
|
let tag = level_desc[obj.grade];
|
||||||
|
return `<${tag}>${obj.name}</${tag}>`;
|
||||||
|
}
|
||||||
|
const skills_css = `
|
||||||
|
.dialog-skills {
|
||||||
|
overflow-y: auto;
|
||||||
|
min-height: 15em;
|
||||||
|
max-height: 35em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide-item {}
|
||||||
|
|
||||||
|
.dialog-skills>pre {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-skills>.skill-item {
|
||||||
|
line-height: 2em;
|
||||||
|
padding-left: 1.5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-style: solid;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.hide-item>.skill-item {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-skills>.dialog-books>.skill-item {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-skills>.skill-item>.skill-level {
|
||||||
|
float: right;
|
||||||
|
margin-right: 0.625em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-skills>.skill-item>.enable-flag {
|
||||||
|
display: none;
|
||||||
|
color: var(--border-color);
|
||||||
|
line-height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-skills>.enable {
|
||||||
|
padding-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-skills>.enable>.enable-flag {
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: 0.25em;
|
||||||
|
padding-right: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-skills>.skill-item>.enable_skill {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-skills>.enable>.item-commands {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-skills>.book-item {
|
||||||
|
line-height: 2em;
|
||||||
|
padding-left: 1.5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-style: solid;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-skills>.book-item>.book-name {
|
||||||
|
flex: 1;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: var(--border-color);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-skills>.book-item>.book-action {
|
||||||
|
flex: 0;
|
||||||
|
background-color: #222;
|
||||||
|
padding-left: 1em;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
`;
|
||||||
354
src/dialog/stats.js
Normal file
354
src/dialog/stats.js
Normal file
@@ -0,0 +1,354 @@
|
|||||||
|
|
||||||
|
|
||||||
|
const STATS_SILDER1 = [["总榜", ''], ["武当派", 'wudang'], ["少林派", 'shaolin'], ["华山派", 'huashan'],
|
||||||
|
["峨眉派", 'emei'], ["逍遥派", 'xiaoyao'], ["丐帮", 'gaibang'], ["杀手楼", 'shashou'],
|
||||||
|
["无门无派", 'none']];
|
||||||
|
const STATS_SILDER2 = [
|
||||||
|
["武器", ""], ["衣服", "cloth"], ["鞋", "shoes"], ["头部", "head"],
|
||||||
|
["披风", "cape"], ["戒指", "ring"], ["项链", "necklace"], ["饰品", "jewels"],
|
||||||
|
["护腕", "wrist"], ["腰带", "waist"], ["暗器", "throwing"]
|
||||||
|
];
|
||||||
|
export default {
|
||||||
|
footers: [{ cmd: "score", name: "综合榜", selected_silder: "", silder: STATS_SILDER1 },
|
||||||
|
{ cmd: "top", name: "高手榜", selected_silder: "", silder: STATS_SILDER1 },
|
||||||
|
{ cmd: "weapon", name: "兵器谱", selected_silder: "", silder: STATS_SILDER2 },
|
||||||
|
{ cmd: "exp", name: "经验榜", selected_silder: "", silder: STATS_SILDER1 },
|
||||||
|
{ cmd: "mp", name: "内力榜", selected_silder: "", silder: STATS_SILDER1 },
|
||||||
|
{ cmd: "money", name: "富豪榜", selected_silder: "", silder: STATS_SILDER1 }
|
||||||
|
],
|
||||||
|
selectedItem: 0,
|
||||||
|
init: function () {
|
||||||
|
Dialog.injectStyle(stats_css);
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
}, onData: function (data) {
|
||||||
|
if (data.close) return Dialog.hide();
|
||||||
|
if (data.tops) {
|
||||||
|
if (data.top) {
|
||||||
|
this.show_desc("你目前在第" + data.top + "名,积分" + data.sc);
|
||||||
|
} else {
|
||||||
|
this.show_desc("你目前没有上榜,积分:" + data.sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.create_tops(data.tops, data);
|
||||||
|
}
|
||||||
|
if (data.weapons) {
|
||||||
|
this.show_desc("");
|
||||||
|
return this.create_weapons(data.weapons);
|
||||||
|
}
|
||||||
|
if (data.scores) {
|
||||||
|
this.show_desc("你目前的评分:" + data.score);
|
||||||
|
return this.create_scores(data.scores);
|
||||||
|
}
|
||||||
|
if (data.items) {
|
||||||
|
this.create_other(data.items, data.st);
|
||||||
|
let dt = new Date(data.time);
|
||||||
|
data.fam = data.fam ?? "";
|
||||||
|
this["last_" + data.st + data.fam] = {
|
||||||
|
items: data.items,
|
||||||
|
time: data.time + 60000,
|
||||||
|
score: data.score
|
||||||
|
};
|
||||||
|
if (data.score)
|
||||||
|
this.show_desc("你目前的评分:" + data.score);
|
||||||
|
else
|
||||||
|
this.show_desc("上次更新:" + dt.getHours() + ":" + dt.getMinutes());
|
||||||
|
}
|
||||||
|
|
||||||
|
}, create_other: function (items, type) {
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < 20; i++) {
|
||||||
|
html.push("<div class='top-item");
|
||||||
|
if (i < 3) html.push(' top', i + 1);
|
||||||
|
html.push("' top='");
|
||||||
|
html.push(i + 1);
|
||||||
|
html.push("'><span class='top-title'>");
|
||||||
|
html.push(this.top_names[i]);
|
||||||
|
html.push("、</span>");
|
||||||
|
html.push("<span class='top-name'>");
|
||||||
|
let role = items[i] ?? ["无", 0];
|
||||||
|
html.push(role[0]);
|
||||||
|
html.push("</span>");
|
||||||
|
html.push("<span class='top-sc'>");
|
||||||
|
html.push(role[1]);
|
||||||
|
html.push("</span>");
|
||||||
|
html.push("</div>")
|
||||||
|
}
|
||||||
|
this.container.html(html.join(""));
|
||||||
|
},
|
||||||
|
silderClick: function () {
|
||||||
|
let elem = $(this);
|
||||||
|
let type = elem.attr("stype");
|
||||||
|
let item = Dialog.stats.selectedItem;
|
||||||
|
if (item.selected_silder === type) return;
|
||||||
|
item.selected_silder = type;
|
||||||
|
elem.parent().find('.select').removeClass('select');
|
||||||
|
elem.addClass('select');
|
||||||
|
Dialog.stats.load_stats();
|
||||||
|
},
|
||||||
|
create_silder: function (items) {
|
||||||
|
let str = [];
|
||||||
|
items = items || [];
|
||||||
|
let tab = this.selectedItem;
|
||||||
|
for (let item of items) {
|
||||||
|
str.push('<div class="stats-silder ',
|
||||||
|
(tab.selected_silder === item[1] ? "select" : ""),
|
||||||
|
'" stype="', item[1], '">', item[0], "</div>");
|
||||||
|
}
|
||||||
|
this.left_silder.html(str.join(""));
|
||||||
|
},
|
||||||
|
top_names: ["一 ", "二 ", "三 ", "四 ", "五 ",
|
||||||
|
"六 ", "七 ", "八 ", "九 ", "十 ",
|
||||||
|
"十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十"],
|
||||||
|
create_scores: function (items, data) {
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < 20; i++) {
|
||||||
|
html.push("<div class='top-item scores");
|
||||||
|
if (i < 3) html.push(' top', i + 1);
|
||||||
|
html.push("' top='");
|
||||||
|
html.push(i + 1);
|
||||||
|
html.push("'><span class='top-title'>");
|
||||||
|
html.push(this.top_names[i]);
|
||||||
|
html.push("、</span>");
|
||||||
|
html.push("<span class='top-name'>");
|
||||||
|
let role = items[i] ?? ["无", ""];
|
||||||
|
html.push(role[0]);
|
||||||
|
html.push("</span>");
|
||||||
|
html.push("<span class='top-sc'>");
|
||||||
|
html.push(role[1]);
|
||||||
|
html.push("</span>");
|
||||||
|
html.push("</div>")
|
||||||
|
}
|
||||||
|
this.container.html(html.join(""));
|
||||||
|
|
||||||
|
},
|
||||||
|
fam_names: {
|
||||||
|
emei: "峨眉第", wudang: "武当第", huashan: "华山第",
|
||||||
|
xiaoyao: "逍遥第", gaibang: "丐帮第", shaolin: "少林第", shashou: "杀手第",
|
||||||
|
none: "散修第"
|
||||||
|
},
|
||||||
|
create_tops: function (items, data) {
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
html.push("<div class='top-item top ");
|
||||||
|
if (i < 3) html.push(' top', i + 1);
|
||||||
|
html.push("' top='");
|
||||||
|
html.push(i + 1);
|
||||||
|
html.push("'><span class='top-title'>");
|
||||||
|
html.push(data.fam ? this.fam_names[data.fam] : "天下第");
|
||||||
|
html.push(this.top_names[i]);
|
||||||
|
html.push("</span>");
|
||||||
|
html.push("<span class='top-name'>");
|
||||||
|
html.push(items[i][0]);
|
||||||
|
html.push("</span>");
|
||||||
|
html.push("<span class='top-sc'>");
|
||||||
|
html.push(items[i][1]);
|
||||||
|
html.push("</span>");
|
||||||
|
html.push("</div>")
|
||||||
|
}
|
||||||
|
this.container.html(html.join(""));
|
||||||
|
this.top = data.top;
|
||||||
|
}, create_weapons: function (items) {
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < 10; i++) {
|
||||||
|
html.push("<div class='top-item weapon top")
|
||||||
|
html.push(i + 1);
|
||||||
|
html.push("' top='");
|
||||||
|
html.push(i + 1);
|
||||||
|
html.push("'><span class='top-title'>");
|
||||||
|
let role = items[i] ?? ["无", ""];
|
||||||
|
html.push(this.top_names[i]);
|
||||||
|
html.push("、</span>");
|
||||||
|
html.push("<span class='top-name'>");
|
||||||
|
html.push(role[0]);
|
||||||
|
html.push("</span>");
|
||||||
|
html.push("<span class='top-sc'>");
|
||||||
|
html.push(role[1]);
|
||||||
|
html.push("</span>");
|
||||||
|
html.push("</div>")
|
||||||
|
}
|
||||||
|
this.container.html(html.join(""));
|
||||||
|
},
|
||||||
|
show: function () {
|
||||||
|
if (!this.selectedItem) this.selectedItem = this.footers[0];
|
||||||
|
this.load_stats();
|
||||||
|
if (!this.element) {
|
||||||
|
|
||||||
|
this.element = $("<div class='stats-container'><div class='stats-container-left'></div></div>");
|
||||||
|
|
||||||
|
this.container = $("<div class='dialog-stats'></div>").appendTo(this.element);
|
||||||
|
this.left_silder = this.element.find('.stats-container-left');
|
||||||
|
this.create_silder(this.selectedItem.silder);
|
||||||
|
}
|
||||||
|
if (this.isShow) return;
|
||||||
|
this.create_footer();
|
||||||
|
Dialog.icon("stats");
|
||||||
|
Dialog.title(this.selectedItem.name);
|
||||||
|
|
||||||
|
Dialog.contentElement.html(this.element);
|
||||||
|
this.element.on("click", ".top-item", this.itemClick);
|
||||||
|
this.left_silder.on("click", ".stats-silder ", this.silderClick);
|
||||||
|
this.isShow = true;
|
||||||
|
}, load_stats: function () {
|
||||||
|
let type = this.selectedItem.cmd;
|
||||||
|
let fam = this.selectedItem.selected_silder;
|
||||||
|
//if (this.ban_silder[fam]) fam = "";
|
||||||
|
let data = this["last_" + type + fam];
|
||||||
|
if (data && data.time > Date.now()) {
|
||||||
|
let dt = new Date(data.time);
|
||||||
|
let str = "";
|
||||||
|
if (data.score) str = "你目前的评分:" + data.score;
|
||||||
|
else str = "上次更新:" + dt.getHours() + ":" + dt.getMinutes();
|
||||||
|
this.show_desc(str);
|
||||||
|
return this.create_other(data.items, type);
|
||||||
|
}
|
||||||
|
let str = "stats " + type;
|
||||||
|
if (fam) str = str + " " + fam;
|
||||||
|
SendCommand(str);
|
||||||
|
}, create_footer: function () {
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < this.footers.length; i++) {
|
||||||
|
var foot = this.footers[i];
|
||||||
|
html.push("<span class='footer-item" + (foot == this.selectedItem ? " select" : "") + "' for='" + i + "''>"
|
||||||
|
+ foot.name + "</span>");
|
||||||
|
}
|
||||||
|
html.push("<span class='stats-span'></span>");
|
||||||
|
Dialog.footer(html.join(""));
|
||||||
|
}, show_desc: function (msg) {
|
||||||
|
Dialog.footerElement.find(".stats-span").html(msg);
|
||||||
|
},
|
||||||
|
footerChanged: function (index) {
|
||||||
|
var item = this.footers[index];
|
||||||
|
if (item == this.selectedItem) return;
|
||||||
|
this.selectedItem = item;
|
||||||
|
Dialog.title(this.selectedItem.name);
|
||||||
|
this.create_silder(this.selectedItem.silder);
|
||||||
|
this.load_stats();
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
itemClick: function () {
|
||||||
|
var elem = $(this);
|
||||||
|
var index = parseInt(elem.attr("top"));
|
||||||
|
var type = Dialog.stats.selectedItem.cmd;
|
||||||
|
|
||||||
|
var html = ["<div class='item-commands'>"];
|
||||||
|
var stype = Dialog.stats.selectedItem.selected_silder;
|
||||||
|
if (type === 'top') {
|
||||||
|
html.push('<span cmd="stats ' + type + ' ' + stype + " " + index + '">查看</span>');
|
||||||
|
if (!Dialog.stats.top || index < Dialog.stats.top) {
|
||||||
|
html.push('<span cmd="biwu ' + stype + " " + index + '">挑战</span>');
|
||||||
|
}
|
||||||
|
html.push('<span cmd="reward top ' + index + '">查看规则和奖励</span>');
|
||||||
|
} else {
|
||||||
|
html.push('<span cmd="stats ' + type + ' ' + stype + " " + index + '">查看</span>');
|
||||||
|
html.push('<span cmd="reward ' + type + " " + index + '">查看奖励</span>');
|
||||||
|
}
|
||||||
|
html.push("</div>");
|
||||||
|
Dialog.stats.element.find(".item-commands").remove();
|
||||||
|
$(html.join("")).insertAfter(elem);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const stats_css = `
|
||||||
|
|
||||||
|
.stats-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 25em;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-container>.stats-container-left {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-container-left>.stats-silder {
|
||||||
|
white-space: nowrap;
|
||||||
|
line-height: 2em;
|
||||||
|
width: 5em;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #111;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
margin-left: 0.5em;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-container-left>.select {
|
||||||
|
background-color: #222;
|
||||||
|
color: #00ff00;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-color: #00ff00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-stats {
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-stats>.top-item {
|
||||||
|
white-space: nowrap;
|
||||||
|
line-height: 2em;
|
||||||
|
padding-left: .5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
background-color: #111;
|
||||||
|
cursor: pointer;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-stats>.top-item>.top-title {
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: bold;
|
||||||
|
height: 1.875em;
|
||||||
|
line-height: 1.875em;
|
||||||
|
padding-left: 1em;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-stats>.top-item>.top-sc {
|
||||||
|
float: right;
|
||||||
|
margin-right: 1em;
|
||||||
|
line-height: 1.875em;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.dialog-stats>.top1>.top-sc {
|
||||||
|
color: #FFA500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-stats>.top2>.top-sc {
|
||||||
|
color: #912CEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-stats>.top3>.top-sc {
|
||||||
|
color: #FFD700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-stats>.top-item>.top-name {
|
||||||
|
height: 1.875em;
|
||||||
|
line-height: 1.875em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-stats>.top-item>.item-commands {
|
||||||
|
padding-left: 3.125em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-span {
|
||||||
|
float: right;
|
||||||
|
padding-right: 10px;
|
||||||
|
color: #C0C0C0;
|
||||||
|
line-height: 2.5em;
|
||||||
|
}
|
||||||
|
`;
|
||||||
169
src/dialog/tasks.js
Normal file
169
src/dialog/tasks.js
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
|
||||||
|
|
||||||
|
const task_css = `
|
||||||
|
|
||||||
|
.dialog-tasks {
|
||||||
|
max-height: 32em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-tasks>.task-item {
|
||||||
|
border-radius: 6px;
|
||||||
|
background-color: #111111;
|
||||||
|
border-left-width: 4px;
|
||||||
|
border-left-style: solid;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-tasks>.none {
|
||||||
|
border-left-color: #808080
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.dialog-tasks>.finish {
|
||||||
|
border-left-color: #00ff00
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-tasks>.over {
|
||||||
|
border-left-color: #008080
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-tasks>.none>.task-btn {
|
||||||
|
border-left-color: #808080;
|
||||||
|
color: #808080;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-tasks>.finish>.task-btn {
|
||||||
|
border-left-color: #00ff00;
|
||||||
|
color: #00ff00;
|
||||||
|
background-color: #00ff0033;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-tasks>.over>.task-btn {
|
||||||
|
border-left-color: #008080;
|
||||||
|
color: #008080;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-item h3 {
|
||||||
|
margin: 0px;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-item .task-desc {
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-item>.task-btn {
|
||||||
|
width: 4.5em;
|
||||||
|
display: inline-block;
|
||||||
|
border-left: 1px solid #343434;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: transparent;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-item>.task-btn:hover {
|
||||||
|
background-color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-tasks>.task-item>.start {
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-tasks>.task-item>.finish {
|
||||||
|
color: #00ff00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-tasks>.task-item>.over {
|
||||||
|
color: #ebebeb;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
init: function () {
|
||||||
|
|
||||||
|
Dialog.injectStyle(task_css);
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
}, update_item: function (data) {
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].id == data.id) {
|
||||||
|
if (data.state) {
|
||||||
|
this.items[i].title = data.title;
|
||||||
|
this.items[i].state = data.state;
|
||||||
|
this.items[i].desc = data.desc;
|
||||||
|
} else {
|
||||||
|
this.items.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.create_items();
|
||||||
|
}, onData: function (data) {
|
||||||
|
|
||||||
|
if (data.id) return this.update_item(data);
|
||||||
|
Dialog.title("任务列表");
|
||||||
|
Dialog.icon("exclamation-sign");
|
||||||
|
this.items = data.items;
|
||||||
|
this.create_items();
|
||||||
|
},
|
||||||
|
show: function () {
|
||||||
|
if (!this.element)
|
||||||
|
this.element = $("<div class='dialog-tasks'></div>");
|
||||||
|
SendCommand("tasks");
|
||||||
|
if (this.isShow) return;
|
||||||
|
this.element.appendTo(Dialog.contentElement);
|
||||||
|
|
||||||
|
this.isShow = true;
|
||||||
|
},
|
||||||
|
status_css: ['', 'none', 'finish', 'over'],
|
||||||
|
create_items: function () {
|
||||||
|
var str = [];
|
||||||
|
var has_fin = false;
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
var item = this.items[i];
|
||||||
|
str.push("<div class='task-item flex-row ");
|
||||||
|
str.push(this.status_css[item.state]);
|
||||||
|
str.push("'><div class='flex-1'><h3>");
|
||||||
|
str.push(item.title)
|
||||||
|
str.push("</h3>");
|
||||||
|
str.push("<pre class='task-desc'>");
|
||||||
|
str.push(item.desc);
|
||||||
|
|
||||||
|
//str.push('<span class="glyphicon glyphicon-info-sign"></span>');
|
||||||
|
str.push("</pre></div>");
|
||||||
|
str.push("<span class='task-btn flex-0'");
|
||||||
|
if (item.state == 1) {
|
||||||
|
str.push(">进行中");
|
||||||
|
} else if (item.state == 2) {
|
||||||
|
str.push(" cmd=\"task ");
|
||||||
|
str.push(item.id);
|
||||||
|
str.push(' fin"');
|
||||||
|
has_fin = true;
|
||||||
|
str.push(">可领取");
|
||||||
|
} else if (item.state == 3) {
|
||||||
|
str.push(">已完成");
|
||||||
|
}
|
||||||
|
str.push("</span>");
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
this.element.html(str.join(""));
|
||||||
|
|
||||||
|
Dialog.footer("");
|
||||||
|
}
|
||||||
|
};
|
||||||
75
src/dialog/team.js
Normal file
75
src/dialog/team.js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
init: function () { },
|
||||||
|
createElement: function () {
|
||||||
|
return $('<div class="dialog-team"></div>');
|
||||||
|
},
|
||||||
|
inner_show: function () {
|
||||||
|
SendCommand("team");
|
||||||
|
this.isShow = true;
|
||||||
|
Dialog.title("队伍");
|
||||||
|
this.element.on("click", ".team-item", this.clickItem);
|
||||||
|
Dialog.icon("list");
|
||||||
|
},
|
||||||
|
items: [],
|
||||||
|
onData: function (data) {
|
||||||
|
if (data.items) {
|
||||||
|
this.items = data.items;
|
||||||
|
if (data.items.length) this.isCap = data.items[0].id == Process.player;
|
||||||
|
else this.isCap = 0;
|
||||||
|
}
|
||||||
|
if (data.dismiss) {
|
||||||
|
this.items.length = 0;
|
||||||
|
this.isCap = false;
|
||||||
|
}
|
||||||
|
if (data.remove) {
|
||||||
|
if (!this.items.length) return;
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
if (this.items[i].id == data.remove) {
|
||||||
|
this.items.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.createItems();
|
||||||
|
},
|
||||||
|
inner_close: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
}, createItems: function () {
|
||||||
|
if (!this.element) return;
|
||||||
|
var str = [];
|
||||||
|
for (var i = 0; i < this.items.length; i++) {
|
||||||
|
var msg = this.items[i];
|
||||||
|
str.push("<div class='team-item' index='" + i + "'>");
|
||||||
|
str.push("<span class='team-flag'>");
|
||||||
|
str.push(i > 0 ? "" : "<span class='glyphicon glyphicon-flag'></span>");
|
||||||
|
str.push("</span>");
|
||||||
|
str.push("<span class='team-title'>");
|
||||||
|
str.push(msg.name);
|
||||||
|
str.push("</span>");
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
if (!str.length) str.push('<div class="empty">你还没有加入任何队伍。</div>');
|
||||||
|
this.element.html(str.join(""));
|
||||||
|
}, clickItem: function () {
|
||||||
|
var elem = $(this);
|
||||||
|
var item = Dialog.team.items[elem.attr("index")];
|
||||||
|
if (!item) return;
|
||||||
|
var html = ["<div class='item-commands'>"];
|
||||||
|
html.push('<span cmd="look3 ' + item.id + '">查看</span>');
|
||||||
|
var isCap = Dialog.team.items[0].id == Process.player;
|
||||||
|
if (isCap && item.id != Process.player) {
|
||||||
|
html.push('<span cmd="team remove ' + item.id + '">移出队伍</span>');
|
||||||
|
} else if (item.id == Process.player) {
|
||||||
|
html.push('<span cmd="team out ' + item.id + '">退出队伍</span>');
|
||||||
|
}
|
||||||
|
if (isCap && item.id == Process.player) {
|
||||||
|
html.push('<span cmd="team set">更改分配方式</span>');
|
||||||
|
}
|
||||||
|
html.push("</div>");
|
||||||
|
Dialog.team.element.find(".item-commands").remove();
|
||||||
|
$(html.join("")).appendTo(elem);
|
||||||
|
}
|
||||||
|
};
|
||||||
148
src/dialog/trade.js
Normal file
148
src/dialog/trade.js
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
|
||||||
|
import Util from '../utils/util.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
init: function () {
|
||||||
|
Dialog.pack.init();
|
||||||
|
},
|
||||||
|
hide: function () {
|
||||||
|
this.element.remove();
|
||||||
|
this.isShow = false;
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.hide();
|
||||||
|
}, onData: function (data) {
|
||||||
|
if (!this.isShow) {
|
||||||
|
Dialog.show("trade");
|
||||||
|
}
|
||||||
|
Dialog.title("和" + data.name + "交易中");
|
||||||
|
var items = Dialog.pack.items;
|
||||||
|
this.trade_target = data.target;
|
||||||
|
this.trade_list.length = 0;
|
||||||
|
if (!Dialog.pack.items) SendCommand("pack");
|
||||||
|
else this.update_pack();
|
||||||
|
Dialog.pack.isShow = false;
|
||||||
|
this.create_items(this.leftElement.empty(), this.trade_list, this.max_count);
|
||||||
|
},
|
||||||
|
update_pack: function (data) {
|
||||||
|
this.create_items(this.rightElement.empty(), Dialog.pack.items, Dialog.pack.max_count);
|
||||||
|
},
|
||||||
|
max_count: 10,
|
||||||
|
trade_list: [],
|
||||||
|
show: function (data) {
|
||||||
|
if (this.isShow) return;
|
||||||
|
Dialog.init();
|
||||||
|
Dialog.curItem = "trade";
|
||||||
|
if (!this.element) {
|
||||||
|
this.element = $('<div class="dialog-list"><div class="obj-list"></div><div class="obj-list"></div></div >');
|
||||||
|
this.leftElement = $(this.element.children()[0]);
|
||||||
|
this.rightElement = $(this.element.children()[1]);
|
||||||
|
}
|
||||||
|
this.leftElement.on("click", ".obj-item", this.left_click);
|
||||||
|
this.rightElement.on("click", ".obj-item", this.right_click);
|
||||||
|
this.element.appendTo(Dialog.contentElement.empty());
|
||||||
|
this.create_footer();
|
||||||
|
this.isShow = true;
|
||||||
|
|
||||||
|
}, create_footer: function () {
|
||||||
|
var html = ["<div class='item-commands'>"];
|
||||||
|
html.push("<span cmd='_trade ok'>确定</span>");
|
||||||
|
html.push("<span cmd='_trade cancle'>取消</span>");
|
||||||
|
html.push('</div>');
|
||||||
|
Dialog.footer(html.join(""));
|
||||||
|
}, confirm: function (cmd) {
|
||||||
|
if (cmd === 'ok' && this.trade_list.length) {
|
||||||
|
for (var i = 0; i < this.trade_list.length; i++) {
|
||||||
|
SendCommand("give " + this.trade_target
|
||||||
|
+ " " + this.trade_list[i].count + " " + this.trade_list[i].id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dialog.hide();
|
||||||
|
|
||||||
|
},
|
||||||
|
create_items: function (elem, items, max) {
|
||||||
|
var html = [];
|
||||||
|
items = Dialog.pack.sort_items(items);
|
||||||
|
for (var i = 0; i < max; i++) {
|
||||||
|
var item = items[i];
|
||||||
|
html.push('<div class="obj-item');
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
html.push(item.is_lock ? " lock" : "", ' grade', item.grade);
|
||||||
|
html.push('"');
|
||||||
|
|
||||||
|
html.push(" oindex='" + item.id + "'>");
|
||||||
|
html.push(item.name);
|
||||||
|
if (item.count > 1) {
|
||||||
|
html.push("<span class='obj-value'>");
|
||||||
|
html.push(item.count);
|
||||||
|
html.push(item.unit);
|
||||||
|
html.push('</span>');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
html.push('">');
|
||||||
|
}
|
||||||
|
html.push('</div>');
|
||||||
|
}
|
||||||
|
elem.html(html.join(""));
|
||||||
|
}, left_click: function () {
|
||||||
|
var elem = $(this);
|
||||||
|
var obj = elem.attr("oindex");
|
||||||
|
if (!obj) return;
|
||||||
|
var item = null;
|
||||||
|
for (var i = 0; i < Dialog.trade.trade_list.length; i++) {
|
||||||
|
if (Dialog.trade.trade_list[i].id == obj) {
|
||||||
|
item = Dialog.trade.trade_list[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!item) return;
|
||||||
|
Dialog.trade.cancle_trade(item);
|
||||||
|
return false;
|
||||||
|
}, enable_item: function (obj, isenable) {
|
||||||
|
var elem = this.rightElement.find(".obj-item[oindex='" + obj.id + "']");
|
||||||
|
if (!elem.length) return;
|
||||||
|
if (isenable) {
|
||||||
|
elem.removeClass("disabled");
|
||||||
|
} else {
|
||||||
|
elem.addClass("disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,
|
||||||
|
right_click: function () {
|
||||||
|
var elem = $(this);
|
||||||
|
if (elem.is(".disabled")) return;
|
||||||
|
var obj = elem.attr("oindex");
|
||||||
|
if (!obj) return;
|
||||||
|
|
||||||
|
var item = Dialog.pack.get_item(obj);
|
||||||
|
|
||||||
|
if (!item) return;
|
||||||
|
if (item.count > 1) {
|
||||||
|
Confirm.Show_trade_add(item);
|
||||||
|
} else {
|
||||||
|
Dialog.trade.add_trade(item);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}, add_trade: function (obj) {
|
||||||
|
for (var i = 0; i < this.trade_list.length; i++) {
|
||||||
|
if (obj.id == this.trade_list[i].id) {
|
||||||
|
this.trade_list[i].count += obj.count;
|
||||||
|
return this.create_items();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.trade_list.push(obj);
|
||||||
|
this.create_items(this.leftElement.empty(), this.trade_list, this.max_count);
|
||||||
|
this.enable_item(obj, false);
|
||||||
|
},
|
||||||
|
cancle_trade: function (obj) {
|
||||||
|
for (var i = 0; i < this.trade_list.length; i++) {
|
||||||
|
if (obj.id == this.trade_list[i].id) {
|
||||||
|
this.trade_list.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.create_items(this.leftElement.empty(), this.trade_list, this.max_count);
|
||||||
|
this.enable_item(obj, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
src/fonts/fa-solid-900.woff2
Normal file
BIN
src/fonts/fa-solid-900.woff2
Normal file
Binary file not shown.
BIN
src/fonts/glyphicons-halflings-regular.eot
Normal file
BIN
src/fonts/glyphicons-halflings-regular.eot
Normal file
Binary file not shown.
BIN
src/fonts/glyphicons-halflings-regular.ttf
Normal file
BIN
src/fonts/glyphicons-halflings-regular.ttf
Normal file
Binary file not shown.
BIN
src/fonts/glyphicons-halflings-regular.woff
Normal file
BIN
src/fonts/glyphicons-halflings-regular.woff
Normal file
Binary file not shown.
BIN
src/fonts/glyphicons-halflings-regular.woff2
Normal file
BIN
src/fonts/glyphicons-halflings-regular.woff2
Normal file
Binary file not shown.
275
src/game/main.js
Normal file
275
src/game/main.js
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
|
||||||
|
import { Page } from '../base/page.js';
|
||||||
|
import Combat from '../combat.js';
|
||||||
|
import MAP from '../map.js';
|
||||||
|
import * as ToolAction from './tool.js';
|
||||||
|
import Dialog from '../dialog/base.js';
|
||||||
|
import { Confirm } from '../confirm.js';
|
||||||
|
import { Warn } from '../confirm.js';
|
||||||
|
import Process from '../process.js';
|
||||||
|
import Setting from '../setting.js';
|
||||||
|
import SCRIPT from '../script.js';
|
||||||
|
|
||||||
|
let isShowChat = false;
|
||||||
|
|
||||||
|
class GameMainPage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = `
|
||||||
|
<div class="container" style="display:none;">
|
||||||
|
<div class="dialog hide">
|
||||||
|
<div class="dialog-header">
|
||||||
|
<span class="dialog-icon glyphicon glyphicon-map-marker"></span>
|
||||||
|
<span class="dialog-title"></span>
|
||||||
|
<span class="dialog-close glyphicon glyphicon-remove-circle"></span>
|
||||||
|
</div>
|
||||||
|
<div class="dialog-content"></div>
|
||||||
|
<div class="dialog-footer "></div>
|
||||||
|
</div>
|
||||||
|
<div class="content-room">
|
||||||
|
<div class="map-panel"></div>
|
||||||
|
<div class="room-title">
|
||||||
|
<span class="room-name"></span><span class='glyphicon glyphicon-map-marker map-icon'></span>
|
||||||
|
</div>
|
||||||
|
<div style="text-indent: 2em;" class="room_desc"></div>
|
||||||
|
<div style="text-indent: 2em;" class="room_exits"></div>
|
||||||
|
<div class="room_items" style="max-height: 8rem; overflow-y: auto;"></div>
|
||||||
|
</div>
|
||||||
|
<div class='channel'></div>
|
||||||
|
<div class="content-message"></div>
|
||||||
|
<div class="tool-bar bottom-bar">
|
||||||
|
<span class="state-bar" command="stateinfo" style="visibility:hidden"><span class="title"></span></span>
|
||||||
|
<span command="stopstate" class="tool-item state-tool" style="display:none;"><span
|
||||||
|
class="glyphicon glyphicon-off tool-icon"></span><span class="tool-text">停止</span></span>
|
||||||
|
<span command="showchat" class="tool-item"><span
|
||||||
|
class="glyphicon glyphicon-volume-down tool-icon"></span><span class="tool-text">聊天</span></span>
|
||||||
|
<span command="events" class="tool-item"><span class="glyphicon glyphicon-dashboard tool-icon"></span><span
|
||||||
|
class="tool-text">活动</span><span class="tag hide"></span></span>
|
||||||
|
<span command="showcombat" class="tool-item"><span class="glyphicon glyphicon-flash tool-icon"></span><span
|
||||||
|
class="tool-text">动作</span></span>
|
||||||
|
<span command="showtool" class="tool-item br-tool hide-tool"></span>
|
||||||
|
<div class="tool-bar right-bar">
|
||||||
|
<span command="setting" class="tool-item" style="display:none"><span
|
||||||
|
class="glyphicon glyphicon-cog tool-icon"></span><span class="tool-text">设置</span></span>
|
||||||
|
<span class="tool-item" command="jh" style="display:none"><span
|
||||||
|
class="glyphicon glyphicon-home tool-icon"></span><span class="tool-text">江湖</span></span>
|
||||||
|
<span command="stats" class="tool-item" style="display:none"><span
|
||||||
|
class="glyphicon glyphicon-stats tool-icon"></span><span class="tool-text">排行</span></span>
|
||||||
|
<span command="message" class="tool-item" style="display:none"><span
|
||||||
|
class="glyphicon glyphicon-envelope tool-icon"></span><span class="tool-text">社交</span><span
|
||||||
|
class="tag hide"></span></span>
|
||||||
|
<span command="shop" class="tool-item" style="display:none"><span
|
||||||
|
class="glyphicon glyphicon-shopping-cart tool-icon"></span><span
|
||||||
|
class="tool-text">商城</span></span>
|
||||||
|
<span command="tasks" class="tool-item" style="display:none"><span
|
||||||
|
class="glyphicon glyphicon-exclamation-sign tool-icon"></span><span
|
||||||
|
class="tool-text">任务</span><span class="tag hide"></span></span>
|
||||||
|
<span command="skills" class="tool-item" style="display:none"><span
|
||||||
|
class="glyphicon glyphicon-book tool-icon"></span><span class="tool-text">技能</span></span>
|
||||||
|
<span command="pack" class="tool-item" style="display:none"><span
|
||||||
|
class="glyphicon glyphicon-briefcase tool-icon"></span><span class="tool-text">背包</span></span>
|
||||||
|
<span class="tool-item" command="score" style="display:none"><span
|
||||||
|
class="glyphicon glyphicon-user tool-icon"></span><span class="tool-text">属性</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="custom-panel"></div>
|
||||||
|
<div class="content-bottom">
|
||||||
|
<div class="combat-panel hide">
|
||||||
|
<div class="room-commands"></div>
|
||||||
|
<div class="combat-commands"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chat-panel hide">
|
||||||
|
<div class="channel-box" channel="chat">
|
||||||
|
<span class="selected" channel="chat">世界</span>
|
||||||
|
<span channel="tm">组队</span>
|
||||||
|
<span channel="fam">门派</span>
|
||||||
|
<span channel="say">房间</span>
|
||||||
|
<span channel="es">全区</span>
|
||||||
|
<span channel="pty">帮派</span>
|
||||||
|
<span channel="emote">表情</span>
|
||||||
|
</div>
|
||||||
|
<div class="chat-input">
|
||||||
|
<input class="sender-box" />
|
||||||
|
<span class="glyphicon glyphicon-send sender-btn"></span>
|
||||||
|
</div>
|
||||||
|
<div class="channel-emotes hide"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
on_mount() {
|
||||||
|
$(".container").on("click", ContainerCommand);
|
||||||
|
$(".channel-box").on("click", "span", ChannelChanged);
|
||||||
|
|
||||||
|
$(".combat-commands").on("click", ".pfm-item", Combat.Perform).on('wheel', Combat.Scroll);
|
||||||
|
$(".room-commands").on('wheel', Combat.Scroll);
|
||||||
|
$(".sender-box").on("keyup", OnSendBoxKeyDown);
|
||||||
|
|
||||||
|
$(".room_items").on("click", ".room-item", Process.selectItem);
|
||||||
|
$(".bottom-bar").on("click", '.tool-item,.state-bar,.item-command', MenuClick);
|
||||||
|
$(".map-panel").on("click", open_map);
|
||||||
|
$(".sender-btn").on("click", SendChatMessage);
|
||||||
|
|
||||||
|
$(".room_exits").on("pointerdown",
|
||||||
|
Process.before_click_exits).on("pointerup", Process.click_exits);
|
||||||
|
$(".room-title>.map-icon").on("click", MAP.LoadMap.bind(MAP));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let last_click = 0;
|
||||||
|
function open_map() {
|
||||||
|
last_click = last_click || 0;
|
||||||
|
if (Date.now() - last_click > 500) {
|
||||||
|
last_click = Date.now();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Dialog.show("map");
|
||||||
|
}
|
||||||
|
function MenuClick(item) {
|
||||||
|
var cmd = $(this).attr("command");
|
||||||
|
if (!cmd) {
|
||||||
|
cmd = $(this).attr("cmd");
|
||||||
|
if (cmd) SendCommand(cmd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return HandlerMenuCommand(cmd);
|
||||||
|
}
|
||||||
|
function HandlerMenuCommand(cmd) {
|
||||||
|
switch (cmd) {
|
||||||
|
case "showtool":
|
||||||
|
ToolAction.ShowTools();
|
||||||
|
break;
|
||||||
|
case "showchat":
|
||||||
|
return ShowChat();
|
||||||
|
case "showcombat":
|
||||||
|
|
||||||
|
return Combat.Show();
|
||||||
|
case "stopstate":
|
||||||
|
if (Dialog.extend.is_record)
|
||||||
|
return Dialog.extend.stop_record();
|
||||||
|
SendCommand("state stop");
|
||||||
|
break;
|
||||||
|
case "stateinfo":
|
||||||
|
SendCommand("state info");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Dialog.show(cmd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function ShowChat() {
|
||||||
|
var elem = $(".chat-panel").toggleClass("hide");
|
||||||
|
if (!elem.is(".hide")) {
|
||||||
|
isShowChat = true;
|
||||||
|
elem.find("input").val("").focus();
|
||||||
|
} else {
|
||||||
|
isShowChat = false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function OnSendBoxKeyDown(e) {
|
||||||
|
if (e.keyCode == 13) {
|
||||||
|
SendChatMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function SendChatMessage() {
|
||||||
|
var value = $(".sender-box").val();
|
||||||
|
if (!value) return;
|
||||||
|
if (value.length > 100) return ReceiveMessage("<hir>你输入的内容太多了。</hir>");
|
||||||
|
var channel = $(".channel-box").attr("channel");
|
||||||
|
$(".sender-box").val("").focus();
|
||||||
|
SendCommand(channel + " " + value + "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function ChannelChanged() {
|
||||||
|
var elem = $(this);
|
||||||
|
var ch = elem.attr("channel");
|
||||||
|
if (ch == "emote") {
|
||||||
|
return ShowEmotePanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem.is(".selected")) return;
|
||||||
|
var parent = elem.parent();
|
||||||
|
parent.children().removeClass("selected");
|
||||||
|
elem.addClass("selected");
|
||||||
|
parent.attr("channel", ch);
|
||||||
|
$(".sender-box").focus();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function ShowEmotePanel() {
|
||||||
|
var panel = $(".channel-emotes");
|
||||||
|
if (panel.is(".hide")) {
|
||||||
|
panel.removeClass("hide");
|
||||||
|
if (!Process.emtoes) {
|
||||||
|
SendCommand("emote");
|
||||||
|
Process.emtoes = [];
|
||||||
|
$(".sender-box").blur();
|
||||||
|
panel.on("click", "span", function () {
|
||||||
|
var text = $(this).html();
|
||||||
|
$(".sender-box").val("*" + text).focus();
|
||||||
|
$(".channel-emotes").addClass("hide");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$(".channel-emotes").addClass("hide");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function ContainerCommand(e) {
|
||||||
|
var elem = $(e.target);
|
||||||
|
var cmd = elem.attr("cmd");
|
||||||
|
if (!cmd) cmd = elem.parent().attr("cmd");
|
||||||
|
if (cmd) {
|
||||||
|
let char = cmd[0];
|
||||||
|
if (char == "_") {
|
||||||
|
var str = cmd.split(" ");
|
||||||
|
switch (str[0]) {
|
||||||
|
case "_confirm":
|
||||||
|
Confirm.Process(str);
|
||||||
|
break;
|
||||||
|
case "_setting":
|
||||||
|
Setting.save(str[1], str[2]);
|
||||||
|
break;
|
||||||
|
case "_trade":
|
||||||
|
Dialog.trade.confirm(str[1]);
|
||||||
|
break;
|
||||||
|
case "_close":
|
||||||
|
Warn.Close(elem);
|
||||||
|
break;
|
||||||
|
case "_hide":
|
||||||
|
break;
|
||||||
|
case "_closed":
|
||||||
|
Dialog.hide();
|
||||||
|
case "_party":
|
||||||
|
Dialog.party.command(str[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if (char === '#') {
|
||||||
|
SCRIPT.run(cmd);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SendCommand(cmd);
|
||||||
|
if (!elem.closest('.dialog-fb').length &&
|
||||||
|
elem.closest(".dialog-content").length > 0) {
|
||||||
|
elem.closest(".item-commands").remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (isShowChat) {
|
||||||
|
if (!elem.closest(".chat-panel").length) {
|
||||||
|
$(".chat-panel").addClass("hide");
|
||||||
|
isShowChat = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Confirm.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GameMainPage;
|
||||||
|
window.HandlerMenuCommand = HandlerMenuCommand;
|
||||||
89
src/game/tool.js
Normal file
89
src/game/tool.js
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
|
||||||
|
let tools = null;
|
||||||
|
let hideTool = null;
|
||||||
|
let bottom_tools = null;
|
||||||
|
let ToolState = 0;
|
||||||
|
let ToolOpacity = 0;
|
||||||
|
let ToolSpeed = 0;
|
||||||
|
|
||||||
|
export function InitTools() {
|
||||||
|
if (!tools) {
|
||||||
|
tools = $(".right-bar>.tool-item");
|
||||||
|
hideTool = $(".br-tool");
|
||||||
|
bottom_tools = $('.bottom-bar>.tool-item');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ShowTools() {
|
||||||
|
InitTools();
|
||||||
|
if (ToolState == 1) return;
|
||||||
|
if (ToolState == 0) {//显示
|
||||||
|
for (var i = 0; i < tools.length; i++) {
|
||||||
|
tools[i].style.display = "";
|
||||||
|
tools[i].style.opacity = 0;
|
||||||
|
}
|
||||||
|
ToolSpeed = 200;
|
||||||
|
ToolOpacity = 0;
|
||||||
|
$(hideTool).removeClass("hide-tool");
|
||||||
|
} else {//隐藏
|
||||||
|
ToolOpacity = 100;
|
||||||
|
ToolSpeed = 100;
|
||||||
|
$(hideTool).addClass("hide-tool");
|
||||||
|
}
|
||||||
|
window.setTimeout(ShowToolsAnimate.bind(null, ToolState), 100);
|
||||||
|
ToolState = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ShowToolsAnimate(type) {
|
||||||
|
if (type == 0) {
|
||||||
|
ToolOpacity = ToolOpacity + ToolSpeed;
|
||||||
|
var to = ToolOpacity;
|
||||||
|
for (var i = tools.length - 1; i >= 0; i--) {
|
||||||
|
if (to < 0) tools[i].style.opacity = 0;
|
||||||
|
else if (to > 100) tools[i].style.opacity = 1;
|
||||||
|
else tools[i].style.opacity = to / 100;
|
||||||
|
to -= 20;
|
||||||
|
if (to < 0) break;
|
||||||
|
}
|
||||||
|
ToolOpacity -= 30;
|
||||||
|
if (to < 100) {
|
||||||
|
window.setTimeout(ShowToolsAnimate.bind(null, type), 100);
|
||||||
|
} else {
|
||||||
|
ToolState = 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ToolOpacity = ToolOpacity - ToolSpeed;
|
||||||
|
var to = ToolOpacity;
|
||||||
|
for (var i = 0; i < tools.length; i++) {
|
||||||
|
if (to < 0) tools[i].style.opacity = 0;
|
||||||
|
else if (to > 100) tools[i].style.opacity = 1;
|
||||||
|
else tools[i].style.opacity = to / 100 * 1;
|
||||||
|
to += 20;
|
||||||
|
if (to >= 100) break;
|
||||||
|
}
|
||||||
|
ToolOpacity -= 20;
|
||||||
|
if (to >= 0) {
|
||||||
|
window.setTimeout(ShowToolsAnimate.bind(null, type), 100);
|
||||||
|
} else {
|
||||||
|
ToolState = 0;
|
||||||
|
for (var i = 0; i < tools.length; i++) {
|
||||||
|
tools[i].style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showFlag(cmd, val) {
|
||||||
|
InitTools();
|
||||||
|
if (val < 0) val = 0;
|
||||||
|
else if (val > 99) val = 99;
|
||||||
|
let tool = tools.filter("[command='" + cmd + "']");
|
||||||
|
if (!tool.length)
|
||||||
|
tool = bottom_tools.filter("[command='" + cmd + "']");
|
||||||
|
if (val) {
|
||||||
|
tool.find(".tag").removeClass("hide");
|
||||||
|
} else {
|
||||||
|
tool.find(".tag").addClass("hide");
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
src/img/loader.gif
Normal file
BIN
src/img/loader.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/img/thk.png
Normal file
BIN
src/img/thk.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
BIN
src/img/timg.gif
Normal file
BIN
src/img/timg.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
15
src/index.html
Normal file
15
src/index.html
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>MUD游戏</title>
|
||||||
|
<meta name="viewport"
|
||||||
|
content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<script type="module" src="./startup.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
84
src/login/bind-phone.js
Normal file
84
src/login/bind-phone.js
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
|
||||||
|
import { Page } from '../base/page.js';
|
||||||
|
import Util from '../utils/util.js';
|
||||||
|
import API from '../api.js';
|
||||||
|
import * as Client from '../client.js';
|
||||||
|
|
||||||
|
class BindPhonePage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = `
|
||||||
|
<div id="bind_panel" class="mypanel" style="display:none;">
|
||||||
|
<ul>
|
||||||
|
<li class="panel_item active"><span>绑定手机</span></li>
|
||||||
|
<li class="content">
|
||||||
|
<h3>你绑定的手机</h3>
|
||||||
|
<input type="text" id="phone_no" placeholder="请输入你的手机号码" class="textbox" />
|
||||||
|
<h3>绑定的手机尾号</h3>
|
||||||
|
<div class="validnum-box">
|
||||||
|
<input type="text" id="phone_valid" placeholder="请输入四位尾号" class="textbox" />
|
||||||
|
<button class="validnum-btn hide">发送验证码</button>
|
||||||
|
</div>
|
||||||
|
<h3>你的密码</h3>
|
||||||
|
<input type="password" id="phone_pwd" placeholder="请输入密码" class="textbox" />
|
||||||
|
</li>
|
||||||
|
<li class="panel_item" command="CheckValid"><span class="glyphicon glyphicon-edit"></span><span
|
||||||
|
style="margin-left:0.5rem">绑定</span></li>
|
||||||
|
<li class="panel_item" command="ToServerPanel"><span
|
||||||
|
class="glyphicon glyphicon-chevron-left"></span><span style="margin-left:0.5rem">返回</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
bind() {
|
||||||
|
Client.hide2show("#bind_panel");
|
||||||
|
API.GetPhone(function (x) {
|
||||||
|
$("#phone_valid").val("");
|
||||||
|
$("#phone_pwd").val("");
|
||||||
|
if (x.code !== 1)
|
||||||
|
return $(".input-error").html(x.result);
|
||||||
|
$(".input-error").remove();
|
||||||
|
let phone = x.result;
|
||||||
|
if (phone) {
|
||||||
|
$("#phone_no").prop("disabled", true).val(phone);
|
||||||
|
$('#phone_valid').parent().show().prev().show();
|
||||||
|
$("#phone_no").prev().html("你已绑定手机,再次验证会取消绑定");
|
||||||
|
$("#phone_no").parent().next().find('span:last()').html("解除绑定");
|
||||||
|
} else {
|
||||||
|
$("#phone_no").prop("disabled", false).val("");
|
||||||
|
$("#phone_no").prev().html("你要绑定的手机(不验证,目前仅作为二级密码验证使用)");
|
||||||
|
$('#phone_valid').parent().hide().prev().hide();
|
||||||
|
$("#phone_no").parent().next().find('span:last()').html("绑定");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
var phone = $("#phone_no");
|
||||||
|
var phone_no = "", valid_no = "";
|
||||||
|
if (!phone.is(":disabled")) {
|
||||||
|
phone_no = phone.val();
|
||||||
|
if (!phone_no) return Client.showInputError("#phone_no", "请输入你的帐号绑定的手机号码");
|
||||||
|
if (!/^1\d{10}$/.test(phone_no)) return Client.showInputError("#phone_no", "手机号码格式错误");
|
||||||
|
} else {
|
||||||
|
valid_no = $("#phone_valid").val();
|
||||||
|
if (!valid_no) return Client.showInputError($("#phone_valid").parent(), "请输入你接收到的六位验证码");
|
||||||
|
if (!/^\d{4}$/.test(valid_no)) return Client.showInputError($("#phone_valid").parent(), "请输入六位数字的验证码");
|
||||||
|
}
|
||||||
|
var pwd2 = $("#phone_pwd").val();
|
||||||
|
if (!pwd2) return Client.showInputError("#phone_pwd", "请重复输入你的新密码");
|
||||||
|
if (pwd2.length < 6 || pwd2.length > 20) return Client.showInputError("#phone_pwd", "密码长度在6到20之间");
|
||||||
|
|
||||||
|
API.BindPhone(valid_no, phone_no, pwd2, function (x) {
|
||||||
|
if (x.code < 1) {
|
||||||
|
Client.showInputError($("#phone_valid").parent(), x.result ?? "绑定失败");
|
||||||
|
Client.hide2show("#bind_panel");
|
||||||
|
} else {
|
||||||
|
Client.hide2show("#role_panel");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BindPhonePage;
|
||||||
82
src/login/change-pwd.js
Normal file
82
src/login/change-pwd.js
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
|
||||||
|
import { Page } from '../base/page.js';
|
||||||
|
import API from '../api.js';
|
||||||
|
import * as Client from '../client.js';
|
||||||
|
|
||||||
|
class ChangePwdPage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = `
|
||||||
|
<div id="pwd_panel" class="mypanel" style="display:none;">
|
||||||
|
<ul>
|
||||||
|
<li class="panel_item active"><span>修改密码</span></li>
|
||||||
|
<li class="content">
|
||||||
|
<h3>输入你现在的密码</h3>
|
||||||
|
<input type="password" id="update_pwd1" value="" placeholder="输入你现在的密码" class="textbox" />
|
||||||
|
<div id="pwd_bind" style="display:none">
|
||||||
|
<h3>你绑定的手机</h3>
|
||||||
|
<input type="text" id="pwd_phone" placeholder="请输入你的手机号码" class="textbox" />
|
||||||
|
<h3>绑定的手机尾号</h3>
|
||||||
|
<div class="validnum-box">
|
||||||
|
<input type="text" id="pwd_no" placeholder="请输入四位尾号" class="textbox" />
|
||||||
|
<button class="validnum-btn hide">发送验证码</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3>你新的密码</h3>
|
||||||
|
<input type="password" id="update_pwd2" value="" placeholder="你新的密码" class="textbox" />
|
||||||
|
<h3>重复你的新密码</h3>
|
||||||
|
<input type="password" id="update_pwd3" value="" placeholder="重复你的新密码" class="textbox" />
|
||||||
|
</li>
|
||||||
|
<li class="panel_item" command="UpdatePwd"><span class="glyphicon glyphicon-edit"></span><span
|
||||||
|
style="margin-left:0.5rem">修改</span></li>
|
||||||
|
<li class="panel_item" command="ToServerPanel"><span
|
||||||
|
class="glyphicon glyphicon-chevron-left"></span><span style="margin-left:0.5rem">返回</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
open() {
|
||||||
|
Client.hide2show("#pwd_panel");
|
||||||
|
API.GetPhone(function (x) {
|
||||||
|
if (x.code !== 1) return Client.showInputError("#update_pwd1", "获取绑定的手机号失败");
|
||||||
|
|
||||||
|
if (x.result) {
|
||||||
|
$("#pwd_phone").prop("disabled", true).val(x.result);
|
||||||
|
$("#pwd_bind").show();
|
||||||
|
} else {
|
||||||
|
$("#pwd_phone").prop("disabled", false).val("");
|
||||||
|
$("#pwd_bind").hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
$('#pwd_panel').find('.input-error').remove();
|
||||||
|
var pwd1 = $("#update_pwd1").val();
|
||||||
|
var pwd2 = $("#update_pwd2").val();
|
||||||
|
var pwd3 = $("#update_pwd3").val();
|
||||||
|
if (pwd1.length < 6 || pwd1.length > 20) return Client.showInputError("#update_pwd1", "密码长度在6到20之间");
|
||||||
|
if (pwd2.length < 6 || pwd2.length > 20) return Client.showInputError("#update_pwd2", "密码长度在6到20之间");
|
||||||
|
if (pwd3 != pwd2) return Client.showInputError("#update_pwd3", "两次密码输入不一致");
|
||||||
|
var valid_no;
|
||||||
|
if ($("#pwd_bind").is(":visible")) {
|
||||||
|
valid_no = $("#pwd_no").val();
|
||||||
|
if (!valid_no) return Client.showInputError($("#pwd_no").parent(), "请输入你绑定的手机尾号");
|
||||||
|
if (!/^\d{4}$/.test(valid_no)) return Client.showInputError($("#pwd_no").parent(), "请输入你绑定的手机尾号");
|
||||||
|
}
|
||||||
|
|
||||||
|
Client.showLoader("正在修改密码", "#pwd_panel");
|
||||||
|
API.ChangePassword(pwd1, pwd2, valid_no, function (x) {
|
||||||
|
if (x.code) {
|
||||||
|
Client.hide2show($("#slist_panel"));
|
||||||
|
} else {
|
||||||
|
Client.showInputError("#update_pwd1", x.result || '修改失败');
|
||||||
|
Client.hide2show("#pwd_panel");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ChangePwdPage;
|
||||||
89
src/login/create-role.js
Normal file
89
src/login/create-role.js
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
import { Page } from '../base/page.js';
|
||||||
|
import API from '../api.js';
|
||||||
|
import * as Client from '../client.js';
|
||||||
|
import { RefreshInput } from './roles.js';
|
||||||
|
|
||||||
|
window.RefreshInput = RefreshInput;
|
||||||
|
|
||||||
|
class CreateRolePage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = `
|
||||||
|
|
||||||
|
|
||||||
|
<div class="mypanel" id="addrole_panel">
|
||||||
|
<ul>
|
||||||
|
<li class="panel_item active">创建你的角色卡</li>
|
||||||
|
<li class="content">
|
||||||
|
<div class="input-error"></div>
|
||||||
|
<div>
|
||||||
|
<h3 class="regist-title-text">你的称呼,2-5个中文字符</h3><span onclick="RefreshInput('name');"
|
||||||
|
class="glyphicon glyphicon-refresh regist-title-ref"></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="text" placeholder="请输入姓名" id="reg_name" class="textbox" style="width:250px;" />
|
||||||
|
</div>
|
||||||
|
<h3>你的性别</h3>
|
||||||
|
<div>
|
||||||
|
<label><input type="radio" name="role_gander" id="gender_0" checked="checked" />男</label>
|
||||||
|
<label><input type="radio" name="role_gander" />女</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="regist-title-text">你的先天属性</h3><span
|
||||||
|
class="glyphicon glyphicon-refresh regist-title-ref" onclick="RefreshInput('prop');"></span>
|
||||||
|
</div>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td style="width:5rem">臂力:<span class="glyphicon glyphicon-exclamation-sign"
|
||||||
|
style="color:#bbbbbb" data-container="body" data-toggle="popover"
|
||||||
|
data-trigger="hover" data-content="影响人物的攻击力,招架等"></span></td>
|
||||||
|
<td style="width:5rem"><input type="text" id="reg_str" class="hide_txt" value="20" /></td>
|
||||||
|
<td style="width:5rem">根骨:<span class="glyphicon glyphicon-exclamation-sign"
|
||||||
|
style="color:#bbbbbb" data-container="body" data-toggle="popover"
|
||||||
|
data-trigger="hover" data-content="影响人物的内力上限,气血,防御等"></span></td>
|
||||||
|
<td><input type="text" id="reg_con" class="hide_txt" value="20" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="width:2.5rem">身法:<span class="glyphicon glyphicon-exclamation-sign"
|
||||||
|
style="color:#bbbbbb" data-container="body" data-toggle="popover"
|
||||||
|
data-trigger="hover" data-content="影响人物的躲闪,暴击等属性"></span></td>
|
||||||
|
<td style="width:5rem"><input type="text" id="reg_dex" class="hide_txt" value="20" /></td>
|
||||||
|
<td style="width:2.5rem">悟性:<span class="glyphicon glyphicon-exclamation-sign"
|
||||||
|
style="color:#bbbbbb" data-container="body" data-toggle="popover"
|
||||||
|
data-trigger="hover" data-content="影响人物对技能的领悟速度等"></span></td>
|
||||||
|
<td style="width:5rem"><input type="text" id="reg_int" class="hide_txt" value="20" /></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div style="margin:0.5rem 0px;color:#999999">需要在15-30之间,并且总和等于80</div>
|
||||||
|
</li>
|
||||||
|
<li class="panel_item" command="CreateRole"><span class="glyphicon glyphicon-saved"></span><span
|
||||||
|
style="margin-left:0.5rem">创建</span></li>
|
||||||
|
<li class="panel_item" command="ToRolePanel"><span class="glyphicon glyphicon-off"></span><span
|
||||||
|
style="margin-left:0.5rem">返回</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
var player = {};
|
||||||
|
player.name = $("#reg_name").val();
|
||||||
|
player.gender = $("#gender_0").is(":checked") ? 1 : 2;
|
||||||
|
player.str = parseInt($("#reg_str").val());
|
||||||
|
player.con = parseInt($("#reg_con").val());
|
||||||
|
player.dex = parseInt($("#reg_dex").val());
|
||||||
|
player.int = parseInt($("#reg_int").val());
|
||||||
|
|
||||||
|
if (!/^[\u4E00-\u9FA5]{2,5}$/.test(player.name)) return Client.showInputError("#reg_name", "名称格式错误,只能使用2-5位中文字符");
|
||||||
|
if (player.str < 15 || player.str > 30) return Client.showInputError("#reg_name", "臂力需要在15-30之间");
|
||||||
|
if (player.con < 15 || player.con > 30) return Client.showInputError("#reg_name", "根骨需要在15-30之间");
|
||||||
|
if (player.dex < 15 || player.dex > 30) return Client.showInputError("#reg_name", "身法需要在15-30之间");
|
||||||
|
if (player.int < 15 || player.int > 30) return Client.showInputError("#reg_name", "悟性需要在15-30之间");
|
||||||
|
if (player.str + player.con + player.dex + player.int != 80) return Client.showInputError("#reg_name", "先天属性需要在15-30之间,并且总和等于80");
|
||||||
|
Client.showLoader("正在创建角色", "#addrole_panel");
|
||||||
|
SendCommand("createrole " + player.name + " " + player.gender + " " + player.str + " " + player.con + " " + player.dex + " " + player.int);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CreateRolePage;
|
||||||
139
src/login/index.js
Normal file
139
src/login/index.js
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
|
||||||
|
import { Page } from '../base/page.js';
|
||||||
|
import Server from './server.js';
|
||||||
|
import Util from '../utils/util.js';
|
||||||
|
import Regist from './regist.js';
|
||||||
|
import Roles from './roles.js';
|
||||||
|
import ResetPwd from './reset-pwd.js';
|
||||||
|
import ChangePwd from './change-pwd.js';
|
||||||
|
import BindPhone from './bind-phone.js';
|
||||||
|
import CreateRole from './create-role.js';
|
||||||
|
import News from './news.js';
|
||||||
|
import LoginIn from './login-in.js';
|
||||||
|
import * as Client from '../client.js';
|
||||||
|
|
||||||
|
const server = new Server();
|
||||||
|
const loginIn = new LoginIn();
|
||||||
|
const regist = new Regist();
|
||||||
|
const roles = new Roles();
|
||||||
|
const resetPwd = new ResetPwd();
|
||||||
|
const changePwd = new ChangePwd();
|
||||||
|
const bindPhone = new BindPhone();
|
||||||
|
const createRole = new CreateRole();
|
||||||
|
const news = new News(); 4
|
||||||
|
|
||||||
|
function showNews() {
|
||||||
|
let nid = $(this).attr('nid');
|
||||||
|
Client.hide2show($("#new_panel "));
|
||||||
|
$("#news_frame").attr("src", "/news/" + nid + ".html");
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoginPage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = `
|
||||||
|
|
||||||
|
${loginIn.template}
|
||||||
|
|
||||||
|
${server.template}
|
||||||
|
${bindPhone.template}
|
||||||
|
|
||||||
|
${changePwd.template}
|
||||||
|
${resetPwd.template}
|
||||||
|
|
||||||
|
${regist.template}
|
||||||
|
${roles.template}
|
||||||
|
${news.template}
|
||||||
|
${createRole.template}
|
||||||
|
<div class="signinfo">©2017 武神传说 </div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
on_mount() {
|
||||||
|
$(".login-content").on("click", ".panel_item", (e) => this.LoginCommand(e));
|
||||||
|
$(".role-list").on("click", ".role-item", function () {
|
||||||
|
$(this).parent().find(".select").removeClass("select");
|
||||||
|
$(this).addClass("select");
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.new-list>li').on('click', showNews);
|
||||||
|
var key = Util.GetUserCookie("p");
|
||||||
|
if (!key) {
|
||||||
|
return $("#login_panel").show();
|
||||||
|
}
|
||||||
|
server.showServers();
|
||||||
|
}
|
||||||
|
|
||||||
|
LoginCommand(e) {
|
||||||
|
var cmd = $(e.currentTarget).attr("command");
|
||||||
|
switch (cmd) {
|
||||||
|
case "ToRolePanel":
|
||||||
|
Client.hide2show($("#role_panel"));
|
||||||
|
break;
|
||||||
|
case "ToServerPanel":
|
||||||
|
Client.closeServer();
|
||||||
|
Client.hide2show($("#slist_panel"));
|
||||||
|
break;
|
||||||
|
case "ToLogin":
|
||||||
|
Client.hide2show($("#login_panel"));
|
||||||
|
break;
|
||||||
|
case "Forget":
|
||||||
|
Client.hide2show($("#reset_panel"));
|
||||||
|
break;
|
||||||
|
case "CancleRegist":
|
||||||
|
Client.hide2show($("#login_panel"));
|
||||||
|
break;
|
||||||
|
case "Down":
|
||||||
|
Client.hide2show($("#download"));
|
||||||
|
break;
|
||||||
|
case "ToRegist":
|
||||||
|
Client.hide2show($("#regist_panel"));
|
||||||
|
regist.open();
|
||||||
|
break;
|
||||||
|
case "Regist":
|
||||||
|
regist.regist();
|
||||||
|
break;
|
||||||
|
case "SelectServer":
|
||||||
|
server.selectServer();
|
||||||
|
break;
|
||||||
|
case "LoginIn":
|
||||||
|
loginIn.loginIn();
|
||||||
|
break;
|
||||||
|
case "ResetPwd":
|
||||||
|
resetPwd.reset();
|
||||||
|
break;
|
||||||
|
case "AddRole":
|
||||||
|
roles.addRole();
|
||||||
|
break;
|
||||||
|
case "SelectRole":
|
||||||
|
roles.select();
|
||||||
|
break;
|
||||||
|
case "CreateRole":
|
||||||
|
createRole.create();
|
||||||
|
break;
|
||||||
|
case "BindPhone":
|
||||||
|
bindPhone.bind();
|
||||||
|
break;
|
||||||
|
case "CheckValid":
|
||||||
|
bindPhone.check();
|
||||||
|
break;
|
||||||
|
case "UpdatePwd":
|
||||||
|
changePwd.update();
|
||||||
|
break;
|
||||||
|
case "ToUpdate":
|
||||||
|
changePwd.open();
|
||||||
|
break;
|
||||||
|
case "ReLogin":
|
||||||
|
loginIn.relogin();
|
||||||
|
break;
|
||||||
|
case "DeleteRole":
|
||||||
|
roles.delete();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LoginPage;
|
||||||
|
export { roles };
|
||||||
70
src/login/login-in.js
Normal file
70
src/login/login-in.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
|
||||||
|
import { Page } from '../base/page.js';
|
||||||
|
import API from '../api.js';
|
||||||
|
import * as Client from '../client.js';
|
||||||
|
import ServerPage from './server.js';
|
||||||
|
import loader from '../img/loader.gif';
|
||||||
|
|
||||||
|
const server = new ServerPage();
|
||||||
|
|
||||||
|
class LoginInPage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = `
|
||||||
|
<div class="login-content">
|
||||||
|
<div id="loader" class="loader hide"><img src="${loader}" alt="" /><span id="loader_msg">正在登陆</span></div>
|
||||||
|
<div class="error hide"></div>
|
||||||
|
<div id="login_panel" class="mypanel" style="display:none;">
|
||||||
|
<ul>
|
||||||
|
<li class="panel_item active">
|
||||||
|
<span>欢迎登陆</span>
|
||||||
|
</li>
|
||||||
|
<li class="content">
|
||||||
|
<h3>你的用户名</h3>
|
||||||
|
<input type="text" id="login_name" value="" placeholder="请输入用户名" class="textbox" />
|
||||||
|
<h3>你的密码</h3>
|
||||||
|
<input type="password" id="login_pwd" value="" placeholder="请输入密码" class="textbox" />
|
||||||
|
</li>
|
||||||
|
<li class="panel_item" command="LoginIn"><span class="glyphicon glyphicon-log-in"></span><span
|
||||||
|
style="margin-left:0.5rem">登陆</span></li>
|
||||||
|
<li class="panel_item" command="ToRegist"><span class="glyphicon glyphicon-edit"></span><span
|
||||||
|
style="margin-left:0.5rem">注册</span></li>
|
||||||
|
<li class="panel_item" command="Forget"><span class="glyphicon glyphicon-question-sign"></span><span
|
||||||
|
style="margin-left:0.5rem">忘记密码</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
relogin() {
|
||||||
|
Client.hide2show($("#login_panel"));
|
||||||
|
var myDate = new Date();
|
||||||
|
myDate.setTime(-1000);
|
||||||
|
var data = document.cookie;
|
||||||
|
var dataArray = data.split("; ");
|
||||||
|
for (var i = 0; i < dataArray.length; i++) {
|
||||||
|
var varName = dataArray[i].split("=");
|
||||||
|
document.cookie = varName[0] + "=''; expires=" + myDate.toGMTString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loginIn() {
|
||||||
|
var name = $("#login_name").val().toLowerCase();
|
||||||
|
var pwd = $("#login_pwd").val();
|
||||||
|
if (!name) return Client.showInputError("#login_name", "请输入用户名");
|
||||||
|
if (!/^[a-z0-9]{5,15}$/.test(name)) return Client.showInputError("#login_name", "用户名格式错误,需要5-15位字母开头的字母,数字或下划线,不区分大小写");
|
||||||
|
if (!pwd) return Client.showInputError("#login_pwd", "请输入密码");
|
||||||
|
if (pwd.length < 6 || pwd.length > 20) return Client.showInputError("#login_pwd", "密码长度在6到20之间");
|
||||||
|
Client.showLoader("正在登录", "#login_panel");
|
||||||
|
API.Login(name, pwd, (x) => {
|
||||||
|
if (x.code) {
|
||||||
|
server.showServers();
|
||||||
|
} else {
|
||||||
|
Client.showInputError("#login_name", x.result || '登陆失败');
|
||||||
|
Client.hide2show("#login_panel");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LoginInPage;
|
||||||
20
src/login/news.js
Normal file
20
src/login/news.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { Page } from '../base/page.js';
|
||||||
|
|
||||||
|
class NewsPage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = `
|
||||||
|
<div id="new_panel" class="mypanel" style="display:none">
|
||||||
|
<ul>
|
||||||
|
<li class="content" style="height:20rem;">
|
||||||
|
<iframe frameborder="0" id="news_frame" width="100%" height="100%"></iframe>
|
||||||
|
</li>
|
||||||
|
<li class="panel_item" command="ToRolePanel"><span class="glyphicon glyphicon-chevron-left"></span><span
|
||||||
|
style="margin-left:0.5rem">返回</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewsPage;
|
||||||
86
src/login/regist.js
Normal file
86
src/login/regist.js
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
|
||||||
|
import { Page } from '../base/page.js';
|
||||||
|
import API from '../api.js';
|
||||||
|
import { hide2show, showInputError, showLoader } from '../client.js';
|
||||||
|
|
||||||
|
class RegistPage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.initReg = false;
|
||||||
|
this.template = `
|
||||||
|
<div id="regist_panel" class="mypanel" style="display:none">
|
||||||
|
<ul>
|
||||||
|
<li class="panel_item active">注册用户</li>
|
||||||
|
<li class="content">
|
||||||
|
<h3>你的用户名</h3>
|
||||||
|
<input type="text" id="regist_name" placeholder="请输入用户名" class="textbox" />
|
||||||
|
<h3>你的密码</h3>
|
||||||
|
<input type="password" id="regist_pwd1" placeholder="请输入密码" class="textbox" />
|
||||||
|
<h3>重复你的密码</h3>
|
||||||
|
<input type="password" id="regist_pwd2" placeholder="请输入密码" class="textbox" />
|
||||||
|
<div id="regist_valpanel">
|
||||||
|
<h3>请输入图片验证码</h3>
|
||||||
|
<div class="validnum-box">
|
||||||
|
<input type="text" id="regist_val" value="" placeholder="请输入图片验证码" class="textbox" />
|
||||||
|
<img src="" class="validnum-img" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="panel_item" command="Regist"><span class="glyphicon glyphicon-saved"></span><span
|
||||||
|
style="margin-left:0.5rem">确定</span></li>
|
||||||
|
<li class="panel_item" command="ToLogin"><span class="glyphicon glyphicon-chevron-left"></span><span
|
||||||
|
style="margin-left:0.5rem">取消</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
on_mount() {
|
||||||
|
}
|
||||||
|
|
||||||
|
open() {
|
||||||
|
if (!this.initReg) {
|
||||||
|
this.GetValidationImage();
|
||||||
|
$(".validnum-box>.validnum-img").on("click", () => this.GetValidationImage());
|
||||||
|
this.initReg = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
regist() {
|
||||||
|
var name = $("#regist_name").val().toLowerCase();
|
||||||
|
var pwd = $("#regist_pwd1").val();
|
||||||
|
if (!name) return showInputError("#regist_name", "请输入用户名");
|
||||||
|
if (!/^[a-z0-9]{5,15}$/.test(name)) return showInputError("#regist_name", "用户名需要是5-10个英文字符");
|
||||||
|
if (!pwd) return showInputError("#regist_pwd1", "请输入密码");
|
||||||
|
if (pwd.length < 6 || pwd.length > 20) return showInputError("#regist_pwd1", "密码长度在6到20之间");
|
||||||
|
if (pwd != $("#regist_pwd2").val()) return showInputError("#regist_pwd2", "重复密码输入不一致,请重新输入");
|
||||||
|
var valno = $("#regist_val").val();
|
||||||
|
if (!valno) return showInputError("#regist_valpanel", "请输入图片中的验证码");
|
||||||
|
if (valno.length != 4) return showInputError("#regist_valpanel", "请输入图片中的四位验证码");
|
||||||
|
let guider = 0, result = /u(\d+)/.exec(location.pathname);
|
||||||
|
if (result) {
|
||||||
|
guider = parseInt(result[1]);
|
||||||
|
if (!(guider > 0)) guider = 0;
|
||||||
|
}
|
||||||
|
showLoader("正在注册账号");
|
||||||
|
API.Regist({
|
||||||
|
name, pwd, valno, guider
|
||||||
|
}, (x) => {
|
||||||
|
if (x.code == 1) {
|
||||||
|
showLoader("注册成功,正在获取服务器列表");
|
||||||
|
setTimeout(() => window.location.reload(), 500);
|
||||||
|
} else {
|
||||||
|
showInputError("#regist_name", x.result || '注册失败');
|
||||||
|
hide2show($("#regist_panel"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
GetValidationImage() {
|
||||||
|
API.ValidationImage(function (x) {
|
||||||
|
$(".validnum-box>.validnum-img").attr('src', "data:image/svg+xml;base64," + x);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RegistPage;
|
||||||
67
src/login/reset-pwd.js
Normal file
67
src/login/reset-pwd.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
|
||||||
|
import { Page } from '../base/page.js';
|
||||||
|
import API from '../api.js';
|
||||||
|
import * as Client from '../client.js';
|
||||||
|
|
||||||
|
class ResetPwdPage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = `
|
||||||
|
<div id="reset_panel" class="mypanel" style="display:none;">
|
||||||
|
<ul>
|
||||||
|
<li class="panel_item active"><span>重置你的密码</span></li>
|
||||||
|
<li class="content">
|
||||||
|
<h3>你的用户名</h3>
|
||||||
|
<input type="text" id="reset_name" value="" placeholder="请输入用户名,如果账号未绑定手机无法重置" class="textbox" />
|
||||||
|
<h3>你绑定的手机</h3>
|
||||||
|
<input type="text" id="reset_phone" placeholder="请输入你的手机号码" class="textbox" />
|
||||||
|
<h3 class="hide">接收到的验证码</h3>
|
||||||
|
<div class="validnum-box hide">
|
||||||
|
<input type="text" id="reset_no" placeholder="请输入六位验证码" class="textbox" />
|
||||||
|
<button class="validnum-btn ">发送验证码</button>
|
||||||
|
</div>
|
||||||
|
<h3>你新的密码</h3>
|
||||||
|
<input type="password" id="reset_pwd1" value="" placeholder="你新的密码" class="textbox" />
|
||||||
|
<h3>重复你的新密码</h3>
|
||||||
|
<input type="password" id="reset_pwd2" value="" placeholder="重复你的新密码" class="textbox" />
|
||||||
|
</li>
|
||||||
|
<li class="panel_item" command="ResetPwd"><span class="glyphicon glyphicon-edit"></span><span
|
||||||
|
style="margin-left:0.5rem">重置密码</span></li>
|
||||||
|
<li class="panel_item" command="ToLogin"><span class="glyphicon glyphicon-chevron-left"></span><span
|
||||||
|
style="margin-left:0.5rem">返回</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
on_mount() {
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
var name = $("#reset_name").val();
|
||||||
|
if (!name) return Client.showInputError("#reset_name", "请输入用户名");
|
||||||
|
if (!/^[a-z0-9]{5,15}$/.test(name)) return Client.showInputError("#reset_name", "用户名格式错误,需要5-15位字母开头的字母,数字或下划线,不区分大小写");
|
||||||
|
var phone = $("#reset_phone").val();
|
||||||
|
if (!phone) return Client.showInputError("#reset_phone", "请输入你的帐号绑定的手机号码");
|
||||||
|
if (!/^1\d{10}$/.test(phone)) return Client.showInputError("#reset_phone", "手机号码格式错误");
|
||||||
|
var valid_no = "";
|
||||||
|
var pwd1 = $("#reset_pwd1").val();
|
||||||
|
if (!pwd1) return Client.showInputError("#reset_pwd1", "请输入你的新密码");
|
||||||
|
var pwd2 = $("#reset_pwd2").val();
|
||||||
|
if (!pwd2) return Client.showInputError("#reset_pwd2", "请重复输入你的新密码");
|
||||||
|
if (pwd2.length < 6 || pwd2.length > 20) return Client.showInputError("#update_pwd2", "密码长度在6到20之间");
|
||||||
|
if (pwd2 != pwd1) return Client.showInputError("#reset_pwd2", "两次密码输入不一致");
|
||||||
|
Client.showLoader("正在修改密码", "#reset_panel");
|
||||||
|
API.ResetPasswordByPhone(name, phone, valid_no, pwd1, function (x) {
|
||||||
|
if (x.code) {
|
||||||
|
Client.hide2show("#login_panel");
|
||||||
|
} else {
|
||||||
|
Client.showInputError("#reset_pwd2", x.result ?? "重置失败");
|
||||||
|
Client.hide2show("#reset_panel");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ResetPwdPage;
|
||||||
157
src/login/roles.js
Normal file
157
src/login/roles.js
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
|
||||||
|
import { Page } from '../base/page.js';
|
||||||
|
import * as Client from '../client.js';
|
||||||
|
import { Confirm } from '../confirm.js';
|
||||||
|
|
||||||
|
var _name0 = "万俟司马上官欧阳夏侯诸葛闻人东方赫连皇甫尉迟公羊澹台公冶宗政濮阳淳于单于太叔申屠公孙仲孙轩辕令狐锺离宇文长孙慕容鲜于闾丘司徒司空丌官司寇子车颛孙端木巫马公西乐正公良拓拔夹谷谷梁梁丘左丘东门西门";
|
||||||
|
var _name1 = "赵钱孙李周吴郑王冯陈楮卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛奚范彭郎";
|
||||||
|
|
||||||
|
var _name2 = "世舜丞主产仁仇仓仕仞任伋众伸佐佺侃侪促俟信俣修倝倡倧偿储僖僧僳儒俊伟列则刚创前剑助劭势勘参叔吏嗣士壮孺守宽宾宋宗宙宣实宰尊峙峻崇崈川州巡帅庚战才承拯操斋昌晁暠曹曾珺玮珹琒琛琩琮琸瑎玚璟璥瑜生畴矗矢石磊砂碫示社祖祚祥禅稹穆竣竦综缜绪舱舷船蚩襦轼辑轩子杰榜碧葆莱蒲天乐东钢铎铖铠铸铿锋镇键镰馗旭骏骢骥驹驾骄诚诤赐慕端征坚建弓强彦御悍擎攀旷昂晷健冀凯劻啸柴木林森朴骞寒函高魁魏鲛鲲鹰丕乒候冕勰备宪宾密封山峰弼彪彭旁日明昪昴胜汉涵汗浩涛淏清澜浦澉澎澔瀚瀛灏沧虚豪豹辅辈迈邶合部阔雄霆震韩俯颁颇频颔风飒飙飚马亮仑仝代儋利力劼勒卓哲喆展帝弛弢弩彰征律德志忠思振挺掣旲旻昊昮晋晟晸朕朗段殿泰滕炅炜煜煊炎选玄勇君稼黎利贤谊金鑫辉墨欧有友闻问";
|
||||||
|
|
||||||
|
var _name3 = "筠柔竹霭凝晓欢霄枫芸菲寒伊亚宜姬舒影荔枝思丽秀娟英华慧巧美娜静淑惠珠翠雅芝玉萍红娥玲芬芳燕彩春菊勤珍贞莉兰凤洁梅琳素云莲真环雪荣妹霞香月莺媛艳瑞凡佳嘉琼桂娣叶璧璐娅琦晶妍茜秋珊莎锦黛青倩婷姣婉娴瑾颖露瑶怡婵雁蓓纨仪荷丹蓉眉君琴蕊薇菁梦岚苑婕馨瑗琰韵融园艺咏卿聪澜纯毓悦昭冰爽琬茗羽希宁欣飘育滢馥";
|
||||||
|
|
||||||
|
function create_name(s, t) {
|
||||||
|
t = t || (parseInt(Math.random() * 2) + 1);
|
||||||
|
var str = [];
|
||||||
|
if (t == 2) {
|
||||||
|
var key = parseInt(Math.random() * _name0.length);
|
||||||
|
if (key % 2 == 1) key -= 1;
|
||||||
|
str.push(_name0[key++]);
|
||||||
|
str.push(_name0[key]);
|
||||||
|
} else {
|
||||||
|
str.push(_name1[parseInt(Math.random() * _name1.length)]);
|
||||||
|
}
|
||||||
|
if (s == 0) {
|
||||||
|
str.push(_name2[parseInt(Math.random() * _name2.length)]);
|
||||||
|
} else {
|
||||||
|
str.push(_name3[parseInt(Math.random() * _name3.length)]);
|
||||||
|
}
|
||||||
|
if (parseInt(Math.random() * 4) > 1) {
|
||||||
|
if (s == 0) {
|
||||||
|
str.push(_name2[parseInt(Math.random() * _name2.length)]);
|
||||||
|
} else {
|
||||||
|
str.push(_name3[parseInt(Math.random() * _name3.length)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_id() {
|
||||||
|
var key1 = 'abcdefghijklmnopqrstuvwxyz';
|
||||||
|
var key2 = '123456789';
|
||||||
|
var str = [];
|
||||||
|
var length = parseInt(Math.random() * 3) + 3;
|
||||||
|
for (var i = 0; i < length; i++) {
|
||||||
|
if (i < 3) {
|
||||||
|
str.push(key1[parseInt(Math.random() * key1.length)]);
|
||||||
|
} else {
|
||||||
|
str.push(key2[parseInt(Math.random() * key2.length)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_prop() {
|
||||||
|
var sum = 20;
|
||||||
|
var ary = [];
|
||||||
|
for (var i = 0; i < 4; i++) {
|
||||||
|
var rand = parseInt(Math.random() * 15 + 1);
|
||||||
|
if (sum >= rand) {
|
||||||
|
i == 3 ? rand = sum : sum -= rand;
|
||||||
|
ary[i] = rand;
|
||||||
|
} else {
|
||||||
|
ary[i] = sum;
|
||||||
|
sum = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var me = {};
|
||||||
|
me.str = ary[0] + 15;
|
||||||
|
me.con = ary[1] + 15;
|
||||||
|
me.dex = ary[2] + 15;
|
||||||
|
me.int = ary[3] + 15;
|
||||||
|
return me;
|
||||||
|
}
|
||||||
|
|
||||||
|
function RefreshInput(type) {
|
||||||
|
switch (type) {
|
||||||
|
case 'name':
|
||||||
|
$("#reg_name").val(create_name($("#gender_0").is(":checked") ? 0 : 1));
|
||||||
|
break;
|
||||||
|
case 'id':
|
||||||
|
$("#reg_id").val(create_id());
|
||||||
|
break;
|
||||||
|
case 'prop':
|
||||||
|
var obj = create_prop();
|
||||||
|
$("#reg_str").val(obj.str);
|
||||||
|
$("#reg_con").val(obj.con);
|
||||||
|
$("#reg_dex").val(obj.dex);
|
||||||
|
$("#reg_int").val(obj.int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RolesPage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = `
|
||||||
|
<div id="role_panel" class="mypanel" style="display:none">
|
||||||
|
<ul>
|
||||||
|
<li class="panel_item active">选择你的角色</li>
|
||||||
|
<li class="content">
|
||||||
|
<ul class="role-list"></ul>
|
||||||
|
</li>
|
||||||
|
<li class="panel_item" command="SelectRole"><span class="glyphicon glyphicon-ok"></span><span
|
||||||
|
style="margin-left:0.5rem">登陆</span></li>
|
||||||
|
<li class="panel_item" command="AddRole"><span class="glyphicon glyphicon-plus"></span><span
|
||||||
|
style="margin-left:0.5rem">创建角色</span></li>
|
||||||
|
<li class="panel_item" command="DeleteRole"><span class="glyphicon glyphicon-remove"></span><span
|
||||||
|
style="margin-left:0.5rem">删除角色</span></li>
|
||||||
|
<li class="panel_item" command="ToServerPanel"><span
|
||||||
|
class="glyphicon glyphicon-chevron-left"></span><span style="margin-left:0.5rem">返回列表</span>
|
||||||
|
</li>
|
||||||
|
<li class="bottom">
|
||||||
|
<ul class="new-list">
|
||||||
|
<li nid="251026">10月27日重启更新预告</li>
|
||||||
|
<li nid="250928">国庆活动和更新说明</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
select() {
|
||||||
|
var item = $(".role-list>.select");
|
||||||
|
if (!item.length) return;
|
||||||
|
var id = item.attr("roleid");
|
||||||
|
SendCommand("login " + id);
|
||||||
|
Client.showLoader("正在进入游戏", "#role_panel");
|
||||||
|
}
|
||||||
|
|
||||||
|
addRole() {
|
||||||
|
var count = $(".role-list>.role-item").length;
|
||||||
|
if (count > 4) return Confirm.Show({
|
||||||
|
content: "你只能最多创建五个角色"
|
||||||
|
});
|
||||||
|
Client.hide2show($("#addrole_panel"));
|
||||||
|
RefreshInput("name");
|
||||||
|
RefreshInput("prop");
|
||||||
|
RefreshInput("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
delete() {
|
||||||
|
var item = $(".role-list>.select");
|
||||||
|
if (!item.length) return;
|
||||||
|
var id = item.attr("roleid");
|
||||||
|
if (!id) return;
|
||||||
|
Confirm.Show({
|
||||||
|
content: "是否确认删除角色:" + item.html(),
|
||||||
|
onOK: function () {
|
||||||
|
SendCommand("deleterole " + id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RolesPage;
|
||||||
|
export { RefreshInput };
|
||||||
111
src/login/server.js
Normal file
111
src/login/server.js
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
|
||||||
|
import { Page } from '../base/page.js';
|
||||||
|
import API from '../api.js';
|
||||||
|
import * as Client from '../client.js';
|
||||||
|
import Util from '../utils/util.js';
|
||||||
|
import { Confirm } from '../confirm.js';
|
||||||
|
|
||||||
|
let SERVERS = null;
|
||||||
|
|
||||||
|
class ServerPage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = `
|
||||||
|
<div id="slist_panel" class="mypanel" style="display:none">
|
||||||
|
<ul>
|
||||||
|
<li class="panel_item active">选择你要登录的游戏</li>
|
||||||
|
<li class="content">
|
||||||
|
<ul class="server-list"></ul>
|
||||||
|
</li>
|
||||||
|
<li class="panel_item" command="SelectServer"><span class="glyphicon glyphicon-ok"></span><span
|
||||||
|
style="margin-left:0.5rem">选择服务器</span></li>
|
||||||
|
<li class="panel_item" command="ToUpdate"><span class="glyphicon glyphicon-edit"></span><span
|
||||||
|
style="margin-left:0.5rem">修改密码</span></li>
|
||||||
|
<li class="panel_item" command="BindPhone"><span class="glyphicon glyphicon-lock"></span><span
|
||||||
|
style="margin-left:0.5rem">绑定手机</span></li>
|
||||||
|
<li class="panel_item" command="ReLogin"><span class="glyphicon glyphicon-chevron-left"></span><span
|
||||||
|
style="margin-left:0.5rem">返回登录</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
showServers() {
|
||||||
|
if (!SERVERS) {
|
||||||
|
Client.showLoader("正在获取服务器列表");
|
||||||
|
API.GetServer((x) => {
|
||||||
|
if (!x || typeof x == "string") {
|
||||||
|
Client.showInputError("#login_pwd", "获取服务器列表出错");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SERVERS = x;
|
||||||
|
this.displayServer(x);
|
||||||
|
this.showServers();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var x = SERVERS;
|
||||||
|
if (!x || !x.length) {
|
||||||
|
Client.hide2show("#login_panel");
|
||||||
|
Client.showInputError("#login_pwd", "获取服务器列表出错");
|
||||||
|
} else {
|
||||||
|
var sel_ser = Util.GetUserCookie("s");
|
||||||
|
var sel_item = sel_ser ? SERVERS[sel_ser] : (x.length == 1 ? SERVERS[0] : null);
|
||||||
|
if (sel_item) {
|
||||||
|
Client.showLoader("正在连接服务器");
|
||||||
|
return Client.connectServer(sel_item);
|
||||||
|
}
|
||||||
|
Client.hide2show("#slist_panel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectServer() {
|
||||||
|
if (!SERVERS) return;
|
||||||
|
var index = parseInt($(".server-list>.select").attr("index"));
|
||||||
|
if (!(index >= 0 && index < SERVERS.length)) {
|
||||||
|
return Confirm.Show({ content: "你没有选择要连接的服务器。" });
|
||||||
|
}
|
||||||
|
var item = SERVERS[index];
|
||||||
|
if (!item) {
|
||||||
|
Confirm.Show({ content: "你没有选择要连接的服务器。" });
|
||||||
|
}
|
||||||
|
Client.showLoader("正在连接服务器");
|
||||||
|
Client.connectServer(item);
|
||||||
|
Util.SetCookie("s", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
displayServer() {
|
||||||
|
if (!SERVERS) return;
|
||||||
|
var islocal = location.hostname.startsWith('127.0.0.1')
|
||||||
|
|| location.hostname.startsWith('localhost');
|
||||||
|
var istest = location.search.startsWith('?test');
|
||||||
|
if (islocal) {
|
||||||
|
SERVERS.push({ id: 100, name: "本地测试1", ip: "127.0.0.1", port: 31300 });
|
||||||
|
}
|
||||||
|
var html = [];
|
||||||
|
var named = "武神传说2";
|
||||||
|
for (var i = 0; i < SERVERS.length; i++) {
|
||||||
|
if (!istest && !islocal && SERVERS[i].istest) continue;
|
||||||
|
html.push("<li class='role-item");
|
||||||
|
if (i == 0) html.push(" select");
|
||||||
|
html.push("' index='" + i + "'>");
|
||||||
|
html.push(named);
|
||||||
|
html.push(" ");
|
||||||
|
html.push(SERVERS[i].name);
|
||||||
|
if (SERVERS[i].isdef) {
|
||||||
|
html.push("<span style='color:red;font-size:0.5rem;line-height:2rem;height:2rem;'> (推荐)</span>");
|
||||||
|
}
|
||||||
|
html.push("</li>");
|
||||||
|
}
|
||||||
|
|
||||||
|
$(".server-list").html(html.join("")).on("click", 'li', function () {
|
||||||
|
var elem = $(this);
|
||||||
|
if (elem.is(".select")) return;
|
||||||
|
elem.parent().find(".select").removeClass("select");
|
||||||
|
elem.addClass("select");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ServerPage;
|
||||||
|
export { SERVERS };
|
||||||
21
src/main.js
Normal file
21
src/main.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { Page } from './base/page.js';
|
||||||
|
import LoginPage from './login/index.js';
|
||||||
|
import GameMainPage from './game/main.js';
|
||||||
|
|
||||||
|
const login = new LoginPage();
|
||||||
|
const game = new GameMainPage();
|
||||||
|
|
||||||
|
class MainPage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.template = `${login.render()}\n${game.render()}`;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
on_mount() {
|
||||||
|
login.on_mount();
|
||||||
|
game.on_mount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MainPage;
|
||||||
356
src/map.js
Normal file
356
src/map.js
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
DIRS: ["west", "north", "south", "east", "northwest", "southwest", "northeast", "southeast",
|
||||||
|
"down", "up", "westdown", "northdown", "southdown", "eastdown", "westup", "northup", "southup", "eastup", "enter", "out"],
|
||||||
|
REG: /<(\w+)>(.+)<\/\w+>/,
|
||||||
|
CreateExitsMap: function (exits, w, name) {
|
||||||
|
var str = name.split("-");
|
||||||
|
if (str.length > 1) name = str[str.length - 1];
|
||||||
|
name = name.replace(/\(.*?\)/, "");
|
||||||
|
var unitY = 30;
|
||||||
|
var unitX = 70;
|
||||||
|
var unitW = 60;
|
||||||
|
var unitH = 20;
|
||||||
|
var height = unitY + 10;
|
||||||
|
var l = (w - unitW) / 2, t = 10;
|
||||||
|
var dirs = {};
|
||||||
|
if (exits["north"] && exits["up"]) {
|
||||||
|
exits["north_2"] = exits["up"];
|
||||||
|
delete exits["up"];
|
||||||
|
}
|
||||||
|
if (exits["south"] && exits["down"]) {
|
||||||
|
exits["south_2"] = exits["down"];
|
||||||
|
delete exits["down"];
|
||||||
|
}
|
||||||
|
for (var dir in exits) {
|
||||||
|
if (dir.indexOf("south") > -1 || dir == "down" || dir == "out") {
|
||||||
|
dirs["s"] = true;
|
||||||
|
} else if (dir.indexOf("north") > -1 || dir == "up" || dir == "enter") {
|
||||||
|
dirs["n"] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dirs.s) height += unitY;
|
||||||
|
if (dirs.n) {
|
||||||
|
height += unitY;
|
||||||
|
t += unitY;
|
||||||
|
}
|
||||||
|
var html = [];
|
||||||
|
html.push('<svg style="margin-left:-2em" height="' + height + '" width="' + w + '">');
|
||||||
|
html.push('<rect x="' + l + '" y="' + t + '" fill="dimgrey" stroke-width="1" stroke="gray" ');
|
||||||
|
html.push('width="' + unitW + '" height="' + unitH + '"></rect>');
|
||||||
|
html.push(' <text x="' + (l + 30) + '" y="' + (t + 14) + '" text-anchor="middle" style="font-size:12px;" ');
|
||||||
|
this.pushName(html, name, true);
|
||||||
|
for (var dir in exits) {
|
||||||
|
var pos1, pos2, pos;
|
||||||
|
switch (dir) {
|
||||||
|
case "west":
|
||||||
|
case "westup":
|
||||||
|
case "westdown":
|
||||||
|
pos1 = [l - (unitX - unitW), t + unitH / 2];
|
||||||
|
pos2 = [l, t + unitH / 2];
|
||||||
|
pos = [l - unitX, t];
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "east":
|
||||||
|
case "eastup":
|
||||||
|
case "eastdown":
|
||||||
|
pos1 = [l + unitW, t + unitH / 2];
|
||||||
|
pos2 = [l + unitX, t + unitH / 2];
|
||||||
|
pos = [l + unitX, t];
|
||||||
|
break;
|
||||||
|
case "south":
|
||||||
|
case "southup":
|
||||||
|
case "southdown":
|
||||||
|
case "down":
|
||||||
|
pos1 = [l + unitW / 2, t + unitH];
|
||||||
|
pos2 = [l + unitW / 2, t + unitY];
|
||||||
|
pos = [l, t + unitY];
|
||||||
|
break;
|
||||||
|
case "north":
|
||||||
|
case "northup":
|
||||||
|
case "northdown":
|
||||||
|
case "up":
|
||||||
|
pos1 = [l + unitW / 2, t];
|
||||||
|
pos2 = [l + unitW / 2, t - (unitY - unitH)];
|
||||||
|
pos = [l, t - unitY];
|
||||||
|
break;
|
||||||
|
case "northwest":
|
||||||
|
pos1 = [l - unitX + unitW, t - unitY + unitH];
|
||||||
|
pos2 = [l, t];
|
||||||
|
pos = [l - unitX, t - unitY];
|
||||||
|
break;
|
||||||
|
case "northeast":
|
||||||
|
case "north_2":
|
||||||
|
case "enter":
|
||||||
|
pos1 = [l + unitX, t - unitY + unitH];
|
||||||
|
pos2 = [l + unitW, t];
|
||||||
|
pos = [l + unitX, t - unitY];
|
||||||
|
break;
|
||||||
|
case "southeast":
|
||||||
|
case "south_2":
|
||||||
|
pos1 = [l + unitX, t + unitY];
|
||||||
|
pos2 = [l + unitW, t + unitH];
|
||||||
|
pos = [l + unitX, t + unitY];
|
||||||
|
break;
|
||||||
|
case "southwest":
|
||||||
|
case "out":
|
||||||
|
pos1 = [l - unitX + unitW, t + unitY];
|
||||||
|
pos2 = [l, t + unitH];
|
||||||
|
pos = [l - unitX, t + unitY];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var rm_name = exits[dir];
|
||||||
|
if (dir == "south_2") dir = "down";
|
||||||
|
else if (dir == "north_2") dir = "up";
|
||||||
|
html.push('<rect x="' + pos[0] + '" y="' + pos[1] + '" dir="' + dir + '" fill="#232323" stroke-width="1" stroke="gray" ');
|
||||||
|
html.push('width="' + unitW + '" height="' + unitH + '"></rect>');
|
||||||
|
html.push(' <text x="' + (pos[0] + 30) + '" y="' + (pos[1] + 14) + '" dir="' + dir + '" text-anchor="middle" style="font-size:12px;"');
|
||||||
|
this.pushName(html, rm_name, false);
|
||||||
|
|
||||||
|
if (pos1) {
|
||||||
|
html.push('<line stroke="gray" ');
|
||||||
|
html.push(" x1='" + pos1[0] + "' y1='" + pos1[1] + "' x2='" + pos2[0] + "' y2='" + pos2[1] + "'");
|
||||||
|
if (dir.indexOf("up") > -1 || dir.indexOf("down") > -1) {
|
||||||
|
html.push(" stroke-dasharray='5,5'");
|
||||||
|
html.push(" stroke-width='10'");
|
||||||
|
} else {
|
||||||
|
html.push(" stroke-width='1'");
|
||||||
|
}
|
||||||
|
html.push("></line >");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push("</svg>");
|
||||||
|
return html.join("");
|
||||||
|
}, colors: {
|
||||||
|
"hig": "#00FF00", "hir": "#FF0000", "him": "#FF00FF",
|
||||||
|
"hic": "#00FFFF", "hiy": "#FFFF00", "red": "#800000",
|
||||||
|
"wht": "#C0C0C0", "mag": "#800080", "red": "#800000"
|
||||||
|
, "hiw": "#FFFFFF", "gre": "#008000", "blu": "#000080", "hib": "#0000FF"
|
||||||
|
}, GetColor: function (name, issel) {
|
||||||
|
return this.colors[name.toLowerCase()] || "dimgrey";
|
||||||
|
},
|
||||||
|
ShowMap: function (map, id) {
|
||||||
|
if (!map) return;
|
||||||
|
this.CurMapID = id;
|
||||||
|
var html = [];
|
||||||
|
var pos = this.getMinPos(map);
|
||||||
|
var offX = 0 - pos.minX;
|
||||||
|
var offY = 0 - pos.minY;
|
||||||
|
var unitY = 50;
|
||||||
|
var unitX = 100;
|
||||||
|
var unitW = 60;
|
||||||
|
var unitH = 20;
|
||||||
|
var content = $(".map-panel");
|
||||||
|
this.MapWidth = (pos.maxX + offX + 1) * unitX;
|
||||||
|
var off_x = 0;
|
||||||
|
var content_width = content.width();
|
||||||
|
if (this.MapWidth < content_width) {
|
||||||
|
off_x = (content_width - this.MapWidth) / 2;
|
||||||
|
this.MapWidth = content_width;
|
||||||
|
}
|
||||||
|
this.MapHeight = (pos.maxY + offY + 1) * unitY;
|
||||||
|
if (this.MapWidth < 0 || this.MapHeight < 0) return;
|
||||||
|
var reg = /^([a-z]{1,2})(\d)?([d|l])?$/;
|
||||||
|
html.push('<svg class="map" height="' + this.MapHeight + '" width="' + this.MapWidth + '">');
|
||||||
|
for (var i = 0; i < map.length; i++) {
|
||||||
|
html.push("<rect class='map-room' rm='" + map[i].id + "' ");
|
||||||
|
|
||||||
|
var l = (map[i].p[0] + offX) * unitX + off_x + 20;
|
||||||
|
var t = (map[i].p[1] + offY) * unitY + 20;
|
||||||
|
html.push("x='" + l + "' y='" + t + "'");
|
||||||
|
html.push(' fill="dimgrey" stroke-width="1" stroke="gray" ');
|
||||||
|
html.push('width="' + unitW + '" height="' + unitH + '"></rect>');
|
||||||
|
var exits = map[i].exits;
|
||||||
|
if (exits) {
|
||||||
|
for (var j = 0; j < exits.length; j++) {
|
||||||
|
reg.test(exits[j]);
|
||||||
|
var length = RegExp.$2 ? parseInt(RegExp.$2) : 1;
|
||||||
|
var pos1;
|
||||||
|
var pos2;
|
||||||
|
switch (RegExp.$1) {
|
||||||
|
case "w":
|
||||||
|
pos1 = [l - (unitX - unitW) - unitX * (length - 1), t + unitH / 2];
|
||||||
|
pos2 = [l, t + unitH / 2];
|
||||||
|
break;
|
||||||
|
case "e":
|
||||||
|
pos1 = [l + unitW, t + unitH / 2];
|
||||||
|
pos2 = [l + unitX + unitX * (length - 1), t + unitH / 2];
|
||||||
|
break;
|
||||||
|
case "s":
|
||||||
|
pos1 = [l + unitW / 2, t + unitH];
|
||||||
|
pos2 = [l + unitW / 2, t + unitY + unitY * (length - 1)];
|
||||||
|
break;
|
||||||
|
case "n":
|
||||||
|
pos1 = [l + unitW / 2, t];
|
||||||
|
pos2 = [l + unitW / 2, t - (unitY - unitH) - unitY * (length - 1)];
|
||||||
|
break;
|
||||||
|
case "nw":
|
||||||
|
pos1 = [l - length * unitX + unitW, t - length * unitY + unitH];
|
||||||
|
pos2 = [l, t];
|
||||||
|
break;
|
||||||
|
case "ne":
|
||||||
|
pos1 = [l + unitW, t];
|
||||||
|
pos2 = [l + length * unitX, t - (unitY - unitH)];
|
||||||
|
break;
|
||||||
|
case "se":
|
||||||
|
pos1 = [l + unitW, t + unitH];
|
||||||
|
pos2 = [l + length * unitX, t + length * unitY];
|
||||||
|
break;
|
||||||
|
case "sw":
|
||||||
|
pos1 = [l, t + unitH];
|
||||||
|
pos2 = [l - (unitX - unitW) - unitX * (length - 1), t + length * unitY];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pos1) {
|
||||||
|
html.push('<line stroke="gray" ');
|
||||||
|
html.push(" x1='" + pos1[0] + "' y1='" + pos1[1] + "' x2='" + pos2[0] + "' y2='" + pos2[1] + "'");
|
||||||
|
if (RegExp.$3) {
|
||||||
|
html.push(" stroke-dasharray='5,5'");
|
||||||
|
}
|
||||||
|
if (RegExp.$3 == "l") {
|
||||||
|
html.push(" stroke-width='10'");
|
||||||
|
} else {
|
||||||
|
html.push(" stroke-width='1'");
|
||||||
|
}
|
||||||
|
html.push("></line >");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
html.push(' <text x="' + (l + 30) + '" y="' + (t + 14) + '" text-anchor="middle" style="font-size:12px;" ');
|
||||||
|
this.pushName(html, map[i].n, true);
|
||||||
|
}
|
||||||
|
html.push("</svg>");
|
||||||
|
content.html(html.join(""));
|
||||||
|
this.MapContent = $("svg");
|
||||||
|
if (!this.IsShow) {
|
||||||
|
this.IsShow = true;
|
||||||
|
$(".map-panel").slideDown("fast");
|
||||||
|
}
|
||||||
|
this.SetRoom(this.Room);
|
||||||
|
},
|
||||||
|
pushName: function (html, rm_name, issel) {
|
||||||
|
var mathch = this.REG.exec(rm_name);
|
||||||
|
if (mathch) {
|
||||||
|
html.push(' fill="' + this.GetColor(mathch[1]) + '"');
|
||||||
|
html.push('>' + mathch[2] + '</text>');
|
||||||
|
} else {
|
||||||
|
html.push(' fill="');
|
||||||
|
html.push(issel ? "#232323" : "dimgrey");
|
||||||
|
html.push('">' + rm_name + '</text>');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getMinPos: function (map) {
|
||||||
|
var pos = {
|
||||||
|
minX: 99999,
|
||||||
|
minY: 99999,
|
||||||
|
maxX: 0,
|
||||||
|
maxY: 0
|
||||||
|
};
|
||||||
|
for (var i = 0; i < map.length; i++) {
|
||||||
|
var x = map[i].p[0];
|
||||||
|
var y = map[i].p[1];
|
||||||
|
if (x < pos.minX) {
|
||||||
|
pos.minX = x;
|
||||||
|
} if (x > pos.maxX) pos.maxX = x;
|
||||||
|
if (y < pos.minY) {
|
||||||
|
pos.minY = y;
|
||||||
|
} if (y > pos.maxY) pos.maxY = y;
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
},
|
||||||
|
State: 0,
|
||||||
|
ZoomState: 100,
|
||||||
|
Buffer: {},
|
||||||
|
HideItem: function () {
|
||||||
|
if (this.State == 0) {
|
||||||
|
this.State = 1;
|
||||||
|
$(".room_desc").slideUp("fast");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ShowItem: function () {
|
||||||
|
if (this.State == 1) {
|
||||||
|
this.State = 0;
|
||||||
|
$(".room_desc").slideDown("fast");
|
||||||
|
}
|
||||||
|
}, ZoomIn: function (pars) {
|
||||||
|
if (pars.zoom) return;
|
||||||
|
this.ZoomState = this.ZoomState / pars.zoom;
|
||||||
|
if (this.ZoomState > 200) this.ZoomState = 200;
|
||||||
|
if (this.ZoomState < 80) this.ZoomState = 80;
|
||||||
|
var pw = this.MapWidth * this.ZoomState / 100;
|
||||||
|
var ph = this.MapHeight * this.ZoomState / 100;
|
||||||
|
this.MapContent.attr("viewBox", "0,0," + pw + "," + ph);
|
||||||
|
}, SetRoom: function (rm) {
|
||||||
|
this.Room = rm;
|
||||||
|
if (!this.IsShow) return;
|
||||||
|
|
||||||
|
if (this.CurRoomItem) {
|
||||||
|
this.CurRoomItem.attr("fill", "dimgrey");
|
||||||
|
this.CurRoomItem.attr("stroke", "gray");
|
||||||
|
}
|
||||||
|
this.CurRoomItem = null;
|
||||||
|
var item = this.MapContent.find("rect[rm='" + rm.path + "']");
|
||||||
|
if (item.length) {
|
||||||
|
this.CurRoomItem = item;
|
||||||
|
this.CurRoomItem.attr("fill", "#bebebe");
|
||||||
|
this.CurRoomItem.attr("stroke", "gray");
|
||||||
|
var pos = [item.attr("x"), item.attr("y"), item.attr("width"), item.attr("height")];
|
||||||
|
var elem = document.querySelector(".map-panel");
|
||||||
|
var height = elem.offsetHeight;
|
||||||
|
var width = elem.offsetWidth;
|
||||||
|
elem.scrollTop = pos[1] - (height - pos[3]) / 2;
|
||||||
|
elem.scrollLeft = pos[0] - (width - pos[2]) / 2;
|
||||||
|
}
|
||||||
|
var map_path = rm.path.substr(0, rm.path.lastIndexOf("/"));
|
||||||
|
if (map_path != this.CurMapID) {
|
||||||
|
if (this.Buffer[map_path]) {
|
||||||
|
return this.ShowMap(this.Buffer[map_path], map_path);
|
||||||
|
}
|
||||||
|
SendCommand("map " + map_path);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
LoadMap: function () {
|
||||||
|
if (this.IsShow) {
|
||||||
|
this.IsShow = false;
|
||||||
|
return $(".map-panel").slideUp("fast");
|
||||||
|
}
|
||||||
|
var rm = this.Room;
|
||||||
|
if (!rm) return;
|
||||||
|
var name = rm.path.substr(0, rm.path.lastIndexOf("/"));
|
||||||
|
if (name == this.CurMapID) {
|
||||||
|
$(".map-panel").slideDown("fast");
|
||||||
|
this.IsShow = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.Buffer[name]) {
|
||||||
|
return this.ShowMap(this.Buffer[name], name);
|
||||||
|
}
|
||||||
|
SendCommand("map " + name);
|
||||||
|
}, SetMapBuffer: function (maps, id) {
|
||||||
|
this.Buffer[id] = maps;
|
||||||
|
}, UpdateMap: function (mapid, data) {
|
||||||
|
var map = this.Buffer[mapid];
|
||||||
|
if (!map) return;
|
||||||
|
if (!data.id) {
|
||||||
|
this.Buffer[mapid] = null;
|
||||||
|
if (this.CurMapID == mapid) this.CurMapID = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < map.length; i++) {
|
||||||
|
if (map[i].id == data.id) {
|
||||||
|
map[i].n = data.n || map[i].n;
|
||||||
|
map[i].p = data.p || map[i].p;
|
||||||
|
map[i].exits = data.exits || map[i].exits;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mapid == this.CurMapID) {
|
||||||
|
this.ShowMap(map, mapid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
87
src/message.js
Normal file
87
src/message.js
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import Util from './utils/util.js';
|
||||||
|
|
||||||
|
const MessageQueue = {
|
||||||
|
size: 3,
|
||||||
|
max: 666,
|
||||||
|
container: null,
|
||||||
|
pages: null,
|
||||||
|
count: 0,
|
||||||
|
allow_scroll: true,
|
||||||
|
create: function (elem, size = 3, max = 666) {
|
||||||
|
let queue = Object.create(this);
|
||||||
|
queue.container = elem;
|
||||||
|
queue.pages = [];
|
||||||
|
queue.size = size;
|
||||||
|
queue.max = max;
|
||||||
|
|
||||||
|
if (Util.isMobile) {
|
||||||
|
elem.on('touchend', this.stopDrag.bind(queue));
|
||||||
|
} else {
|
||||||
|
elem.on('wheel', this.stopDrag.bind(queue));
|
||||||
|
}
|
||||||
|
queue.scroll_button = $('<div class="scroll-flag" style="display:none;"><span class="glyphicon glyphicon-chevron-down"></span></div>');
|
||||||
|
queue.scroll_button.appendTo(elem);
|
||||||
|
queue.scroll_button.on('pointerup', queue.start_move.bind(queue));
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
},
|
||||||
|
stopDrag: function (e) {
|
||||||
|
let is_end = this.is_end();
|
||||||
|
if (is_end === this.allow_scroll) return;
|
||||||
|
this.allow_scroll = is_end;
|
||||||
|
if (is_end) {
|
||||||
|
this.scroll_button.hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
start_move: function () {
|
||||||
|
this.allow_scroll = true;
|
||||||
|
this.scroll_button.hide();
|
||||||
|
this.scroll2end();
|
||||||
|
},
|
||||||
|
push: function (x) {
|
||||||
|
let queue = this.pages;
|
||||||
|
if (!queue.length) {
|
||||||
|
queue.push($("<pre></pre>").appendTo(this.container));
|
||||||
|
}
|
||||||
|
if (this.count > this.max) {
|
||||||
|
if (queue.length >= this.size) {
|
||||||
|
queue.splice(0, 1)[0].remove();
|
||||||
|
}
|
||||||
|
this.count = 0;
|
||||||
|
queue.push($("<pre></pre>").appendTo(this.container));
|
||||||
|
}
|
||||||
|
|
||||||
|
let page = queue[queue.length - 1];
|
||||||
|
page.append(x + "\n");
|
||||||
|
this.count++;
|
||||||
|
},
|
||||||
|
clear: function () {
|
||||||
|
for (let item of this.pages) {
|
||||||
|
item.remove();
|
||||||
|
}
|
||||||
|
this.pages.length = 0;
|
||||||
|
this.count = 0;
|
||||||
|
},
|
||||||
|
is_end: function () {
|
||||||
|
const elem = this.container[0];
|
||||||
|
const scrollHeight = elem.scrollHeight;
|
||||||
|
const clientHeight = elem.clientHeight;
|
||||||
|
const scrollTop = elem.scrollTop;
|
||||||
|
return scrollTop + clientHeight >= scrollHeight - 50;
|
||||||
|
},
|
||||||
|
scroll2end: function () {
|
||||||
|
const elem = this.container[0];
|
||||||
|
const scrollHeight = elem.scrollHeight;
|
||||||
|
const clientHeight = elem.clientHeight;
|
||||||
|
if (scrollHeight < clientHeight) return;
|
||||||
|
if (!this.allow_scroll) {
|
||||||
|
let rect = this.container[0].getBoundingClientRect();
|
||||||
|
|
||||||
|
return this.scroll_button.show().css('top',
|
||||||
|
rect.bottom - this.scroll_button.height() - screenTop);
|
||||||
|
}
|
||||||
|
elem.scrollTop = elem.scrollHeight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MessageQueue;
|
||||||
542
src/process.js
Normal file
542
src/process.js
Normal file
@@ -0,0 +1,542 @@
|
|||||||
|
|
||||||
|
import MessageQueue from './message.js';
|
||||||
|
import { connectServer, hide2show, isConnected, onLogin, SendCommand, showLoader, GameClient } from './client.js';
|
||||||
|
import Combat from './combat.js';
|
||||||
|
import Setting from './setting.js';
|
||||||
|
import MAP from './map.js';
|
||||||
|
import SCRIPT from './script.js';
|
||||||
|
import { roles } from './login/index.js';
|
||||||
|
import { SERVERS } from "./login/server.js";
|
||||||
|
|
||||||
|
const MessageContent = () => $(".content-message");
|
||||||
|
const MessagePage = { append: (div) => $(".content-message").append(div) };
|
||||||
|
|
||||||
|
const Process = {
|
||||||
|
itemsElement: null,
|
||||||
|
contentScroll: true,
|
||||||
|
message: null,
|
||||||
|
channel: null,
|
||||||
|
relogin() {
|
||||||
|
hide2show('#login_panel')
|
||||||
|
},
|
||||||
|
clear: function () {
|
||||||
|
Dialog.pack.items = null;
|
||||||
|
Dialog.skills.items = null;
|
||||||
|
|
||||||
|
this.state(null);
|
||||||
|
},
|
||||||
|
init: function () {
|
||||||
|
Process.itemsElement = $(".room_items");
|
||||||
|
this.message = MessageQueue.create($(".content-message"));
|
||||||
|
this.ChannelElement = $('.channel');
|
||||||
|
this.ChannelElement.on("click", Dialog.channel.show.bind(Dialog.channel));
|
||||||
|
this.channel = MessageQueue.create(this.ChannelElement, 4, 200);
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
startMoveMessage: function (e) {
|
||||||
|
window.addEventListener('mousemove', Process.moveMessage);
|
||||||
|
window.addEventListener("mouseup", Process.endMoveMessage);
|
||||||
|
Process.mouseY = e.clientY;
|
||||||
|
},
|
||||||
|
moveMessage: function (e) {
|
||||||
|
|
||||||
|
let diff = Process.mouseY - e.clientY;
|
||||||
|
let mc = MessageContent();
|
||||||
|
let elem = mc[0];
|
||||||
|
let height = mc.height();
|
||||||
|
let padding = elem.style.marginBottom;
|
||||||
|
if (padding) padding = parseInt(padding.replace('px', ""));
|
||||||
|
else padding = 0;
|
||||||
|
padding = (padding + diff);
|
||||||
|
if (padding < 0) padding = 0;
|
||||||
|
else if (padding > height * 0.7) return;
|
||||||
|
elem.style.marginBottom = padding + "px";
|
||||||
|
Process.mouseY = e.clientY;
|
||||||
|
e.preventDefault();
|
||||||
|
},
|
||||||
|
endMoveMessage: function () {
|
||||||
|
window.removeEventListener('mousemove', Process.moveMessage);
|
||||||
|
window.removeEventListener("mouseup", Process.endMoveMessage);
|
||||||
|
},
|
||||||
|
|
||||||
|
regist: function (x) {
|
||||||
|
if (x.result) {
|
||||||
|
hide2show("#addrole_panel");
|
||||||
|
$("#addrole_panel .input-error").html(x.result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emote: function (data) {
|
||||||
|
Process.emotes = data.items || 0;
|
||||||
|
var str = [];
|
||||||
|
for (var i = 0; i < Process.emotes.length; i++) {
|
||||||
|
str.push('<span>');
|
||||||
|
str.push(Process.emotes[i]);
|
||||||
|
str.push("</span>");
|
||||||
|
}
|
||||||
|
$(".channel-emotes").html(str.join(""));
|
||||||
|
}
|
||||||
|
, deleterole: function (x) {
|
||||||
|
if (x.result) {
|
||||||
|
var item = $("#role_panel>ul>.content>.role-list>.role-item[roleid='" + x.id + "']");
|
||||||
|
item.remove();
|
||||||
|
var elems = $("#role_panel>ul>.content>.role-list>.role-item");
|
||||||
|
if (item.is(".select") && elems.length) {
|
||||||
|
$(elems[0]).addClass("select");
|
||||||
|
} else if (!elems.length) {
|
||||||
|
roles.addRole();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Confirm.Show({
|
||||||
|
content: "<span class='input-error'>" + (x.message || "删除失败") + "</span>",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, cross: function (data) {
|
||||||
|
var serv = null;
|
||||||
|
for (var i = 0; i < SERVERS.length; i++) {
|
||||||
|
if (SERVERS[i].ID == data.sid) {
|
||||||
|
serv = SERVERS[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!serv) return;
|
||||||
|
|
||||||
|
GameClient.ChangeServer = true;
|
||||||
|
GameClient.Close();
|
||||||
|
Dialog.pack.items = null;
|
||||||
|
if (data.cross_type == 'duizhan') {
|
||||||
|
Dialog.skills.items = null;
|
||||||
|
Dialog.skills.isShow = false;
|
||||||
|
}
|
||||||
|
console.log("重新连接到", serv.Name);
|
||||||
|
if (!data.pid) Process.die({ relive: true });
|
||||||
|
connectServer(serv, data.pid);
|
||||||
|
}
|
||||||
|
,
|
||||||
|
roles: function (x) {
|
||||||
|
var result = x.roles;
|
||||||
|
if (!result.length) {
|
||||||
|
roles.addRole();
|
||||||
|
} else {
|
||||||
|
hide2show("#role_panel");
|
||||||
|
var html = [];
|
||||||
|
for (var i = 0; i < result.length; i++) {
|
||||||
|
html.push("<li class='role-item");
|
||||||
|
if (i == 0) html.push(" select");
|
||||||
|
html.push("' roleid='" + result[i].id + "'>");
|
||||||
|
html.push(result[i].title);
|
||||||
|
html.push(" ");
|
||||||
|
html.push(result[i].name);
|
||||||
|
html.push("</li>");
|
||||||
|
}
|
||||||
|
$(".role-list").html(html.join(""));
|
||||||
|
}
|
||||||
|
}, loginerror: function (msg) {
|
||||||
|
$(".container").hide();
|
||||||
|
$(".login-content").show();
|
||||||
|
showLoader("<strong>登陆失败:</strong>" + msg.msg + "");
|
||||||
|
|
||||||
|
//hide2show ("#role_panel");
|
||||||
|
}, login: function (x) {
|
||||||
|
if (!Process.player) {
|
||||||
|
hide2show(".container");
|
||||||
|
}
|
||||||
|
Process.player = x.id;
|
||||||
|
Process.level = x.level;
|
||||||
|
Setting.load(x.setting);
|
||||||
|
onLogin();
|
||||||
|
//var panel = $(".player-panel").html(CreateHeadPanel(x));
|
||||||
|
|
||||||
|
}, levelup: function (x) {
|
||||||
|
Process.level = x.level;
|
||||||
|
},
|
||||||
|
|
||||||
|
selectItem: function (e) {
|
||||||
|
if ($(e.target).is(".status-item")) {
|
||||||
|
var sid = e.target.getAttribute("sid");
|
||||||
|
let pid = $(e.target).closest('.room-item').attr('itemid');
|
||||||
|
if (!sid) return;
|
||||||
|
if (pid === Process.player)
|
||||||
|
return SendCommand("status " + sid);
|
||||||
|
return SendCommand("status " + sid + " " + pid);
|
||||||
|
}
|
||||||
|
var id = $(this).attr("itemid");
|
||||||
|
console.log(id);
|
||||||
|
if (id) {
|
||||||
|
if (id == Process.player) {
|
||||||
|
var name = $(this).find(".item-name").html();
|
||||||
|
|
||||||
|
var cmds = [{ cmd: "look " + id, name: "查看" },
|
||||||
|
{ cmd: "dazuo", name: "打坐" },
|
||||||
|
{ cmd: "liaoshang", name: "疗伤" }];
|
||||||
|
if (Dialog.team.items && Dialog.team.items.length) {
|
||||||
|
cmds.push({ cmd: "team out", name: "退出队伍" });
|
||||||
|
if (Dialog.team.isCap) {
|
||||||
|
cmds.push({ cmd: "team dismiss", name: "解散队伍" });
|
||||||
|
cmds.push({ cmd: "team set", name: "更改分配方式" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Process.item({
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
me: 1,
|
||||||
|
desc: name,
|
||||||
|
commands: cmds
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SendCommand("select " + id);
|
||||||
|
}
|
||||||
|
}, countwidth: function (m1, m2) {
|
||||||
|
var w = m1 * 100 / m2;
|
||||||
|
if (w < 0) w = 0;
|
||||||
|
if (w > 100) w = 100;
|
||||||
|
return w;
|
||||||
|
}, itemremove: function (data) {
|
||||||
|
var item = Combat.STATUS[data.id];
|
||||||
|
if (item) {
|
||||||
|
for (var si in item.items) {
|
||||||
|
clearInterval(item.items[si].handler);
|
||||||
|
}
|
||||||
|
var div = item.elem.parent();
|
||||||
|
if (div.next().is(".item-commands")) {
|
||||||
|
div.next().remove();
|
||||||
|
}
|
||||||
|
div.remove();
|
||||||
|
delete Combat.STATUS[data.id];
|
||||||
|
}
|
||||||
|
|
||||||
|
Process.cur_room.items.RemoveAt(x => x.id === data.id);
|
||||||
|
}, itemadd: function (data) {
|
||||||
|
if (Setting.off_plist && data.p && data.id != Process.player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var item = data, player_item;
|
||||||
|
if (Setting.item_firstme && item.id == Process.player) {
|
||||||
|
|
||||||
|
player_item = $(Process.create_roomitem(item)).prependTo(Process.itemsElement);
|
||||||
|
} else {
|
||||||
|
player_item = $(Process.create_roomitem(item)).appendTo(Process.itemsElement);
|
||||||
|
}
|
||||||
|
if (Combat.STATUS[data.id]) Process.itemremove(data);
|
||||||
|
Combat.AppendStatusItem(item.id, player_item.find(".item-status-bar"), item.status);
|
||||||
|
Process.cur_room.items.push(item);
|
||||||
|
}
|
||||||
|
, items: function (room) {
|
||||||
|
Process.itemsElement.empty();
|
||||||
|
Combat.STATUS = {};//更换房间,状态信息清空
|
||||||
|
for (var i = 0; i < room.items.length; i++) {
|
||||||
|
var item = room.items[i];
|
||||||
|
if (!item) continue;
|
||||||
|
item.player = item.p;
|
||||||
|
if (item.m) {
|
||||||
|
item.type = '师父';
|
||||||
|
item.master = 1;
|
||||||
|
}
|
||||||
|
if (item.f) {
|
||||||
|
item.type = '随从';
|
||||||
|
item.follower = 1;
|
||||||
|
}
|
||||||
|
if (item.l) {
|
||||||
|
item.type = '商人';
|
||||||
|
item.trader = 1;
|
||||||
|
}
|
||||||
|
if (Setting.off_plist && item.p && item.id != Process.player) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var player_item;
|
||||||
|
if (Setting.item_firstme && item.id == Process.player) {
|
||||||
|
|
||||||
|
player_item = $(Process.create_roomitem(item)).prependTo(Process.itemsElement);
|
||||||
|
} else {
|
||||||
|
player_item = $(Process.create_roomitem(item)).appendTo(Process.itemsElement);
|
||||||
|
}
|
||||||
|
Combat.AppendStatusItem(item.id, player_item.find(".item-status-bar"), item.status);
|
||||||
|
}
|
||||||
|
if (!Process.cur_room) Process.cur_room = {};
|
||||||
|
Process.cur_room.items = room.items;
|
||||||
|
},
|
||||||
|
|
||||||
|
get_hpnum: function (hp, max_hp) {
|
||||||
|
var diff = hp / max_hp;
|
||||||
|
if (diff > 0.8) return "<hiy>" + hp + "</hiy>";
|
||||||
|
if (diff > 0.5) return "<yel>" + hp + "</yel>";
|
||||||
|
if (diff > 0.2) return "<red>" + hp + "</red>";
|
||||||
|
return "<hir>" + hp + "</hir>";
|
||||||
|
}, create_roomitem: function (item) {
|
||||||
|
var str = [];
|
||||||
|
|
||||||
|
str.push("<div class='room-item' itemid='" + item.id + "'>");
|
||||||
|
if (item.max_hp) {
|
||||||
|
str.push('<div class="item-status"');
|
||||||
|
if (!Combat.IsShow || Setting.off_hp) {
|
||||||
|
str.push(' style="display:none;"');
|
||||||
|
}
|
||||||
|
|
||||||
|
str.push('>');
|
||||||
|
str.push('<div class="progress hp"><div class="progress-bar" max="' + item.max_hp + '" style="width:' + Process.countwidth(item.hp, item.max_hp) + '%"></div></div>');
|
||||||
|
str.push('<div class="progress mp"><div class="progress-bar" max="' + item.max_mp + '" style="width:' + Process.countwidth(item.mp, item.max_mp) + '%"></div></div>');
|
||||||
|
str.push("</div>");
|
||||||
|
}
|
||||||
|
str.push("<span class='item-status-bar'>");
|
||||||
|
|
||||||
|
str.push('</span>');
|
||||||
|
|
||||||
|
|
||||||
|
str.push("<span class='item-name'>");
|
||||||
|
str.push(item.name);
|
||||||
|
if (Setting.show_hpnum && item.max_hp) {
|
||||||
|
|
||||||
|
str.push('<span class="progress-num">['
|
||||||
|
+ this.get_hpnum(item.hp, item.max_hp) + "<nor>/</nor><hiy>" + item.max_hp + '</hiy>]</span>');
|
||||||
|
}
|
||||||
|
|
||||||
|
str.push('</span>');
|
||||||
|
str.push("</div>");
|
||||||
|
return str.join("");
|
||||||
|
},
|
||||||
|
room: function (room) {
|
||||||
|
$(".room_items").html("");
|
||||||
|
$(".room-name").html(room.name);
|
||||||
|
$(".room_desc").html(room.desc);
|
||||||
|
Process.room_name = room.name;
|
||||||
|
if (!Setting.keep_msg) {
|
||||||
|
Process.message.clear();
|
||||||
|
} else if (Setting.keep_msg) {
|
||||||
|
ReceiveMessage("你来到了" + room.name + "。");
|
||||||
|
}
|
||||||
|
if (Process.room_path == room.path) return;
|
||||||
|
if (Setting.show_roomitem) {
|
||||||
|
Process.searchItems(room);
|
||||||
|
}
|
||||||
|
|
||||||
|
Combat.ShowRoomCommands(room);
|
||||||
|
|
||||||
|
Process.room_path = room.path;
|
||||||
|
Process.cur_room = room;
|
||||||
|
MAP.SetRoom(room);
|
||||||
|
}, roomHiddenItemsReg: /<\w{3}\scmd=['"](.+?)['"]>(.+?)<\/\w{3}>/g,
|
||||||
|
searchItems: function (room) {
|
||||||
|
|
||||||
|
var result = null, roomdesc = room.desc;
|
||||||
|
while ((result = this.roomHiddenItemsReg.exec(roomdesc)) !== null) {
|
||||||
|
|
||||||
|
room.commands.push({
|
||||||
|
cmd: result[1],
|
||||||
|
name: result[2]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}, exits: function (room) {
|
||||||
|
var items = room ? room.items : Process.room_exits;
|
||||||
|
if (!items) return;
|
||||||
|
Process.room_exits = items;
|
||||||
|
if (Setting.exits_dir == 1) {
|
||||||
|
var str = ["这里明显的出口有:"];
|
||||||
|
var exits = [];
|
||||||
|
for (var i = 0; i < MAP.DIRS.length; i++) {
|
||||||
|
if (items[MAP.DIRS[i]]) {
|
||||||
|
exits.push(MAP.DIRS[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < exits.length; i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
str.push(i == exits.length - 1 ? " 和 " : "、");
|
||||||
|
}
|
||||||
|
str.push("<span class='exits-item' dir='" + exits[i] + "'>" + exits[i] + "</span>");
|
||||||
|
}
|
||||||
|
if (exits.length) {
|
||||||
|
$(".room_exits").html(str.join(""));
|
||||||
|
} else {
|
||||||
|
$(".room_exits").html("<HIK>这里没有明显的出口。<HIK>");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$(".room_exits").html(MAP.CreateExitsMap(items, $(".container").width(), Process.room_name))
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
before_click_exits: function (e) {
|
||||||
|
var elem = $(e.target);
|
||||||
|
if (!elem.attr("dir")) return;
|
||||||
|
if (elem.is("rect"))
|
||||||
|
elem.attr("fill", "gray");
|
||||||
|
else if (elem.is("text"))
|
||||||
|
elem.prev().attr("fill", "gray");
|
||||||
|
},
|
||||||
|
click_exits: function (e) {
|
||||||
|
var elem = $(e.target);
|
||||||
|
var dir = elem.attr("dir");
|
||||||
|
if (!dir) return;
|
||||||
|
if (elem.is("rect"))
|
||||||
|
elem.attr("fill", "#232323");
|
||||||
|
else if (elem.is("text"))
|
||||||
|
elem.prev().attr("fill", "#232323");
|
||||||
|
SendCommand("go " + dir);
|
||||||
|
}, query_rmitem: function (id) {
|
||||||
|
for (let item of this.cur_room.items) {
|
||||||
|
if (item.id === id) return item;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
item: function (item) {
|
||||||
|
ReceiveMessage(item.desc);
|
||||||
|
item.commands = item.commands ?? [];
|
||||||
|
let npc = Process.query_rmitem(item.id);
|
||||||
|
if (npc) item = Object.assign(item, npc);
|
||||||
|
|
||||||
|
SCRIPT.LAST_OBJ = item;
|
||||||
|
Dialog.extend.append(item.commands, 'item', item);
|
||||||
|
var html = ["<div class='item-commands'>"];
|
||||||
|
for (var i = 0; i < item.commands.length; i++) {
|
||||||
|
html.push("<span cmd='" + item.commands[i].cmd + "'>");
|
||||||
|
html.push(item.commands[i].name);
|
||||||
|
html.push("</span>");
|
||||||
|
}
|
||||||
|
html.push("</div>");
|
||||||
|
if (Setting.show_command && Combat.STATUS[item.id]) {
|
||||||
|
Process.itemsElement.find(".item-commands").remove();
|
||||||
|
var roomitem = Combat.STATUS[item.id].elem.parent();
|
||||||
|
$(html.join("")).insertAfter(roomitem);
|
||||||
|
|
||||||
|
return Process.message.scroll2end();
|
||||||
|
}
|
||||||
|
ReceiveMessage(html.join(""));
|
||||||
|
},
|
||||||
|
actions: function (data) {
|
||||||
|
Combat.ShowActions(data);
|
||||||
|
}, cmds: function (data) {
|
||||||
|
if (!data.items) return;
|
||||||
|
var html = ["<div class='item-commands'>"];
|
||||||
|
if (!data.items.length) data.items = [data.items];
|
||||||
|
for (var i = 0; i < data.items.length; i++) {
|
||||||
|
html.push("<span cmd='" + data.items[i].cmd + "'>");
|
||||||
|
html.push(data.items[i].name);
|
||||||
|
html.push("</span>");
|
||||||
|
}
|
||||||
|
html.push("</div>");
|
||||||
|
ReceiveMessage(html.join(""));
|
||||||
|
}
|
||||||
|
, map: function (x) {
|
||||||
|
MAP.SetMapBuffer(x.map, x.path);
|
||||||
|
MAP.ShowMap(x.map, x.path);
|
||||||
|
}, updatemap: function (x) {
|
||||||
|
MAP.UpdateMap(x.map, x);
|
||||||
|
}, dialog: function (data) {
|
||||||
|
Dialog.show(data.dialog, data);
|
||||||
|
}, sc: function (data) {
|
||||||
|
Combat.StatusChanged(data);
|
||||||
|
}, perform: function (data) {
|
||||||
|
Combat.ShowPFM(data);
|
||||||
|
}, disobj: function (data) {
|
||||||
|
Combat.DisObj(data);
|
||||||
|
}, changepfm: function (data) {
|
||||||
|
Combat.ChangeDistime(data);
|
||||||
|
}, clearDistime: function (data) {
|
||||||
|
Combat.ClearDistime(data);
|
||||||
|
}, pay: function (data) {
|
||||||
|
if (data.pay === 3) {//wxqr
|
||||||
|
ReceiveMessage('<yel>请打开微信扫描二维码支付:</yel>\n');
|
||||||
|
let div = $('<div style="width:100%;text-align:center;"><img style="border:solid 2px #808088" src="' + data.url + '"/></div>');
|
||||||
|
|
||||||
|
div.children(0).on('load', function () {
|
||||||
|
ReceiveMessage("");
|
||||||
|
});
|
||||||
|
MessagePage.append(div);
|
||||||
|
} else {
|
||||||
|
window.location.href = data.url;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dispfm: function (data) {
|
||||||
|
|
||||||
|
Combat.On_Perform(data);
|
||||||
|
}, status: function (data) {
|
||||||
|
Combat.StatusItemChanged(data);
|
||||||
|
},
|
||||||
|
combat: function (data) {
|
||||||
|
if (data.start) {
|
||||||
|
if (Setting.auto_showcombat == 1 && !Combat.IsShow) {
|
||||||
|
Combat.Show();
|
||||||
|
}
|
||||||
|
if (Setting.auto_hideroom == 1) {
|
||||||
|
if (!Setting.hide_roomdesc) {
|
||||||
|
$(".room_desc").hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.end) {
|
||||||
|
if (Setting.auto_hideroom == 1) {
|
||||||
|
if (!Setting.hide_roomdesc) {
|
||||||
|
$(".room_desc").show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, state: function (data) {
|
||||||
|
if (data && data.state) {
|
||||||
|
|
||||||
|
var ary = ["<span class='title'>" + data.state + "</span>"];
|
||||||
|
if (data.commands) {
|
||||||
|
// ary.push("<div class='item-commands'>");
|
||||||
|
for (var i = 0; i < data.commands.length; i++) {
|
||||||
|
ary.push("<span class='item-command' cmd='" + data.commands[i].cmd + "'>");
|
||||||
|
ary.push(data.commands[i].name);
|
||||||
|
ary.push("</span>");
|
||||||
|
}
|
||||||
|
// ary.push("</div>");
|
||||||
|
}
|
||||||
|
$(".state-bar").html(ary.join("")).css('visibility', 'visible');
|
||||||
|
|
||||||
|
if (data.no_stop) $(".state-tool").hide();
|
||||||
|
else $(".state-tool").show();
|
||||||
|
Process.states = data.desc;
|
||||||
|
if (Process.timer) clearInterval(Process.timer);
|
||||||
|
if (Process.states && Process.states.length) {
|
||||||
|
if (typeof Process.states == "string") {
|
||||||
|
Process.states = [Process.states];
|
||||||
|
}
|
||||||
|
Process.timer = setInterval(Process.updatestate, data.interval || 5000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$(".state-bar").empty().css('visibility', 'hidden');
|
||||||
|
$(".state-tool").hide();
|
||||||
|
clearInterval(Process.timer);
|
||||||
|
}
|
||||||
|
}, updatestate: function () {
|
||||||
|
if (Process.states && isConnected()) {
|
||||||
|
var length = Process.states.length;
|
||||||
|
ReceiveMessage(Process.states[parseInt(Math.random() * length)]);
|
||||||
|
}
|
||||||
|
}, die: function (data) {
|
||||||
|
if (data.relive) {
|
||||||
|
return Process.state({});
|
||||||
|
}
|
||||||
|
Process.state({
|
||||||
|
state: "<hiw>你已经死亡:</hiw>",
|
||||||
|
no_stop: true,
|
||||||
|
desc: ["<blk>一股阴冷的气息包围着你。</blk>", "<blu>朦胧中你好像听到有人在喊:过来吧,过来吧!</blu>"],
|
||||||
|
commands: data.commands,
|
||||||
|
interval: 12000
|
||||||
|
});
|
||||||
|
|
||||||
|
}, warn: function (data) {
|
||||||
|
Warn.Show(data);
|
||||||
|
}, msg: function (data) {
|
||||||
|
var msg = Dialog.channel.createElement(data, !Setting.no_spmsg);
|
||||||
|
if (!msg) return;
|
||||||
|
if (!Setting.no_spmsg) {
|
||||||
|
Process.channel.push(msg);
|
||||||
|
Process.channel.scroll2end();
|
||||||
|
} else {
|
||||||
|
ReceiveMessage(msg);
|
||||||
|
}
|
||||||
|
}, addAction: function (data) {
|
||||||
|
Combat.AddObj(data.id, data.name, data.distime);
|
||||||
|
}, removeAction: function (data) {
|
||||||
|
Combat.DisObj({ id: data.id, remove: true });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function ReceiveMessage(x) {
|
||||||
|
Process.message.push(x);
|
||||||
|
Process.message.scroll2end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default Process;
|
||||||
246
src/script.js
Normal file
246
src/script.js
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
|
||||||
|
import Util from './utils/util.js';
|
||||||
|
import { Confirm } from './confirm.js';
|
||||||
|
|
||||||
|
const MAP_DIR_EXITS = {
|
||||||
|
left: ["west", "westup", "westdown"],
|
||||||
|
right: ["east", "eastup", "eastdown"],
|
||||||
|
up: ["north", "northup", "northdown", 'up'],
|
||||||
|
down: ["south", "southup", "southdown", 'down'],
|
||||||
|
leftup: ["northwest"],
|
||||||
|
leftdown: ["southwest"],
|
||||||
|
rightup: ['northeast'],
|
||||||
|
rightdown: ['southeast']
|
||||||
|
};
|
||||||
|
|
||||||
|
const SCRIPT = {
|
||||||
|
is_running: false,
|
||||||
|
run: async function (str) {
|
||||||
|
this.is_running = true;
|
||||||
|
try {
|
||||||
|
let cmds = str.split(';');
|
||||||
|
for (let cmd of cmds) {
|
||||||
|
await this.run_one(cmd);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('扩展执行失败:', error);
|
||||||
|
}
|
||||||
|
this.is_running = false;
|
||||||
|
|
||||||
|
},
|
||||||
|
var_reg: /^@(\w+)(?:\(([^)]*)\))?$/,
|
||||||
|
run_one: async function (cmd) {
|
||||||
|
let paras = cmd.split(' ');
|
||||||
|
let action_name = paras[0];
|
||||||
|
let action = this.actions.def;
|
||||||
|
if (action_name[0] === '#') {
|
||||||
|
action_name = action_name.substring(1);
|
||||||
|
action = this.actions[action_name] ?? this.actions.def;
|
||||||
|
}
|
||||||
|
let results = [[]], para = null;
|
||||||
|
|
||||||
|
for (let i = 1; i < paras.length; i++) {
|
||||||
|
if (!results.length) break;
|
||||||
|
para = paras[i];
|
||||||
|
if (para[0] === '@') {
|
||||||
|
await this.push_paras(results, para);
|
||||||
|
} else {
|
||||||
|
results.map(x => x.push(para));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let result of results) {
|
||||||
|
await action(result, action_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
push_paras: async function (results, para) {
|
||||||
|
const match = para.match(this.var_reg);
|
||||||
|
if (!match) throw new Error("<cyn>错误的参数格式" + para + "</cyn>");
|
||||||
|
const method = match[1];
|
||||||
|
const params = match[2] ? match[2].split(',').map(param => param.trim()) : [];
|
||||||
|
let value = this.vars[method];
|
||||||
|
if (!value) throw new Error("<cyn>无效参数" + para + "</cyn>");
|
||||||
|
let vals = await value(...params);
|
||||||
|
if (!vals) return results.length = 0;
|
||||||
|
if (!Array.isArray(vals)) return results.map(x => x.push(vals));
|
||||||
|
if (!vals.length) return results.length = 0;
|
||||||
|
let index = results.length;
|
||||||
|
for (let i = 1; i < vals.length; i++) {
|
||||||
|
for (let j = 0; j < index; j++) {
|
||||||
|
results.push([...results[j], vals[i]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let j = 0; j < index; j++) {
|
||||||
|
results[j].push(vals[0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
|
||||||
|
def: function (paras, cmd) {
|
||||||
|
if (paras.length)
|
||||||
|
SendCommand(cmd + " " + paras.join(" "));
|
||||||
|
else
|
||||||
|
SendCommand(cmd);
|
||||||
|
},
|
||||||
|
wait: function (paras) {
|
||||||
|
return Util.Sleep(parseInt(paras[0]));
|
||||||
|
},
|
||||||
|
action: async function (paras) {
|
||||||
|
let index = parseInt(paras[0]);
|
||||||
|
if (!(index >= 0 && index < 10)) return;
|
||||||
|
let cmd = $('.room-commands').children().eq(index).attr('cmd');
|
||||||
|
if (cmd) SCRIPT.run(cmd);
|
||||||
|
},
|
||||||
|
pfm: function (paras) {
|
||||||
|
let index = parseInt(paras[0]);
|
||||||
|
if (!(index >= 0 && index < 10)) return SendCommand('perform ' + paras[0]);
|
||||||
|
let cmd = $('.combat-commands').children().eq(index).attr('pid');
|
||||||
|
if (cmd) SCRIPT.run("perform " + cmd);
|
||||||
|
}, menu: function (paras) {
|
||||||
|
let cmd = paras[0];
|
||||||
|
if (cmd) HandlerMenuCommand(cmd);
|
||||||
|
}, msg: function (paras) {
|
||||||
|
paras.length > 0 && ReceiveMessage(paras.join(""));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
vars: {
|
||||||
|
me: function () {
|
||||||
|
return Process.player;
|
||||||
|
},
|
||||||
|
dir: function (t) {
|
||||||
|
let dirs = MAP_DIR_EXITS[t];
|
||||||
|
if (!dirs) return;
|
||||||
|
for (let item of dirs) {
|
||||||
|
if (Process.room_exits[item])
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}, npc: function (...paras) {
|
||||||
|
let room = Process.cur_room;
|
||||||
|
let result = [];
|
||||||
|
for (let item of room.items) {
|
||||||
|
if (!item) continue;
|
||||||
|
if (item.hp > 0 && !item.p) {
|
||||||
|
if (!paras || !paras.length) {
|
||||||
|
result.push(item.id);
|
||||||
|
} else
|
||||||
|
for (let par of paras) {
|
||||||
|
if (item.name.indexOf(par) > -1) {
|
||||||
|
result.push(item.id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
item: function (...paras) {
|
||||||
|
let room = Process.cur_room;
|
||||||
|
let result = [];
|
||||||
|
for (let item of room.items) {
|
||||||
|
if (!item) continue;
|
||||||
|
if (!paras || !paras.length) {
|
||||||
|
result.push(item.id);
|
||||||
|
} else
|
||||||
|
for (let par of paras) {
|
||||||
|
if (item.name.indexOf(par) > -1) {
|
||||||
|
result.push(item.id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}, id: function () {
|
||||||
|
let obj = SCRIPT.LAST_OBJ;
|
||||||
|
if (obj) return obj.id;
|
||||||
|
return "";
|
||||||
|
},
|
||||||
|
obj: function (par) {
|
||||||
|
let obj = SCRIPT.LAST_OBJ;
|
||||||
|
if (!par || !obj) return;
|
||||||
|
return obj[par];
|
||||||
|
},
|
||||||
|
pack: function (...paras) {
|
||||||
|
let items = Dialog.pack.isShow ? Dialog.pack.items : Dialog.pack2.items;
|
||||||
|
if (!items) return;
|
||||||
|
let result = [];
|
||||||
|
for (let item of items) {
|
||||||
|
for (let par of paras) {
|
||||||
|
if (item.name.indexOf(par) > -1) {
|
||||||
|
result.push(item.id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
goods: function (...paras) {
|
||||||
|
let items = Dialog.list.selllist;
|
||||||
|
if (!items) return;
|
||||||
|
let result = [];
|
||||||
|
for (let item of items) {
|
||||||
|
for (let par of paras) {
|
||||||
|
if (item.name.indexOf(par) > -1) {
|
||||||
|
result.push(item.id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
input: function () {
|
||||||
|
const par = { btn_text: "确定", min: 0, max: 0 };
|
||||||
|
for (let i = 0; i < arguments.length; i++) {
|
||||||
|
let val = arguments[i];
|
||||||
|
if (typeof val === 'string') par.btn_text = val;
|
||||||
|
else par.max > 0 ? (par.min = val) : (par.max = val);
|
||||||
|
}
|
||||||
|
par.content = Confirm.get_countelement(par.min || 1,
|
||||||
|
par.max || 9999);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
par.onOK = resolve;
|
||||||
|
par.onCancle = reject;
|
||||||
|
Confirm.Show(par);
|
||||||
|
|
||||||
|
});
|
||||||
|
}, mat: function (val) {
|
||||||
|
let last = SCRIPT.lAST_MATCHES;
|
||||||
|
if (!last) return;
|
||||||
|
return last[val];
|
||||||
|
}, data: function (prop) {
|
||||||
|
if (!prop || !SCRIPT.LAST_DATA)
|
||||||
|
return;
|
||||||
|
return SCRIPT.LAST_DATA[prop];
|
||||||
|
}, master: function () {
|
||||||
|
return Dialog.master.master;
|
||||||
|
}, dc: function () {
|
||||||
|
if (Dialog.master.isShow) return "dc " + Dialog.master.master;
|
||||||
|
return Dialog.pack2.command_before;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
helper: {
|
||||||
|
actions: [
|
||||||
|
"#wait 100:等待100毫秒执行",
|
||||||
|
"#msg 你好:输出提示消息",
|
||||||
|
"#menu score,打开对话框",
|
||||||
|
"#action (0-9),执行动作栏对应位置的操作",
|
||||||
|
"#pfm (0-9),释放对应位置的绝招",
|
||||||
|
"持续增加"
|
||||||
|
],
|
||||||
|
vars: [
|
||||||
|
"@dir(left):获取当前房间左边方向的出口命令",
|
||||||
|
"@npc(小二):获取当前房间的npc ID,无参数返回所有npc",
|
||||||
|
"@item:获取当前房间所有物品ID,参数匹配名称",
|
||||||
|
"@id:当前正在操作的道具,技能,NPC等的ID",
|
||||||
|
"持续增加"
|
||||||
|
],
|
||||||
|
paras: [
|
||||||
|
"参数用来判断所在位置的数据属性,比如地图的参数,有name,type,index",
|
||||||
|
"name(扬州):名称里包含扬州二字的地图",
|
||||||
|
"index(>3):索引大于3的地图"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
export default SCRIPT;
|
||||||
|
export { MAP_DIR_EXITS };
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user