%%%-------------------------------------------------------------------
%%% @doc    宠物基础逻辑
%%% Module  : lib_pet.erl
%%% Created : 2019-12-09
%%% @Author : tyl
%%%-------------------------------------------------------------------
-module(lib_pet).

-include("common.hrl").
-include("server.hrl").
-include("pet.hrl").
-include("figure.hrl").
-include("errcode.hrl").
-include("def_module.hrl").
-include("predefine.hrl").
-include("def_goods.hrl").
-include("def_fun.hrl").
-include("goods.hrl").

-export([
	make_list/3
	,refresh_attr/2            %% 刷新属性
	,refresh_power/1           %% 刷新战力
	,offline_refresh_attr/2    %% 离线登陆计算属性

	,send_msg/3                %% 发送消息
	,send_error/2              %% 发送错误消息

	,get_pets_info/1                       %% 获取宠物栏信息
	,adopt_pet/2                           %% 领养(激活)宠物
	,upgrade_pet/2                         %% 宠物进化
	,feed_pet/4                            %% 喂养宠物(升级)
	,get_pet_skill_and_skill_diamonds/2    %% 获取宠物技能和技能宝石
	,inlay_skill_diamond/5                 %% 技能宝石镶嵌/替换
	,compound_stone/3                      %% 宝石合成

	,vote_pet_info/1                       %% 查询今日投票信息
	,vote_for_pet/2                        %% 宠物全服投票
	,receive_vote_rank_reward/2            %% 领取昨日投票榜奖励

	,awaken_pet/2                          %% 宠物觉醒

	,get_normal_support_info/1             %% 查询助战数据
	,support_pet_normal/3                  %% 宠物助战
	,check_if_open_support_slot/2          %% 检测是否达到宠物助战槽开启条件
	,trans_to_support_list/2               %% 玩家宠物助战信息格式转换

	,calc_next_star/2                 %% 计算进化下一星级
	,calc_pet_sum_star/2              %% 计算宠物总星级

	,calc_pets_attr_add_ratio/2       %% 所有宠物助战属性加成
	,calc_all_pet_attr/1              %% 计算宠物总属性
	,calc_pet_power/1                 %% 计算宠物战力
	,calc_all_pet_extra_power/1       %% 计算宠物总额外战力

    ,get_pet_power/1				%% 获得宠物总战力
	,trans_to_pet_list/2            %% 玩家宠物数据格式转换
	,get_all_pet_skill_list/3       %% 根据天赋类型获取所有宠物技能列表
%%	,get_pet_skill_list/4      %% 根据天赋类型获取单只宠物技能列表
%%	,get_pet_skill_diamonds/2  %% 获取单只宠物的技能石
]).


%% API
make_list(pet, PetInfoList, RoleId) ->
	F = fun([PetId, PetStar, PetLv, PetExp, AdoptTime, IsAwaken, OldPower], TPetList) ->
		DiamondsList = get_pet_skill_diamonds_from_db(RoleId, PetId),
		{PetLifeSkills, PetAttrSkills, PetBattleSkills} =
			get_pet_skill_list(PetId, PetStar),
		Pet = #pet_info{
			pet_id            = PetId,
			pet_star          = PetStar,
			pet_lv            = PetLv,
			pet_exp           = PetExp,
			pet_life_skills   = PetLifeSkills,
			pet_attr_skills   = PetAttrSkills,
			pet_battle_skills = PetBattleSkills,
			diamond_slots     = DiamondsList,
			adopt_time        = AdoptTime,
			is_awaken         = IsAwaken,
			old_power         = OldPower
		},
		NewPet = calc_pet_sum_attr(Pet),
		%% 检查是否觉醒切换技能
		NewPet1 = check_if_change_skill(NewPet),
		[NewPet1|TPetList]
	end,
	lists:foldl(F, [], PetInfoList).

%% 获取宠物基础信息
get_pets_info(Player) ->
	#player_status{status_pet = StatusPet} = Player,
	case StatusPet of
		#status_pet{
			pets        = TPetInfoList,
			power       = Power,
			extra_power = ExtraPower
		} when length(TPetInfoList) > 0 ->
			#status_pet{
				follow_pet = FollowPetId,
				pets       = PetInfoList
			} = StatusPet,
			PetList = pack_pets_info(PetInfoList, []),
			{FollowPetId, PetList, Power+ExtraPower};
		_ ->
			FollowPetId = 0, PetList = [], AllPetPower = 0,
			{FollowPetId, PetList, AllPetPower}
	end.

%% 宠物领养(激活)
adopt_pet(#player_status{figure = Figure, id = RoleId} = Player, PetId) ->
	InitStar = 1,
	case data_pet:get_pet_cfg(PetId, InitStar) of
		#pet_cfg{cost = [{Type, GoodsId, Num}], pet_name = PetName,
			pet_race = PetRace, color = ColorId, rare_degree = RareDegree
		} ->
			CheckList = [
				{has_actived, PetId}, {enough_debris, GoodsId, Num}
			],
			case lib_pet_check:check_active(CheckList, Player) of
				{true, NewPlayer} ->
					%% 扣除材料
					CostList = [{Type, GoodsId, Num}],
					case lib_goods_api:cost_object_list_with_check(NewPlayer, CostList, pet_active_cost, "pet active") of
						{true, NewPlayer1, _} ->
							{NewPlayer2, PetPower} = do_adopt_pet(NewPlayer1, PetId),
							%% 日志
							lib_log_api:log_pet_grow(RoleId, PetId, 0, 0, 0, 1, 1, 1, 0, CostList),
							send_msg(NewPlayer2, 16303, [1, PetId, InitStar, PetPower]),
							lib_chat:send_TV({all}, ?MOD_PET, 1, [Figure#figure.name, RoleId, trans_tv_string(PetRace, PetName)]),
							ta_agent_fire:pet_star_up(NewPlayer2, [PetId, RareDegree, ColorId, PetRace, 0, 1, GoodsId, Num]),
							NewPlayer2;
						{false, ErrCode, _NewPlayer} -> send_error(Player, ErrCode), Player
					end;
				{false, Res} -> send_error(Player, Res), Player
			end;
		_ -> send_error(Player, ?ERRCODE(err163_not_pet)), Player
	end.

%% 宠物进化
upgrade_pet(#player_status{status_pet = StatusPet, figure = Figure, id = RoleId, scene = Scene,
	scene_pool_id = PoolId, copy_id = CopyId, x = X, y = Y} = Player, PetId) ->
	#status_pet{pets = PetInfoList, follow_pet = FollowPet} = StatusPet,
	case lists:keyfind(PetId, #pet_info.pet_id, PetInfoList) of
		#pet_info{pet_star = PetStar, pet_lv = PetLv, pet_exp = PetExp} ->
			CheckList = [
				{is_max_star, PetId, PetStar},
				{enough_debris, PetId, PetStar}
			],
			case lib_pet_check:check_upgrade(CheckList) of
				true ->
					NewPetStar = calc_next_star(PetId, PetStar),
					#pet_cfg{cost = CostList, pet_name = PetName, pet_race = PetRace, rare_degree = RareDegree, color = ColorId} =
						data_pet:get_pet_cfg(PetId, NewPetStar),
					case lib_goods_api:cost_object_list_with_check(Player, CostList, pet_updrade_cost, "pet upgrade") of
						{true, NewPlayer1, _} ->
							{NewPlayer2, PetPower} = do_upgrade_pet(NewPlayer1, PetId, NewPetStar),
							send_msg(NewPlayer2, 16303, [2, PetId, NewPetStar, PetPower]),
							lib_log_api:log_pet_grow(RoleId, PetId, PetStar, PetLv, PetExp, 3, PetStar+1, PetLv, PetExp, CostList),
							case PetId == FollowPet of
								true ->
									NewPlayer3 = update_player_figure(NewPlayer2, [PetId, NewPetStar]),
									mod_scene_agent:update(NewPlayer3, [{follow_pet, [PetId, NewPetStar]}]),
									%% 场景广播
									{ok, Bin1} = pt_163:write(16306, [RoleId, PetId, NewPetStar, 1]),
									lib_server_send:send_to_area_scene(Scene, PoolId, CopyId, X, Y, Bin1);
								_ ->
									NewPlayer3 = NewPlayer2
							end,
							lib_chat:send_TV({all}, ?MOD_PET, 2,
								[Figure#figure.name, RoleId, trans_tv_string(PetRace, PetName), tran_tv_string1(NewPetStar)]
							),
							custom_act_mobilize:update_mobilize_task(NewPlayer3, petstar, 1, false),
							case CostList of
								[{_, GoodsId, Num}|_] -> ok;
								_ -> GoodsId = 0, Num = 0
							end,
							ta_agent_fire:pet_star_up(NewPlayer3, [PetId, RareDegree, ColorId, PetRace, PetStar, NewPetStar, GoodsId, Num]),
							NewPlayer3;
						{false, ErrCode, _NewPlayer} -> send_error(Player, ErrCode), Player
					end;
				{false, Res} -> send_error(Player, Res), Player
			end;
		_ -> send_error(Player, ?ERRCODE(err163_pet_not_adopt)), Player
	end.

%% 宠物喂养
feed_pet(#player_status{id = RoleId, status_pet = StatusPet} = Player, PetId, GoodsId, GoodNum) ->
	#status_pet{pets = PetsInfo} = StatusPet,
	case lists:keyfind(PetId, #pet_info.pet_id, PetsInfo) of
		#pet_info{
			pet_lv  = PetLv, pet_exp = PetExp, pet_star = PetStar
		} = Pet ->
			#pet_cfg{rare_degree = RareDegree, pet_race = Race} = data_pet:get_pet_cfg(PetId, 1),
			case data_pet:get_pet_race_material_cfg(Race) of
				#pet_race_material_cfg{cost_material = GoodsList}  -> ok;
				_ -> GoodsList = []
			end,
			CheckList = [
				{max_lv, RareDegree, PetLv},
				{goods_enough, GoodsId, GoodsList}
			],
			case lib_pet_check:check_grow_up(CheckList) of
				true ->
					[{_, OwnNum}] = lib_goods_api:get_goods_num(Player, [GoodsId]),
					CostNum  = ?IF(OwnNum >= GoodNum, GoodNum, OwnNum),
					CostList = [{?TYPE_GOODS, GoodsId, CostNum}],
					case lib_goods_api:cost_object_list_with_check(Player, CostList, pet_grow_up_cost, "pet grow up") of
						{true, NewPlayer, _} ->
							{_GoodsId, AddExp} = lists:keyfind(GoodsId, 1, GoodsList),
							{FeedPlayer, NewPetLv, NewPetExp, PetPower} = do_feed_pet(NewPlayer, Pet, AddExp*CostNum),
							lib_log_api:log_pet_grow(RoleId, PetId, PetStar, PetLv, PetExp, 2, PetStar, NewPetLv, NewPetExp, CostList),
							send_msg(FeedPlayer, 16302, [PetId, NewPetLv, NewPetExp, PetPower]),
							lib_task_api:pet_lv(FeedPlayer),
							{ok, FeedPlayer2} = lib_seven_days_goal:do_finish_task(FeedPlayer, ?MOD_PET, 0, NewPetLv, true),
							custom_act_mobilize:update_mobilize_task(FeedPlayer2, petup, NewPetLv - PetLv, false),
							FeedPlayer2;
						{false, ErrCode, _NewPlayer} -> send_error(Player, ErrCode), Player
					end;
				{false, Res} -> send_error(Player, Res), Player
			end;
		_ -> send_error(Player, ?ERRCODE(err163_pet_not_adopt)), Player
	end.

%% 获取技能和技能宝石栏数据
get_pet_skill_and_skill_diamonds(#player_status{status_pet = StatusPet} = Player, PetId) ->
	#status_pet{pets = PetsInfo} = StatusPet,
	case lists:keyfind(PetId, #pet_info.pet_id, PetsInfo) of
		#pet_info{
			pet_life_skills   = PetLifeSkills,
			pet_attr_skills   = PetAttrSkills,
			pet_battle_skills = PetBattleSkills,
			diamond_slots     = DiamondSlots} ->
			F = fun(SlotId, TList) ->
				#pet_skill_cfg{
					skill_talent_id   = SkillId,
					skill_talent_type = SkillType} =
				data_pet:get_pet_skill_cfg(PetId, SlotId),
				case lists:member(SkillId, PetLifeSkills++PetAttrSkills++PetBattleSkills) of
					true -> [{SlotId, SkillType, SkillId}|TList];
					_ -> TList
				end
			end,
			SkillInfoList = lists:foldl(F, [], ?SKILL_SLOT_LIST),
			PackInfo = [PetId, SkillInfoList, DiamondSlots],
			send_msg(Player, 16304, PackInfo);
		_ -> send_error(Player, ?ERRCODE(err163_pet_not_adopt))
	end.

%% 技能石镶嵌/替换
inlay_skill_diamond(#player_status{status_pet = StatusPet, id = RoleId} = Player, PetId, DiamondSlot, DiamondId, _GoodsId) ->
	#status_pet{pets = PetsInfo} = StatusPet,
	case lists:keyfind(PetId, #pet_info.pet_id, PetsInfo) of
		#pet_info{diamond_slots = DiamondSlots} = PetInfo ->
			CheckList = [{has_diamond, DiamondId}, {diamond_slot, DiamondSlot}
						,{is_same_diamond, DiamondId, DiamondSlots}
						,{is_need_race, DiamondId, PetId}
			],
			case lib_pet_check:check_diamond_inlay(CheckList) of
				true ->
					case lists:keyfind(DiamondSlot, 1, DiamondSlots) of
						{_DiamondSlot, OldDiamondId} -> %% 槽位上已有宝石
							case OldDiamondId == DiamondId of
								true -> %% 卸下
									Player;
								_ -> %% 替换
									case check_can_replace(DiamondSlots, DiamondId, DiamondSlot) of
										true ->
											case do_replace_skill_diamond(Player, PetInfo, DiamondSlot, OldDiamondId, DiamondId) of
												{ok, NewPlayer, PetPower} ->
													lib_log_api:log_pet_jewel(RoleId, PetId, DiamondSlot, OldDiamondId, DiamondId),
													send_msg(NewPlayer, 16305, [PetId, DiamondSlot, DiamondId, _GoodsId, PetPower]), NewPlayer;
												{false, Res, Player} -> send_error(Player, Res), Player
											end;
										{false, Err} ->
											send_error(Player, Err), Player
									end
							end;
						_ -> %% 第一次镶嵌
							case check_can_inlay(DiamondSlots, DiamondId) of
								true ->
									case do_inlay_skill_diamond(Player, PetInfo, {DiamondSlot, DiamondId}) of
										{ok, NewPlayer, PetPower} ->
											lib_log_api:log_pet_jewel(RoleId, PetId, DiamondSlot, 0, DiamondId),
											send_msg(NewPlayer, 16305, [PetId, DiamondSlot, DiamondId, _GoodsId, PetPower]), NewPlayer;
										{false, Res, Player} -> send_error(Player, Res), Player
									end;
								{false, Err} ->
									send_error(Player, Err), Player
							end
					end;
				{false, Res} -> send_error(Player, Res), Player
			end;
		_ -> send_error(Player, ?ERRCODE(err163_pet_not_adopt)), Player
	end.

check_can_inlay(DiamondSlots, DiamondId) ->
	#pet_diamond_storage_cfg{diamond_type = Type} = data_pet:get_pet_diamond_storage_cfg(DiamondId),
	case not_same_type(Type, DiamondSlots) of
		true -> true;
		_ -> {false, ?ERRCODE(err163_same_diamond_type)}
	end.

check_can_replace(DiamondSlots, DiamondId, SlotId) ->
	#pet_diamond_storage_cfg{diamond_type = Type} = data_pet:get_pet_diamond_storage_cfg(DiamondId),
	{_, ODiamondId} = lists:keyfind(SlotId, 1, DiamondSlots),
	case data_pet:get_pet_diamond_storage_cfg(ODiamondId) of
		#pet_diamond_storage_cfg{diamond_type = TType} when TType == Type ->
			true;
		_ ->
			case not_same_type(Type, DiamondSlots) of
				true -> true;
				_ -> {false, ?ERRCODE(err163_same_diamond_type)}
			end
	end.

%% 判断是否同类型宝石
not_same_type(Type, DiamondSlots) ->
	F = fun({_SlotId, TDiamondId}) ->
		case data_pet:get_pet_diamond_storage_cfg(TDiamondId) of
			#pet_diamond_storage_cfg{diamond_type = TType} when TType == Type ->
				false;
			_ ->
				true
		end end,
	case lists:all(F, DiamondSlots) of
		true -> true;
		_ -> {false, ?ERRCODE(err163_same_diamond_type)}
	end.

%% ----------------------------------------------------------
%% @doc 宝石合成 @end
%% ----------------------------------------------------------
compound_stone(Player, Type, DiamondId) ->
	CompoundList = case data_pet:get_stone_compound(DiamondId) of
		               #pet_stone_compound_cfg{compound_list = TCompoundList} ->
			               TCompoundList;
		               _ ->
			               []
	               end,
	NewPlayer =
	case CompoundList of
		[{_, _}|_] ->
			CompoundIds = [TId||{TId, _} <- CompoundList],
			HasDiamonds = lib_goods_api:get_goods_num(Player, CompoundIds),
			case Type of
				1 -> compound_one(Player, DiamondId, CompoundList, HasDiamonds);
				2 -> compound_more(Player, DiamondId, CompoundList, HasDiamonds)
			end;
		_ ->
			send_error(Player, ?ERRCODE(err163_compound_cfg_err)),
			Player
	end,
	{ok, NewPlayer}.

compound_one(Player, DiamondId, CompoundList, HasDiamonds) ->
	CheckHas = check_has_diamond(HasDiamonds),
	CheckEnough = check_enough(HasDiamonds, CompoundList),
	if
		not CheckHas ->
			send_error(Player, ?ERRCODE(err163_compound_diamond_not_enough)),
			Player;
		not CheckEnough ->
			send_error(Player, ?ERRCODE(err163_compound_diamond_not_enough)),
			Player;
		true ->
			Cost = [{?TYPE_GOODS, GoodTypeId, Num}||{GoodTypeId, Num}<-CompoundList],
			case lib_goods_api:cost_object_list(Player, Cost, compound_diamond, "") of
				{true, Player1} ->
					Produce = #produce{type = compound_diamond, reward = [{?TYPE_GOODS, DiamondId, 1}]},
					{ok, NewPlayer} = lib_goods_api:send_reward_with_mail(Player1, Produce, ?MOD_PET),
					send_msg(Player, 16318, [?SUCCESS, 1, DiamondId]),
					NewPlayer;
				{false, Err, _} ->
					send_error(Player, Err),
					Player
			end
	end.

%% 代码兼容配方里面宝石类型不同情况
compound_more(Player, DiamondId, CompoundList, HasDiamonds) ->
	CalcF = fun({TDiamondId, HasNum}, TList) ->
		case lists:keyfind(TDiamondId, 1, CompoundList) of
			{_, NeedNum} when NeedNum > 0, HasNum > 0 ->
				[{TDiamondId, HasNum div NeedNum}|TList];
			_ ->
				[{TDiamondId, 0}|TList]
		end end,
	[{_, CanCompoundNum}|_] = CanCompoundList = lists:keysort(2, lists:foldl(CalcF, [], HasDiamonds)),
	CanCompoundList1 = [{D, N}||{D, N}<-CanCompoundList, N=/=0],
	LenCompound = erlang:length(CanCompoundList1), LenHas = erlang:length(HasDiamonds),
	case CanCompoundNum > 0 of
		true when LenCompound == LenHas ->
			Cost = [{?TYPE_GOODS, GoodTypeId, Num*CanCompoundNum}||{GoodTypeId, Num}<-CompoundList],
			case lib_goods_api:cost_object_list(Player, Cost, compound_diamond, "") of
				{true, Player1} ->
					Produce = #produce{type = compound_diamond, reward = [{?TYPE_GOODS, DiamondId, CanCompoundNum}]},
					{ok, NewPlayer} = lib_goods_api:send_reward_with_mail(Player1, Produce, ?MOD_PET),
					send_msg(Player, 16318, [?SUCCESS, 1, DiamondId]),
					NewPlayer;
				{false, Err, _} ->
					send_error(Player, Err),
					Player
			end;
		_ ->
			send_error(Player, ?ERRCODE(err163_compound_diamond_not_enough)),
			Player
	end.

check_has_diamond([]) -> false;
check_has_diamond(HasDiamonds) ->
	F = fun({_, Num}) ->
		Num > 0
	end,
	lists:all(F, HasDiamonds).

check_enough(HasDiamonds, CompoundList) ->
	F = fun({DiamondId, NeedNum}, Ret) ->
		case lists:keyfind(DiamondId, 1, HasDiamonds) of
			{_, HasNum} when HasNum >= NeedNum -> Ret;
			_ -> false
		end end,
	lists:foldl(F, true, CompoundList).

%% ----------------------------------------------------------
%% @doc 查询今日投票信息 @end
%% ----------------------------------------------------------
vote_pet_info(#player_status{id = RoleId, status_pet = StatusPet} = _Player) ->
	#status_pet{support_times = SupportTimes, vote_list = VoteList} = StatusPet,
	mod_pet_support_mgr:vote_pet_info(RoleId, VoteList, SupportTimes),
	ok.

%% ----------------------------------------------------------
%% @doc 宠物全服投票 @end
%% ----------------------------------------------------------
vote_for_pet(Player, PetId) ->
	#player_status{id = RoleId, status_pet = StatusPet} = Player,
	#status_pet{support_times = SupportTimes, vote_list = VoteList, receive_pet_list = ReceiveList} = StatusPet,
	AllCfgPet = data_pet:get_all_pets_cfg(),
	CheckPet = lists:member(PetId, AllCfgPet),
	HasVote  = lists:member(PetId, VoteList),
	CheckVoteCount = SupportTimes >= ?DAY_VOTE_PET_COUNT,
	if
		%% 是否有宠物
		not CheckPet ->
			Player;
		%% 点赞次数是否足够
		CheckVoteCount ->
			send_error(Player, ?ERRCODE(err163_vote_times_not_enough)),
			Player;
		%% 是否点赞过
		HasVote ->
			send_error(Player, ?ERRCODE(err163_has_vote)),
			Player;
		true ->
			%% 玩家进程先增加次数，管理进程判断奖励发放
			case lib_pet_support_mod:check_enter_center() of
				{_, ZoneId} when is_integer(ZoneId) ->
					Node = clusters_node:get_node(),
					clusters_node:apply_cast(
						mod_pet_support_center, center_vote_for_pet,
						[ZoneId, Node, RoleId, PetId]
					);
				_ ->
					mod_pet_support_mgr:server_vote_for_pet(RoleId, PetId)
			end,
			NewVoteList = [PetId|VoteList],
			NewSupportTimes = SupportTimes + 1,
			lib_pet_data:save_db_pet_vote_info(RoleId, NewSupportTimes, NewVoteList, ReceiveList),
			send_msg(Player, 16314, [NewVoteList, NewSupportTimes]),
			NewStatusPet = StatusPet#status_pet{vote_list = NewVoteList, support_times = NewSupportTimes},
			NewPlayer = Player#player_status{status_pet = NewStatusPet},
			NewPlayer
	end.

%% ----------------------------------------------------------
%% @doc 领取昨日投票榜奖励 @end
%% ----------------------------------------------------------
receive_vote_rank_reward(#player_status{id = RoleId, status_pet = StatusPet}, PetId) ->
	#status_pet{receive_pet_list = ReceiveList} = StatusPet,
	case lists:member(PetId, ReceiveList) of
		true -> ignore;
		_ ->
			case lib_pet_support_mod:check_enter_center() of
				{_, ZoneId} when is_integer(ZoneId) ->
					Node = clusters_node:get_node(),
					clusters_node:apply_cast(
						mod_pet_support_center, center_receive_rank_reward,
						[ZoneId, Node, RoleId, PetId]
					);
				_ ->
					mod_pet_support_mgr:receive_rank_reward(RoleId, PetId)
			end
	end,
	ok.

%% -------------------------------------------------------------------------
%% @doc 查询助战槽位信息 @end
%% -------------------------------------------------------------------------
get_normal_support_info(Player) ->
	#player_status{status_pet = StatusPet} = Player,
	#status_pet{support_list = SupportList} = StatusPet,
	case SupportList of
		[#pet_support_slot{}|_] ->
			PackList = pack_pet_support_info(SupportList, []),
			PackList;
		_ -> []
	end.

pack_pet_support_info([], PackList) -> PackList;
pack_pet_support_info([PetSupportSlot|L], TPackList) ->
	#pet_support_slot{
		slot_id      = SlotId,
		pet_id       = PetId
	} = PetSupportSlot,
	pack_pet_support_info(L, [{SlotId, PetId}|TPackList]).

%% 检测是否达到宠物助战槽开启条件
check_if_open_support_slot(Player, SumStar) ->
	#player_status{status_pet = StatusPet} = Player,
	#status_pet{open_support_slots = OpenedSlots} = StatusPet,
	SlotList = data_pet:get_all_support_slot_cfg(),
	case OpenedSlots of
		0 ->
			OpenedSlots1 = [],
			NotOpenedSlots = SlotList;
		_ ->
			OpenedSlots1 = OpenedSlots,
			NotOpenedSlots = SlotList--OpenedSlots
	end,
	F = fun(SlotId, TSlots) ->
		case data_pet:get_pet_support_slot_cfg(SlotId) of
			#pet_support_slot_cfg{open_sum_star = OpenSumStar} ->
				if
					SumStar >= OpenSumStar -> [SlotId|TSlots];
					true -> TSlots
				end;
			_ -> TSlots
		end end,
	NewOpenSlots = lists:foldl(F, [], NotOpenedSlots),
	NewStatusPet = StatusPet#status_pet{open_support_slots = NewOpenSlots++OpenedSlots1},
	lib_pet_data:save_dict_status_pet(Player, NewStatusPet).

%% ----------------------------------------------------------
%% @doc 宠物助战 @end
%% ----------------------------------------------------------
support_pet_normal(Player, SlotId, PetId) ->
	#player_status{id = RoleId, status_pet = StatusPet,scene = SceneId,
		scene_pool_id = PoolId, copy_id = CopyId, x = X, y = Y
	} = Player,
	#status_pet{
		pets               = PetInfoList,
		support_list       = SupportList,
		open_support_slots = OpenSlots,
		battle_skills      = OldBattleSkills
	} = StatusPet,
	CheckList = [{has_adopt_pet, PetInfoList, PetId}
		,{is_slot_open, OpenSlots, SlotId},
		{is_same_slot, SupportList, SlotId, PetId}
	],
	case lib_pet_check:check_normal_support_pet(CheckList) of
		true ->
			case do_support_pet_normal(Player, SupportList, SlotId, PetId) of
				{true, NewSupportList, OldPetId, PetOldSlot} ->
					%% 重新计算属性加成(也可以不计算，refresh_attr会重新计算)
					case lists:keyfind(OldPetId, #pet_support_slot.pet_id, NewSupportList) of
						#pet_support_slot{slot_id = OldPetSlotId} -> ok;
						_ -> OldPetSlotId = 0
					end,
					%% PetId - 宠物Id  SlotId - 宠物需要上阵的槽位，
					%% OldPetId - 槽位上原有的宠物Id  OldPetSlotId - 宠物原来所在槽位(即替换前槽位)
					NewPetInfoList = recalc_pet_attr(PetInfoList, PetId, SlotId, OldPetId, OldPetSlotId),
					BattleSkillList = calc_battle_skill(NewPetInfoList, NewSupportList),
					NewStatusPet = StatusPet#status_pet{pets = NewPetInfoList, support_list = NewSupportList, battle_skills = BattleSkillList},
					NewPlayer = lib_pet_data:save_dict_status_pet(Player, NewStatusPet),
					RefreshPlayer = refresh_attr(NewPlayer, support_pet_normal),
					OldBattleSkills1 = [{OldBattleSkill, 1}||OldBattleSkill<-OldBattleSkills],
					BattleSkillList1 = [{NewBattleSkill, 1}||NewBattleSkill<-BattleSkillList],
					%% 推送主战位(跟随)信息给场景中其他玩家
					case SlotId == 1 of
						%% 1> 替换主战位宠物
						true ->
							#pet_info{pet_star = PetStar} = lists:keyfind(PetId, #pet_info.pet_id, PetInfoList),
							RefreshPlayer1 = update_player_figure(
								RefreshPlayer#player_status{status_pet = NewStatusPet#status_pet{follow_pet = PetId}},
								[PetId, PetStar]
							),
							mod_scene_agent:update(RefreshPlayer1, [{follow_pet, [PetId, PetStar]}]),
							mod_scene_agent:update(RefreshPlayer1,
								[{delete_passive_skill, OldBattleSkills1}, {passive_skill, BattleSkillList1}]
							),
							%% 场景广播
							{ok, Bin1} = pt_163:write(16306, [RoleId, PetId, PetStar, 1]),
							lib_server_send:send_to_area_scene(SceneId, PoolId, CopyId, X, Y, Bin1);
						%% 2> 主战位宠物被替换下来
						_ when PetOldSlot == 1 ->
							case lists:keyfind(OldPetId, #pet_info.pet_id, PetInfoList) of
								#pet_info{pet_star = PetStar} -> ok;
								_ -> PetStar = 0
							end,
							RefreshPlayer1 = update_player_figure(
								RefreshPlayer#player_status{status_pet = NewStatusPet#status_pet{follow_pet = OldPetId}},
								[OldPetId, PetStar]
							),
							mod_scene_agent:update(RefreshPlayer1, [{follow_pet, [OldPetId, PetStar]}]),
							mod_scene_agent:update(RefreshPlayer1,
								[{delete_passive_skill, OldBattleSkills1}, {passive_skill, BattleSkillList1}]
							),
							%% 场景广播
							{ok, Bin1} = pt_163:write(16306, [RoleId, OldPetId, PetStar, 1]),
							lib_server_send:send_to_area_scene(SceneId, PoolId, CopyId, X, Y, Bin1);
						%% 3> 非主战位的相互替换
						_ ->
							RefreshPlayer1 = RefreshPlayer
					end,
					%% 检查主战位宠物是否撤离
					% CheckPlayer = check_top_support(NewSupportList, RefreshPlayer1),
					%% 更新场景数据
					update_scene_after_support(RefreshPlayer1, PetInfoList, NewSupportList),
					send_msg(RefreshPlayer1, 16308, [PetId, SlotId, OldPetId, PetOldSlot]),
					RefreshPlayer1;
				_ ->
					send_error(Player, ?FAIL), Player
			end;
		{false, Res} -> send_error(Player, Res), Player
	end.

update_scene_after_support(CheckPlayer, PetInfoList, NewSupportList) ->
	InfoFun = fun(#pet_support_slot{pet_id = TPetId, slot_id = TSlotId}, TList) when TPetId > 0 ->
		case lists:keyfind(TPetId, #pet_info.pet_id, PetInfoList) of
			#pet_info{pet_star = TPetStar, is_awaken = IsAwaken} ->
				case TSlotId == 1 of
					true -> [{TPetId, TPetStar, IsAwaken, 1}|TList];
					_ -> [{TPetId, TPetStar, IsAwaken, 0}|TList]
				end;
			_ -> TList
		end;
		(_, TList) -> TList
	          end,
	PetList = lists:foldl(InfoFun, [], NewSupportList),
	mod_scene_agent:update(CheckPlayer, [{support_pet_list, PetList}]),
	mod_scene_agent:update(CheckPlayer, [{battle_attr, CheckPlayer#player_status.battle_attr}]).

do_support_pet_normal(Player, SupportList, SlotId, PetId) ->
	#player_status{id = RoleId} = Player,
	{OldPetId, _OldPetSupport} =
	case lists:keyfind(SlotId, #pet_support_slot.slot_id, SupportList) of
		#pet_support_slot{pet_id = TOldPetId} = TOldPetSupport ->
			{TOldPetId, TOldPetSupport};
		_ -> {0, []}
	end,
	{PetOldSlotId, _PetSupport} =
	case lists:keyfind(PetId, #pet_support_slot.pet_id, SupportList) of
		#pet_support_slot{slot_id = TPetOldSlotId} = TPetSupport ->
			{TPetOldSlotId, TPetSupport};
		_ -> {0, []}
	end,
	%% 先删除,再写入
	SupportList1 = lists:keydelete(SlotId, #pet_support_slot.slot_id, SupportList),
	SupportList2 = lists:keydelete(PetOldSlotId, #pet_support_slot.slot_id, SupportList1),
	NewSlotSupport = #pet_support_slot{slot_id = SlotId, pet_id = PetId},
	case OldPetId =/= 0 andalso PetOldSlotId =/= 0 of
		true ->
			OldSlotSupport = #pet_support_slot{slot_id = PetOldSlotId, pet_id = OldPetId},
			NewSupportList  = lists:keystore(PetOldSlotId, #pet_support_slot.slot_id, SupportList2, OldSlotSupport),
			NewSupportList1 = lists:keystore(SlotId, #pet_support_slot.slot_id, NewSupportList, NewSlotSupport);
		_ ->
			NewSupportList1 = lists:keystore(SlotId, #pet_support_slot.slot_id, SupportList2, NewSlotSupport)
	end,
	{IsChangeTrue, FSupportList} =
	case batch_save_support_pet(RoleId, NewSupportList1) of
		ok -> {true, NewSupportList1};
		_  -> {false, SupportList}
	end,
	{IsChangeTrue, FSupportList, OldPetId, PetOldSlotId}.

batch_save_support_pet(RoleId, SupportList) ->
	NowTime = utime:unixtime(),
	F = fun(#pet_support_slot{slot_id = SlotId, pet_id = PetId}, {TSqlList, TSlotList}) ->
		case SlotId == 0 orelse PetId == 0 of
			true -> {TSqlList, TSlotList};
			_ ->
				case lists:member(SlotId, TSlotList) of
					true -> {TSqlList, TSlotList};
					_ ->
						Sql = io_lib:format(?SQL_BATCH_SAVE_PET_SUPPORT_SLOT_VALUE, [RoleId, SlotId, PetId, NowTime]),
						{[Sql|TSqlList], [SlotId|TSlotList]}
				end
		end end,
	{SqlList, _} = lists:foldl(F, {[], []}, SupportList),
	if
		SqlList =/= [] ->
			NewValues = util:join_bitstring(SqlList, <<", ">>),
			FinalSql = io_lib:format(?SQL_BATCH_SAVE_PET_SUPPORT_SLOT, [NewValues]),
			DbFun = fun() ->
				db:execute(<<"delete from pet_support_info where `role_id` = ~p">>,[RoleId]),
				db:execute(FinalSql),
				ok
			end,
			case catch db:transaction(DbFun) of
				ok -> ok;
				_ -> skip
			end;
		true ->
			skip
	end.

calc_battle_skill(PetInfoList, SupportList) ->
	SupportPets = [PetId||#pet_support_slot{slot_id = SlotId, pet_id = PetId}<-SupportList,
					SlotId =< ?PET_BATTLE_SKILL_SLOT],
	F = fun(#pet_info{pet_id = TPetId, pet_battle_skills = BattleSkills}, TList) ->
			case lists:member(TPetId, SupportPets) of
				true -> BattleSkills ++ TList;
				_ -> TList
			end end,
	CalcBattleSkills = lists:foldl(F, [], PetInfoList),
	CalcBattleSkills.

recalc_pet_attr(PetInfoList, PetId, SlotId, OldPetId, OldPetSlotId) ->
	PetAddRatio = case data_pet:get_pet_support_slot_cfg(SlotId) of
		              #pet_support_slot_cfg{attr_add_ratio = TAddRatio} -> TAddRatio;
		              _ -> 0
	              end,
	OldPetAddRatio = case data_pet:get_pet_support_slot_cfg(OldPetSlotId) of
		                 #pet_support_slot_cfg{attr_add_ratio = TAddRatio1} -> TAddRatio1;
		                 _ -> 0
	                 end,
	PetInfoList1 = case lists:keyfind(PetId, #pet_info.pet_id, PetInfoList) of
		               #pet_info{} = PetInfo ->
			               PetInfo1 = calc_pet_sum_attr(PetInfo),
			               NewPetAttr = calc_attr_add_ratio(PetInfo1#pet_info.pet_attr, PetAddRatio),
			               NewPetInfo = PetInfo1#pet_info{pet_attr = NewPetAttr, pet_power = calc_pet_power(NewPetAttr)},
			               lists:keystore(PetId, #pet_info.pet_id, PetInfoList, NewPetInfo);
		               _ ->
			               PetInfoList
	               end,
	PetInfoList2 = case lists:keyfind(OldPetId, #pet_info.pet_id, PetInfoList1) of
		               #pet_info{} = OldPetInfo ->
			               OldPetInfo1 = calc_pet_sum_attr(OldPetInfo),
			               NewPetAttr1 = calc_attr_add_ratio(OldPetInfo1#pet_info.pet_attr, OldPetAddRatio),
			               NewPetInfo1 = OldPetInfo1#pet_info{pet_attr = NewPetAttr1, pet_power = calc_pet_power(NewPetAttr1)},
			               lists:keystore(OldPetId, #pet_info.pet_id, PetInfoList1, NewPetInfo1);
		               _ ->
			               PetInfoList1
	               end,
	PetInfoList2.

%%check_top_support(SupportList, Player) ->
%%	#player_status{id = RoleId, status_pet = StatusPet, scene = SceneId,
%%		scene_pool_id = PoolId,copy_id = CopyId, x = X, y = Y
%%	} = Player,
%%	case lists:keyfind(1, #pet_support_slot.slot_id, SupportList) of
%%		#pet_support_slot{pet_id = PetId} when PetId > 0 ->
%%			Player;
%%		_ ->
%%			NewPlayer = update_player_figure(
%%				Player#player_status{status_pet = StatusPet#status_pet{follow_pet = 0}},
%%				[0, 0]
%%			),
%%			mod_scene_agent:update(NewPlayer, [{follow_pet, [0, 0]}]),
%%			%% 场景广播
%%			{ok, Bin1} = pt_163:write(16306, [RoleId, 0, 0, 0]),
%%			lib_server_send:send_to_area_scene(SceneId, PoolId, CopyId, X, Y, Bin1),
%%			NewPlayer
%%	end.

trans_to_support_list([], TransList) -> TransList;
trans_to_support_list([SupportInfo|L], TmpTransList) ->
	[SlotId, PetId] = SupportInfo,
	SupportSlot = #pet_support_slot{
		slot_id      = SlotId,
		pet_id       = PetId
	},
	trans_to_support_list(L, [SupportSlot|TmpTransList]).

%% ----------------------------------------------------------
%% @doc 宠物觉醒 @end
%% ----------------------------------------------------------
awaken_pet(#player_status{status_pet = StatusPet, id = RoleId} = Player, PetId) ->
	#status_pet{pets = PetInfoList} = StatusPet,
	case lists:keyfind(PetId, #pet_info.pet_id, PetInfoList) of
		#pet_info{pet_star = PetStar, pet_lv = PetLv, pet_exp = PetExp} ->
			case data_pet:get_awaken_cfg(PetId) of
				#pet_awaken_cfg{need_star = NeedStar, cost_material = CostMaterial} ->
					case PetStar >= NeedStar of
						true ->
							case lib_goods_api:cost_object_list_with_check(Player, CostMaterial, awaken_pet, "awaken pet") of
								{true, Player1, _} ->
									NewPlayer = do_awaken_pet(Player1, PetId),
									lib_log_api:log_pet_grow(RoleId, PetId, PetStar, PetLv, PetExp, 4, PetStar, PetLv, PetExp, CostMaterial),
									send_msg(Player, 16316, [?SUCCESS, PetId]),
									NewPlayer;
								{false, Error, _} ->
									send_msg(Player, 16316, [Error, PetId]),
									Player
							end;
						_ ->
							send_msg(Player, 16316, [?ERRCODE(err163_star_not_reach), PetId]),
							Player
					end;
				_ ->
					send_msg(Player, 16316, [?ERRCODE(err163_cannot_awaken), PetId]),
					Player
			end;
		_ ->
			send_msg(Player, 16316, [?ERRCODE(err163_not_adopt), PetId]),
			Player
	end.


%% --------------------------------------------------------------------
%% 计算进化下一级
calc_next_star(PetId, NowStar) ->
	case data_pet:get_pet_cfg(PetId, NowStar+1) of
		#pet_cfg{} ->
			NextStar  = NowStar + 1;
		_ ->
			NextStar = 0
	end,
	NextStar.

%% 计算宠物总星数
calc_pet_sum_star([], 0) -> 0;
calc_pet_sum_star([], SumStar) -> SumStar;
calc_pet_sum_star([{_PetId, PetStar}|TList], SumStar) ->
	calc_pet_sum_star(TList, PetStar + SumStar).

send_msg(Player, Cmd, Msg) ->
	{ok, Bin} = pt_163:write(Cmd, Msg),
	lib_server_send:send_to_sid(Player#player_status.sid, Bin).

send_error(Player, ErrCode) ->
	#player_status{sid = Sid} = Player,
	{ok, Bin} = pt_163:write(16300, [ErrCode]),
	lib_server_send:send_to_sid(Sid, Bin).

%% ------------------------------ 属性相关 ------------------------------
%% 统计所有宠物的属性
calc_all_pet_attr(PetInfoList) ->
	F = fun(PetInfo, TAttrList) ->
		case PetInfo of
			#pet_info{pet_attr = PetAttr} ->
				ulists:kv_list_plus_extra(TAttrList, PetAttr);
			_ -> TAttrList
		end
	end,
	lists:foldl(F, [], PetInfoList).

calc_all_pet_extra_power(PetInfoList) ->
	F = fun(PetInfo, TPower) ->
		case PetInfo of
			#pet_info{pet_extra_power = ExtraPower} when ExtraPower > 0 ->
				ExtraPower + TPower;
			_ -> TPower
		end
	end,
	lists:foldl(F, 0, PetInfoList).

%% 获取宠物本星级的基础属性
get_base_attr_list(PetId, PetStar) ->
	case data_pet:get_pet_cfg(PetId, PetStar) of
		#pet_cfg{attr_list = AttrList} ->
			[{AttrId, AttrValue} || {AttrId, AttrValue, _Add} <- AttrList];
		_ -> []
	end.

%% 获取宠物等级增长的属性
get_lv_attr(PetId, PetStar, PetLv) ->
	case data_pet:get_pet_cfg(PetId, PetStar) of
		#pet_cfg{attr_list = AttrList} ->
			[{AttrId, Add*max(0,PetLv-1)} || {AttrId, _AttrValue, Add} <- AttrList];
		_ -> []
	end.

%% 获取觉醒属性
get_awaken_attr(PetId) ->
	case data_pet:get_awaken_cfg(PetId) of
		#pet_awaken_cfg{add_attr = [{AttId, Value, _}]} -> [{AttId, Value}];
		#pet_awaken_cfg{add_attr = [{_AttId, _Value}] = Attr} -> Attr;
		_ -> []
	end.

%% 计算宠物本星级的基础属性加和
calc_attr(BaseAttr, AddAttr) ->
	ulists:kv_list_plus_extra(BaseAttr, AddAttr).

%% 计算宝石加成属性
calc_diamonds_attr(DiamondsList) ->
	Adder = fun({_SlotId, DiamondId}, {TAttrList, TPower}) ->
		case data_pet:get_pet_diamond_storage_cfg(DiamondId) of
			#pet_diamond_storage_cfg{add_attr_list = AddAttr} ->
				AttrList1 = ulists:kv_list_plus_extra(TAttrList, AddAttr),
				NewAttrList1 = lib_player_attr:partial_attr_convert(AttrList1),
				AttrR = attr_conv:to_attr_record(NewAttrList1),
				DiamondPower = lib_player_attr:calc_attr_power(AttrR),
				Power1 = TPower + DiamondPower,
				{AttrList1, Power1};
			_ ->
				{TAttrList, TPower}
		end
	end,
	lists:foldl(Adder, {[], 0}, DiamondsList).

%% 计算宠物支援全属性比例加成
calc_attr_add_ratio(AttrList, AddRatio) ->
	NewAttrList = [{AttrId, round(Value*(1 + AddRatio))}||{AttrId, Value}<- AttrList],
	NewAttrList.

%% 计算所有激活宠物的助战加成
calc_all_pet_attr_add_ratio(StatusPet) ->
	#status_pet{
		pets           = PetsInfoList,
		support_list   = SupportList
	} = StatusPet,
	NewPetsInfoList = calc_pets_attr_add_ratio(PetsInfoList, SupportList),
	StatusPet#status_pet{pets = NewPetsInfoList}.

%% 属性加成具体逻辑(注意需要全量计算拥有宠物,单个宠物时不可以使用)
%% 单个宠物使用pet_attr_add_ratio
calc_pets_attr_add_ratio(PetsInfoList, SupportList) ->
	F = fun(PetInfo, TPetsList) ->
		#pet_info{pet_id = PetId, pet_attr = PetAttr} = PetInfo,
		case lists:keyfind(PetId, #pet_support_slot.pet_id, SupportList) of
			#pet_support_slot{slot_id = SlotId} ->
				%% 注意配置是小数位的加成值
				case data_pet:get_pet_support_slot_cfg(SlotId) of
					#pet_support_slot_cfg{attr_add_ratio = AddRatio} -> ok;
					_ -> AddRatio = 0
				end,
				NewPetAttr = calc_attr_add_ratio(PetAttr, AddRatio),
				NewPetInfo = PetInfo#pet_info{pet_attr = NewPetAttr, pet_power = calc_pet_power(NewPetAttr)},
				lists:keystore(PetId, #pet_info.pet_id, TPetsList, NewPetInfo);
			_ ->
				lists:keystore(PetId, #pet_info.pet_id, TPetsList, PetInfo)
		end end,
	NewPetsInfoList = lists:foldl(F, [], PetsInfoList),
	NewPetsInfoList.

pet_attr_add_ratio(PetInfo, SupportList) ->
	#pet_info{pet_id = PetId, pet_attr = PetAttr} = PetInfo,
	case lists:keyfind(PetId, #pet_support_slot.pet_id, SupportList) of
		#pet_support_slot{slot_id = SlotId} ->
			case data_pet:get_pet_support_slot_cfg(SlotId) of
				#pet_support_slot_cfg{attr_add_ratio = AddRatio} -> ok;
				_ -> AddRatio = 0
			end,
			NewPetAttr = calc_attr_add_ratio(PetAttr, AddRatio),
			NewPetInfo = PetInfo#pet_info{pet_attr = NewPetAttr, pet_power = calc_pet_power(NewPetAttr)},
			NewPetInfo;
		_ ->
			PetInfo
	end.

%% 计算战力
calc_pet_power(AttrList) ->
	NewAttrList = lib_player_attr:partial_attr_convert(AttrList),
	AttrR  = attr_conv:to_attr_record(NewAttrList),
	AttrR1 = lib_player_attr:attr_count_with_extra(AttrR),
	Power  = lib_player_attr:calc_attr_power(AttrR1),
	Power.

get_pet_power(Player) ->
	case Player#player_status.status_pet of
		#status_pet{power = Power, extra_power = ExtraPower
		} -> Power + ExtraPower;
		_ -> 0
	end.

%% 计算宠物(单只)基础属性+宝石属性+技能属性+觉醒属性 加和属性
calc_pet_sum_attr(PetInfo) ->
	#pet_info{
		pet_id            = PetId,
		pet_star          = PetStar,
		pet_lv            = PetLv,
		pet_life_skills   = LifeSkills,
		pet_attr_skills   = AttrSkills,
		pet_battle_skills = BattleSkills,
		diamond_slots     = DiamondsSlots,
		is_awaken         = IsAwaken
	} = PetInfo,
	SkillList = LifeSkills ++ AttrSkills ++ BattleSkills,
	SkillAttr  = lib_skill_attr:count_skill_attr_with_mod_id(?MOD_PET, SkillList, 1),
	NewSkillList = [{SkillId, 1} || SkillId <- SkillList],
	SkillPower = lib_skill:count_skill_power(NewSkillList),
	{DiamondAttr, _DiamondPower} = calc_diamonds_attr(DiamondsSlots),
	BaseAttr = get_base_attr_list(PetId, PetStar),
	LvAttr   = get_lv_attr(PetId, PetStar, PetLv),
	AwakenAttr = case IsAwaken of
					 1 -> get_awaken_attr(PetId);
					 _ -> []
	             end,
	StageAttr = BaseAttr ++ LvAttr,
	SumAttr = util:combine_list(StageAttr ++ SkillAttr ++ DiamondAttr ++ AwakenAttr),
	PetInfo#pet_info{
		pet_attr  = SumAttr,
		pet_power = calc_pet_power(SumAttr),
		pet_extra_power = SkillPower
	}.

%% 计算所有宠物的基础属性加和(不包含支援属性加成)
calc_all_pet_attr_exclude_add_ratio(StatusPet) ->
	#status_pet{pets = PetInfoList} = StatusPet,
	F = fun(PetInfo, TPetInfoList) ->
		#pet_info{pet_id = PetId} = PetInfo,
		NewPetInfo = calc_pet_sum_attr(PetInfo),
		lists:keystore(PetId, #pet_info.pet_id, TPetInfoList, NewPetInfo)
	end,
	NewPetInfoList = lists:foldl(F, [], PetInfoList),
	StatusPet#status_pet{pets = NewPetInfoList}.

%% 刷新属性(内存中必须已经加载了所有宠物&技能石&技能)
refresh_attr(#player_status{status_pet = StatusPet} = Player, Type) ->
	StatusPet1   = calc_all_pet_attr_exclude_add_ratio(StatusPet),
	NewStatusPet = calc_all_pet_attr_add_ratio(StatusPet1),  % 助战属性加成
	PetInfoList  = NewStatusPet#status_pet.pets,
	NewAttrList    = calc_all_pet_attr(PetInfoList),
	NewPower       = calc_pet_power(NewAttrList),
	NewExtraPower  = calc_all_pet_extra_power(PetInfoList),
	NewStatusPet1 = NewStatusPet#status_pet{
		attr_list = NewAttrList, power = NewPower,
		extra_power = NewExtraPower},
	NewPlayer = lib_pet_data:save_dict_status_pet(Player, NewStatusPet1),
	RefreshPlayer = lib_player:count_player_attribute(NewPlayer, ?MOD_PET, Type),
	lib_player:send_attribute_change_notify(RefreshPlayer, ?NOTIFY_ATTR),
	%% 刷新榜单上玩家最新战力 和 宠物最新战力
	PetInfoList1  = refresh_to_rank(RefreshPlayer, PetInfoList),
	NewStatusPet2 = NewStatusPet1#status_pet{pets = PetInfoList1},
	RefreshPlayer1 = lib_pet_data:save_dict_status_pet(RefreshPlayer, NewStatusPet2),
	RefreshPlayer1.
%% 离线登陆计算属性(相比refresh_attr少了send_attribute_change_notify)
offline_refresh_attr(#player_status{status_pet = StatusPet} = Player, Type) ->
	StatusPet1   = calc_all_pet_attr_exclude_add_ratio(StatusPet),
	NewStatusPet = calc_all_pet_attr_add_ratio(StatusPet1),  % 助战属性加成
	#status_pet{pets = PetInfoList} = NewStatusPet,
	NewAttrList    = calc_all_pet_attr(PetInfoList),
	NewPower       = calc_pet_power(NewAttrList),
	NewExtraPower  = calc_all_pet_extra_power(PetInfoList),
	NewStatusPet1 = NewStatusPet#status_pet{
		attr_list = NewAttrList, power = NewPower,
		extra_power = NewExtraPower},
	NewPlayer = lib_pet_data:save_dict_status_pet(Player, NewStatusPet1),
	RefreshPlayer = lib_player:count_player_attribute(NewPlayer, ?MOD_PET, Type),
	RefreshPlayer.

%% 登录刷新战力
refresh_power(Player) ->
	#player_status{status_pet = StatusPet} = Player,
	#status_pet{power = BasicPower, extra_power = SkillPower} = StatusPet,
	NewStatusPet = StatusPet#status_pet{power = BasicPower + SkillPower},
	lib_pet_data:save_dict_status_pet(Player, NewStatusPet).

%% 刷新战力榜
refresh_to_rank(Player, PetsInfoList) ->
	#player_status{id = RoleId, figure = Figure, server_num = ServerNum} = Player,
	%% todo: 宠物前后战力对比
	ForF = fun(#pet_info{pet_id = PetId, pet_power = PetPower, old_power = OldPower} = PetInfo, TList) ->
		case PetPower > OldPower of
			true ->
				lib_pet_data:update_db_pet_power(RoleId, PetId, PetPower),
				RoleMsg = {RoleId, Figure#figure.name, Figure#figure.power, ServerNum},
				mod_pet_support_mgr:pet_power_change(RoleMsg, PetId, PetPower, OldPower),
				lists:keystore(PetId, #pet_info.pet_id, TList, PetInfo#pet_info{old_power = PetPower});
			_ ->
				TList
		end end,
	lists:foldl(ForF, PetsInfoList, PetsInfoList).

%% ---------------------------- 技能相关 -------------------------------
trans_to_pet_list([], []) -> [];
trans_to_pet_list([], PetList) -> PetList;
trans_to_pet_list([PetInfo|T], PetList) ->
	#pet_info{
		pet_id    = PetId,
		pet_star  = PetStar
	} = PetInfo,
	NewPetList = [{PetId, PetStar}|PetList],
	trans_to_pet_list(T, NewPetList).

%% 检查宠物(单只)技能是否增加
check_if_add_skill(Player, StatusPet, Pet) ->
	#pet_info{
		pet_id = PetId, pet_star = PetStar,
		pet_life_skills = OldLifeSkills, pet_attr_skills = OldAttrSkills,
		pet_battle_skills = OldBattleSkills
	} = Pet,
	{LifeSkills, AttrSkills, BattleSkills} =
		get_pet_skill_list(PetId, PetStar),
	case (LifeSkills -- OldLifeSkills) ++ (AttrSkills -- OldAttrSkills) ++ (BattleSkills -- OldBattleSkills) of
		[] -> {StatusPet, Pet};
		_  ->  %% 新增了技能
			#status_pet{support_list = SupportList, life_skills = LifeSkillList,
				passive_skills = PassiveSkillList, battle_skills = BattleSkillList} = StatusPet,
			case lists:keyfind(PetId, #pet_support_slot.pet_id, SupportList) of
				#pet_support_slot{slot_id = ?PET_BATTLE_SKILL_SLOT} ->
					AddPassiveSkills = AttrSkills -- OldAttrSkills,
					NewBattleSkills  = BattleSkills;
				_    ->
					AddPassiveSkills = AttrSkills -- OldAttrSkills,
					NewBattleSkills  = BattleSkillList
			end,
			AddPassive = [{SkillId, 1} || SkillId <- AddPassiveSkills++NewBattleSkills],
			OldBattleSkills1 = [{OldBattleSkill, 1}||OldBattleSkill<-OldBattleSkills],
			mod_scene_agent:update(Player,
				[{delete_passive_skill, OldBattleSkills1}, {passive_skill, AddPassive}]
			),
			{   StatusPet#status_pet{
					life_skills    = LifeSkillList ++ (LifeSkills -- OldLifeSkills),
					passive_skills = PassiveSkillList ++ AddPassiveSkills,
					battle_skills  = NewBattleSkills},
				Pet#pet_info{
					pet_life_skills   = LifeSkills,
					pet_attr_skills   = AttrSkills,
					pet_battle_skills = BattleSkills}
			}
	end.

%% 觉醒后切换技能
check_if_change_skill(PetInfo) ->
	#pet_info{pet_id = PetId, is_awaken = IsAwaken,
		pet_battle_skills = OldBattleSkill
	} = PetInfo,
	case IsAwaken of
		1 ->
			case data_pet:get_awaken_cfg(PetId) of
				#pet_awaken_cfg{skill_list = BattleSkill} -> ok;
				_ -> BattleSkill = []
			end;
		_ -> BattleSkill = OldBattleSkill
	end,
	NewPetInfo = PetInfo#pet_info{pet_battle_skills = BattleSkill},
	NewPetInfo.

%% 根据天赋类型获取所有宠物技能列表
get_all_pet_skill_list(_, [], _TalentType) -> [];
get_all_pet_skill_list(PetInfoList, SupportList, TalentType) ->
	F = fun(PetInfo, AllSkillList) ->
		#pet_info{
			pet_id            = PetId,
			pet_life_skills   = LifeSkills,
			pet_attr_skills   = AttrSkills,
			pet_battle_skills = BattleSkills
		} = PetInfo,
		if
			TalentType == ?SKILL_LIFE   ->
				LifeSkills++AllSkillList;
			TalentType == ?SKILL_ATTR   ->
				AttrSkills++AllSkillList;
			TalentType == ?SKILL_BATTLE ->
				case lists:keyfind(PetId, #pet_support_slot.pet_id, SupportList) of
					#pet_support_slot{slot_id = SlotId} when SlotId =< ?PET_BATTLE_SKILL_SLOT ->
						BattleSkills ++ AllSkillList;
					_    -> AllSkillList
				end;
			true -> AllSkillList
		end
	end,
	lists:foldl(F, [], PetInfoList).

%% 获取单只宠物的技能列表
get_pet_skill_list(PetId, PetStar) ->
	%% 筛选符合阶级&星级条件的技能
	Filter = fun(SlotId, {TLifeSkills, TAttrSkills, TBattleSkills}) ->
		case data_pet:get_pet_skill_cfg(PetId, SlotId) of
			#pet_skill_cfg{
				skill_talent_id   = SkillId,
				skill_talent_type = SkillType,
				active_star       = ActiveStar
			} ->
				if
					PetStar >= ActiveStar ->
						if
							SkillType == ?SKILL_LIFE ->
								{[SkillId|TLifeSkills], TAttrSkills, TBattleSkills};
							SkillType == ?SKILL_ATTR ->
								{TLifeSkills, [SkillId|TAttrSkills], TBattleSkills};
							SkillType == ?SKILL_BATTLE ->
								{TLifeSkills, TAttrSkills, [SkillId|TBattleSkills]};
							true ->
								{TLifeSkills, TAttrSkills, TBattleSkills}
						end;
					true -> {TLifeSkills, TAttrSkills, TBattleSkills}
				end;
			_ -> {TLifeSkills, TAttrSkills, TBattleSkills}
		end
	end,
	lists:foldl(Filter, {[], [], []}, ?SKILL_SLOT_LIST).

%% 获取宠物技能石槽位
get_pet_skill_diamonds_from_db(RoleId, PetId) ->
	DiamondList = lib_pet_data:get_db_pet_skill_diamond(RoleId, PetId),
	F = fun([SlotId, DiamondId], TList) ->
		[{SlotId, DiamondId}|TList]
	end,
	lists:foldl(F, [], DiamondList).

%% ---------------------------- builtin function -------------------------------
%% 打包宠物基础数据
pack_pets_info([], []) -> [];
pack_pets_info([], PackList) -> PackList;
pack_pets_info([PetInfo|T], TList) ->
	#pet_info{
		pet_id     = PetId,
		pet_star   = PetStar,
		pet_lv     = PetLv,
		pet_exp    = PetExp,
		pet_attr   = AttrList,
		pet_power  = Power,
		adopt_time = AdoptTime,
		is_awaken  = IsAwaken
	} = PetInfo,
	NewList = [{PetId, PetStar, PetLv, PetExp, AttrList, Power, AdoptTime, IsAwaken}|TList],
	pack_pets_info(T, NewList).

%% 更新玩家figure中的宠物信息
update_player_figure(Player, FollowPetInfo) ->
	#player_status{figure = Figure, id = RoleId} = Player,
	NewFigure = Figure#figure{follow_pet = FollowPetInfo},
	lib_role:update_role_show(RoleId, [{figure, NewFigure}]),
	Player#player_status{figure = NewFigure}.

%% 激活宠物具体逻辑
do_adopt_pet(#player_status{status_pet = StatusPet, id = RoleId} = Player, PetId) ->
	InitStar = 1,
	BaseAttr = get_base_attr_list(PetId, InitStar), %% 激活只有基础属性
	LvAttr   = get_lv_attr(PetId, InitStar, 1),
	StageAttr = util:combine_list(BaseAttr++LvAttr),
	Power    = calc_pet_power(StageAttr),
	{PetLifeSkills, PetAttrSkills, PetBattleSkills} =
		get_pet_skill_list(PetId, InitStar),
	AdoptTime = utime:unixtime(),
	Pet = #pet_info{
		pet_id            = PetId,
		pet_star          = InitStar,
		pet_lv            = 1,
		pet_exp           = 0,
		pet_attr          = StageAttr,
		pet_power         = Power,
		pet_life_skills   = PetLifeSkills,
		pet_attr_skills   = PetAttrSkills,
		pet_battle_skills = PetBattleSkills,
		diamond_slots     = [],
		adopt_time        = AdoptTime
	},
	NewPet  = calc_pet_sum_attr(Pet),
	PetInfo = [InitStar, 1, 0, AdoptTime, 0, 0],
	lib_pet_data:save_db_pet_info(RoleId, PetId, PetInfo),
	lib_pet_data:save_ets_pet(RoleId, NewPet),
	%% 更新技能列表&属性列表&战力&总星级
	NewStatusPet = lib_pet_data:save_dict_pet_info(StatusPet, NewPet),
	NewStatusPet1 = NewStatusPet#status_pet{                 %% 非跟随只加生活&属性技能
		life_skills    = StatusPet#status_pet.life_skills ++ PetLifeSkills,
		passive_skills = StatusPet#status_pet.passive_skills ++ PetAttrSkills,
		sum_pet_star   = StatusPet#status_pet.sum_pet_star + 1
	},
	%% 触发成就
	handle_pet_achievement(Player, NewStatusPet1),
	%% 触发成就
	Data = calc_pet_lv_num(NewStatusPet1),
	lib_achievement_api:pet_lv_up_event(Player, Data),
	NewPlayer = Player#player_status{status_pet = NewStatusPet1},
	RefreshPlayer  = refresh_attr(NewPlayer, adopt_pet),
	mod_scene_agent:update(RefreshPlayer, [{battle_attr, RefreshPlayer#player_status.battle_attr}]),
	SumPower = NewPet#pet_info.pet_power + NewPet#pet_info.pet_extra_power,
	CheckPlayer = check_if_open_support_slot(RefreshPlayer, NewStatusPet1#status_pet.sum_pet_star),
	{CheckPlayer, SumPower}.

%% 宠物进化具体逻辑
do_upgrade_pet(#player_status{status_pet = StatusPet, id = RoleId} = Player,
		PetId, NewPetStar) ->
	#status_pet{pets = PetInfoList, support_list = SupportList} = StatusPet,
	PetInfo = lists:keyfind(PetId, #pet_info.pet_id, PetInfoList),
	#pet_info{pet_lv = PetLv, pet_star = PetStar} = PetInfo,
	%% 更新属性
	BaseAttr  = get_base_attr_list(PetId, NewPetStar),
	LvAttr    = get_lv_attr(PetId, NewPetStar, PetLv),
	StageAttr = calc_attr(BaseAttr, LvAttr),
	Power     = calc_pet_power(StageAttr),
%%	DiamondsList = get_pet_skill_diamonds(RoleId, PetId),
	NewPet = PetInfo#pet_info{   %% 此处技能未刷新
		pet_id    = PetId,
		pet_star  = NewPetStar,
		pet_attr  = StageAttr,
		pet_power = Power
	},
	%% 检查全部的技能变动
	{NewStatusPet, NewPetInfo} =
		check_if_add_skill(Player, StatusPet, NewPet),
	NewPetInfo1 = calc_pet_sum_attr(NewPetInfo),
	%% 存库
	lib_pet_data:update_db_pet_info(RoleId, PetId, NewPetStar),
	NewPetStar =/= PetStar andalso lib_pet_data:save_ets_pet(RoleId, NewPet),
	NewPetInfoList = lists:keyreplace(PetId, #pet_info.pet_id, PetInfoList, NewPetInfo1),
	NewStatusPet1  = NewStatusPet#status_pet{
		pets         = NewPetInfoList,
		sum_pet_star = NewStatusPet#status_pet.sum_pet_star+1},
	NewPlayer = lib_pet_data:save_dict_status_pet(Player, NewStatusPet1),
	RefreshPlayer  = refresh_attr(NewPlayer, upgrade_pet),
	mod_scene_agent:update(RefreshPlayer, [{battle_attr, RefreshPlayer#player_status.battle_attr}]),
	%% 更新宠物信息
	InfoFun = fun(#pet_support_slot{pet_id = TPetId, slot_id = TSlotId}, TList) when TPetId > 0 ->
		case lists:keyfind(TPetId, #pet_info.pet_id, NewPetInfoList) of
			#pet_info{pet_star = TPetStar, is_awaken = IsAwaken} ->
				case TSlotId == 1 of
					true -> [{TPetId, TPetStar, IsAwaken, 1}|TList];
					_ -> [{TPetId, TPetStar, IsAwaken, 0}|TList]
				end;
			_ -> TList
		end;
		(_, TList) -> TList
	end,
	PetList = lists:foldl(InfoFun, [], SupportList),
	mod_scene_agent:update(RefreshPlayer, [{support_pet_list, PetList}]),
	CheckPlayer = check_if_open_support_slot(RefreshPlayer, NewStatusPet1#status_pet.sum_pet_star),
	SumPower = NewPetInfo1#pet_info.pet_power + NewPetInfo1#pet_info.pet_extra_power,
	{CheckPlayer, SumPower}.

handle_skill_stone_achievement(Player, StatusPet) ->
	#status_pet{pets = PetsList} = StatusPet,
	F = fun(Pet, {TColorList, TSuitMap}) ->
		#pet_info{diamond_slots = DiamondSlots} = Pet,
		%% 颜色件数
		F1 = fun({_SlotId, GoodId}, TList1) ->
			case data_goods:get_goods_color(GoodId) of
				Color when Color > 0 ->
					case lists:keyfind(Color, 1, TList1) of
						{_, Num} -> lists:keystore(Color, 1, TList1, {Color, Num + 1});
						_        -> lists:keystore(Color, 1, TList1, {Color, 1})
					end;
				_ ->
					TList1
			end end,
		TColorList1 = lists:foldl(F1, TColorList, DiamondSlots),
		%% 套装数
		F2 = fun({_SlotId, GoodsId2}, TList2) ->
			case data_goods:get_goods_color(GoodsId2) of
				Color2 when Color2 > 0 ->
					case lists:member(Color2, TList2) of
						true -> TList2;
						_ -> [Color2|TList2]
					end;
				_ ->
					TList2
			end end,
		SuitList = lists:foldl(F2, [], DiamondSlots),
		case erlang:length(SuitList) =:= 1 of
			true when erlang:length(DiamondSlots) =:= 4 ->
				[SuitColor] = SuitList,
				Num = maps:get(SuitColor, TSuitMap, 0),
				TSuitMap1 = maps:put(SuitColor, Num + 1, TSuitMap);
			_ ->
				TSuitMap1 = TSuitMap
		end,
		{TColorList1, TSuitMap1}
	end,
	{_ColorList, ColorSuitMap} = lists:foldl(F, {[], #{}}, PetsList),
	lib_achievement_api:pet_stone_suit_event(Player, ColorSuitMap).

handle_pet_achievement(Player, StatusPet) ->
	#status_pet{pets = PetsList} = StatusPet,
	F = fun(Pet, TList) ->
		#pet_info{
			pet_id = PetId, pet_star = Star} = Pet,
		case data_pet:get_pet_cfg(PetId, Star) of
			#pet_cfg{color = Color} ->
				case lists:keyfind(Color, 1, TList) of
					{_, OwnNum} -> lists:keystore(Color, 1, TList, {Color, OwnNum + 1});
					_        -> lists:keystore(Color, 1, TList, {Color, 1})
				end;
			_ ->
				TList
		end
	end,
	Data = lists:foldl(F, [], PetsList),
	lib_achievement_api:own_pet_event(Player, Data).

%% 宠物喂养具体逻辑
do_feed_pet(#player_status{status_pet = StatusPet, id = RoleId} = Player, Pet, AddExp) ->
	#pet_info{
		pet_id = PetId, pet_lv = PetLv, pet_exp = PetExp,
		pet_star = PetStar
	} = Pet,
	#pet_cfg{rare_degree = RareDegree} = data_pet:get_pet_cfg(PetId, PetStar),
	case get_pet_growup_exp_need(RareDegree, PetLv) of
		NeedExp when NeedExp > 0 ->
			SumExp = PetExp + AddExp,
			if
				SumExp >= NeedExp ->
					{NewPetLv, NewPetExp} =
						do_add_exp(RareDegree, PetLv, SumExp, NeedExp);
				true -> %% 不够升等级
					NewPetLv  = PetLv,
					NewPetExp = PetExp + AddExp
			end;
		_ ->  %% 本级是最高等级
			NewPetLv  = PetLv,
			NewPetExp = PetExp + AddExp
	end,
	lib_pet_data:update_db_pet_lv(RoleId, PetId, NewPetLv, NewPetExp),
	%% 刷新经验&属性  %% TODO：+日志
	BaseAttr = get_base_attr_list(PetId, PetStar),
	LvAttr   = get_lv_attr(PetId, PetStar, NewPetLv),
	SumAttr  = calc_attr(BaseAttr, LvAttr),
	NewPet = Pet#pet_info{
		pet_lv = NewPetLv, pet_exp = NewPetExp,
		pet_attr  = SumAttr,
		pet_power = calc_pet_power(SumAttr)
	},
	NewPet1 = calc_pet_sum_attr(NewPet),
	NewPetLv =/= PetLv andalso lib_pet_data:save_ets_pet(RoleId, NewPet1),
	NewStatusPet = lib_pet_data:update_dict_pet_info(StatusPet, NewPet1),
	%% 触发成就
	Data = calc_pet_lv_num(NewStatusPet),
	lib_achievement_api:pet_lv_up_event(Player, Data),
	NewPlayer = lib_pet_data:save_dict_status_pet(Player, NewStatusPet),
	RefreshPlayer  = refresh_attr(NewPlayer, upgrade_pet),
	mod_scene_agent:update(RefreshPlayer, [{battle_attr, RefreshPlayer#player_status.battle_attr}]),
	{RefreshPlayer, NewPetLv, NewPetExp, NewPet1#pet_info.pet_power+NewPet1#pet_info.pet_extra_power}.

get_pet_growup_exp_need(RareDegree, PetLv) ->
	case data_pet:get_pet_grow_up_cfg(RareDegree, PetLv+1) of
		#pet_grow_up_cfg{need_exp = NeedExp} ->
			NeedExp;
		_ -> 0
	end.

do_add_exp(RareDegree, PetLv, SumExp, NeedExp) ->
	NewPetLv = PetLv + 1,
	LeftExp  = SumExp - NeedExp,
	NextNeedExp = get_pet_growup_exp_need(RareDegree, NewPetLv),
	if
		NextNeedExp > 0 andalso LeftExp > NextNeedExp ->
			do_add_exp(RareDegree, NewPetLv, LeftExp, NextNeedExp);
		true ->
			{NewPetLv, LeftExp}
	end.

%% 获取当前同等级的宠物数量[{lv, num}...]
calc_pet_lv_num(StatusPet) ->
	#status_pet{pets = PetsList} = StatusPet,
	F = fun(PetInfo, TList) ->
		#pet_info{pet_lv = Lv} = PetInfo,
		case lists:keyfind(Lv, 1, TList) of
			{_, Num} ->
				lists:keystore(Lv, 1, TList, {Lv, Num+1});
			_ ->
				lists:keystore(Lv, 1, TList, {Lv, 1})
		end
	end,
	lists:foldl(F, [], PetsList).

%% 替换技能石具体逻辑
do_replace_skill_diamond(#player_status{id = RoleId} = Player,
		#pet_info{pet_id = PetId} = PetInfo, DiamondSlot, OldDiamondId, DiamondId) ->
	case inlay_skill_diamond_core(Player, OldDiamondId, DiamondId) of
		{ok, Player1} ->
			NewPlayer = lib_pet_data:update_dict_diamond_slots(
				Player1, PetInfo, {DiamondSlot, DiamondId}, ?PET_DIAMOND_INLAY),
			%% 写库
			lib_pet_data:update_db_pet_skill_diamond(RoleId, PetId, DiamondSlot, DiamondId),
			%% 刷新属性
			#player_status{status_pet = NewStatusPet} = NewPlayer,
			#status_pet{pets = NewPetsInfo} = NewStatusPet,
			NewPetInfo = calc_pet_sum_attr(
				lists:keyfind(PetId, #pet_info.pet_id, NewPetsInfo)),
			lib_pet_data:save_ets_pet(RoleId, NewPetInfo),
			NewStatusPet1 = lib_pet_data:update_dict_pet_info(NewStatusPet, NewPetInfo),
			NewPlayer1 = lib_pet_data:save_dict_status_pet(NewPlayer, NewStatusPet1),
			RefreshPlayer = refresh_attr(NewPlayer1, inlay_pet_diamond),
			handle_skill_stone_achievement(NewPlayer1, NewStatusPet1),
			{ok, RefreshPlayer, NewPetInfo#pet_info.pet_power+NewPetInfo#pet_info.pet_extra_power};
		{false, Res} -> {false, Res, Player}
	end.

%% 镶嵌技能石具体逻辑
do_inlay_skill_diamond(#player_status{id = RoleId} = Player,
		#pet_info{pet_id = PetId} = PetInfo, {DiamondSlot, DiamondId}) ->
	case inlay_skill_diamond_core(Player, 0, DiamondId) of
		{ok, Player1} ->
			NewPlayer = lib_pet_data:update_dict_diamond_slots(
				Player1, PetInfo, {DiamondSlot, DiamondId}, ?PET_DIAMOND_INLAY),
			lib_pet_data:save_db_pet_skill_diamond(RoleId, PetId, DiamondSlot, DiamondId),
			%% 刷新属性
			#player_status{status_pet = NewStatusPet} = NewPlayer,
			#status_pet{pets = NewPetsInfo} = NewStatusPet,
			NewPetInfo = calc_pet_sum_attr(
				lists:keyfind(PetId, #pet_info.pet_id, NewPetsInfo)),
			lib_pet_data:save_ets_pet(RoleId, NewPetInfo),
			NewStatusPet1 = lib_pet_data:update_dict_pet_info(NewStatusPet, NewPetInfo),
			%% 触发成就
			handle_skill_stone_achievement(Player, NewStatusPet1),
			NewPlayer1 = lib_pet_data:save_dict_status_pet(NewPlayer, NewStatusPet1),
			RefreshPlayer = refresh_attr(NewPlayer1, inlay_pet_diamond),
			{ok, RefreshPlayer, NewPetInfo#pet_info.pet_power+NewPetInfo#pet_info.pet_extra_power};
		{false, Res} -> {false, Res, Player}
	end.

%% 技能宝石镶嵌背包具体逻辑 % GoodsId 全服唯一物品Id
inlay_skill_diamond_core(Player, OldDiamondId, DiamondId) ->
	if
		OldDiamondId =/= 0 andalso DiamondId =/= 0 ->
			case lib_goods_api:cost_object_list_with_check(Player, [{?TYPE_GOODS, DiamondId, 1}], pet_skill_diamond, "") of
				{true, Player1, _} ->
					Produce = #produce{
						title = utext:get(11), content = utext:get(12),
						type = pet_skill_diamond, reward = [{?TYPE_GOODS, OldDiamondId, 1}],
						remark = "", show_tips = 1},
					lib_goods_api:send_reward_with_mail(Player1, Produce, ?MOD_PET);
				{false, Res, _NewPS} ->
					{false, Res}
			end;
		true ->
			case lib_goods_api:cost_object_list_with_check(Player, [{?TYPE_GOODS, DiamondId, 1}], pet_skill_diamond, "") of
				{true, NewPs, _} -> {ok, NewPs};
				{false, Res, _NewPS} ->
					{false, Res}
			end
	end.

%% 觉醒具体逻辑
do_awaken_pet(#player_status{status_pet = StatusPet, id = RoleId} = Player, PetId) ->
	#status_pet{pets = PetInfoList, support_list = SupportList} = StatusPet,
	PetInfo = lists:keyfind(PetId, #pet_info.pet_id, PetInfoList),
	%% 检查全部的技能变动
	NewPetInfo  = check_if_change_skill(PetInfo#pet_info{is_awaken = 1}),
	%% 存库
	lib_pet_data:update_db_pet_awaken(RoleId, PetId),
	NewPetInfo1 = calc_pet_sum_attr(NewPetInfo),
	%% 上阵属性加成
	NewPetInfo2 = pet_attr_add_ratio(NewPetInfo1, SupportList),
	NewPetInfoList = lists:keyreplace(PetId, #pet_info.pet_id, PetInfoList, NewPetInfo2),
	%% 重新计算战斗技能
	PetBattleSkills  = lib_pet:get_all_pet_skill_list(NewPetInfoList, SupportList, ?SKILL_BATTLE),
	NewStatusPet  = StatusPet#status_pet{
		pets           = NewPetInfoList
		,battle_skills = PetBattleSkills
	},
	NewPlayer = lib_pet_data:save_dict_status_pet(Player, NewStatusPet),
	RefreshPlayer = refresh_attr(NewPlayer, awaken_pet),
	%% 觉醒成就
	handle_awaken_achievement(NewPlayer, NewPetInfoList),
	mod_scene_agent:update(RefreshPlayer, [{battle_attr, RefreshPlayer#player_status.battle_attr}]),
	RefreshPlayer.

handle_awaken_achievement(Player, PetInfoList) ->
	F = fun(#pet_info{is_awaken = IsAwaken, pet_lv = PetLv}, TSumLv) ->
		case IsAwaken of
			1 -> PetLv + TSumLv;
			_ -> TSumLv
		end end,
	SumLv = lists:foldl(F, 0, PetInfoList),
	lib_achievement_api:pet_awaken_event(Player, SumLv),
	ok.

trans_tv_string(PetRace, PetName) ->
	case PetRace of
		1 ->
			ulists:concat(["<color@1>", PetName, "</color>"]);
		2 ->
			ulists:concat(["<color@3>", PetName, "</color>"]);
		3 ->
			ulists:concat(["<color@2>", PetName, "</color>"]);
		_ ->
			PetName
	end.

tran_tv_string1(Star) ->
	ulists:concat(["<color@2>", Star, "</color>"]).
