feat(任务): 增加准备阶段与战斗阶段的切换逻辑
- 在准备阶段显示卡牌面板和开始战斗按钮,并发放金币奖励 - 进入战斗阶段时隐藏卡牌面板并禁用按钮 - 根据波数动态计算准备阶段金币奖励 - 修复金币同步和初始化问题
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ import { _decorator, instantiate, Label, Node, NodeEventType, Prefab, SpriteAtla
|
|||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||||
import { GameEvent } from "../common/config/GameEvent";
|
import { GameEvent } from "../common/config/GameEvent";
|
||||||
import { CARD_POOL_INIT_LEVEL, CARD_POOL_MAX_LEVEL, CardConfig, CardInitCoins, CardsUpSet, getCardsByLv } from "../common/config/CardSet";
|
import { CARD_POOL_INIT_LEVEL, CARD_POOL_MAX_LEVEL, CardConfig, CardsUpSet, getCardsByLv } from "../common/config/CardSet";
|
||||||
import { CardComp } from "./CardComp";
|
import { CardComp } from "./CardComp";
|
||||||
import { oops } from "db://oops-framework/core/Oops";
|
import { oops } from "db://oops-framework/core/Oops";
|
||||||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||||
@@ -25,6 +25,10 @@ export class MissionCardComp extends CCComp {
|
|||||||
/** 四个插卡槽位(固定顺序分发:1~4) */
|
/** 四个插卡槽位(固定顺序分发:1~4) */
|
||||||
@property(Node)
|
@property(Node)
|
||||||
cards_node:Node = null!
|
cards_node:Node = null!
|
||||||
|
@property({ tooltip: "战斗阶段卡牌面板下移隐藏距离" })
|
||||||
|
cardsBattleHideOffsetY: number = 1280;
|
||||||
|
@property({ tooltip: "卡牌面板位移动画时长" })
|
||||||
|
cardsPanelMoveDuration: number = 0.2;
|
||||||
@property(Node)
|
@property(Node)
|
||||||
card1:Node = null!
|
card1:Node = null!
|
||||||
@property(Node)
|
@property(Node)
|
||||||
@@ -55,6 +59,9 @@ export class MissionCardComp extends CCComp {
|
|||||||
private poolLv: number = CARD_POOL_INIT_LEVEL;
|
private poolLv: number = CARD_POOL_INIT_LEVEL;
|
||||||
private readonly heroInfoItemGap: number = 86;
|
private readonly heroInfoItemGap: number = 86;
|
||||||
private heroInfoSyncTimer: number = 0;
|
private heroInfoSyncTimer: number = 0;
|
||||||
|
private cardsShowPos: Vec3 = new Vec3();
|
||||||
|
private cardsHidePos: Vec3 = new Vec3();
|
||||||
|
private cardsPosReady: boolean = false;
|
||||||
private heroInfoItems: Map<number, {
|
private heroInfoItems: Map<number, {
|
||||||
node: Node,
|
node: Node,
|
||||||
model: HeroAttrsComp,
|
model: HeroAttrsComp,
|
||||||
@@ -65,6 +72,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
this.bindEvents();
|
this.bindEvents();
|
||||||
this.cacheCardComps();
|
this.cacheCardComps();
|
||||||
this.layoutCardSlots();
|
this.layoutCardSlots();
|
||||||
|
this.initCardsPanelPos();
|
||||||
this.onMissionStart();
|
this.onMissionStart();
|
||||||
mLogger.log(this.debugMode, "MissionCardComp", "onLoad init", {
|
mLogger.log(this.debugMode, "MissionCardComp", "onLoad init", {
|
||||||
slots: this.cardComps.length,
|
slots: this.cardComps.length,
|
||||||
@@ -82,10 +90,11 @@ export class MissionCardComp extends CCComp {
|
|||||||
|
|
||||||
/** 任务开始时:重置卡池等级、清空4槽、显示面板 刷新一次卡池*/
|
/** 任务开始时:重置卡池等级、清空4槽、显示面板 刷新一次卡池*/
|
||||||
onMissionStart() {
|
onMissionStart() {
|
||||||
|
this.enterPreparePhase();
|
||||||
this.poolLv = CARD_POOL_INIT_LEVEL;
|
this.poolLv = CARD_POOL_INIT_LEVEL;
|
||||||
const missionData = this.getMissionData();
|
const missionData = this.getMissionData();
|
||||||
if (missionData) {
|
if (missionData) {
|
||||||
missionData.coin = CardInitCoins;
|
missionData.coin = Math.max(0, Math.floor(missionData.coin ?? 0));
|
||||||
missionData.hero_num = 0;
|
missionData.hero_num = 0;
|
||||||
missionData.hero_max_num = 5;
|
missionData.hero_max_num = 5;
|
||||||
missionData.hero_extend_max_num = 6;
|
missionData.hero_extend_max_num = 6;
|
||||||
@@ -136,6 +145,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
/** 生命周期事件 */
|
/** 生命周期事件 */
|
||||||
this.on(GameEvent.MissionStart, this.onMissionStart, this);
|
this.on(GameEvent.MissionStart, this.onMissionStart, this);
|
||||||
this.on(GameEvent.MissionEnd, this.onMissionEnd, this);
|
this.on(GameEvent.MissionEnd, this.onMissionEnd, this);
|
||||||
|
this.on(GameEvent.FightStart, this.onFightStart, this);
|
||||||
this.on(GameEvent.CoinAdd, this.onCoinAdd, this);
|
this.on(GameEvent.CoinAdd, this.onCoinAdd, this);
|
||||||
oops.message.on(GameEvent.MasterCalled, this.onMasterCalled, this);
|
oops.message.on(GameEvent.MasterCalled, this.onMasterCalled, this);
|
||||||
oops.message.on(GameEvent.HeroDead, this.onHeroDead, this);
|
oops.message.on(GameEvent.HeroDead, this.onHeroDead, this);
|
||||||
@@ -150,6 +160,11 @@ export class MissionCardComp extends CCComp {
|
|||||||
this.cards_up?.on(NodeEventType.TOUCH_CANCEL, this.onUpgradeTouchCancel, this);
|
this.cards_up?.on(NodeEventType.TOUCH_CANCEL, this.onUpgradeTouchCancel, this);
|
||||||
}
|
}
|
||||||
private onCoinAdd(args:any){
|
private onCoinAdd(args:any){
|
||||||
|
if (args?.syncOnly) {
|
||||||
|
this.updatePoolLvUI();
|
||||||
|
this.playCoinChangeAnim((args?.delta ?? 0) > 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const v = typeof args === 'number' ? args : (args?.delta ?? args?.value ?? 0);
|
const v = typeof args === 'number' ? args : (args?.delta ?? args?.value ?? 0);
|
||||||
if (v === 0) return;
|
if (v === 0) return;
|
||||||
this.setMissionCoin(this.getMissionCoin() + v);
|
this.setMissionCoin(this.getMissionCoin() + v);
|
||||||
@@ -157,6 +172,10 @@ export class MissionCardComp extends CCComp {
|
|||||||
this.playCoinChangeAnim(v > 0);
|
this.playCoinChangeAnim(v > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onFightStart() {
|
||||||
|
this.enterBattlePhase();
|
||||||
|
}
|
||||||
|
|
||||||
/** 解除按钮监听,避免节点销毁后回调泄漏 */
|
/** 解除按钮监听,避免节点销毁后回调泄漏 */
|
||||||
private unbindEvents() {
|
private unbindEvents() {
|
||||||
oops.message.off(GameEvent.MasterCalled, this.onMasterCalled, this);
|
oops.message.off(GameEvent.MasterCalled, this.onMasterCalled, this);
|
||||||
@@ -271,6 +290,34 @@ export class MissionCardComp extends CCComp {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private initCardsPanelPos() {
|
||||||
|
if (!this.cards_node || !this.cards_node.isValid || this.cardsPosReady) return;
|
||||||
|
const pos = this.cards_node.position;
|
||||||
|
this.cardsShowPos = new Vec3(pos.x, pos.y, pos.z);
|
||||||
|
this.cardsHidePos = new Vec3(pos.x, pos.y - Math.abs(this.cardsBattleHideOffsetY), pos.z);
|
||||||
|
this.cardsPosReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enterPreparePhase() {
|
||||||
|
if (!this.cards_node || !this.cards_node.isValid) return;
|
||||||
|
this.initCardsPanelPos();
|
||||||
|
this.cards_node.active = true;
|
||||||
|
Tween.stopAllByTarget(this.cards_node);
|
||||||
|
this.cards_node.setPosition(this.cardsShowPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
private enterBattlePhase() {
|
||||||
|
if (!this.cards_node || !this.cards_node.isValid) return;
|
||||||
|
this.initCardsPanelPos();
|
||||||
|
this.cards_node.active = true;
|
||||||
|
Tween.stopAllByTarget(this.cards_node);
|
||||||
|
tween(this.cards_node)
|
||||||
|
.to(this.cardsPanelMoveDuration, {
|
||||||
|
position: this.cardsHidePos
|
||||||
|
})
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
|
||||||
/** 构建本次抽卡结果,保证最终可分发4条数据 */
|
/** 构建本次抽卡结果,保证最终可分发4条数据 */
|
||||||
private buildDrawCards(): CardConfig[] {
|
private buildDrawCards(): CardConfig[] {
|
||||||
const cards = getCardsByLv(this.poolLv);
|
const cards = getCardsByLv(this.poolLv);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { _decorator, Vec3,Animation, instantiate, Prefab, Node, ProgressBar, Label } from "cc";
|
import { _decorator, Vec3,Animation, instantiate, Prefab, Node, NodeEventType, ProgressBar, Label } from "cc";
|
||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||||
import { smc } from "../common/SingletonModuleComp";
|
import { smc } from "../common/SingletonModuleComp";
|
||||||
@@ -30,11 +30,19 @@ export class MissionComp extends CCComp {
|
|||||||
private maxMonsterCount: number = 5;
|
private maxMonsterCount: number = 5;
|
||||||
@property({ tooltip: "恢复刷怪阈值" })
|
@property({ tooltip: "恢复刷怪阈值" })
|
||||||
private resumeMonsterCount: number = 3;
|
private resumeMonsterCount: number = 3;
|
||||||
|
@property({ tooltip: "准备阶段基础金币奖励" })
|
||||||
|
private prepareBaseCoinReward: number = 10;
|
||||||
|
@property({ tooltip: "每波准备阶段额外金币" })
|
||||||
|
private prepareCoinWaveGrow: number = 1;
|
||||||
|
@property({ tooltip: "准备阶段金币奖励上限" })
|
||||||
|
private prepareCoinRewardCap: number = 20;
|
||||||
|
|
||||||
// VictoryComp:any = null;
|
// VictoryComp:any = null;
|
||||||
// reward:number = 0;
|
// reward:number = 0;
|
||||||
// reward_num:number = 0;
|
// reward_num:number = 0;
|
||||||
@property(Node)
|
@property(Node)
|
||||||
|
start_btn:Node = null!
|
||||||
|
@property(Node)
|
||||||
time_node:Node = null!
|
time_node:Node = null!
|
||||||
|
|
||||||
FightTime:number = FightSet.FiIGHT_TIME
|
FightTime:number = FightSet.FiIGHT_TIME
|
||||||
@@ -61,6 +69,7 @@ export class MissionComp extends CCComp {
|
|||||||
private heapTrendBaseMB: number = -1;
|
private heapTrendBaseMB: number = -1;
|
||||||
private monsterCountSyncTimer: number = 0;
|
private monsterCountSyncTimer: number = 0;
|
||||||
private currentWave: number = 0;
|
private currentWave: number = 0;
|
||||||
|
private lastPrepareCoinWave: number = 0;
|
||||||
private readonly heroViewMatcher = ecs.allOf(HeroViewComp);
|
private readonly heroViewMatcher = ecs.allOf(HeroViewComp);
|
||||||
private readonly skillViewMatcher = ecs.allOf(SkillView);
|
private readonly skillViewMatcher = ecs.allOf(SkillView);
|
||||||
private readonly heroAttrsMatcher = ecs.allOf(HeroAttrsComp);
|
private readonly heroAttrsMatcher = ecs.allOf(HeroAttrsComp);
|
||||||
@@ -75,8 +84,12 @@ export class MissionComp extends CCComp {
|
|||||||
this.on(GameEvent.MissionEnd,this.mission_end,this)
|
this.on(GameEvent.MissionEnd,this.mission_end,this)
|
||||||
this.on(GameEvent.NewWave,this.onNewWave,this)
|
this.on(GameEvent.NewWave,this.onNewWave,this)
|
||||||
this.on(GameEvent.DO_AD_BACK,this.do_ad,this)
|
this.on(GameEvent.DO_AD_BACK,this.do_ad,this)
|
||||||
|
this.start_btn?.on(NodeEventType.TOUCH_END, this.onStartFightBtnClick, this)
|
||||||
this.removeMemoryPanel()
|
this.removeMemoryPanel()
|
||||||
}
|
}
|
||||||
|
onDestroy(){
|
||||||
|
this.start_btn?.off(NodeEventType.TOUCH_END, this.onStartFightBtnClick, this)
|
||||||
|
}
|
||||||
protected update(dt: number): void {
|
protected update(dt: number): void {
|
||||||
if(!smc.mission.play) return
|
if(!smc.mission.play) return
|
||||||
if(smc.mission.pause) return
|
if(smc.mission.pause) return
|
||||||
@@ -131,22 +144,35 @@ export class MissionComp extends CCComp {
|
|||||||
this.node.active=true
|
this.node.active=true
|
||||||
this.data_init()
|
this.data_init()
|
||||||
oops.message.dispatchEvent(GameEvent.FightReady)
|
oops.message.dispatchEvent(GameEvent.FightReady)
|
||||||
|
this.enterPreparePhase()
|
||||||
let loading=this.node.parent.getChildByName("loading")
|
let loading=this.node.parent.getChildByName("loading")
|
||||||
loading.active=true
|
loading.active=true
|
||||||
this.scheduleOnce(()=>{
|
this.scheduleOnce(()=>{
|
||||||
loading.active=false
|
loading.active=false
|
||||||
},0.5)
|
},0.5)
|
||||||
this.scheduleOnce(()=>{
|
|
||||||
this.to_fight()
|
|
||||||
},0.1)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
to_fight(){
|
to_fight(){
|
||||||
|
smc.mission.stop_spawn_mon = false;
|
||||||
smc.mission.in_fight=true
|
smc.mission.in_fight=true
|
||||||
|
if (this.start_btn && this.start_btn.isValid) this.start_btn.active = false;
|
||||||
oops.message.dispatchEvent(GameEvent.FightStart) //GameSetMonComp 监听刷怪
|
oops.message.dispatchEvent(GameEvent.FightStart) //GameSetMonComp 监听刷怪
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private enterPreparePhase() {
|
||||||
|
smc.mission.in_fight = false;
|
||||||
|
smc.mission.stop_spawn_mon = true;
|
||||||
|
if (this.start_btn && this.start_btn.isValid) this.start_btn.active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private onStartFightBtnClick() {
|
||||||
|
if (!smc.mission.play) return;
|
||||||
|
if (smc.mission.pause) return;
|
||||||
|
if (smc.mission.in_fight) return;
|
||||||
|
this.to_fight();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
open_Victory(e:any,is_hero_dead: boolean = false){
|
open_Victory(e:any,is_hero_dead: boolean = false){
|
||||||
// 暂停游戏循环和怪物行为
|
// 暂停游戏循环和怪物行为
|
||||||
@@ -181,14 +207,13 @@ export class MissionComp extends CCComp {
|
|||||||
smc.mission.play=false
|
smc.mission.play=false
|
||||||
smc.mission.pause = false;
|
smc.mission.pause = false;
|
||||||
smc.mission.in_fight = false;
|
smc.mission.in_fight = false;
|
||||||
|
if (this.start_btn && this.start_btn.isValid) this.start_btn.active = false;
|
||||||
this.cleanComponents()
|
this.cleanComponents()
|
||||||
this.clearBattlePools()
|
this.clearBattlePools()
|
||||||
this.node.active=false
|
this.node.active=false
|
||||||
}
|
}
|
||||||
|
|
||||||
data_init(){
|
data_init(){
|
||||||
// 重置金币为初始值 (如果需要保留金币,请注释掉此行)
|
|
||||||
smc.vmdata.gold = 0;
|
|
||||||
//局内数据初始化 smc 数据初始化
|
//局内数据初始化 smc 数据初始化
|
||||||
smc.mission.play = true;
|
smc.mission.play = true;
|
||||||
smc.mission.pause = false;
|
smc.mission.pause = false;
|
||||||
@@ -215,6 +240,8 @@ export class MissionComp extends CCComp {
|
|||||||
this.heapTrendTimer = 0;
|
this.heapTrendTimer = 0;
|
||||||
this.heapTrendBaseMB = -1;
|
this.heapTrendBaseMB = -1;
|
||||||
this.monsterCountSyncTimer = 0;
|
this.monsterCountSyncTimer = 0;
|
||||||
|
this.lastPrepareCoinWave = 0;
|
||||||
|
smc.vmdata.mission_data.coin = 0;
|
||||||
|
|
||||||
// 重置全局属性加成和主角引用 (确保新一局数据干净)
|
// 重置全局属性加成和主角引用 (确保新一局数据干净)
|
||||||
// smc.role = null;
|
// smc.role = null;
|
||||||
@@ -229,10 +256,28 @@ export class MissionComp extends CCComp {
|
|||||||
if (wave <= 0) return;
|
if (wave <= 0) return;
|
||||||
this.currentWave = wave;
|
this.currentWave = wave;
|
||||||
smc.vmdata.mission_data.level = wave;
|
smc.vmdata.mission_data.level = wave;
|
||||||
|
this.grantPrepareCoinByWave(wave);
|
||||||
this.lastTimeSecond = -1;
|
this.lastTimeSecond = -1;
|
||||||
this.update_time();
|
this.update_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private grantPrepareCoinByWave(wave: number) {
|
||||||
|
if (wave <= 0) return;
|
||||||
|
if (wave <= this.lastPrepareCoinWave) return;
|
||||||
|
const base = Math.max(0, Math.floor(this.prepareBaseCoinReward));
|
||||||
|
const grow = Math.max(0, Math.floor(this.prepareCoinWaveGrow));
|
||||||
|
const cap = Math.max(0, Math.floor(this.prepareCoinRewardCap));
|
||||||
|
const reward = Math.min(cap, base + (wave - 1) * grow);
|
||||||
|
if (reward <= 0) {
|
||||||
|
this.lastPrepareCoinWave = wave;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
smc.vmdata.mission_data.coin = Math.max(0, Math.floor((smc.vmdata.mission_data.coin ?? 0) + reward));
|
||||||
|
this.lastPrepareCoinWave = wave;
|
||||||
|
oops.message.dispatchEvent(GameEvent.CoinAdd, { delta: reward, syncOnly: true });
|
||||||
|
mLogger.log(this.debugMode, 'MissionComp', "prepare coin reward", { wave, reward, coin: smc.vmdata.mission_data.coin });
|
||||||
|
}
|
||||||
|
|
||||||
private getMonsterThresholds(): { max: number; resume: number } {
|
private getMonsterThresholds(): { max: number; resume: number } {
|
||||||
const max = Math.max(1, Math.floor(this.maxMonsterCount));
|
const max = Math.max(1, Math.floor(this.maxMonsterCount));
|
||||||
const resume = Math.min(max - 1, Math.max(0, Math.floor(this.resumeMonsterCount)));
|
const resume = Math.min(max - 1, Math.max(0, Math.floor(this.resumeMonsterCount)));
|
||||||
|
|||||||
Reference in New Issue
Block a user