feat(物品系统): 添加物品使用功能及相关配置
- 在GameEvent枚举中添加UseItemCard事件 - 创建ItemSet物品配置表,包含8种不同效果的物品 - 在HeroAttrsComp中添加物品使用逻辑,处理物品效果应用 - 修改MissionCardComp支持物品购买界面和购买逻辑 - 添加物品购买后的视觉反馈和状态管理
This commit is contained in:
@@ -48,6 +48,7 @@ export enum GameEvent {
|
||||
FuncSelect = "FuncSelect",
|
||||
TalentSelect = "TalentSelect",
|
||||
UseTalentCard = "UseTalentCard",
|
||||
UseItemCard = "UseItemCard",
|
||||
NewWave = "NewWave",
|
||||
AD_BACK_TRUE = "AD_BACK_TRUE",
|
||||
AD_BACK_FALSE = "AD_BACK_FALSE",
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
import { Attrs, BType } from "./HeroAttrs";
|
||||
|
||||
/**
|
||||
* 物品配置接口
|
||||
*/
|
||||
export interface ItemConf {
|
||||
id: number;
|
||||
name: string;
|
||||
desc: string;
|
||||
price: number;
|
||||
duration: number; // 持续时间(秒)
|
||||
attr: Attrs; // 提升的属性
|
||||
value: number; // 提升的值
|
||||
bType: BType; // 值类型(数值/百分比)
|
||||
}
|
||||
|
||||
/**
|
||||
* 物品配置表
|
||||
* 20秒强效果,60秒弱效果
|
||||
*/
|
||||
export const ItemSet: Record<number, ItemConf> = {
|
||||
// ==================== 20秒强效果 (价格: 100) ====================
|
||||
1001: {
|
||||
id: 1001,
|
||||
name: "狂暴药水",
|
||||
desc: "20秒内攻击力+50%",
|
||||
price: 100,
|
||||
duration: 20,
|
||||
attr: Attrs.AP,
|
||||
value: 50,
|
||||
bType: BType.RATIO
|
||||
},
|
||||
1002: {
|
||||
id: 1002,
|
||||
name: "急速药水",
|
||||
desc: "20秒内攻速+50%",
|
||||
price: 100,
|
||||
duration: 20,
|
||||
attr: Attrs.AS,
|
||||
value: 50,
|
||||
bType: BType.RATIO
|
||||
},
|
||||
1003: {
|
||||
id: 1003,
|
||||
name: "金钟罩",
|
||||
desc: "20秒内防御+50%",
|
||||
price: 100,
|
||||
duration: 20,
|
||||
attr: Attrs.DEF,
|
||||
value: 50,
|
||||
bType: BType.RATIO
|
||||
},
|
||||
1004: {
|
||||
id: 1004,
|
||||
name: "神行药水",
|
||||
desc: "20秒内移速+50%",
|
||||
price: 100,
|
||||
duration: 20,
|
||||
attr: Attrs.SPEED,
|
||||
value: 50,
|
||||
bType: BType.RATIO
|
||||
},
|
||||
|
||||
// ==================== 60秒弱效果 (价格: 50) ====================
|
||||
2001: {
|
||||
id: 2001,
|
||||
name: "力量药剂",
|
||||
desc: "60秒内攻击力+20%",
|
||||
price: 50,
|
||||
duration: 60,
|
||||
attr: Attrs.AP,
|
||||
value: 20,
|
||||
bType: BType.RATIO
|
||||
},
|
||||
2002: {
|
||||
id: 2002,
|
||||
name: "敏捷药剂",
|
||||
desc: "60秒内攻速+20%",
|
||||
price: 50,
|
||||
duration: 60,
|
||||
attr: Attrs.AS,
|
||||
value: 20,
|
||||
bType: BType.RATIO
|
||||
},
|
||||
2003: {
|
||||
id: 2003,
|
||||
name: "护甲药剂",
|
||||
desc: "60秒内防御+20%",
|
||||
price: 50,
|
||||
duration: 60,
|
||||
attr: Attrs.DEF,
|
||||
value: 20,
|
||||
bType: BType.RATIO
|
||||
},
|
||||
2004: {
|
||||
id: 2004,
|
||||
name: "轻灵药剂",
|
||||
desc: "60秒内移速+20%",
|
||||
price: 50,
|
||||
duration: 60,
|
||||
attr: Attrs.SPEED,
|
||||
value: 20,
|
||||
bType: BType.RATIO
|
||||
},
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ import { BuffConf } from "../common/config/SkillSet";
|
||||
import { HeroInfo, AttrSet } from "../common/config/heroSet";
|
||||
import { HeroSkillsComp } from "./HeroSkills";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import { ItemSet } from "../common/config/ItemSet";
|
||||
|
||||
|
||||
interface talTrigger{
|
||||
@@ -78,10 +79,17 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
onLoad() {
|
||||
// 监听升级事件
|
||||
oops.message.on(GameEvent.CanUpdateLv, this.onLevelUp, this);
|
||||
oops.message.on(GameEvent.UseItemCard, this.onUseItemCard, this);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
oops.message.off(GameEvent.CanUpdateLv, this.onLevelUp, this);
|
||||
oops.message.off(GameEvent.UseItemCard, this.onUseItemCard, this);
|
||||
}
|
||||
|
||||
onUseItemCard(event: string, args: any) {
|
||||
if (!this.is_master) return;
|
||||
this.useItem(args);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -579,9 +587,40 @@ export class HeroAttrsComp extends ecs.Comp {
|
||||
useValueTalByUuid(t_uuid: number) {
|
||||
const buff = this.BUFFS_TAL[t_uuid];
|
||||
if (!buff) return;
|
||||
const attrIndex = buff.attrIndex;
|
||||
delete this.BUFFS_TAL[t_uuid];
|
||||
buff.count--;
|
||||
if (buff.count <= 0) {
|
||||
delete this.BUFFS_TAL[t_uuid];
|
||||
}
|
||||
this.recalculateSingleAttr(buff.attrIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用物品
|
||||
* @param itemId 物品ID
|
||||
*/
|
||||
useItem(itemId: number) {
|
||||
const item = ItemSet[itemId];
|
||||
if (!item) return;
|
||||
|
||||
console.log(`[HeroAttrs] 使用物品: ${item.name} (${item.desc})`);
|
||||
|
||||
// 直接添加到 BUFFS_TEMP
|
||||
const attrIndex = item.attr;
|
||||
|
||||
if (!this.BUFFS_TEMP[attrIndex]) {
|
||||
this.BUFFS_TEMP[attrIndex] = [];
|
||||
}
|
||||
|
||||
this.BUFFS_TEMP[attrIndex].push({
|
||||
value: item.value,
|
||||
BType: item.bType,
|
||||
remainTime: item.duration
|
||||
});
|
||||
|
||||
// 重新计算受影响的属性
|
||||
this.recalculateSingleAttr(attrIndex);
|
||||
|
||||
oops.gui.toast(`使用了 ${item.name}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { _decorator, Label, Node, tween, Vec3 } from "cc";
|
||||
import { _decorator, Label, Node, tween, Vec3, Color, Sprite } from "cc";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||
import { GameEvent } from "../common/config/GameEvent";
|
||||
import { talConf, ItalConf } from "../common/config/TalSet";
|
||||
import { ItemSet } from "../common/config/ItemSet";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@@ -34,13 +36,18 @@ export class MissionCardComp extends CCComp {
|
||||
|
||||
// 当前卡片类型
|
||||
curCardType: CardType = CardType.Talent;
|
||||
|
||||
// 已购买的卡片槽位标记 (用于物品购买)
|
||||
purchasedSlots: boolean[] = [false, false, false, false, false];
|
||||
|
||||
onLoad() {
|
||||
oops.message.on(GameEvent.TalentSelect, this.onTalentSelect, this);
|
||||
oops.message.on(GameEvent.ShopOpen, this.onShopOpen, this);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
oops.message.off(GameEvent.TalentSelect, this.onTalentSelect, this);
|
||||
oops.message.off(GameEvent.ShopOpen, this.onShopOpen, this);
|
||||
this.ent.destroy();
|
||||
}
|
||||
|
||||
@@ -56,13 +63,28 @@ export class MissionCardComp extends CCComp {
|
||||
if (card) {
|
||||
const selected = card.getChildByName("selected");
|
||||
if (selected) selected.active = false;
|
||||
// 恢复缩放和颜色
|
||||
card.setScale(1, 1, 1);
|
||||
const sprite = card.getComponent(Sprite);
|
||||
if (sprite) sprite.color = new Color(255, 255, 255);
|
||||
}
|
||||
});
|
||||
// 重置购买状态
|
||||
this.purchasedSlots = [false, false, false, false, false];
|
||||
}
|
||||
|
||||
// 是否已经选择了天赋
|
||||
private hasSelected: boolean = false;
|
||||
|
||||
private onShopOpen(event: string, args: any) {
|
||||
this.node.active = true;
|
||||
this.hasSelected = false;
|
||||
this.curCardType = CardType.Potion;
|
||||
this.resetCardStates();
|
||||
this.refCards();
|
||||
this.playShowAnimation();
|
||||
}
|
||||
|
||||
private onTalentSelect(event: string, args: any) {
|
||||
this.node.active = true;
|
||||
this.hasSelected = false; // 重置选择状态
|
||||
@@ -180,6 +202,47 @@ export class MissionCardComp extends CCComp {
|
||||
}
|
||||
|
||||
if (selectedData && selectedCardNode) {
|
||||
// 处理物品购买逻辑
|
||||
if (this.curCardType === CardType.Potion) {
|
||||
if (this.purchasedSlots[_index]) {
|
||||
oops.gui.toast("该物品已购买");
|
||||
return;
|
||||
}
|
||||
|
||||
if (smc.vmdata.gold < selectedData.price) {
|
||||
oops.gui.toast("金币不足");
|
||||
return;
|
||||
}
|
||||
|
||||
// 扣除金币
|
||||
smc.updateGold(-selectedData.price);
|
||||
|
||||
// 发送使用物品事件
|
||||
oops.message.dispatchEvent(GameEvent.UseItemCard, selectedData.id);
|
||||
|
||||
// 标记已购买
|
||||
this.purchasedSlots[_index] = true;
|
||||
|
||||
// 视觉反馈 (变灰)
|
||||
const sprite = selectedCardNode.getComponent(Sprite);
|
||||
if (sprite) sprite.color = new Color(150, 150, 150);
|
||||
|
||||
oops.gui.toast("购买成功");
|
||||
|
||||
// 检查是否所有卡片都已购买,如果是则关闭
|
||||
let allPurchased = true;
|
||||
// 检查当前显示的卡片是否都买了
|
||||
if (this.card1.active && !this.purchasedSlots[1]) allPurchased = false;
|
||||
if (this.card2.active && !this.purchasedSlots[2]) allPurchased = false;
|
||||
if (this.card3.active && !this.purchasedSlots[3]) allPurchased = false;
|
||||
if (this.card4.active && !this.purchasedSlots[4]) allPurchased = false;
|
||||
|
||||
if (allPurchased) {
|
||||
this.node.active = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.hasSelected = true;
|
||||
console.log("选择卡片:", selectedData.name, "类型:", this.curCardType);
|
||||
|
||||
@@ -216,6 +279,13 @@ export class MissionCardComp extends CCComp {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭界面
|
||||
*/
|
||||
close() {
|
||||
this.node.active = false;
|
||||
}
|
||||
|
||||
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
||||
reset() {
|
||||
this.node.destroy();
|
||||
|
||||
Reference in New Issue
Block a user