feat(talent): 引入天赋碎片系统替换通用天赋点
- 新增 TalentFragmentType 枚举和 TalentFragmentInfo 接口定义碎片类型 - 在 SingletonModuleComp 中新增 talent_fragments 字段存储碎片库存,talent_points 改为可选字段以兼容旧存档 - 为每个天赋配置 fragmentType 指定升级所需的具体碎片类型 - 修改 TalentsComp 升级逻辑,从消耗天赋点改为扣除对应类型的碎片 - 重置天赋功能现在返还已消耗的碎片而非天赋点 - 更新界面显示,展示碎片库存摘要和具体消耗
This commit is contained in:
@@ -8,7 +8,7 @@ import { WxCloudApi } from "../wx_clound_client_api/WxCloudApi";
|
|||||||
import { GameEvent } from "./config/GameEvent";
|
import { GameEvent } from "./config/GameEvent";
|
||||||
import { GameScoreStats } from "./config/HeroAttrs";
|
import { GameScoreStats } from "./config/HeroAttrs";
|
||||||
import { mLogger } from "./Logger";
|
import { mLogger } from "./Logger";
|
||||||
import { TalentType } from "./config/TalentSet";
|
import { TalentFragmentType, TalentType } from "./config/TalentSet";
|
||||||
import { gameDataSync } from "./GameDataSync";
|
import { gameDataSync } from "./GameDataSync";
|
||||||
import { FightSet } from "./config/GameSet";
|
import { FightSet } from "./config/GameSet";
|
||||||
|
|
||||||
@@ -23,7 +23,8 @@ export interface GameDate{
|
|||||||
talents: Partial<Record<TalentType, number>>,
|
talents: Partial<Record<TalentType, number>>,
|
||||||
player_level: number,
|
player_level: number,
|
||||||
player_exp: number,
|
player_exp: number,
|
||||||
talent_points: number,
|
talent_fragments: Partial<Record<TalentFragmentType, number>>,
|
||||||
|
talent_points?: number,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export interface CloudData {
|
export interface CloudData {
|
||||||
@@ -66,12 +67,14 @@ export class SingletonModuleComp extends ecs.Comp {
|
|||||||
talents: Partial<Record<TalentType, number>>;
|
talents: Partial<Record<TalentType, number>>;
|
||||||
player_level: number;
|
player_level: number;
|
||||||
player_exp: number;
|
player_exp: number;
|
||||||
talent_points: number;
|
talent_fragments: Partial<Record<TalentFragmentType, number>>;
|
||||||
|
talent_points?: number;
|
||||||
} = {
|
} = {
|
||||||
talents: {}, // 存储各个天赋的等级: { talent_id: level }
|
talents: {}, // 存储各个天赋的等级: { talent_id: level }
|
||||||
player_level: 1, // 玩家等级
|
player_level: 1, // 玩家等级
|
||||||
player_exp: 0, // 玩家当前经验
|
player_exp: 0, // 玩家当前经验
|
||||||
talent_points: 0, // 当前可用天赋点
|
talent_fragments: {}, // 当前拥有的天赋碎片库存
|
||||||
|
talent_points: 0, // 兼容旧存档的历史字段
|
||||||
};
|
};
|
||||||
|
|
||||||
vmdata: any = {
|
vmdata: any = {
|
||||||
@@ -240,6 +243,7 @@ export class SingletonModuleComp extends ecs.Comp {
|
|||||||
if (remoteCol.talents) this.collection.talents = remoteCol.talents;
|
if (remoteCol.talents) this.collection.talents = remoteCol.talents;
|
||||||
if (typeof remoteCol.player_level === 'number') this.collection.player_level = remoteCol.player_level;
|
if (typeof remoteCol.player_level === 'number') this.collection.player_level = remoteCol.player_level;
|
||||||
if (typeof remoteCol.player_exp === 'number') this.collection.player_exp = remoteCol.player_exp;
|
if (typeof remoteCol.player_exp === 'number') this.collection.player_exp = remoteCol.player_exp;
|
||||||
|
if (remoteCol.talent_fragments) this.collection.talent_fragments = remoteCol.talent_fragments;
|
||||||
if (typeof remoteCol.talent_points === 'number') this.collection.talent_points = remoteCol.talent_points;
|
if (typeof remoteCol.talent_points === 'number') this.collection.talent_points = remoteCol.talent_points;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,28 @@ export enum TalentType {
|
|||||||
SellBonus = 11 // 出售补贴
|
SellBonus = 11 // 出售补贴
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum TalentFragmentType {
|
||||||
|
Power = 1, // 力量碎片
|
||||||
|
Tempest = 2, // 风暴碎片
|
||||||
|
Vitality = 3, // 生机碎片
|
||||||
|
Frost = 4, // 寒霜碎片
|
||||||
|
Tactics = 5, // 谋略碎片
|
||||||
|
Spirit = 6, // 灵契碎片
|
||||||
|
Trade = 7, // 商贸碎片
|
||||||
|
Fate = 8 // 命运碎片
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TalentFragmentInfo {
|
||||||
|
/** 碎片 ID */
|
||||||
|
id: TalentFragmentType;
|
||||||
|
/** 碎片名称 */
|
||||||
|
name: string;
|
||||||
|
/** 碎片图标或标识(可选) */
|
||||||
|
icon?: string;
|
||||||
|
/** 该碎片可用于哪些天赋,单个碎片最多映射 3 个天赋 */
|
||||||
|
talentIds: TalentType[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface TalentInfo {
|
export interface TalentInfo {
|
||||||
/** 天赋 ID */
|
/** 天赋 ID */
|
||||||
id: number;
|
id: number;
|
||||||
@@ -30,8 +52,10 @@ export interface TalentInfo {
|
|||||||
maxLevel: number;
|
maxLevel: number;
|
||||||
/** 每一级的加成数值,从第1级到最大级 */
|
/** 每一级的加成数值,从第1级到最大级 */
|
||||||
values: number[];
|
values: number[];
|
||||||
/** 升到每一级所需的消耗点数,从第1级到最大级 */
|
/** 每一级的消耗数量,下标 0 表示升到 1 级 */
|
||||||
costs: number[];
|
costs: number[];
|
||||||
|
/** 升级所需的单碎片类型 */
|
||||||
|
fragmentType: TalentFragmentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TalentConfig = {
|
export const TalentConfig = {
|
||||||
@@ -41,30 +65,42 @@ export const TalentConfig = {
|
|||||||
{ maxLevel: 20, expPerLevel: 150 },
|
{ maxLevel: 20, expPerLevel: 150 },
|
||||||
{ maxLevel: 30, expPerLevel: 200 }
|
{ maxLevel: 30, expPerLevel: 200 }
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// 天赋碎片配置:不同天赋可共用同一种碎片,单个碎片最多映射 3 个天赋
|
||||||
|
fragments: [
|
||||||
|
{ id: TalentFragmentType.Power, name: "力量碎片", icon: "◆", talentIds: [TalentType.Attack, TalentType.Critical, TalentType.Puncture] },
|
||||||
|
{ id: TalentFragmentType.Tempest, name: "风暴碎片", icon: "◇", talentIds: [TalentType.WindFury, TalentType.RefreshDiscount] },
|
||||||
|
{ id: TalentFragmentType.Vitality, name: "生机碎片", icon: "●", talentIds: [TalentType.Hp, TalentType.DeadTrigger, TalentType.Summon] },
|
||||||
|
{ id: TalentFragmentType.Frost, name: "寒霜碎片", icon: "○", talentIds: [TalentType.Freeze] },
|
||||||
|
{ id: TalentFragmentType.Tactics, name: "谋略碎片", icon: "■", talentIds: [TalentType.BuyDiscount] },
|
||||||
|
{ id: TalentFragmentType.Spirit, name: "灵契碎片", icon: "□", talentIds: [TalentType.SellBonus] },
|
||||||
|
{ id: TalentFragmentType.Trade, name: "商贸碎片", icon: "▲", talentIds: [] },
|
||||||
|
{ id: TalentFragmentType.Fate, name: "命运碎片", icon: "△", talentIds: [] }
|
||||||
|
] as TalentFragmentInfo[],
|
||||||
|
|
||||||
// 所有天赋定义(使用数组维护)
|
// 所有天赋定义(使用数组维护)
|
||||||
talents: [
|
talents: [
|
||||||
{ id: TalentType.Attack, name: "攻击强化", icon: "⚔️", desc: "所有英雄 ATK +{value}%",
|
{ id: TalentType.Attack, name: "攻击强化", icon: "⚔️", desc: "所有英雄 ATK +{value}%",
|
||||||
maxLevel: 5, values: [3, 6, 9, 12, 15], costs: [1, 1, 2, 2, 3] },
|
maxLevel: 5, values: [3, 6, 9, 12, 15], costs: [1, 1, 2, 2, 3], fragmentType: TalentFragmentType.Power },
|
||||||
{ id: TalentType.Hp, name: "生命强化", icon: "❤️", desc: "所有英雄 HP +{value}%",
|
{ id: TalentType.Hp, name: "生命强化", icon: "❤️", desc: "所有英雄 HP +{value}%",
|
||||||
maxLevel: 5, values: [5, 10, 15, 20, 25], costs: [1, 1, 2, 2, 3] },
|
maxLevel: 5, values: [5, 10, 15, 20, 25], costs: [1, 1, 2, 2, 3], fragmentType: TalentFragmentType.Vitality },
|
||||||
{ id: TalentType.Critical, name: "暴击强化", icon: "🔥", desc: "所有英雄暴击率 +{value}%",
|
{ id: TalentType.Critical, name: "暴击强化", icon: "🔥", desc: "所有英雄暴击率 +{value}%",
|
||||||
maxLevel: 5, values: [2, 4, 6, 8, 10], costs: [1, 1, 2, 2, 3] },
|
maxLevel: 5, values: [2, 4, 6, 8, 10], costs: [1, 1, 2, 2, 3], fragmentType: TalentFragmentType.Power },
|
||||||
{ id: TalentType.WindFury, name: "风怒强化", icon: "⚡", desc: "所有英雄风怒率 +{value}%",
|
{ id: TalentType.WindFury, name: "风怒强化", icon: "⚡", desc: "所有英雄风怒率 +{value}%",
|
||||||
maxLevel: 5, values: [2, 4, 6, 8, 10], costs: [1, 1, 2, 2, 3] },
|
maxLevel: 5, values: [2, 4, 6, 8, 10], costs: [1, 1, 2, 2, 3], fragmentType: TalentFragmentType.Tempest },
|
||||||
{ id: TalentType.Freeze, name: "冰冻强化", icon: "❄️", desc: "所有英雄冰冻率 +{value}%",
|
{ id: TalentType.Freeze, name: "冰冻强化", icon: "❄️", desc: "所有英雄冰冻率 +{value}%",
|
||||||
maxLevel: 5, values: [2, 4, 6, 8, 10], costs: [1, 1, 2, 2, 3] },
|
maxLevel: 5, values: [2, 4, 6, 8, 10], costs: [1, 1, 2, 2, 3], fragmentType: TalentFragmentType.Frost },
|
||||||
{ id: TalentType.Puncture, name: "穿刺强化", icon: "🗡️", desc: "所有英雄穿刺 +{value}",
|
{ id: TalentType.Puncture, name: "穿刺强化", icon: "🗡️", desc: "所有英雄穿刺 +{value}",
|
||||||
maxLevel: 5, values: [0.2, 0.4, 0.6, 0.8, 1.0], costs: [1, 1, 2, 2, 3] },
|
maxLevel: 5, values: [0.2, 0.4, 0.6, 0.8, 1.0], costs: [1, 1, 2, 2, 3], fragmentType: TalentFragmentType.Power },
|
||||||
{ id: TalentType.DeadTrigger, name: "亡语强化", icon: "🛡️", desc: "死亡触发技能额外触发次数+{value}次",
|
{ id: TalentType.DeadTrigger, name: "亡语强化", icon: "🛡️", desc: "死亡触发技能额外触发次数+{value}次",
|
||||||
maxLevel: 5, values: [1], costs: [25] },
|
maxLevel: 1, values: [1], costs: [25], fragmentType: TalentFragmentType.Vitality },
|
||||||
{ id: TalentType.Summon, name: "召唤强化", icon: "🛡️", desc: "召唤触发技能额外触发次数+{value}次",
|
{ id: TalentType.Summon, name: "召唤强化", icon: "🛡️", desc: "召唤触发技能额外触发次数+{value}次",
|
||||||
maxLevel: 1, values: [1], costs: [25] },
|
maxLevel: 1, values: [1], costs: [25], fragmentType: TalentFragmentType.Vitality },
|
||||||
{ id: TalentType.BuyDiscount, name: "采购优惠", icon: "🛒", desc: "购买英雄 -{value}金",
|
{ id: TalentType.BuyDiscount, name: "采购优惠", icon: "🛒", desc: "购买英雄 -{value}金",
|
||||||
maxLevel: 1, values: [1], costs: [10] },
|
maxLevel: 1, values: [1], costs: [10], fragmentType: TalentFragmentType.Tactics },
|
||||||
{ id: TalentType.RefreshDiscount, name: "刷新优惠", icon: "🔄", desc: "刷新重抽 -{value}金",
|
{ id: TalentType.RefreshDiscount, name: "刷新优惠", icon: "🔄", desc: "刷新重抽 -{value}金",
|
||||||
maxLevel: 1, values: [1], costs: [10] },
|
maxLevel: 1, values: [1], costs: [10], fragmentType: TalentFragmentType.Tempest },
|
||||||
{ id: TalentType.SellBonus, name: "出售补贴", icon: "💰", desc: "出售英雄返还 +{value}金币",
|
{ id: TalentType.SellBonus, name: "出售补贴", icon: "💰", desc: "出售英雄返还 +{value}金币",
|
||||||
maxLevel: 1, values: [1], costs: [10] }
|
maxLevel: 1, values: [1], costs: [10], fragmentType: TalentFragmentType.Spirit }
|
||||||
] as TalentInfo[]
|
] as TalentInfo[]
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/modu
|
|||||||
import { mLogger } from "../common/Logger";
|
import { mLogger } from "../common/Logger";
|
||||||
import { smc } from "../common/SingletonModuleComp";
|
import { smc } from "../common/SingletonModuleComp";
|
||||||
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||||
import { TalentConfig, TalentInfo, TalentType } from "../common/config/TalentSet";
|
import { TalentConfig, TalentFragmentInfo, TalentFragmentType, TalentInfo, TalentType } from "../common/config/TalentSet";
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -32,9 +32,9 @@ const { ccclass, property } = _decorator;
|
|||||||
* TalentsComp —— 天赋系统界面组件
|
* TalentsComp —— 天赋系统界面组件
|
||||||
*
|
*
|
||||||
* 职责:
|
* 职责:
|
||||||
* 1. 展示玩家等级、当前经验、进度条、可用天赋点。
|
* 1. 展示玩家等级、当前经验、进度条、碎片库存。
|
||||||
* 2. 展示天赋列表及每个天赋的当前等级。
|
* 2. 展示天赋列表及每个天赋的当前等级。
|
||||||
* 3. 处理天赋升级点击事件,扣除天赋点并保存。
|
* 3. 处理天赋升级点击事件,扣除碎片并保存。
|
||||||
* 4. 处理重置天赋(看广告)功能。
|
* 4. 处理重置天赋(看广告)功能。
|
||||||
*/
|
*/
|
||||||
@ccclass('TalentsComp')
|
@ccclass('TalentsComp')
|
||||||
@@ -53,7 +53,7 @@ export class TalentsComp extends CCComp {
|
|||||||
@property({ type: ProgressBar, tooltip: "经验进度条" })
|
@property({ type: ProgressBar, tooltip: "经验进度条" })
|
||||||
pb_exp: ProgressBar = null!;
|
pb_exp: ProgressBar = null!;
|
||||||
|
|
||||||
@property({ type: Label, tooltip: "当前可用天赋点数文本,例如 '4/30'" })
|
@property({ type: Label, tooltip: "当前碎片库存摘要文本" })
|
||||||
lbl_points: Label = null!;
|
lbl_points: Label = null!;
|
||||||
|
|
||||||
@property({ type: Node, tooltip: "天赋列表容器,用于动态添加天赋项" })
|
@property({ type: Node, tooltip: "天赋列表容器,用于动态添加天赋项" })
|
||||||
@@ -96,12 +96,12 @@ export class TalentsComp extends CCComp {
|
|||||||
this.updateTalentList();
|
this.updateTalentList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 更新玩家等级、经验、天赋点信息 */
|
/** 更新玩家等级、经验、碎片信息 */
|
||||||
private updatePlayerInfo() {
|
private updatePlayerInfo() {
|
||||||
const collection = smc.collection;
|
const collection = smc.collection;
|
||||||
let level = collection.player_level || 1;
|
let level = collection.player_level || 1;
|
||||||
let exp = collection.player_exp || 0;
|
let exp = collection.player_exp || 0;
|
||||||
let points = collection.talent_points || 0;
|
const fragmentSummary = this.getFragmentSummaryText();
|
||||||
|
|
||||||
// 限制最大等级
|
// 限制最大等级
|
||||||
if (level > this.MAX_PLAYER_LEVEL) {
|
if (level > this.MAX_PLAYER_LEVEL) {
|
||||||
@@ -109,7 +109,7 @@ export class TalentsComp extends CCComp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.lbl_level) this.lbl_level.string = `Lv.${level}`;
|
if (this.lbl_level) this.lbl_level.string = `Lv.${level}`;
|
||||||
if (this.lbl_points) this.lbl_points.string = `天赋点: ${points}/${this.MAX_PLAYER_LEVEL}`;
|
if (this.lbl_points) this.lbl_points.string = fragmentSummary;
|
||||||
|
|
||||||
// 计算当前等级升级所需经验
|
// 计算当前等级升级所需经验
|
||||||
let expRequired = this.getExpRequirement(level);
|
let expRequired = this.getExpRequirement(level);
|
||||||
@@ -179,31 +179,46 @@ export class TalentsComp extends CCComp {
|
|||||||
if (lblLevel) lblLevel.string = `Lv.${currentLevel}`;
|
if (lblLevel) lblLevel.string = `Lv.${currentLevel}`;
|
||||||
|
|
||||||
let isMax = currentLevel >= talentInfo.maxLevel;
|
let isMax = currentLevel >= talentInfo.maxLevel;
|
||||||
let cost = isMax ? 0 : talentInfo.costs[currentLevel];
|
const levelCost = isMax ? null : this.getLevelFragmentCost(talentInfo, currentLevel);
|
||||||
let points = smc.collection.talent_points || 0;
|
const canUpgrade = !!levelCost && this.hasEnoughFragments(levelCost);
|
||||||
|
|
||||||
if (lblCost) {
|
if (lblCost) {
|
||||||
lblCost.string = isMax ? "已满级" : `消耗: ${cost}点`;
|
lblCost.string = isMax ? "已满级" : `消耗: ${this.buildFragmentCostText(levelCost!)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (btnUpgrade) {
|
if (btnUpgrade) {
|
||||||
btnUpgrade.interactable = !isMax && points >= cost;
|
btnUpgrade.interactable = !isMax && canUpgrade;
|
||||||
// 清除旧的监听,避免重复绑定
|
// 清除旧的监听,避免重复绑定
|
||||||
btnUpgradeNode?.off(Button.EventType.CLICK);
|
btnUpgradeNode?.off(Button.EventType.CLICK);
|
||||||
btnUpgradeNode?.on(Button.EventType.CLICK, () => {
|
btnUpgradeNode?.on(Button.EventType.CLICK, () => {
|
||||||
this.onUpgradeClicked(talentInfo.id, currentLevel, cost);
|
this.onUpgradeClicked(talentInfo.id, currentLevel);
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 点击升级按钮 */
|
/** 点击升级按钮 */
|
||||||
private onUpgradeClicked(talentId: TalentType, currentLevel: number, cost: number) {
|
private onUpgradeClicked(talentId: TalentType, currentLevel: number) {
|
||||||
const collection = smc.collection;
|
const collection = smc.collection;
|
||||||
let points = collection.talent_points || 0;
|
const talentInfo = TalentConfig.talents.find(t => t.id === talentId);
|
||||||
|
if (!talentInfo) {
|
||||||
|
oops.gui.toast("天赋配置不存在");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (points >= cost && currentLevel < 5) {
|
if (currentLevel >= talentInfo.maxLevel) {
|
||||||
// 1. 扣除消耗
|
oops.gui.toast("该天赋已满级");
|
||||||
collection.talent_points -= cost;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const levelCost = this.getLevelFragmentCost(talentInfo, currentLevel);
|
||||||
|
if (!levelCost) {
|
||||||
|
oops.gui.toast("天赋消耗配置异常");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.hasEnoughFragments(levelCost)) {
|
||||||
|
// 1. 扣除单碎片消耗
|
||||||
|
this.consumeFragments(levelCost);
|
||||||
// 2. 更新等级
|
// 2. 更新等级
|
||||||
collection.talents[talentId] = currentLevel + 1;
|
collection.talents[talentId] = currentLevel + 1;
|
||||||
|
|
||||||
@@ -215,7 +230,7 @@ export class TalentsComp extends CCComp {
|
|||||||
|
|
||||||
oops.gui.toast("天赋升级成功");
|
oops.gui.toast("天赋升级成功");
|
||||||
} else {
|
} else {
|
||||||
oops.gui.toast("天赋点不足或已满级");
|
oops.gui.toast("碎片不足或已满级");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,26 +240,32 @@ export class TalentsComp extends CCComp {
|
|||||||
this.watch_ad().then(success => {
|
this.watch_ad().then(success => {
|
||||||
if (success) {
|
if (success) {
|
||||||
const collection = smc.collection;
|
const collection = smc.collection;
|
||||||
// 计算已消耗的天赋点总和
|
// 计算已消耗碎片并返还
|
||||||
let refundedPoints = 0;
|
const refundedFragments: Partial<Record<TalentFragmentType, number>> = {};
|
||||||
for (let id in collection.talents) {
|
for (let id in collection.talents) {
|
||||||
let talentId = Number(id) as TalentType;
|
let talentId = Number(id) as TalentType;
|
||||||
let level = collection.talents[talentId] || 0;
|
let level = collection.talents[talentId] || 0;
|
||||||
let talentInfo = TalentConfig.talents.find(t => t.id === talentId);
|
let talentInfo = TalentConfig.talents.find(t => t.id === talentId);
|
||||||
if (talentInfo) {
|
if (talentInfo) {
|
||||||
for (let i = 0; i < level; i++) {
|
for (let i = 0; i < level; i++) {
|
||||||
refundedPoints += talentInfo.costs[i];
|
const levelCost = this.getLevelFragmentCost(talentInfo, i);
|
||||||
|
if (!levelCost) continue;
|
||||||
|
refundedFragments[levelCost.type] = (refundedFragments[levelCost.type] || 0) + levelCost.amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置天赋等级并返还点数
|
// 重置天赋等级并返还碎片
|
||||||
collection.talents = {};
|
collection.talents = {};
|
||||||
collection.talent_points += refundedPoints;
|
if (!collection.talent_fragments) {
|
||||||
|
collection.talent_fragments = {};
|
||||||
// 限制不超过最大点数(30)
|
}
|
||||||
if (collection.talent_points > this.MAX_PLAYER_LEVEL) {
|
for (const fragmentType in refundedFragments) {
|
||||||
collection.talent_points = this.MAX_PLAYER_LEVEL;
|
const key = Number(fragmentType) as TalentFragmentType;
|
||||||
|
const amount = refundedFragments[key] || 0;
|
||||||
|
if (amount > 0) {
|
||||||
|
collection.talent_fragments[key] = (collection.talent_fragments[key] || 0) + amount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 同步到云端
|
// 同步到云端
|
||||||
@@ -252,13 +273,59 @@ export class TalentsComp extends CCComp {
|
|||||||
|
|
||||||
// 刷新界面
|
// 刷新界面
|
||||||
this.refreshUI();
|
this.refreshUI();
|
||||||
oops.gui.toast("天赋已重置,点数已返还");
|
oops.gui.toast("天赋已重置,碎片已返还");
|
||||||
} else {
|
} else {
|
||||||
oops.gui.toast("广告观看失败,无法重置");
|
oops.gui.toast("广告观看失败,无法重置");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 获取升级到下一等级所需的单碎片消耗 */
|
||||||
|
private getLevelFragmentCost(talentInfo: TalentInfo, currentLevel: number): { type: TalentFragmentType; amount: number } | null {
|
||||||
|
if (talentInfo.fragmentType === undefined) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: talentInfo.fragmentType,
|
||||||
|
amount: talentInfo.costs[currentLevel] ?? 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 判断当前库存是否满足一次升级 */
|
||||||
|
private hasEnoughFragments(cost: { type: TalentFragmentType; amount: number }): boolean {
|
||||||
|
const bag = smc.collection.talent_fragments || {};
|
||||||
|
return (bag[cost.type] || 0) >= cost.amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行碎片扣除 */
|
||||||
|
private consumeFragments(cost: { type: TalentFragmentType; amount: number }) {
|
||||||
|
const bag = smc.collection.talent_fragments || (smc.collection.talent_fragments = {});
|
||||||
|
bag[cost.type] = Math.max(0, (bag[cost.type] || 0) - cost.amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 生成单次升级消耗文案 */
|
||||||
|
private buildFragmentCostText(cost: { type: TalentFragmentType; amount: number }): string {
|
||||||
|
const info = this.getFragmentInfo(cost.type);
|
||||||
|
const own = smc.collection.talent_fragments?.[cost.type] || 0;
|
||||||
|
const fragmentName = info ? info.name : `碎片${cost.type}`;
|
||||||
|
return `${fragmentName} ${own}/${cost.amount}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 顶部碎片库存摘要 */
|
||||||
|
private getFragmentSummaryText(): string {
|
||||||
|
const bag = smc.collection.talent_fragments || {};
|
||||||
|
const summary = TalentConfig.fragments
|
||||||
|
.filter(fragment => (bag[fragment.id] || 0) > 0)
|
||||||
|
.map(fragment => `${fragment.name}:${bag[fragment.id] || 0}`)
|
||||||
|
.join(" ");
|
||||||
|
return summary ? `碎片: ${summary}` : "碎片: 暂无";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 按碎片类型查找碎片配置 */
|
||||||
|
private getFragmentInfo(type: TalentFragmentType): TalentFragmentInfo | undefined {
|
||||||
|
return TalentConfig.fragments.find(fragment => fragment.id === type);
|
||||||
|
}
|
||||||
|
|
||||||
/** 模拟看广告回调,实际项目中需要替换为真实的广告SDK调用 */
|
/** 模拟看广告回调,实际项目中需要替换为真实的广告SDK调用 */
|
||||||
private watch_ad(): Promise<boolean> {
|
private watch_ad(): Promise<boolean> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
@@ -282,4 +349,4 @@ export class TalentsComp extends CCComp {
|
|||||||
reset() {
|
reset() {
|
||||||
this.node.destroy();
|
this.node.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user