randomFishResult(); // 2. 更新经验和金币 $expMul = $this->vipService->getExpMultiplier($user); $jjbMul = $this->vipService->getJjbMultiplier($user); if ($result['exp'] !== 0) { $finalExp = $result['exp'] > 0 ? (int) round($result['exp'] * $expMul) : $result['exp']; $this->currencyService->change( $user, 'exp', $finalExp, CurrencySource::FISHING_GAIN, "钓鱼收竿:{$result['message']}", $roomId, ); } if ($result['jjb'] !== 0) { $finalJjb = $result['jjb'] > 0 ? (int) round($result['jjb'] * $jjbMul) : $result['jjb']; $this->currencyService->change( $user, 'gold', $finalJjb, CurrencySource::FISHING_GAIN, "钓鱼收竿:{$result['message']}", $roomId, ); } $user->refresh(); // 3. 广播钓鱼结果到聊天室 $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}】{$result['message']}{$promoTag}", 'is_secret' => false, 'font_color' => $result['exp'] >= 0 ? '#16a34a' : '#dc2626', 'action' => '', 'sent_at' => now()->toDateTimeString(), ]; $this->chatState->pushMessage($roomId, $sysMsg); broadcast(new MessageSent($roomId, $sysMsg)); // 发送完需持久化,不过 controller 里并未直接看到 SaveMessageJob, 但 AIheartbeat 里有。 // 这里就先维持原样,只 broadcast 和 pushMessage return $result; } /** * 随机钓鱼结果(从数据库 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' => $event->exp, 'jjb' => $event->jjb, ]; } }