PetBattleLogic.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. <?php
  2. namespace App\Module\Pet\Logic;
  3. use App\Module\Pet\Enums\PetGrade;
  4. use App\Module\Pet\Models\PetLevelConfig;
  5. use App\Module\Pet\Models\PetUser;
  6. use Exception;
  7. use Illuminate\Support\Facades\Log;
  8. /**
  9. * 宠物战斗逻辑类
  10. *
  11. * 处理宠物战斗相关的业务逻辑,包括战力计算、战斗结果计算、
  12. * 奖励发放等功能。该类是宠物战斗模块内部使用的核心逻辑类,
  13. * 不对外提供服务,由PetBattleService调用。
  14. */
  15. class PetBattleLogic
  16. {
  17. /**
  18. * 获取战斗体力消耗
  19. *
  20. * @param int $battleType 战斗类型
  21. * @return int 体力消耗
  22. */
  23. public function getBattleStaminaCost(int $battleType): int
  24. {
  25. // 根据战斗类型返回不同的体力消耗
  26. switch ($battleType) {
  27. case 1: // 偷菜战斗
  28. return config('pet.battle_stamina_cost.steal', 10);
  29. case 2: // 守护战斗
  30. return config('pet.battle_stamina_cost.defend', 15);
  31. case 3: // 争霸赛战斗
  32. return config('pet.battle_stamina_cost.royale', 20);
  33. default:
  34. return 10; // 默认消耗10点体力
  35. }
  36. }
  37. /**
  38. * 执行战斗
  39. *
  40. * @param int $petId 宠物ID
  41. * @param int $battleType 战斗类型
  42. * @param int $targetId 目标ID
  43. * @return array 战斗结果
  44. * @throws Exception
  45. */
  46. public function executeBattle(int $petId, int $battleType, int $targetId): array
  47. {
  48. // 获取宠物信息
  49. $pet = PetUser::findOrFail($petId);
  50. // 根据战斗类型执行不同的战斗逻辑
  51. switch ($battleType) {
  52. case 1: // 偷菜战斗
  53. return $this->executeStealBattle($pet, $targetId);
  54. case 2: // 守护战斗
  55. return $this->executeDefendBattle($pet, $targetId);
  56. case 3: // 争霸赛战斗
  57. return $this->executeRoyaleBattle($pet, $targetId);
  58. default:
  59. throw new Exception("未知的战斗类型");
  60. }
  61. }
  62. /**
  63. * 执行偷菜战斗
  64. *
  65. * @param PetUser $pet 宠物对象
  66. * @param int $targetId 目标用户ID
  67. * @return array 战斗结果
  68. */
  69. protected function executeStealBattle(PetUser $pet, int $targetId): array
  70. {
  71. // 计算宠物战力
  72. $petPower = $this->calculatePetPower($pet->id);
  73. // 获取目标用户的守护宠物
  74. // 这里需要根据实际项目中的农场模块接口进行实现
  75. // 暂时使用模拟数据
  76. $targetPetPower = 0;
  77. $targetPet = null;
  78. // 模拟获取目标用户的守护宠物
  79. $targetPets = PetUser::where('user_id', $targetId)
  80. ->where('status', 1) // 正常状态
  81. ->get();
  82. if ($targetPets->isNotEmpty()) {
  83. // 找出战力最高的宠物作为守护宠物
  84. foreach ($targetPets as $tp) {
  85. $tp_power = $this->calculatePetPower($tp->id);
  86. if ($tp_power > $targetPetPower) {
  87. $targetPetPower = $tp_power;
  88. $targetPet = $tp;
  89. }
  90. }
  91. }
  92. // 计算成功率
  93. $successRate = $this->calculateStealSuccessRate($petPower, $targetPetPower);
  94. // 随机决定是否成功
  95. $random = mt_rand(1, 100);
  96. $success = $random <= $successRate;
  97. // 计算奖励
  98. $rewards = [];
  99. if ($success) {
  100. // 成功偷菜,获得奖励
  101. $rewards = $this->calculateStealRewards($pet, $targetId);
  102. }
  103. // 记录战斗详情
  104. $details = [
  105. 'pet_power' => $petPower,
  106. 'target_pet_power' => $targetPetPower,
  107. 'success_rate' => $successRate,
  108. 'random_roll' => $random,
  109. 'success' => $success
  110. ];
  111. // 返回战斗结果
  112. return [
  113. 'success' => $success,
  114. 'opponent_id' => $targetId,
  115. 'opponent' => [
  116. 'user_id' => $targetId,
  117. 'pet_id' => $targetPet ? $targetPet->id : null,
  118. 'pet_name' => $targetPet ? $targetPet->name : '无守护宠物',
  119. 'pet_power' => $targetPetPower
  120. ],
  121. 'rewards' => $rewards,
  122. 'details' => $details
  123. ];
  124. }
  125. /**
  126. * 执行守护战斗
  127. *
  128. * @param PetUser $pet 宠物对象
  129. * @param int $targetId 目标用户ID
  130. * @return array 战斗结果
  131. */
  132. protected function executeDefendBattle(PetUser $pet, int $targetId): array
  133. {
  134. // 计算宠物战力
  135. $petPower = $this->calculatePetPower($pet->id);
  136. // 获取目标用户的偷菜宠物
  137. // 这里需要根据实际项目中的农场模块接口进行实现
  138. // 暂时使用模拟数据
  139. $targetPetPower = mt_rand(800, 1500); // 模拟目标宠物战力
  140. // 计算成功率
  141. $successRate = $this->calculateDefendSuccessRate($petPower, $targetPetPower);
  142. // 随机决定是否成功
  143. $random = mt_rand(1, 100);
  144. $success = $random <= $successRate;
  145. // 计算奖励
  146. $rewards = [];
  147. if ($success) {
  148. // 成功守护,获得奖励
  149. $rewards = $this->calculateDefendRewards($pet);
  150. }
  151. // 记录战斗详情
  152. $details = [
  153. 'pet_power' => $petPower,
  154. 'target_pet_power' => $targetPetPower,
  155. 'success_rate' => $successRate,
  156. 'random_roll' => $random,
  157. 'success' => $success
  158. ];
  159. // 返回战斗结果
  160. return [
  161. 'success' => $success,
  162. 'opponent_id' => $targetId,
  163. 'opponent' => [
  164. 'user_id' => $targetId,
  165. 'pet_power' => $targetPetPower
  166. ],
  167. 'rewards' => $rewards,
  168. 'details' => $details
  169. ];
  170. }
  171. /**
  172. * 执行争霸赛战斗
  173. *
  174. * @param PetUser $pet 宠物对象
  175. * @param int $targetId 目标Boss ID或对手宠物ID
  176. * @return array 战斗结果
  177. */
  178. protected function executeRoyaleBattle(PetUser $pet, int $targetId): array
  179. {
  180. // 计算宠物战力
  181. $petPower = $this->calculatePetPower($pet->id);
  182. // 获取目标Boss或对手宠物信息
  183. // 这里需要根据实际项目中的争霸赛系统进行实现
  184. // 暂时使用模拟数据
  185. $targetPetPower = 0;
  186. $targetPet = null;
  187. if ($targetId > 0) {
  188. // 对战其他宠物
  189. $targetPet = PetUser::find($targetId);
  190. if ($targetPet) {
  191. $targetPetPower = $this->calculatePetPower($targetId);
  192. }
  193. } else {
  194. // 对战Boss
  195. $targetPetPower = 5000; // 模拟Boss战力
  196. }
  197. // 计算成功率
  198. $successRate = $this->calculateRoyaleSuccessRate($petPower, $targetPetPower);
  199. // 随机决定是否成功
  200. $random = mt_rand(1, 100);
  201. $success = $random <= $successRate;
  202. // 计算奖励
  203. $rewards = [];
  204. if ($success) {
  205. // 战斗胜利,获得奖励
  206. $rewards = $this->calculateRoyaleRewards($pet, $targetId);
  207. }
  208. // 计算造成的伤害(用于争霸赛排名)
  209. $damage = $this->calculateRoyaleDamage($petPower, $targetPetPower, $success);
  210. // 记录战斗详情
  211. $details = [
  212. 'pet_power' => $petPower,
  213. 'target_pet_power' => $targetPetPower,
  214. 'success_rate' => $successRate,
  215. 'random_roll' => $random,
  216. 'success' => $success,
  217. 'damage' => $damage
  218. ];
  219. // 返回战斗结果
  220. return [
  221. 'success' => $success,
  222. 'opponent_id' => $targetId,
  223. 'opponent' => $targetPet ? [
  224. 'pet_id' => $targetPet->id,
  225. 'pet_name' => $targetPet->name,
  226. 'pet_grade' => $targetPet->grade->value,
  227. 'pet_level' => $targetPet->level,
  228. 'pet_power' => $targetPetPower
  229. ] : [
  230. 'boss_id' => 0,
  231. 'boss_name' => 'Boss',
  232. 'boss_power' => $targetPetPower
  233. ],
  234. 'rewards' => $rewards,
  235. 'damage' => $damage,
  236. 'details' => $details
  237. ];
  238. }
  239. /**
  240. * 计算宠物战力
  241. *
  242. * @param int $petId 宠物ID
  243. * @return int 战力值
  244. */
  245. public function calculatePetPower(int $petId): int
  246. {
  247. // 获取宠物信息
  248. $pet = PetUser::findOrFail($petId);
  249. // 获取宠物等级配置
  250. $levelConfig = PetLevelConfig::where('level', $pet->level)->first();
  251. // 基础战力
  252. $basePower = $levelConfig ? ($levelConfig->numeric_attributes['base_power'] ?? 100) : 100;
  253. // 品阶加成
  254. $gradeBonus = config('pet.grade_attribute_bonus.' . $pet->grade->value, 0);
  255. // 计算最终战力
  256. $power = $basePower * (1 + $gradeBonus);
  257. // 记录日志
  258. Log::info('计算宠物战力', [
  259. 'pet_id' => $petId,
  260. 'level' => $pet->level,
  261. 'grade' => $pet->grade->value,
  262. 'base_power' => $basePower,
  263. 'grade_bonus' => $gradeBonus,
  264. 'final_power' => $power
  265. ]);
  266. return (int)$power;
  267. }
  268. /**
  269. * 计算偷菜成功率
  270. *
  271. * @param int $petPower 宠物战力
  272. * @param int $targetPetPower 目标宠物战力
  273. * @return int 成功率(百分比)
  274. */
  275. protected function calculateStealSuccessRate(int $petPower, int $targetPetPower): int
  276. {
  277. // 如果目标没有守护宠物,成功率较高
  278. if ($targetPetPower <= 0) {
  279. return 80;
  280. }
  281. // 基础成功率
  282. $baseRate = 50;
  283. // 根据战力差计算成功率
  284. $powerDiff = $petPower - $targetPetPower;
  285. $rateAdjustment = $powerDiff / 100; // 每100点战力差调整1%成功率
  286. // 最终成功率,限制在10%-90%之间
  287. $finalRate = max(10, min(90, $baseRate + $rateAdjustment));
  288. return (int)$finalRate;
  289. }
  290. /**
  291. * 计算守护成功率
  292. *
  293. * @param int $petPower 宠物战力
  294. * @param int $targetPetPower 目标宠物战力
  295. * @return int 成功率(百分比)
  296. */
  297. protected function calculateDefendSuccessRate(int $petPower, int $targetPetPower): int
  298. {
  299. // 基础成功率
  300. $baseRate = 60;
  301. // 根据战力差计算成功率
  302. $powerDiff = $petPower - $targetPetPower;
  303. $rateAdjustment = $powerDiff / 100; // 每100点战力差调整1%成功率
  304. // 最终成功率,限制在20%-95%之间
  305. $finalRate = max(20, min(95, $baseRate + $rateAdjustment));
  306. return (int)$finalRate;
  307. }
  308. /**
  309. * 计算争霸赛成功率
  310. *
  311. * @param int $petPower 宠物战力
  312. * @param int $targetPetPower 目标宠物战力
  313. * @return int 成功率(百分比)
  314. */
  315. protected function calculateRoyaleSuccessRate(int $petPower, int $targetPetPower): int
  316. {
  317. // 基础成功率
  318. $baseRate = 40;
  319. // 根据战力差计算成功率
  320. $powerDiff = $petPower - $targetPetPower;
  321. $rateAdjustment = $powerDiff / 150; // 每150点战力差调整1%成功率
  322. // 最终成功率,限制在5%-85%之间
  323. $finalRate = max(5, min(85, $baseRate + $rateAdjustment));
  324. return (int)$finalRate;
  325. }
  326. /**
  327. * 计算偷菜奖励
  328. *
  329. * @param PetUser $pet 宠物对象
  330. * @param int $targetId 目标用户ID
  331. * @return array 奖励列表
  332. */
  333. protected function calculateStealRewards(PetUser $pet, int $targetId): array
  334. {
  335. // 这里需要根据实际项目中的农场模块接口进行实现
  336. // 暂时使用模拟数据
  337. // 模拟获取可偷取的作物
  338. $availableCrops = [
  339. ['item_id' => 1001, 'name' => '小麦', 'max_amount' => 5],
  340. ['item_id' => 1002, 'name' => '胡萝卜', 'max_amount' => 3],
  341. ['item_id' => 1003, 'name' => '土豆', 'max_amount' => 2]
  342. ];
  343. // 随机选择1-2种作物
  344. $cropCount = mt_rand(1, min(2, count($availableCrops)));
  345. $selectedCrops = array_rand($availableCrops, $cropCount);
  346. if (!is_array($selectedCrops)) {
  347. $selectedCrops = [$selectedCrops];
  348. }
  349. // 计算偷取数量和经验值
  350. $rewards = [
  351. 'exp' => mt_rand(5, 15), // 获得5-15点经验
  352. 'items' => []
  353. ];
  354. foreach ($selectedCrops as $index) {
  355. $crop = $availableCrops[$index];
  356. $amount = mt_rand(1, $crop['max_amount']);
  357. $rewards['items'][] = [
  358. 'item_id' => $crop['item_id'],
  359. 'name' => $crop['name'],
  360. 'amount' => $amount
  361. ];
  362. }
  363. return $rewards;
  364. }
  365. /**
  366. * 计算守护奖励
  367. *
  368. * @param PetUser $pet 宠物对象
  369. * @return array 奖励列表
  370. */
  371. protected function calculateDefendRewards(PetUser $pet): array
  372. {
  373. // 这里需要根据实际项目中的奖励系统进行实现
  374. // 暂时使用模拟数据
  375. // 计算守护奖励和经验值
  376. $rewards = [
  377. 'exp' => mt_rand(10, 20), // 获得10-20点经验
  378. 'items' => []
  379. ];
  380. // 随机获得守护奖励物品
  381. $rewardItems = [
  382. ['item_id' => 2001, 'name' => '守护徽章', 'probability' => 0.3, 'amount' => 1],
  383. ['item_id' => 2002, 'name' => '防御药水', 'probability' => 0.5, 'amount' => 1],
  384. ['item_id' => 2003, 'name' => '农场币', 'probability' => 1.0, 'amount_min' => 10, 'amount_max' => 50]
  385. ];
  386. foreach ($rewardItems as $item) {
  387. $random = mt_rand(1, 100) / 100;
  388. if ($random <= $item['probability']) {
  389. $amount = isset($item['amount_min']) ?
  390. mt_rand($item['amount_min'], $item['amount_max']) :
  391. $item['amount'];
  392. $rewards['items'][] = [
  393. 'item_id' => $item['item_id'],
  394. 'name' => $item['name'],
  395. 'amount' => $amount
  396. ];
  397. }
  398. }
  399. return $rewards;
  400. }
  401. /**
  402. * 计算争霸赛奖励
  403. *
  404. * @param PetUser $pet 宠物对象
  405. * @param int $targetId 目标ID
  406. * @return array 奖励列表
  407. */
  408. protected function calculateRoyaleRewards(PetUser $pet, int $targetId): array
  409. {
  410. // 这里需要根据实际项目中的争霸赛系统进行实现
  411. // 暂时使用模拟数据
  412. // 计算争霸赛奖励和经验值
  413. $rewards = [
  414. 'exp' => mt_rand(20, 40), // 获得20-40点经验
  415. 'items' => []
  416. ];
  417. // 如果是击败Boss,获得更多奖励
  418. if ($targetId <= 0) {
  419. // Boss战奖励
  420. $bossRewardItems = [
  421. ['item_id' => 3001, 'name' => '争霸徽章', 'amount' => 1],
  422. ['item_id' => 3002, 'name' => '高级狗粮', 'amount' => mt_rand(1, 3)],
  423. ['item_id' => 3003, 'name' => '钻石', 'amount' => mt_rand(10, 30)]
  424. ];
  425. foreach ($bossRewardItems as $item) {
  426. $rewards['items'][] = [
  427. 'item_id' => $item['item_id'],
  428. 'name' => $item['name'],
  429. 'amount' => $item['amount']
  430. ];
  431. }
  432. } else {
  433. // PVP战奖励
  434. $pvpRewardItems = [
  435. ['item_id' => 3001, 'name' => '争霸徽章', 'amount' => 1],
  436. ['item_id' => 3004, 'name' => '荣誉点数', 'amount' => mt_rand(5, 15)]
  437. ];
  438. foreach ($pvpRewardItems as $item) {
  439. $rewards['items'][] = [
  440. 'item_id' => $item['item_id'],
  441. 'name' => $item['name'],
  442. 'amount' => $item['amount']
  443. ];
  444. }
  445. }
  446. return $rewards;
  447. }
  448. /**
  449. * 计算争霸赛造成的伤害
  450. *
  451. * @param int $petPower 宠物战力
  452. * @param int $targetPetPower 目标宠物战力
  453. * @param bool $success 是否成功
  454. * @return int 造成的伤害
  455. */
  456. protected function calculateRoyaleDamage(int $petPower, int $targetPetPower, bool $success): int
  457. {
  458. // 基础伤害
  459. $baseDamage = $petPower * 0.1;
  460. // 如果战斗成功,额外增加伤害
  461. if ($success) {
  462. $baseDamage *= 1.5;
  463. }
  464. // 根据目标战力调整伤害
  465. $powerRatio = $petPower / max(1, $targetPetPower);
  466. $damageAdjustment = $powerRatio * 0.5;
  467. // 最终伤害,加入随机因素
  468. $finalDamage = $baseDamage * (1 + $damageAdjustment) * (0.8 + mt_rand(0, 40) / 100);
  469. return (int)$finalDamage;
  470. }
  471. }