feat: 拆分特殊卡类型并实现升级和刷新功能
- 将 CardType.Special 拆分为 SpecialUpgrade 和 SpecialRefresh - 新增特殊卡使用逻辑:升级功能卡可随机升级场上英雄,刷新功能卡可筛选卡池 - 添加 drawCardsByRule 函数支持按类型、英雄类型和等级抽取卡牌 - 在 MissionCardComp 中处理特殊卡使用事件并更新UI
This commit is contained in:
@@ -3,12 +3,15 @@ import { _decorator, instantiate, Label, Node, NodeEventType, Prefab, SpriteAtla
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
import { CARD_POOL_INIT_LEVEL, CARD_POOL_MAX_LEVEL, CARD_POOL_UPGRADE_DISCOUNT_PER_WAVE, CardConfig, CardsUpSet, getCardsByLv } from "../common/config/CardSet";
|
||||
import { CARD_POOL_INIT_LEVEL, CARD_POOL_MAX_LEVEL, CARD_POOL_UPGRADE_DISCOUNT_PER_WAVE, CardConfig, CardType, CardsUpSet, drawCardsByRule, getCardsByLv, SpecialRefreshCardList, SpecialRefreshHeroType, SpecialUpgradeCardList } from "../common/config/CardSet";
|
||||
import { CardComp } from "./CardComp";
|
||||
import { oops } from "db://oops-framework/core/Oops";
|
||||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||
import { HInfoComp } from "./HInfoComp";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { HeroInfo, HType } from "../common/config/heroSet";
|
||||
import { HeroViewComp } from "../hero/HeroViewComp";
|
||||
import { FacSet } from "../common/config/GameSet";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@@ -152,6 +155,7 @@ export class MissionCardComp extends CCComp {
|
||||
oops.message.on(GameEvent.MasterCalled, this.onMasterCalled, this);
|
||||
oops.message.on(GameEvent.HeroDead, this.onHeroDead, this);
|
||||
oops.message.on(GameEvent.UseHeroCard, this.onUseHeroCard, this);
|
||||
oops.message.on(GameEvent.UseSpecialCard, this.onUseSpecialCard, this);
|
||||
|
||||
/** 按钮事件:抽卡与卡池升级 */
|
||||
this.cards_chou?.on(NodeEventType.TOUCH_START, this.onDrawTouchStart, this);
|
||||
@@ -193,6 +197,7 @@ export class MissionCardComp extends CCComp {
|
||||
oops.message.off(GameEvent.MasterCalled, this.onMasterCalled, this);
|
||||
oops.message.off(GameEvent.HeroDead, this.onHeroDead, this);
|
||||
oops.message.off(GameEvent.UseHeroCard, this.onUseHeroCard, this);
|
||||
oops.message.off(GameEvent.UseSpecialCard, this.onUseSpecialCard, this);
|
||||
this.cards_chou?.off(NodeEventType.TOUCH_START, this.onDrawTouchStart, this);
|
||||
this.cards_chou?.off(NodeEventType.TOUCH_END, this.onDrawTouchEnd, this);
|
||||
this.cards_chou?.off(NodeEventType.TOUCH_CANCEL, this.onDrawTouchCancel, this);
|
||||
@@ -231,6 +236,30 @@ export class MissionCardComp extends CCComp {
|
||||
}
|
||||
}
|
||||
|
||||
private onUseSpecialCard(event: string, args: any) {
|
||||
const payload = args ?? event;
|
||||
const uuid = Number(payload?.uuid ?? 0);
|
||||
const type = Number(payload?.type ?? 0) as CardType;
|
||||
if (!uuid) return;
|
||||
let success = false;
|
||||
if (type === CardType.SpecialUpgrade) {
|
||||
const card = SpecialUpgradeCardList[uuid];
|
||||
if (!card) return;
|
||||
success = this.tryUpgradeOneHero(card.currentLv, card.targetLv);
|
||||
if (!success) oops.gui.toast(`场上没有可从${card.currentLv}级升到${card.targetLv}级的英雄`);
|
||||
} else if (type === CardType.SpecialRefresh) {
|
||||
const card = SpecialRefreshCardList[uuid];
|
||||
if (!card) return;
|
||||
success = this.tryRefreshHeroCardsByEffect(card.refreshHeroType, card.refreshLv);
|
||||
if (!success) oops.gui.toast("当前卡池无符合条件的英雄卡");
|
||||
}
|
||||
mLogger.log(this.debugMode, "MissionCardComp", "use special card", {
|
||||
uuid,
|
||||
type,
|
||||
success
|
||||
});
|
||||
}
|
||||
|
||||
private onDrawTouchStart() {
|
||||
this.playButtonPressAnim(this.cards_chou);
|
||||
}
|
||||
@@ -365,6 +394,31 @@ export class MissionCardComp extends CCComp {
|
||||
return filled;
|
||||
}
|
||||
|
||||
private tryRefreshHeroCards(heroType?: HType, heroLv?: number): boolean {
|
||||
const cards = drawCardsByRule(this.poolLv, {
|
||||
count: 4,
|
||||
type: CardType.Hero,
|
||||
heroType,
|
||||
heroLv
|
||||
});
|
||||
if (cards.length <= 0) return false;
|
||||
this.layoutCardSlots();
|
||||
this.dispatchCardsToSlots(cards.slice(0, 4));
|
||||
return true;
|
||||
}
|
||||
|
||||
private tryRefreshHeroCardsByEffect(refreshHeroType: SpecialRefreshHeroType, refreshLv: number): boolean {
|
||||
const heroType = this.resolveRefreshHeroType(refreshHeroType);
|
||||
const heroLv = refreshLv > 0 ? refreshLv : undefined;
|
||||
return this.tryRefreshHeroCards(heroType, heroLv);
|
||||
}
|
||||
|
||||
private resolveRefreshHeroType(refreshHeroType: SpecialRefreshHeroType): HType | undefined {
|
||||
if (refreshHeroType === SpecialRefreshHeroType.Melee) return HType.Melee;
|
||||
if (refreshHeroType === SpecialRefreshHeroType.Ranged) return HType.Long;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** 全量分发给4槽;每个槽位是否接收由 CardComp 自己判断(锁定可跳过) */
|
||||
private dispatchCardsToSlots(cards: CardConfig[]) {
|
||||
for (let i = 0; i < this.cardComps.length; i++) {
|
||||
@@ -636,6 +690,56 @@ export class MissionCardComp extends CCComp {
|
||||
return count;
|
||||
}
|
||||
|
||||
private queryAliveHeroActors(): Array<{ model: HeroAttrsComp, view: HeroViewComp | null }> {
|
||||
const actors: Array<{ model: HeroAttrsComp, view: HeroViewComp | null }> = [];
|
||||
ecs.query(ecs.allOf(HeroAttrsComp)).forEach((entity: ecs.Entity) => {
|
||||
const model = entity.get(HeroAttrsComp);
|
||||
if (!model) return;
|
||||
if (model.fac !== FacSet.HERO) return;
|
||||
if (model.is_dead) return;
|
||||
const view = entity.get(HeroViewComp);
|
||||
actors.push({ model, view });
|
||||
});
|
||||
return actors;
|
||||
}
|
||||
|
||||
private tryUpgradeOneHero(currentLv: number, targetLv: number): boolean {
|
||||
const fromLv = Math.max(1, Math.floor(currentLv));
|
||||
const toLv = Math.max(1, Math.floor(targetLv));
|
||||
if (toLv <= fromLv) return false;
|
||||
const candidates = this.queryAliveHeroActors().filter(item => item.model.lv === fromLv);
|
||||
if (candidates.length === 0) return false;
|
||||
const target = candidates[Math.floor(Math.random() * candidates.length)];
|
||||
this.applyHeroLevel(target.model, toLv);
|
||||
if (target.view) {
|
||||
target.view.palayBuff("buff_lvup");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private applyHeroLevel(model: HeroAttrsComp, targetLv: number) {
|
||||
const hero = HeroInfo[model.hero_uuid];
|
||||
if (!hero) return;
|
||||
const nextLv = Math.max(1, Math.min(3, Math.floor(targetLv)));
|
||||
const hpRate = model.hp_max > 0 ? model.hp / model.hp_max : 1;
|
||||
model.lv = nextLv;
|
||||
model.ap = hero.ap * nextLv;
|
||||
model.hp_max = hero.hp * nextLv;
|
||||
model.hp = Math.max(1, Math.floor(model.hp_max * Math.max(0, Math.min(1, hpRate))));
|
||||
model.skills = {};
|
||||
for (const key in hero.skills) {
|
||||
const skill = hero.skills[key];
|
||||
if (!skill) continue;
|
||||
model.skills[skill.uuid] = { ...skill, lv: Math.max(0, skill.lv + nextLv - 2), ccd: 0 };
|
||||
}
|
||||
model.updateSkillDistanceCache();
|
||||
model.dirty_hp = true;
|
||||
oops.message.dispatchEvent(GameEvent.HeroLvUp, {
|
||||
uuid: model.hero_uuid,
|
||||
lv: nextLv
|
||||
});
|
||||
}
|
||||
|
||||
private updateHeroNumUI(animate: boolean, isIncrease: boolean) {
|
||||
this.syncMissionHeroData();
|
||||
if (!animate || !isIncrease) return;
|
||||
|
||||
Reference in New Issue
Block a user