PetBattleLogic.php 17 KB

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