ItemRecipe.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <?php
  2. namespace App\Module\GameItems\Models;
  3. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  4. use Illuminate\Database\Eloquent\Relations\HasMany;
  5. use UCore\ModelCore;
  6. /**
  7. * 物品合成配方
  8. *
  9. * field start
  10. * @property int $id 配方ID,主键
  11. * @property string $name 配方名称
  12. * @property string $code 配方编码(唯一)
  13. * @property string $description 配方描述
  14. * @property int $consume_group_id 消耗组ID
  15. * @property int $reward_group_id 奖励组ID
  16. * @property int $condition_group_id 条件组ID
  17. * @property int $result_item_id 产出物品ID,外键关联kku_item_items表
  18. * @property int $result_min_quantity 最小产出数量
  19. * @property int $result_max_quantity 最大产出数量
  20. * @property float $success_rate 成功率(百分比,最大100)
  21. * @property object|array $coin_cost 货币成本,以JSON格式存储多种货币类型和数量
  22. * @property int $level_required 所需等级
  23. * @property int $is_default_unlocked 是否默认解锁(0:否, 1:是)
  24. * @property object|array $unlock_condition 解锁条件,以JSON格式存储
  25. * @property int $cooldown_seconds 冷却时间(秒)
  26. * @property int $category_id 配方分类ID
  27. * @property int $sort_order 排序权重
  28. * @property bool $is_active 是否激活(0:否, 1:是)
  29. * @property \Carbon\Carbon $created_at 创建时间
  30. * @property \Carbon\Carbon $updated_at 更新时间
  31. * field end
  32. */
  33. class ItemRecipe extends ModelCore
  34. {
  35. /**
  36. * 与模型关联的表名
  37. *
  38. * @var string
  39. */
  40. protected $table = 'item_recipes';
  41. // attrlist start
  42. protected $fillable = [
  43. 'id',
  44. 'name',
  45. 'code',
  46. 'description',
  47. 'consume_group_id',
  48. 'reward_group_id',
  49. 'condition_group_id',
  50. 'result_item_id',
  51. 'result_min_quantity',
  52. 'result_max_quantity',
  53. 'success_rate',
  54. 'coin_cost',
  55. 'level_required',
  56. 'is_default_unlocked',
  57. 'unlock_condition',
  58. 'cooldown_seconds',
  59. 'category_id',
  60. 'sort_order',
  61. 'is_active',
  62. ];
  63. // attrlist end
  64. /**
  65. * 应该被转换为原生类型的属性
  66. *
  67. * @var array
  68. */
  69. protected $casts = [
  70. 'consume_group_id' => 'integer',
  71. 'reward_group_id' => 'integer',
  72. 'condition_group_id' => 'integer',
  73. 'success_rate' => 'float',
  74. 'cooldown_seconds' => 'integer',
  75. 'category_id' => 'integer',
  76. 'sort_order' => 'integer',
  77. 'is_active' => 'boolean',
  78. ];
  79. /**
  80. * 获取消耗组
  81. *
  82. * @return BelongsTo
  83. */
  84. public function consumeGroup(): BelongsTo
  85. {
  86. return $this->belongsTo(\App\Module\Game\Models\GameConsumeGroup::class, 'consume_group_id');
  87. }
  88. /**
  89. * 获取奖励组
  90. *
  91. * @return BelongsTo
  92. */
  93. public function rewardGroup(): BelongsTo
  94. {
  95. return $this->belongsTo(\App\Module\Game\Models\GameRewardGroup::class, 'reward_group_id');
  96. }
  97. /**
  98. * 获取条件组
  99. *
  100. * @return BelongsTo
  101. */
  102. public function conditionGroup(): BelongsTo
  103. {
  104. return $this->belongsTo(\App\Module\Game\Models\GameConditionGroup::class, 'condition_group_id');
  105. }
  106. /**
  107. * 获取用户配方解锁状态
  108. *
  109. * @return HasMany
  110. */
  111. public function userRecipes(): HasMany
  112. {
  113. return $this->hasMany(ItemUserRecipe::class, 'recipe_id');
  114. }
  115. /**
  116. * 获取合成记录
  117. *
  118. * @return HasMany
  119. */
  120. public function craftLogs(): HasMany
  121. {
  122. return $this->hasMany(ItemCraftLog::class, 'recipe_id');
  123. }
  124. /**
  125. * 检查用户是否已解锁该配方
  126. *
  127. * @param int $userId 用户ID
  128. * @return bool
  129. */
  130. public function isUnlockedByUser(int $userId): bool
  131. {
  132. $userRecipe = $this->userRecipes()
  133. ->where('user_id', $userId)
  134. ->first();
  135. return $userRecipe && $userRecipe->is_unlocked;
  136. }
  137. /**
  138. * 检查用户是否可以合成该配方
  139. *
  140. * @param int $userId 用户ID
  141. * @return array 检查结果,包含是否可合成和原因
  142. */
  143. public function canCraftByUser(int $userId): array
  144. {
  145. // 检查配方是否激活
  146. if (!$this->is_active) {
  147. return [
  148. 'can_craft' => false,
  149. 'reason' => '配方未激活',
  150. ];
  151. }
  152. // 检查条件组(如果设置了条件组)
  153. if ($this->condition_group_id && $this->conditionGroup) {
  154. $conditionService = app(\App\Module\Game\Services\ConditionService::class);
  155. $conditionResult = $conditionService->checkConditionGroup($userId, $this->condition_group_id);
  156. if (!$conditionResult['is_satisfied']) {
  157. return [
  158. 'can_craft' => false,
  159. 'reason' => '条件不满足',
  160. 'condition_details' => $conditionResult['details'],
  161. ];
  162. }
  163. }
  164. // 检查冷却时间
  165. if ($this->cooldown_seconds > 0) {
  166. $lastCraft = $this->craftLogs()
  167. ->where('user_id', $userId)
  168. ->where('created_at', '>', now()->subSeconds($this->cooldown_seconds))
  169. ->first();
  170. if ($lastCraft) {
  171. $remainingSeconds = $this->cooldown_seconds - now()->diffInSeconds($lastCraft->created_at);
  172. return [
  173. 'can_craft' => false,
  174. 'reason' => '冷却中',
  175. 'remaining_seconds' => $remainingSeconds,
  176. ];
  177. }
  178. }
  179. // 检查消耗组是否满足
  180. if ($this->consume_group_id && $this->consumeGroup) {
  181. $consumeService = app(\App\Module\Game\Services\ConsumeService::class);
  182. $consumeResult = $consumeService->checkConsumeGroup($userId, $this->consume_group_id);
  183. if (!$consumeResult['can_consume']) {
  184. return [
  185. 'can_craft' => false,
  186. 'reason' => '材料不足',
  187. 'consume_details' => $consumeResult['details'],
  188. ];
  189. }
  190. }
  191. return [
  192. 'can_craft' => true,
  193. ];
  194. }
  195. }