ItemRecipe.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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 \App\Module\GameItems\Casts\RecipeDisplayAttributesCast $display_attributes 展示属性,以JSON格式存储键值对,用于界面展示和描述的属性
  18. * @property float $success_rate 成功率(0-100之间的小数,100 = 100%)
  19. * @property int $cooldown_seconds 冷却时间(秒)
  20. * @property int $category_id 配方分类ID
  21. * @property int $sort_order 排序权重
  22. * @property bool $is_active 是否激活(0:否, 1:是)
  23. * @property \Carbon\Carbon $created_at 创建时间
  24. * @property \Carbon\Carbon $updated_at 更新时间
  25. * field end
  26. */
  27. class ItemRecipe extends ModelCore
  28. {
  29. /**
  30. * 与模型关联的表名
  31. *
  32. * @var string
  33. */
  34. protected $table = 'item_recipes';
  35. // attrlist start
  36. protected $fillable = [
  37. 'id',
  38. 'name',
  39. 'code',
  40. 'description',
  41. 'consume_group_id',
  42. 'reward_group_id',
  43. 'condition_group_id',
  44. 'display_attributes',
  45. 'success_rate',
  46. 'cooldown_seconds',
  47. 'category_id',
  48. 'sort_order',
  49. 'is_active',
  50. ];
  51. // attrlist end
  52. /**
  53. * 应该被转换为原生类型的属性
  54. *
  55. * @var array
  56. */
  57. protected $casts = [
  58. 'consume_group_id' => 'integer',
  59. 'reward_group_id' => 'integer',
  60. 'condition_group_id' => 'integer',
  61. 'display_attributes' => \App\Module\GameItems\Casts\RecipeDisplayAttributesCast::class,
  62. 'success_rate' => 'float',
  63. 'cooldown_seconds' => 'integer',
  64. 'category_id' => 'integer',
  65. 'sort_order' => 'integer',
  66. 'is_active' => 'boolean',
  67. ];
  68. /**
  69. * 获取消耗组
  70. *
  71. * @return BelongsTo
  72. */
  73. public function consumeGroup(): BelongsTo
  74. {
  75. return $this->belongsTo(\App\Module\Game\Models\GameConsumeGroup::class, 'consume_group_id');
  76. }
  77. /**
  78. * 获取奖励组
  79. *
  80. * @return BelongsTo
  81. */
  82. public function rewardGroup(): BelongsTo
  83. {
  84. return $this->belongsTo(\App\Module\Game\Models\GameRewardGroup::class, 'reward_group_id');
  85. }
  86. /**
  87. * 获取条件组
  88. *
  89. * @return BelongsTo
  90. */
  91. public function conditionGroup(): BelongsTo
  92. {
  93. return $this->belongsTo(\App\Module\Game\Models\GameConditionGroup::class, 'condition_group_id');
  94. }
  95. /**
  96. * 获取用户配方解锁状态
  97. *
  98. * @return HasMany
  99. */
  100. public function userRecipes(): HasMany
  101. {
  102. return $this->hasMany(ItemUserRecipe::class, 'recipe_id');
  103. }
  104. /**
  105. * 获取合成记录
  106. *
  107. * @return HasMany
  108. */
  109. public function craftLogs(): HasMany
  110. {
  111. return $this->hasMany(ItemCraftLog::class, 'recipe_id');
  112. }
  113. /**
  114. * 检查用户是否已解锁该配方
  115. *
  116. * @param int $userId 用户ID
  117. * @return bool
  118. */
  119. public function isUnlockedByUser(int $userId): bool
  120. {
  121. $userRecipe = $this->userRecipes()
  122. ->where('user_id', $userId)
  123. ->first();
  124. return $userRecipe && $userRecipe->is_unlocked;
  125. }
  126. /**
  127. * 格式化消耗组详情用于显示
  128. *
  129. * @return string
  130. */
  131. public function formatConsumeDetails(): string
  132. {
  133. if (!$this->consumeGroup) {
  134. return '<span class="text-muted">无消耗组</span>';
  135. }
  136. return $this->consumeGroup->formatConsumeDetails();
  137. }
  138. /**
  139. * 格式化奖励组详情用于显示
  140. *
  141. * @return string
  142. */
  143. public function formatRewardDetails(): string
  144. {
  145. if (!$this->rewardGroup) {
  146. return '<span class="text-muted">无奖励组</span>';
  147. }
  148. return $this->rewardGroup->formatRewardDetails();
  149. }
  150. /**
  151. * 格式化条件组详情用于显示
  152. *
  153. * @return string
  154. */
  155. public function formatConditionDetails(): string
  156. {
  157. if (!$this->conditionGroup) {
  158. return '<span class="text-muted">无条件组</span>';
  159. }
  160. return $this->conditionGroup->formatConditionDetails();
  161. }
  162. /**
  163. * 检查用户是否可以合成该配方
  164. *
  165. * @param int $userId 用户ID
  166. * @return array 检查结果,包含是否可合成和原因
  167. */
  168. public function canCraftByUser(int $userId): array
  169. {
  170. // 检查配方是否激活
  171. if (!$this->is_active) {
  172. return [
  173. 'can_craft' => false,
  174. 'reason' => '配方未激活',
  175. ];
  176. }
  177. // 检查条件组(如果设置了条件组)
  178. if ($this->condition_group_id && $this->conditionGroup) {
  179. $conditionService = app(\App\Module\Game\Services\ConditionService::class);
  180. $conditionResult = $conditionService->checkCondition($userId, $this->condition_group_id);
  181. if (!$conditionResult['success']) {
  182. return [
  183. 'can_craft' => false,
  184. 'reason' => '条件不满足: ' . $conditionResult['message'],
  185. ];
  186. }
  187. }
  188. // 检查消耗组是否满足
  189. if ($this->consume_group_id && $this->consumeGroup) {
  190. $consumeService = app(\App\Module\Game\Services\ConsumeService::class);
  191. $consumeResult = $consumeService->checkConsume($userId, $this->consume_group_id);
  192. if (!$consumeResult->success) {
  193. return [
  194. 'can_craft' => false,
  195. 'reason' => '材料不足: ' . $consumeResult->message,
  196. ];
  197. }
  198. }
  199. return [
  200. 'can_craft' => true,
  201. ];
  202. }
  203. }