import { Vec2 } from "cc"; import GBaseMode from "../GBaseMode"; import { GRoleUtil } from "../entity/GRole"; import { GTactical } from "../entity/GTactical"; import GRoleDefault from "../base/role/GRoleDefault"; import { Prefab } from "cc"; import { _decorator } from "cc"; import { instantiate } from "cc"; import { GPVPModePlayerEnum } from "./GPVPMode"; import { JNFrameInfo } from "../../../../extensions/ngame/assets/ngame/sync/frame/JNSyncFrame"; import { GMapLoop } from "../base/common/map/GMapLoop"; import { Node } from "cc"; import JNFrameTime from "../../../../extensions/ngame/assets/ngame/sync/frame/game/time/JNFrameTime"; import { TD, app } from "../../App"; import { v3 } from "cc"; import { v2 } from "cc"; import GFSMOnHookMode from "./OnHook/GFSMOnHookMode"; import { TB, TbGEntity } from "../../config/data/schema"; import PlayerTacticalData, { PlayerTacticalEvent } from "../../data/PlayerTacticalData"; import GRoleOnHookPlayerExpand from "../base/role/expand/OnHook/GRoleOnHookPlayerExpand"; import PlayerPetData from "../../data/PlayerPetData"; import { GUI } from "../../ui/UIConfig"; import { GOnHookPet, GOnHookPets } from "../../../../extensions/ngame/assets/ngame/message/proto"; import GOnHookManager, { GOnHookManagerEvent } from "../../manager/battle/mode/GOnHookManager"; import GRoleOnHookCreepsExpand from "../base/role/expand/OnHook/GRoleOnHookCreepsExpand"; import GPetAttribute from "../base/values/attribute/role/GPetAttribute"; import GOnHookData from "../../data/GOnHookData"; import { GModeEvent, GModeHitInfo } from "./GMode"; import GBattleData, { GBattleDataEnum } from "../../data/GBattleData"; import GNormalModeBase, { GNormalModePlayerEnum } from "./default/GNormalModeBase"; const { ccclass, property } = _decorator; //挂机模式状态 export enum GOnHookModeState{ GoTarget,//前往目标 Attack, //攻击 AttackEnd, //攻击结束 } /** * 挂机模式 无限出现小怪 (不是联机模式 该模式支持使用本地数据 和 API) */ @ccclass('GOnHookMode') export default class GOnHookMode extends GNormalModeBase<{},{}>{ //玩家宠物 playerRoles: GRoleDefault[] = []; //敌方宠物 enemyRoles: GRoleDefault[] = []; //每一波怪的距离 everyX:number = 600; //下一波怪的对战位置X _nextFightX:number = 0; get nextFightX(){return this._nextFightX} set nextFightX(value:number){ //修改玩家阵法位置 this.playerInfo.tactical.setOffset(this.playerPos.clone().add(v2(value,0))) this.enemyInfo.tactical.setOffset(this.enemyPos.clone().add(v2(value,0))) this._nextFightX = value; } fsm:GFSMOnHookMode; //是否允许攻击 isAllowAttack:boolean = false; //是否战斗失败 isFail:boolean = false; //让胜负失效 get isEndGame(){return true;} //添加监听事件 addEvent(){ app.event.on(PlayerTacticalEvent.UPDATE_TACTICAL,this.onUpdatePlayerPet,this); app.event.on(GBattleDataEnum.UPDARE_ATTRIBUTE_SUCCESS,this.onUpdateAttribute,this); // app.event.on(GOnHookManagerEvent.UPDATE_MAP,this.onUpdateWorld,this); } //移除监听事件 onDestroy(){ super.onDestroy(); app.event.off(PlayerTacticalEvent.UPDATE_TACTICAL,this.onUpdatePlayerPet,this); app.event.off(GBattleDataEnum.UPDARE_ATTRIBUTE_SUCCESS,this.onUpdateAttribute,this); // app.event.off(GOnHookManagerEvent.UPDATE_MAP,this.onUpdateWorld,this); } onSyncInitSuccess():void{ //初始化战斗 console.log("GOnHookMode 模式初始化"); super.onSyncInitSuccess(); //初始化状态机 this.fsm = new GFSMOnHookMode(this); //更新场景 this.onUpdateWorld(); this.onUpdatePlayerPet(); //添加监听 this.addEvent(); // //模拟请求生成宠物 // app.socket.SendBack(GAction.MODE_ON_HOOK_SPAWN_PET,{ // type:GActionType.GOnHookPets, // fun:(info:GOnHookPets) => { // console.log("接受到野怪列表",info) // } // }) //生成玩家 // this.playerInfo.roles.forEach((info,index) => this.onGenRole(GNormalModePlayerEnum.PLAYER,index + 1,info)) // //生成敌人 // this.onResetGenerateEnemy(); } //更新地图 onUpdateWorld(){ let info = TD.TbGOnHookMaps.get(GOnHookData.getIns().info.onHookMap); this.setWorldMap(info.mapId); } //更新页面 onUpdateView(){ } //更新玩家宠物 onUpdatePlayerPet(){ //获取玩家阵容 let infos = PlayerTacticalData.getIns().getTacticalInfo(); //移除不再阵容中的宠物 let roles = [...this.getOnesRoleAlive(GNormalModePlayerEnum.PLAYER)] roles.forEach(role => { let expand = role.getComponent(GRoleOnHookPlayerExpand); //如果宠物不再阵容中 则 移除宠物 if(infos.indexOf(expand.petId) < 0){ //移除宠物 this.playerRoles.splice(this.playerRoles.indexOf(role),1); role.isDie = true; } }) infos.forEach((petId,index) => { if(petId){ this.onGenPlayerPet(index+1,petId); } }) } //更新属性 onUpdateAttribute(){ this.getOnesRole(GNormalModePlayerEnum.PLAYER).forEach(pet => { pet.onEffectiveValue(GBattleData.getIns().data.getPetAttribute(pet.getComponent(GRoleOnHookPlayerExpand).petId)); }); } //更新帧 onSyncUpdate(dt: number,frame:JNFrameInfo, input?: {}){ super.onSyncUpdate(dt,frame,input); this.onUpdateMap(dt); this.onUpdateCamera(dt); this.fsm.onUpdate(dt,frame); } //更新相机逻辑 onUpdateCamera(dt:number){ //如果没有敌人相机永远锁定最前面的宠物 if(this.isAllowAttack && this.isHaveEnemy()){ //如果有敌人则移动到战斗位置 let cameraWorld = this.camera.node.worldPosition.clone(); this.camera.node.worldPosition = cameraWorld.lerp(v3(this.nextFightX,cameraWorld.y,cameraWorld.z),(dt / 1000)); }else{ //获取冲到最前面的宠物 let roles = this.getOnesRoleAlive(GNormalModePlayerEnum.PLAYER); let frontRole = roles.sort((role1,role2) => role2.v2World.x - role1.v2World.x)[0]; if(!frontRole) return; //设置相机 位置 let cameraWorld = this.camera.node.worldPosition.clone(); this.camera.node.worldPosition = cameraWorld.lerp(v3(frontRole.v2World.x,cameraWorld.y,cameraWorld.z),(dt / 1000)); } } //生成玩家宠物 onGenPlayerPet(index:number,petId:number){ //如果场上有这个宠物则更新阵法位置 let passRole:GRoleDefault; this.playerRoles.forEach(role => { if(role.getComponent(GRoleOnHookPlayerExpand).petId == petId) passRole = role; }) if(passRole){ //更新宠物阵法位置 passRole.tacticalIndex = index; return; } //获取要生成的宠物 let info = PlayerPetData.getIns().petIdQueryPetInfo(petId); if(!info){ app.layer.Open(GUI.Tips,{text:"未拥有当前上阵的宠物"}); return; } let role = this.onGenRole(GNormalModePlayerEnum.PLAYER,index,TD.TbGRole.get(info.petTbId)); //向宠物添加 OnHook 扩展 let expand = role.node.addComponent(GRoleOnHookPlayerExpand); expand.petId = petId; //添加宠物属性 role.onEffectiveValue(GBattleData.getIns().data.getPetAttribute(petId)); } //生成野怪 onGenCreeps(index:number,creeps:GOnHookPet){ let role = this.onGenRole(GNormalModePlayerEnum.ENEMY,index,TD.TbGRole.get(creeps.petTbId)); //向野怪添加扩展 let expand = role.node.addComponent(GRoleOnHookCreepsExpand); expand.creeps = creeps; //添加野怪属性 role.onEffectiveValues(new GPetAttribute({ petId:0, petPlayerId:0, petTbId:creeps.petTbId, petStar:creeps.petLevel, petStarExp:0, })); } //获取敌人 getEnumy(player:GRoleDefault,type:GNormalModePlayerEnum):GRoleDefault{ if(!this.isAllowAttack) return null; return super.getEnumy(player,type); } //生成敌人 onResetFight(){ //初始化战斗失败 this.isFail = false; this.enemyRoles = []; let sign = TD.TbGOnHookMaps.get(GOnHookData.getIns().info.onHookMap).sign; let table:{data:TbGEntity.TOnHookLevel} = TD[sign].get(GOnHookData.getIns().info.levelId); for (let index = 0; index < table.data.petSize; index++) { //获取敌人 let creeps = GOnHookManager.getIns().getNextCreeps(); if(!creeps) return; //没有获取到野怪则返回 this.onGenCreeps(index + 1,creeps); } this.onUpdatePlayerPet(); // this.enemyInfo.roles.forEach((info,index) => this.onGenRole(GNormalModePlayerEnum.ENEMY,index + 1,info)); } //角色死亡回调 onRoleKillBack(role:GRoleDefault){ super.onRoleKillBack(role); //如果死亡的是野怪则通知野怪死亡 if(role.getComponent(GRoleOnHookCreepsExpand)){ GOnHookManager.getIns().onKillSreeps(role.getComponent(GRoleOnHookCreepsExpand).creeps); //如果野怪都死了 并且 战斗成功 则向服务器发送战斗成功 if(this.enemyRoles.length <= 0 && !this.isFail){ GOnHookManager.getIns().onWinLevel(); } } //如果死亡的是玩家宠物 并且 场上没有玩家宠物则重新战斗 if(role.getComponent(GRoleOnHookPlayerExpand)){ if(this.playerRoles.length <= 0){ //玩家战斗失败 this.isFail = true; this.onUpdatePlayerPet(); } } } //清理缓存 onClearCache(){ //清理宠物 let roles = [...this.playerRoles]; roles.forEach(role => { if(!role.get()){ this.playerRoles.splice(this.playerRoles.indexOf(role),1); } }) roles = [...this.enemyRoles]; roles.forEach(role => { if(!role.get()){ this.enemyRoles.splice(this.enemyRoles.indexOf(role),1); } }) } //是否有怪物 isHaveEnemy(){ if(!this.isAllowAttack) return []; return this.getOnesRoleAlive(GNormalModePlayerEnum.ENEMY).filter(role => !!role.get()).length > 0; } //前往下一个目标 onNextTarget(){ //下一个目标点 this.nextFightX = this.nextFightX + this.everyX; } }