| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- <?php
- namespace App\Module\Pet\Validators;
- use App\Module\Pet\Enums\PetStatus;
- use App\Module\Pet\Models\PetLevelConfig;
- use App\Module\Pet\Models\PetSkill;
- use App\Module\Pet\Models\PetUser;
- use Illuminate\Support\Facades\Log;
- use UCore\Validator;
- /**
- * 宠物技能使用验证器
- *
- * 用于验证宠物技能使用条件的合法性
- */
- class PetSkillUseValidator extends Validator
- {
- /**
- * 验证方法
- *
- * @param mixed $value 宠物ID
- * @param array $data 所有数据
- * @return bool 验证是否通过
- */
- public function validate(mixed $value, array $data): bool
- {
- $petId = $value;
- $skillId = $data['skillId'] ?? 0;
- try {
- // 获取宠物信息
- $pet = PetUser::find($petId);
- if (!$pet) {
- $this->addError('宠物不存在');
- return false;
- }
- // 获取技能信息
- $skill = PetSkill::find($skillId);
- if (!$skill) {
- $this->addError('技能(' . $skillId . ')不存在');
- return false;
- }
- // 检查宠物状态
- if ($pet->status !== PetStatus::NORMAL) {
- $this->addError('宠物当前状态(' . $pet->status->name . ')不允许使用技能');
- return false;
- }
- // 检查宠物当前等级是否可以使用该技能(基于等级配置表)
- if (!$this->checkPetSkillAvailable($pet, $skillId)) {
- $this->addError('该技能在当前等级(' . $pet->level . ')不可用');
- return false;
- }
- // 检查宠物体力是否足够
- if ($pet->stamina < $skill->stamina_cost) {
- $this->addError('宠物体力(' . $pet->stamina . ')不足,需要体力(' . $skill->stamina_cost . ')才能使用该技能');
- return false;
- }
- // 检查技能冷却时间
- $lastUsed = $pet->skillLogs()
- ->where('skill_id', $skillId)
- ->orderBy('used_at', 'desc')
- ->first();
- if ($lastUsed) {
- $cooldownSeconds = $skill->cool_down;
- $now = now();
- $lastUsedTime = $lastUsed->used_at;
- // 确保时间计算的正确性
- if ($lastUsedTime instanceof \Carbon\Carbon) {
- $secondsSinceLastUse = $now->diffInSeconds($lastUsedTime, false);
- } else {
- // 如果不是Carbon对象,尝试解析
- $lastUsedTime = \Carbon\Carbon::parse($lastUsedTime);
- $secondsSinceLastUse = $now->diffInSeconds($lastUsedTime, false);
- }
- // 如果secondsSinceLastUse为负数,说明lastUsed时间在未来,这是异常情况
- if ($secondsSinceLastUse < 0) {
- // 异常情况下,重置为0,允许技能使用
- $secondsSinceLastUse = 0;
- }
- if ($secondsSinceLastUse < $cooldownSeconds) {
- $remainingCooldown = $cooldownSeconds - $secondsSinceLastUse;
- $this->addError('技能冷却中,还需等待' . $remainingCooldown . '秒');
- return false;
- }
- }
- return true;
- } catch (\Exception $e) {
- $this->addError('验证过程发生错误: ' . $e->getMessage());
- return false;
- }
- }
- /**
- * 检查宠物当前等级是否可以使用指定技能
- *
- * 基于宠物等级配置表中的 skills 字段进行检查
- *
- * @param PetUser $pet 宠物对象
- * @param int $skillId 技能ID
- * @return bool 是否可以使用该技能
- */
- private function checkPetSkillAvailable(PetUser $pet, int $skillId): bool
- {
- try {
- // 获取宠物当前等级的配置
- // 注意:这里假设所有宠物都使用 pet_id=1 的配置,如果有多种宠物类型,需要修改
- $levelConfig = PetLevelConfig::where('pet_id', 1)
- ->where('level', $pet->level)
- ->first();
- if (!$levelConfig) {
- Log::warning('宠物等级配置不存在', [
- 'pet_id' => $pet->id,
- 'pet_level' => $pet->level,
- 'skill_id' => $skillId
- ]);
- // 如果没有配置,默认允许使用(向后兼容)
- return true;
- }
- // 检查技能是否在可用技能列表中
- $availableSkills = $levelConfig->skills ?? [];
- $isAvailable = in_array($skillId, $availableSkills);
- Log::info('宠物技能可用性检查', [
- 'pet_id' => $pet->id,
- 'pet_level' => $pet->level,
- 'skill_id' => $skillId,
- 'available_skills' => $availableSkills,
- 'is_available' => $isAvailable
- ]);
- return $isAvailable;
- } catch (\Exception $e) {
- Log::error('检查宠物技能可用性时发生错误', [
- 'pet_id' => $pet->id,
- 'pet_level' => $pet->level,
- 'skill_id' => $skillId,
- 'error' => $e->getMessage()
- ]);
- // 发生错误时默认允许使用(向后兼容)
- return true;
- }
- }
- }
|