xy-server/game/activity/FactionWar.ts
2025-04-23 09:34:08 +08:00

1531 lines
59 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import PlayerMgr from "../object/PlayerMgr";
import ActivityDefine from "./ActivityDefine";
import TeamMgr from "../core/TeamMgr";
import SKDataUtil from "../gear/SKDataUtil";
import SKLogger from "../gear/SKLogger";
import {BattleType, MsgCode, Fortifications, FortificationsOperate, ETaskKind} from "../role/EEnum";
import * as schedule from "node-schedule";
import GTimer from "../common/GTimer";
import BangMgr from "../bang/BangMgr";
import DB from "../utils/DB";
import GameUtil from "../core/GameUtil";
import NpcConfigMgr from "../core/NpcConfigMgr";
import NpcMgr from "../core/NpcMgr";
/**
* 帮战
*/
export default class FactionWar {
static shared = new FactionWar();
// 比武状态
contest_state: any = {
not_sign: 0, // 未报名
yet_sign: 1, // 已报名
}
//----------------------------------------------------- 左边 ----------------------------------------------------
/** 左边基地 */
gate_xy_left: any = {x: 21, y: 10}
/** 左边基地出城门传送位置 */
out_gate_xy_left: any = {x: 44, y: 47}
/** 左边神龙大炮蓄力0-10ms攻击范围 MinLon最小经度MaxLon最大经度MinLat最小纬度MaxLat最大纬度 */
cannon_left_0_10: any = {MinLon: 26, MaxLon: 72, MinLat: 55, MaxLat: 93}
/** 左边神龙大炮蓄力10-19ms攻击范围 */
cannon_left_10_19: any = {MinLon: 22, MaxLon: 78, MinLat: 33, MaxLat: 71}
/** 左边神龙大炮攻击城门范围 */
cannon_left_gate: any = {MinLon: 26, MaxLon: 45, MinLat: 16, MaxLat: 37}
/** 玄冰塔、烈火塔 左边边攻击范围 */
tower_left: any = {MinLon: 25, MaxLon: 151, MinLat: 29, MaxLat: 76}
//----------------------------------------------------- 右边 ----------------------------------------------------
/** 右边基地 */
gate_xy_right: any = {x: 188, y: 102}
/** 右边基地出城门传送位置 */
out_gate_xy_right: any = {x: 154, y: 76}
/** 右边神龙大炮蓄力0-10ms攻击范围 MinLon最小经度MaxLon最大经度MinLat最小纬度MaxLat最大纬度 */
cannon_right_0_10: any = {MinLon: 46, MaxLon: 100, MinLat: 79, MaxLat: 110}
/** 右边神龙大炮蓄力10-19ms攻击范围 */
cannon_right_10_19: any = {MinLon: 91, MaxLon: 179, MinLat: 62, MaxLat: 91}
/** 右边神龙大炮攻击城门范围 */
cannon_right_gate: any = {MinLon: 150, MaxLon: 168, MinLat: 79, MaxLat: 97}
/** 玄冰塔、烈火塔 右边攻击范围 */
tower_right: any = {MinLon: 73, MaxLon: 187, MinLat: 36, MaxLat: 100}
// 定时时间(毫秒单位)
state_time: any = {
start_time: 20 * 60 * 1000, // 通知完20分钟后开始帮战
}
// 战斗状态
FightState: any = {
Wait: 1, // 等待
FightEnd: 2 // 结束战斗
}
// 神龙大炮攻击半径
cannon_radius: number;
// 烈火塔及玄冰塔攻击半径
tower_radius: number;
// 入围帮派
cut_faction: any;
name: any;
// 帮战状态
activity_state: any;
// 帮战开始时间
start_time: any;
// 比武时间
contest_time: any[];
// 比武定时器
schedule: any;
// 神龙大炮定时器
cannon_schedule: any;
// 玄冰塔定时器-左
ice_l_schedule: any;
// 烈火塔定时器-左
fire_l_schedule: any;
// 玄冰塔定时器-右
ice_r_schedule: any;
// 烈火塔定时器-右
fire_r_schedule: any;
// 比武参赛队伍
contest_team: any;
// 帮战参赛成员
contest_map: Map<String, any>;
// 烈火塔、玄冰塔,神龙大炮信息
urban_defense_map: Map<number, any>;
// 玄冰塔,击中目标记录<角色编号,控制时间>
ice_map: Map<number, number>;
// 玄冰塔ms击中目标记录检查定时
ms_ice_target_schedule: any;
// 烈火塔,击中目标记录<角色编号,控制时间>
fire_map: Map<number, number>;
// 烈火塔ms击中目标记录检查定时
ms_fire_target_schedule: any;
// 帮战所有参赛成员 - 角色编号 - {战斗状态 2战斗中 1未战斗,帮派编号,击杀人数 field场数,field_win: 本人胜利场,contest: 高手胜利场, member_win成员胜利场}
contest_map_info: Map<number, any>;
constructor() {
this.name = '帮战';
// 比武定时器
this.schedule = 0;
// 神龙大炮定时器
this.cannon_schedule = 0;
// 神龙大炮攻击半径
this.cannon_radius = 13.5;
// 烈火塔及玄冰塔攻击半径
this.tower_radius = 12.5;
// 入围帮派
this.cut_faction = {};
// 比武参赛队伍
this.contest_team = {};
// 帮战参赛成员
this.contest_map = new Map<String, any[]>();
// 比武时间
this.contest_time = [10, 20, 30];
// 玄冰塔,击中目标记录<角色编号,控制时间>
this.ice_map = new Map<number, number>();
// 烈火塔,击中目标记录<角色编号,控制时间>
this.fire_map = new Map<number, number>();
// 烈火塔、玄冰塔信息
this.urban_defense_map = new Map<number, any>();
// 帮战所有参赛成员 - 角色编号 - {战斗状态 2战斗中 1未战斗,帮派编号,击杀人数 field场数,field_win: 本人胜利场,contest: 高手胜利场, member_win成员胜利场}
this.contest_map_info = new Map<number, any>();
// 帮战开启时间
this.start_time = 0;
}
init() {
this.activity_state = ActivityDefine.activityState.Close;
this.defenceInfo();
//周一MON、周二TUE、周三WED、周四THU、周五FRI、周六SAT、周天SUN
// 周三、周四晚18:30抽取入围帮派
schedule.scheduleJob("0 30 18 ? * WED,THU", () => {
this.cutFaction();
})
//周三、周四晚19:40开始进入帮战
schedule.scheduleJob("0 40 19 ? * WED,THU", () => {
// 修改状态为准备报名
this.satReadyOpen();
})
//周三、周四晚20:40开结束帮战
schedule.scheduleJob("0 40 20 ? * WED,THU", () => {
//结束帮战
this.close();
})
// 重启服务器读取当前入围帮战资格数据
DB.getCutFaction((code: any, info: any) => {
if (MsgCode.SUCCESS == code) {
for (let i = 0; i < info.length; i++) {
this.cut_faction[info[i].side_id] = {
gate_hp: 5000, // 城门血量
gate_max_hp: 5000, // 城门最大血量
site: info[i].site, // 占据地图位置
enemy_id: info[i].enemy_id, // 敌方帮派编号
cannon: 0, // 神龙炮开炮数
tower: 0 // 能量塔攻击数
};
this.contest_map.set(info[i].side_id.toString(), []);
}
this.tower_info_update();
}
});
this.clear_npc();
}
clear_npc(npc_id: any = 0, type: any = 0) {
if (npc_id == 0) {
for (let [key, value] of this.urban_defense_map) {
if (key != Fortifications.cannon) {
let npc: any = NpcMgr.shared.getNpcByConfigID(value.shadow);
if (npc) {
NpcMgr.shared.DeleteNpc(npc.onlyid);
}
if (type != 0){
let npc: any = NpcMgr.shared.getNpcByConfigID(key);
if (npc) {
NpcMgr.shared.DeleteNpc(npc.onlyid);
}
}
}
}
} else {
let npc: any = NpcMgr.shared.getNpcByConfigID(npc_id);
if (npc) {
NpcMgr.shared.DeleteNpc(npc.onlyid);
}
}
}
create_npc(npc_id: any){
let npc: any = NpcConfigMgr.shared.getConfig(npc_id);
if (npc){
NpcMgr.shared.CreateNpc(npc_id, npc.auto_create.map, npc.auto_create.x, npc.auto_create.y);
}
}
// 城防信息初始化
defenceInfo(){
/** 左边 type: 2烈火塔 3玄冰塔 state 0 蓄力1 打断, 2 自动攻击, 3 破损 */
this.urban_defense_map.set(7207, {shadow: 47207, durable: 450, durableMax: 450, type: Fortifications.fire, site: "L", state: FortificationsOperate.INTERRUPT, bangId: 0, roleId: 0});
this.urban_defense_map.set(7208, {shadow: 47208, durable: 450, durableMax: 450, type: Fortifications.ice, site: "L", state: FortificationsOperate.INTERRUPT, bangId: 0, roleId: 0});
/** 右边 type: 2烈火塔 3玄冰塔 0 蓄力1 打断, 2 自动攻击, 3 破损 */
this.urban_defense_map.set(7206, {shadow: 47206, time: 0, durable: 450, durableMax: 450, type: Fortifications.ice, site: "R", state: FortificationsOperate.INTERRUPT, bangId: 0, roleId: 0});
this.urban_defense_map.set(7205, {shadow: 47205, durable: 450, durableMax: 450, type: Fortifications.fire, site: "R", state: FortificationsOperate.INTERRUPT, bangId: 0, roleId: 0});
/** 神龙大炮 time 当前蓄力时间ms state 0 蓄力 1 打断 2 roleId 当前蓄力者角色编号, bangId 帮派ID */
this.urban_defense_map.set(Fortifications.cannon, {time: 0, state: FortificationsOperate.INTERRUPT, roleId: 0, bangId: 0});
}
// 筛选入围帮派
cutFaction() {
let flag = true;
let bangList: any = BangMgr.shared.getBangList();
let peak_team_all: any = [];
let peak_team: any = [];
// 帮派集合必须大于2
if (bangList.length > 2) {
let num = 1;
// let num = Math.floor(bangList.length / 2);
// // 最少为两组
// if ((num % 2) != 0){
// num -= 1;
// }
// // 最大为3组
// if (num > 3){
// num = 3;
// }
// 筛选入围的帮派
for (let i = 0; i < num; i++) {
let count = 0;
while (flag) {
if (peak_team.length < 2) {
if (count >= 5) {
flag = false;
continue;
}
count++;
let ran = Math.floor(Math.random() * bangList.length);
peak_team.push(bangList[ran]);
peak_team_all.push(bangList[ran]);
} else {
flag = false;
}
}
if (peak_team.length >= 2) {
// 存储当前入围帮派信息
this.cut_faction[peak_team[0].bangid] = {
enemy_id: peak_team[1].bangid,// 敌方帮派编号
site: "L", // 占据地图位置
gate_hp: 5000, // 城门血量
gate_max_hp: 5000, // 城门最大血量
cannon: 0, // 神龙炮开炮数
tower: 0 // 能量塔攻击数
};
this.contest_map.set(peak_team[0].bangid.toString(), []);
// 存储当前入围帮派信息
this.cut_faction[peak_team[1].bangid] = {
enemy_id: peak_team[0].bangid,// 敌方帮派编号
site: "R", // 占据地图位置
gate_hp: 5000, // 城门血量
gate_max_hp: 5000, // 城门最大血量
cannon: 0, // 神龙炮开炮数
tower: 0 // 能量塔攻击数
};
this.contest_map.set(peak_team[1].bangid.toString(), []);
this.tower_info_update();
DB.insertCutFaction(peak_team[0].bangid,"L", peak_team[1].bangid, "R");
}
peak_team = [];
flag = true;
}
}
}
/**
* 开启活动进行通知
*/
satReadyOpen() {
let times = 3;
let broad = () => {
times--;
let msg = `${this.name} 开启报名,请大家踊跃参加!`;
PlayerMgr.shared.broadcast('s2c_notice', {
strRichText: msg
});
PlayerMgr.shared.broadcast('s2c_game_chat', {scale: 3, msg: msg, name: '', resid: 0, teamid: 0,});
if (times >= 0) {
setTimeout(() => {
broad();
}, 10 * 1000);
}
}
broad();
// 修改状态为报名
this.activity_state = ActivityDefine.activityState.ReadyOpen;
// 活动开始 启动定时检测塔击中玩家
setTimeout(() => {
this.start_time = GTimer.getTime();
this.activity_state = ActivityDefine.activityState.Opening;
this.ms_ice_target_schedule = setInterval(this.timing_inspect_ice, 1000, this);
this.ms_fire_target_schedule = setInterval(this.timing_inspect_fire, 1000, this);
// 通知前端帮战开始
this.gateHpUpdate(Object.keys(this.cut_faction)[0],0)
}, this.state_time.start_time);
}
// 定时检测被玄冰塔击中玩家
timing_inspect_ice(this_: any){
for (let [key, value] of this_.ice_map) {
value -= 1;
if (value <= 0){
this_.ice_map.delete(key);
let player = PlayerMgr.shared.getPlayerByRoleId(key);
if (player){
// 通知前端解冻
player.isFrozen = 0;
player.send('s2c_aoi_pinfo', {
list: [player.toObj()]
});
player.send("s2c_wars_player_state",{type: 2, ice: 0, time: GTimer.getTime()});
}
}else {
this_.ice_map.set(key,value);
}
}
}
// 定时检测被烈火塔击中玩家
timing_inspect_fire(this_: any){
for (let [key, value] of this_.fire_map) {
value -= 1;
if (value <= 0){
this_.fire_map.delete(key);
}else {
this_.fire_map.set(key,value);
}
}
}
/**
* 请求进入帮战:玩家报名
*/
playerSign(player: any) {
if (player.bangid < 0) {
player.send_notice("你没有帮派");
return MsgCode.FAILED;
}
let data: any = this.cut_faction[player.bangid];
if (data == undefined || data == null) {
player.send_notice("你们帮目前没有帮战");
return MsgCode.FAILED;
}
if (this.activity_state != ActivityDefine.activityState.ReadyOpen){
player.send_notice("当前不在帮战报名时间");
return MsgCode.FAILED;
}
// 获取当前参赛成员
let map_data: any[] = this.contest_map.get(player.bangid.toString());
let team = TeamMgr.shared.getTeamInfo(player.teamid);
let list: any[] = [];
if (team != null) {
for (let i = 0; i < team.playerlist.length; i++) {
const mem = team.playerlist[i];
if (mem.bangid != player.bangid) {
player.send_notice(`队伍中玩家${mem.name}不是本帮成员!`);
return MsgCode.FAILED;
} else {
list.push(mem.roleid);
}
}
for (let value of list) {
map_data.push(value);
this.contest_map_info.set(value,{state: this.FightState.Wait, bangId: player.bangid, count: 0, field: 0, field_win: 0, contest: 0, member_win: 0});
}
} else {
list.push(player.roleid);
map_data.push(player.roleid);
this.contest_map_info.set(player.roleid,{state: this.FightState.Wait, bangId: player.bangid, count: 0, field: 0, field_win: 0, contest: 0, member_win: 0});
}
for (let value of list) {
let p = PlayerMgr.shared.getPlayerByRoleId(value);
if (p){
let d = p.toObj();
d.bangpost = p.bangpost
p.send('s2c_aoi_pinfo', {
list: [d]
});
}
}
// 统计当前参战成员
this.contest_map.set(player.bangid.toString(), map_data);
this.cut_faction[player.bangid] = data;
this.portal(player,0);
return MsgCode.SUCCESS;
}
/**
* 请求离开帮战
* @param player
* @param teamId
*/
leave(player: any) {
// 离开帮战从数组删除当前成员信息
let map_data = this.contest_map.get(player.bangid.toString());
if (map_data != undefined){
let team = TeamMgr.shared.getTeamInfo(player.teamid);
if (team != null) {
for (let i = 0; i < team.playerlist.length; i++) {
const mem = team.playerlist[i];
let index = map_data.indexOf(mem.roleid);
if (index > -1) {
map_data.splice(index, 1);
}
this.contest_map_info.delete(mem.roleid);
}
}else {
let index = map_data.indexOf(player.roleid);
if (index > -1) {
map_data.splice(index, 1);
}
this.contest_map_info.delete(player.roleid);
}
this.contest_map.set(player.bangid.toString(), map_data);
}
}
/**
* 返回基地
* @param player
*/
goHome(player: any, type: number) {
let data = this.check(player, 0);
if (type == 1) {
let contest_team: any = this.contest_team[player.bangid];
if (contest_team != undefined){
if (this.contest_state.yet_sign == contest_team.state){
// 关闭定时器
clearTimeout(this.schedule);
}
// 清理比武成员
delete this.contest_team[player.bangid]
}
}
if (data != null) {
this.portal(player,0)
}
}
/**
* 帮战信息统计
* @param player
* @param is 0 帮战信息返回 1 帮战结束返回
*/
detail_statistics(player: any, is: number = 0) {
if (this.activity_state == ActivityDefine.activityState.Close) {
return;
}
// 1.获取当前帮派信息
let data: any = this.cut_faction[player.bangid];
let enemy: any = this.cut_faction[data.enemy_id];
// 获取帮派信息
let bang: any = BangMgr.shared.getBang(player.bangid);
// 参战人数
let list = this.contest_map.get(player.bangid.toString());
// 敌方帮派信息
let bang_: any = BangMgr.shared.getBang(data.enemy_id);
let bang_list: any = this.contest_map.get(data.enemy_id.toString());
// 返回状态 处理
let type = 0;
let impl: string = "s2c_detail_statistics";
if (is == 1){
impl = "s2c_faction_war_over";
if (data.gate_hp > enemy.gate_hp){
type = 1;
player.addMoney(GameUtil.goldKind.bang_Score,100000,"帮战胜利奖励");
player.addBagItem(70004,15,true);
player.addBagItem(100320,50,true);
}else{
player.addMoney(GameUtil.goldKind.bang_Score,50000,"帮战失败奖励");
player.getTaskMgr().AddActive(ETaskKind.DAILY,60);
player.addBagItem(100320,50,true);
}
}else {
if (this.activity_state == ActivityDefine.activityState.Opening){
type = 1;
}
}
// 报名中
if (this.activity_state == ActivityDefine.activityState.ReadyOpen) {
player.send("s2c_detail_statistics", {
factionSide: SKDataUtil.toJson({name: bang.name, num: list.length}, "{}"),
factionEnemy: SKDataUtil.toJson({name: bang_.name, num: bang_list.length}, "{}"),
type: type,
time: this.start_time
});
}
// 正在进行中
else {
// 己方成员胜利场数
let member = 0;
// 己方高手胜利场
let contest = 0;
// 己方自己杀敌
let self = 0;
// 最高杀人数
let highest = "(0场)";
// 敌方成员胜利场数
let member_ = 0;
// 敌方高手胜利场
let contest_ = 0;
// 敌方最高杀人数
let highest_ = "(0场)";
let list: any = [];
let list_enemy: any = [];
for (let [key, value] of this.contest_map_info) {
if (value.bangId == player.bangid) {
member += value.member_win;
contest += value.contest;
if (key == player.roleid) {
self = value.count;
}
list.push({key: key, count: value.count, field: value.field});
} else {
member_ += value.member_win;
contest_ += value.contest;
list_enemy.push({key: key, count: value.count, field: value.field});
}
};
// 己方最高杀人数读取
list = list.sort((a: any, b: any) => {
return b.count - a.count;
});
if (list.length > 0) {
let s = list[0];
if (s.field > 0) {
let p = PlayerMgr.shared.getPlayerByRoleId(s.key);
highest = p.name + "(" + s.field + "场)";
}
}
// 敌方最高杀人数读取
list_enemy = list_enemy.sort((a: any, b: any) => {
return b.count - a.count;
});
if (list_enemy.length > 0) {
let s = list_enemy[0];
if (s.field > 0) {
let p = PlayerMgr.shared.getPlayerByRoleId(s.key);
highest_ = p.name + "(" + s.field + "场)";
}
}
player.send(impl, {
factionSide: SKDataUtil.toJson({
name: bang.name,
num: list.length,
gateHp: data.gate_hp,
gateMaxHp: data.gate_max_hp,
member: member,
contest: contest,
tower: data.tower,
cannon: data.cannon,
highest: highest,
self: self
}, "{}"),
factionEnemy: SKDataUtil.toJson({
name: bang_.name,
num: list.length,
gateHp: enemy.gate_hp,
gateMaxHp: enemy.gate_max_hp,
member: member_,
contest: contest_,
tower: enemy.tower,
cannon: enemy.cannon,
highest: highest_,
self: 0
}, "{}"),
type: type,
time: this.start_time
});
}
}
/**
* 上阵迎敌
*/
toMeetThem(player: any) {
let data = this.check(player,1);
if (data != null) {
this.portal(player,1)
}
}
/**
* 帮战点击敌方战斗
* @param player 发起者
* @param enemyRole 被受者
*/
factionCombat(player: any, enemyRole: any) {
let data = this.check(player, 1);
if (data != null) {
// 发起者
let team = TeamMgr.shared.getTeamInfo(player.teamid);
if (team != null) {
if (team.playerlist.length < 3) {
player.send_notice("您当前队伍人数小于3人不可进行该操作");
return;
}
for (let i = 0; i < team.playerlist.length; i++) {
const mem = team.playerlist[i];
let contest = this.contest_map_info.get(mem.roleid)
contest.state = this.FightState.FightEnd;
this.contest_map_info.set(mem.roleid, contest);
}
} else {
player.send_notice("您当前未组队不可进行该操作");
return;
}
// 被受者
let enemy_team = TeamMgr.shared.getTeamInfo(enemyRole.teamid);
if (enemy_team != null) {
for (let i = 0; i < enemy_team.playerlist.length; i++) {
const mem = enemy_team.playerlist[i];
let contest = this.contest_map_info.get(mem.roleid)
contest.state = this.FightState.FightEnd;
this.contest_map_info.set(mem.roleid, contest);
}
} else {
this.goHome(enemyRole, 0);
player.send_notice("敌方未组队不可进行该操作");
return;
}
this.fortifications_examine(enemyRole);
// 开启战斗挑战
this.beforeFight(player, enemyRole, BattleType.FactionWarFight);
}
}
/**
* 前往比武场
*/
goContest(player: any) {
// 校验是否在前往比武场时间段
if (this.contest_time.indexOf(GTimer.getMinutes()) != -1) {
// 校验信息
let data = this.check(player);
if (data != null) {
// 1.如果信息未知 查询是否有该帮派 该帮派帮主是否是当前操作者
if (player.bangpost == GameUtil.bangPost.Unknow) {
let bang = BangMgr.shared.getBang(player.bangid);
if (bang != null && bang != undefined) {
if (bang.masterid == player.roleid) {
player.bangpost = GameUtil.bangPost.BangZhu;
}
}
}
// 2.比武场必须由管理者带领前往
if (player.bangpost == GameUtil.bangPost.BangZhong || player.bangpost == GameUtil.bangPost.Unknow) {
player.send_notice("比武场必须由管理者带领前往")
return;
}
// 3.帮战比武必须3人及以上
let team = TeamMgr.shared.getTeamInfo(player.teamid);
if (team == null || team.playerlist.length < 3) {
player.send_notice("帮战比武必须3人及以上才可以参加哦");
return;
}
// 3.1 队伍中必须都是当前帮成员
for (let i = 0; i < team.playerlist.length; i++) {
const mem = team.playerlist[i];
if (mem.bangid != player.bangid) {
player.send_notice(`队伍中玩家${mem.name}不是本帮成员!`);
return;
}
}
// 4.保证比武场只有当前帮一支队伍
if (this.contest_team[player.bangid] == undefined || this.contest_team[player.bangid] == null) {
// 4.1 如果比武场没有当前帮派则存储数据 {当前队伍编号,比武报名状态}
this.contest_team[player.bangid] = {
teamId: player.teamid,
state: this.contest_state.not_sign,
roleId: player.roleid
};
// 4.2 将当前队伍传送至比武场
player.map_transfer(3001, 167, 24)
return;
} else {
player.send_notice(`本帮已有成员在比武场啦!`);
return;
}
}
} else {
player.send_notice("不在比武时间内");
}
}
/**
* 帮战-比武
* @param player
*/
contest(player: any) {
// 1.检验帮派
let data = this.check(player);
if (data != null) {
// 2.检查比武数据是否存在当前队伍
if (this.contest_team[player.bangid] != undefined && this.contest_team[player.bangid] != null) {
// 2.1 如果当前有已经报名的队伍则开打
for (let key in this.contest_team) {
let data: any = this.contest_team[key];
if (data.state == this.contest_state.yet_sign) {
let team: any = TeamMgr.shared.getTeamInfo(data.teamId);
if (team == null || team == undefined) {
// 返回基地
this.goHome(player, 1);
}
if (team.leader.roleid == player.roleid) {
player.send_notice("你已经报名比武了,请耐心等待挑战者!")
return;
}
// 开启比武挑战
this.beforeFight(player, PlayerMgr.shared.getPlayerByRoleId(team.leader.roleid), BattleType.FactionWarContest);
// 关闭定时器
clearTimeout(this.schedule);
// 比武状态改变
let side: any = this.contest_team[player.bangid];
side.state = this.contest_state.yet_sign;
this.contest_team[player.bangid] = side;
break;
} else {
// 比武状态改变
data.state = this.contest_state.yet_sign;
this.contest_team[player.bangid] = data;
// 生成一个定时器 2分钟后没有敌方队伍前来比赛则判断当前队伍胜利
this.schedule = setTimeout(() => {
for (let key in this.contest_team) {
let data: any = this.contest_team[key];
if (data.state == this.contest_state.yet_sign) {
let team: any = TeamMgr.shared.getTeamInfo(data.teamId);
if (team != null && team != undefined) {
this.contestResult(PlayerMgr.shared.getPlayerByRoleId(team.leader.roleid), 1);
} else {
// 返回基地
this.goHome(PlayerMgr.shared.getPlayerByRoleId(data.roleId), 1);
}
break;
}
}
}, 2 * 60 * 1000);
player.send_notice("报名成功")
}
}
} else {
// 返回基地
this.goHome(player, 0);
player.send_notice("参赛数据中未找到您队伍数据");
}
}
}
/**
* 比武结束处理
* @param player 当前玩家
* @param isWin 1 胜利 0 失败
*/
contestResult(player: any, isWin: number) {
// 1.获取当前帮派信息
let win_data: any = this.cut_faction[player.bangid]
// 1.2 如果胜利
if (isWin == 1) {
// 高手胜利场次记录该数据
if(player.teamid > 0){
if (player.isleader){
let data = this.contest_map_info.get(player.roleid);
data.contest += 1;
this.contest_map_info.set(player.roleid,data);
}
}
// 1.2.1.敌方帮派帮派大门血量改变
this.gateHpUpdate(win_data.enemy_id,-600);
}
this.portal(player,0)
}
/**
* 战斗结束处理
* @param player 当前玩家
* @param isWin 1 胜利 0 失败
*/
fightResult(player: any, isWin: number, battle: any) {
// 1.获取当前帮派信息
let win_data: any = this.cut_faction[player.bangid]
// 1.2 取出战斗数据存
let contest = this.contest_map_info.get(player.roleid);
// 1.3 如果胜利
if (isWin == 1) {
// 1.3.1.敌方帮派帮派大门血量改变
this.gateHpUpdate(win_data.enemy_id,-10);
if (contest != undefined){
for (let role of battle.campB.broles) {
// 如果是玩家 并且死亡
if (role.living_type == 1) {
// 1.3.1 杀敌数加1
contest.count += 1;
}
}
}
// 1.3.1.胜利场
contest.field_win += 1;
// 如果是队长 成员胜利场加1
if(player.teamid > 0){
if (player.isleader){
contest.member_win += 1;
}
}
}
// 1.4 场次加1
contest.field += 1;
// 更新战斗状态
contest.state = this.FightState.Wait;
// 战斗数据存
this.contest_map_info.set(player.roleid,contest)
this.portal(player,0)
}
/**
* 校验
* @param player
*/
check(player: any, type: number = 0): any {
if (player.bangid < 0) {
player.send_notice("你没有帮派");
player.map_transfer(1011);
return null;
}
let data: any = this.cut_faction[player.bangid];
if (data == undefined || data == null) {
player.send_notice("你们帮目前没有帮战");
player.map_transfer(1011);
return null;
}
if (type != 0){
if(player.teamid <= 0){
player.send_notice("请先进行组队");
return null;
}
let team = TeamMgr.shared.getTeamInfo(player.teamid);
if (team == null || team.playerlist.length < 3) {
player.send_notice("您当前队伍人数 < 3人,不可进行该操作");
return null;
}
}
return data;
}
/**
* 传送
* @param player 玩家信息
* @param type 0基地 1基地外围
*/
portal(player: any, type: number){
let data: any = this.cut_faction[player.bangid];
if (data != undefined && data != null){
if (data.site == "L"){
if (type == 0){
player.map_transfer(3001, this.gate_xy_left.x, this.gate_xy_left.y);
}else {
player.map_transfer(3001, this.out_gate_xy_left.x, this.out_gate_xy_left.y);
}
}else {
if (type == 0){
player.map_transfer(3001, this.gate_xy_right.x, this.gate_xy_right.y);
}else {
player.map_transfer(3001, this.out_gate_xy_right.x, this.out_gate_xy_right.y);
}
}
}else {
player.map_transfer(3001, 105, 51);
}
return;
}
/**
* 烈火塔、玄冰塔操作
* @param player 玩家信息
* @param type 0蓄力1打断
* @param serial 塔编号
*/
tower_action(player: any, type: number, serial: number){
let data = this.check(player, 1);
if (data != null) {
// 获取塔状态(如果正在蓄力或者已经破损直接返回)
let tower: any = this.urban_defense_map.get(serial);
if (tower.state == FortificationsOperate.DAMAGED) {
player.send("s2c_ask_fortifications", {
type: tower.type,
serial: serial,
is: type,
state: MsgCode.FAILED
});
return;
}
// 1.蓄力
if (type == FortificationsOperate.STOREUP) {
// 1.1 如果在蓄力状态直接返回
if (tower.state == FortificationsOperate.STOREUP) {
player.send("s2c_ask_fortifications", {
type: tower.type,
serial: serial,
is: type,
state: MsgCode.FAILED
});
return;
}
if (tower.state == FortificationsOperate.AUTOMATIC) {
player.send("s2c_ask_fortifications", {
type: tower.type,
serial: serial,
is: type,
state: MsgCode.FAILED
});
player.send_notice("当前塔不需要蓄力");
return;
}
// 1.2 关闭定时器
this.stopTowerSchedule(tower.site, tower.type);
// 1.3塔操作数据
tower.time = 1;
tower.state = FortificationsOperate.STOREUP;
tower.roleId = player.roleid;
this.urban_defense_map.set(serial, tower);
if (tower.site == "L") {
if (tower.type == Fortifications.ice) {
// 1.4生成一个每ms定时器到20ms自动发射
this.ice_l_schedule = setInterval(this.towerScheduleMs, 20 * 1000, serial, this);
} else {
// 1.4生成一个每ms定时器到20ms自动发射
this.fire_l_schedule = setInterval(this.towerScheduleMs, 20 * 1000, serial, this);
}
} else {
if (tower.type == Fortifications.ice) {
// 1.4生成一个每ms定时器到20ms自动发射
this.ice_r_schedule = setInterval(this.towerScheduleMs, 20 * 1000, serial, this);
} else {
// 1.4生成一个每ms定时器到20ms自动发射
this.fire_r_schedule = setInterval(this.towerScheduleMs, 20 * 1000, serial, this);
}
}
player.send("s2c_ask_fortifications", {
type: tower.type,
serial: Fortifications.cannon,
is: type,
state: MsgCode.SUCCESS
});
}
// 2.打断
else {
// 2.1 关闭定时器
this.stopTowerSchedule(tower.site, tower.type);
// 2.2恢复数据
tower.time = 0;
tower.state = FortificationsOperate.INTERRUPT;
}
this.urban_defense_map.set(serial, tower);
}
}
/**
* 执行塔
* @param this_
*/
towerScheduleMs(serial: number, this_: any) {
// 1.获取塔状态
let tower: any = this_.urban_defense_map.get(serial);
tower.roleId = 0;
tower.time += 1;
// 1.2.塔发射,减去耐久度
tower.durable -= 10;
tower.state = FortificationsOperate.AUTOMATIC;
// 1.3耐久度小于等于0 停止攻击
if (tower.durable <= 0) {
tower.state = FortificationsOperate.DAMAGED;
this_.stopTowerSchedule(tower.site, tower.type);
this_.clear_npc(serial);
this_.create_npc(tower.shadow);
}
// 1.4发射
this_.bombard_tower(serial, tower);
this_.urban_defense_map.set(serial, tower);
}
/**
* 战斗打断正在蓄力
* @param player
*/
fortifications_examine(player: any){
for (let [key, value] of this.urban_defense_map) {
if (key >= 7205 && key <= 7208){
if (value.state == FortificationsOperate.STOREUP && value.roleId == player.roleid){
this.tower_action(player,1,key);
break;
}
}else {
if (value.state == FortificationsOperate.STOREUP && value.roleId == player.roleid){
this.cannon_action(player,1);
break;
}
}
}
}
/**
* 关闭塔定时器
* @param site L 左 R 右
* @param type 2 烈火塔 3 玄冰塔
*/
stopTowerSchedule(site: any, type: any){
if (site == "L") {
if (type == Fortifications.ice) {
// 左边玄冰塔定时器关闭
clearInterval(this.ice_l_schedule);
} else {
// 左边烈火塔定时器关闭
clearInterval(this.fire_l_schedule);
}
} else {
if (type == Fortifications.ice) {
// 右边玄冰塔定时器关闭
clearInterval(this.ice_r_schedule);
} else {
// 右边边烈火塔定时器关闭
clearInterval(this.fire_r_schedule);
}
}
}
/**
* 塔发射攻击
* @param serial 塔的编号
* @param tower 塔的信息
*/
bombard_tower(serial: number, tower: any) {
let x: any = 35;
let y: any = 88;
let scope: any = {};
let hit_foe: any[];
if (tower.site == "L") {
scope = this.tower_left;
} else {
scope = this.tower_right;
}
let list: any[] = [];
let site: any[] = SKDataUtil.randomLonLat(scope.MinLon, scope.MaxLon, scope.MinLat, scope.MaxLat);
if (site.length > 1) {
x = site[0];
y = site[1];
}
for (let key in this.cut_faction) {
let data = this.cut_faction[key];
let arr: any[] = this.contest_map.get(key);
if (data.site != tower.site) {
// 敌方帮派成员
hit_foe = arr;
} else {
// 能量塔攻击数加1
data.tower += 1;
}
list = list.concat(arr);
}
// 通知所有参加帮派玩家(发射炮弹效果)
PlayerMgr.shared.broadcastPart(list, "s2c_bombard_site", {x: x, y: y, serial: serial, type: tower.type, direction: ""});
// 通知所有参加帮派玩家(塔的血量)
PlayerMgr.shared.broadcastPart(list, "s2c_gang_tower_info", {
towerId: serial,
durable: tower.durable,
durableMax: tower.durableMax,
bangId: tower.bangId
});
// 获取附近敌方帮派成员
for (let key of hit_foe) {
let player = PlayerMgr.shared.getPlayerByRoleId(Number(key));
if (player) {
// 判断是否在炸点范围 在炸点范围送回基地
let is = SKDataUtil.confineTo(x, y, player.x, player.y, this.tower_radius);
if (is) {
// 被玄冰塔击中冰冻20秒
if (tower.type == Fortifications.ice) {
let num = 20;
this.ice_map.set(player.roleid, num);
// 通知前端冰冻该玩家
player.send("s2c_wars_player_state", {type: 1, ice: num, time: GTimer.getTime()});
player.isFrozen = 1;
player.send('s2c_aoi_pinfo', {
list: [player.toObj()]
});
}
// 被烈火塔击中送回基地120ms内不得再进入战场
else {
let num = 120;
this.fire_map.set(player.roleid, num);
// 返回基地
if(player.teamid > 0){
if (player.isleader){
this.goHome(player, 0);
}
}else {
this.goHome(player, 0);
}
player.send_notice("你已被神烈火塔击中, 传送回基地");
}
}
}
}
}
/**
* 神龙大炮操作(当别人切磋该玩家打断)
* @param player 玩家信息
* @param type 0蓄力1打断
* @param 神龙大炮 time 当前蓄力时间ms state 0 蓄力1 打断, roleId 当前蓄力者角色编号, bangId 帮派ID
*/
cannon_action(player: any, type: number) {
let data = this.check(player, 1);
if (data != null) {
// 1.蓄力
if (type == FortificationsOperate.STOREUP) {
// 1.1获取神龙大炮状态(如果正在蓄力直接返回)
let cannon: any = this.urban_defense_map.get(Fortifications.cannon);
if (cannon.state == FortificationsOperate.STOREUP) {
player.send("s2c_ask_fortifications", {
type: Fortifications.cannon,
serial: Fortifications.cannon,
is: type,
state: MsgCode.FAILED
});
return;
} else {
// 1.2关闭定时器
clearInterval(this.cannon_schedule);
// 1.3储存神龙跑操作数据
cannon.time = 1;
cannon.state = FortificationsOperate.STOREUP;
cannon.roleId = player.roleid;
cannon.bangId = player.bangid;
this.urban_defense_map.set(Fortifications.cannon, cannon);
// 1.4生成一个每ms定时器到20ms自动发射炮弹
SKLogger.info("神龙大炮开始蓄力!")
this.cannon_schedule = setInterval(this.cannonScheduleMs, 1000, this);
player.send("s2c_ask_fortifications", {
type: Fortifications.cannon,
serial: Fortifications.cannon,
is: type,
state: MsgCode.SUCCESS
});
}
}
// 2.打断
else {
// 2.1关闭定时器
clearInterval(this.cannon_schedule);
SKLogger.info("神龙大炮被打断蓄力!")
// 2.2获取神龙大炮状态
let cannon_ms: any = this.urban_defense_map.get(Fortifications.cannon);
if (cannon_ms != undefined) {
this.bombard_cannon(cannon_ms.bangId, cannon_ms.time);
}
// 2.3数据恢复初始状态
this.urban_defense_map.set(Fortifications.cannon, {
time: 0,
state: FortificationsOperate.INTERRUPT,
roleId: 0,
bangId: 0
});
}
}
}
/**
* 执行神龙大炮
* @param this_
*/
cannonScheduleMs(this_: any){
// 1.获取神龙大炮状态
let cannon_ms: any = this_.urban_defense_map.get(Fortifications.cannon);
cannon_ms.time += 1;
SKLogger.info("当前塔蓄力时间:"+cannon_ms.time)
// 1.2神龙大炮蓄力时间大于等于20ms则发炮数据恢复初始状态
if (cannon_ms.time >= 20) {
// 1.3关闭定时器
clearInterval(this_.cannon_schedule);
this_.urban_defense_map.set(Fortifications.cannon, {
time: 0,
state: FortificationsOperate.INTERRUPT,
roleId: 0,
bangId: 0
});
this_.bombard_cannon(cannon_ms.bangId, cannon_ms.time);
}else {
this_.urban_defense_map.set(Fortifications.cannon, cannon_ms);
}
}
/**
* 发射神龙大炮
* @param bangId 己方帮派编号
* @param time 蓄力时间
*/
bombard_cannon(bangId: any, time: number) {
// 1.获取当前帮派信息
let data: any = this.cut_faction[bangId]
let gate: any;
let x: any = 35;
let y: any = 88;
let direction: string = "L";
let flag: boolean = false;
if (data != undefined) {
if (data.site == "L") {
if (time >= 20) {
gate = this.cannon_right_gate;
flag = true;
} else if (time < 20 && time > 10) {
gate = this.cannon_right_10_19;
} else {
gate = this.cannon_right_0_10;
}
let site: any[] = SKDataUtil.randomLonLat(gate.MinLon, gate.MaxLon, gate.MinLat, gate.MaxLat);
if (site.length > 1) {
x = site[0];
y = site[1];
}
direction = "R";
} else {
if (time >= 20) {
gate = this.cannon_left_gate;
flag = true;
} else if (time < 20 && time > 10) {
gate = this.cannon_left_10_19;
} else {
gate = this.cannon_left_0_10;
}
let site: any[] = SKDataUtil.randomLonLat(gate.MinLon, gate.MaxLon, gate.MinLat, gate.MaxLat);
if (site.length > 1) {
x = site[0];
y = site[1];
}else {
x = 58;
y = 98;
}
}
// 神龙炮开炮数加1
data.cannon += 1;
let side: any[] = this.contest_map.get(bangId.toString());
let enemy: any[] = this.contest_map.get(data.enemy_id.toString());
let list: any[] = side.concat(enemy);
// 通知所有参加帮派玩家(发射炮弹效果)
PlayerMgr.shared.broadcastPart(list,"s2c_bombard_site", {x: x, y: y, serial: Fortifications.cannon, type: Fortifications.cannon, direction: direction})
// 没有打到门子上
if (!flag){
// 获取附近的人
for (let key of list) {
let player = PlayerMgr.shared.getPlayerByRoleId(Number(key));
if (player) {
// 判断是否在炸点范围 在炸点范围送回基地
let is = SKDataUtil.confineTo(x, y, player.x, player.y, this.cannon_radius);
if (is){
// 返回基地
if(player.teamid > 0){
if (player.isleader){
this.goHome(player, 0);
}
}else {
this.goHome(player, 0);
}
player.send_notice("你已被神龙大炮击中, 传送回基地");
}
}
}
}else {
this.gateHpUpdate(data.enemy_id,-180);
}
}
}
/**
* 城门血量改变
* @param bangId
* @param value
*/
gateHpUpdate(bangId: any,value: number){
// 获取当前帮信息
let data: any = this.cut_faction[bangId];
let data_: any = this.cut_faction[data.enemy_id];
data.gate_hp += value;
let l: any = {};
let r: any = {};
// 己方帮成员
let side: any[] = this.contest_map.get(bangId.toString());
// 敌方帮成员
let enemy: any[] = this.contest_map.get(data.enemy_id.toString());
let list: any[] = side.concat(enemy);
if (data.site == "L"){
let bang: any = BangMgr.shared.getBang(bangId);
let bang_: any = BangMgr.shared.getBang(data.enemy_id);
l = {gateHp: data.gate_hp, gateMaxHp: data.gate_max_hp, name: bang.name};
r = {gateHp: data_.gate_hp, gateMaxHp: data_.gate_max_hp, name: bang_.name};
}else {
let bang: any = BangMgr.shared.getBang(bangId);
let bang_: any = BangMgr.shared.getBang(data.enemy_id);
r = {gateHp: data.gate_hp, gateMaxHp: data.gate_max_hp, name: bang.name};
l = {gateHp: data_.gate_hp, gateMaxHp: data_.gate_max_hp, name: bang_.name};
}
// 通知所有参加帮派玩家(城门血量改变)
PlayerMgr.shared.broadcastPart(list,"s2c_gate_hp", {gateHpL: SKDataUtil.toJson(l,"{}"), gateHpR: SKDataUtil.toJson(r,"{}"), time: this.start_time});
// 如果帮派大门血量小于等于0 结束帮战
if (data.gate_hp <= 0) {
// 5.帮战结束
this.close();
}
}
/**
* 获取烈火塔、玄冰塔信息
* @param player 玩家信息
* @param serial 塔编号
*/
tower_info(player: any, serial: number){
let data = this.check(player, 1);
if (data != null) {
let tower = this.urban_defense_map.get(serial);
if (tower != null && tower != undefined) {
let bangId: any = 0;
for (let key in this.cut_faction) {
let data: any = this.cut_faction[key];
if (data.site == tower.site) {
bangId = key;
break;
}
}
player.send("s2c_gang_tower", {
towerId: serial, // 塔编号
durable: tower.durable, // 当前耐久
durableMax: tower.durableMax, // 最大耐久
bangId: bangId // 帮派编号
});
} else {
player.send_notice("获取塔信息失败!");
}
}
}
/**
* 将塔的帮派编号赋值
*/
tower_info_update(){
for (let [key, value] of this.urban_defense_map) {
if (key >= 7205 && key <= 7208){
let tower = this.urban_defense_map.get(key);
if (tower != null && tower != undefined){
for (let k in this.cut_faction) {
let data: any = this.cut_faction[k];
if (data.site == tower.site) {
tower.bangId = k;
this.urban_defense_map.set(key,tower);
break;
}
}
}
}
};
}
//----------------------------------------------------------------------------------------------------------------------
// 战斗开始之前的 10秒
beforeFight(t1: any, t2: any, type: any) {
let team = TeamMgr.shared.getTeamInfo(t1.teamid);
let eteam = TeamMgr.shared.getTeamInfo(t2.teamid);
if (team && eteam) {
let selfTeam = [];
for (let index = 0; index < team.playerlist.length; index++) {
let member = team.playerlist[index];
let satRole: any = {};
satRole.onlyid = member.onlyid;
satRole.roleid = member.roleid;
satRole.resid = member.resid;
satRole.level = member.level;
satRole.name = member.name;
selfTeam.push(satRole);
}
let enemyTeam = [];
for (let index = 0; index < eteam.playerlist.length; index++) {
let member = eteam.playerlist[index];
let satRole: any = {};
satRole.onlyid = member.onlyid;
satRole.roleid = member.roleid;
satRole.resid = member.resid;
satRole.level = member.level;
satRole.name = member.name;
enemyTeam.push(satRole);
}
TeamMgr.shared.broadcast(t1.teamid, 's2c_match', {
teamS: selfTeam,
teamE: enemyTeam,
});
TeamMgr.shared.broadcast(t2.teamid, 's2c_match', {
teamS: enemyTeam,
teamE: selfTeam,
});
t1.fight_state = this.FightState.Fighting;
t2.fight_state = this.FightState.Fighting;
setTimeout(() => {
this.startFight(t1, t2, type);
}, 11 * 1000);
}
}
/**
* 进入战斗
* @param t1
* @param t2
*/
startFight(t1: any, t2: any, type: any) {
let team = TeamMgr.shared.getTeamInfo(t1.teamid);
let eteam = TeamMgr.shared.getTeamInfo(t2.teamid);
if (team && eteam) {
let eonlyid = eteam.leader.onlyid;
team.leader.playerBattle(eonlyid, type);
}
}
/**
* 关闭活动
*/
close() {
if (this.activity_state == ActivityDefine.activityState.Close) {
return;
}
this.defenceInfo();
// 左边玄冰塔定时器关闭
clearInterval(this.ice_l_schedule);
// 左边烈火塔定时器关闭
clearInterval(this.fire_l_schedule);
// 右边玄冰塔定时器关闭
clearInterval(this.ice_r_schedule);
// 右边边烈火塔定时器关闭
clearInterval(this.fire_r_schedule);
clearInterval(this.ms_ice_target_schedule);
clearInterval(this.ms_fire_target_schedule);
// 通知帮战结束
let list: any[] = [];
for (let [key, value] of this.contest_map) {
list = list.concat(value);
}
for (let i = 0; i < list.length; i++) {
if (list[i] != undefined){
let player = PlayerMgr.shared.getPlayerByRoleId(list[i]);
if (player) {
this.detail_statistics(player,1);
if(player.teamid > 0){
// 清理跳转长安
if (player.isleader){
player.map_transfer(1011);
}
}else {
// 清理跳转长安
player.map_transfer(1011);
}
}
}
}
// 活动状态
this.activity_state = ActivityDefine.activityState.Close;
// 帮战参赛成员
this.contest_map.clear();
this.cut_faction = {};
// 玄冰塔,击中目标记录<角色编号,控制时间>
this.ice_map.clear();
// 烈火塔,击中目标记录<角色编号,控制时间>
this.fire_map.clear();
// 帮战所有参赛成员 - 角色编号 - {战斗状态 2战斗中 1未战斗,帮派编号,击杀人数 field场数,field_win: 本人胜利场,contest: 高手胜利场, member_win成员胜利场}
this.contest_map_info.clear();
this.clear_npc(0,1);
for (let [key, value] of this.urban_defense_map) {
if (key != Fortifications.cannon) {
this.create_npc(key);
}
}
}
}