增加辅助机器人
This commit is contained in:
parent
b169103835
commit
4c9e74b571
@ -1,2 +1,2 @@
|
|||||||
pm2 start npm --name "card" -- run "dev:jc"
|
pm2 start npm --name "card" --log-date-format "YYYY-MM-DD HH:MM:ss" -- run "dev:jc"
|
||||||
pm2 start npm --name "robot" -- run "dev:robot"
|
pm2 start npm --name "robot" --log-date-format "YYYY-MM-DD HH:MM:ss" -- run "dev:robot"
|
||||||
|
@ -7,3 +7,5 @@ export const error = debug('jc:error');
|
|||||||
export const msgLog = debug('jc:msg');
|
export const msgLog = debug('jc:msg');
|
||||||
|
|
||||||
export const robotLog = debug('jc:robot');
|
export const robotLog = debug('jc:robot');
|
||||||
|
|
||||||
|
export const assistLog = debug('jc:assist');
|
||||||
|
19
src/global.d.ts
vendored
19
src/global.d.ts
vendored
@ -8,6 +8,7 @@ import {RemovePetMsg} from "./message/RemovePetMsg";
|
|||||||
import {Dispatcher} from "@colyseus/command";
|
import {Dispatcher} from "@colyseus/command";
|
||||||
import {Delayed} from "@gamestdio/timer/lib/Delayed";
|
import {Delayed} from "@gamestdio/timer/lib/Delayed";
|
||||||
import {Player} from "./rooms/schema/Player";
|
import {Player} from "./rooms/schema/Player";
|
||||||
|
import {RobotClient} from "./robot/RobotClient";
|
||||||
|
|
||||||
export {};
|
export {};
|
||||||
|
|
||||||
@ -34,6 +35,11 @@ declare module "colyseus" {
|
|||||||
* @param player 玩家id或者玩家的对象
|
* @param player 玩家id或者玩家的对象
|
||||||
*/
|
*/
|
||||||
getClient(player: string | Player): Client;
|
getClient(player: string | Player): Client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前room的client数量
|
||||||
|
*/
|
||||||
|
clientCount(): number;
|
||||||
// >>>>>>>>> Begin of extend send message <<<<<<<<<<<<<
|
// >>>>>>>>> Begin of extend send message <<<<<<<<<<<<<
|
||||||
/**
|
/**
|
||||||
* 广播玩家加入房间
|
* 广播玩家加入房间
|
||||||
@ -154,6 +160,8 @@ declare module "colyseus" {
|
|||||||
*/
|
*/
|
||||||
bMsgQueue(datas: IMsg[], options?: any): void;
|
bMsgQueue(datas: IMsg[], options?: any): void;
|
||||||
|
|
||||||
|
send(client: Client, type: string, data?: any): void;
|
||||||
|
|
||||||
|
|
||||||
// >>>>>>>>> End of extend send message <<<<<<<<<<<<<
|
// >>>>>>>>> End of extend send message <<<<<<<<<<<<<
|
||||||
|
|
||||||
@ -241,6 +249,17 @@ declare module "colyseus" {
|
|||||||
*/
|
*/
|
||||||
addRobot(playerId?: string):void;
|
addRobot(playerId?: string):void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加一个辅助机器人
|
||||||
|
* @param sessionId
|
||||||
|
*/
|
||||||
|
addAssistClient(sessionId: string): void;
|
||||||
|
/**
|
||||||
|
* 获取当前session的辅助机器人
|
||||||
|
* @param sessionId
|
||||||
|
*/
|
||||||
|
getAssistClient(sessionId: string): RobotClient;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ import {Player} from "../rooms/schema/Player";
|
|||||||
import {EffectCardCfg} from "../cfg/parsers/EffectCardCfg";
|
import {EffectCardCfg} from "../cfg/parsers/EffectCardCfg";
|
||||||
import {SkillTargetType} from "../rooms/logic/skill/SkillConst";
|
import {SkillTargetType} from "../rooms/logic/skill/SkillConst";
|
||||||
import CfgMan from "../rooms/logic/CfgMan";
|
import CfgMan from "../rooms/logic/CfgMan";
|
||||||
|
import gameUtil from "../utils/game.util";
|
||||||
|
import assistantUtil from "../utils/assistant.util";
|
||||||
|
|
||||||
export class Robot {
|
export class Robot {
|
||||||
host: string;
|
host: string;
|
||||||
@ -37,6 +39,17 @@ export class Robot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async reConnect(sessionId: string) {
|
||||||
|
try {
|
||||||
|
this.room = await this.client.reconnect(this.roomId, sessionId);
|
||||||
|
this.addListeners();
|
||||||
|
this.sessionId = this.room.sessionId;
|
||||||
|
return this.room.sessionId;
|
||||||
|
} catch (err) {
|
||||||
|
error(`error reConnect room ${this.host}, ${this.roomId}, sessionId: ${sessionId}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addListeners() {
|
addListeners() {
|
||||||
let self = this;
|
let self = this;
|
||||||
this.room.onMessage("*", (type, data) => {
|
this.room.onMessage("*", (type, data) => {
|
||||||
@ -117,129 +130,6 @@ export class Robot {
|
|||||||
this.room.send(messageType, message);
|
this.room.send(messageType, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkTriple(cardArr: Card[], card?: Card): Card[] {
|
|
||||||
if (card) cardArr.push(card);
|
|
||||||
let pointMap: Map<number, Card[]> = new Map();
|
|
||||||
let cardIdSet: Set<number> = new Set();
|
|
||||||
for (let c of cardArr) {
|
|
||||||
if (c.type !== 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pointMap.has(c.number)) {
|
|
||||||
let arr = pointMap.get(c.number);
|
|
||||||
arr.push(c);
|
|
||||||
pointMap.set(c.number, arr);
|
|
||||||
} else {
|
|
||||||
pointMap.set(c.number, [c]);
|
|
||||||
}
|
|
||||||
cardIdSet.add(c.number);
|
|
||||||
}
|
|
||||||
let fetched = false;
|
|
||||||
let result:Card[] = [];
|
|
||||||
// 优先出对子
|
|
||||||
for (let [point, arr] of pointMap) {
|
|
||||||
if (card) {
|
|
||||||
if (point == card.number && arr.length >= 3) {
|
|
||||||
fetched = true;
|
|
||||||
result = arr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (arr.length >= 3) {
|
|
||||||
fetched = true;
|
|
||||||
result = arr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (fetched) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cardIds = [...cardIdSet];
|
|
||||||
cardIds.sort((a, b) => a - b);
|
|
||||||
let tmp = [];
|
|
||||||
for (let i = 0, length = cardIds.length; i < length; i++) {
|
|
||||||
let cur = cardIds[i];
|
|
||||||
i == 0 && tmp.push(cur);
|
|
||||||
if (i > 0) {
|
|
||||||
if (cur != tmp[i - 1] + 1) {
|
|
||||||
tmp.length = 0;
|
|
||||||
}
|
|
||||||
tmp.push(cur);
|
|
||||||
}
|
|
||||||
if (card) {
|
|
||||||
if (tmp.indexOf(card.number) >= 0 && tmp.length >=3 ){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (tmp.length >= 3) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tmp.length >= 3) {
|
|
||||||
let subTmp = [];
|
|
||||||
for (let i = tmp[0] - 1; i > 0 ; i -- ) {
|
|
||||||
if (cardIdSet.has(i)) {
|
|
||||||
subTmp.push(i);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let i = tmp[tmp.length]; i < cardIdSet.size; i ++) {
|
|
||||||
if (cardIdSet.has(i)) {
|
|
||||||
subTmp.push(i);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmp = tmp.concat(subTmp);
|
|
||||||
for (let point of tmp) {
|
|
||||||
if (card && point === card.number) {
|
|
||||||
result.push(card);
|
|
||||||
} else {
|
|
||||||
result.push(pointMap.get(point)[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
return arrUtil.randomGet(cardArr, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 随机获取敌对玩家
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
private getEnemyPlayer(): Player {
|
|
||||||
let enemys = [];
|
|
||||||
for (let [,player] of this.room.state.players) {
|
|
||||||
if (player.team !== this.player.team) {
|
|
||||||
enemys.push(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return arrUtil.randomOne(enemys);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 随机获取可用的随从
|
|
||||||
* @param player
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
private getRandomPet(player: Player): number {
|
|
||||||
let pets = [];
|
|
||||||
for (let [, pet] of player.pets) {
|
|
||||||
if (pet.ap > 0 && pet.state == 1)
|
|
||||||
pets.push(pet);
|
|
||||||
}
|
|
||||||
let result;
|
|
||||||
if (pets.length > 0) {
|
|
||||||
result = arrUtil.randomOne(pets);
|
|
||||||
}
|
|
||||||
return result ? result.pos : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// >>>>>>>>>>>>>>>>>> begin
|
// >>>>>>>>>>>>>>>>>> begin
|
||||||
/**
|
/**
|
||||||
@ -247,13 +137,9 @@ export class Robot {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private async selectHero() {
|
private async selectHero() {
|
||||||
let heroMap: Map<number, HeroCfg> = global.$cfg.get(BaseConst.HERO);
|
|
||||||
let heroArr = [...heroMap.values()];
|
|
||||||
let hero = arrUtil.randomGet(heroArr, 1);
|
|
||||||
await this.delay(2);
|
await this.delay(2);
|
||||||
this.reply('select_hero_c2s', {
|
let data = assistantUtil.randomHero();
|
||||||
heroId: hero[0].id
|
this.reply('select_hero_c2s', data);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -284,7 +170,7 @@ export class Robot {
|
|||||||
await this.delay(3);
|
await this.delay(3);
|
||||||
let self = this;
|
let self = this;
|
||||||
let cardArr = [...self.player.cards.values()];
|
let cardArr = [...self.player.cards.values()];
|
||||||
let cards = self.checkTriple(cardArr);
|
let cards = assistantUtil.checkTriple(cardArr);
|
||||||
if (!cards) {
|
if (!cards) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -302,7 +188,7 @@ export class Robot {
|
|||||||
await this.delay(2);
|
await this.delay(2);
|
||||||
let targetCard = [...this.room.state.cards.values()][0];
|
let targetCard = [...this.room.state.cards.values()][0];
|
||||||
let cardArr = [...this.player.cards.values()];
|
let cardArr = [...this.player.cards.values()];
|
||||||
let tmpCards = this.checkTriple(cardArr, targetCard);
|
let tmpCards = assistantUtil.checkTriple(cardArr, targetCard);
|
||||||
let next = this.giveup.bind(this);
|
let next = this.giveup.bind(this);
|
||||||
if (tmpCards.length > 1) {
|
if (tmpCards.length > 1) {
|
||||||
let cardIds: number[] = [];
|
let cardIds: number[] = [];
|
||||||
@ -345,66 +231,8 @@ export class Robot {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private async selectPet() {
|
private async selectPet() {
|
||||||
await this.delay(5, 0.2);
|
let data = await assistantUtil.selectPet(this.player, this.room.state);
|
||||||
let cards = [...this.room.state.cards.values()];
|
this.reply('select_pet_c2s', data);
|
||||||
let result;
|
|
||||||
let effectMap: Map<number, EffectCardCfg> = global.$cfg.get(BaseConst.EFFECTCARD);
|
|
||||||
for (let card of cards) {
|
|
||||||
let effect = effectMap.get(card.effect);
|
|
||||||
if (effect.type_id == 1) {
|
|
||||||
result = card;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!result) {
|
|
||||||
result = arrUtil.randomGet(cards, 1)[0];
|
|
||||||
}
|
|
||||||
let targetType: SkillTargetType = CfgMan.getTargetByCard(result.id);
|
|
||||||
let targetPlayer;
|
|
||||||
let targetPos;
|
|
||||||
switch (targetType) {
|
|
||||||
case SkillTargetType.ENEMY_PLAYER:
|
|
||||||
targetPlayer = this.getEnemyPlayer();
|
|
||||||
break;
|
|
||||||
case SkillTargetType.ENEMY_PET:
|
|
||||||
for (let [,player] of this.room.state.players) {
|
|
||||||
if (player.team !== this.player.team) {
|
|
||||||
let pos = this.getRandomPet(player);
|
|
||||||
if (pos > - 1) {
|
|
||||||
targetPlayer = player;
|
|
||||||
targetPos = pos;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SkillTargetType.FRIEND_PET:
|
|
||||||
for (let [,player] of this.room.state.players) {
|
|
||||||
if (player.team == this.player.team) {
|
|
||||||
let pos = this.getRandomPet(player);
|
|
||||||
if (pos > - 1) {
|
|
||||||
targetPlayer = player;
|
|
||||||
targetPos = pos;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SkillTargetType.SELF_PET:
|
|
||||||
let pos = this.getRandomPet(this.player);
|
|
||||||
if (pos > - 1) {
|
|
||||||
targetPlayer = this.player;
|
|
||||||
targetPos = pos;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.reply('select_pet_c2s', {
|
|
||||||
card: result.id,
|
|
||||||
player: targetPlayer?.id,
|
|
||||||
pos: targetPos,
|
|
||||||
effCards: []
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,19 +1,12 @@
|
|||||||
import {Client, Room} from "colyseus";
|
import {Client, Room} from "colyseus";
|
||||||
import {ClientState, ISendOptions} from "colyseus/lib/transport/Transport";
|
import {ClientState, ISendOptions} from "colyseus/lib/transport/Transport";
|
||||||
import {EventEmitter} from 'events';
|
import {EventEmitter} from 'events';
|
||||||
import {robotLog as log} from '../common/Debug';
|
import {assistLog as log} from '../common/Debug';
|
||||||
import {CardGameState} from "../rooms/schema/CardGameState";
|
import {CardGameState} from "../rooms/schema/CardGameState";
|
||||||
import Clock from "@gamestdio/timer";
|
|
||||||
import {GameStateConst} from "../constants/GameStateConst";
|
import {GameStateConst} from "../constants/GameStateConst";
|
||||||
import {Card} from "../rooms/schema/Card";
|
import {Card} from "../rooms/schema/Card";
|
||||||
import {BaseConst} from "../constants/BaseConst";
|
|
||||||
import arrUtil from "../utils/array.util";
|
|
||||||
import {HeroCfg} from "../cfg/parsers/HeroCfg";
|
|
||||||
import {EffectCardCfg} from "../cfg/parsers/EffectCardCfg";
|
|
||||||
import CfgMan from '../rooms/logic/CfgMan';
|
|
||||||
import {SkillTargetType} from "../rooms/logic/skill/SkillConst";
|
|
||||||
import {Player} from "../rooms/schema/Player";
|
import {Player} from "../rooms/schema/Player";
|
||||||
import gameUtil from "../utils/game.util";
|
import assistantUtil from "../utils/assistant.util";
|
||||||
|
|
||||||
export class RobotClient implements Client {
|
export class RobotClient implements Client {
|
||||||
id: string;
|
id: string;
|
||||||
@ -23,26 +16,19 @@ export class RobotClient implements Client {
|
|||||||
selfPlayer: Player;
|
selfPlayer: Player;
|
||||||
state: ClientState;
|
state: ClientState;
|
||||||
svrstate: CardGameState;
|
svrstate: CardGameState;
|
||||||
room: Room;
|
|
||||||
clock: Clock;
|
|
||||||
myTurn: boolean = false;
|
myTurn: boolean = false;
|
||||||
cards: Map<String, Card>;
|
cards: Map<String, Card>;
|
||||||
onMessageHandlers: {[id: string]: (client: Client, message: any) => void} = {};
|
onMessageHandlers: {[id: string]: (client: Client, message: any) => void} = {};
|
||||||
listenerState: any;
|
listenerState: any;
|
||||||
listenerTurn: any;
|
listenerTurn: any;
|
||||||
|
active: boolean = false;
|
||||||
|
|
||||||
constructor(sessionId: string, state: CardGameState, clock: Clock, onMessageHandlers: {[id: string]: (client: Client, message: any) => void}) {
|
constructor(sessionId: string, state: CardGameState, onMessageHandlers: {[id: string]: (client: Client, message: any) => void}) {
|
||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
this.svrstate = state;
|
this.svrstate = state;
|
||||||
this.selfPlayer = this.svrstate.players.get(sessionId);
|
this.selfPlayer = this.svrstate.players.get(sessionId);
|
||||||
this.clock = clock;
|
|
||||||
this.ref = new EventEmitter();
|
this.ref = new EventEmitter();
|
||||||
this.onMessageHandlers = onMessageHandlers;
|
this.onMessageHandlers = onMessageHandlers;
|
||||||
let self = this;
|
|
||||||
let time = Math.random() * 2500 | 0;
|
|
||||||
this.clock.setTimeout(function (){
|
|
||||||
self.reply('play_ready_c2s', '');
|
|
||||||
}, time);
|
|
||||||
this.addListeners();
|
this.addListeners();
|
||||||
|
|
||||||
log(`new robot with session: ${sessionId}`);
|
log(`new robot with session: ${sessionId}`);
|
||||||
@ -74,13 +60,15 @@ export class RobotClient implements Client {
|
|||||||
|
|
||||||
private gameSateUpdate(currentValue: number, previousValue: number) {
|
private gameSateUpdate(currentValue: number, previousValue: number) {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
if (!this.active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
log(`server game state change: ${currentValue}, pre value: ${previousValue}`);
|
log(`server game state change: ${currentValue}, pre value: ${previousValue}`);
|
||||||
switch (currentValue) {
|
switch (currentValue) {
|
||||||
case GameStateConst.CHANGE_HERO:
|
case GameStateConst.CHANGE_HERO:
|
||||||
self.selectHero();
|
self.selectHero();
|
||||||
break;
|
break;
|
||||||
case GameStateConst.STATE_CHANGE_CARD:
|
case GameStateConst.STATE_CHANGE_CARD:
|
||||||
self.cards = self.svrstate.players.get(self.sessionId).cards;
|
|
||||||
self.changeCard();
|
self.changeCard();
|
||||||
break;
|
break;
|
||||||
case GameStateConst.STATE_BEGIN_EAT:
|
case GameStateConst.STATE_BEGIN_EAT:
|
||||||
@ -94,8 +82,11 @@ export class RobotClient implements Client {
|
|||||||
}
|
}
|
||||||
private gameTurnUpdate(currentValue: string, previousValue: string) {
|
private gameTurnUpdate(currentValue: string, previousValue: string) {
|
||||||
let self = this;
|
let self = this;
|
||||||
log(`server turn change: ${currentValue}, pre value: ${previousValue}`);
|
|
||||||
self.myTurn = currentValue === self.sessionId;
|
self.myTurn = currentValue === self.sessionId;
|
||||||
|
if (!this.active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log(`server turn change: ${currentValue}, pre value: ${previousValue}`);
|
||||||
if (self.myTurn) {
|
if (self.myTurn) {
|
||||||
self.discard();
|
self.discard();
|
||||||
}
|
}
|
||||||
@ -104,6 +95,9 @@ export class RobotClient implements Client {
|
|||||||
public send(messageOrType: any, messageOrOptions?: any | ISendOptions, options?: ISendOptions) {
|
public send(messageOrType: any, messageOrOptions?: any | ISendOptions, options?: ISendOptions) {
|
||||||
log(`receive server msg: ${messageOrType}, ${messageOrOptions}`);
|
log(`receive server msg: ${messageOrType}, ${messageOrOptions}`);
|
||||||
let self = this;
|
let self = this;
|
||||||
|
if (!this.active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let data = messageOrOptions;
|
let data = messageOrOptions;
|
||||||
switch (messageOrType) {
|
switch (messageOrType) {
|
||||||
case 'draw_card_s2c':
|
case 'draw_card_s2c':
|
||||||
@ -127,80 +121,16 @@ export class RobotClient implements Client {
|
|||||||
(this.onMessageHandlers['*'] as any)(this, messageType, message);
|
(this.onMessageHandlers['*'] as any)(this, messageType, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkTriple(cardArr: Card[], card?: Card): Card[] {
|
|
||||||
if (card) cardArr.push(card);
|
|
||||||
let cards = cardArr.filter(o => o.type == 1);
|
|
||||||
cards.sort((a, b) => a.number - b.number);
|
|
||||||
let result = [];
|
|
||||||
for (let i = 0, length = cards.length; i < length; i ++) {
|
|
||||||
let cur = cards[i];
|
|
||||||
i == 0 && result.push(cur);
|
|
||||||
if (i > 0) {
|
|
||||||
let isSame = false;
|
|
||||||
if (result.length > 1) {
|
|
||||||
if (result[result.length - 1].number == result[result.length - 2].number) {
|
|
||||||
isSame = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((result[result.length - 1].number == cur.number) && (isSame || result.length == 1)) {
|
|
||||||
result.push(cur);
|
|
||||||
} else if ((result[result.length - 1].number + 1 == cur.number) && (!isSame || result.length == 1)) {
|
|
||||||
result.push(cur);
|
|
||||||
} else {
|
|
||||||
result.length = 0;
|
|
||||||
result.push(cur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result.length < 3) {
|
|
||||||
return [cards[0]];
|
|
||||||
} else {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 随机获取敌对玩家
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
private getEnemyPlayer(): Player {
|
|
||||||
let enemys = [];
|
|
||||||
for (let [,player] of this.svrstate.players) {
|
|
||||||
if (player.team !== this.selfPlayer.team) {
|
|
||||||
enemys.push(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return arrUtil.randomOne(enemys);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 随机获取可用的随从
|
|
||||||
* @param player
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
private getRandomPet(player: Player): number {
|
|
||||||
let pets = [];
|
|
||||||
for (let [, pet] of player.pets) {
|
|
||||||
if (pet.ap > 0 && pet.state == 1)
|
|
||||||
pets.push(pet);
|
|
||||||
}
|
|
||||||
let result;
|
|
||||||
if (pets.length > 0) {
|
|
||||||
result = arrUtil.randomOne(pets);
|
|
||||||
}
|
|
||||||
return result ? result.pos : -1;
|
|
||||||
}
|
|
||||||
// >>>>>>>>>>>>>>>>>> begin
|
// >>>>>>>>>>>>>>>>>> begin
|
||||||
/**
|
/**
|
||||||
* 出牌
|
* 出牌
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private discard() {
|
private async discard() {
|
||||||
|
await assistantUtil.delay(3);
|
||||||
let self = this;
|
let self = this;
|
||||||
let next = function () {
|
let cardArr = [...self.selfPlayer.cards.values()];
|
||||||
let cardArr = [...self.cards.values()];
|
let cards = assistantUtil.checkTriple(cardArr);
|
||||||
// cardArr.sort((a, b) => a.number - b.number);
|
|
||||||
let cards = self.checkTriple(cardArr);
|
|
||||||
if (!cards) {
|
if (!cards) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -209,17 +139,16 @@ export class RobotClient implements Client {
|
|||||||
cards: cardIds
|
cards: cardIds
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.clock.setTimeout(next, 1500);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 吃牌或者放弃
|
* 吃牌或者放弃
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private eatOrGiveUp() {
|
private async eatOrGiveUp() {
|
||||||
|
await assistantUtil.delay(2);
|
||||||
let targetCard = [...this.svrstate.cards.values()][0];
|
let targetCard = [...this.svrstate.cards.values()][0];
|
||||||
let cardArr = [...this.cards.values()];
|
let cardArr = [...this.selfPlayer.cards.values()];
|
||||||
let tmpCards = this.checkTriple(cardArr, targetCard);
|
let tmpCards = assistantUtil.checkTriple(cardArr, targetCard);
|
||||||
let next = this.giveup.bind(this);
|
let next = this.giveup.bind(this);
|
||||||
if (tmpCards.length > 1) {
|
if (tmpCards.length > 1) {
|
||||||
let cardIds: number[] = [];
|
let cardIds: number[] = [];
|
||||||
@ -230,8 +159,7 @@ export class RobotClient implements Client {
|
|||||||
}
|
}
|
||||||
next = this.eatCard.bind(this, cardIds, targetCard.id);
|
next = this.eatCard.bind(this, cardIds, targetCard.id);
|
||||||
}
|
}
|
||||||
|
next.apply(this);
|
||||||
this.clock.setTimeout(next, 1500);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -256,17 +184,23 @@ export class RobotClient implements Client {
|
|||||||
this.reply('give_up_eat_c2s', {});
|
this.reply('give_up_eat_c2s', {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开局装备
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private async setReady() {
|
||||||
|
await assistantUtil.delay(2.5);
|
||||||
|
this.reply('play_ready_c2s', '');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开局选择英雄
|
* 开局选择英雄
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private selectHero() {
|
private async selectHero() {
|
||||||
let heroMap: Map<number, HeroCfg> = global.$cfg.get(BaseConst.HERO);
|
await assistantUtil.delay(2);
|
||||||
let heroArr = [...heroMap.values()];
|
let data = assistantUtil.randomHero();
|
||||||
let hero = arrUtil.randomGet(heroArr, 1);
|
this.reply('select_hero_c2s', data);
|
||||||
this.reply('select_hero_c2s', {
|
|
||||||
heroId: hero[0].id
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -286,66 +220,9 @@ export class RobotClient implements Client {
|
|||||||
* 选择一个法术或者一个随从
|
* 选择一个法术或者一个随从
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private selectPet() {
|
private async selectPet() {
|
||||||
let cards = [...this.svrstate.cards.values()];
|
let data = await assistantUtil.selectPet(this.selfPlayer, this.svrstate);
|
||||||
let result;
|
this.reply('select_pet_c2s', data)
|
||||||
let effectMap: Map<number, EffectCardCfg> = global.$cfg.get(BaseConst.EFFECTCARD);
|
|
||||||
for (let card of cards) {
|
|
||||||
let effect = effectMap.get(card.effect);
|
|
||||||
if (effect.type_id == 1) {
|
|
||||||
result = card;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!result) {
|
|
||||||
result = arrUtil.randomGet(cards, 1)[0];
|
|
||||||
}
|
|
||||||
let targetType: SkillTargetType = CfgMan.getTargetByCard(result.id);
|
|
||||||
let targetPlayer;
|
|
||||||
let targetPos;
|
|
||||||
switch (targetType) {
|
|
||||||
case SkillTargetType.ENEMY_PLAYER:
|
|
||||||
targetPlayer = this.getEnemyPlayer();
|
|
||||||
break;
|
|
||||||
case SkillTargetType.ENEMY_PET:
|
|
||||||
for (let [,player] of this.svrstate.players) {
|
|
||||||
if (player.team !== this.selfPlayer.team) {
|
|
||||||
let pos = this.getRandomPet(player);
|
|
||||||
if (pos > - 1) {
|
|
||||||
targetPlayer = player;
|
|
||||||
targetPos = pos;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SkillTargetType.FRIEND_PET:
|
|
||||||
for (let [,player] of this.svrstate.players) {
|
|
||||||
if (player.team == this.selfPlayer.team) {
|
|
||||||
let pos = this.getRandomPet(player);
|
|
||||||
if (pos > - 1) {
|
|
||||||
targetPlayer = player;
|
|
||||||
targetPos = pos;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SkillTargetType.SELF_PET:
|
|
||||||
let pos = this.getRandomPet(this.selfPlayer);
|
|
||||||
if (pos > - 1) {
|
|
||||||
targetPlayer = this.selfPlayer;
|
|
||||||
targetPos = pos;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.reply('select_pet_c2s', {
|
|
||||||
card: result.id,
|
|
||||||
player: targetPlayer?.id,
|
|
||||||
pos: targetPos,
|
|
||||||
effCards: []
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,4 +6,9 @@ export class RobotManage {
|
|||||||
let robot = new Robot(host, room);
|
let robot = new Robot(host, room);
|
||||||
let sessionId = await robot.connect();
|
let sessionId = await robot.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async reConnect({host, room, sessionId}: { host: string, room: string, sessionId: string }) {
|
||||||
|
let robot = new Robot(host, room);
|
||||||
|
await robot.reConnect(sessionId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,20 @@ const router = express.Router();
|
|||||||
|
|
||||||
router.get('/create', async (req, res, next) => {
|
router.get('/create', async (req, res, next) => {
|
||||||
let query = req.query;
|
let query = req.query;
|
||||||
let {host, room } = query;
|
let {host, room, sessionId } = query;
|
||||||
host = host as string;
|
host = host as string;
|
||||||
room = room as string;
|
room = room as string;
|
||||||
debug(`receive create robot msg: ${host}, ${room}`);
|
|
||||||
let manage = singleton(RobotManage);
|
let manage = singleton(RobotManage);
|
||||||
try {
|
try {
|
||||||
|
if (sessionId) {
|
||||||
|
sessionId = sessionId as string;
|
||||||
|
debug(`receive reconnect msg: ${host}, ${room}, ${sessionId}`);
|
||||||
|
await manage.reConnect({host, room, sessionId})
|
||||||
|
} else {
|
||||||
|
debug(`receive create robot msg: ${host}, ${room}`);
|
||||||
await manage.addOne({host, room});
|
await manage.addOne({host, room});
|
||||||
|
}
|
||||||
res.json({errcode: 0});
|
res.json({errcode: 0});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.json({errcode: 1})
|
res.json({errcode: 1})
|
||||||
|
@ -27,6 +27,9 @@ export class GeneralRoom extends Room {
|
|||||||
battleMan = new BattleHandler();
|
battleMan = new BattleHandler();
|
||||||
// 用于游戏过程中各种计时器, 使用该计时器的前提是, 只针对当前操作玩家
|
// 用于游戏过程中各种计时器, 使用该计时器的前提是, 只针对当前操作玩家
|
||||||
gameClock: Map<string, Delayed> = new Map();
|
gameClock: Map<string, Delayed> = new Map();
|
||||||
|
|
||||||
|
assistMap: Map<String, RobotClient> = new Map();
|
||||||
|
|
||||||
async onAuth (client:Client, options: any, request: IncomingMessage) {
|
async onAuth (client:Client, options: any, request: IncomingMessage) {
|
||||||
console.log(options);
|
console.log(options);
|
||||||
// TODO: 验证用户信息
|
// TODO: 验证用户信息
|
||||||
@ -102,19 +105,24 @@ export class GeneralRoom extends Room {
|
|||||||
async onLeave (client: Client, consented: boolean) {
|
async onLeave (client: Client, consented: boolean) {
|
||||||
if (this.state.gameState === GameStateConst.STATE_GAME_OVER || this.state.gameState === GameStateConst.STATE_WAIT_JOIN) {
|
if (this.state.gameState === GameStateConst.STATE_GAME_OVER || this.state.gameState === GameStateConst.STATE_WAIT_JOIN) {
|
||||||
this.state.players.delete(client.sessionId);
|
this.state.players.delete(client.sessionId);
|
||||||
|
this.assistMap.delete(client.sessionId);
|
||||||
this.bUserLeft(client.sessionId);
|
this.bUserLeft(client.sessionId);
|
||||||
} else {
|
} else {
|
||||||
this.state.players.get(client.sessionId).state = PlayerStateConst.PLAYER_OFFLINE;
|
this.state.players.get(client.sessionId).state = PlayerStateConst.PLAYER_OFFLINE;
|
||||||
|
let assistClient = this.getAssistClient(client.sessionId);
|
||||||
|
assistClient.active = true;
|
||||||
try {
|
try {
|
||||||
if (consented) {
|
if (consented) {
|
||||||
throw new Error("consented leave");
|
throw new Error("consented leave");
|
||||||
}
|
} else {
|
||||||
await this.allowReconnection(client, 60);
|
await this.allowReconnection(client, 60);
|
||||||
|
debugRoom(`${client.sessionId} 重连`);
|
||||||
|
assistClient.active = false;
|
||||||
this.state.players.get(client.sessionId).state = PlayerStateConst.PLAYER_NORMAL;
|
this.state.players.get(client.sessionId).state = PlayerStateConst.PLAYER_NORMAL;
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugRoom(`player realy level :${client.sessionId}`);
|
debugRoom(`player realy level :${client.sessionId}, try add robot`);
|
||||||
this.state.players.delete(client.sessionId);
|
// this.state.players.delete(client.sessionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,17 +133,26 @@ export class GeneralRoom extends Room {
|
|||||||
|
|
||||||
getClient(player: string | Player): Client {
|
getClient(player: string | Player): Client {
|
||||||
let result: Client;
|
let result: Client;
|
||||||
|
let sessionId;
|
||||||
if (typeof player == 'string') {
|
if (typeof player == 'string') {
|
||||||
|
sessionId = player;
|
||||||
result = this.clients.find(client => client.sessionId == player );
|
result = this.clients.find(client => client.sessionId == player );
|
||||||
} else {
|
} else {
|
||||||
|
sessionId = player.id;
|
||||||
result = this.clients.find(client => client.sessionId == player.id );
|
result = this.clients.find(client => client.sessionId == player.id );
|
||||||
}
|
}
|
||||||
if (!result) {
|
if (!result) {
|
||||||
error(`无法获取id为: ${typeof player == 'string' ? player : player.id} 的客户端`)
|
error(`无法获取id为: ${typeof player == 'string' ? player : player.id} 的客户端`);
|
||||||
|
result = this.getAssistClient(sessionId);
|
||||||
|
debugRoom(`启用辅助机器人, 当前机器人状态: ${(result as RobotClient).active}`)
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clientCount(): number {
|
||||||
|
return this.clients.length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 给room.gameClock设定任务
|
* 给room.gameClock设定任务
|
||||||
* gameClock任何时候只有一个可执行的任务
|
* gameClock任何时候只有一个可执行的任务
|
||||||
@ -213,7 +230,9 @@ export class GeneralRoom extends Room {
|
|||||||
let data = {
|
let data = {
|
||||||
host: 'ws://127.0.0.1:2567',
|
host: 'ws://127.0.0.1:2567',
|
||||||
room: this.roomId,
|
room: this.roomId,
|
||||||
|
sessionId: playerId
|
||||||
}
|
}
|
||||||
|
|
||||||
axios.get('http://127.0.0.1:2500/robot/create', {
|
axios.get('http://127.0.0.1:2500/robot/create', {
|
||||||
params: data
|
params: data
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
@ -247,4 +266,13 @@ export class GeneralRoom extends Room {
|
|||||||
// }
|
// }
|
||||||
// this._events.emit('join', client);
|
// this._events.emit('join', client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addAssistClient(sessionId: string) {
|
||||||
|
let client = new RobotClient(sessionId, this.state, this['onMessageHandlers']);
|
||||||
|
this.assistMap.set(sessionId, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAssistClient(sessionId: string): RobotClient {
|
||||||
|
return this.assistMap.get(sessionId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,6 +215,17 @@ Object.defineProperties(Room.prototype, {
|
|||||||
value: function (client: Client, data?: any) {
|
value: function (client: Client, data?: any) {
|
||||||
client && client.send("change_card_s2c", data);
|
client && client.send("change_card_s2c", data);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
send: {
|
||||||
|
value: function (client: Client, type: string, data?: any) {
|
||||||
|
if (client) {
|
||||||
|
client.send(type, data);
|
||||||
|
} else {
|
||||||
|
let assistClient = this.getAssistClient(client.sessionId);
|
||||||
|
assistClient && assistClient.send(type, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -21,8 +21,8 @@ export class BeginGameCommand extends Command<CardGameState, {}> {
|
|||||||
let cardAll = card0.concat(card1);
|
let cardAll = card0.concat(card1);
|
||||||
arrUtil.randomSort(cardAll);
|
arrUtil.randomSort(cardAll);
|
||||||
this.state.cardQueue = cardAll;
|
this.state.cardQueue = cardAll;
|
||||||
for (let client of this.room.clients) {
|
for (let [id] of this.state.players) {
|
||||||
this.room.addCard(client.sessionId, singleton(GameEnv).initCardNum, 0);
|
this.room.addCard(id, singleton(GameEnv).initCardNum, 0);
|
||||||
}
|
}
|
||||||
this.state.updateGameState(GameStateConst.STATE_CHANGE_CARD);
|
this.state.updateGameState(GameStateConst.STATE_CHANGE_CARD);
|
||||||
// 超时后结束换卡, 进入下一轮
|
// 超时后结束换卡, 进入下一轮
|
||||||
|
@ -24,15 +24,15 @@ export class DiscardCommand extends Command<CardGameState, { client: Client, car
|
|||||||
execute({ client, cards , dtype} = this.payload) {
|
execute({ client, cards , dtype} = this.payload) {
|
||||||
const player = this.state.players.get(client.sessionId);
|
const player = this.state.players.get(client.sessionId);
|
||||||
if (!player) {
|
if (!player) {
|
||||||
client && client.send('discard_card_s2c', {errcode: 1, errmsg: 'player不存在'});
|
this.room.send(client,'discard_card_s2c', {errcode: 1, errmsg: 'player不存在'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!gameUtil.checkCardsExists(player.cards, cards)) {
|
if (!gameUtil.checkCardsExists(player.cards, cards)) {
|
||||||
client && client.send('discard_card_s2c', {errcode: 2, errmsg: '要出的牌在手牌中不存在'});
|
this.room.send(client,'discard_card_s2c', {errcode: 2, errmsg: '要出的牌在手牌中不存在'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.state.currentTurn != client.sessionId) {
|
if (this.state.currentTurn != client.sessionId) {
|
||||||
client && client.send('discard_card_s2c', {errcode: 3, errmsg: '不是当前轮'});
|
this.room.send(client,'discard_card_s2c', {errcode: 3, errmsg: '不是当前轮'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let tmpCards = [];
|
let tmpCards = [];
|
||||||
@ -40,7 +40,7 @@ export class DiscardCommand extends Command<CardGameState, { client: Client, car
|
|||||||
tmpCards.push(player.cards.get(id + ''));
|
tmpCards.push(player.cards.get(id + ''));
|
||||||
}
|
}
|
||||||
if (!gameUtil.checkDiscard(tmpCards)) {
|
if (!gameUtil.checkDiscard(tmpCards)) {
|
||||||
client && client.send('discard_card_s2c', {errcode: 4, errmsg: '出牌不符合规则'});
|
this.room.send(client,'discard_card_s2c', {errcode: 4, errmsg: '出牌不符合规则'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (let [key, val] of this.state.cards) {
|
for (let [key, val] of this.state.cards) {
|
||||||
@ -65,7 +65,7 @@ export class DiscardCommand extends Command<CardGameState, { client: Client, car
|
|||||||
* 如果出一张牌的话, 进入胡牌轮
|
* 如果出一张牌的话, 进入胡牌轮
|
||||||
* 否则直接进入选随从轮
|
* 否则直接进入选随从轮
|
||||||
*/
|
*/
|
||||||
client && client.send('discard_card_s2c', {errcode: 0, cards: cards, type: dtype})
|
this.room.send(client,'discard_card_s2c', {errcode: 0, cards: cards, type: dtype})
|
||||||
if (cards.length === 1) {
|
if (cards.length === 1) {
|
||||||
let cardArr: Card[] = [...this.state.cards.values()];
|
let cardArr: Card[] = [...this.state.cards.values()];
|
||||||
this.room.battleMan.onCardDiscarded(player, cardArr[0])
|
this.room.battleMan.onCardDiscarded(player, cardArr[0])
|
||||||
@ -79,7 +79,7 @@ export class DiscardCommand extends Command<CardGameState, { client: Client, car
|
|||||||
this.room.battleMan.onCardLinkOver(player, cardArr);
|
this.room.battleMan.onCardLinkOver(player, cardArr);
|
||||||
this.state.updateGameState(GameStateConst.STATE_PICK_PET);
|
this.state.updateGameState(GameStateConst.STATE_PICK_PET);
|
||||||
let self = this;
|
let self = this;
|
||||||
client && client.send('eat_card_s2c', {player: player.id, errcode: 0, errmsg: ''});
|
this.room.send(client,'eat_card_s2c', {player: player.id, errcode: 0, errmsg: ''});
|
||||||
let time = singleton(GameEnv).playerActTime * 1000 + player.extraTime;
|
let time = singleton(GameEnv).playerActTime * 1000 + player.extraTime;
|
||||||
// 开启选随从计时, 计时结束后结束当前轮
|
// 开启选随从计时, 计时结束后结束当前轮
|
||||||
let timeOverSelectPet = function () {
|
let timeOverSelectPet = function () {
|
||||||
|
@ -12,19 +12,19 @@ export class EatCardCommand extends Command<CardGameState, { client: Client, car
|
|||||||
execute({ client, cards, target } = this.payload) {
|
execute({ client, cards, target } = this.payload) {
|
||||||
const player = this.state.players.get(client.sessionId);
|
const player = this.state.players.get(client.sessionId);
|
||||||
if (!player) {
|
if (!player) {
|
||||||
client && client.send('eat_card_s2c', {errcode: 1, errmsg: 'player不存在或者'});
|
this.room.send(client,'eat_card_s2c', {errcode: 1, errmsg: 'player不存在或者'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!gameUtil.checkCardsExists(player.cards, cards)) {
|
if (!gameUtil.checkCardsExists(player.cards, cards)) {
|
||||||
client && client.send('eat_card_s2c', {errcode: 2, errmsg: '要出的牌在手牌中不存在'});
|
this.room.send(client,'eat_card_s2c', {errcode: 2, errmsg: '要出的牌在手牌中不存在'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.state.currentTurn == client.sessionId) {
|
if (this.state.currentTurn == client.sessionId) {
|
||||||
client && client.send('eat_card_s2c', {errcode: 3, errmsg: '不能吃自己的牌'});
|
this.room.send(client,'eat_card_s2c', {errcode: 3, errmsg: '不能吃自己的牌'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.state.cards.has(target + '')) {
|
if (!this.state.cards.has(target + '')) {
|
||||||
client && client.send('eat_card_s2c', {errcode: 4, errmsg: '找不到要吃的牌'});
|
this.room.send(client,'eat_card_s2c', {errcode: 4, errmsg: '找不到要吃的牌'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let tmpCards = [];
|
let tmpCards = [];
|
||||||
@ -33,16 +33,16 @@ export class EatCardCommand extends Command<CardGameState, { client: Client, car
|
|||||||
}
|
}
|
||||||
tmpCards.push(this.state.cards.get(target + ''));
|
tmpCards.push(this.state.cards.get(target + ''));
|
||||||
if (!gameUtil.checkDiscard(tmpCards)) {
|
if (!gameUtil.checkDiscard(tmpCards)) {
|
||||||
client && client.send('discard_card_s2c', {errcode: 5, errmsg: '不符合吃牌规则'});
|
this.room.send(client,'discard_card_s2c', {errcode: 5, errmsg: '不符合吃牌规则'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.state.gameState !== GameStateConst.STATE_BEGIN_EAT) {
|
if (this.state.gameState !== GameStateConst.STATE_BEGIN_EAT) {
|
||||||
client && client.send('discard_card_s2c', {errcode: 7, errmsg: '不是吃牌轮'});
|
this.room.send(client,'discard_card_s2c', {errcode: 7, errmsg: '不是吃牌轮'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//将吃牌数据临时保存
|
//将吃牌数据临时保存
|
||||||
if (this.state.tmpActionMap.has(client.sessionId)) {
|
if (this.state.tmpActionMap.has(client.sessionId)) {
|
||||||
client && client.send('discard_card_s2c', {errcode: 8, errmsg: '不可更改操作'});
|
this.room.send(client,'discard_card_s2c', {errcode: 8, errmsg: '不可更改操作'});
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
this.state.tmpActionMap.set(client.sessionId, cards);
|
this.state.tmpActionMap.set(client.sessionId, cards);
|
||||||
|
@ -101,12 +101,12 @@ export class EatConfirmCommand extends Command<CardGameState, { timeUp: boolean
|
|||||||
// 成功后广播吃牌成功消息
|
// 成功后广播吃牌成功消息
|
||||||
let client = this.room.getClient(player.id);
|
let client = this.room.getClient(player.id);
|
||||||
this.room.broadcast('eat_card_s2c', {player: player.id, errcode: 0, errmsg: ''}, {except: client});
|
this.room.broadcast('eat_card_s2c', {player: player.id, errcode: 0, errmsg: ''}, {except: client});
|
||||||
client && client.send('eat_card_s2c', {player: player.id, errcode: 0, errmsg: ''});
|
this.room.send(client,'eat_card_s2c', {player: player.id, errcode: 0, errmsg: ''});
|
||||||
// 向其他玩家发送吃卡失败的消息
|
// 向其他玩家发送吃卡失败的消息
|
||||||
for (let [key, val] of tmpActionMap) {
|
for (let [key, val] of tmpActionMap) {
|
||||||
if (typeof val != 'number' && key !== player.id) {
|
if (typeof val != 'number' && key !== player.id) {
|
||||||
let client = this.room.getClient(key);
|
let client = this.room.getClient(key);
|
||||||
client && client.send('eat_card_s2c', {errcode: 9, errmsg: '吃卡失败'});
|
this.room.send(client,'eat_card_s2c', {errcode: 9, errmsg: '吃卡失败'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!player && timeUp) {
|
} else if (!player && timeUp) {
|
||||||
|
@ -50,7 +50,7 @@ export class GMCommand extends Command<CardGameState, {client: Client, message:
|
|||||||
str += '更新英雄血量: herohp:玩家index|血量 例: herohp:0|500 \n';
|
str += '更新英雄血量: herohp:玩家index|血量 例: herohp:0|500 \n';
|
||||||
str += '生成几张特定效果的卡: addcard:玩家index|效果卡id|数量 例: addcard:0|20011|1\n';
|
str += '生成几张特定效果的卡: addcard:玩家index|效果卡id|数量 例: addcard:0|20011|1\n';
|
||||||
str += '将某一队设为赢家: setwin:队伍index 例: setwin:0\n';
|
str += '将某一队设为赢家: setwin:队伍index 例: setwin:0\n';
|
||||||
client && client.send('notice_msg', str);
|
this.room.send(client,'notice_msg', str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,7 +60,7 @@ export class GMCommand extends Command<CardGameState, {client: Client, message:
|
|||||||
*/
|
*/
|
||||||
addRobot(msg:string) {
|
addRobot(msg:string) {
|
||||||
let count = msg ? parseInt(msg) : 1;
|
let count = msg ? parseInt(msg) : 1;
|
||||||
let count2 = this.room.maxClients - this.room.clients.length;
|
let count2 = this.room.maxClients - this.room.clientCount();
|
||||||
for (let i = 0; i< Math.min(count, count2); i++) {
|
for (let i = 0; i< Math.min(count, count2); i++) {
|
||||||
this.room.addRobot();
|
this.room.addRobot();
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ export class GMCommand extends Command<CardGameState, {client: Client, message:
|
|||||||
card.effect = effectId;
|
card.effect = effectId;
|
||||||
}
|
}
|
||||||
let client = this.room.getClient(player.id);
|
let client = this.room.getClient(player.id);
|
||||||
client && client.send('sync_card', {}, {afterNextPatch: true});
|
this.room.send(client,'sync_card', {}, {afterNextPatch: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,7 +82,7 @@ export class GameResultCommand extends Command<CardGameState, {}> {
|
|||||||
await self.room.setPrivate(false);
|
await self.room.setPrivate(false);
|
||||||
//开启匹配定时, 长时间没匹配到人的话, 添加机器人
|
//开启匹配定时, 长时间没匹配到人的话, 添加机器人
|
||||||
let timeOutWaitingPlayer = function () {
|
let timeOutWaitingPlayer = function () {
|
||||||
let count = self.room.maxClients - self.room.clients.length;
|
let count = self.room.maxClients - self.room.clientCount();
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
self.room.addRobot();
|
self.room.addRobot();
|
||||||
|
@ -17,11 +17,12 @@ export class OnJoinCommand extends Command<CardGameState, {
|
|||||||
// 实际的team会在PlayReadyCommand中设置
|
// 实际的team会在PlayReadyCommand中设置
|
||||||
let player = new Player(client.sessionId, 0, team);
|
let player = new Player(client.sessionId, 0, team);
|
||||||
this.state.players.set(client.sessionId, player);
|
this.state.players.set(client.sessionId, player);
|
||||||
|
this.room.addAssistClient(client.sessionId);
|
||||||
let self = this;
|
let self = this;
|
||||||
if (this.room.clients.length == 1) {
|
if (this.room.clientCount() == 1) {
|
||||||
// 正常的匹配逻辑进入的第一个玩家, 开启定时, 超过设定时间人没齐的话, 添加机器人
|
// 正常的匹配逻辑进入的第一个玩家, 开启定时, 超过设定时间人没齐的话, 添加机器人
|
||||||
let timeOutWaitingPlayer = function () {
|
let timeOutWaitingPlayer = function () {
|
||||||
let count = self.room.maxClients - self.room.clients.length;
|
let count = self.room.maxClients - self.room.clientCount();
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
self.room.addRobot();
|
self.room.addRobot();
|
||||||
@ -30,7 +31,7 @@ export class OnJoinCommand extends Command<CardGameState, {
|
|||||||
}
|
}
|
||||||
let time = singleton(GameEnv).waitingPlayerTime * 1000;
|
let time = singleton(GameEnv).waitingPlayerTime * 1000;
|
||||||
self.room.beginSchedule(time, timeOutWaitingPlayer, 'waiting_player');
|
self.room.beginSchedule(time, timeOutWaitingPlayer, 'waiting_player');
|
||||||
} else if (this.room.clients.length > 1 && this.room.clients.length < this.room.maxClients) {
|
} else if (this.room.clientCount() > 1 && this.room.clientCount() < this.room.maxClients) {
|
||||||
let moreTime = singleton(GameEnv).waitingPlayerOnePlus * 1000;
|
let moreTime = singleton(GameEnv).waitingPlayerOnePlus * 1000;
|
||||||
self.room.addScheduleTime(moreTime, 'play_join', 'waiting_player')
|
self.room.addScheduleTime(moreTime, 'play_join', 'waiting_player')
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ export class PrepareCommand extends Command<CardGameState, {}> {
|
|||||||
this.state.updateGameState(GameStateConst.DETERMINE_TURN);
|
this.state.updateGameState(GameStateConst.DETERMINE_TURN);
|
||||||
let time = 3000;
|
let time = 3000;
|
||||||
//TODO:: 每人发2张牌, 并比较大小, 确定先手
|
//TODO:: 每人发2张牌, 并比较大小, 确定先手
|
||||||
for (let client of this.room.clients) {
|
for (let client of this.state.players) {
|
||||||
|
|
||||||
// this.room.broadcast();
|
// this.room.broadcast();
|
||||||
}
|
}
|
||||||
|
222
src/utils/assistant.util.ts
Normal file
222
src/utils/assistant.util.ts
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
import {Card} from "../rooms/schema/Card";
|
||||||
|
import arrUtil from "./array.util";
|
||||||
|
import {EffectCardCfg} from "../cfg/parsers/EffectCardCfg";
|
||||||
|
import {BaseConst} from "../constants/BaseConst";
|
||||||
|
import {SkillTargetType} from "../rooms/logic/skill/SkillConst";
|
||||||
|
import CfgMan from "../rooms/logic/CfgMan";
|
||||||
|
import {CardGameState} from "../rooms/schema/CardGameState";
|
||||||
|
import {Player} from "../rooms/schema/Player";
|
||||||
|
import {HeroCfg} from "../cfg/parsers/HeroCfg";
|
||||||
|
|
||||||
|
let assistantUtil = {
|
||||||
|
delay(max: number, min?: number) {
|
||||||
|
min = min || 0;
|
||||||
|
let milliseconds = (Math.random() * (max - min) + min) * 1000 | 0;
|
||||||
|
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 检查是否可以吃牌
|
||||||
|
* @param cardArr 待检查的卡组
|
||||||
|
* @param card 目标牌
|
||||||
|
*/
|
||||||
|
checkTriple(cardArr: Card[], card?: Card): Card[] {
|
||||||
|
if (card) cardArr.push(card);
|
||||||
|
let pointMap: Map<number, Card[]> = new Map();
|
||||||
|
let cardIdSet: Set<number> = new Set();
|
||||||
|
for (let c of cardArr) {
|
||||||
|
if (c.type !== 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pointMap.has(c.number)) {
|
||||||
|
let arr = pointMap.get(c.number);
|
||||||
|
arr.push(c);
|
||||||
|
pointMap.set(c.number, arr);
|
||||||
|
} else {
|
||||||
|
pointMap.set(c.number, [c]);
|
||||||
|
}
|
||||||
|
cardIdSet.add(c.number);
|
||||||
|
}
|
||||||
|
let fetched = false;
|
||||||
|
let result: Card[] = [];
|
||||||
|
// 优先出对子
|
||||||
|
for (let [point, arr] of pointMap) {
|
||||||
|
if (card) {
|
||||||
|
if (point == card.number && arr.length >= 3) {
|
||||||
|
fetched = true;
|
||||||
|
result = arr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (arr.length >= 3) {
|
||||||
|
fetched = true;
|
||||||
|
result = arr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (fetched) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cardIds = [...cardIdSet];
|
||||||
|
cardIds.sort((a, b) => a - b);
|
||||||
|
let tmp = [];
|
||||||
|
for (let i = 0, length = cardIds.length; i < length; i++) {
|
||||||
|
let cur = cardIds[i];
|
||||||
|
i == 0 && tmp.push(cur);
|
||||||
|
if (i > 0) {
|
||||||
|
if (cur != tmp[i - 1] + 1) {
|
||||||
|
tmp.length = 0;
|
||||||
|
}
|
||||||
|
tmp.push(cur);
|
||||||
|
}
|
||||||
|
if (card) {
|
||||||
|
if (tmp.indexOf(card.number) >= 0 && tmp.length >= 3) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (tmp.length >= 3) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp.length >= 3) {
|
||||||
|
let subTmp = [];
|
||||||
|
for (let i = tmp[0] - 1; i > 0; i--) {
|
||||||
|
if (cardIdSet.has(i)) {
|
||||||
|
subTmp.push(i);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = tmp[tmp.length]; i < cardIdSet.size; i++) {
|
||||||
|
if (cardIdSet.has(i)) {
|
||||||
|
subTmp.push(i);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp = tmp.concat(subTmp);
|
||||||
|
for (let point of tmp) {
|
||||||
|
if (card && point === card.number) {
|
||||||
|
result.push(card);
|
||||||
|
} else {
|
||||||
|
result.push(pointMap.get(point)[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return arrUtil.randomGet(cardArr, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 随机获取敌对玩家
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
getEnemyPlayer(dstPlayer: Player, state: CardGameState): Player {
|
||||||
|
let enemys = [];
|
||||||
|
for (let [, player] of state.players) {
|
||||||
|
if (player.team !== dstPlayer.team) {
|
||||||
|
enemys.push(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arrUtil.randomOne(enemys);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机获取可用的随从
|
||||||
|
* @param player
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
getRandomPet(player: Player): number {
|
||||||
|
let pets = [];
|
||||||
|
for (let [, pet] of player.pets) {
|
||||||
|
if (pet.ap > 0 && pet.state == 1)
|
||||||
|
pets.push(pet);
|
||||||
|
}
|
||||||
|
let result;
|
||||||
|
if (pets.length > 0) {
|
||||||
|
result = arrUtil.randomOne(pets);
|
||||||
|
}
|
||||||
|
return result ? result.pos : -1;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 选择一个法术或者一个随从
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
async selectPet(dstPlayer: Player, state: CardGameState) {
|
||||||
|
await this.delay(5, 0.2);
|
||||||
|
let cards = [...state.cards.values()];
|
||||||
|
let result;
|
||||||
|
let effectMap: Map<number, EffectCardCfg> = global.$cfg.get(BaseConst.EFFECTCARD);
|
||||||
|
for (let card of cards) {
|
||||||
|
let effect = effectMap.get(card.effect);
|
||||||
|
if (effect.type_id == 1) {
|
||||||
|
result = card;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!result) {
|
||||||
|
result = arrUtil.randomGet(cards, 1)[0];
|
||||||
|
}
|
||||||
|
let targetType: SkillTargetType = CfgMan.getTargetByCard(result.effect);
|
||||||
|
let targetPlayer;
|
||||||
|
let targetPos;
|
||||||
|
switch (targetType) {
|
||||||
|
case SkillTargetType.ENEMY_PLAYER:
|
||||||
|
targetPlayer = this.getEnemyPlayer(dstPlayer, state);
|
||||||
|
break;
|
||||||
|
case SkillTargetType.ENEMY_PET:
|
||||||
|
for (let [, player] of state.players) {
|
||||||
|
if (player.team !== dstPlayer.team) {
|
||||||
|
let pos = this.getRandomPet(player);
|
||||||
|
if (pos > -1) {
|
||||||
|
targetPlayer = player;
|
||||||
|
targetPos = pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SkillTargetType.FRIEND_PET:
|
||||||
|
for (let [, player] of state.players) {
|
||||||
|
if (player.team == dstPlayer.team) {
|
||||||
|
let pos = this.getRandomPet(player);
|
||||||
|
if (pos > -1) {
|
||||||
|
targetPlayer = player;
|
||||||
|
targetPos = pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SkillTargetType.SELF_PET:
|
||||||
|
let pos = this.getRandomPet(dstPlayer);
|
||||||
|
if (pos > -1) {
|
||||||
|
targetPlayer = dstPlayer;
|
||||||
|
targetPos = pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//TODO: 增加效果卡
|
||||||
|
let effCards: number[] = [];
|
||||||
|
return {
|
||||||
|
card: result.id,
|
||||||
|
player: targetPlayer?.id,
|
||||||
|
pos: targetPos,
|
||||||
|
effCards
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
randomHero() {
|
||||||
|
let heroMap: Map<number, HeroCfg> = global.$cfg.get(BaseConst.HERO);
|
||||||
|
let heroArr = [...heroMap.values()];
|
||||||
|
let hero = arrUtil.randomGet(heroArr, 1);
|
||||||
|
return {heroId: hero[0].id}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default assistantUtil;
|
@ -255,7 +255,8 @@ let gameUtil = {
|
|||||||
result += pet.ap;
|
result += pet.ap;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
},
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
export default gameUtil;
|
export default gameUtil;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user