mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-06-26 19:34:47 +00:00
340 lines
11 KiB
TypeScript
340 lines
11 KiB
TypeScript
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;
|
|
|
|
}
|
|
|
|
}
|
|
|