randomFishResult(); // 2. 获取会员倍率 $expMul = $this->vipService->getExpMultiplier($user); $jjbMul = $this->vipService->getJjbMultiplier($user); // 3. 计算最终经验和金币 $finalExp = 0; $finalJjb = 0; if ($result['exp'] !== 0) { // 当经验为 正数 则可使用会员翻倍,负数则不 $finalExp = $result['exp'] > 0 ? (int)round($result['exp'] * $expMul) : $result['exp']; } if ($result['jjb'] !== 0) { $finalJjb = $result['jjb'] > 0 ? (int)round($result['jjb'] * $jjbMul) : $result['jjb']; } // 4. 计算会员额外加成部分 $bonusExp = 0; $bonusJjb = 0; if ($result['exp'] > 0 && $finalExp > $result['exp']) { $bonusExp = $finalExp - $result['exp']; } if ($result['jjb'] > 0 && $finalJjb > $result['jjb']) { $bonusJjb = $finalJjb - $result['jjb']; } // 5. 生成最终展示文案 $finalMessage = $this->buildFinalMessage($result['message'], $bonusExp, $bonusJjb, $user); // 6. 更新经验 if ($finalExp !== 0) { $this->currencyService->change($user, 'exp', $finalExp, CurrencySource::FISHING_GAIN, "钓鱼收竿:{$finalMessage}", $roomId, ); } // 7. 更新金币 if ($finalJjb !== 0) { $this->currencyService->change($user, 'gold', $finalJjb, CurrencySource::FISHING_GAIN, "钓鱼收竿:{$finalMessage}", $roomId, ); } $user->refresh(); // 8. 广播钓鱼结果到聊天室 $promoTag = ''; if (!$isAi) { $autoFishingMinutesLeft = $this->shopService->getActiveAutoFishingMinutesLeft($user); $promoTag = $autoFishingMinutesLeft > 0 ? ' 🎣 自动钓鱼卡' : ''; } $sysMsg = [ 'id' => $this->chatState->nextMessageId($roomId), 'room_id' => $roomId, 'from_user' => '钓鱼播报', 'to_user' => '大家', 'content' => "{$result['emoji']} 【{$user->username}】{$finalMessage}{$promoTag}", 'is_secret' => false, 'font_color' => ($result['exp'] < 0 || $result['jjb'] < 0) ? '#dc2626' : '#16a34a', 'action' => '', 'sent_at' => now()->toDateTimeString(), ]; $this->chatState->pushMessage($roomId, $sysMsg); broadcast(new MessageSent($roomId, $sysMsg)); // 发送完需持久化,不过 controller 里并未直接看到 SaveMessageJob, 但 AIheartbeat 里有。 // 这里就先维持原样,只 broadcast 和 pushMessage return [ 'emoji' => $result['emoji'], 'message' => $finalMessage, 'exp' => $finalExp, 'jjb' => $finalJjb, 'base_exp' => $result['exp'], 'base_jjb' => $result['jjb'], 'bonus_exp' => $bonusExp, 'bonus_jjb' => $bonusJjb, ]; } /** * 生成最终展示文案 * * 示例: * - 钓到一条金鱼,获得经验10,金币20 * - 钓到一条金鱼,获得经验10,金币20(会员加成:+经验10,+金币20) */ private function buildFinalMessage(string $baseMessage, int $bonusExp, int $bonusJjb, $user): string { $bonusParts = []; if ($bonusExp > 0) { $bonusParts[] = "+经验{$bonusExp}"; } if ($bonusJjb > 0) { $bonusParts[] = "+金币{$bonusJjb}"; } if (empty($bonusParts)) { return $baseMessage; } return $baseMessage . '(' . $user->vipName() . '追加:' . implode(',', $bonusParts) . ')'; } /** * 随机钓鱼结果(从数据库 fishing_events 加权随机抽取) * * 若数据库中无激活事件,回退到兜底结果。 * * @return array{emoji: string, message: string, exp: int, jjb: int} */ public function randomFishResult(): array { $event = FishingEvent::rollOne(); if (!$event) { return [ 'emoji' => '🐟', 'message' => '钓到一条小鱼,获得金币10', 'exp' => 0, 'jjb' => 10, ]; } return [ 'emoji' => $event->emoji, 'message' => $event->message, 'exp' => (int)$event->exp, 'jjb' => (int)$event->jjb, ]; } }