PetDtoFactory.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <?php
  2. namespace App\Module\Pet\Factories;
  3. use App\Module\Pet\Dtos\PetDataDto;
  4. use App\Module\Pet\Dtos\PetLifeSkillDto;
  5. use App\Module\Pet\Models\PetUser;
  6. use App\Module\Pet\Models\PetSkill;
  7. use App\Module\Pet\Models\PetLevelConfig;
  8. use App\Module\Pet\Logic\PetLogic;
  9. use Illuminate\Support\Facades\Log;
  10. /**
  11. * 宠物DTO工厂类
  12. *
  13. * 负责创建宠物相关的DTO对象
  14. */
  15. class PetDtoFactory
  16. {
  17. /**
  18. * 创建宠物数据DTO
  19. *
  20. * @param PetUser $pet 宠物模型
  21. * @param int|null $fightingCapacity 战力值,如果为null则会计算
  22. * @return PetDataDto 宠物数据DTO
  23. */
  24. public static function createPetDataDto(PetUser $pet, ?int $fightingCapacity = null): PetDataDto
  25. {
  26. // 创建宠物DTO
  27. $petDto = new PetDataDto();
  28. $petDto->id = $pet->id;
  29. $petDto->typeId = $pet->type_id ?? 0; // 如果模型中没有type_id字段,默认为0
  30. $petDto->name = $pet->name;
  31. $petDto->level = $pet->level;
  32. $petDto->exp = $pet->experience;
  33. $petDto->power = $pet->stamina;
  34. // 获取宠物等级配置
  35. /**
  36. * @var PetLevelConfig $levelConfig
  37. */
  38. $levelConfig = PetLevelConfig::where('level', $pet->level)->first();
  39. $petDto->maxpower = $levelConfig ? ($levelConfig->numeric_attributes->stamina_max ?? 100) : 100;
  40. // 计算战力
  41. if ($fightingCapacity === null) {
  42. $petLogic = new PetLogic();
  43. $fightingCapacity = $petLogic->calculatePower($pet->id);
  44. }
  45. $petDto->fightingCapacity = $fightingCapacity;
  46. $petDto->score = $fightingCapacity; // 暂时使用战力作为评分
  47. // 设置品阶和状态
  48. // grade字段在数据库中是integer,直接使用
  49. $petDto->grade = $pet->grade;
  50. // status字段被转换为PetStatus枚举,需要获取value
  51. $petDto->status = $pet->status->value;
  52. // 获取宠物生活技能
  53. $petDto->lifeSkills = self::createPetLifeSkillDtos($pet);
  54. return $petDto;
  55. }
  56. /**
  57. * 创建宠物生活技能DTO数组
  58. *
  59. * @param PetUser $pet 宠物模型
  60. * @return array 生活技能DTO数组
  61. */
  62. public static function createPetLifeSkillDtos(PetUser $pet): array
  63. {
  64. // 获取所有技能
  65. $allSkills = PetSkill::all();
  66. // 筛选出宠物等级可用的技能(基于等级配置表)
  67. $availableSkills = $allSkills->filter(function ($skill) use ($pet) {
  68. return self::checkPetSkillAvailable($pet, $skill->id);
  69. });
  70. // 获取宠物当前激活的技能
  71. $activeSkills = \App\Module\Pet\Models\PetActiveSkill::where('pet_id', $pet->id)
  72. ->where('status', 'active')
  73. ->where('end_time', '>', now())
  74. ->get()
  75. ->keyBy('skill_id');
  76. // 获取技能使用记录,计算冷却时间
  77. $skillLogs = $pet->skillLogs()
  78. ->orderBy('used_at', 'desc')
  79. ->get()
  80. ->groupBy('skill_id');
  81. $skillDtos = [];
  82. foreach ($availableSkills as $skill) {
  83. $skillDto = new PetLifeSkillDto();
  84. $curnum = 0; // 当前剩余时间(激活技能的剩余时间)
  85. $maxnum = 0; // 最大时间(激活技能的持续时间)
  86. // 检查是否有激活的技能
  87. if (isset($activeSkills[$skill->id])) {
  88. /**
  89. * @var \App\Module\Pet\Models\PetActiveSkill $activeSkill
  90. */
  91. $activeSkill = $activeSkills[$skill->id];
  92. $now = now();
  93. // 计算激活技能的剩余时间
  94. $remainingSeconds = $now->diffInSeconds($activeSkill->end_time, false);
  95. if ($remainingSeconds > 0) {
  96. $curnum = $remainingSeconds; // 剩余激活时间
  97. $maxnum = $skill->duration_time; // 技能持续时间
  98. }
  99. $skillDto->end_times = $activeSkill->end_time->getTimestamp();
  100. }
  101. $skillDto->skillId = $skill->id;
  102. // $skillDto->canuse = $canUse; // 不再处理
  103. $skillDto->curnum = $curnum; // 激活技能的剩余时间
  104. $skillDto->maxnum = $maxnum; // 激活技能的持续时间
  105. // $
  106. $skillDtos[] = $skillDto;
  107. }
  108. return $skillDtos;
  109. }
  110. /**
  111. * 检查宠物当前等级是否可以使用指定技能
  112. *
  113. * 基于宠物等级配置表中的 skills 字段进行检查
  114. *
  115. * @param PetUser $pet 宠物对象
  116. * @param int $skillId 技能ID
  117. * @return bool 是否可以使用该技能
  118. */
  119. private static function checkPetSkillAvailable(PetUser $pet, int $skillId): bool
  120. {
  121. try {
  122. // 获取宠物当前等级的配置
  123. // 注意:这里假设所有宠物都使用 pet_id=1 的配置,如果有多种宠物类型,需要修改
  124. $levelConfig = PetLevelConfig::where('pet_id', 1)
  125. ->where('level', $pet->level)
  126. ->first();
  127. if (!$levelConfig) {
  128. Log::warning('宠物等级配置不存在', [
  129. 'pet_id' => $pet->id,
  130. 'pet_level' => $pet->level,
  131. 'skill_id' => $skillId
  132. ]);
  133. // 如果没有配置,默认允许使用(向后兼容)
  134. return true;
  135. }
  136. // 检查技能是否在可用技能列表中
  137. $availableSkills = $levelConfig->skills ?? [];
  138. $isAvailable = in_array($skillId, $availableSkills);
  139. Log::info('宠物技能可用性检查', [
  140. 'pet_id' => $pet->id,
  141. 'pet_level' => $pet->level,
  142. 'skill_id' => $skillId,
  143. 'available_skills' => $availableSkills,
  144. 'is_available' => $isAvailable
  145. ]);
  146. return $isAvailable;
  147. } catch (\Exception $e) {
  148. Log::error('检查宠物技能可用性时发生错误', [
  149. 'pet_id' => $pet->id,
  150. 'pet_level' => $pet->level,
  151. 'skill_id' => $skillId,
  152. 'error' => $e->getMessage()
  153. ]);
  154. // 发生错误时默认允许使用(向后兼容)
  155. return true;
  156. }
  157. }
  158. }