4 Commits

Author SHA1 Message Date
panFD
2ae48afb99 refactor(MissionCard): 优化刷新石数量变更逻辑
1.  调整注释描述,将装备数量改为刷新石数量
2.  新增刷新石数量变化动画播放逻辑
3.  重构刷新石数量变更事件处理方法,支持传递变化数值并触发动画
2026-07-31 20:53:17 +08:00
panFD
f10772bfd8 refactor(missionCard): 优化英雄槽位加载逻辑并清理废弃代码
1. 移除不再需要的showCards节点和heroPrefab引用
2. 简化ensureHeroBoxSlots方法,改为直接缓存预放置的槽位
3. 更新对应注释说明当前槽位由编辑器预创建
4. 新增装备数量显示节点的属性声明
2026-07-31 20:30:30 +08:00
panFD
f7bee02ae0 chore: 删除废弃的英雄和技能配置文件
清理了不再使用的heros.xlsx、skills.csv以及对应的元数据文件,移除冗余的游戏配置资源
2026-07-31 20:22:56 +08:00
panFD
34b0443ccb refactor(mission): 调整刷新石消耗逻辑并统一配置
1. 新增刷新石单次消耗常量配置到GameSet
2. 重构刷新消耗计算逻辑,统一从配置读取消耗值
3. 更新UI显示逻辑,正确展示单次刷新所需刷新石数量
4. 修复刷新石扣除逻辑,按实际配置值扣除而非固定1
2026-07-31 20:22:43 +08:00
7 changed files with 55 additions and 97 deletions

View File

@@ -50,6 +50,8 @@ export enum FightSet {
BASE_COST = 5,
INIT_COIN = 7, // 初始金币数
INIT_REFRESH_STONE = 3, // 初始刷新石数量
/** 单次刷新消耗的刷新石数量 */
REFRESH_STONE_COST = 1,
}
/**

View File

@@ -1,12 +0,0 @@
{
"ver": "1.0.0",
"importer": "*",
"imported": true,
"uuid": "19f625a6-5615-4db8-8e96-03e227bbf253",
"files": [
".json",
".xlsx"
],
"subMetas": {},
"userData": {}
}

View File

@@ -1,26 +0,0 @@
uuid,name,path,fac,cards_lv,lv,type,sp_name,icon,TGroup,readyAnm,endAnm,act,DTType,ap,hit_count,hitcd,speed,with,ready,EAnm,DAnm,IType,RType,EType,buffs,info,frz,bezier_start_y,bezier_mid_y,bezier_arc,bck,crt,kind
6001,skill_name_6001,,,,,,atk,1026,3,,,atk,0,100,1,0.2,720,0,0.2,0,,0,0,2,,skill_info_6001,,,,,,,
6002,skill_name_6002,,,,,,ball_fire,1126,3,,,atk,0,100,1,0.3,720,90,0.2,0,,1,1,2,,skill_info_6002,0,,,,,,
6003,skill_name_6003,,,,,,ball_winds,1126,3,,,atk,0,100,1,0.3,720,90,0.2,0,,1,1,2,,skill_info_6003,,,,,,,
6004,skill_name_6004,,,,,,ball_zi,1126,3,,,atk,0,100,1,0.3,720,90,0.2,0,,1,0,2,,skill_info_6004,,,,,,,
6005,skill_name_6005,,,,,,arrow,1135,3,,,atk,0,100,1,0.2,720,0,0.2,0,,1,1,2,,skill_info_6005,,20,140,1.05,,,
6007,skill_name_6007,,,,,,ball_forst,1126,3,,,atk,0,100,1,0.3,720,90,0.2,0,,1,1,2,,skill_info_6007,,,,,,,
6007,skill_name_6008,,,,,,ball_water,1126,3,,,atk,0,100,1,0.3,720,90,0.2,0,,1,1,2,,skill_info_6008,,,,,,,
6101,skill_name_6101,,,,,,atk_fire,1173,3,reds,,max,0,150,6,0.2,720,0,0.2,0,,0,2,0,,skill_info_6101,,,,,20,,
6102,skill_name_6102,,,,,,atk_s4,1173,3,yellow,,max,0,150,6,0.2,720,0,0.2,0,,0,2,0,,skill_info_6102,,,,,,20,
6103,skill_name_6103,,,,,,atk_fire,1173,3,reds,,max,1,150,6,0.2,720,0,0.2,0,,1,2,0,,skill_info_6103,,,,,,20,
6104,skill_name_6104,,,,,,arrow_big_yellow,1135,3,yellow,,max,0,100,6,0.2,720,0,0.2,0,,1,0,2,,skill_info_6104,,,,,,20,
6105,skill_name_6105,,,,,,atk_fire,1173,3,blues,,max,1,150,6,0.2,720,0,0.2,0,,1,2,0,,skill_info_6105,0,,,,,,
6106,skill_name_6106,,,,,,atk_fire,1173,3,reds,,max,1,150,6,0.2,720,0,0.2,0,,1,2,0,,skill_info_6106,,,,,20,,
6301,skill_name_6301,,,,,,buff_wind,1255,0,up_blue,,atk,0,3,1,0.2,720,0,0.2,0,,2,2,0,,skill_info_6301,,,,,,,2
6302,skill_name_6302,,,,,,buff_wind,1292,2,up_green,,atk,0,300,1,0.2,720,0,0.2,0,,2,2,0,,skill_info_6302,,,,,,,1
6303,skill_name_6303,,,,,,buff_wind,1255,0,up_blue,,atk,0,3,1,0.2,720,0,0.2,0,,2,2,0,,skill_info_6303,,,,,,,2
6304,skill_name_6304,,,,,,buff_wind,1292,2,up_green,,atk,0,200,3,0.2,720,0,0.2,0,,2,2,0,,skill_info_6304,,,,,,,1
6305,skill_name_6305,,,,,,buff_wind,1255,2,up_blue,,atk,0,2,3,0.2,720,0,0.2,0,,2,2,0,,skill_info_6305,,,,,,,2
6401,skill_name_6401,,,,,,buff_wind,1255,2,up_ap,,atk,0,0,1,0.2,720,0,0.2,0,,2,2,0,ap:5,skill_info_6401,,,,,,,3
6402,skill_name_6402,,,,,,buff_wind,1255,2,up_hp,,atk,0,0,1,0.2,720,0,0.2,0,,2,2,0,hp_max:20,skill_info_6402,,,,,,,3
6403,skill_name_6403,,,,,,buff_wind,1255,2,up_hp,,atk,0,0,1,0.2,720,0,0.2,0,,2,2,0,ap:5|hp_max:20,skill_info_6403,,,,,,,3
6404,skill_name_6404,,,,,,buff_wind,1255,2,up_ap,,atk,0,0,3,0.2,720,0,0.2,0,,2,2,0,ap:2,skill_info_6404,,,,,,,3
6405,skill_name_6405,,,,,,buff_wind,1255,2,up_hp,,atk,0,0,3,0.2,720,0,0.2,0,,2,2,0,hp_max:10,skill_info_6405,,,,,,,3
6406,skill_name_6406,,,,,,buff_wind,1255,2,up_ap,,atk,0,0,3,0.2,720,0,0.2,0,,2,2,0,ap:2|hp_max:10,skill_info_6406,,,,,,,3
6501,skill_name_6501,,,,,,buff_wind,1255,0,up_ap,,atk,0,50,3,0.2,720,0,0.2,0,,2,2,0,,skill_info_6501,,,,,,,3
1 uuid name path fac cards_lv lv type sp_name icon TGroup readyAnm endAnm act DTType ap hit_count hitcd speed with ready EAnm DAnm IType RType EType buffs info frz bezier_start_y bezier_mid_y bezier_arc bck crt kind
2 6001 skill_name_6001 atk 1026 3 atk 0 100 1 0.2 720 0 0.2 0 0 0 2 skill_info_6001
3 6002 skill_name_6002 ball_fire 1126 3 atk 0 100 1 0.3 720 90 0.2 0 1 1 2 skill_info_6002 0
4 6003 skill_name_6003 ball_winds 1126 3 atk 0 100 1 0.3 720 90 0.2 0 1 1 2 skill_info_6003
5 6004 skill_name_6004 ball_zi 1126 3 atk 0 100 1 0.3 720 90 0.2 0 1 0 2 skill_info_6004
6 6005 skill_name_6005 arrow 1135 3 atk 0 100 1 0.2 720 0 0.2 0 1 1 2 skill_info_6005 20 140 1.05
7 6007 skill_name_6007 ball_forst 1126 3 atk 0 100 1 0.3 720 90 0.2 0 1 1 2 skill_info_6007
8 6007 skill_name_6008 ball_water 1126 3 atk 0 100 1 0.3 720 90 0.2 0 1 1 2 skill_info_6008
9 6101 skill_name_6101 atk_fire 1173 3 reds max 0 150 6 0.2 720 0 0.2 0 0 2 0 skill_info_6101 20
10 6102 skill_name_6102 atk_s4 1173 3 yellow max 0 150 6 0.2 720 0 0.2 0 0 2 0 skill_info_6102 20
11 6103 skill_name_6103 atk_fire 1173 3 reds max 1 150 6 0.2 720 0 0.2 0 1 2 0 skill_info_6103 20
12 6104 skill_name_6104 arrow_big_yellow 1135 3 yellow max 0 100 6 0.2 720 0 0.2 0 1 0 2 skill_info_6104 20
13 6105 skill_name_6105 atk_fire 1173 3 blues max 1 150 6 0.2 720 0 0.2 0 1 2 0 skill_info_6105 0
14 6106 skill_name_6106 atk_fire 1173 3 reds max 1 150 6 0.2 720 0 0.2 0 1 2 0 skill_info_6106 20
15 6301 skill_name_6301 buff_wind 1255 0 up_blue atk 0 3 1 0.2 720 0 0.2 0 2 2 0 skill_info_6301 2
16 6302 skill_name_6302 buff_wind 1292 2 up_green atk 0 300 1 0.2 720 0 0.2 0 2 2 0 skill_info_6302 1
17 6303 skill_name_6303 buff_wind 1255 0 up_blue atk 0 3 1 0.2 720 0 0.2 0 2 2 0 skill_info_6303 2
18 6304 skill_name_6304 buff_wind 1292 2 up_green atk 0 200 3 0.2 720 0 0.2 0 2 2 0 skill_info_6304 1
19 6305 skill_name_6305 buff_wind 1255 2 up_blue atk 0 2 3 0.2 720 0 0.2 0 2 2 0 skill_info_6305 2
20 6401 skill_name_6401 buff_wind 1255 2 up_ap atk 0 0 1 0.2 720 0 0.2 0 2 2 0 ap:5 skill_info_6401 3
21 6402 skill_name_6402 buff_wind 1255 2 up_hp atk 0 0 1 0.2 720 0 0.2 0 2 2 0 hp_max:20 skill_info_6402 3
22 6403 skill_name_6403 buff_wind 1255 2 up_hp atk 0 0 1 0.2 720 0 0.2 0 2 2 0 ap:5|hp_max:20 skill_info_6403 3
23 6404 skill_name_6404 buff_wind 1255 2 up_ap atk 0 0 3 0.2 720 0 0.2 0 2 2 0 ap:2 skill_info_6404 3
24 6405 skill_name_6405 buff_wind 1255 2 up_hp atk 0 0 3 0.2 720 0 0.2 0 2 2 0 hp_max:10 skill_info_6405 3
25 6406 skill_name_6406 buff_wind 1255 2 up_ap atk 0 0 3 0.2 720 0 0.2 0 2 2 0 ap:2|hp_max:10 skill_info_6406 3
26 6501 skill_name_6501 buff_wind 1255 0 up_ap atk 0 50 3 0.2 720 0 0.2 0 2 2 0 skill_info_6501 3

View File

@@ -1,11 +0,0 @@
{
"ver": "1.0.1",
"importer": "text",
"imported": true,
"uuid": "f1181369-d7bf-401c-8ec5-c5cbc520ff20",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}

View File

@@ -86,8 +86,6 @@ export class MissionCardComp extends CCComp {
/** 英雄抽卡面板(战斗阶段收起,准备阶段展开) */
@property(Node)
showCards: Node = null!
@property(Node)
cardPanNode: Node = null!
@property(Node)
cards_node: Node = null!
@@ -108,8 +106,6 @@ export class MissionCardComp extends CCComp {
herosPanNode: Node = null!
@property(Node)
herosBoxNode: Node = null!
@property(Prefab)
heroPrefab: Prefab = null!
/** 装备面板显示按钮 */
@property(Node)
@@ -160,6 +156,9 @@ export class MissionCardComp extends CCComp {
/** 英雄数量显示节点(含 icon + num 子节点) */
@property(Node)
hero_num_node: Node = null!
/** 刷新石数量显示节点(含 icon + num 子节点) */
@property(Node)
refresh_stone_num_node: Node = null!
// ======================== 运行时状态 ========================
@@ -240,9 +239,6 @@ export class MissionCardComp extends CCComp {
if (this.showHeros && this.showHeros.isValid) {
this.showHeros.off(NodeEventType.TOUCH_END, this.onShowHerosClick, this);
}
if (this.showCards && this.showCards.isValid) {
this.showCards.off(NodeEventType.TOUCH_END, this.onShowCardsClick, this);
}
if (this.closeCards && this.closeCards.isValid) {
this.closeCards.off(NodeEventType.TOUCH_END, this.onCloseCardsClick, this);
}
@@ -391,8 +387,7 @@ export class MissionCardComp extends CCComp {
this.cards_chou?.on(NodeEventType.TOUCH_END, this.onDrawTouchEnd, this);
this.cards_chou?.on(NodeEventType.TOUCH_CANCEL, this.onDrawTouchCancel, this);
/** 显示卡牌面板按钮 */
this.showCards?.on(NodeEventType.TOUCH_END, this.onShowCardsClick, this);
/** 隐藏卡牌面板按钮 */
this.closeCards?.on(NodeEventType.TOUCH_END, this.onCloseCardsClick, this);
@@ -438,9 +433,14 @@ export class MissionCardComp extends CCComp {
}
}
/** 刷新石数量变更:刷新刷新按钮的可用状态费用显示 */
private onRefreshStone() {
/** 刷新石数量变更:刷新刷新按钮状态/费用显示,并播放数量变化动画 */
private onRefreshStone(event: string, args: any) {
const payload = args ?? event;
const v = typeof payload === 'number' ? payload : (payload?.delta ?? payload?.value ?? 0);
this.updateDrawCostUI();
if (v !== 0) {
this.playRefreshStoneChangeAnim(v > 0);
}
}
/** 战斗开始:保留卡牌面板,允许玩家在战斗阶段继续抽卡和召唤英雄 */
@@ -641,9 +641,7 @@ export class MissionCardComp extends CCComp {
if (this.showHeros && this.showHeros.isValid) {
this.showHeros.off(NodeEventType.TOUCH_END, this.onShowHerosClick, this);
}
if (this.showCards && this.showCards.isValid) {
this.showCards.off(NodeEventType.TOUCH_END, this.onShowCardsClick, this);
}
if (this.closeCards && this.closeCards.isValid) {
this.closeCards.off(NodeEventType.TOUCH_END, this.onCloseCardsClick, this);
}
@@ -968,7 +966,7 @@ export class MissionCardComp extends CCComp {
/**
* 同步英雄信息盒槽位与场上英雄:
* 1. 确保 herosBoxNode 下存在 3 个 HeroBoxComp 槽位(复用 + 实例化补充)。
* 1. 刷新 herosBoxNode 下 HeroBoxComp 槽位缓存(编辑器已预放 3 个)。
* 2. 查询当前存活英雄列表,按序绑定到槽位。
* 3. 多余槽位显示空英雄信息。
*
@@ -977,7 +975,7 @@ export class MissionCardComp extends CCComp {
private refreshHeroBoxSlots() {
if (!this.herosBoxNode || !this.herosBoxNode.isValid) return;
this.ensureHeroBoxSlots(3);
this.ensureHeroBoxSlots();
// 查询场上存活英雄(含复活中的实体,按 eid 升序保证稳定顺序)
const actors: Array<{ eid: number, model: HeroAttrsComp }> = [];
@@ -1005,28 +1003,15 @@ export class MissionCardComp extends CCComp {
}
/**
* 确保英雄信息盒槽位数量足够
* 优先复用 herosBoxNode 现有子节点,不足时从 heroPrefab 实例化补充。
* 缓存英雄信息盒槽位组件引用
* 槽位已在编辑器中预先放置herosBoxNode 下挂 HeroBoxComp
* 运行时仅刷新缓存,不再动态实例化。
*/
private ensureHeroBoxSlots(targetCount: number) {
private ensureHeroBoxSlots() {
if (!this.herosBoxNode || !this.herosBoxNode.isValid) return;
// 刷新缓存
this.heroBoxComps = this.herosBoxNode.children
.map(node => node.getComponent(HeroBoxComp))
.filter((comp): comp is HeroBoxComp => !!comp);
// 补充实例化不足的槽位
while (this.heroBoxComps.length < targetCount) {
if (!this.heroPrefab) break;
const node = instantiate(this.heroPrefab);
// 先禁用根节点 Widget 再挂到父节点,避免 lateUpdate 覆盖 position
const widget = node.getComponent(Widget);
if (widget) widget.enabled = false;
this.herosBoxNode.addChild(node);
const comp = node.getComponent(HeroBoxComp) || node.addComponent(HeroBoxComp);
this.heroBoxComps.push(comp);
}
}
/**
@@ -1699,10 +1684,11 @@ export class MissionCardComp extends CCComp {
private updateDrawCostUI() {
const stones = MissionEconomy.getRefreshStone();
this.updateOneRefreshBtnUI(this.cards_chou, stones);
this.updateOneRefreshBtnUI(this.equip_refresh, stones);
this.updateOneRefreshBtnUI(this.shop_refresh, stones);
this.updateOneRefreshBtnUI(this.skill_refresh, stones);
const stoneCost = MissionEconomy.getRefreshStoneCost();
this.updateOneRefreshBtnUI(this.cards_chou, stones, stoneCost);
this.updateOneRefreshBtnUI(this.equip_refresh, stones, stoneCost);
this.updateOneRefreshBtnUI(this.shop_refresh, stones, stoneCost);
this.updateOneRefreshBtnUI(this.skill_refresh, stones, stoneCost);
}
/**
@@ -1717,11 +1703,13 @@ export class MissionCardComp extends CCComp {
*
* @param btnNode 刷新按钮节点
* @param stones 当前刷新石数量(外部统一读取,避免 4 次重复访问)
* @param stoneCost 单次刷新消耗的刷新石数量
*/
private updateOneRefreshBtnUI(btnNode: Node | null, stones: number) {
private updateOneRefreshBtnUI(btnNode: Node | null, stones: number, stoneCost: number) {
if (!btnNode || !btnNode.isValid) return;
const useStone = stones > 0;
// 刷新石足够一次消耗时走刷新石通道,否则走金币通道
const useStone = stones >= stoneCost;
// 置灰遮罩:有刷新石必定可刷新,否则按金币判断
const nobg = btnNode.getChildByName("nobg");
@@ -1745,14 +1733,14 @@ export class MissionCardComp extends CCComp {
}
}
// 刷新石费用节点(显示当前持有数量)
// 刷新石费用节点(显示单次刷新消耗数量)
const stoneNode = container.getChildByName("stone");
if (stoneNode) {
stoneNode.active = useStone;
if (useStone) {
const numLabel = stoneNode.getChildByName("num")?.getComponent(Label);
if (numLabel) {
numLabel.string = `${stones}`;
numLabel.string = `${stoneCost}`;
}
}
}
@@ -1773,6 +1761,16 @@ export class MissionCardComp extends CCComp {
this.playHeroNumNodePop(num, peak);
}
/** 刷新石计数变化动画(与金币一致的 icon+num 弹跳) */
private playRefreshStoneChangeAnim(isIncrease: boolean) {
if (!this.refresh_stone_num_node || !this.refresh_stone_num_node.isValid) return;
const peak = isIncrease ? 1.2 : 1.2;
const icon = this.refresh_stone_num_node.getChildByName("icon");
if (icon && icon.isValid) this.playHeroNumNodePop(icon, peak);
const num = this.refresh_stone_num_node.getChildByName("num");
if (num && num.isValid) this.playHeroNumNodePop(num, peak);
}
public setHeroMaxCount(max: number) {
const missionData = this.getMissionData();
if (!missionData) return;

View File

@@ -1,6 +1,7 @@
import { smc } from "../common/SingletonModuleComp";
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { FightSet } from "../common/config/GameSet";
import { FieldSkillType } from "../common/config/SkillSet";
import { FieldSkillHelper } from "../hero/FieldSkillHelper";
@@ -70,26 +71,32 @@ export class MissionEconomy {
oops.message.dispatchEvent(GameEvent.RefreshStone, { delta: amount });
}
/** 单次刷新消耗的刷新石数量 */
static getRefreshStoneCost(): number {
return Math.max(1, Math.floor(FightSet.REFRESH_STONE_COST));
}
/**
* 判断当前是否可以执行一次刷新(刷新石或金币足够)
* 判断当前是否可以执行一次刷新(刷新石足够或金币足够)
*/
static canRefresh(baseCost: number = 1): boolean {
if (this.getRefreshStone() > 0) return true;
if (this.getRefreshStone() >= this.getRefreshStoneCost()) return true;
return this.getCoin() >= this.getRefreshCost(baseCost);
}
/**
/**
* 执行刷新卡牌:
* 1. 刷新石 > 0 时优先扣除 1 颗刷新石(不消耗金币)。
* 1. 刷新石足够时优先扣除 REFRESH_STONE_COST 颗刷新石(不消耗金币)。
* 2. 刷新石不足时扣除金币(含刷新优惠折扣)。
*/
static executeRefresh(baseCost: number = 1): boolean {
// 优先消耗刷新石
const stoneCost = this.getRefreshStoneCost();
const stones = this.getRefreshStone();
if (stones > 0) {
smc.vmdata.mission_data.refresh_stone = stones - 1;
if (stones >= stoneCost) {
smc.vmdata.mission_data.refresh_stone = stones - stoneCost;
smc.vmdata.scores.refresh_count++;
oops.message.dispatchEvent(GameEvent.RefreshStone, { delta: -1 });
oops.message.dispatchEvent(GameEvent.RefreshStone, { delta: -stoneCost });
return true;
}