import DataMgr from "../data/DataMgr"; import { RESET_GAME } from "../data/Define"; import TalkMgr from "../game/TalkMgr"; import { UIGame } from "../UI/UIGame"; import { xGame } from "../xGame"; import D2BallSrc from "./D2BallSrc"; import D2RootBallSrc from "./D2RootBallSrc"; enum AIState { none = 0, idle, //闲置状态(对方击球) reset, //重置母球 move, //移动母球 wait, // select, //选择 turn, //调整杆的角度 shoot, //击球 leave, //离线 } export default class AIPlayer { private dtime: number = 30; private gameSrc: UIGame; private awayTime: number = 0; private awayNum: number = 0; private hideTime: number = 0; private rootMoveTime: number = 0; private isGuide: boolean = false; private tempDir1: Laya.Vector2; private tempDir2: Laya.Vector2; private tempDir3: Laya.Vector2; private state = AIState.none; private waitTime = 0; private forceNum = 0; private forceMax = 0; private ballSize = 33; //选取次数 private selectNum = 0; //球杆旋转值 private destRot = 0; //AI等级(1-10) private aiLv = 10; //可以打的球 private kickBall: D2BallSrc[] = []; //可以直线打的球 private lineBall: D2BallSrc[] = [] //可以直接进袋的球 private scoreBall: D2BallSrc[] = []; //与袋口没阻挡的球 private holeBall: D2BallSrc[] = []; //调杆次数 private turnNum: number = 0; private setNum: number = 0; private setMax: number = 0; private setRate: number = 0; //球边界坐标 public rectL: number = 0; public rectR: number = 0; public rectT: number = 0; public rectB: number = 0; private wBall: D2RootBallSrc; private rootPos = { x: 0, y: 0 }; private bestForce = 0; private bestAngle = 180; private bestPos = { x: 0, y: 0 }; private bestKick = { x: 0, y: 0 }; private posList = []; private posIdx: number = 0; private chatTime: number = 3000; constructor() { this.tempDir1 = new Laya.Vector2(); this.tempDir2 = new Laya.Vector2(); this.tempDir3 = new Laya.Vector2(); Laya.timer.loop(this.dtime, this, this.onUpdate); xGame.eventMgr.off(RESET_GAME, this, this.resetAI); xGame.eventMgr.on(RESET_GAME, this, this.resetAI); this.gameSrc = xGame.common.gameUI; this.hideTime = Laya.timer.currTimer; Moyu.setOnTipCall((id) => { if (id == 20012) this.hideTime = Laya.timer.currTimer; else (id == 20011) { let dt = Laya.timer.currTimer - this.hideTime; console.log("onshow" + dt); if (dt > 30000 && this.state > AIState.none) xGame.common.gameMgr.aiGameEnd(false); } }, this) } public init() { let ggg = 1; if (DataMgr.getGuideDefaultModel() === 1) { ggg = DataMgr.getLianXiGuide(); } else { ggg = DataMgr.getSkillGuide(); } this.isGuide = ggg < 1 || DataMgr.gameData.gameCount < 1; this.awayTime = xGame.tools.random(5000, 10000); this.awayNum = 0; this.hideTime = Laya.timer.currTimer; let rect = xGame.common.d2World.borderRect; this.rectL = Math.ceil(rect.x) + 17; this.rectT = Math.ceil(rect.y) + 17; this.rectR = Math.floor(rect.x + rect.width) - 17; this.rectB = Math.floor(rect.y + rect.height) - 17; this.wBall = xGame.common.d2World.rootBall; //母球 this.ballSize = this.wBall.gameObj.width - 1; if (this.posList.length < 1) { let dp = 40; for (let i = this.rectL; i < this.rectR + dp; i = i + dp) { for (let j = this.rectT; j < this.rectB + dp; j = j + dp) { let dx = i < this.rectR ? i : this.rectR; let dy = j < this.rectB ? j : this.rectB; let order = xGame.tools.random(0, 1000); this.posList.push({ x: dx, y: dy, order: order }); } } this.posList.sort(function (a, b) { return a.order - b.order; }); this.setMax = this.posList.length; } this.state = AIState.idle; } public setAiLevel(num) { this.aiLv = num; } //计算可打的球 initBall() { //this.aiLv = xGame.tools.random(1, 11); //console.log("AI等级" + this.aiLv); this.rootPos.x = this.wBall.gameObj.x; this.rootPos.y = this.wBall.gameObj.y; this.initHoleBall(); } initHoleBall() { this.kickBall = []; this.lineBall = [] this.scoreBall = []; this.holeBall = []; this.selectNum = 0; this.forceNum = 0; this.forceMax = 0; this.turnNum = 0; let list = xGame.common.d2World.ballArr; if (list.length < 20 && !this.isGuide) //大招模式球太多时随机选择 { let holes = xGame.common.gameMgr.holePosList; for (let i = 0; i < list.length; i++) { let obj = list[i]; if (!obj) continue; //重置前面计算了的参数 obj.kickPos.x = 0; obj.kickPos.y = 0; obj.poleAngle = 0; obj.hard = 0; obj.borderDis = 0; obj.kickAngle = 180; if (obj.number == 0) //母球 continue; if (obj.ballType == xGame.common.gameMgr.selfCamp) //对方球 continue; if (obj.number == 8 && xGame.common.gameMode == 0) { if (xGame.common.gameMgr.aiBallArr.length > 0 || !xGame.common.gameMgr.ensureBallType) continue; } let b = obj.gameObj; let wbp = this.rootPos; let bx = wbp.x - b.x; let by = wbp.y - b.y; obj.borderDis = xGame.tools.random(0, 100); this.kickBall.push(obj); //与母球之间有其他球 if (!this.isLine(wbp, obj)) continue; obj.kickAngle = xGame.tools.random(90, 180); obj.kickPos.x = b.x; obj.kickPos.y = b.y; this.lineBall.push(obj); let minDis = 999999; let hole = false; for (let j = 0; j < holes.length; j++) { let hp = holes[j]; //袋口方向不对 if (bx >= 0 && hp.x > b.x + 100) continue; if (bx <= 0 && hp.x < b.x - 100) continue; if (by < -10 && hp.y < wbp.y) continue; if (by > 10 && hp.y > wbp.y) continue; //与袋口之间没有球 if (!this.isBlock(obj.number, b.x, b.y, hp.x, hp.y)) { let dis = xGame.tools.getDeltaxy(b.x, b.y, hp.x, hp.y); if (dis < minDis) { let dx = b.x - this.tempDir1.x * this.ballSize; let dy = b.y - this.tempDir1.y * this.ballSize; this.tempDir3.x = this.tempDir1.x; this.tempDir3.y = this.tempDir1.y; if (!this.isBlock(this.wBall.number, wbp.x, wbp.y, dx, dy, obj.number)) //进球路线上没有其他球 { obj.kickPos.x = dx; obj.kickPos.y = dy; let num = Laya.Vector2.dot(this.tempDir1, this.tempDir3); if (num > 1) num = 1; obj.kickAngle = Math.acos(num) * 57.3; //库边球难度加大 if (b.x < this.rectL + 2 || b.x > this.rectR - 2 || b.y < this.rectT + 2 || b.y > this.rectB - 2) dis = dis * 2; //中袋球难度加大 if (Math.abs(hp.x - 600) < 100) dis += 50; obj.hard = dis + obj.kickAngle * 3; hole = true; } } } } if (hole) { this.scoreBall.push(obj); this.holeBall.push(obj); } } this.scoreBall.sort(function (a, b) { return a.hard - b.hard; }); this.holeBall.sort(function (a, b) { return a.kickAngle - b.kickAngle; }); this.kickBall.sort(function (a, b) { return a.borderDis - b.borderDis; }); } else { let max = list.length - 1; let i = xGame.tools.random(0, max); for (i; i <= max; i++) { let idx = i >= max ? i -= max : i; let obj = list[idx]; if (obj && obj.number != 0) { obj.kickAngle = xGame.tools.random(90, 180); obj.kickPos.x = obj.gameObj.x + xGame.tools.random(-10, 10); obj.kickPos.y = obj.gameObj.y + xGame.tools.random(-10, 10); this.lineBall.push(obj); break; } } } } selectBall() { let ball: D2BallSrc = null; this.destRot = 0; let max = this.isGuide ? 1 : 3 - Math.ceil(this.aiLv / 4) + xGame.tools.random(0, 2); //let wb=xGame.common.d2World.rootBall; let ai = 110 - this.aiLv * 10; let mis = xGame.tools.random(-ai, ai) * 0.005; let score = false; //没有可以直接进袋的球 if (this.scoreBall.length < 1) { if (this.lineBall.length < 1) { for (let i = 0; i < this.kickBall.length; i++) { let list = []; let bo = this.kickBall[i]; let bobj = bo.gameObj; let rect = xGame.common.d2World.borderRect; let mobj = this.wBall.gameObj; //上边库 let minb = bobj.y - rect.y - 20; let minw = mobj.y - rect.y - 50; if (minb > 0 && minw > 0) { let dlenx = 0; let dleny = mobj.y - rect.y; let spx = mobj.x; let spy = rect.y - dleny; list.push({ order: minb, bx: 0, by: rect.y, spx: spx, spy: spy, dlenx: dlenx, dleny: dleny }); } //下边库 minb = rect.y + rect.height - bobj.y - 20 minw = rect.y + rect.height - mobj.y - 50; if (minb > 0 && minw > 0) { let dlenx = 0; let dleny = rect.y + rect.height - mobj.y; let spx = mobj.x; let spy = rect.y + rect.height + dleny; list.push({ order: minb, bx: 0, by: rect.y + rect.height, spx: spx, spy: spy, dlenx: dlenx, dleny: dleny }); } //左边库 minb = bobj.x - rect.x - 20; minw = mobj.x - rect.x - 50; if (minb > 0 && minw > 0) { let dlenx = mobj.x - rect.x; let dleny = 0; let spx = rect.x - dlenx; let spy = mobj.y; list.push({ order: minb, bx: rect.x, by: 0, spx: spx, spy: spy, dlenx: dlenx, dleny: dleny }); } //右边库 minb = rect.x + rect.width - bobj.x - 20; minw = rect.x + rect.width - mobj.x - 50; if (minb > 0 && minw > 0) { let dlenx = rect.x + rect.width - mobj.x; let dleny = 0; let spx = rect.x + rect.width + dlenx; let spy = mobj.y; list.push({ order: minb, bx: rect.x + rect.width, by: 0, spx: spx, spy: spy, dlenx: dlenx, dleny: dleny }); } //按距边排序 list.sort(function (a, b) { return a.order - b.order; }); for (let i = 0; i < list.length; i++) { let data = list[i]; let mx = mobj.x - bobj.x; let my = mobj.y - bobj.y; xGame.tools.getV2Dir(data.spx, data.spy, bobj.x, bobj.y, this.tempDir1); xGame.tools.getV2Dir(data.spx, data.spy, mobj.x, mobj.y, this.tempDir2); let num = Laya.Vector2.dot(this.tempDir1, this.tempDir2); if (num > 1) num = 1; let cos = Math.acos(num); if (cos > 1.57) cos = 1.57; else if (cos < 0.01) cos = 0.01; let tan = Math.tan(cos); let dx = tan * data.dleny; let dy = tan * data.dlenx; let bx = data.bx > 0 ? data.bx : (mobj.x + (mx > 0 ? -dx : dx)); if (Math.abs(bx - 667) < 40) //避开中袋 continue; let by = data.by > 0 ? data.by : (mobj.y + (my > 0 ? -dy : dy)); if (!this.isBlock(0, mobj.x, mobj.y, bx, by) && !this.isBlock(bo.number, bobj.x, bobj.y, bx, by)) { let dis = Math.abs(data.dlenx) + Math.abs(data.dleny) + xGame.tools.getDistance(bx, by, bo.gameObj.x, bo.gameObj.y); this.forceMax = dis * 0.08; this.destRot += mis * 0.1; this.setKick(bx, by); return true; } } } } else { ball = xGame.common.getRandArrEle(this.lineBall); } } else { for (let i = 0; i < this.scoreBall.length; i++) { if (i < this.scoreBall.length - 1) { let rand = 70 + this.aiLv * 10 + i * 10; if (xGame.tools.random(0, 100) < rand) { ball = this.scoreBall[i]; break; } } else { ball = this.scoreBall[i]; break; } } score = true; this.selectNum++; } if (!ball) ball = xGame.common.getRandArrEle(xGame.common.d2World.ballArr); //选取完成 if (this.selectNum >= max) { console.log('zh:jian kong bug1'); if (ball && ball.gameObj) { // 安全访问ball.gameObj的属性 } else { console.log('zh:jian kong bug2 如果到这里应该能看到一个alert弹框报错'); } let dx = ball.gameObj.x; let dy = ball.gameObj.y; let kickAngle = 0; //击球夹角 if (score) { dx = ball.kickPos.x; dy = ball.kickPos.y; this.tempDir2 = xGame.tools.getV2Dir(this.wBall.gameObj.x, this.wBall.gameObj.y, dx, dy, this.tempDir2); this.tempDir3 = xGame.tools.getV2Dir(dx, dy, ball.gameObj.x, ball.gameObj.y, this.tempDir3); let adot = Laya.Vector2.dot(this.tempDir3, this.tempDir2); if (adot > 1) adot = 1; kickAngle = Math.acos(adot) * 57.3; if (kickAngle > 45) //大角度的失误不往球外偏移 { let kdx = ball.kickPos.x - ball.gameObj.x; let kdy = ball.kickPos.y - ball.gameObj.y; dx = ball.kickPos.x - kdx * mis * 0.3; dy = ball.kickPos.y - kdy * mis * 0.3; } else this.destRot += mis; } else if (ball.poleAngle != 0) //插边球 { this.destRot += ball.poleAngle; } if (xGame.common.gameMode == 0) { let af = kickAngle * 0.08; this.forceMax = ball.hard * 0.1 + af * af; } this.setKick(dx, dy); } else //模拟多次选择 { let rand = this.aiLv * 5 + 40; if (xGame.tools.random(0, 100) < rand && this.scoreBall.length > 0) ball = xGame.common.getRandArrEle(this.scoreBall); else ball = xGame.common.getRandArrEle(xGame.common.d2World.ballArr); rand = this.aiLv * 3 + 40 + this.selectNum * 20; if (xGame.tools.random(0, 100) > rand) { this.selectNum = max; } this.setState(AIState.select, xGame.tools.random(500, 1000)); this.selectNum++; } ball.onClick(0, true); } isBlock(bn, bx, by, hx, hy, dn = -1) { this.tempDir1 = xGame.tools.getV2Dir(bx, by, hx, hy, this.tempDir1); let balls = xGame.common.d2World.ballArr; let max = xGame.tools.getDis(hx, hy, bx, by); for (let index = 0; index < balls.length; index++) { let obj = balls[index]; if (obj.number == 0) //母球 continue; if (obj.number == bn || obj.number == dn) //自己 continue; //其他球与该球的方向距离 let dis = xGame.tools.getDistance(obj.gameObj.x, obj.gameObj.y, bx, by); // if(bn==0) // dis=obj.getDis(this.wBall); // else // dis= if (dis * dis > max) continue; this.tempDir2 = xGame.tools.getV2Dir(bx, by, obj.gameObj.x, obj.gameObj.y, this.tempDir2); let num = Laya.Vector2.dot(this.tempDir1, this.tempDir2); if (num > 1) num = 1; if (num < 0) //大于90 continue; let gap = Math.sin(Math.acos(num)) * dis; if (gap < this.ballSize) return true; } return false; } //能否直接打到该球 isLine(xy, ball: D2BallSrc) { let bx = xy.x; let by = xy.y; if (this.isBlock(0, bx, by, ball.gameObj.x, ball.gameObj.y, ball.number)) { let dis = ball.getDestDis(xy); let angle = Math.asin((ball.gameObj.width - 3) / dis); let sin = Math.sin(angle); let cos = Math.cos(angle); this.tempDir3 = xGame.tools.getV2Dir(bx, by, ball.gameObj.x, ball.gameObj.y, this.tempDir3); this.tempDir2.x = this.tempDir3.x * cos - this.tempDir3.y * sin; this.tempDir2.y = this.tempDir3.x * sin + this.tempDir3.y * cos; let dx = bx + this.tempDir2.x * dis; let dy = by + this.tempDir2.y * dis; let isr = this.isBlock(0, bx, by, dx, dy, ball.number); sin = Math.sin(-angle); cos = Math.cos(-angle); this.tempDir2.x = this.tempDir3.x * cos - this.tempDir3.y * sin; this.tempDir2.y = this.tempDir3.x * sin + this.tempDir3.y * cos; dx = bx + this.tempDir2.x * dis; dy = by + this.tempDir2.y * dis; let isl = this.isBlock(0, bx, by, dx, dy, ball.number); if (isr && isl) return false; ball.poleAngle = isr ? -angle * 57.3 : angle * 57.3; } return true; } //调整球杆 turnPole() { //控制调整频率 this.turnNum++; let rot = xGame.common.d2World.d2Gan.ui.rotation % 360; let dr = rot - this.destRot; let abs = Math.abs(dr) % 360; //不转大圈 if (abs > 180) { if (rot > 180) rot -= 360; if (this.destRot > 180) this.destRot -= 360; } let max = this.turnNum * 5 + this.aiLv * 5; if (abs < 0.2 && xGame.tools.random(0, 100) < max) { xGame.common.d2World.d2Gan.rotDest(this.destRot); let at = xGame.tools.random(1000, 2000); if (!this.onAway(3)) at += xGame.tools.random(10000, 15000); this.setState(AIState.shoot, at); //console.log("调杆"+this.turnNum+"次"); } else { let mr = 0; if (abs > 3) mr = 1 + xGame.tools.random(2, 6) * abs * 0.01 else if (Math.random() > 0.6) mr = xGame.tools.random(1, 10) * 0.1 mr = dr > 0 ? -mr : mr; xGame.common.d2World.d2Gan.rotDest(rot + mr); //xGame.common.d2World.d2Gan.rotateSelf(mr); } } //击球方向、力 setKick(dx, dy) { this.forceMax += this.wBall.getDestDis({ x: dx, y: dy }) * 0.1; this.tempDir2 = xGame.tools.getV2Dir(this.wBall.gameObj.x, this.wBall.gameObj.y, dx, dy, this.tempDir2); this.tempDir1.x = 0; this.tempDir1.y = 1; this.tempDir2.y = -this.tempDir2.y; let num = Laya.Vector2.dot(this.tempDir1, this.tempDir2); if (num > 1) num = 1; let rot = Math.acos(num) * 57.3; //0~360 if (this.tempDir2.x < 0) rot = 360 - rot; this.destRot += rot; if (!xGame.common.gameMgr.finishOneShoot) //开球可能额外加力 { this.forceMax += xGame.tools.random(10, 50); this.forceMax -= this.aiLv * 2; // 高级AI低概率大力开球 if (this.forceMax < 20) this.forceMax = 20; } if (this.forceMax > 100) this.forceMax = 101; else if (this.forceMax < 10) this.forceMax += xGame.tools.random(0, 10); if (xGame.common.gameMode == 1) this.forceMax = xGame.tools.random(80, 100); else this.forceMax = xGame.tools.random(this.forceMax * 0.5, this.forceMax); let max = 2000 - this.aiLv * 100; if (Math.random() > 0.8) max += xGame.tools.random(100, 2000); this.setState(AIState.turn, xGame.tools.random(500, max)); } //拉杆击球 shoot() { if (this.waitTime < 0 && Math.abs(this.forceNum - this.forceMax) < 4) { if (Math.random() > 0.8) //拉到位后再有点小延迟 { this.gameSrc.aiForce(1); this.setState(AIState.wait); } } else { let df = xGame.tools.random(3, 8); if (this.forceNum < this.forceMax) this.forceNum += df; else this.forceNum -= df; let startY = this.gameSrc.ui.powerNode.y; let height = this.gameSrc.ui.powerNode.height; // let force = startY + height * this.forceNum * 0.01; this.gameSrc.aiForce(2, force); } } reset() { for (let i = 0; i < 4; i++) { this.setRate--; this.setNum++; let pos = this.posList[this.posIdx]; this.rootPos.x = pos.x + xGame.tools.random(-20, 20); this.rootPos.y = pos.y + xGame.tools.random(-20, 20); if (!xGame.common.gameMgr.isTouchedBall && this.rootPos.x > 387) this.rootPos.x = 387; if (this.rootPos.x < this.rectL) this.rootPos.x = this.rectL; else if (this.rootPos.x > this.rectR) this.rootPos.x = this.rectR; if (this.rootPos.y < this.rectT) this.rootPos.y = this.rectT; else if (this.rootPos.y > this.rectB) this.rootPos.y = this.rectB; this.posIdx++; let max = this.posList.length; if (this.posIdx >= max) this.posIdx -= max; this.initHoleBall(); let ball = null; if (this.scoreBall.length > 0) ball = this.scoreBall[0]; else if (this.lineBall.length > 0) ball = xGame.common.getRandArrEle(this.lineBall); if (ball && ball.kickAngle < this.bestAngle) { this.bestAngle = ball.kickAngle; this.bestKick.x = ball.kickPos.x; this.bestKick.y = ball.kickPos.y; this.bestPos.x = this.rootPos.x; this.bestPos.y = this.rootPos.y; this.bestForce = ball.hard * 0.08; } } if (this.setNum >= this.setMax) this.setMax = 0; if (this.setRate < 1) { this.setState(AIState.move, 0); this.rootMoveTime = Laya.timer.currTimer; this.gameSrc.aiRootMove(true); } } delayLine() { this.gameSrc.aiRootMove(false); } move() { if (this.bestPos.x < 1) this.bestPos = this.rootPos; let wObj = this.wBall.gameObj; let destx = wObj.x; let desty = wObj.y; let dx = Math.abs(destx - this.bestPos.x); let dy = Math.abs(desty - this.bestPos.y); let mx = 3 + dx * 0.03; let my = 3 + dy * 0.03; if (dx < 4 && dy < 4) { let dt = Laya.timer.currTimer - this.rootMoveTime; dt = dt < 1000 ? 1000 - dt : 0; if (this.setMax > 0) { let min = this.setMax * 0.3 + this.aiLv * 5; this.setRate = xGame.tools.random(min, this.setMax); this.setState(AIState.reset, 0); } else { this.destRot = 0; // this.forceMax = this.bestForce; this.setKick(this.bestKick.x, this.bestKick.y); } if (dt > 100) { Laya.timer.clear(this, this.delayLine) Laya.timer.once(dt, this, this.delayLine); } else this.gameSrc.aiRootMove(false); } else { if (dx > 4) destx = wObj.x < this.bestPos.x ? wObj.x + mx : wObj.x - mx; if (dy > 4) desty = wObj.y < this.bestPos.y ? wObj.y + my : wObj.y - my; this.gameSrc.onRootMove({ x: destx, y: desty }); } } resetRoot() { this.bestAngle = 180; this.bestForce = 0; this.setMax = this.posList.length; this.posIdx = xGame.tools.random(0, this.setMax); let min = this.setMax * 0.3 + this.aiLv * 5; this.setRate = xGame.tools.random(min, this.setMax); let max = 2000 - this.aiLv * 100; if (Math.random() > 0.8) max += xGame.tools.random(100, 1000); if (this.isGuide) this.setState(AIState.select, 500); else if (this.onAway(2)) this.setState(AIState.reset, xGame.tools.random(400, max)); else this.setState(AIState.none); if (xGame.common.gameMgr.finishOneShoot) this.chat(); } //运行ai runAI() { if (this.state > AIState.idle) return; this.initBall(); this.onGame(2500); if (Math.random() > 0.6) this.chat(); } stopRun() { this.setState(AIState.idle); } onGame(base: number) { let max = base - this.aiLv * 100; if (Math.random() > 0.8) max += xGame.tools.random(100, 1000); if (this.onAway(2)) this.setState(AIState.select, xGame.tools.random(500, max)); else this.setState(AIState.none); } setState(sta, wt = 0) { if (this.state == AIState.none) return; this.state = sta; this.waitTime = wt; } onUpdate() { if (this.state == AIState.none) return; this.awayTime -= this.dtime; if (this.awayTime < 1) { this.awayTime = xGame.tools.random(6000, 10000); this.awayNum += (11 - this.aiLv); this.onAway(1); } if (this.waitTime >= 0) { this.waitTime -= this.dtime; return; } switch (this.state) { case AIState.idle: this.chat(); break; case AIState.reset: this.reset(); break; case AIState.move: this.move(); break; case AIState.leave: this.state = AIState.none; xGame.common.gameMgr.aiGameEnd(true); break; case AIState.select: this.selectBall(); break; case AIState.turn: this.turnPole(); break; case AIState.shoot: this.shoot(); break; } } onAway(type) { if (type == 1)//逃跑 { let db = xGame.common.gameMgr.aiBallArr.length - xGame.common.gameMgr.selfBallArr.length; let num = this.awayNum + db * 20; if (db > 0 && num > 0 && xGame.tools.random(0, 10000) < num && this.state == AIState.idle) { xGame.common.gameMgr.aiLeave(); this.setState(AIState.leave, 6666); } } else if (type == 2) //不打(超时) { let db = xGame.common.gameMgr.aiBallArr.length - xGame.common.gameMgr.selfBallArr.length; let num = this.awayNum + db * 30; if (xGame.tools.random(0, 10000) < num) return false } else if (type == 3) //拉杆延迟(可能超时) { let db = xGame.common.gameMgr.aiBallArr.length - xGame.common.gameMgr.selfBallArr.length; let num = this.awayNum + db * 10; if (xGame.tools.random(0, 4000) < num) return false } return true; } chat() { if (this.chatTime > 0) { this.chatTime -= this.dtime; return; } this.chatTime = xGame.tools.random(2000, 10000); let rand = xGame.tools.random(0, 100); if (rand < 15) this.talk(); else if (rand < 35) this.emotion(); } talk() { xGame.common.talkMgr.showAITalk(0); } emotion() { xGame.common.talkMgr.showAIEmotion(0); } resetAI() { this.stopRun(); this.state = AIState.none; } }