info('开始生成作物灾害...'); try { // 获取处于发芽期或生长期的作物 $crops = FarmCrop::whereIn('growth_stage', [GROWTH_STAGE::SPROUT, GROWTH_STAGE::GROWTH]) ->get(); $this->info("找到 {$crops->count()} 个可能受灾的作物"); $generatedCount = 0; foreach ($crops as $crop) { $userId = $crop->user_id; $land = $crop->land; $seed = $crop->seed; // 跳过已经有灾害的土地 if ($land->status === LAND_STATUS::DISASTER) { continue; } // 获取种子的灾害抵抗属性 $disasterResistance = $seed->disaster_resistance ?? []; // 获取土地的灾害抵抗属性 $landDisasterResistance = $land->landType->disaster_resistance ?? 0; // 检查用户是否有有效的神灵加持 $activeBuffs = FarmGodBuff::where('user_id', $userId) ->where('expire_time', '>', now()) ->pluck('buff_type') ->toArray(); // 灾害类型及其基础概率 $disasterTypes = [ DISASTER_TYPE::DROUGHT => 0.1, // 干旱 DISASTER_TYPE::PEST => 0.1, // 虫害 DISASTER_TYPE::WEED => 0.1, // 杂草 ]; // 随机选择一种灾害类型 $randomDisasterType = array_rand($disasterTypes); $baseProb = $disasterTypes[$randomDisasterType]; // 计算最终概率,考虑种子抵抗、土地抵抗和神灵加持 $seedResistance = $disasterResistance[$this->getDisasterKey($randomDisasterType)] ?? 0; $finalProb = $baseProb - $seedResistance - $landDisasterResistance; // 如果有对应的神灵加持,则不生成该类型的灾害 $buffType = DISASTER_TYPE::getPreventBuffType($randomDisasterType); if ($buffType && in_array($buffType, $activeBuffs)) { $finalProb = 0; } // 确保概率在有效范围内 $finalProb = max(0, min(1, $finalProb)); // 随机决定是否生成灾害 if (mt_rand(1, 100) <= $finalProb * 100) { // 生成灾害 $disasterInfo = [ 'type' => $randomDisasterType, 'generated_at' => now()->toDateTimeString(), 'status' => 'active' ]; // 更新作物灾害信息 $disasters = $crop->disasters ?? []; $disasters[] = $disasterInfo; $crop->disasters = $disasters; // 更新土地状态为灾害 $land->status = LAND_STATUS::DISASTER; // 保存更改 $crop->save(); $land->save(); // 触发灾害生成事件 event(new DisasterGeneratedEvent($userId, $crop, $randomDisasterType, $disasterInfo)); $generatedCount++; $this->info("作物 ID: {$crop->id}, 用户 ID: {$userId}, 灾害类型: {$randomDisasterType}"); } } $this->info("成功生成 {$generatedCount} 个作物灾害"); Log::info('作物灾害生成成功', [ 'total' => $crops->count(), 'generated' => $generatedCount ]); return 0; } catch (\Exception $e) { $this->error('作物灾害生成失败: ' . $e->getMessage()); Log::error('作物灾害生成失败', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return 1; } } /** * 获取灾害类型对应的键名 * * @param int $disasterType * @return string */ private function getDisasterKey(int $disasterType): string { $keys = [ DISASTER_TYPE::DROUGHT => 'drought', DISASTER_TYPE::PEST => 'pest', DISASTER_TYPE::WEED => 'weed', ]; return $keys[$disasterType] ?? ''; } }