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