ShopManager.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. import { _decorator, Component, sys } from 'cc';
  2. import { ConfigManager, WeaponConfig } from '../Core/ConfigManager';
  3. const { ccclass, property } = _decorator;
  4. /**
  5. * 商店物品接口
  6. */
  7. export interface ShopItem {
  8. id: string;
  9. name: string;
  10. type: 'weapon' | 'upgrade' | 'consumable';
  11. price: number;
  12. currency: 'coin' | 'gem';
  13. weaponId?: string; // 如果是武器类型
  14. description: string;
  15. icon: string;
  16. available: boolean;
  17. purchased: boolean;
  18. maxPurchases?: number; // 最大购买次数,-1为无限
  19. currentPurchases?: number; // 当前购买次数
  20. }
  21. /**
  22. * 商店管理器
  23. * 负责物品购买、货币管理等功能
  24. */
  25. @ccclass('ShopManager')
  26. export class ShopManager extends Component {
  27. private static instance: ShopManager = null;
  28. private coins: number = 100; // 初始金币
  29. private gems: number = 10; // 初始宝石
  30. private shopItems: ShopItem[] = [];
  31. private purchasedItems: string[] = [];
  32. onLoad() {
  33. if (ShopManager.instance === null) {
  34. ShopManager.instance = this;
  35. this.loadShopData();
  36. this.initializeShopItems();
  37. } else if (ShopManager.instance !== this) {
  38. this.destroy();
  39. return;
  40. }
  41. }
  42. onDestroy() {
  43. if (ShopManager.instance === this) {
  44. ShopManager.instance = null;
  45. }
  46. }
  47. public static getInstance(): ShopManager {
  48. return ShopManager.instance;
  49. }
  50. // 初始化商店物品
  51. private initializeShopItems() {
  52. // 基础武器商店物品
  53. this.shopItems = [
  54. {
  55. id: 'weapon_basic_gun',
  56. name: '基础手枪',
  57. type: 'weapon',
  58. price: 50,
  59. currency: 'coin',
  60. weaponId: 'basic_gun',
  61. description: '基础的射击武器,伤害适中',
  62. icon: 'shop/weapon_basic_gun',
  63. available: true,
  64. purchased: false,
  65. maxPurchases: 1,
  66. currentPurchases: 0
  67. },
  68. {
  69. id: 'weapon_sniper',
  70. name: '狙击枪',
  71. type: 'weapon',
  72. price: 150,
  73. currency: 'coin',
  74. weaponId: 'sniper_rifle',
  75. description: '高伤害远程武器',
  76. icon: 'shop/weapon_sniper',
  77. available: true,
  78. purchased: false,
  79. maxPurchases: 1,
  80. currentPurchases: 0
  81. },
  82. {
  83. id: 'weapon_rocket',
  84. name: '火箭筒',
  85. type: 'weapon',
  86. price: 5,
  87. currency: 'gem',
  88. weaponId: 'rocket_launcher',
  89. description: '范围爆炸伤害武器',
  90. icon: 'shop/weapon_rocket',
  91. available: true,
  92. purchased: false,
  93. maxPurchases: 1,
  94. currentPurchases: 0
  95. },
  96. {
  97. id: 'upgrade_damage',
  98. name: '伤害提升',
  99. type: 'upgrade',
  100. price: 100,
  101. currency: 'coin',
  102. description: '永久增加所有武器10%伤害',
  103. icon: 'shop/upgrade_damage',
  104. available: true,
  105. purchased: false,
  106. maxPurchases: 5,
  107. currentPurchases: 0
  108. },
  109. {
  110. id: 'consumable_health_potion',
  111. name: '生命药水',
  112. type: 'consumable',
  113. price: 20,
  114. currency: 'coin',
  115. description: '恢复50点生命值',
  116. icon: 'shop/health_potion',
  117. available: true,
  118. purchased: false,
  119. maxPurchases: -1, // 无限购买
  120. currentPurchases: 0
  121. }
  122. ];
  123. }
  124. // 加载商店数据
  125. private loadShopData() {
  126. const savedData = sys.localStorage.getItem('shopData');
  127. if (savedData) {
  128. try {
  129. const data = JSON.parse(savedData);
  130. this.coins = data.coins || 100;
  131. this.gems = data.gems || 10;
  132. this.purchasedItems = data.purchasedItems || [];
  133. console.log('商店数据加载成功');
  134. } catch (error) {
  135. console.error('商店数据解析失败:', error);
  136. this.resetShopData();
  137. }
  138. }
  139. }
  140. // 保存商店数据
  141. private saveShopData() {
  142. const data = {
  143. coins: this.coins,
  144. gems: this.gems,
  145. purchasedItems: this.purchasedItems,
  146. shopItems: this.shopItems.map(item => ({
  147. id: item.id,
  148. purchased: item.purchased,
  149. currentPurchases: item.currentPurchases
  150. }))
  151. };
  152. try {
  153. sys.localStorage.setItem('shopData', JSON.stringify(data));
  154. console.log('商店数据保存成功');
  155. } catch (error) {
  156. console.error('商店数据保存失败:', error);
  157. }
  158. }
  159. // 重置商店数据
  160. private resetShopData() {
  161. this.coins = 100;
  162. this.gems = 10;
  163. this.purchasedItems = [];
  164. this.saveShopData();
  165. }
  166. // 获取金币数量
  167. public getCoins(): number {
  168. return this.coins;
  169. }
  170. // 获取宝石数量
  171. public getGems(): number {
  172. return this.gems;
  173. }
  174. // 添加金币
  175. public addCoins(amount: number) {
  176. this.coins += amount;
  177. this.saveShopData();
  178. console.log(`获得 ${amount} 金币,总计: ${this.coins}`);
  179. }
  180. // 添加宝石
  181. public addGems(amount: number) {
  182. this.gems += amount;
  183. this.saveShopData();
  184. console.log(`获得 ${amount} 宝石,总计: ${this.gems}`);
  185. }
  186. // 消费金币
  187. public spendCoins(amount: number): boolean {
  188. if (this.coins >= amount) {
  189. this.coins -= amount;
  190. this.saveShopData();
  191. console.log(`消费 ${amount} 金币,剩余: ${this.coins}`);
  192. return true;
  193. }
  194. console.warn(`金币不足,需要 ${amount},当前 ${this.coins}`);
  195. return false;
  196. }
  197. // 消费宝石
  198. public spendGems(amount: number): boolean {
  199. if (this.gems >= amount) {
  200. this.gems -= amount;
  201. this.saveShopData();
  202. console.log(`消费 ${amount} 宝石,剩余: ${this.gems}`);
  203. return true;
  204. }
  205. console.warn(`宝石不足,需要 ${amount},当前 ${this.gems}`);
  206. return false;
  207. }
  208. // 获取所有商店物品
  209. public getShopItems(): ShopItem[] {
  210. return this.shopItems.filter(item => item.available);
  211. }
  212. // 获取特定类型的商店物品
  213. public getShopItemsByType(type: 'weapon' | 'upgrade' | 'consumable'): ShopItem[] {
  214. return this.shopItems.filter(item => item.type === type && item.available);
  215. }
  216. // 获取单个商店物品
  217. public getShopItem(itemId: string): ShopItem | null {
  218. return this.shopItems.find(item => item.id === itemId) || null;
  219. }
  220. // 检查是否可以购买物品
  221. public canPurchaseItem(itemId: string): boolean {
  222. const item = this.getShopItem(itemId);
  223. if (!item || !item.available) return false;
  224. // 检查购买次数限制
  225. if (item.maxPurchases !== -1 && item.currentPurchases >= item.maxPurchases) {
  226. return false;
  227. }
  228. // 检查货币是否足够
  229. if (item.currency === 'coin') {
  230. return this.coins >= item.price;
  231. } else if (item.currency === 'gem') {
  232. return this.gems >= item.price;
  233. }
  234. return false;
  235. }
  236. // 购买物品
  237. public purchaseItem(itemId: string): boolean {
  238. const item = this.getShopItem(itemId);
  239. if (!item || !this.canPurchaseItem(itemId)) {
  240. console.warn(`无法购买物品: ${itemId}`);
  241. return false;
  242. }
  243. // 消费货币
  244. let success = false;
  245. if (item.currency === 'coin') {
  246. success = this.spendCoins(item.price);
  247. } else if (item.currency === 'gem') {
  248. success = this.spendGems(item.price);
  249. }
  250. if (success) {
  251. // 更新购买状态
  252. item.currentPurchases = (item.currentPurchases || 0) + 1;
  253. if (item.maxPurchases !== -1 && item.currentPurchases >= item.maxPurchases) {
  254. item.purchased = true;
  255. }
  256. // 添加到已购买列表
  257. if (this.purchasedItems.indexOf(itemId) === -1) {
  258. this.purchasedItems.push(itemId);
  259. }
  260. this.saveShopData();
  261. console.log(`成功购买: ${item.name}`);
  262. // 处理购买后的效果
  263. this.applyItemEffect(item);
  264. return true;
  265. }
  266. return false;
  267. }
  268. // 应用物品效果
  269. private applyItemEffect(item: ShopItem) {
  270. switch (item.type) {
  271. case 'weapon':
  272. // 武器类型:解锁武器
  273. console.log(`解锁武器: ${item.weaponId}`);
  274. // 这里可以通知其他系统武器已解锁
  275. break;
  276. case 'upgrade':
  277. // 升级类型:应用永久效果
  278. console.log(`应用升级: ${item.name}`);
  279. // 这里可以修改全局属性
  280. break;
  281. case 'consumable':
  282. // 消耗品类型:立即使用
  283. console.log(`使用消耗品: ${item.name}`);
  284. // 这里可以应用临时效果
  285. break;
  286. }
  287. }
  288. // 检查物品是否已购买
  289. public isItemPurchased(itemId: string): boolean {
  290. return this.purchasedItems.indexOf(itemId) !== -1;
  291. }
  292. // 获取已购买的武器列表
  293. public getPurchasedWeapons(): string[] {
  294. const purchasedWeaponItems = this.shopItems.filter(item =>
  295. item.type === 'weapon' && this.isItemPurchased(item.id)
  296. );
  297. return purchasedWeaponItems.map(item => item.weaponId).filter(id => id);
  298. }
  299. // 重置所有购买记录(调试用)
  300. public resetPurchases() {
  301. this.shopItems.forEach(item => {
  302. item.purchased = false;
  303. item.currentPurchases = 0;
  304. });
  305. this.purchasedItems = [];
  306. this.saveShopData();
  307. console.log('所有购买记录已重置');
  308. }
  309. // 添加免费金币(调试用)
  310. public addFreeCoins(amount: number = 1000) {
  311. this.addCoins(amount);
  312. console.log(`添加免费金币: ${amount}`);
  313. }
  314. // 添加免费宝石(调试用)
  315. public addFreeGems(amount: number = 100) {
  316. this.addGems(amount);
  317. console.log(`添加免费宝石: ${amount}`);
  318. }
  319. }