fighting_capacity = ($pet->blood + $pet->blood_add) * 0.2 + ($pet->attack + $pet->attack_add) * 1 + ($pet->anti + $pet->anti_add) * 2 + ($pet->crit + $pet->crit_add) * 3 + ($pet->dodge + $pet->dodge_add) * 3; } /** * 孵化 * @param $userID * @param $petItemID * @return Pet */ public static function broodingEgg($userID, $petItemID) { return SafeUtil::dbOperate(function ($userID, $petItemID) { $itemConfig = GameConfigServices::getParamByPath('item_list.' . $petItemID); if (empty($itemConfig)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ((int)$itemConfig['type2'] != ItemServices::ITEM_TYPE2_EGG) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $evolutionConfig = GameConfigServices::getParamByPath('evolution_list.' . $petItemID); if (empty($evolutionConfig)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $needTime = intval($evolutionConfig['evolution_time']); $gem = intval($evolutionConfig['Diamonds']); if ($needTime <= 0 || $gem <= 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $user = User::findById($userID); $petConfig = GameConfigServices::getParamByPath('pet.' . $petItemID); if (intval($petConfig['player_level']) > $user->level) throw new StatusException(ResultStatusServices::RS_LEVEL_LIMIT); $petConfig = GameConfigServices::getParamByPath('pet.' . $evolutionConfig['next_id']); if (empty($petConfig)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $log = SystemLogUtil::get($userID, SystemLogUtil::TYPE_ITEM, $petItemID, -1, SystemLogUtil::FROM_TYPE_BROODING_EGG, []); MoneyUtil::checkAndModifyNum($userID, $petItemID, false, -1, $log); $pet = new Pet(); $pet->user_id = $userID; $pet->pet_config_id = $petConfig['id']; $pet->name = $petConfig['name']; $pet->blood = (int)$petConfig['blood']; $pet->attack = (int)$petConfig['attack']; $pet->anti = (int)$petConfig['anti']; $pet->crit = (int)$petConfig['crit']; $pet->dodge = (int)$petConfig['dodge']; $pet->end_brooding_time = time() + $needTime; $pet->accelerate_brooding_gem = $gem; self::updateFight($pet); self::updateFeedTime($pet); if (!$pet->save()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR); //成就 AchievementUtil::addCount($userID, AchievementUtil::ID_HATCH_PET, 1); return $pet; }, [$userID, $petItemID]); } /** * 加速孵化 */ public static function accelerateBroodingEgg($userID, $petID) { SafeUtil::dbOperate(function ($userID, $petID) { return SafeUtil::redisLockOperate(function ($userID, $petID) { $pet = Pet::findByPetID($petID); if (empty($pet)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->end_brooding_time <= time() || $pet->accelerate_brooding_gem <= 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->user_id != $userID) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $log = SystemLogUtil::get($pet->user_id, SystemLogUtil::TYPE_GEM, -$pet->accelerate_brooding_gem, 0, SystemLogUtil::FROM_TYPE_ACCELERATE_BROODING_EGG, []); MoneyUtil::checkAndModifyRes($pet->user_id, false, -$pet->accelerate_brooding_gem, ItemServices::ITEM_TYPE2_GEM, $log); $pet->end_brooding_time = time(); $pet->accelerate_brooding_gem = 0; self::updateFeedTime($pet); if (!$pet->save()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR); }, [$userID, $petID], RedisKeyUtil::lockPet($petID)); }, [$userID, $petID]); } /** * 进化 * @param $petID */ public static function evolution($userID, $petID) { SafeUtil::dbOperate(function ($userID, $petID) { SafeUtil::redisLockOperate(function ($userID, $petID) { $pet = Pet::findByPetID($petID); if (empty($pet)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->end_brooding_time > time()) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->user_id != $userID) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $petConfig = GameConfigServices::getParamByPath('pet.' . $pet->pet_config_id); if ($pet->level != intval($petConfig['max_level'])) throw new StatusException(ResultStatusServices::RS_PET_NEED_UPGRADE_MAX_LEVEL); if ($pet->blood_train_count != $pet->level || $pet->attack_train_count != $pet->level || $pet->anti_train_count != $pet->level || $pet->crit_train_count != $pet->level || $pet->dodge_train_count != $pet->level ) throw new StatusException(ResultStatusServices::RS_PET_TRAIN_NEED_MAX); $evolutionConfig = GameConfigServices::getParamByPath('evolution_list.' . $pet->pet_config_id); if (empty($evolutionConfig)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $user = User::findById($userID); $nextPetConfig = GameConfigServices::getParamByPath('pet.' . $evolutionConfig['next_id']); if (intval($nextPetConfig['player_level']) > $user->level) throw new StatusException(ResultStatusServices::RS_LEVEL_LIMIT); MoneyUtil::parseItem(sprintf('%s:1', $evolutionConfig['drawing_id']), 1, false, $pet->user_id, SystemLogUtil::FROM_TYPE_PET_EVOLUTION, ['config' => $evolutionConfig]); $expendList = MoneyUtil::parseAllItem($evolutionConfig['crystal_id'], 1, false, $pet->user_id, SystemLogUtil::FROM_TYPE_PET_EVOLUTION, ['config' => $evolutionConfig]); if (count($expendList) == 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $pet->pet_config_id = $evolutionConfig['next_id']; // $pet->level = 1; // $pet->exp = 0; $petConfig = GameConfigServices::getParamByPath('pet.' . $pet->pet_config_id); $pet->name = (int)$petConfig['name']; $pet->blood = (int)$petConfig['blood']; $pet->attack = (int)$petConfig['attack']; $pet->anti = (int)$petConfig['anti']; $pet->crit = (int)$petConfig['crit']; $pet->dodge = (int)$petConfig['dodge']; // $pet->blood_train_count = 0; // $pet->attack_train_count = 0; // $pet->anti_train_count = 0; // $pet->crit_train_count = 0; // $pet->dodge_train_count = 0; self::updateFight($pet); self::updateFeedTime($pet); if (!$pet->save()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR); if ($pet->is_enter_war == self::ENTER_WAR) ArenaUtil::updatePet($userID, $pet); }, [$userID, $petID], RedisKeyUtil::lockPet($petID)); }, [$userID, $petID]); } /** * 培养 * @param $petID */ public static function train($userID, $petID, $type) { SafeUtil::dbOperate(function ($userID, $petID, $type) { SafeUtil::redisLockOperate(function ($userID, $petID, $type) { $type = (int)$type; if (!in_array($type, self::PROPERTY_LIST)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $pet = Pet::findByPetID($petID); if (empty($pet)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->end_brooding_time > time()) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->user_id != $userID) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $trainConfig = GameConfigServices::getParamByPath('culture.' . $pet->pet_config_id); if (empty($trainConfig)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $expendList = MoneyUtil::parseAllItemIndex($trainConfig['consume_id'], $type - 1, 1, false, $pet->user_id, SystemLogUtil::FROM_TYPE_PET_TRAIN, ['config' => $trainConfig]); if (count($expendList) == 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); switch ($type) { case self::PROPERTY_BLOOD: { if ($pet->blood_train_count == $pet->level) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $pet->blood_add += (int)$trainConfig['blood']; $pet->blood_train_count += 1; //任务记录 DailyTaskUtil::addTaskCount($userID, DailyTaskUtil::TYPE_TRAIN_PET_BLOOD, null, 1); break; } case self::PROPERTY_ATTACK: { if ($pet->attack_train_count == $pet->level) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $pet->attack_add += (int)$trainConfig['attack']; $pet->attack_train_count += 1; //任务记录 DailyTaskUtil::addTaskCount($userID, DailyTaskUtil::TYPE_TRAIN_PET_ATTACK, null, 1); break; } case self::PROPERTY_ANTI: { if ($pet->anti_train_count == $pet->level) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $pet->anti_add += (int)$trainConfig['anti']; $pet->anti_train_count += 1; //任务记录 DailyTaskUtil::addTaskCount($userID, DailyTaskUtil::TYPE_TRAIN_PET_ANTI, null, 1); break; } case self::PROPERTY_CRIT: { if ($pet->crit_train_count == $pet->level) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $pet->crit_add += (int)$trainConfig['crit']; $pet->crit_train_count += 1; //任务记录 DailyTaskUtil::addTaskCount($userID, DailyTaskUtil::TYPE_TRAIN_PET_CRIT, null, 1); break; } case self::PROPERTY_DODGE: { if ($pet->dodge_train_count == $pet->level) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $pet->dodge_add += (int)$trainConfig['dodge']; $pet->dodge_train_count += 1; //任务记录 DailyTaskUtil::addTaskCount($userID, DailyTaskUtil::TYPE_TRAIN_PET_DODGE, null, 1); break; } } self::updateFight($pet); self::updateFeedTime($pet); if (!$pet->save()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR); if ($pet->is_enter_war == self::ENTER_WAR) ArenaUtil::updatePet($userID, $pet); }, [$userID, $petID, $type], RedisKeyUtil::lockPet($petID)); }, [$userID, $petID, $type]); } /** * 升级 * @param $petID */ public static function upgrade($userID, $petID, $gold) { SafeUtil::dbOperate(function ($userID, $petID, $gold) { SafeUtil::redisLockOperate(function ($userID, $petID, $gold) { $gold = (int)$gold; if ($gold <= 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $pet = Pet::findByPetID($petID); if (empty($pet)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->end_brooding_time > time()) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->user_id != $userID) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $user = User::findById($userID); $petConfig = GameConfigServices::getParamByPath('pet.' . $pet->pet_config_id); if ($pet->level >= intval($petConfig['max_level'])) throw new StatusException(ResultStatusServices::RS_PET_MAX_LEVEL_LIMIT); $levelConfig = GameConfigServices::getParamByPath('pet_level.' . ($pet->level + 1)); if (empty($levelConfig)) throw new StatusException(ResultStatusServices::RS_PET_MAX_LEVEL_LIMIT); $rate = (int)GameConfigServices::getCommonNumByID(GameConfigServices::COMMON_GOLD_EXCHANGE_PET_EXP_RATE); if ($rate <= 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $addExp = intval($gold / $rate); $gold = intval($addExp * $rate); if ($addExp <= 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $log = SystemLogUtil::get($pet->user_id, SystemLogUtil::TYPE_GOLD, -$gold, 0, SystemLogUtil::FROM_TYPE_PET_UPGRADE, []); MoneyUtil::checkAndModifyRes($userID, false, -$gold, ItemServices::ITEM_TYPE2_GOLD, $log); $pet->exp += $addExp; if ($pet->exp >= $levelConfig['exp']) { if ($pet->level >= $user->level) throw new StatusException(ResultStatusServices::RS_PET_FARM_LEVEL_LIMIT); $pet->level++; $pet->exp = 0; $pet->blood_add += (int)$levelConfig['blood']; $pet->attack_add += (int)$levelConfig['attack']; $pet->anti_add += (int)$levelConfig['anti']; $pet->crit_add += (int)$levelConfig['crit']; $pet->dodge_add += (int)$levelConfig['dodge']; //成就 AchievementUtil::addCount($userID, AchievementUtil::ID_PET_LEVEL, $pet->level, true); AchievementUtil::addCount($userID, AchievementUtil::ID_PET_LEVEL_2, $pet->level, true); } self::updateFight($pet); self::updateFeedTime($pet); if (!$pet->save()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR); if ($pet->is_enter_war == self::ENTER_WAR) ArenaUtil::updatePet($userID, $pet); }, [$userID, $petID, $gold], RedisKeyUtil::lockPet($petID)); }, [$userID, $petID, $gold]); } /** * 喂养 * @param $petID */ public static function feed($userID, $petID, $itemID) { SafeUtil::dbOperate(function ($userID, $petID, $itemID) { SafeUtil::redisLockOperate(function ($userID, $petID, $itemID) { $pet = Pet::findByPetID($petID); if (empty($pet)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->end_brooding_time > time()) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->user_id != $userID) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $itemConfig = GameConfigServices::getParamByPath('item_list.' . $itemID); if (empty($itemConfig)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ((int)$itemConfig['type2'] != ItemServices::ITEM_TYPE2_DOG_FOOD) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $addFeed = (int)$itemConfig['effect_id']; if ($addFeed <= 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $log = SystemLogUtil::get($userID, SystemLogUtil::TYPE_ITEM, $itemID, -1, SystemLogUtil::FROM_TYPE_FEED_DOG, []); MoneyUtil::checkAndModifyNum($userID, $itemID, false, -1, $log); self::updateFeedTime($pet); $pet->feed += $addFeed; if (!$pet->save()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR); //任务记录 DailyTaskUtil::addTaskCount($userID, DailyTaskUtil::TYPE_FEED_PET, null, 1); }, [$userID, $petID, $itemID], RedisKeyUtil::lockPet($petID)); }, [$userID, $petID, $itemID]); } /** * 参战 * @param $petID */ public static function setEnterWar($userID, $petID) { SafeUtil::dbOperate(function ($userID, $petID) { SafeUtil::redisLockOperate(function ($userID, $petID) { $pet = Pet::findEnterWarPetByUserID($userID); if (!empty($pet)) { if ($pet->id == $petID) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); self::updateFeedTime($pet); $pet->is_enter_war = self::NOT_ENTER_WAR; if (!$pet->save()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR); } $pet = Pet::findByPetID($petID); if (empty($pet)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->end_brooding_time > time()) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->user_id != $userID) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->is_enter_war == self::ENTER_WAR) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); self::updateFeedTime($pet); $pet->is_enter_war = self::ENTER_WAR; if (!$pet->save()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR); if ($pet->is_enter_war == self::ENTER_WAR) ArenaUtil::updatePet($userID, $pet); }, [$userID, $petID], RedisKeyUtil::lockPet($petID)); }, [$userID, $petID]); } /** * 获取战斗信息 * @param $fromUserID * @param $beUserID * @return mixed * @throws StatusException */ public static function getBattleInfo($fromUserID, $beUserID, $checkFriend = true) { $pet = Pet::findEnterWarPetByUserID($fromUserID); if (empty($pet)) throw new StatusException(ResultStatusServices::RS_BATTLE_PET_NOT_ENTER_BATTLE); if ($checkFriend && !FriendServices::isFriend($fromUserID, $beUserID)) throw new StatusException(ResultStatusServices::RS_NOT_FRIEND); $data['from_pet'] = $pet->toArray(); $data['from_user'] = User::findById($fromUserID)->genClientData(false); $pet = Pet::findEnterWarPetByUserID($beUserID); if (empty($pet)) { $list = Pet::findAllByUserID($beUserID); if (count($list) > 0) $pet = $list[0]; } $data['be_pet'] = empty($pet) ? null : $pet->toArray(); $data['be_user'] = User::findById($beUserID)->genClientData(false); return $data; } /** * 战斗 * @param $fromUserID * @param $fromPetID * @param $beUserID * @param $battleResultType * @return mixed */ public static function battle($fromUserID, $fromPetID, $beUserID, $battleResultType) { SafeUtil::dbOperate(function ($fromUserID, $fromPetID, $beUserID, $battleResultType) { SafeUtil::redisLockOperate(function ($fromUserID, $fromPetID, $beUserID, $battleResultType) { if (!in_array($battleResultType, self::BATTLE_RESULT_LIST)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $pet = Pet::findByPetID($fromPetID); if (empty($pet)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->end_brooding_time > time()) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); if ($pet->user_id != $fromUserID) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $petConfig = GameConfigServices::getParamByPath('pet.' . $pet->pet_config_id); if (empty($petConfig)) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); $hunger = intval($petConfig['hunger']); if ($hunger < 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR); self::updateFeedTime($pet); $pet->feed -= $hunger; // if ($pet->feed < 0) throw new StatusException(ResultStatusServices::RS_PET_HUNGER); if ($pet->feed < 0) $pet->feed = 0; $battleConfig = GameConfigServices::getBattleConfig($battleResultType); $levelConfig = GameConfigServices::getParamByPath('pet_level.' . ($pet->level + 1)); // if (empty($levelConfig)) throw new StatusException(ResultStatusServices::RS_MAX_LEVEL); $exp = intval($battleConfig['experience_outcome']); // if ($exp > 0) MoneyUtil::addUserExp($fromUserID, intval($battleConfig['experience_outcome'])); if (!empty($levelConfig)) { $pet->exp += $exp; if ($pet->level >= intval($petConfig['max_level'])) { if ($pet->exp >= $levelConfig['exp']) $pet->exp = $levelConfig['exp']; } elseif ($pet->exp >= $levelConfig['exp']) { $fromUser = User::findById($fromUserID); if ($pet->level < $fromUser->level) { $pet->level++; $pet->exp = 0; $pet->blood += (int)$levelConfig['blood']; $pet->attack += (int)$levelConfig['attack']; $pet->anti += (int)$levelConfig['anti']; $pet->crit += (int)$levelConfig['crit']; $pet->dodge += (int)$levelConfig['dodge']; self::updateFight($pet); //成就 AchievementUtil::addCount($fromUserID, AchievementUtil::ID_PET_LEVEL, $pet->level, true); AchievementUtil::addCount($fromUserID, AchievementUtil::ID_PET_LEVEL_2, $pet->level, true); } else { $pet->exp = intval($levelConfig['exp']); } } } if (!$pet->save()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR); if ($battleResultType == self::BATTLE_SUCCESS) { //胜利 MoneyUtil::parseItem($battleConfig['outcome_id'], 1, true, $fromUserID, SystemLogUtil::FROM_TYPE_BATTLE_SUCCESS, ['config' => $battleConfig]); // //偷果实 // $stealNum = rand(intval($battleConfig['fruit_min']), intval($battleConfig['fruit_max'])); // if ($stealNum > 0) { // $farmDbData = Farm::findRedis($beUserID); // LandService::updateAllCropStatus($beUserID, $farmDbData->id, $farmDbData->level); // // $landDbList = Land::findAll(['farm_id' => $farmDbData->id]); // // $num = $stealNum; // foreach ($landDbList as $land) { // // $rs = LandService::steal($farmDbData->id, $land->position, $num); // if ($rs != ResultStatusServices::RS_OPERATION_SUCCESS) continue; // // if ($num > 0) $stealNum -= $num; // // //修改仓库数量 // $cropConfig = GameConfigServices::getParamByPath('crop_list.' . $land->crop_id); // $itemID = $cropConfig['item_id']; // $log = SystemLogUtil::get($fromUserID, SystemLogUtil::TYPE_ITEM, $itemID, $num, SystemLogUtil::FROM_TYPE_STEAL_GET, []); // MoneyUtil::checkAndModifyNum($fromUserID, $itemID, true, $num, $log); // array_push($stealItemList, ['item_id' => $itemID, 'num' => $num]); // // if ($stealNum == 0) break; // } // // //任务记录 // DailyTaskUtil::addTaskCount($fromUserID, DailyTaskUtil::TYPE_STEAL_SUCCESS, null, 1); // // //成就 // AchievementUtil::addCount($fromUserID, AchievementUtil::ID_STEAL, 1); // // AchievementUtil::addCount($fromUserID, AchievementUtil::ID_STEAL_SUCCESS, 1); // } } else { //失败 MoneyUtil::parseItem($battleConfig['outcome_id'], 1, false, $fromUserID, SystemLogUtil::FROM_TYPE_BATTLE_FAIL, ['config' => $battleConfig]); AchievementUtil::addCount($beUserID, AchievementUtil::ID_CATCHING_THIEF, 1); } //任务记录 DailyTaskUtil::addTaskCount($fromUserID, DailyTaskUtil::TYPE_STEAL, null, 1); }, [$fromUserID, $fromPetID, $beUserID, $battleResultType], RedisKeyUtil::lockPet($fromPetID)); }, [$fromUserID, $fromPetID, $beUserID, $battleResultType]); } /** * 更新喂养扣点 * @param Pet $pet */ public static function updateFeedTime(Pet $pet) { if ($pet->is_enter_war == self::ENTER_WAR) { $dis = time() - $pet->last_feed_update_time; $period = intval(GameConfigServices::getCommonNumByID(GameConfigServices::COMMON_FEED_EXPEND_PERIOD)); $expendPoint = intval(GameConfigServices::getCommonNumByID(GameConfigServices::COMMON_FEED_EXPEND_POINT)); if ($expendPoint <= 0) return; $point = intval($expendPoint * floatval($dis) / $period); if ($point > 0) { $pet->feed -= $point; if ($pet->feed < 0) $pet->feed = 0; $pet->last_feed_update_time = time(); } } else { $pet->last_feed_update_time = time(); } } }