init: add workspace files
This commit is contained in:
195
world/extends/char/auto_combat.js
Normal file
195
world/extends/char/auto_combat.js
Normal file
@@ -0,0 +1,195 @@
|
||||
CHARACTER.prototype.reauto_attack = function () {
|
||||
if (!this.auto_pfm && this.fight_type) {
|
||||
if (this.attack_handler) clearTimeout(this.attack_handler);
|
||||
this.auto_attack();
|
||||
}
|
||||
}
|
||||
CHARACTER.prototype.auto_attack = function () {
|
||||
var target = this.query_enemy();
|
||||
if (this.hp <= 0) {
|
||||
if (this.fight_type && target) {
|
||||
return target.end_attack(this);
|
||||
}
|
||||
return this.end_fight();
|
||||
}
|
||||
if (!target) {
|
||||
return this.end_fight();
|
||||
}
|
||||
|
||||
if (this.is_faint) {
|
||||
this.attack_handler = this.call_out(this.auto_attack, this.is_faint);
|
||||
return;
|
||||
}
|
||||
if (this.release_time) {
|
||||
var diff_time = this.release_time - Date.now();
|
||||
if (diff_time > 0) {
|
||||
this.attack_handler = this.call_out(this.auto_attack, diff_time);
|
||||
return;
|
||||
}
|
||||
this.release_time = 0;
|
||||
}
|
||||
var sh = 0;
|
||||
|
||||
if (this.is_busy) {
|
||||
if (this.auto_pfm && this.busy_pfm) {
|
||||
if (!this.check_pfms(target)) {
|
||||
// this.send_room(guard_msg.random(), target);
|
||||
}
|
||||
} else {
|
||||
// this.send_room(guard_msg.random(), target);
|
||||
this.attack_handler = this.call_out(this.auto_attack, this.is_busy);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!this.auto_pfm || !this.check_pfms(target)) {
|
||||
if (target.fight_type) {
|
||||
//如果没有自动PFM 就普通攻击
|
||||
sh = this.do_attack({
|
||||
target: target,
|
||||
gj: this.gj,
|
||||
mz: this.mz
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!sh || this.end_attack(target, sh)) {
|
||||
this.attack_handler = this.call_out(this.auto_attack, this.gjsd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
CHARACTER.prototype.use_pfm = function (target, pfm, level, sktype) {
|
||||
if (!pfm) return false;
|
||||
var isrelease = false;
|
||||
if (this.query_prop('no_pfm')) {
|
||||
|
||||
this.send_room("<red>$N释放技能" + pfm.name + ",但是没有产生任何效果。</red>\n");
|
||||
|
||||
this.remove_status('bikou');
|
||||
isrelease = true;
|
||||
} else if (target && target.parry_skill && target.parry_skill.on_parry_pfm) {
|
||||
isrelease = target.parry_skill.on_parry_pfm(target, this, pfm, level);
|
||||
} else {
|
||||
isrelease = pfm.use(this, target, level, sktype) !== false;
|
||||
}
|
||||
if (isrelease !== false) {
|
||||
this.add_mp(-pfm.query_mp(this, level) || 0);
|
||||
|
||||
this.set_temp("used_pfm", pfm.id, 20000);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
CHARACTER.prototype.check_pfms = function (target) {
|
||||
if (!this.auto_skills) this.init_pfms();
|
||||
if (!this.auto_skills) return false;
|
||||
this.attack_count = this.attack_count || this.pfm_rate || 3;
|
||||
|
||||
if (this.random(this.attack_count) !== 0) {
|
||||
this.attack_count--;
|
||||
return false;
|
||||
}
|
||||
var now = Date.now();
|
||||
var canuser = [];
|
||||
for (var i = 0; i < this.auto_skills.length; i++) {
|
||||
var item = this.auto_skills[i];
|
||||
if (item.ban_use) {
|
||||
continue;
|
||||
}
|
||||
if (this.is_busy && !item.pfm.allow_busy) {
|
||||
continue;
|
||||
}
|
||||
if (item.release_time) {
|
||||
if (item.release_time > now) {
|
||||
continue;
|
||||
}
|
||||
item.release_time = 0;
|
||||
}
|
||||
if (item.pfm.query_mp(this, item.level) <= this.mp)
|
||||
canuser.push(item);
|
||||
}
|
||||
if (!canuser.length) return false;
|
||||
|
||||
var skill = canuser.random();
|
||||
if (!skill) return false;
|
||||
if (this.use_pfm(target, skill.pfm, skill.level, skill.type)) {
|
||||
|
||||
var rtime = skill.pfm.query_releasetime(this, skill.levelvel);
|
||||
|
||||
if (rtime > 0)
|
||||
this.release_time = rtime + now;
|
||||
else {
|
||||
this.release_time = 0;
|
||||
rtime = 0;
|
||||
}
|
||||
|
||||
skill.release_time = now +
|
||||
skill.pfm.query_distime(this, skill.level, skill.is_ref) + rtime;
|
||||
|
||||
return this.release_time > 0 || target.hp <= 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
CHARACTER.prototype.init_pfms = function () {
|
||||
this.auto_skills = [];
|
||||
if (!this.skills) return;
|
||||
var bases = ["", "force", "unarmed", "dodge", "parry", "bite", "throwing"];
|
||||
var weapon = this.query_weapon_type();
|
||||
if (weapon !== WEAPON_TYPE.NONE) bases[0] = weapon;
|
||||
if (this.is_player && !this.throwing_name()) {
|
||||
bases[6] = "";
|
||||
}
|
||||
for (var base of bases) {
|
||||
if (!base) continue;
|
||||
var base_skill = this.skills[base];
|
||||
if (!base_skill) continue;
|
||||
|
||||
var sp_skill = SKILL.get(base_skill.enable_skill || base);
|
||||
|
||||
var level = base_skill.enable_skill ?
|
||||
this.query_skill(base_skill.enable_skill)
|
||||
: this.query_skill(base);
|
||||
if (sp_skill && sp_skill.pfm) {
|
||||
for (var p in sp_skill.pfm) {
|
||||
this.add_auto_pfm(sp_skill.pfm[p], base, level, false);
|
||||
}
|
||||
}
|
||||
if (base_skill.enable_skill) {
|
||||
var ref_pfm = this.query_ref_skill(this.skills[base_skill.enable_skill]);
|
||||
if (ref_pfm) {
|
||||
this.add_auto_pfm(ref_pfm, base, level / 2, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CHARACTER.prototype.add_auto_pfm = function (pfmitem, baseSkill, level, is_ref) {
|
||||
if (pfmitem.no_auto) return;
|
||||
if (pfmitem.enable_skill && pfmitem.enable_skill !== baseSkill) return;
|
||||
if (pfmitem.check && pfmitem.check(this, level, baseSkill) === false) return;
|
||||
|
||||
if (pfmitem.allow_busy) this.busy_pfm = true;
|
||||
this.auto_skills.push({
|
||||
pfm: pfmitem,
|
||||
level: level,
|
||||
id: baseSkill + "/" + pfmitem.pid,
|
||||
type: baseSkill,
|
||||
is_ref: is_ref
|
||||
});
|
||||
}
|
||||
CHARACTER.prototype.set_releasetime = function (rtime) {
|
||||
let release_time = Date.now() + rtime;
|
||||
if (this.is_player) {
|
||||
this.notify('{type:"dispfm",id:"all",rtime:'
|
||||
+ rtime + ',distime:0}');
|
||||
} else {
|
||||
if (!this.auto_skills) this.init_pfms();
|
||||
}
|
||||
this.release_time = release_time;
|
||||
if (!this.auto_skills) return;
|
||||
for (let askill of this.auto_skills) {
|
||||
if (!askill.release_time || askill.release_time < release_time) {
|
||||
askill.release_time = release_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
382
world/extends/char/combat.js
Normal file
382
world/extends/char/combat.js
Normal file
@@ -0,0 +1,382 @@
|
||||
|
||||
CHARACTER.prototype.recount = function () {
|
||||
|
||||
this.gjsd = 4000 - this.query_prop("gjsd");
|
||||
this.gjsd = parseInt(this.gjsd - (this.gjsd * this.query_prop("gjsd_per") / 100));
|
||||
if (this.gjsd < 500) this.gjsd = 500;
|
||||
|
||||
this.gj = parseInt(this.str + (this.query_prop("gj") + this.query_prop("str") * this.str / 10) * (100 + this.query_prop("gj_per")) / 100);
|
||||
this.fy = parseInt(((this.str + this.con) / 10 + this.query_prop("fy") + this.query_prop("con") * this.con / 10) * (100 + this.query_prop("fy_per")) / 100);
|
||||
this.mz = parseInt((this.dex / 2 + this.query_prop("mz")) * (100 + this.query_prop("mz_per")) / 100);
|
||||
this.ds = parseInt((this.dex / 2 + this.query_prop("ds") + this.query_prop("dex") * this.dex / 5) * (100 + this.query_prop("ds_per")) / 100);
|
||||
this.zj = parseInt((this.str / 2 + this.query_prop("zj") + this.query_prop("str") * this.str / 5) * (100 + this.query_prop("zj_per")) / 100);
|
||||
this.bj = parseInt(this.dex / 10 + this.query_prop("bj_per"));
|
||||
|
||||
this.diff_sh_per = this.query_prop('diff_sh_per');
|
||||
this.diff_fy_per = this.query_prop('diff_fy_per');
|
||||
|
||||
|
||||
}
|
||||
|
||||
CHARACTER.prototype.crit = function (target, part, bj_per) {
|
||||
if (this.random(100) < bj_per
|
||||
+ (part ? part.crit : 0) - target.query_prop("diff_bj")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
CHARACTER.prototype.do_attack = function (par) {
|
||||
if (this.is_faint || this.hp <= 0 || !this.fight_type) return;
|
||||
var target = par.target;
|
||||
if (!target) {
|
||||
target = this.query_enemy();
|
||||
if (!target) return;
|
||||
}
|
||||
var weapon = this.query_weapon();//par.no_weapon ? null :
|
||||
var attackskill = par.no_weapon ? this.noweapon_skill : this.attack_skill;
|
||||
|
||||
if (attackskill.on_before_attack
|
||||
&& !par.is_throwing
|
||||
&& !par.no_append_before) attackskill.on_before_attack(this, target, par);
|
||||
if (this.force_skill.on_before_attack && !par.no_append_before) {
|
||||
this.force_skill.on_before_attack(this, target, par);
|
||||
}
|
||||
|
||||
this.attack_part = par.part ?? target.query_part();
|
||||
|
||||
var attack_msg = par.attack_msg;
|
||||
if (attack_msg === undefined) {
|
||||
attack_msg = attackskill.query_attack_action(this, target);
|
||||
}
|
||||
if (par.attack_before) {
|
||||
attack_msg = par.attack_before + attack_msg;
|
||||
}
|
||||
var weapon_type = par.no_weapon ?
|
||||
WEAPON_TYPE.NONE : (weapon ? weapon.weapon_type : WEAPON_TYPE.NONE);
|
||||
if (attack_msg) this.send_combat(attack_msg, target);
|
||||
|
||||
|
||||
var sh = par.gj ?? this.gj, mz = par.mz ?? this.mz;
|
||||
par.is_dodge = false; par.is_parry = false;
|
||||
if (target.is_faint || this.is_shadow) {
|
||||
par.is_dodge = false;
|
||||
par.is_parry = false;
|
||||
}
|
||||
else if (target.is_rash) {
|
||||
par.is_dodge = false;
|
||||
par.is_parry = (target.is_busy || par.no_parry) ? false : Math.random() * (target.zj / 2) + target.zj / 2 > mz;
|
||||
} else if (this.is_miss && !par.no_dodge) {
|
||||
par.is_dodge = true;
|
||||
par.is_parry = (target.is_busy || par.no_parry) ? false : Math.random() * (target.zj / 2) + target.zj / 2 > mz;
|
||||
} else if (target.is_miss || par.no_dodge) {
|
||||
par.is_dodge = false;
|
||||
par.is_parry = (target.is_busy || par.no_parry) ? false : (Math.random() * (target.zj / 2) + target.zj / 2 > mz);
|
||||
} else if (target.is_busy || par.no_parry) {
|
||||
par.is_dodge = Math.random() * (target.ds / 2) + target.ds / 2 > mz;
|
||||
par.is_parry = false;
|
||||
} else {
|
||||
par.is_dodge = Math.random() * (target.ds / 2) + target.ds / 2 > mz;
|
||||
par.is_parry = Math.random() * (target.zj / 2) + target.zj / 2 > mz;
|
||||
}
|
||||
if (par.is_dodge) {
|
||||
if (par.on_dodge) par.on_dodge(target);
|
||||
} else if (target.dodge_skill.on_dodge) {
|
||||
target.dodge_skill.on_dodge(target, this, par);
|
||||
}
|
||||
if (par.is_dodge) {
|
||||
sh = 0;
|
||||
this.send_combat((par.miss_msg || target.dodge_skill.query_dodge_action()) + "\n", target);
|
||||
} else {
|
||||
|
||||
if (target.parry_skill.on_parry &&
|
||||
!par.no_parry && !target.is_busy && !target.is_faint) {
|
||||
target.parry_skill.on_parry(target, this, par);
|
||||
}
|
||||
if (par.on_parry) {
|
||||
par.on_parry(target, par.is_parry);
|
||||
}
|
||||
par.bj = par.bj ?? this.bj;
|
||||
if (par.is_parry) {
|
||||
sh = 0;
|
||||
} else {
|
||||
if (weapon && weapon.do_attack &&
|
||||
((par.no_weapon && weapon_type === WEAPON_TYPE.NONE)
|
||||
|| (!par.no_weapon && weapon_type !== WEAPON_TYPE.NONE))
|
||||
&& !par.is_throwing) {
|
||||
sh += weapon.do_attack(this, target, par);
|
||||
}
|
||||
if (attackskill.on_attack && !par.is_throwing) {
|
||||
sh += attackskill.on_attack(this, target, par);
|
||||
}
|
||||
sh = sh * this.attack_part.hert;
|
||||
if (!par.no_power) {
|
||||
sh = sh + sh * this.query_prop("add_sh_per") / 100; //增加伤害%
|
||||
|
||||
par.iscirt = par.cirt ? par.cirt(target, this.attack_part, par.bj) : this.crit(target,
|
||||
this.attack_part, par.bj);
|
||||
|
||||
if (par.iscirt)
|
||||
sh = sh * (150 + (par.add_bjsh_per ?? this.query_prop("add_bjsh_per"))) / 100;
|
||||
}
|
||||
}
|
||||
let power_gj = par.power_gj ?? 0;
|
||||
if (this.force_skill.do_force_attack) {
|
||||
power_gj += this.force_skill.do_force_attack(this, target, par);
|
||||
}
|
||||
if (power_gj > 0 && (!weapon || weapon.weapon_type === WEAPON_TYPE.NONE)) {
|
||||
power_gj = power_gj + power_gj * this.query_prop("add_sh_per") / 100; //增加伤害%
|
||||
if (par.iscirt)
|
||||
power_gj = power_gj * (150 + (par.add_bjsh_per ?? this.query_prop("add_bjsh_per"))) / 100;
|
||||
|
||||
}
|
||||
|
||||
if (power_gj > 0) sh += power_gj;
|
||||
if (target.force_skill.on_force_parry) {
|
||||
par.power_gj = power_gj;
|
||||
sh -= target.force_skill.on_force_parry(target, this, sh, par);
|
||||
if (this.hp <= 0 || !target.fight_type) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (sh > 0)
|
||||
sh = target.damage(sh, this, par.diff_fy);
|
||||
|
||||
if (par.is_parry) {
|
||||
this.send_combat((par.parry_msg || target.parry_skill.query_parry_action(target, this, weapon_type)) + "\n", target);
|
||||
if (sh > 0) {
|
||||
target.send_combat(query_status_msg(target.hp, target.max_hp));
|
||||
target.on_damage && target.on_damage(this, sh);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sh > 0) {
|
||||
this.send_combat(damage_msg(sh, par.is_throwing ? WEAPON_TYPE.THROWING : weapon_type,
|
||||
target, par.iscirt, par.damage_msg)
|
||||
, target);
|
||||
target.send_combat(query_status_msg(target.hp, target.max_hp));
|
||||
target.on_damage && target.on_damage(this, sh);
|
||||
} else {
|
||||
this.send_combat("结果没有造成任何伤害。\n", true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (this.fight_type) {
|
||||
if (!par.no_append_target && target.fight_type) {
|
||||
target.dodge_skill.on_dodge_over
|
||||
&& target.dodge_skill.on_dodge_over(target, this, par);
|
||||
|
||||
if (!par.is_dodge)
|
||||
target.parry_skill.on_parry_over &&
|
||||
target.parry_skill.on_parry_over(target, this, par);
|
||||
}
|
||||
if (!par.no_append) {
|
||||
attackskill.on_attack_over && attackskill.on_attack_over(this, target, par, sh);
|
||||
this.force_skill.on_force_over &&
|
||||
this.force_skill.on_force_over(this, target, par, sh);
|
||||
}
|
||||
}
|
||||
return sh;
|
||||
}
|
||||
CHARACTER.prototype.from_attack = function (sh, mz, gjmsg, shmsg, dsmsg, parrymsg) {
|
||||
gjmsg && this.send_room(gjmsg);
|
||||
var is_dodge = mz > 0 ? Math.random() * (this.ds / 2) + this.ds / 2 > mz : false;
|
||||
if (is_dodge) {
|
||||
this.send_room((dsmsg || this.dodge_skill.query_dodge_action()), this);
|
||||
} else {
|
||||
this.send_room(shmsg);
|
||||
this.damage(sh);
|
||||
this.send_combat(query_status_msg(this.hp, this.max_hp));
|
||||
|
||||
if (this.fight_type === 1 && this.hp < 0) {
|
||||
this.hp = 1;
|
||||
} else if (this.hp <= 0) {
|
||||
this.die();
|
||||
this.end_fight();
|
||||
}
|
||||
}
|
||||
return is_dodge;
|
||||
}
|
||||
CHARACTER.prototype.do_recover = function (hp) {
|
||||
hp = hp + hp * this.query_prop('recover_per') / 100;
|
||||
if (!(hp > 0)) return 0;
|
||||
return this.add_hp(parseInt(hp));
|
||||
}
|
||||
|
||||
CHARACTER.prototype.damage = function (sh, from, diff_fy) {
|
||||
if (!(sh > 0)) return 0;
|
||||
let diff_sh_per = this.diff_sh_per;
|
||||
let fy = this.fy;
|
||||
if (diff_fy > 0) {
|
||||
diff_sh_per -= diff_sh_per * diff_fy / 100;
|
||||
fy -= fy * diff_fy / 100;
|
||||
}
|
||||
let diff_fy_per = from ? from.diff_fy_per : 0;//忽视防御,从免伤开始减
|
||||
if (diff_sh_per > 0 && diff_fy_per > 0) {
|
||||
diff_sh_per -= diff_fy_per;
|
||||
if (diff_sh_per < 0) {
|
||||
diff_fy_per = -diff_sh_per;
|
||||
}
|
||||
}
|
||||
if (fy > 0 && diff_fy_per > 0) {
|
||||
fy -= fy * diff_fy_per / 100;
|
||||
if (fy < 0) fy = 0;
|
||||
}
|
||||
if (diff_sh_per > 0)
|
||||
sh = sh - sh * diff_sh_per / 100;//伤害减免
|
||||
if (fy > 0 && sh > 0)
|
||||
sh = (sh / (sh + fy) * sh);
|
||||
sh = sh - this.query_prop("diff_sh");
|
||||
|
||||
if (sh > 0 && this.equipment && this.equipment[1] && this.equipment[1].on_defense) {
|
||||
sh = this.equipment[1].on_defense(this, from, sh);
|
||||
}
|
||||
if (sh > 0 && this.force_skill.on_damage) {
|
||||
sh = this.force_skill.on_damage(this, from, sh);
|
||||
}
|
||||
|
||||
if (sh > 0) {
|
||||
sh = parseInt(sh);
|
||||
if (this.record_damage && from) {
|
||||
if (!this.damages) this.damages = {};
|
||||
let damag = (this.damages[from.id] || 0) + sh;
|
||||
this.damages[from.id] = damag;
|
||||
this.sum_damages = (this.sum_damages ?? 0) + sh;
|
||||
}
|
||||
this.add_hp(-sh);
|
||||
return sh;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
CHARACTER.prototype.damage2 = function (sh, from) {
|
||||
if (!sh) return;
|
||||
|
||||
if (this.record_damage && from) {
|
||||
if (!this.damages) this.damages = {};
|
||||
var damag = (this.damages[from.id] || 0) + sh;
|
||||
this.damages[from.id] = damag;
|
||||
|
||||
}
|
||||
if (this.force_skill.on_damage) {
|
||||
sh = this.force_skill.on_damage(this, from, sh);
|
||||
if (!sh) return 0;
|
||||
}
|
||||
this.add_hp(-sh);
|
||||
return sh;
|
||||
}
|
||||
CHARACTER.prototype.damage3 = function (sh, from) {
|
||||
if (!(sh > 0)) return;
|
||||
|
||||
this.add_hp(-sh);
|
||||
if (this.force_skill.on_damage) {
|
||||
this.force_skill.on_damage(this, from, 0);
|
||||
}
|
||||
return sh;
|
||||
}
|
||||
|
||||
|
||||
var catch_hunt_msg = [
|
||||
"<HIW>$N和$n仇人相见分外眼红,立刻打了起来!</HIW>",
|
||||
"<HIW>$N对著$n大喝:「可恶,又是你!」</HIW>",
|
||||
"<HIW>$N和$n一碰面,二话不说就打了起来!</HIW>",
|
||||
"<HIW>$N一眼瞥见$n,「哼」的一声冲了过来!</HIW>",
|
||||
"<HIW>$N一见到$n,愣了一愣,大叫:「我宰了你!」</HIW>",
|
||||
"<HIW>$N喝道:「$n,我们的帐还没算完,看招!」</HIW>",
|
||||
"<HIW>$N喝道:「$n,看招!」</HIW>"];
|
||||
var guard_msg = [
|
||||
"<CYN>$N注视著$n的行动,企图寻找机会出手。\n</CYN>",
|
||||
"<CYN>$N正盯著$n的一举一动,随时准备发动攻势。\n</CYN>",
|
||||
"<CYN>$N缓缓地移动脚步,想要找出$n的破绽。\n</CYN>",
|
||||
"<CYN>$N目不转睛地盯著$n的动作,寻找进攻的最佳时机。\n</CYN>",
|
||||
"<CYN>$N慢慢地移动著脚步,伺机出手。\n</CYN>",
|
||||
];
|
||||
|
||||
|
||||
var status_msg = [
|
||||
"($N<HIG>看起来充满活力,一点也不累。</HIG>)\n",
|
||||
"($N<HIG>似乎有些疲惫,但是仍然十分有活力。</HIG>)\n",
|
||||
"($N<HIY>看起来可能有些累了。</HIY>)\n",
|
||||
"($N<HIY>动作似乎开始有点不太灵光,但是仍然有条不紊。</HIY>)\n",
|
||||
"($N<HIY>气喘嘘嘘,看起来状况并不太好。</HIY>)\n",
|
||||
"($N<RED>似乎十分疲惫,看来需要好好休息了。</RED>)\n",
|
||||
"($N<RED>已经一副头重脚轻的模样,正在勉力支撑著不倒下去。</RED>)\n",
|
||||
"($N<RED>看起来已经力不从心了。</RED>)\n",
|
||||
"($N<HIR>摇头晃脑、歪歪斜斜地站都站不稳,眼看就要倒在地上。</HIR>)\n",
|
||||
"($N<HIR>已经陷入半昏迷状态,随时都可能摔倒晕去。</HIR>)\n"
|
||||
];
|
||||
function query_status_msg(hp, maxhp) {
|
||||
var ratio = parseInt(hp * 10 / maxhp);
|
||||
if (ratio < 0) ratio = 0;
|
||||
if (ratio > 9) ratio = 9;
|
||||
return status_msg[9 - ratio];
|
||||
}
|
||||
function damage_msg2(msg, damage, iscrit) {
|
||||
return msg + "\n$N对$n造成" + iscrit ? ("<hir>" + damage + "</hir>点暴击伤害") : ("<wht>" + damage + "</wht>点伤害");//$N的攻击对$n
|
||||
}
|
||||
function damage_msg(damage, type, ob, iscrit, msg) {
|
||||
if (msg) {
|
||||
return msg + "\n$N对$n造成" + (iscrit ? ("<hir>" + damage + "</hir>点暴击伤害") : ("<wht>" + damage + "</wht>点伤害"));//$N的攻击对$n
|
||||
}
|
||||
|
||||
if (damage === 0) return "结果没有造成任何伤害。";
|
||||
var sh = iscrit ? "<hir>" + damage + "</hir>点暴击伤害" : "<wht>" + damage + "</wht>点伤害";
|
||||
if (ob.hp > 0) {
|
||||
damage = damage * 100 / ob.hp;
|
||||
} else
|
||||
damage = 120;
|
||||
switch (type) {
|
||||
case WEAPON_TYPE.BLADE:
|
||||
case WEAPON_TYPE.WHIP:
|
||||
if (damage < 5) return "结果只是轻轻地划破$p的皮肉,造成" + sh + "。";
|
||||
else if (damage < 10) return "结果在$p$l划出一道细长的血痕,造成" + sh + "!";
|
||||
else if (damage < 20) return "结果「嗤」地一声划出一道伤口,造成" + sh + "!";
|
||||
else if (damage < 40) return "结果「嗤」地一声划出一道血淋淋的伤口,造成" + sh + "!";
|
||||
else if (damage < 80) return "结果「嗤」地一声划出一道又长又深的伤口,溅得$N满脸鲜血,造成" + sh + "!";
|
||||
else return "结果只听见$n一声惨嚎,$w已在$p$l划出一道深及见骨的可怕伤口,造成" + sh + "!!";
|
||||
case WEAPON_TYPE.SWORD:
|
||||
if (damage < 10) return "结果只是轻轻地刺破$p的皮肉,造成" + sh + "!";
|
||||
else if (damage < 20) return "结果在$p$l刺出一个创口,造成" + sh + "!";
|
||||
else if (damage < 40) return "结果「噗」地一声刺入了$n$l寸许,造成" + sh + "!";
|
||||
else if (damage < 60) return "结果「噗」地一声刺进$n的$l,使$p不由自主地退了几步,造成" + sh + "!";
|
||||
else if (damage < 80) return "结果「噗嗤」地一声,$w已在$p$l刺出一个血肉模糊的血窟窿,造成" + sh + "!";
|
||||
else return "结果只听见$n一声惨嚎,$w已在$p的$l对穿而出,鲜血溅得满地,造成" + sh + "!!";
|
||||
case WEAPON_TYPE.NONE:
|
||||
case WEAPON_TYPE.STAFF:
|
||||
case WEAPON_TYPE.CLUB:
|
||||
if (damage < 5) return "结果只是轻轻地碰到,比拍苍蝇稍微重了点,造成" + sh + "!";
|
||||
else if (damage < 10) return "结果在$p的$l造成一处瘀青,造成" + sh + "!";
|
||||
else if (damage < 25) return "结果一击命中,$n的$l登时肿了一块老高,造成" + sh + "!";
|
||||
else if (damage < 40) return "结果一击命中,$n闷哼了一声显然吃了不小的亏,造成" + sh + "!";
|
||||
else if (damage < 50) return "结果「砰」地一声,$n退了两步,造成" + sh + "!";
|
||||
else if (damage < 60) return "结果这一下「砰」地一声打得$n连退了好几步,差一点摔倒,造成" + sh + "!";
|
||||
else if (damage < 80) return "结果重重地击中,$n「哇」地一声吐出一口鲜血,造成" + sh + "!";
|
||||
else return "结果只听见「砰」地一声巨响,$n像一捆稻草般飞了出去,造成" + sh + "!!";
|
||||
case "force":
|
||||
if (damage < 10) return "结果只是把$n打得退了半步,毫发无损,造成" + sh + "!";
|
||||
else if (damage < 20) return "结果$n痛哼一声,在$p的$l造成一处瘀伤,造成" + sh + "!";
|
||||
else if (damage < 30) return "结果一击命中,把$n打得痛得弯下腰去,造成" + sh + "!";
|
||||
else if (damage < 40) return "结果$n闷哼了一声,脸上一阵青一阵白,显然受了点内伤,造成" + sh + "!";
|
||||
else if (damage < 60) return "结果$n脸色一下变得惨白,昏昏沉沉接连退了好几步,造成" + sh + "!";
|
||||
else if (damage < 75) return "结果重重地击中,$n「哇」地一声吐出一口鲜血,造成" + sh + "!";
|
||||
else if (damage < 90) return "结果「轰」地一声,$n全身气血倒流,口中鲜血狂喷而出,造成" + sh + "!";
|
||||
else return "结果只听见几声喀喀轻响,$n一声惨叫,像滩软泥般塌了下去,造成" + sh + "!!";
|
||||
|
||||
case WEAPON_TYPE.THROWING:
|
||||
if (damage < 5) return "结果只是轻轻地划破$p的皮肉,造成" + sh + "。";
|
||||
else if (damage < 10) return "结果在$p$l划出一道细长的血痕,造成" + sh + "!";
|
||||
else if (damage < 20) return "结果「嗤」地一声划出一道伤口,造成" + sh + "!";
|
||||
else if (damage < 40) return "结果「嗤」地一声划出一道血淋淋的伤口,造成" + sh + "!";
|
||||
else if (damage < 80) return "结果「嗤」地一声划出一道又长又深的伤口,溅得$N满脸鲜血,造成" + sh + "!";
|
||||
else return "结果只听见$n一声惨嚎,$T已在$p$l划出一道深及见骨的可怕伤口,造成" + sh + "!!";
|
||||
default:
|
||||
//if (damage < 10) return "结果只是勉强造成一处轻微伤害!";
|
||||
//else if (damage < 20) return "结果造成轻微的伤害!";
|
||||
//else if (damage < 30) return "结果造成一处伤害!";
|
||||
//else if (damage < 50) return "结果造成一处严重伤害!";
|
||||
//else if (damage < 60) return "结果造成颇为严重的伤害!!";
|
||||
//else if (damage < 70) return "结果造成相当严重的伤害!!";
|
||||
//else if (damage < 80) return "结果造成十分严重的伤害!!";
|
||||
//else if (damage < 90) return "结果造成极其严重的伤害!!";
|
||||
//else return "结果造成非常可怕的严重伤害!!";
|
||||
return "<wht>结果造成" + sh + "。</wht>";
|
||||
}
|
||||
}
|
||||
197
world/extends/char/user.js
Normal file
197
world/extends/char/user.js
Normal file
@@ -0,0 +1,197 @@
|
||||
|
||||
USER.prototype.recount = function () {
|
||||
this.max_hp = parseInt(this.con * 5 + (this.max_mp * this.query_force_rad()
|
||||
+ this.query_prop("max_hp") + this.query_prop("con") * this.con) * (100 + this.query_prop("hp_per")) / 100);
|
||||
|
||||
if (this.hp > this.max_hp) this.hp = this.max_hp;
|
||||
|
||||
this.gjsd = 4000 - this.query_prop("gjsd");
|
||||
if (this.gjsd > 500) {
|
||||
this.gjsd = parseInt(this.gjsd - (this.gjsd * this.query_prop("gjsd_per") / 100));
|
||||
if (this.gjsd < 500) this.gjsd = 500;
|
||||
} else {
|
||||
this.gjsd = 500;
|
||||
}
|
||||
|
||||
this.gj = parseInt(this.str + (this.query_prop("gj") + this.query_prop("str") * this.str / 10) * (100 + this.query_prop("gj_per")) / 100);
|
||||
this.fy = parseInt(((this.str + this.con) / 10 + this.query_prop("fy") + this.query_prop("con") * this.con / 10) * (100 + this.query_prop("fy_per")) / 100);
|
||||
this.mz = parseInt((this.dex / 2 + this.query_prop("mz")) * (100 + this.query_prop("mz_per")) / 100);
|
||||
this.ds = parseInt((this.dex / 2 + this.query_prop("ds") + this.query_prop("dex") * this.dex / 10) * (100 + this.query_prop("ds_per")) / 100);
|
||||
if (this.dodge_skill && this.dodge_skill.on_recount_dodge) {
|
||||
this.ds += this.dodge_skill.on_recount_dodge(this);
|
||||
}
|
||||
this.zj = parseInt((this.str / 2 + this.query_prop("zj") + this.query_prop("str") * this.str / 10) * (100 + this.query_prop("zj_per")) / 100);
|
||||
if (this.parry_skill && this.parry_skill.on_recount_parry) {
|
||||
this.zj += this.parry_skill.on_recount_parry(this);
|
||||
}
|
||||
this.bj = parseInt(this.dex / 10 + this.query_prop("bj_per"));
|
||||
this.diff_sh_per = this.query_prop('diff_sh_per');
|
||||
|
||||
|
||||
this.diff_fy_per = this.query_prop('diff_fy_per');
|
||||
}
|
||||
|
||||
USER.prototype.level_up = function () {
|
||||
if (!this.level) {
|
||||
var sk = this.skill_limit();
|
||||
this.level = 1;
|
||||
this.notify("<hiy>恭喜你提升到了" + this.get_level_desc() + "境界。</hiy>");
|
||||
this.add_exp(10000, 10000);
|
||||
var now_sk = this.skill_limit();
|
||||
this.limit_mp += 1000;
|
||||
this.notify("<hiw>你的内力限制增加了1000。</hiw>");
|
||||
this.notify("<hiw>你的技能等级限制增加了" + (now_sk - sk) + "。</hiw>");
|
||||
|
||||
} else if (this.level == 1) {
|
||||
var sk = this.skill_limit();
|
||||
this.level = 2;
|
||||
this.notify("<hiy>恭喜你提升到了" + this.get_level_desc() + "境界。</hiy>");
|
||||
this.add_exp(100000, 100000);
|
||||
var now_sk = this.skill_limit();
|
||||
this.limit_mp += 5000;
|
||||
this.notify("<hiw>你的最大内力限制增加了5000。</hiw>");
|
||||
this.notify("<hiw>你的技能等级限制增加了" + (now_sk - sk) + "。</hiw>");
|
||||
} else if (this.level == 2) {
|
||||
var sk = this.skill_limit();
|
||||
this.level = 3;
|
||||
this.notify("<hiy>恭喜你提升到了" + this.get_level_desc() + "境界。</hiy>");
|
||||
this.add_exp(200000, 200000);
|
||||
var now_sk = this.skill_limit();
|
||||
this.limit_mp += 10000;
|
||||
this.notify("<hiw>你的最大内力限制增加了10000。</hiw>");
|
||||
this.notify("<hiw>你的技能等级限制增加了" + (now_sk - sk) + "。</hiw>");
|
||||
|
||||
} else if (this.level == 3) {
|
||||
var sk = this.skill_limit();
|
||||
this.level = 4;
|
||||
this.notify("<hiy>恭喜你提升到了" + this.get_level_desc() + "境界。</hiy>");
|
||||
this.add_exp(500000, 500000);
|
||||
var now_sk = this.skill_limit();
|
||||
this.limit_mp += 20000;
|
||||
this.notify("<hiw>你的最大内力限制增加了20000。</hiw>");
|
||||
this.notify("<hiw>你的技能等级限制增加了" + (now_sk - sk) + "。</hiw>");
|
||||
} else if (this.level == 4) {
|
||||
var sk = this.skill_limit();
|
||||
this.level = 5;
|
||||
this.notify("<hiy>恭喜你提升到了" + this.get_level_desc() + "境界。</hiy>");
|
||||
this.add_exp(1000000, 1000000);
|
||||
var now_sk = this.skill_limit();
|
||||
this.limit_mp += 50000;
|
||||
this.notify("<hiw>你的最大内力限制增加了50000。</hiw>");
|
||||
this.notify("<hiw>你的技能等级限制增加了" + (now_sk - sk) + "。</hiw>");
|
||||
} else if (this.level == 5) {
|
||||
var sk = this.skill_limit();
|
||||
this.level = 6;
|
||||
this.notify("<hiy>恭喜你提升到了" + this.get_level_desc() + "境界。</hiy>");
|
||||
this.add_exp(2000000, 2000000);
|
||||
this.limit_mp += 500000;
|
||||
this.add_temp("fenpei", 1);
|
||||
this.notify("<hiw>你的最大内力限制增加了500000。</hiw>");
|
||||
this.notify("<hiw>你的先天属性增加了1点。</hiw>");
|
||||
}
|
||||
this.color_name = null;
|
||||
this.environment.item_changed(this, true);
|
||||
this.send(`{type:"levelup",level:${this.level}}`);
|
||||
}
|
||||
USER.prototype.is_team = function (p) {
|
||||
if (!p || !p.team) return;
|
||||
return this.team == p.team;
|
||||
}
|
||||
|
||||
USER.prototype.query_teamid = function () {
|
||||
if (this.team) return this.team.id;
|
||||
return this.id;
|
||||
}
|
||||
|
||||
USER.prototype.can_trans = function () {
|
||||
if (!this.environment) return true;
|
||||
if (this.environment.is_fb()) return this.notify_fail("你现在正在副本区域。");
|
||||
if (this.environment.parent.on_leave(this) == false) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
USER.prototype.enable_area = function () {
|
||||
|
||||
let area = this.environment.parent;
|
||||
if (!(area.jd_index >= 0)) return;
|
||||
if (!this.query_bool('fb2', area.jd_index)) {
|
||||
this.set_bool('fb2', area.jd_index, true);
|
||||
this.send('<him>你解锁新地图【' + area.name + '】。</him>');
|
||||
this.send(`{type:"dialog",dialog:"jh",unlock2:${this.query_temp('fb2', 0)}}`);
|
||||
}
|
||||
|
||||
}
|
||||
USER.prototype.isenable_area = function (fb) {
|
||||
if (!fb) return false;
|
||||
if (typeof fb === 'number') {
|
||||
return this.query_bool('fb2', fb);
|
||||
}
|
||||
if (!(fb.jd_index >= 0)) return false;
|
||||
return this.query_bool('fb2', fb.jd_index);
|
||||
}
|
||||
USER.prototype.query_bool = function (key, index) {
|
||||
let step = parseInt(index / 32);
|
||||
if (step > 0) key = key.toString() + step.toString();
|
||||
let num = this.query_temp(key, 0);
|
||||
if (!num) return false;
|
||||
let bit = index % 32;
|
||||
return (num & (1 << bit)) !== 0;
|
||||
}
|
||||
USER.prototype.set_bool = function (key, index, value, time) {
|
||||
let step = parseInt(index / 32);
|
||||
if (step > 0) key = key.toString() + step.toString();
|
||||
let num = this.query_temp(key, 0);
|
||||
let bit = index % 32;
|
||||
if (value)
|
||||
this.set_temp(key, num | (1 << bit), time);
|
||||
else
|
||||
this.set_temp(key, num & ~(1 << bit), time);
|
||||
}
|
||||
USER.prototype.clear_bool = function (key, count) {
|
||||
let num = this.query_temp(key, 0);
|
||||
if (!num) return;
|
||||
for (let i = 0; i < count; i++) {
|
||||
if ((num & (1 << i)) !== 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.remove_temp(key);
|
||||
}
|
||||
|
||||
|
||||
USER.prototype.expend_jingli = function (val) {
|
||||
if (val > 0 && this.query_jingli() >= val) {
|
||||
var expend = this.query_temp("ex_jl", 0);
|
||||
if (expend >= 200) {
|
||||
var add = this.query_temp("ad_jl", 0);
|
||||
if (add < val) return false;
|
||||
this.add_temp("ad_jl", -val);
|
||||
|
||||
} else {
|
||||
if (expend + val > 200) {
|
||||
this.set_temp("ex_jl", 200, UTIL.diff_time());
|
||||
val = val - (200 - expend);
|
||||
this.add_temp("ad_jl", -val);
|
||||
} else {
|
||||
this.add_temp("ex_jl", val, UTIL.diff_time());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
USER.prototype.create_for = function (id) {
|
||||
if (!this.custom_skills) return false;
|
||||
return this.custom_skills.indexOf(id) > -1;
|
||||
}
|
||||
USER.prototype.query_age = function () {
|
||||
var dt = Date.now() - this.reg_time * 60000;
|
||||
|
||||
return 14 + dt / 86400000 / 12 - this.query_prop("age") - this.query_temp("age", 0);
|
||||
}
|
||||
FOLLOWER.prototype.remove_obj = USER.prototype.remove_obj;
|
||||
FOLLOWER.prototype.recount = USER.prototype.recount;
|
||||
FOLLOWER.prototype.items_changed = USER.prototype.items_changed;
|
||||
FOLLOWER.prototype.send_commands = USER.prototype.send_commands;
|
||||
|
||||
|
||||
115
world/extends/data.js
Normal file
115
world/extends/data.js
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
const STATS = WORLD.STATS;
|
||||
const DATA = WORLD.DATA;
|
||||
DATA.exps = [15, 20, 30, 40, 50, 100, 200, 80, 90, 100, 110, 120, 130];
|
||||
|
||||
DATA.stone_values = [1000, 5000, 30000, 150000, 1000000, 10000000];
|
||||
DATA.book_values = [1, 1000, 5000, 10000, 100000, 500000, 2000000];
|
||||
|
||||
DATA.get_exp = function (me) {
|
||||
return me.random(5) + this.exps[me.level];
|
||||
}
|
||||
|
||||
|
||||
|
||||
const FAMS_TATAS = ['WUDANG', 'HUASHAN', 'SHAOLIN',
|
||||
'EMEI', 'GAIBANG', 'XIAOYAO', 'SHASHOU', 'NONE'];
|
||||
DATA.on_save = function (str) {
|
||||
str.push(',tops:', STATS.saveTops(STATS.TOPS));
|
||||
|
||||
str.push(',score:', STATS.saveScore());
|
||||
|
||||
// str.push(',weapons:', STATS.saveWeapon());
|
||||
str.push(',messages:', WORLD.MESSAGE.save());
|
||||
str.push(',notices:', WORLD.MESSAGE.saveNotice());
|
||||
|
||||
for (let key of FAMS_TATAS) {
|
||||
let tops = STATS['tops_' + key];
|
||||
if (tops) {
|
||||
str.push(',tops_', key, ':', STATS.saveTops(tops));
|
||||
}
|
||||
}
|
||||
str.push(',eq_stats:', JSON.stringify(STATS.EQ_STATS ?? []));
|
||||
|
||||
str.push(',score_stats:', JSON.stringify(STATS.SC_STATS ?? {}));
|
||||
}
|
||||
|
||||
DATA.on_load = function (data) {
|
||||
WORLD.MESSAGE.load(data);
|
||||
this.remove_temp('xy_status');
|
||||
this.remove_temp('xy_users');
|
||||
this.remove_temp('xy_party');
|
||||
STATS.TOPS = STATS.load_tops(data.tops);
|
||||
// STATS.WEAPON = data.weapons ?? new Array(20).fill({ "score": 0 });
|
||||
STATS.SCORE = data.score ?? new Array(20).fill({ "name": "无", "score": 0 });
|
||||
STATS.EQ_STATS = new Array(11);
|
||||
data.eq_stats = data.eq_stats ?? [];
|
||||
for (let i = 0; i < 11; i++) {
|
||||
STATS.EQ_STATS[i] = data.eq_stats[i] ?? new Array(10).fill({ "score": 0 });
|
||||
}
|
||||
for (let key of FAMS_TATAS) {
|
||||
let tops = data['tops_' + key];
|
||||
STATS['tops_' + key] =
|
||||
STATS.load_tops(tops, FAMILIES[key].name + "弟子", key);
|
||||
}
|
||||
const sc_stats = data.score_stats ?? {};
|
||||
STATS.SC_STATS = {};
|
||||
for (let key of FAMS_TATAS) {
|
||||
STATS.SC_STATS[key] = sc_stats[key] ??
|
||||
new Array(20).fill({ "name": "无", "score": 0 });
|
||||
}
|
||||
|
||||
console.log("全局数据已加载");
|
||||
}
|
||||
DATA.create_def_tops = function () {
|
||||
for (let key of FAMS_TATAS) {
|
||||
STATS['tops_' + key] = STATS.load_tops(null, FAMILIES[key].name + "弟子");
|
||||
}
|
||||
|
||||
}
|
||||
DATA.create_def_eqs = function () {
|
||||
STATS.EQ_STATS = new Array(11);
|
||||
for (let i = 0; i < 11; i++) {
|
||||
STATS.EQ_STATS[i] = new Array(10).fill({ "score": 0 });
|
||||
}
|
||||
STATS.EQ_STATS[0] = STATS.WEAPON;
|
||||
}
|
||||
DATA.create_def_scs = function () {
|
||||
STATS.SC_STATS = {};
|
||||
for (let key of FAMS_TATAS) {
|
||||
STATS.SC_STATS[key] = new Array(20).fill({ "score": 0 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DATA.PROPS = {
|
||||
|
||||
|
||||
};
|
||||
|
||||
DATA.reset_famtops = function (me, fam) {
|
||||
me.remove_temp('top_fam_sc');
|
||||
me.remove_temp('top_fam');
|
||||
let tops = STATS['tops_' + fam.id];
|
||||
if (tops) {
|
||||
for (let i = 0; i < tops.length; i++) {
|
||||
let user = tops[i];
|
||||
if (user.userid === me.id) {
|
||||
user.userid = null;
|
||||
user.name = fam.name + "弟子";
|
||||
user.title = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
tops = STATS.SC_STATS?.[fam.id];
|
||||
if (tops) {
|
||||
for (let i = 0; i < tops.length; i++) {
|
||||
if (tops[i].id === me.id) {
|
||||
tops.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
15
world/extends/item/eq.js
Normal file
15
world/extends/item/eq.js
Normal file
@@ -0,0 +1,15 @@
|
||||
EQUIPMENT.prototype.query_score = function () {
|
||||
if (this.grade) {
|
||||
var sc = this.score;
|
||||
if (!sc) sc = this.grade * 100;
|
||||
sc += this.level * this.grade * 10;
|
||||
if (this.st_prop) {
|
||||
for (var i = 0; i < this.st_prop.length; i++) {
|
||||
sc += this.st_prop[i].grade * 10;
|
||||
}
|
||||
}
|
||||
return sc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
10
world/extends/item/obj.js
Normal file
10
world/extends/item/obj.js
Normal file
@@ -0,0 +1,10 @@
|
||||
OBJ.prototype.format_to_sell = function () {
|
||||
|
||||
return `["${this.color_name}","${this.id}",${this.count},${this.grade},"${this.unit}",${this.value}]`;
|
||||
}
|
||||
|
||||
|
||||
OBJ.prototype.format_to_pack = function () {
|
||||
|
||||
return `["${this.color_name}","${this.id}",${this.count},${this.grade},"${this.unit}",${this.transable ? this.value : 0},${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},${this.is_locked ? 1 : 0},${this.otype}]`;
|
||||
}
|
||||
101
world/extends/login.js
Normal file
101
world/extends/login.js
Normal file
@@ -0,0 +1,101 @@
|
||||
const USERLOGIN = WORLD.USERLOGIN;
|
||||
USERLOGIN.check_user = function (loginuser, id) {
|
||||
|
||||
return true;
|
||||
}
|
||||
USERLOGIN.check_session = function (user, str) {
|
||||
|
||||
if (user.userid) {
|
||||
return this.login_error(user, '参数错误');
|
||||
}
|
||||
str = str.split(" ");
|
||||
|
||||
if (str.length < 2) {
|
||||
return this.login_error(user, '参数错误');
|
||||
}
|
||||
var cookieUser = this.encryptUser(str[0], str[1]);
|
||||
if (!cookieUser || cookieUser.id === 0) {
|
||||
return this.login_error(user, "登录参数错误,请使用账号密码<CMD onclick=\\'HideAndShow(\"#login_panel\")\\'>重新登录</CMD>");
|
||||
}
|
||||
user.user_level = cookieUser.level ?? 0;
|
||||
|
||||
user.wait_input = null;
|
||||
user.userid = cookieUser.id;
|
||||
user.password = cookieUser.pwd;
|
||||
user.loginTime = cookieUser.loginTime;
|
||||
user.ip_address = user.socket.remoteAddress;
|
||||
if (cookieUser.id !== WORLD.admin_user) {
|
||||
if (WORLD.CONNECT_COUNT > WORLD.max_connect_count) {
|
||||
return this.login_error(user, '服务器人数过多,请稍后再试。');
|
||||
}
|
||||
if (str.length === 2 && WORLD.USERS.length > WORLD.max_user_count) {
|
||||
return this.login_error(user, '服务器人数过多,请稍后再试。');
|
||||
}
|
||||
if (!WORLD.before_login(user)) {
|
||||
return this.login_error(user, '服务器正在关闭或开启,请稍后再试。');
|
||||
}
|
||||
}
|
||||
|
||||
if (str.length === 4) {
|
||||
if (parseInt(str[3]) !== WORLD.SERVERID)
|
||||
return this.login_error(user, '参数错误。');
|
||||
var data = WORLD.can_cross(str[2]);
|
||||
if (!data) {
|
||||
return this.login_error(user, '不允许登录');
|
||||
}
|
||||
WORLD.on_user_cross_login(user, data);
|
||||
return;
|
||||
|
||||
} else {
|
||||
user.serverid = WORLD.SERVERID;
|
||||
}
|
||||
if (str[2]) {
|
||||
return this.wait_login(user, 'login ' + str[2]);
|
||||
}
|
||||
this.load_roles(user);
|
||||
user.wait_input = this.wait_login;
|
||||
}
|
||||
|
||||
USERLOGIN.wait_login = function (user, str) {
|
||||
if (!str) return;
|
||||
var i = str.indexOf(' ');
|
||||
var cmd = str, pars = "";
|
||||
if (i > 0) {
|
||||
cmd = str.substr(0, i);
|
||||
pars = str.substr(i + 1);
|
||||
}
|
||||
const command = WORLD.COMMANDS[cmd];
|
||||
if (command && command.allow_login) {
|
||||
return WORLD.COMMANDS[cmd].enter(user, pars);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
USERLOGIN.load_roles = async function (user) {
|
||||
try {
|
||||
let roles = await WORLD.DB.getRoles(user.userid, user.serverid);
|
||||
|
||||
if (!roles || !roles.length) {
|
||||
user.send("{type:'roles',roles:[]}");
|
||||
} else {
|
||||
|
||||
var str = ["{type:'roles',roles:["];
|
||||
for (var i = 0; i < roles.length; i++) {
|
||||
str.push("{name:'");
|
||||
str.push(roles[i].name);
|
||||
str.push("',title:'");
|
||||
str.push(roles[i].title);
|
||||
str.push("',id:'");
|
||||
str.push(roles[i].id);
|
||||
str.push("'}");
|
||||
if (i !== roles.length - 1) str.push(",");
|
||||
}
|
||||
str.push("]}");
|
||||
user.send(str.join(""));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(user.userid, '角色读取 ', error);
|
||||
WORLD.log(null, "登陆失败:" + user.userid, error.message);
|
||||
return USERLOGIN.login_error(user, '数据读取失败');
|
||||
}
|
||||
}
|
||||
22
world/extends/map/area.js
Normal file
22
world/extends/map/area.js
Normal file
@@ -0,0 +1,22 @@
|
||||
AREA.prototype.notify_update = function () {
|
||||
this.json = null;
|
||||
if (this.is_area)
|
||||
WORLD.send(`{type:"dialog",dialog:"jh",t:"fam",refresh:${this.index}}`);
|
||||
else
|
||||
WORLD.send(`{type:"dialog",dialog:"jh",t:"fb",refresh:${this.fb_index}}`);
|
||||
}
|
||||
AREA.prototype.query_owner = function (me) {
|
||||
return me.query_teamid();
|
||||
}
|
||||
AREA.prototype.clear_copy = function (me) {
|
||||
var room = ROOM.Get(this.first)?.query_copy2(me);
|
||||
if (room)
|
||||
room.clear_copy(me);
|
||||
}
|
||||
AREA.prototype.is_unlock = function (me) {
|
||||
if (this.jd_index >= 0)
|
||||
return me.isenable_area(this);
|
||||
return (this.unlock_index ?? this.fb_index) <= me.query_temp("fb", 0);
|
||||
}
|
||||
|
||||
|
||||
37
world/extends/map/fam_area.js
Normal file
37
world/extends/map/fam_area.js
Normal file
@@ -0,0 +1,37 @@
|
||||
const stand_actions = [
|
||||
['goto fam1', '练功', '回到你所在门派师父所在位置学习武功'],
|
||||
|
||||
['goto fam2', '后勤', '前往当前门派后勤管理的位置']
|
||||
];
|
||||
const pt_action = [
|
||||
'goto pt_fam', '进入战场', '你的帮派正在进攻'
|
||||
];
|
||||
|
||||
FAMILY_AREA.prototype.query_actions = function (me) {
|
||||
let actions = [];
|
||||
for (let item of stand_actions) {
|
||||
actions.push([
|
||||
item[0] + " " + this.family, item[1], item[2]
|
||||
]);
|
||||
}
|
||||
let fam = FAMILIES[this.family];
|
||||
if (fam.battle_family) {
|
||||
let target_fam = FAMILIES[fam.battle_family];
|
||||
actions.push([
|
||||
'goto fam3 ' + this.family, '进入战场', target_fam.name + "正在进攻" + fam.name
|
||||
]);
|
||||
}
|
||||
if (fam.first_npc) {
|
||||
actions.push([
|
||||
'sx greet', '请安', fam.name + "首席弟子:" + fam.first_npc.name
|
||||
]);
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
// FAMILY_AREA.prototype.query_owner = function (me) {
|
||||
// return me.query_teamid();
|
||||
// }
|
||||
FAMILY_AREA.prototype.notify_update = function () {
|
||||
this.json = null;
|
||||
WORLD.send(`{type:"dialog",dialog:"jh",t:"fam",refresh:${this.index}}`);
|
||||
}
|
||||
169
world/extends/message.js
Normal file
169
world/extends/message.js
Normal file
@@ -0,0 +1,169 @@
|
||||
|
||||
|
||||
const MESSAGE = WORLD.MESSAGE;
|
||||
MESSAGE.pushUserMessage = function (toid, from, msg) {
|
||||
let user = this.stores.get(toid);
|
||||
if (!user) {
|
||||
user = new Map();
|
||||
this.stores.set(toid, user);
|
||||
}
|
||||
let store = user.get(from.id);
|
||||
if (!store) {
|
||||
store = { name: from.name, items: [] };
|
||||
user.set(from.id, store);
|
||||
}
|
||||
msg.index = store.items.length;
|
||||
store.items.push(msg);
|
||||
|
||||
}
|
||||
MESSAGE.getUserMessages = function (me) {
|
||||
let store = this.stores.get(me.id);
|
||||
let newMessages = [];
|
||||
if (this.NOTICES.length) {
|
||||
let nt = this.NOTICES[this.NOTICES.length - 1];
|
||||
newMessages.push({
|
||||
id: "notice",
|
||||
content: nt.content.length > 50 ? nt.content.substring(0, 50) : nt.content,
|
||||
time: nt.time,
|
||||
name: "公告"
|
||||
});
|
||||
}
|
||||
if (store) {
|
||||
let diff_time = 24 * 3600000 * 30;
|
||||
let now = Date.now();
|
||||
store.forEach((x, y) => {
|
||||
let last = x.items[x.items.length - 1];
|
||||
if (last) {
|
||||
if (now - last.time < diff_time)
|
||||
newMessages.push({
|
||||
id: y,
|
||||
name: x.name,
|
||||
content: last.content,
|
||||
time: last.time
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return newMessages;
|
||||
}
|
||||
MESSAGE.getMessageFromID = function (me, from, count) {
|
||||
let items = [];
|
||||
if (from !== "notice") {
|
||||
let store = this.stores.get(me.id);
|
||||
if (!store) return;
|
||||
let list = store.get(from);
|
||||
if (!list) return items;
|
||||
items = list.items;
|
||||
} else {
|
||||
items = this.NOTICES;
|
||||
}
|
||||
count = count || 0;
|
||||
let ary = [];
|
||||
let diff_time = 24 * 3600000 * 30;
|
||||
let now = Date.now();
|
||||
for (let i = 0; i < 13; i++) {
|
||||
let index = items.length - count - i - 1;
|
||||
if (index < 0) break;
|
||||
if (now - items[index].time < diff_time)
|
||||
ary.push(items[index]);
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
MESSAGE.getMessageByIndex = function (me, from, index) {
|
||||
let store = this.stores.get(me.id);
|
||||
if (!store) return;
|
||||
let list = store.get(from);
|
||||
return list && list.items[index];
|
||||
}
|
||||
MESSAGE.save = function () {
|
||||
|
||||
let str = ["["];
|
||||
let now = Date.now();
|
||||
let diff_time = 24 * 3600000 * 30;
|
||||
this.stores.forEach((x, uid) => {
|
||||
if (str.length > 1) str.push(",");
|
||||
str.push("{id:\"");
|
||||
str.push(uid);
|
||||
str.push("\",items:[");
|
||||
let isReceive = false;
|
||||
x.forEach((st, from) => {
|
||||
if (isReceive) str.push(",");
|
||||
str.push("{uid:\"");
|
||||
str.push(from);
|
||||
str.push("\",name:\"");
|
||||
str.push(st.name);
|
||||
str.push("\",items:[");
|
||||
let ishasmsg = false;
|
||||
for (let i = 0; i < st.items.length; i++) {
|
||||
let item = st.items[i];
|
||||
if (now - item.time < diff_time) {
|
||||
if (ishasmsg) str.push(",");
|
||||
str.push("{time:");
|
||||
str.push(item.time);
|
||||
str.push(",content:`");
|
||||
str.push(item.content);
|
||||
str.push("`");
|
||||
if (item.attach) {
|
||||
str.push(",attach:[");
|
||||
for (let j = 0; j < item.attach.length; j++) {
|
||||
str.push("{name:\"");
|
||||
str.push(item.attach[j].name);
|
||||
str.push("\",obj:\"");
|
||||
str.push(item.attach[j].obj);
|
||||
str.push("\",count:");
|
||||
str.push(item.attach[j].count || 1);
|
||||
str.push("}");
|
||||
if (j !== item.attach.length - 1) {
|
||||
str.push(",");
|
||||
}
|
||||
}
|
||||
str.push("]");
|
||||
if (item.rec) {
|
||||
str.push(",rec:true");
|
||||
}
|
||||
}
|
||||
str.push("}");
|
||||
ishasmsg = true;
|
||||
}
|
||||
}
|
||||
str.push("]}");
|
||||
isReceive = true;
|
||||
});
|
||||
str.push("]}");
|
||||
});
|
||||
str.push("]");
|
||||
return str.join("");
|
||||
}
|
||||
MESSAGE.saveNotice = function () {
|
||||
if (this.NOTICES.length > 500) this.NOTICES.splice(0, this.NOTICES.length - 500);
|
||||
return JSON.stringify(this.NOTICES);
|
||||
}
|
||||
MESSAGE.load = function (data) {
|
||||
this.NOTICES = data.notices ?? [];
|
||||
let sts = data.messages ?? [];
|
||||
if (!sts) return;
|
||||
for (let i = 0; i < sts.length; i++) {
|
||||
let st = sts[i];
|
||||
let user = new Map();
|
||||
for (let j = 0; j < st.items.length; j++) {
|
||||
let ust = st.items[j];
|
||||
let obj = {
|
||||
name: ust.name,
|
||||
items: []
|
||||
};
|
||||
for (let k = 0; k < ust.items.length; k++) {
|
||||
let msg = ust.items[k];
|
||||
obj.items.push({
|
||||
content: msg.content,
|
||||
time: msg.time,
|
||||
rec: msg.rec,
|
||||
attach: msg.attach,
|
||||
index: obj.items.length
|
||||
});
|
||||
}
|
||||
user.set(ust.uid, obj);
|
||||
}
|
||||
this.stores.set(st.id, user);
|
||||
}
|
||||
console.log("消息数据已加载");
|
||||
}
|
||||
415
world/extends/skill/family.js
Normal file
415
world/extends/skill/family.js
Normal file
@@ -0,0 +1,415 @@
|
||||
FAMILY.prototype.init = function () {
|
||||
if (!this.def_npcs) return;
|
||||
for (let item of this.def_npcs) {
|
||||
let rm = ROOM.Get(item[1]);
|
||||
if (!rm) throw new Error('房间' + item[1] + "不存在");
|
||||
let npc = NPC.CLONE(item[0]);
|
||||
if (!npc) throw new Error('npc ' + item[0] + "不存在");
|
||||
rm.items.push(npc);
|
||||
rm.max_item_count = 100;
|
||||
npc.environment = rm;
|
||||
if (npc.is(this.boss_path) && !this.boss) {
|
||||
this.boss = npc;
|
||||
}
|
||||
npc.on_died = this.on_npc_die;
|
||||
npc.relive = this.on_famnpc_relive;
|
||||
}
|
||||
}
|
||||
FAMILY.UPDATE_NPC = function (path) {
|
||||
for (let key in FAMILIES) {
|
||||
let fam = FAMILIES[key];
|
||||
if (!fam.def_npcs) continue;
|
||||
fam.update_npc(path);
|
||||
}
|
||||
}
|
||||
FAMILY.prototype.update_npc = function (path) {
|
||||
for (let item of this.def_npcs) {
|
||||
let spath = item[0];
|
||||
if (spath.startsWith(path)) {
|
||||
let rm = ROOM.Get(item[1]);
|
||||
if (!rm) continue;
|
||||
let npc = rm.find_obj_bypath(spath);
|
||||
npc.destroy();
|
||||
npc = NPC.CREATE(spath, rm);
|
||||
if (npc.is(this.boss_path)) {
|
||||
this.boss = npc;
|
||||
}
|
||||
npc.on_died = this.on_npc_die;
|
||||
npc.relive = this.on_famnpc_relive;
|
||||
}
|
||||
}
|
||||
}
|
||||
FAMILY.prototype.on_famnpc_relive = function () {
|
||||
if (!this.die_room) return;
|
||||
this.die_room.item_changed(this, true);
|
||||
this.die_room = null;
|
||||
|
||||
if (this.equipment && this.items[0] && !this.equipment[0]) {
|
||||
this.equip(this.items[0]);
|
||||
}
|
||||
}
|
||||
FAMILY.prototype.on_npc_die = function (me) {
|
||||
//这里的this是被击杀的NPC
|
||||
var fam = FAMILIES[this.family.id];
|
||||
if (!me) return;
|
||||
var fam2 = FAMILIES[me.family.id];
|
||||
if (fam == fam2) {
|
||||
me.notify("<cyn>你残害同门,门派功绩减少。</cyn>");
|
||||
me.add_temp("gongji", -1);
|
||||
return;
|
||||
}
|
||||
if (!fam || !fam2 || fam == FAMILIES.NONE || fam2 == FAMILIES.NONE) return;
|
||||
|
||||
me.add_temp("killer_" + fam.id, 1, 600000);//十分钟门派仇恨
|
||||
me.notify("<red>你击杀了" + fam.name + "的弟子,对方门派在10分钟内可以对你发出追杀令。</red>");
|
||||
if (fam.battle_family || fam2.battle_family) {
|
||||
return;
|
||||
}
|
||||
fam.check_battle(this, me);
|
||||
}
|
||||
|
||||
|
||||
FAMILY.prototype.check_battle = function (npc, killer, target) {
|
||||
// if (!killer) return;
|
||||
var to_fam = killer ? killer.family : target;
|
||||
if (!to_fam || !to_fam.can_battle || !this.can_battle) return;
|
||||
|
||||
if (this.battle_family || to_fam.battle_family) return;
|
||||
if (this.query_temp("battle") ||
|
||||
to_fam.query_temp("battle")
|
||||
|| !this.boss || !to_fam.boss) return;
|
||||
this.battle_family = to_fam.id;
|
||||
to_fam.battle_family = this.id;
|
||||
if (killer) {
|
||||
if (npc !== this.boss) {
|
||||
this.on_kill(npc, killer);
|
||||
} else if (this.first_npc) {
|
||||
this.first_npc
|
||||
.do_command("chat",
|
||||
killer.family.name + "欺人太甚,门下弟子" + killer.name + "击杀我派" +
|
||||
npc.name + "," + this.name + "众弟子听令,对" + killer.family.name + "弟子格杀勿论!");
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
to_fam.on_battle(this);
|
||||
}
|
||||
|
||||
|
||||
this.begin_attack(to_fam);
|
||||
to_fam.begin_attack(this);
|
||||
npc.send_fam("<hiy>\n你的门派和" + to_fam.name + "的战斗开始了,请回门派防守或者进攻对方门派。\n战斗时间30分钟,结束条件是对方或己方掌门被击杀。</hiy>");
|
||||
|
||||
to_fam.send("<hiy>\n你的门派和" + this.name + "的战斗开始了,请回门派防守或者进攻对方门派。\n战斗时间30分钟,结束条件是对方或己方掌门被击杀。</hiy>");
|
||||
|
||||
|
||||
}
|
||||
|
||||
FAMILY.prototype.begin_attack = function (fam) {
|
||||
|
||||
this.battle_score = 0;
|
||||
this.set_temp("battle", 1, 3600000);
|
||||
this.call_out(this.battle_over, 30 * 60000, "timeout");
|
||||
|
||||
this.area.rooms[0].create_copy(this.id, 0);
|
||||
|
||||
this.area.notify_update();
|
||||
|
||||
this.create_guards();
|
||||
this.create_npcs();
|
||||
|
||||
EVENTS.add(this.create_event());
|
||||
}
|
||||
FAMILY.prototype.create_event = function (rm) {
|
||||
let target_fam = FAMILIES[this.battle_family];
|
||||
return {
|
||||
id: this.id + "_bat",
|
||||
name: "门派战争",
|
||||
desc: "你的门派正在和" + target_fam.name + "发生战争,击杀对方弟子会获得丰厚奖励。",
|
||||
time: Date.now() + 30 * 60000,
|
||||
grade: 2,
|
||||
command: "进入战场",
|
||||
check: (me) => me.family === this,
|
||||
on_command: function (me) {
|
||||
me.do_command('goto', 'fam3');
|
||||
}
|
||||
}
|
||||
}
|
||||
FAMILY.prototype.get_room = function (rm) {
|
||||
return rm.query_copy(this.id);
|
||||
}
|
||||
FAMILY.prototype.create_guards = function () {
|
||||
if (!this.boss_guard) return;
|
||||
|
||||
var boss_room = this.get_room(ROOM.Get(this.boss_guard[0]));
|
||||
var npc = NPC.CLONE("pub/menpai");
|
||||
npc.init_from(this, 5);
|
||||
npc.name = this.boss.name;
|
||||
npc.desc = this.boss.desc;
|
||||
npc.title = "<ora>" + this.boss.title + "</ora>";
|
||||
|
||||
npc.age = this.boss.age;
|
||||
npc.gender = this.boss.gender;
|
||||
this.npcs.push(npc);
|
||||
boss_room.item_changed(npc, true);
|
||||
|
||||
this.battle_boss = npc;
|
||||
for (var i = 0; i < this.boss_guard.length; i++) {
|
||||
for (var j = 0; j < 2; j++) {
|
||||
npc = NPC.CLONE("pub/menpai");
|
||||
npc.init_from(this, i == 0 ? 4 : 3);
|
||||
var rm = this.get_room(ROOM.Get(this.boss_guard[i]));
|
||||
|
||||
this.npcs.push(npc);
|
||||
rm.item_changed(npc, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
FAMILY.prototype.remove_npcs = function (npc) {
|
||||
this.npcs.remove(npc);
|
||||
if (this.battle_boss) {
|
||||
this.battle_boss.remove_status("boss");
|
||||
}
|
||||
}
|
||||
FAMILY.prototype.create_npc = function (level) {
|
||||
var npc = NPC.CLONE("pub/menpai");
|
||||
npc.init_from(this, level);
|
||||
return npc;
|
||||
}
|
||||
// let rm = null;
|
||||
// if (lv === 2 && this.guard_rooms) {
|
||||
// rm = ROOM.Get(this.guard_rooms.random());
|
||||
// }
|
||||
// if (!rm) rm = this.area.rooms.random();
|
||||
FAMILY.prototype.create_npcs = function () {
|
||||
if (this.npcs.length < 27) {
|
||||
let count = 27 - this.npcs.length;
|
||||
for (let i = 0; i < count; i++) {
|
||||
let lv = i > 15 ? 2 : (i < 8 ? 0 : 1);
|
||||
let rm = this.get_room(this.area.rooms.random());
|
||||
let npc = this.create_npc(lv);
|
||||
this.npcs.push(npc);
|
||||
rm.item_changed(npc, true);
|
||||
}
|
||||
if (this.battle_boss) {
|
||||
this.battle_boss.add_status({
|
||||
id: "boss",
|
||||
name: "号令",
|
||||
prop: {
|
||||
hp_per: 30,
|
||||
// gj_per: 30,
|
||||
fy_per: 30,
|
||||
ds_per: 30,
|
||||
mz_per: 30
|
||||
},
|
||||
no_clear: true,
|
||||
override: 1,
|
||||
count: count,
|
||||
max_count: 100,
|
||||
duration: 0,
|
||||
desc: "当你的门派还有NPC存活时,增加你的属性"
|
||||
});
|
||||
}
|
||||
}
|
||||
this.create_handler = this.call_out(this.create_npcs, 200000);
|
||||
}
|
||||
FAMILY.prototype.battle_over = function (suc_type) {
|
||||
if (!this.battle_family) return;
|
||||
var fam = FAMILIES[this.battle_family];
|
||||
if (!fam) return;
|
||||
this.battle_family = null;
|
||||
if (this.create_handler) clearTimeout(this.create_handler);
|
||||
for (var i = 0; i < this.npcs.length; i++) {
|
||||
if (this.npcs[i].hp > 0) {
|
||||
this.npcs[i].send_room("$N急匆匆的走掉了。");
|
||||
this.npcs[i].destroy();
|
||||
}
|
||||
}
|
||||
this.npcs.length = 0;
|
||||
if (suc_type == "suc") {
|
||||
COMMAND.DO("sys", "" + this.name + "和" + fam.name + "的战斗结束了," + this.name + "获得了最终胜利,接下来的一小时" + this.name + "所有弟子练功效率提高50%。");
|
||||
|
||||
this.add_battle_status(50);
|
||||
EVENTS.add(this.finish_event(50, fam));
|
||||
} else if (suc_type == "die") {
|
||||
this.send("<hir>由于你的门派掌门被击杀,和" + fam.name + "的战斗失败了。</hir>");
|
||||
} else if (suc_type == "fail") {
|
||||
this.send("<hir>由于你的门派掌门被击杀,和" + fam.name + "的战斗失败了。</hir>");
|
||||
} else {
|
||||
if (this.battle_score > fam.battle_score) {
|
||||
this.send("<hiy>和" + fam.name + "的战斗结束了,你的门派占得优势,接下来的一小时" + this.name + "所有弟子练功效率提高20%。</hiy>");
|
||||
this.add_battle_status(20);
|
||||
EVENTS.add(this.finish_event(20, fam));
|
||||
|
||||
} else {
|
||||
this.send("<hiy>和" + fam.name + "的战斗结束了,你的门派没有取得优势。</hiy>");
|
||||
EVENTS.add(this.finish_event(0, fam));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if (FAMILIES.SHASHOU.query_temp('ss_target') === this.id) {
|
||||
let sc = 0;
|
||||
if (suc_type === 'suc') sc = 0;
|
||||
else if (suc_type === 'fail') sc = 50;
|
||||
else sc = this.battle_score > fam.battle_score ? 0 : 20;
|
||||
EVENTS.remove(FAMILIES.SHASHOU.id + "_bat");
|
||||
EVENTS.add(FAMILIES.SHASHOU.finish_event(sc, this));
|
||||
FAMILIES.SHASHOU.remove_temp('ss_target');
|
||||
if (sc > 0) {
|
||||
FAMILIES.SHASHOU.add_battle_status(sc);
|
||||
FAMILIES.SHASHOU.send("<hiy>和"
|
||||
+ this.name + "的战斗结束了,你的门派占得优势,接下来的一小时所有弟子练功效率提高" + sc + "%。</hiy>");
|
||||
} else {
|
||||
FAMILIES.SHASHOU.send("<hiy>和"
|
||||
+ this.name + "的战斗结束了,你的门派没有取得优势。</hiy>");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// console.log(this.name, "战斗结束,清理NPC:", this.npcs.length);
|
||||
if (this.battle_boss)
|
||||
this.battle_boss.destroy();
|
||||
this.battle_boss = null;
|
||||
this.area.notify_update();
|
||||
this.call_out(this.clear_room, 300000);//300秒后清理战场副本
|
||||
EVENTS.remove(this.id + "_bat");
|
||||
}
|
||||
|
||||
FAMILY.prototype.clear_room = function () {
|
||||
const rm = this.area.rooms[0];
|
||||
rm.clear_by_area(rm.parent, this.id);
|
||||
}
|
||||
|
||||
FAMILY.prototype.finish_event = function (suc, target_fam) {
|
||||
let msg = suc > 0 ? "你的门派占得优势,所有弟子获得鼓舞,练功效率+" +
|
||||
suc + "%。" : "你的门派没有取得优势。";
|
||||
return {
|
||||
id: this.id + "_settle",
|
||||
name: "门派战争",
|
||||
desc: "你的门派和" + target_fam.name + "战斗结束了," + msg,
|
||||
time: this.temp["battle"].e,
|
||||
grade: 2,
|
||||
command: "领取战利品",
|
||||
check: (me) => me.family === this,
|
||||
on_command: (me) => {
|
||||
// if (!suc) return me.send('你所在的门派没有在战争中取得优势,请再接再厉。');
|
||||
this.battle_settle(me)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
FAMILY.prototype.add_battle_status = function (t) {
|
||||
this.battle_gift = t;
|
||||
this.add_temp("lianxi_per", t, 3600000);
|
||||
this.add_temp("study_per", t, 3600000);
|
||||
this.add_temp("dazuo_per", t, 3600000);
|
||||
|
||||
}
|
||||
FAMILY.prototype.on_login = function (me) {
|
||||
if (this.first_npc && me.id == this.first_npc.userid) {
|
||||
if (!this.is_init_first)
|
||||
this.init_dadizi(this.first_npc, me);
|
||||
this.send('{type:"msg",ch:"fam",content:"' + this.first_npc.title + me.name + '上线了。",uid:0,name:"",fam:"' + this.name + '"}');
|
||||
}
|
||||
}
|
||||
FAMILY.prototype.set_dadizi = function (id, name) {
|
||||
this.tops = {};
|
||||
|
||||
if (this.boss)
|
||||
this.boss.do_command("fam", '本门弟子' + name + '表现突出,提升为' + this.top_name + '。');
|
||||
|
||||
this.is_init_first = false;
|
||||
WORLD.DATA.set_temp(this.id + "_top", id);
|
||||
WORLD.DATA.set_temp(this.id + "_top_name", name);
|
||||
if (this.first_npc) {
|
||||
if (this.first_npc.environment.is_shadow) {
|
||||
var rm = ROOM.Get(this.first_npc.environment.path);
|
||||
var npc = rm.find_obj_bypath('pub/dadizi#' + this.id);
|
||||
if (npc) {
|
||||
this.first_npc = npc;
|
||||
} else {
|
||||
this.first_npc = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.init_dadizi(this.first_npc, WORLD.getUser(id));
|
||||
this.area.notify_update();
|
||||
}
|
||||
}
|
||||
FAMILY.prototype.init_dadizi = function (npc, me) {
|
||||
this.first_npc = npc;
|
||||
npc.name = WORLD.DATA.query_temp(this.id + "_top_name") || this.top_name;
|
||||
npc.title = this.top_name;
|
||||
npc.userid = WORLD.DATA.query_temp(this.id + "_top");
|
||||
if (!me) return;
|
||||
npc.level = me.level;
|
||||
var copy_prop = ["str", "con", "dex", "int", "gender", "max_mp", "exp", "pot", "kar", "per"
|
||||
, "name", "skills", "hp", "max_hp", "mp"];
|
||||
for (var i = 0; i < copy_prop.length; i++) {
|
||||
npc[copy_prop[i]] = me[copy_prop[i]];
|
||||
}
|
||||
npc.equipment = [];
|
||||
if (me.equipment) {
|
||||
var eqs = me.equipment;
|
||||
for (var i = 0; i < eqs.length; i++) {
|
||||
if (!eqs[i]) continue;
|
||||
var obj = eqs[i].clone(me);
|
||||
npc.equipment[obj.eq_type] = obj;
|
||||
}
|
||||
}
|
||||
npc.max_hp = npc.hp = npc.max_hp * 2;
|
||||
npc.age = me.query_age();
|
||||
npc.clear_prop();
|
||||
npc.init();
|
||||
npc.recount();
|
||||
npc.auto_skills = null;
|
||||
npc.environment && npc.environment.item_changed(npc, true);
|
||||
this.is_init_first = true;
|
||||
this.first_npc_exp = npc.exp;
|
||||
}
|
||||
FAMILY.prototype.send_channel = function (me, msg) {
|
||||
|
||||
var msg = '{type:"msg",ch:"fam",content:"' + msg + '",fam:"' + this.name + '", name:"' + (me ? me.name : "门派管理") + '" }';
|
||||
this.send(msg);
|
||||
}
|
||||
FAMILY.SAVE = function () {
|
||||
var obj = {};
|
||||
for (var key in FAMILIES) {
|
||||
var fam = FAMILIES[key];
|
||||
if (fam.tops) {
|
||||
obj[key + "_tops"] = fam.tops;
|
||||
}
|
||||
obj.temp = fam.temp;
|
||||
}
|
||||
return JSON.stringify(obj);
|
||||
}
|
||||
FAMILY.LOAD = function (str) {
|
||||
var obj = JSON.toObject(str);
|
||||
if (!obj) return;
|
||||
for (var key in FAMILIES) {
|
||||
var fam = FAMILIES[key];
|
||||
if (obj[key + "_tops"]) {
|
||||
fam.tops = obj[key + "_tops"];
|
||||
}
|
||||
fam.temp = obj.temp;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const TITLES = ['入门弟子', '弟子', '执事', '护法', '长老', '供奉'];
|
||||
|
||||
FAMILY.prototype.query_task_title = function (me) {
|
||||
let level = me.query_temp('sm_level', 0);
|
||||
return me.family.name + TITLES[level];
|
||||
}
|
||||
|
||||
FAMILY.prototype.query_job_title = function (level) {
|
||||
return TITLES[level];
|
||||
}
|
||||
|
||||
51
world/extends/skill/skill.js
Normal file
51
world/extends/skill/skill.js
Normal file
@@ -0,0 +1,51 @@
|
||||
PERFORM.prototype.query_releasetime = function (me, lv) {
|
||||
var rtime = this.release_time;
|
||||
if (!(rtime >= 0)) rtime = me.gjsd;
|
||||
|
||||
if (this.releasetime_key) {
|
||||
rtime = rtime - me.query_prop("releasetime") - me.query_prop(this.releasetime_key);
|
||||
} else {
|
||||
rtime = rtime - me.query_prop("releasetime");
|
||||
}
|
||||
|
||||
if (this.releasetime_per_key) {
|
||||
rtime = rtime - rtime * (me.query_prop("releasetime_per") + me.query_prop(this.releasetime_per_key)) / 100;
|
||||
} else {
|
||||
rtime = rtime - rtime * (me.query_prop("releasetime_per")) / 100;
|
||||
}
|
||||
if (rtime < 500) return 500;
|
||||
return parseInt(rtime);
|
||||
}
|
||||
|
||||
PERFORM.prototype.query_distime = function (me, lv, isref) {
|
||||
var dis = this.distime;
|
||||
if (!dis) dis = me.gjsd;
|
||||
if (isref) dis = dis * 2;
|
||||
if (this.distime_key) {
|
||||
dis = dis - me.query_prop("distime") - me.query_prop(this.distime_key);
|
||||
} else {
|
||||
dis = dis - me.query_prop("distime");
|
||||
}
|
||||
if (this.distime_per_key) {
|
||||
dis = dis - dis * (me.query_prop("distime_per") + me.query_prop(this.distime_per_key)) / 100;
|
||||
} else {
|
||||
dis = dis - dis * (me.query_prop("distime_per")) / 100;
|
||||
}
|
||||
|
||||
|
||||
if (dis < 3000) return 3000;
|
||||
return parseInt(dis);
|
||||
}
|
||||
PERFORM.prototype.query_mp = function (me, lv) {
|
||||
var mp = this.mp || 0;
|
||||
|
||||
mp = mp + lv * mp / 20;
|
||||
if (this.expend_mp_per_key) {
|
||||
mp = mp - mp * (me.query_prop("expend_mp_per")
|
||||
+ me.query_prop(this.expend_mp_per_key)) / 100;
|
||||
} else {
|
||||
mp = mp - mp * me.query_prop("expend_mp_per") / 100;
|
||||
}
|
||||
if (mp < 0) mp = 0;
|
||||
return parseInt(mp);
|
||||
}
|
||||
232
world/extends/stats.js
Normal file
232
world/extends/stats.js
Normal file
@@ -0,0 +1,232 @@
|
||||
|
||||
|
||||
const STATS = WORLD.STATS;
|
||||
STATS.load_tops = function (tops, defname = '武林高手', key = "") {
|
||||
tops = tops ?? new Array(10).fill({ path: "pub/gaoshou1" });
|
||||
const ary = [];
|
||||
for (let i = 0; i < tops.length; i++) {
|
||||
let item = tops[i];
|
||||
let npc;
|
||||
npc = NPC.CLONE("pub/gaoshou1");
|
||||
npc.name = defname;
|
||||
if (item.userid) {
|
||||
this.loadTopUser(item, npc);
|
||||
} else {
|
||||
npc.score = 10 - i;
|
||||
}
|
||||
npc.top_index = i + 1;
|
||||
npc.id = "top_" + key + "_" + i;
|
||||
ary.push(npc);
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
|
||||
STATS.loadTopUser = function (data, npc) {
|
||||
npc.title = data.title;
|
||||
npc.name = data.name;
|
||||
for (let i = 0; i < COPY_PROPS.length; i++) {
|
||||
npc[COPY_PROPS[i]] = data[COPY_PROPS[i]];
|
||||
}
|
||||
npc.skills = data.skills;
|
||||
if (data.eq) {
|
||||
npc.equipment = [];
|
||||
for (let i = 0; i < data.eq.length; i++) {
|
||||
let item = data.eq[i];
|
||||
if (!item) continue;
|
||||
let obj = OBJ.CREATE(item[0]);
|
||||
if (!obj) continue;
|
||||
obj.load_db(item);
|
||||
npc.equipment[i] = obj;
|
||||
}
|
||||
}
|
||||
npc.userid = data.userid;
|
||||
npc.temp = data.temp;
|
||||
npc.clear_prop();
|
||||
npc.init();
|
||||
npc.recount();
|
||||
}
|
||||
STATS.checkStats = function (player) {
|
||||
this.updateScore(player);
|
||||
WORLD.COMMANDS.biwu.checkStats(player);
|
||||
}
|
||||
|
||||
const COPY_PROPS = ["str", "con", "dex", "int", "gender", "max_mp", "exp", "pot", "kar", "per"
|
||||
, "hp", "max_hp", "mp", 'age', 'score'];
|
||||
|
||||
STATS.saveTops = function (tops) {
|
||||
|
||||
let str = ["["];
|
||||
for (let i = 0; i < tops.length; i++) {
|
||||
let top = tops[i];
|
||||
if (top.userid) {
|
||||
str.push("{userid:\"");
|
||||
str.push(top.userid);
|
||||
str.push("\",name:\"");
|
||||
str.push(top.name);
|
||||
str.push("\",title:\"");
|
||||
str.push(top.title);
|
||||
str.push("\"");
|
||||
for (let j = 0; j < COPY_PROPS.length; j++) {
|
||||
str.push(",");
|
||||
str.push(COPY_PROPS[j]);
|
||||
str.push(":");
|
||||
str.push(top[COPY_PROPS[j]]);
|
||||
}
|
||||
if (top.skills) {
|
||||
str.push(",skills:");
|
||||
str.push(JSON.stringify(top.skills));
|
||||
}
|
||||
if (top.equipment) {
|
||||
str.push(",eq:[");
|
||||
for (let j = 0; j < top.equipment.length; j++) {
|
||||
if (j > 0) str.push(",");
|
||||
if (top.equipment[j]) top.equipment[j].save_db(str);
|
||||
else str.push("null");
|
||||
}
|
||||
str.push("]");
|
||||
}
|
||||
if (top.temp) {
|
||||
str.push(",temp:", JSON.stringify(top.temp));
|
||||
}
|
||||
|
||||
str.push("}");
|
||||
|
||||
} else {
|
||||
str.push('{ path: "pub/gaoshou1"}');
|
||||
}
|
||||
if (i !== this.TOPS.length - 1) str.push(",");
|
||||
}
|
||||
str.push("]");
|
||||
return str.join("");
|
||||
}
|
||||
|
||||
|
||||
STATS.saveWeapon = function () {
|
||||
|
||||
return JSON.stringify(this.WEAPON);
|
||||
}
|
||||
STATS.saveScore = function () {
|
||||
return JSON.stringify(this.SCORE);
|
||||
}
|
||||
STATS.updateEqitem = function (me, wea, ary) {
|
||||
let score = wea.query_score();
|
||||
if (!score) return;
|
||||
let cur_index = -1;
|
||||
let new_index = -1;
|
||||
for (let i = ary.length - 1; i >= 0; i--) {
|
||||
let item = ary[i];
|
||||
if (item.user === me.id) {
|
||||
if (wea.id === item.id || score > item.score) {
|
||||
cur_index = i;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (score > item.score) {
|
||||
new_index = i;
|
||||
}
|
||||
|
||||
}
|
||||
if (cur_index === -1 && new_index === -1) return;
|
||||
|
||||
if (cur_index === -1) {//新上榜的
|
||||
let item = {
|
||||
id: wea.id,
|
||||
user: me.id,
|
||||
score: score,
|
||||
name: me.name,
|
||||
desc: wea.get_desc(me),
|
||||
wname: wea.color_name
|
||||
};
|
||||
ary.splice(new_index, 0, item);
|
||||
if (ary.length > 15)
|
||||
ary.length = 15;
|
||||
return item;
|
||||
}
|
||||
|
||||
let item = ary[cur_index];
|
||||
item.wname = wea.color_name;
|
||||
item.desc = wea.get_desc(me);
|
||||
item.id = wea.id;
|
||||
item.user = me.id;
|
||||
item.name = me.name;
|
||||
item.score = score;
|
||||
if (cur_index === new_index
|
||||
|| new_index - cur_index === 1) {
|
||||
return item;
|
||||
}
|
||||
if (new_index === -1) {//掉出去,放最后
|
||||
ary.splice(cur_index, 1);
|
||||
ary.push(item);
|
||||
} else if (cur_index > new_index) { //提升了
|
||||
|
||||
ary.splice(cur_index, 1);
|
||||
ary.splice(new_index, 0, item);
|
||||
} else {
|
||||
ary.splice(new_index, 0, item);
|
||||
ary.splice(cur_index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
STATS.updateWeapon = function (me, wea) {
|
||||
//if (wea.eq_type !== EQUIP_TYPE.WEAPON) return;
|
||||
if (!WORLD.is_server(me)) return;
|
||||
let eqs = this.EQ_STATS[wea.eq_type];
|
||||
this.updateEqitem(me, wea, eqs);
|
||||
|
||||
}
|
||||
STATS.updateScoreItem = function (me, ary) {
|
||||
let score = me.score;
|
||||
let cur_index = -1;
|
||||
let new_index = -1;
|
||||
for (let i = ary.length - 1; i >= 0; i--) {
|
||||
let item = ary[i];
|
||||
if (item.id === me.id) {
|
||||
cur_index = i;
|
||||
}
|
||||
if (score > item.score) {
|
||||
new_index = i;
|
||||
}
|
||||
|
||||
}
|
||||
if (cur_index === -1 && new_index === -1) return;
|
||||
|
||||
if (cur_index === -1) {//新上榜的
|
||||
let item = { id: me.id, score: score, name: me.color_name || me.name };
|
||||
ary.splice(new_index, 0, item);
|
||||
if (ary.length > 30)
|
||||
ary.length = 30;
|
||||
return;
|
||||
}
|
||||
|
||||
let item = ary[cur_index];
|
||||
item.score = score;
|
||||
|
||||
item.name = me.color_name || me.name;
|
||||
if (cur_index === new_index
|
||||
|| new_index - cur_index === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (new_index === -1) {//掉出去,放最后
|
||||
ary.splice(cur_index, 1);
|
||||
ary.push(item);
|
||||
} else if (cur_index > new_index) { //提升了
|
||||
|
||||
ary.splice(cur_index, 1);
|
||||
ary.splice(new_index, 0, item);
|
||||
} else {
|
||||
ary.splice(new_index, 0, item);
|
||||
ary.splice(cur_index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
STATS.updateScore = function (me) {
|
||||
if (!WORLD.is_server(me)) return;
|
||||
let ary = this.SCORE;
|
||||
this.updateScoreItem(me, ary);
|
||||
let fam = this.SC_STATS[me.family.id];
|
||||
if (!fam) return;
|
||||
this.updateScoreItem(me, fam);
|
||||
|
||||
}
|
||||
0
world/extends/update.js
Normal file
0
world/extends/update.js
Normal file
63
world/extends/world.js
Normal file
63
world/extends/world.js
Normal file
@@ -0,0 +1,63 @@
|
||||
|
||||
WORLD.on_startup = function () {
|
||||
init_fams();
|
||||
WORLD.COMMANDS.jh.init();
|
||||
}
|
||||
|
||||
function init_fams() {
|
||||
for (let fam in FAMILIES) {
|
||||
FAMILIES[fam].init();
|
||||
}
|
||||
}
|
||||
|
||||
WORLD.on_user_quit = function (user) {
|
||||
//在玩家退出游戏时调用
|
||||
if (WORLD.is_server(user)) {
|
||||
if (user.query_temp('pt')) {
|
||||
WORLD.COMMANDS['party'].on_user_login(user, false);//帮派初始化
|
||||
}
|
||||
WORLD.on_user_save(user);
|
||||
} else {
|
||||
if (user.query_temp('cross_type') == 'duizhan') {
|
||||
WORLD.PUB_USERS.push(user);
|
||||
user.disconnect_time = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
WORLD.on_user_save = function (user) {
|
||||
//在玩家退出游戏,或者游戏关闭时候调用
|
||||
|
||||
}
|
||||
|
||||
|
||||
WORLD.on_heart_beat = function (now) {
|
||||
|
||||
}
|
||||
|
||||
const illegalUARegex = /node|python|java|curl|wget|postman|robot|spider|bot/i;
|
||||
const Origins = [];
|
||||
WORLD.check_connect = function (socket) {
|
||||
if (WORLD.SERVER.istest) return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
WORLD.close = async function () {
|
||||
WORLD.status = 5;
|
||||
console.log('正在尝试关闭数据连接');
|
||||
for (let user of this.USERS) {
|
||||
if (user.socket)
|
||||
user.socket.end();
|
||||
}
|
||||
//await this.LISTENER.close();
|
||||
console.log('关闭网络连接');
|
||||
clearInterval(this.heart_beat_service);
|
||||
// console.time('savedb');
|
||||
if (await WORLD.save()) {
|
||||
// console.timeEnd('savedb');
|
||||
//await this.DB.close();
|
||||
console.log('关闭数据连接');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user