|
|
@@ -0,0 +1,603 @@
|
|
|
+# 神秘种子土地影响系统设计
|
|
|
+
|
|
|
+**文档版本:** 1.0
|
|
|
+**创建时间:** 2025-05-27
|
|
|
+**设计目标:** 实现土地类型影响神秘种子产出类型的机制
|
|
|
+
|
|
|
+## 1. 系统概述
|
|
|
+
|
|
|
+### 1.1 设计理念
|
|
|
+
|
|
|
+神秘种子土地影响系统通过土地类型来调整神秘种子的产出概率分布,让不同等级的土地对神秘种子产生不同的影响效果,增加游戏的策略性和土地升级的价值。
|
|
|
+
|
|
|
+### 1.2 核心机制
|
|
|
+
|
|
|
+- **基于配置的概率调整**:通过数据库配置实现土地类型对产出概率的影响
|
|
|
+- **动态概率计算**:在发芽期确定最终产出时,根据土地类型动态调整各产出项的概率
|
|
|
+- **保持兼容性**:不影响现有的产出配置系统,作为概率修正器存在
|
|
|
+
|
|
|
+## 2. 数据库设计
|
|
|
+
|
|
|
+### 2.1 新增表:神秘种子土地影响配置表
|
|
|
+
|
|
|
+```sql
|
|
|
+CREATE TABLE `kku_farm_mystery_seed_land_effects` (
|
|
|
+ `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
|
|
+ `seed_id` bigint unsigned NOT NULL COMMENT '种子ID(神秘种子)',
|
|
|
+ `land_type_id` bigint unsigned NOT NULL COMMENT '土地类型ID',
|
|
|
+ `output_item_id` bigint unsigned NOT NULL COMMENT '产出物品ID',
|
|
|
+ `probability_modifier` decimal(7,4) NOT NULL DEFAULT '0.0000' COMMENT '概率修正值(百分比,可为负数)',
|
|
|
+ `probability_override` decimal(7,4) NULL DEFAULT NULL COMMENT '概率覆盖值(百分比,覆盖种子的物品原产出概率,优先级高于修正值)',
|
|
|
+ `is_active` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用',
|
|
|
+ `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
+ `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
+ PRIMARY KEY (`id`),
|
|
|
+ UNIQUE KEY `unique_seed_land_output` (`seed_id`,`land_type_id`,`output_item_id`),
|
|
|
+ KEY `idx_seed_id` (`seed_id`),
|
|
|
+ KEY `idx_land_type_id` (`land_type_id`),
|
|
|
+ KEY `idx_output_item_id` (`output_item_id`)
|
|
|
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='神秘种子土地影响配置表';
|
|
|
+```
|
|
|
+
|
|
|
+### 2.2 配置示例数据
|
|
|
+
|
|
|
+```sql
|
|
|
+-- 神秘种子(ID=1)在不同土地类型上的产出概率调整
|
|
|
+-- 假设基础产出配置:物品2(10%)、物品3(10%,默认)、物品4(10%)
|
|
|
+
|
|
|
+-- 普通土地:无影响
|
|
|
+INSERT INTO `kku_farm_mystery_seed_land_effects` VALUES
|
|
|
+(1, 1, 1, 2, 0.0000, NULL, 1, NOW(), NOW()),
|
|
|
+(2, 1, 1, 3, 0.0000, NULL, 1, NOW(), NOW()),
|
|
|
+(3, 1, 1, 4, 0.0000, NULL, 1, NOW(), NOW());
|
|
|
+
|
|
|
+-- 红土地:提升物品2概率,降低物品4概率
|
|
|
+INSERT INTO `kku_farm_mystery_seed_land_effects` VALUES
|
|
|
+(4, 1, 2, 2, 5.0000, NULL, 1, NOW(), NOW()), -- +5%
|
|
|
+(5, 1, 2, 3, 0.0000, NULL, 1, NOW(), NOW()), -- 不变
|
|
|
+(6, 1, 2, 4, -3.0000, NULL, 1, NOW(), NOW()); -- -3%
|
|
|
+
|
|
|
+-- 黑土地:进一步提升物品2概率
|
|
|
+INSERT INTO `kku_farm_mystery_seed_land_effects` VALUES
|
|
|
+(7, 1, 3, 2, 10.0000, NULL, 1, NOW(), NOW()), -- +10%
|
|
|
+(8, 1, 3, 3, -2.0000, NULL, 1, NOW(), NOW()), -- -2%
|
|
|
+(9, 1, 3, 4, -5.0000, NULL, 1, NOW(), NOW()); -- -5%
|
|
|
+
|
|
|
+-- 金土地:大幅提升稀有物品概率,物品2使用覆盖值
|
|
|
+INSERT INTO `kku_farm_mystery_seed_land_effects` VALUES
|
|
|
+(10, 1, 4, 2, 0.0000, 25.0000, 1, NOW(), NOW()), -- 覆盖为25%
|
|
|
+(11, 1, 4, 3, -5.0000, NULL, 1, NOW(), NOW()), -- -5%
|
|
|
+(12, 1, 4, 4, 8.0000, NULL, 1, NOW(), NOW()); -- +8%
|
|
|
+
|
|
|
+-- 蓝土地:平衡提升所有稀有物品
|
|
|
+INSERT INTO `kku_farm_mystery_seed_land_effects` VALUES
|
|
|
+(13, 1, 5, 2, 12.0000, NULL, 1, NOW(), NOW()), -- +12%
|
|
|
+(14, 1, 5, 3, -3.0000, NULL, 1, NOW(), NOW()), -- -3%
|
|
|
+(15, 1, 5, 4, 12.0000, NULL, 1, NOW(), NOW()); -- +12%
|
|
|
+
|
|
|
+-- 紫土地:极大提升最稀有物品概率,物品2和物品4使用覆盖值
|
|
|
+INSERT INTO `kku_farm_mystery_seed_land_effects` VALUES
|
|
|
+(16, 1, 6, 2, 0.0000, 30.0000, 1, NOW(), NOW()), -- 覆盖为30%
|
|
|
+(17, 1, 6, 3, -8.0000, NULL, 1, NOW(), NOW()), -- -8%
|
|
|
+(18, 1, 6, 4, 0.0000, 25.0000, 1, NOW(), NOW()); -- 覆盖为25%
|
|
|
+```
|
|
|
+
|
|
|
+## 3. 业务逻辑设计
|
|
|
+
|
|
|
+### 3.1 概率计算流程
|
|
|
+
|
|
|
+```
|
|
|
+1. 获取神秘种子的基础产出配置
|
|
|
+2. 获取当前土地类型
|
|
|
+3. 查询土地影响配置
|
|
|
+4. 应用概率调整(优先级:覆盖值 > 修正值)
|
|
|
+ - 如果有覆盖值:直接使用覆盖值作为最终概率
|
|
|
+ - 如果无覆盖值:基础概率 + 修正值
|
|
|
+5. 确保概率总和合理
|
|
|
+6. 执行随机选择
|
|
|
+```
|
|
|
+
|
|
|
+### 3.2 概率修正算法
|
|
|
+
|
|
|
+```php
|
|
|
+/**
|
|
|
+ * 计算神秘种子在特定土地上的调整后概率
|
|
|
+ *
|
|
|
+ * @param int $seedId 种子ID
|
|
|
+ * @param int $landTypeId 土地类型ID
|
|
|
+ * @return array 调整后的产出配置
|
|
|
+ */
|
|
|
+public function calculateAdjustedProbabilities(int $seedId, int $landTypeId): array
|
|
|
+{
|
|
|
+ // 1. 获取基础产出配置
|
|
|
+ $baseOutputs = FarmSeedOutput::where('seed_id', $seedId)
|
|
|
+ ->where('is_active', true)
|
|
|
+ ->get();
|
|
|
+
|
|
|
+ // 2. 获取土地影响配置
|
|
|
+ $landEffects = FarmMysterySeeLandEffect::where('seed_id', $seedId)
|
|
|
+ ->where('land_type_id', $landTypeId)
|
|
|
+ ->where('is_active', true)
|
|
|
+ ->get()
|
|
|
+ ->keyBy('output_item_id');
|
|
|
+
|
|
|
+ // 3. 应用概率调整(优先级:覆盖值 > 修正值)
|
|
|
+ $adjustedOutputs = [];
|
|
|
+ foreach ($baseOutputs as $output) {
|
|
|
+ $baseProbability = $output->probability;
|
|
|
+ $landEffect = $landEffects[$output->item_id] ?? null;
|
|
|
+
|
|
|
+ // 优先使用覆盖值,其次使用修正值
|
|
|
+ if ($landEffect && $landEffect->probability_override !== null) {
|
|
|
+ // 使用覆盖值直接替换原概率
|
|
|
+ $adjustedProbability = $landEffect->probability_override;
|
|
|
+ $adjustmentType = 'override';
|
|
|
+ } else {
|
|
|
+ // 使用修正值调整原概率
|
|
|
+ $modifier = $landEffect->probability_modifier ?? 0;
|
|
|
+ $adjustedProbability = $baseProbability + $modifier;
|
|
|
+ $adjustmentType = 'modifier';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保概率在合理范围内 (0-100)
|
|
|
+ $adjustedProbability = max(0, min(100, $adjustedProbability));
|
|
|
+
|
|
|
+ $adjustedOutputs[] = [
|
|
|
+ 'item_id' => $output->item_id,
|
|
|
+ 'min_amount' => $output->min_amount,
|
|
|
+ 'max_amount' => $output->max_amount,
|
|
|
+ 'original_probability' => $baseProbability,
|
|
|
+ 'adjusted_probability' => $adjustedProbability,
|
|
|
+ 'adjustment_type' => $adjustmentType,
|
|
|
+ 'is_default' => $output->is_default
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 概率归一化(可选)
|
|
|
+ return $this->normalizeProbabilities($adjustedOutputs);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 3.3 概率归一化处理
|
|
|
+
|
|
|
+```php
|
|
|
+/**
|
|
|
+ * 归一化概率分布
|
|
|
+ *
|
|
|
+ * @param array $outputs 产出配置数组
|
|
|
+ * @return array 归一化后的产出配置
|
|
|
+ */
|
|
|
+private function normalizeProbabilities(array $outputs): array
|
|
|
+{
|
|
|
+ $totalProbability = array_sum(array_column($outputs, 'adjusted_probability'));
|
|
|
+
|
|
|
+ // 如果总概率为0,使用默认产出
|
|
|
+ if ($totalProbability <= 0) {
|
|
|
+ foreach ($outputs as &$output) {
|
|
|
+ if ($output['is_default']) {
|
|
|
+ $output['adjusted_probability'] = 100;
|
|
|
+ } else {
|
|
|
+ $output['adjusted_probability'] = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return $outputs;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果需要归一化到100%
|
|
|
+ if ($totalProbability != 100) {
|
|
|
+ $scaleFactor = 100 / $totalProbability;
|
|
|
+ foreach ($outputs as &$output) {
|
|
|
+ $output['adjusted_probability'] *= $scaleFactor;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return $outputs;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## 4. 模型设计
|
|
|
+
|
|
|
+### 4.1 神秘种子土地影响模型
|
|
|
+
|
|
|
+```php
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Module\Farm\Models;
|
|
|
+
|
|
|
+use UCore\ModelCore;
|
|
|
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 神秘种子土地影响配置模型
|
|
|
+ */
|
|
|
+class FarmMysterySeeLandEffect extends ModelCore
|
|
|
+{
|
|
|
+ protected $table = 'farm_mystery_seed_land_effects';
|
|
|
+
|
|
|
+ protected $fillable = [
|
|
|
+ 'seed_id',
|
|
|
+ 'land_type_id',
|
|
|
+ 'output_item_id',
|
|
|
+ 'probability_modifier',
|
|
|
+ 'probability_override',
|
|
|
+ 'is_active'
|
|
|
+ ];
|
|
|
+
|
|
|
+ protected $casts = [
|
|
|
+ 'probability_modifier' => 'decimal:4',
|
|
|
+ 'probability_override' => 'decimal:4',
|
|
|
+ 'is_active' => 'boolean'
|
|
|
+ ];
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关联种子
|
|
|
+ */
|
|
|
+ public function seed(): BelongsTo
|
|
|
+ {
|
|
|
+ return $this->belongsTo(FarmSeed::class, 'seed_id');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关联土地类型
|
|
|
+ */
|
|
|
+ public function landType(): BelongsTo
|
|
|
+ {
|
|
|
+ return $this->belongsTo(FarmLandType::class, 'land_type_id');
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## 5. 业务逻辑层
|
|
|
+
|
|
|
+### 5.1 神秘种子逻辑类
|
|
|
+
|
|
|
+```php
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Module\Farm\Logics;
|
|
|
+
|
|
|
+use App\Module\Farm\Models\FarmMysterySeeLandEffect;
|
|
|
+use App\Module\Farm\Models\FarmSeedOutput;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 神秘种子业务逻辑
|
|
|
+ */
|
|
|
+class MysterySeeLLogic
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * 为神秘种子选择最终产出(在发芽期调用)
|
|
|
+ *
|
|
|
+ * @param int $seedId 种子ID
|
|
|
+ * @param int $landTypeId 土地类型ID
|
|
|
+ * @return array 选择的产出信息
|
|
|
+ */
|
|
|
+ public function selectFinalOutput(int $seedId, int $landTypeId): array
|
|
|
+ {
|
|
|
+ // 获取调整后的概率分布
|
|
|
+ $adjustedOutputs = $this->calculateAdjustedProbabilities($seedId, $landTypeId);
|
|
|
+
|
|
|
+ // 执行随机选择
|
|
|
+ return $this->randomSelectOutput($adjustedOutputs);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 基于概率随机选择产出
|
|
|
+ *
|
|
|
+ * @param array $outputs 产出配置数组
|
|
|
+ * @return array 选择的产出信息
|
|
|
+ */
|
|
|
+ private function randomSelectOutput(array $outputs): array
|
|
|
+ {
|
|
|
+ $random = mt_rand(1, 10000) / 100; // 精确到0.01%
|
|
|
+ $cumulativeProbability = 0;
|
|
|
+
|
|
|
+ foreach ($outputs as $output) {
|
|
|
+ $cumulativeProbability += $output['adjusted_probability'];
|
|
|
+
|
|
|
+ if ($random <= $cumulativeProbability) {
|
|
|
+ return [
|
|
|
+ 'item_id' => $output['item_id'],
|
|
|
+ 'min_amount' => $output['min_amount'],
|
|
|
+ 'max_amount' => $output['max_amount']
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果随机值超出范围,返回默认产出
|
|
|
+ $defaultOutput = collect($outputs)->firstWhere('is_default', true);
|
|
|
+ if ($defaultOutput) {
|
|
|
+ return [
|
|
|
+ 'item_id' => $defaultOutput['item_id'],
|
|
|
+ 'min_amount' => $defaultOutput['min_amount'],
|
|
|
+ 'max_amount' => $defaultOutput['max_amount']
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 最后的保险:返回第一个产出
|
|
|
+ $firstOutput = $outputs[0] ?? null;
|
|
|
+ if ($firstOutput) {
|
|
|
+ return [
|
|
|
+ 'item_id' => $firstOutput['item_id'],
|
|
|
+ 'min_amount' => $firstOutput['min_amount'],
|
|
|
+ 'max_amount' => $firstOutput['max_amount']
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new \Exception('神秘种子没有有效的产出配置');
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## 6. 集成到现有系统
|
|
|
+
|
|
|
+### 6.1 修改作物生长逻辑
|
|
|
+
|
|
|
+在作物从种子期进入发芽期时,如果是神秘种子,需要调用新的逻辑来确定最终产出:
|
|
|
+
|
|
|
+```php
|
|
|
+// 在 CropLogic 的作物生长更新方法中
|
|
|
+public function updateCropGrowthStage(FarmCrop $crop): bool
|
|
|
+{
|
|
|
+ // ... 现有逻辑 ...
|
|
|
+
|
|
|
+ // 当作物进入发芽期时,确定最终产出
|
|
|
+ if ($newStage == GROWTH_STAGE::SPROUT && !$crop->final_output_item_id) {
|
|
|
+ $seed = $crop->seed;
|
|
|
+
|
|
|
+ // 如果是神秘种子,使用土地影响逻辑
|
|
|
+ if ($seed->type == SEED_TYPE::MYSTERIOUS->value) {
|
|
|
+ $land = $crop->land;
|
|
|
+ $mysteryLogic = new MysterySeeLLogic();
|
|
|
+ $selectedOutput = $mysteryLogic->selectFinalOutput($seed->id, $land->land_type);
|
|
|
+
|
|
|
+ // 设置最终产出物品ID
|
|
|
+ $crop->final_output_item_id = $selectedOutput['item_id'];
|
|
|
+ $crop->save();
|
|
|
+
|
|
|
+ Log::info('神秘种子确定最终产出', [
|
|
|
+ 'crop_id' => $crop->id,
|
|
|
+ 'seed_id' => $seed->id,
|
|
|
+ 'land_type' => $land->land_type,
|
|
|
+ 'final_output_item_id' => $selectedOutput['item_id']
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ... 其他逻辑 ...
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 6.2 后台管理界面
|
|
|
+
|
|
|
+#### 6.2.1 神秘种子土地影响配置控制器
|
|
|
+
|
|
|
+```php
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Module\Farm\AdminControllers;
|
|
|
+
|
|
|
+use App\Module\Farm\Models\FarmMysterySeeLandEffect;
|
|
|
+use App\Module\Farm\Repositories\FarmMysterySeeLandEffectRepository;
|
|
|
+use UCore\DcatAdmin\AdminController;
|
|
|
+use Dcat\Admin\Grid;
|
|
|
+use Dcat\Admin\Show;
|
|
|
+use Dcat\Admin\Form;
|
|
|
+
|
|
|
+class FarmMysterySeeLandEffectController extends AdminController
|
|
|
+{
|
|
|
+ protected function grid()
|
|
|
+ {
|
|
|
+ return Grid::make(new FarmMysterySeeLandEffectRepository(), function (Grid $grid) {
|
|
|
+ $grid->column('id', 'ID')->sortable();
|
|
|
+ $grid->column('seed.name', '种子名称');
|
|
|
+ $grid->column('landType.name', '土地类型');
|
|
|
+ $grid->column('output_item_id', '产出物品ID');
|
|
|
+ $grid->column('probability_modifier', '概率修正值')->display(function ($value) {
|
|
|
+ $color = $value > 0 ? 'success' : ($value < 0 ? 'danger' : 'secondary');
|
|
|
+ return "<span class='badge badge-{$color}'>{$value}%</span>";
|
|
|
+ });
|
|
|
+ $grid->column('probability_override', '概率覆盖值')->display(function ($value) {
|
|
|
+ return $value !== null ? "<span class='badge badge-warning'>{$value}%</span>" : '-';
|
|
|
+ });
|
|
|
+ $grid->column('is_active', '状态')->bool();
|
|
|
+ $grid->column('created_at', '创建时间');
|
|
|
+
|
|
|
+ $grid->filter(function (Grid\Filter $filter) {
|
|
|
+ $filter->equal('seed_id', '种子')->select('/admin/api/farm-seeds');
|
|
|
+ $filter->equal('land_type_id', '土地类型')->select('/admin/api/land-types');
|
|
|
+ $filter->equal('is_active', '状态')->select([1 => '启用', 0 => '禁用']);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function form()
|
|
|
+ {
|
|
|
+ return Form::make(new FarmMysterySeeLandEffectRepository(), function (Form $form) {
|
|
|
+ $form->display('id', 'ID');
|
|
|
+ $form->select('seed_id', '种子')->options('/admin/api/farm-seeds')->required();
|
|
|
+ $form->select('land_type_id', '土地类型')->options('/admin/api/land-types')->required();
|
|
|
+ $form->number('output_item_id', '产出物品ID')->required();
|
|
|
+ $form->decimal('probability_modifier', '概率修正值')->help('百分比值,可为负数。如:5.0000 表示 +5%');
|
|
|
+ $form->decimal('probability_override', '概率覆盖值')->help('百分比值,直接覆盖原概率。如:25.0000 表示覆盖为25%。优先级高于修正值,留空则使用修正值');
|
|
|
+ $form->switch('is_active', '是否启用')->default(1);
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## 7. 配置示例与效果
|
|
|
+
|
|
|
+### 7.1 土地类型影响效果表
|
|
|
+
|
|
|
+| 土地类型 | 物品2概率 | 物品3概率 | 物品4概率 | 设计理念 |
|
|
|
+|---------|----------|----------|----------|---------|
|
|
|
+| 普通土地 | 10% (基础) | 10% (基础) | 10% (基础) | 基础概率,无影响 |
|
|
|
+| 红土地 | 15% (+5%) | 10% (+0%) | 7% (-3%) | 轻微提升稀有度 |
|
|
|
+| 黑土地 | 20% (+10%) | 8% (-2%) | 5% (-5%) | 明显提升主要稀有物品 |
|
|
|
+| 金土地 | **25% (覆盖)** | 5% (-5%) | 18% (+8%) | 大幅提升稀有物品,物品2使用覆盖值 |
|
|
|
+| 蓝土地 | 22% (+12%) | 7% (-3%) | 22% (+12%) | 平衡提升多种稀有物品 |
|
|
|
+| 紫土地 | **30% (覆盖)** | 2% (-8%) | **25% (覆盖)** | 极大提升最稀有物品,使用覆盖值 |
|
|
|
+
|
|
|
+**说明:**
|
|
|
+- **粗体**表示使用概率覆盖值
|
|
|
+- (+X%)表示使用概率修正值
|
|
|
+- (基础)表示使用原始概率
|
|
|
+
|
|
|
+### 7.2 概率覆盖值 vs 概率修正值
|
|
|
+
|
|
|
+#### 7.2.1 使用场景对比
|
|
|
+
|
|
|
+| 特性 | 概率修正值 | 概率覆盖值 |
|
|
|
+|------|-----------|-----------|
|
|
|
+| **计算方式** | 基础概率 + 修正值 | 直接替换为覆盖值 |
|
|
|
+| **适用场景** | 微调概率,保持相对关系 | 精确控制概率,打破原有平衡 |
|
|
|
+| **配置灵活性** | 受基础概率限制 | 完全自由设定 |
|
|
|
+| **优先级** | 低 | 高 |
|
|
|
+| **典型用途** | 常规土地的渐进式提升 | 特殊土地的突破性改变 |
|
|
|
+
|
|
|
+#### 7.2.2 实际应用示例
|
|
|
+
|
|
|
+**场景1:渐进式提升(使用修正值)**
|
|
|
+- 基础概率:物品A 10%,物品B 10%,物品C 10%
|
|
|
+- 红土地修正:+5%, +0%, -3%
|
|
|
+- 最终概率:15%, 10%, 7%
|
|
|
+- **特点**:保持原有概率的相对关系
|
|
|
+
|
|
|
+**场景2:突破性改变(使用覆盖值)**
|
|
|
+- 基础概率:物品A 10%,物品B 10%,物品C 10%
|
|
|
+- 紫土地覆盖:30%, NULL, 25%
|
|
|
+- 最终概率:30%, 2%(-8%), 25%
|
|
|
+- **特点**:完全重新定义概率分布
|
|
|
+
|
|
|
+#### 7.2.3 配置策略建议
|
|
|
+
|
|
|
+1. **低级土地**:使用修正值进行微调
|
|
|
+2. **中级土地**:混合使用修正值和少量覆盖值
|
|
|
+3. **高级土地**:大量使用覆盖值实现质的飞跃
|
|
|
+4. **特殊土地**:完全使用覆盖值创造独特体验
|
|
|
+
|
|
|
+### 7.3 策略性考虑
|
|
|
+
|
|
|
+1. **土地选择策略**:玩家需要根据想要的产出类型选择合适的土地
|
|
|
+2. **土地升级价值**:高级土地不仅有产量加成,还能影响神秘种子的产出类型
|
|
|
+3. **风险与收益**:高级土地提升稀有物品概率,但可能降低某些物品的概率
|
|
|
+4. **覆盖值的战略意义**:高级土地通过覆盖值提供确定性的高概率,降低随机性风险
|
|
|
+
|
|
|
+## 8. 技术实现要点
|
|
|
+
|
|
|
+### 8.1 性能优化
|
|
|
+
|
|
|
+1. **缓存机制**:缓存土地影响配置,减少数据库查询
|
|
|
+2. **批量处理**:支持批量计算多个神秘种子的概率
|
|
|
+3. **索引优化**:在关键字段上建立合适的索引
|
|
|
+
|
|
|
+### 8.2 数据一致性
|
|
|
+
|
|
|
+1. **事务处理**:确保概率计算和产出确定在同一事务中
|
|
|
+2. **数据验证**:验证概率修正值的合理性
|
|
|
+3. **默认值处理**:确保总是有有效的产出结果
|
|
|
+
|
|
|
+### 8.3 扩展性设计
|
|
|
+
|
|
|
+1. **多种子支持**:系统设计支持多种神秘种子
|
|
|
+2. **配置灵活性**:通过数据库配置,无需修改代码
|
|
|
+3. **效果叠加**:预留其他因素影响概率的接口
|
|
|
+
|
|
|
+## 9. 测试方案
|
|
|
+
|
|
|
+### 9.1 单元测试
|
|
|
+
|
|
|
+```php
|
|
|
+public function testMysterySeeLProbabilityCalculation()
|
|
|
+{
|
|
|
+ // 测试概率计算逻辑
|
|
|
+ $logic = new MysterySeeLLogic();
|
|
|
+ $result = $logic->calculateAdjustedProbabilities(1, 4); // 神秘种子在金土地
|
|
|
+
|
|
|
+ $this->assertGreaterThan(10, $result[0]['adjusted_probability']); // 物品2概率应该提升
|
|
|
+}
|
|
|
+
|
|
|
+public function testProbabilityOverrideVsModifier()
|
|
|
+{
|
|
|
+ // 测试覆盖值优先级高于修正值
|
|
|
+ $logic = new MysterySeeLLogic();
|
|
|
+
|
|
|
+ // 创建测试数据:同时设置修正值和覆盖值
|
|
|
+ $testEffect = new FarmMysterySeeLandEffect([
|
|
|
+ 'seed_id' => 1,
|
|
|
+ 'land_type_id' => 6,
|
|
|
+ 'output_item_id' => 2,
|
|
|
+ 'probability_modifier' => 5.0000, // 修正值 +5%
|
|
|
+ 'probability_override' => 30.0000, // 覆盖值 30%
|
|
|
+ 'is_active' => true
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $result = $logic->calculateAdjustedProbabilities(1, 6);
|
|
|
+
|
|
|
+ // 应该使用覆盖值30%,而不是基础概率+修正值
|
|
|
+ $item2Result = collect($result)->firstWhere('item_id', 2);
|
|
|
+ $this->assertEquals(30.0000, $item2Result['adjusted_probability']);
|
|
|
+ $this->assertEquals('override', $item2Result['adjustment_type']);
|
|
|
+}
|
|
|
+
|
|
|
+public function testProbabilityModifierWhenNoOverride()
|
|
|
+{
|
|
|
+ // 测试没有覆盖值时使用修正值
|
|
|
+ $logic = new MysterySeeLLogic();
|
|
|
+
|
|
|
+ $testEffect = new FarmMysterySeeLandEffect([
|
|
|
+ 'seed_id' => 1,
|
|
|
+ 'land_type_id' => 2,
|
|
|
+ 'output_item_id' => 2,
|
|
|
+ 'probability_modifier' => 5.0000, // 修正值 +5%
|
|
|
+ 'probability_override' => null, // 无覆盖值
|
|
|
+ 'is_active' => true
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $result = $logic->calculateAdjustedProbabilities(1, 2);
|
|
|
+
|
|
|
+ // 应该使用基础概率+修正值
|
|
|
+ $item2Result = collect($result)->firstWhere('item_id', 2);
|
|
|
+ $this->assertEquals(15.0000, $item2Result['adjusted_probability']); // 10% + 5%
|
|
|
+ $this->assertEquals('modifier', $item2Result['adjustment_type']);
|
|
|
+}
|
|
|
+
|
|
|
+public function testProbabilityNormalization()
|
|
|
+{
|
|
|
+ // 测试概率归一化
|
|
|
+ $logic = new MysterySeeLLogic();
|
|
|
+ $result = $logic->calculateAdjustedProbabilities(1, 1);
|
|
|
+
|
|
|
+ $totalProbability = array_sum(array_column($result, 'adjusted_probability'));
|
|
|
+ $this->assertGreaterThan(0, $totalProbability);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 9.2 集成测试
|
|
|
+
|
|
|
+1. **完整流程测试**:从种植到收获的完整流程
|
|
|
+2. **概率分布测试**:大量测试验证概率分布的正确性
|
|
|
+3. **边界条件测试**:测试极端配置下的系统行为
|
|
|
+
|
|
|
+## 10. 部署与维护
|
|
|
+
|
|
|
+### 10.1 部署步骤
|
|
|
+
|
|
|
+1. 创建新数据表
|
|
|
+2. 插入初始配置数据
|
|
|
+3. 部署新代码
|
|
|
+4. 更新后台管理菜单
|
|
|
+5. 进行功能测试
|
|
|
+
|
|
|
+### 10.2 监控指标
|
|
|
+
|
|
|
+1. **概率分布监控**:监控实际产出分布是否符合预期
|
|
|
+2. **性能监控**:监控概率计算的性能影响
|
|
|
+3. **错误监控**:监控异常情况和错误日志
|
|
|
+
|
|
|
+### 10.3 配置调优
|
|
|
+
|
|
|
+1. **数据分析**:分析玩家行为和产出数据
|
|
|
+2. **平衡调整**:根据游戏平衡性调整概率修正值
|
|
|
+3. **新内容扩展**:支持新的神秘种子和土地类型
|
|
|
+```
|