30日1930-实现宠物自动技能效果.md 15 KB

实现宠物三个自动技能的具体效果

任务描述

完整实现自动收菜、自动播种、灾害防护三个宠物技能的具体效果

需求分析

背景

在之前的任务中,我们已经建立了宠物自动技能的基础架构:

  • 技能激活和管理系统
  • 定时任务处理框架
  • 技能状态记录和监控

但是三个核心技能的具体效果还没有完整实现,需要:

  1. 自动收菜:自动收获成熟的作物
  2. 自动播种:自动在空闲土地上播种
  3. 灾害防护:自动检查并清除作物灾害

技能需求详细分析

1. 自动收菜技能

  • 触发条件:每分钟检查一次
  • 执行逻辑
    • 查找用户所有可收获的土地
    • 逐个调用收获服务
    • 记录收获结果和统计信息
  • 资源消耗:无额外消耗(收获本身不消耗道具)

2. 自动播种技能

  • 触发条件:每分钟检查一次
  • 执行逻辑
    • 查找用户所有空闲的土地
    • 获取用户拥有的种子物品
    • 优先使用配置的种子类型
    • 逐个播种并消耗种子
  • 资源消耗:消耗种子物品

3. 灾害防护技能

  • 触发条件:每5分钟检查一次
  • 执行逻辑
    • 查找用户所有有作物的土地
    • 检查作物是否有活跃的灾害
    • 根据防护类型自动清除灾害
    • 消耗相应的清除道具
  • 资源消耗:消耗灾害清除道具

实现方案

1. 扩展农场服务接口

1.1 LandService新增方法

/**
 * 获取用户所有可收获的土地
 */
public static function getHarvestableLands(int $userId): Collection

/**
 * 获取用户所有空闲的土地
 */
public static function getIdleLands(int $userId): Collection

/**
 * 获取用户所有有作物的土地
 */
public static function getLandsWithCrops(int $userId): Collection

1.2 LandLogic实现方法

public function getHarvestableLands(int $userId): Collection
{
    // 查询状态为可收获的土地
    $lands = FarmLand::where('user_id', $userId)
        ->where('status', LAND_STATUS::HARVESTABLE->value)
        ->orderBy('position')
        ->get();

    return $lands->map(function ($land) {
        return LandInfoDto::fromModel($land);
    });
}

2. 扩展物品服务接口

2.1 ItemService新增方法

/**
 * 获取用户拥有的种子物品
 */
public static function getUserSeedItems(int $userId, bool $includeExpired = false): array
{
    // 获取所有种子的物品ID
    $seedItemIds = FarmSeed::pluck('item_id')->toArray();
    
    // 查询用户拥有的种子物品
    $userItems = ItemUser::where('user_id', $userId)
        ->whereIn('item_id', $seedItemIds)
        ->where('quantity', '>', 0)
        ->get();

    // 按物品ID分组并汇总数量
    $seedItems = [];
    foreach ($userItems as $userItem) {
        $itemId = $userItem->item_id;
        $seedItems[$itemId] = ($seedItems[$itemId] ?? 0) + $userItem->quantity;
    }

    return $seedItems;
}

3. 完善PetAutoSkillLogic类

3.1 自动收菜实现

public function processAutoHarvest(PetActiveSkill $activeSkill): void
{
    $pet = $activeSkill->pet;
    $userId = $pet->user_id;

    // 获取用户所有可收获的土地
    $harvestableLands = LandService::getHarvestableLands($userId);

    $harvestCount = 0;
    foreach ($harvestableLands as $land) {
        try {
            DB::beginTransaction();

            // 调用收获服务
            $result = CropService::harvestCrop($userId, $land->id);
            
            if ($result && !$result->error) {
                $harvestCount++;
                Log::info('自动收菜成功', [
                    'user_id' => $userId,
                    'pet_id' => $pet->id,
                    'land_id' => $land->id
                ]);
            }

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            Log::warning('自动收菜失败', [
                'user_id' => $userId,
                'pet_id' => $pet->id,
                'land_id' => $land->id,
                'error' => $e->getMessage()
            ]);
        }
    }

    // 记录统计信息
    $this->recordSkillStatistics($activeSkill, 'auto_harvest', [
        'harvest_count' => $harvestCount,
        'total_lands_checked' => $harvestableLands->count()
    ]);
}

3.2 自动播种实现

public function processAutoPlant(PetActiveSkill $activeSkill): void
{
    $pet = $activeSkill->pet;
    $userId = $pet->user_id;

    // 获取用户所有空闲的土地
    $idleLands = LandService::getIdleLands($userId);

    // 获取优先使用的种子列表
    $preferredSeeds = $activeSkill->getConfigValue('preferred_seeds', []);
    
    // 获取用户拥有的种子物品
    $availableSeeds = $this->getAvailableSeeds($userId, $preferredSeeds);

    $plantCount = 0;
    foreach ($idleLands as $land) {
        if (empty($availableSeeds)) {
            break; // 种子用完了
        }

        try {
            DB::beginTransaction();

            // 选择种子(优先使用配置的种子)
            $seedItemId = array_shift($availableSeeds);

            // 先消耗种子物品
            ItemService::consumeItem($userId, $seedItemId, null, 1, [
                'source' => 'pet_auto_plant'
            ]);

            // 调用种植服务
            $result = CropService::plantCrop($userId, $land->id, $seedItemId);
            
            if ($result) {
                $plantCount++;
                Log::info('自动播种成功', [
                    'user_id' => $userId,
                    'pet_id' => $pet->id,
                    'land_id' => $land->id,
                    'seed_item_id' => $seedItemId
                ]);
            }

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            Log::warning('自动播种失败', [
                'user_id' => $userId,
                'pet_id' => $pet->id,
                'land_id' => $land->id,
                'error' => $e->getMessage()
            ]);
        }
    }

    // 记录统计信息
    $this->recordSkillStatistics($activeSkill, 'auto_plant', [
        'plant_count' => $plantCount,
        'total_lands_checked' => $idleLands->count()
    ]);
}

3.3 灾害防护实现

public function processDisasterProtection(PetActiveSkill $activeSkill): void
{
    $pet = $activeSkill->pet;
    $userId = $pet->user_id;

    // 获取防护的灾害类型
    $protectedTypes = $activeSkill->getConfigValue('protected_types', ['all']);

    // 获取用户所有有作物的土地
    $landsWithCrops = LandService::getLandsWithCrops($userId);

    $protectionCount = 0;
    foreach ($landsWithCrops as $land) {
        try {
            // 检查土地是否有灾害
            $hasDisaster = $this->checkLandDisaster($land, $protectedTypes);
            
            if ($hasDisaster) {
                // 自动清除灾害(需要消耗相应道具)
                $cleared = $this->autoClearDisaster($userId, $land, $protectedTypes);
                
                if ($cleared) {
                    $protectionCount++;
                    Log::info('自动清除灾害成功', [
                        'user_id' => $userId,
                        'pet_id' => $pet->id,
                        'land_id' => $land->id
                    ]);
                }
            }
        } catch (\Exception $e) {
            Log::warning('灾害防护处理失败', [
                'user_id' => $userId,
                'pet_id' => $pet->id,
                'land_id' => $land->id,
                'error' => $e->getMessage()
            ]);
        }
    }

    // 记录统计信息
    $this->recordSkillStatistics($activeSkill, 'disaster_protection', [
        'protection_count' => $protectionCount,
        'total_lands_checked' => $landsWithCrops->count(),
        'protected_types' => $protectedTypes
    ]);
}

4. 灾害检查和清除逻辑

4.1 检查土地灾害

protected function checkLandDisaster($land, array $protectedTypes): bool
{
    // 检查土地状态是否为灾害状态
    if ($land->status !== LAND_STATUS::DISASTER->value) {
        return false;
    }

    // 获取土地上的作物
    $crop = $land->crop;
    if (!$crop) {
        return false;
    }

    // 检查作物是否有活跃的灾害
    $disasters = $crop->disasters ?? [];
    
    foreach ($disasters as $disaster) {
        if (($disaster['status'] ?? '') === 'active') {
            $disasterType = $disaster['type'] ?? 0;
            
            // 如果防护类型包含'all'或包含特定灾害类型
            if (in_array('all', $protectedTypes) || in_array($disasterType, $protectedTypes)) {
                return true;
            }
        }
    }

    return false;
}

4.2 自动清除灾害

protected function autoClearDisaster(int $userId, $land, array $protectedTypes): bool
{
    $crop = $land->crop;
    if (!$crop) {
        return false;
    }

    $disasters = $crop->disasters ?? [];
    $clearedCount = 0;
    
    foreach ($disasters as $disaster) {
        if (($disaster['status'] ?? '') === 'active') {
            $disasterType = $disaster['type'] ?? 0;
            
            // 检查是否需要清除这种类型的灾害
            if (in_array('all', $protectedTypes) || in_array($disasterType, $protectedTypes)) {
                try {
                    // 获取对应的清除道具
                    $clearItem = $this->getDisasterClearItem($userId, $disasterType);
                    
                    if ($clearItem) {
                        // 调用农场服务清除灾害
                        $result = CropService::clearDisaster($userId, $land->id, $disasterType);
                        
                        if ($result) {
                            // 消耗道具
                            ItemService::consumeItem(
                                $userId, 
                                $clearItem['item_id'], 
                                null, 
                                1, 
                                ['source' => 'pet_auto_disaster_protection']
                            );
                            
                            $clearedCount++;
                        }
                    }
                } catch (\Exception $e) {
                    Log::warning('宠物自动清除灾害失败', [
                        'user_id' => $userId,
                        'land_id' => $land->id,
                        'disaster_type' => $disasterType,
                        'error' => $e->getMessage()
                    ]);
                }
            }
        }
    }

    return $clearedCount > 0;
}

修改内容

修改文件列表

  1. app/Module/Farm/Services/LandService.php - 新增土地查询方法
  2. app/Module/Farm/Logics/LandLogic.php - 实现土地查询逻辑
  3. app/Module/GameItems/Services/ItemService.php - 新增种子物品查询方法
  4. app/Module/Pet/Logic/PetAutoSkillLogic.php - 完善三个技能的具体实现

具体实现特点

1. 自动收菜技能

  • 无资源消耗:收获本身不需要额外道具
  • 批量处理:一次处理所有可收获的土地
  • 事务安全:每个土地的收获都在独立事务中
  • 错误隔离:单个土地收获失败不影响其他土地

2. 自动播种技能

  • 智能种子选择:优先使用配置的种子类型
  • 资源管理:先消耗种子再播种,确保资源正确扣除
  • 数量控制:种子用完自动停止播种
  • 配置灵活:支持用户配置优先种子列表

3. 灾害防护技能

  • 类型过滤:支持防护特定类型的灾害或全部灾害
  • 道具映射:根据灾害类型自动选择对应的清除道具
  • 资源检查:确保用户拥有足够的清除道具
  • 批量清除:一次处理所有符合条件的灾害

技术特点

1. 模块化设计

  • 服务分离:农场、物品、宠物模块各司其职
  • 接口清晰:通过Service层进行模块间通信
  • 职责明确:每个方法只负责特定的功能

2. 错误处理

  • 事务保护:每个操作都在事务中执行
  • 异常隔离:单个操作失败不影响其他操作
  • 详细日志:记录成功和失败的详细信息
  • 降级处理:异常情况下仍能继续处理其他项目

3. 性能优化

  • 批量查询:一次查询所有相关数据
  • 智能过滤:只处理符合条件的项目
  • 资源预检:提前检查资源可用性
  • 统计优化:合并统计信息减少数据库操作

4. 用户体验

  • 智能配置:支持用户自定义优先级
  • 资源保护:确保不会浪费用户资源
  • 状态透明:详细记录每次操作的结果
  • 灵活控制:支持不同类型的防护策略

游戏平衡性

1. 资源消耗

  • 自动收菜:无额外消耗,纯便利功能
  • 自动播种:消耗种子,与手动播种相同
  • 灾害防护:消耗清除道具,与手动清除相同

2. 效率控制

  • 时间间隔:收菜和播种每分钟,防护每5分钟
  • 数量限制:受用户拥有的资源限制
  • 技能持续时间:有明确的生效期限

3. 策略性

  • 种子选择:用户可以配置优先种子
  • 灾害类型:用户可以选择防护的灾害类型
  • 资源管理:需要用户合理准备道具

监控和统计

1. 操作统计

  • 成功次数:记录每次执行的成功操作数量
  • 失败原因:详细记录失败的具体原因
  • 资源消耗:统计消耗的道具数量和类型

2. 性能监控

  • 执行时间:监控每次技能执行的耗时
  • 数据库查询:优化查询性能
  • 内存使用:控制批量操作的内存占用

3. 用户行为

  • 使用频率:统计技能的使用频率
  • 配置偏好:分析用户的配置选择
  • 效果评估:评估技能对用户游戏体验的影响

任务状态

✅ 已完成

相关文件

  • app/Module/Farm/Services/LandService.php - 土地服务扩展
  • app/Module/Farm/Logics/LandLogic.php - 土地逻辑实现
  • app/Module/GameItems/Services/ItemService.php - 物品服务扩展
  • app/Module/Pet/Logic/PetAutoSkillLogic.php - 自动技能逻辑实现

后续优化建议

1. 性能优化

  • 考虑使用缓存减少数据库查询
  • 优化批量操作的事务处理
  • 实现更智能的资源预分配

2. 功能扩展

  • 支持更多的技能配置选项
  • 增加技能效果的个性化定制
  • 实现技能间的协同效果

3. 用户体验

  • 提供更详细的技能执行报告
  • 增加技能效果的可视化展示
  • 优化技能配置的用户界面