%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     式神
%%% @end
%%%-------------------------------------------------------------------
-module(god_logic).
-author("liushl").
-include("server.hrl").
-include("god.hrl").
-include("common.hrl").
-include("goods.hrl").
-include("def_goods.hrl").
-include("def_fun.hrl").
-include("figure.hrl").
-include("def_module.hrl").
-include("predefine.hrl").
-include("attr.hrl").
-include("errcode.hrl").


%% API
-export([
    god_active/2            %% 唤神激活
    , god_star_up/2          %% 唤神升星
    , god_skill_up/2         %% 唤神技能升级
    , god_lv_up/5            %% 唤神升级

    , god_equip/4            %% 唤神装备
    , god_equip_remove/3     %% 唤神卸装备
    , god_equip_upgrade/3    %% 唤神装备升级

    , god_summon/2           %% 主动召唤唤神
    , god_front/3            %% 唤神上阵

    , unlock_pos/2           %% 解锁上阵位
    , god_lottery/3
    , log_god_lottery/1
]).

-export([
    db_get_all_god/1
    , db_get_role_god/1
    , db_save_role_god/2

    , get_sp_attr/1
    , calc_one_god_attr/1
    , calc_all_god_attr_1/1
    , calc_all_god_attr_2/3
    , get_god_equip_attr/2
    , get_unlock_suit_skill_num/1
    , get_god_equip_lv/1

    , do_god_upgrade/1
    , calc_cost_list/4
    , do_god_summon/3

    , summon_init/1
    , summon_new_fighting_god/3
    , role_switch_god/2
    , god_summon_expire/2

    , gm_reset/1
    , god_reset/1
]).

%%%===================================================================
%%% @doc 式神基本操作-激活/升星/升级/技能升级
%%%===================================================================
%%--------------------------------------------------------------------
%% @doc 式神激活
%%--------------------------------------------------------------------
god_active(Player, GodId) ->
    case god_check:check_god_active(Player, GodId) of
        {false, Err} -> {false, Err};
        {true, Cost, God} ->
            case lib_goods_api:cost_object_list_with_check(Player, Cost, god_active, GodId) of
                {false, Err, _} -> {false, Err};
                {true, Player1, _} ->
                    Player2 = do_active(Player1, God, Cost),
                    {ok, Player2}
            end
    end.
do_active(Player, God, Cost) ->
    #player_status{id = RoleId, figure = #figure{name = RoleName}} = Player,
    operate_log([RoleId, RoleName, God#god.id, ?LOG_ACTIVE, 0, 0, 0, 1, 0, God#god.skills, Cost]),
    Player2 = update_god_info(Player, God, true, ?LOG_ACTIVE),
    GodList = Player2#player_status.role_god#role_god.god_info,
    lib_achievement_api:god_active_event(Player2, erlang:length(GodList)),
    lib_server_send:send_to_sid(Player#player_status.sid, pt_173, 17303, [1, God#god.id]),
    Player2.

%%--------------------------------------------------------------------
%% @doc 式神升星
%%--------------------------------------------------------------------
god_star_up(Player, GodId) ->
    case god_check:check_god_star_up(Player, GodId) of
        {false, Err} -> {false, Err};
        {true, Cost, OldStar, God} ->
            case lib_goods_api:cost_object_list_with_check(Player, Cost, god_star_up, GodId) of
                {false, Err, _} -> {false, Err};
                {true, Player1, _} ->
                    #player_status{id = RoleId, figure = #figure{name = RoleName}} = Player,
                    operate_log([RoleId, RoleName, GodId, ?LOG_STAR_UP, OldStar, God#god.star, God#god.lv, God#god.lv, God#god.exp, God#god.skills, Cost]),
                    Player2 = update_god_info(Player1, God, true, ?LOG_STAR_UP),
                    [{_, GoodsId, _}|_] = Cost,
                    #base_god_info{name = GodName} = data_god:get_god_info(GodId, God#god.star),
                    lib_chat:send_TV({all}, ?MOD_GOD, 3, [RoleName, RoleId, GoodsId, GodName, God#god.star]),
                    {ok, Player2, God#god.star}
            end;
        Error ->
            ?ERR("god_logic_error:~w", [Error]),
            {false, 0}
    end.

handle_god_lv_achievement(Player) ->
    GodList = Player#player_status.role_god#role_god.god_info,
    F = fun(#god{lv = GodLv, pos = Pos}, TSumLv) ->
        case ?IS_PRIMARY_GOD(Pos) orelse ?IS_SECONDARY_GOD(Pos) of
            true -> GodLv + TSumLv;
            _ -> TSumLv
        end;
        (_, TSumLv) -> TSumLv
        end,
    SumLv = lists:foldl(F, 0, GodList),
    lib_achievement_api:god_up_event(Player, SumLv),
    ok.

%%--------------------------------------------------------------------
%% @doc 式神升级
%%--------------------------------------------------------------------

%% 处理升多级
do_god_upgrade(God) ->
    #god{lv = Lv, exp = Exp, id = GodId} = God,
    case data_god:get_god_lv_exp(GodId, Lv) of
        NeedExp when is_integer(NeedExp) andalso Exp >= NeedExp ->
            do_god_upgrade(God#god{lv = Lv + 1, exp = Exp - NeedExp});
        _ ->
            God
    end.

god_lv_up(Player, GodId, UpType, GoodsId, GoodsNum) ->
    case god_check:check_god_lv_up(Player, GodId, UpType, GoodsId, GoodsNum) of
        {false, Err} -> {false, Err};
        {ok, Cost, God, Change, OldGod} ->
            case lib_goods_api:cost_object_list_with_check(Player, Cost, god_lv_up, GodId) of
                {false, Err, _} -> {false, Err};
                {true, Player1, _} ->
                    #player_status{id = RoleId, figure = #figure{name = RoleName}} = Player,
                    operate_log([RoleId, RoleName, GodId, ?LOG_LV_UP, God#god.star, God#god.star, OldGod#god.lv, God#god.lv, God#god.exp, God#god.skills, Cost]),
                    Player2 = update_god_info(Player1, God, Change, ?LOG_LV_UP),
                    handle_god_lv_achievement(Player2),
                    pp_god:handle(17302, Player2, [GodId]),
                    {ok, Player2, [God#god.lv, God#god.exp, Change]}
            end;
        Error ->
            ?ERR("god_logic_error:~w", [Error]),
            {false, 0}
    end.

%%--------------------------------------------------------------------
%% @doc 式神技能升级
%%--------------------------------------------------------------------
god_skill_up(Player, GodId) ->
    case god_check:check_god_skill_up(Player, GodId) of
        {false, Err} -> {false, Err};
        {true, Cost, God, {SkillId, _} = NewSkillInfo} ->
            case lib_goods_api:cost_object_list_with_check(Player, Cost, god_skill_up, SkillId) of
                {false, Err, _} -> {false, Err};
                {true, Player1, _} ->
                    #player_status{id = RoleId, figure = #figure{name = RoleName}} = Player,
                    operate_log([RoleId, RoleName, GodId, ?LOG_SKILL, God#god.star, God#god.star, God#god.lv, God#god.lv, God#god.exp, God#god.skills, Cost]),
                    Player2 = update_god_info(Player1, God, true, ?LOG_SKILL),
                    {ok, Player2, NewSkillInfo}
            end;
        Error ->
            ?ERR("god_logic_error:~w", [Error]),
            {false, 0}
    end.

%%%===================================================================
%%% @doc 式神 信息刷新 装备变更不需要写数据
%%%===================================================================
update_god_info(Player, God, true, LogType) ->
    #player_status{role_god = RoleGod, id = RoleId, pid = Pid} = Player,
    #role_god{god_info = GodList} = RoleGod,
    to_save_one_god(LogType, RoleId, God),
    God2 = calc_one_god_attr(God, RoleId),
    GodList1 = lists:keystore(God#god.id, #god.id, GodList, God2),
    %% 激活式神时判断需不需要直接上阵
    check_direct_front(Pid, LogType, God#god.id, GodList1),
    %% 判断已解锁的出战位
    GodList2 = check_to_remove_god_front(LogType, GodList1, RoleId),
    RoleGod1 = RoleGod#role_god{god_info = GodList2},
    Player1 = Player#player_status{role_god = RoleGod1},
    Player2 = update_all_god(Player1),
    Player3 = god_operation_trigger(God, Player2, LogType),
    Player3;
%% 简单操作
update_god_info(Player, God, false, LogType) ->
    #player_status{role_god = RoleGod, id = RoleId} = Player,
    #role_god{god_info = GodList} = RoleGod,
    to_save_one_god(LogType, RoleId, God),
    GodList1 = lists:keystore(God#god.id, #god.id, GodList, God),
    RoleGod1 = RoleGod#role_god{god_info = GodList1},
    Player1 = Player#player_status{role_god = RoleGod1},
    Player1.

%% 唤神操作触发
%% 成就&任务&其它
god_operation_trigger(_God, Player, _LogType) ->
    Player.

%% 计算单个式神属性。装备属性不再重新计算
calc_one_god_attr(God) ->
    calc_one_god_attr(God, 0).

calc_one_god_attr(God, _RoleId) ->
    #god{id = Id, star = Star, lv = Lv, skills = Skills, equip_attr = EquipAttr, suit_info = SuitInfo} = God,
    case data_god:get_god_info(Id, Star) of
        #base_god_info{attr = AttrList} ->
            %% 等级成长属性
            BaseRoleAttr = [{AttrId, Base + (Lv - 1) * Grown} || {AttrId, Base, Grown} <- AttrList],

            %% 技能属性
            SkillAttr = lib_skill_attr:count_skill_attr_with_mod_id(?MOD_GOD, Skills, 1),
            SkillPower = lib_skill:count_skill_power(Skills),

            %% 上阵装备套装效果提供给玩家的属性
            SuitRoleAttr = get_suit_effect(SuitInfo, ?TYPE_SUIT_SKILL_FRONT_ROLE),
            %% 总属性=上阵套装加成属性+技能+基础+装备
            TotalRoleAttr = ulists:kv_list_plus_extra([SuitRoleAttr, SkillAttr, BaseRoleAttr, EquipAttr]),

            %% 局部属性处理
            LastAttr = lib_player_attr:partial_attr_convert(TotalRoleAttr),
            % RoleId == 4294967363 andalso ?ERR("唤神 ~p 上阵套装加成 ~p 技能 ~p 基础 ~p 装备 ~p 汇总 ~p 局部处理后 ~p", [Id, SuitRoleAttr, SkillAttr, BaseRoleAttr, EquipAttr, TotalRoleAttr, LastAttr]),
            %% 套装特殊技能
            SuitSkills = get_suit_effect(SuitInfo, ?TYPE_SUIT_SKILL_SPECIAL),

            God#god{attr = LastAttr, extra_power = SkillPower, suit_skills = SuitSkills};
        _ ->
            God
    end.

%% 获得套装 效果
get_suit_effect(SuitInfo, SuitType) ->
    F = fun({SuitId, SuitNum}, Temp) ->
        case data_god:get_suit_info(SuitId) of
            [_ | _] = List -> %% [{suit_num, skill_type, skill_id, effect}]
                [case SuitType of
                     ?TYPE_SUIT_SKILL_SPECIAL -> SkillId;
                     _ ->
                         case Effect of
                             [Attr] -> Attr;
                             _ -> {1, 1}
                         end
                 end || {Num, Type, SkillId, Effect} <- List, Num =< SuitNum, Type =:= SuitType]
                ++ Temp;
            _ ->
                Temp
        end end,
    lists:foldl(F, [], SuitInfo).

suit_effect_god([{Key, Value} | T], GodAttr) ->
    case lists:keyfind(Key, 1, GodAttr) of
        {_, V} -> suit_effect_god(T, lists:keyreplace(Key, 1, GodAttr, {Key, V * Value}));
        _ -> suit_effect_god(T, GodAttr)
    end;
suit_effect_god(_, GodAttr) -> GodAttr.

update_all_god(Player) ->
    #player_status{role_god = RoleGod} = Player,
    RoleGod1 = calc_all_god_attr_1(RoleGod),
    Player1 = Player#player_status{role_god = RoleGod1},
    Player2 = lib_player:count_player_attribute(Player1, ?MOD_GOD),
    mod_scene_agent:update(Player2, [{battle_attr, Player2#player_status.battle_attr}]),
    lib_player:send_attribute_change_notify(Player2, ?NOTIFY_ATTR),
    Player2.

%% 计算总属性1，这里不计算神属性战力，神属性战力在统计模块战力回调时计算，god_api/calc_god_power
%% 出战位1倍，辅助位0.5倍
%% 主式神基础属性(培养属性) + 主式神装备属性 + 主式神套装属性 + 援助式神基础属性*0.5 + 援助式神装备属性*0.5 + 援助式神套装属性*0.5
calc_all_god_attr_1(RoleGod) ->
    #role_god{god_info = GodInfo} = RoleGod,
    F = fun(God, Temp) ->
        #god{attr = Attr, pos = Pos, suit_skills = SuitSkills} = God,
        if
            ?IS_PRIMARY_GOD(Pos) ->   % 主战
                ulists:kv_list_plus_extra([Attr, Temp]);
            ?IS_SECONDARY_GOD(Pos) -> % 辅助
                ulists:kv_list_plus_extra([assistance_attr(Attr, calc_secondary_discount(SuitSkills)), Temp]);
            true ->
                Temp
        end end,
    TotalAttr = lists:foldl(F, [], GodInfo),
    RoleGod#role_god{attr = TotalAttr}.

calc_secondary_discount(SuitSkills) ->
    case lists:member(?SUIT_SKILL_ROLE_ASSIST_PLUS2, SuitSkills) of
        true -> 0.8;
        false ->
            case lists:member(?SUIT_SKILL_ROLE_ASSIST_PLUS1, SuitSkills) of
                true -> 0.6;
                false -> 0.5
            end
    end.
%% 计算总战力2，计算神属性战力 出战位1倍，辅助位0.5倍 在统计完总属性后计算
%% 主神防 = 主战式神神防*套装加成 + 继承玩家防御*套装加成
%% 援助神防 = 0.5*援助式神神防*套装加成
%% 式神系统计算最终战力
calc_all_god_attr_2(#player_status{id = _RoleId, role_god = RoleGod} = Player, AttrPower, BaseAttr) when is_record(RoleGod, role_god) ->
    #player_status{battle_attr = #battle_attr{hp_lim = RoleHp, attr = #attr{att = RoleAtt, def = RoleDef}}} = Player,
    %% 继承自玩家的属性
    InheritAttr = [{?ATT, RoleAtt}, {?HP, RoleHp * 0.2}, {?DEF, RoleDef}],
    F = fun(God, {TempGod, TempGodPower, TempRolePower}) ->
        #god{
            pos = Pos, suit_info = SuitInfo, id = Id, star = Star,
            extra_power = ExtraPower, lv = Lv, attr = RoleAttr, suit_skills = SuitSkills
        } = God,
        case data_god:get_god_info(Id, Star) of
            #base_god_info{god_attr = GodAttrList} ->
                SuitGodAttr = get_suit_effect(SuitInfo, ?TYPE_SUIT_SKILL_FRONT_GOD),
                %% 式神成长属性
                GodAttr = [{AttrId, Base + max(0, (Lv - 1)) * Grown} || {AttrId, Base, Grown} <- GodAttrList],
                %% 式神成长属性的套装加成
                FromGodAttr = suit_effect_god(SuitGodAttr, GodAttr),
                %% 主战神属性=继承自玩家的属性+有套装加成的式神成长属性
                GodAttrThen = ulists:kv_list_plus_extra([InheritAttr, FromGodAttr]),
                %% 神属性战力+额外战力(技能战力)
                GodPowerShow = calc_god_power(GodAttrThen) + ExtraPower,
                %% 可以提供给玩家的战力
                if
                    ?IS_PRIMARY_GOD(Pos) ->   % 主战
                        LastGodAttr = GodAttrThen,                    %% 主战式神属性 完全
                        GodPowerReal = GodPowerShow,                   %% 主战神属性战力也是全额
                        RoleAttrRecord = attr_conv:to_attr_record(RoleAttr),
                        RolePower = lib_player_attr:calc_attr_power_partial(AttrPower, BaseAttr, RoleAttrRecord), %% 主式神提供的玩家战力
                        RolePowerReal = GodPowerShow + RolePower,
                        PowerShow = RolePowerReal;
                    ?IS_SECONDARY_GOD(Pos) -> % 辅助
                        LastGodAttr = [],                             %% 辅助式神不统计式神属性了
                        GodPowerReal = 0,                              %% 辅助式神不统计式神属性了
                        Discount = calc_secondary_discount(SuitSkills),
                        RoleAttrRecord = attr_conv:to_attr_record(assistance_attr(RoleAttr, Discount)),
                        RolePower = lib_player_attr:calc_attr_power_partial(AttrPower, BaseAttr, RoleAttrRecord),
                        RolePowerReal = RolePower + GodPowerReal,
                        PowerShow = round(RolePower / Discount) + GodPowerShow;
                    true ->                  % 未上阵
                        LastGodAttr = [],                             %% 未上阵就不统计式神属性了
                        GodPowerReal = 0,                              %% 未上阵不提供式神战力
                        RolePowerReal = 0,                              %% 未上阵不提供玩家战力
                        PowerShow = lib_player_attr:calc_preview_power(Player, RoleAttr) + GodPowerShow
                end,
                % RoleId == 8589934774 andalso ?ERR("god_id ~p role_attr ~p total power ~p god_attr ~p god power ~p", [Id, RoleAttr, PowerShow, LastGodAttr, GodPowerShow]),
                {[God#god{god_attr = LastGodAttr, power_show = round(PowerShow)}|TempGod], GodPowerReal+TempGodPower, RolePowerReal+TempRolePower};
            _ ->
                {TempGod, TempGodPower, TempRolePower}
        end end,
    {GodInfo, TotalGodPower, TotalRolePower} = lists:foldl(F, {[], 0, 0}, RoleGod#role_god.god_info),
    NewRoleGod = RoleGod#role_god{god_info = GodInfo, god_power = round(TotalGodPower), role_power = round(TotalRolePower)},
    Player#player_status{role_god = NewRoleGod};
calc_all_god_attr_2(Player, _, _) -> Player.

%% 计算式神战力
calc_god_power(AttrList) ->
    lists:sum([
        case AttrId of
           ?ATT -> AttrValue*0.1;
           ?DEF -> AttrValue*0.1;
           ?HP  -> AttrValue*0.01;
           _    -> 0
       end || {AttrId, AttrValue} <- AttrList]).


%% 主战属性 附加到主战属性
assistance_attr(Attr, Discount) ->
    [{AttId, AttValue * Discount} || {AttId, AttValue} <- Attr].

%%%===================================================================
%%% @doc 式神装备-穿戴/卸载/装备强化/图鉴激活
%%%===================================================================
%% 获得式神装备属性值
get_god_equip_attr(RoleId, GodId, GoodsDict) ->
    GodEquips = lib_goods_util:get_goods_list_by_type(RoleId, ?GOODS_LOC_GOD_EQUIP, ?GOODS_TYPE_GOD_EQUIP, GoodsDict),
    get_god_equip_attr(GodId, GodEquips).
get_god_equip_attr(GodId, GodEquips) ->
    TheGodEquip = [GoodsInfo || GoodsInfo <- GodEquips, GoodsInfo#goods.cell div ?CELL_OFFSET =:= GodId],
    get_god_equip_attr_do(TheGodEquip).
get_god_equip_attr_do(TheGodEquip) ->
    F = fun(GoodsInfo, {Attr, SuitState}) ->
        #goods{goods_id = GoodsId, extra_data = ExtraData} = GoodsInfo,
        Level = get_god_equip_lv(ExtraData),
        case data_god:get_god_equip(GoodsId) of
            #base_god_equip{suit_id = SuitId, attr = BaseAttr} ->
                NewSuitState =
                    case lists:keyfind(SuitId, 1, SuitState) of
                        {_, Num} -> lists:keyreplace(SuitId, 1, SuitState, {SuitId, Num + 1});
                        _ -> [{SuitId, 1} | SuitState]
                    end,
                {get_sp_attr(GoodsInfo) ++ [{AttrId, Base + Level * Grown} || {AttrId, Base, Grown} <- BaseAttr] ++ Attr,
                    NewSuitState};
            _ ->
                {Attr, SuitState}
        end end,
    {TotalAttr, SuitInfo} = lists:foldl(F, {[], []}, TheGodEquip),
    {TotalAttr, SuitInfo}.

%% 获取唤神高级装备额外随机属性
get_sp_attr(GoodsInfo) ->
    #goods{extra_data = ExtraData} = GoodsInfo,
    ExtraAttr = get_god_equip_sp_attr(ExtraData),
    Level = get_god_equip_lv(ExtraData),
    [{AttrId, Base + max(0, (Level div ?GOD_EQUIP_SP_LV - 1)) * Grown} || {AttrId, Base, Grown} <- ExtraAttr].

%% 获取唤神装备等级
get_god_equip_lv(ExtraData) ->
    case lists:keyfind(?GOODS_OTHER_KEY_GOD_EQUIP_LV, 1, ExtraData) of
        {_, Lv} -> Lv;
        _ -> 0
    end.

%% 获取唤神装备经验
get_god_equip_exp(ExtraData) ->
    case lists:keyfind(?GOODS_OTHER_KEY_GOD_EQUIP_EXP, 1, ExtraData) of
        {_, Exp} -> Exp;
        _ -> 0
    end.

get_god_equip_sp_attr(ExtraData) ->
    case lists:keyfind(?GOODS_OTHER_KEY_GOD_SP_ATTR, 1, ExtraData) of
        {_, Data} -> Data;
        _  -> []
    end.

update_all_god_equip_extra_data(KVs, ExtraData) ->
    lists:foldl(fun({K, V}, TempExtraData) ->
        update_god_equip_extra_data(K, V, TempExtraData)
                end, ExtraData, KVs).

update_god_equip_extra_data(Key, NewVal, ExtraData) ->
    lists:keystore(Key, 1, ExtraData, {Key, NewVal}).

%% 装备变更时，刷新式神的装备属性。以后计算战力的时候，装备属性不再计算
%% 另外装备变更时，判断套装属性，如果增加出战位的套装减少，需要判断下阵
when_god_equip_change(God, RoleId, GoodsDict) ->
    #god{id = GodId, suit_info = OldSuit} = God,
    {TotalAttr, SuitInfo} = get_god_equip_attr(RoleId, GodId, GoodsDict),
    God1 = God#god{equip_attr = TotalAttr, suit_info = SuitInfo},
    SuitChange = case OldSuit of
                     SuitInfo -> false;
                     _ -> true
                 end,
    {God1, SuitChange}.

%% 判断下阵式神
check_to_remove_god_front(LogType, GodList, RoleId) when
    LogType =:= ?LOG_SUIT orelse LogType =:= ?LOG_GOD_FRONT ->
    SkillNum = get_unlock_suit_skill_num(GodList),
    F = fun(God, Temp) ->
        case god_check:pos_is_unlock_by_suit(SkillNum, God#god.pos) of
            false ->
                ChangeGod = God#god{pos = 0},
                db_save_one_god(RoleId, ChangeGod),
                [ChangeGod | Temp];
            true ->
                [God | Temp]
        end end,
    lists:foldl(F, [], GodList);
check_to_remove_god_front(_, GodList, _) -> GodList.
%% 式神切换时 判断下阵第二个神仆
check_to_remove_second_god(GodList, #god{pos = Pos, star = Star}, RoleId) when ?IS_PRIMARY_GOD(Pos) andalso Star < 3 ->
    F = fun(God, Temp) ->
        case ?IS_THE_SECONDARY_GOD(Pos, God#god.pos) andalso God#god.pos rem ?POS_OFFSET =:= 2 of
            true ->
                ChangeGod = God#god{pos = 0},
                save_one_god_on_transaction(RoleId, ChangeGod),
                [ChangeGod | Temp];
            false ->
                [God | Temp]
        end end,
    lists:foldl(F, [], GodList);

check_to_remove_second_god(GodList, _, _) -> GodList.
%%--------------------------------------------------------------------
%% @doc 穿戴装备
%%--------------------------------------------------------------------
god_equip(Player, GodId, EquipPos, GoodsId) ->
    GoodsStatus = lib_goods_do:get_goods_status(),
    case god_check:check_god_equip(Player, GodId, EquipPos, GoodsId, GoodsStatus) of
        {ok, NewEquip, OldEquip, Cell, God} ->
            F = fun() ->
                ok = lib_goods_dict:start_dict(),
                case is_record(OldEquip, goods) of
                    true ->
                        [NewEquipInfo, GoodsStatus1] = goods_logic:change_goods_location(NewEquip, ?GOODS_LOC_GOD_EQUIP, Cell, GoodsStatus),
                        [_, GoodsStatus2] = goods_logic:change_goods_location(OldEquip, ?GOODS_LOC_GOD_BAG, NewEquip#goods.cell, GoodsStatus1),
                        OperateType = 0;
                    _ ->
                        [NewEquipInfo, GoodsStatus2] = goods_logic:change_goods_location(NewEquip, ?GOODS_LOC_GOD_EQUIP, Cell, GoodsStatus),
                        OperateType = 1
                end,
                OldDict = GoodsStatus2#goods_status.dict,
                {GoodsDict, GoodsL} = lib_goods_dict:handle_dict_and_notify(OldDict),
                {ok, GoodsStatus2#goods_status{dict = GoodsDict}, GoodsL, NewEquipInfo, OperateType}
                end,
            case catch goods_transaction:transaction(F) of
                {ok, NewGoodsStatus, GoodsL, GoodsInfo, Type} ->
                    #player_status{id = RoleId} = Player,
                    lib_goods_do:set_goods_status(NewGoodsStatus),
                    %% 此处通知客户端将装备从背包位置中移除不会从服务端删除物品
                    lib_goods_api:notify_client_num(RoleId, [NewEquip#goods{num = 0}]),
                    %% 从身上移除
                    is_record(OldEquip, goods) andalso lib_goods_api:notify_client_num(RoleId, [OldEquip#goods{num = 0}]),
                    %% 通知前端更新了物品位置
                    lib_goods_api:notify_client(RoleId, GoodsL, god_equip),
                    {God1, _SuitChange} = when_god_equip_change(God, RoleId, NewGoodsStatus#goods_status.dict),
                    Player1  = update_god_info(Player, God1, true, ?LOG_SUIT),
                    EquipLv  = get_god_equip_lv(GoodsInfo#goods.extra_data),
                    EquipExp = get_god_equip_exp(GoodsInfo#goods.extra_data),
                    log_god_equip_upgrade([RoleId, GoodsInfo#goods.goods_id, GodId, GoodsInfo#goods.cell, Type, EquipLv, EquipLv, EquipExp, EquipExp, [], 0]),
                    handle_god_equip_achievement(Player1),
                    handle_equip_up_achievement(Player1),
                    {ok, Player1};
                Error ->
                    ?ERR("god_equip error:~p", [Error]),
                    {false, 0}
            end;
        {false, Error} ->
            {false, Error};
        Error ->
            ?ERR("god_logic_error:~w", [Error]),
            {false, 0}
    end.

handle_god_equip_achievement(Player) ->
    GoodsStatus = lib_goods_do:get_goods_status(),
    GoodsList = lib_goods_util:get_goods_list(Player#player_status.id, ?GOODS_LOC_GOD_EQUIP, GoodsStatus#goods_status.dict),
    F = fun(#goods{goods_id = GoodsTypeId, color = Color, cell = Cell}, {TColorList, TSuitMap}) ->
            TColorList1 = case lists:keyfind(Color, 1, TColorList) of
                              {_, Num} -> lists:keystore(Color, 1, TColorList, {Color, Num + 1});
                              _ -> lists:keystore(Color, 1, TColorList, {Color, 1})
                          end,
            GodId = Cell div ?CELL_OFFSET,
            TEquipList = maps:get(GodId, TSuitMap, []),
            TSuitMap1 = maps:put(GodId, [GoodsTypeId|TEquipList], TSuitMap),
            {TColorList1, TSuitMap1};
        (_, {TColorList, TSuitMap}) -> {TColorList, TSuitMap}
    end,
    {ColorList, SuitMap} = lists:foldl(F, {[], #{}}, GoodsList),
    SuitNum = maps:fold(fun(_, EquipList, TSuitNum) ->
                                ForFun = fun(EquipId, TMap) ->
                                    case data_god:get_god_equip(EquipId) of
                                        #base_god_equip{suit_id = SuitId} ->
                                            TNum = maps:get(SuitId, TMap, 0),
                                            maps:put(SuitId, TNum+1, TMap);
                                        _ -> TMap
                                    end end,
                                Map = lists:foldl(ForFun, #{}, EquipList),
                                ForFun1 = fun({_, Num}) -> Num >= 4 end,
                                List = maps:to_list(Map),
                                case lists:any(ForFun1, List) of
                                    true -> TSuitNum + 1;
                                    _ -> TSuitNum
                                end
                          end, 0, SuitMap),
    lib_achievement_api:god_equip_event(Player, ColorList),
    lib_achievement_api:god_equip_suit_event(Player, SuitNum),
    ok.

%% 套装 #goods.cell

%%--------------------------------------------------------------------
%% @doc 装备卸载
%%--------------------------------------------------------------------
god_equip_remove(Player, GodId, Pos) ->
    GoodsStatus = lib_goods_do:get_goods_status(),
    case god_check:check_god_equip_remove(Player, GodId, Pos, GoodsStatus) of
        {ok, GoodsInfo, God} ->
            ok = lib_goods_dict:start_dict(),
            [_GoodsInfo1, GoodsStatus2] =
                goods_logic:change_goods_location(GoodsInfo, ?GOODS_LOC_GOD_BAG, 0, GoodsStatus),
            {Dict, GoodsL} = lib_goods_dict:handle_dict_and_notify(GoodsStatus2#goods_status.dict),
            GoodsStatus3 = GoodsStatus2#goods_status{dict = Dict},
            lib_goods_do:set_goods_status(GoodsStatus3),
            RoleId = Player#player_status.id,
            %% 此处通知客户端将装备从背包位置中移除不会从服务端删除物品
            lib_goods_api:notify_client_num(RoleId, [GoodsInfo#goods{num = 0}]),
            lib_goods_api:notify_client(RoleId, GoodsL, god_equip),
            {NewGod, _SuitChange} = when_god_equip_change(God, RoleId, GoodsStatus3#goods_status.dict),
            Player1 = update_god_info(Player, NewGod, true, ?LOG_SUIT),
            EquipLv = get_god_equip_lv(GoodsInfo#goods.extra_data),
            EquipExp = get_god_equip_exp(GoodsInfo#goods.extra_data),
            log_god_equip_upgrade([RoleId, GoodsInfo#goods.goods_id, GodId, GoodsInfo#goods.cell, 3, EquipLv, EquipLv, EquipExp, EquipExp, [], 0]),
            handle_god_equip_achievement(Player1),
            handle_equip_up_achievement(Player1),
            {ok, Player1};
        {false, Err} ->
            {false, Err};
        Error ->
            ?ERR("god_logic_error:~w", [Error]),
            {false, 0}
    end.
%%--------------------------------------------------------------------
%% @doc 装备升级
%%--------------------------------------------------------------------
%% 计算单件装备能够提供的经验
calc_up_exp(_Quality, 0, Exp) -> Exp;
calc_up_exp(Quality, Level, Exp) ->
    case data_god:get_god_equip_lv_exp(Quality, Level) of
        AddExp when is_integer(AddExp) ->
            calc_up_exp(Quality, Level - 1, AddExp + Exp);
        _ ->
            calc_up_exp(Quality, Level - 1, Exp)
    end.
%% 计算所有消耗提供的经验
calc_cost_list([{Id, Num} | T], GoodsStatus, Exp, GoodsList) ->
    case lib_goods_util:get_goods(Id, GoodsStatus#goods_status.dict, ?GOODS_LOC_GOD_BAG) of
        #goods{goods_id = GoodsTypeId} ->
            case lib_goods_check:check_goods_normal(GoodsStatus, Id, GoodsTypeId) of
                {ok, #goods{type = ?GOODS_TYPE_GOD_EQUIP, location = ?GOODS_LOC_GOD_BAG, extra_data = ExtraData,
                    goods_id = GoodsId, num = Total} = GoodsInfo} when Total >= Num ->
                    OldExp = get_god_equip_exp(ExtraData),
                    Level = get_god_equip_lv(ExtraData),
                    case data_god:get_god_equip(GoodsId) of
                        #base_god_equip{exp = AddExp, quality = Quality} ->
                            UpExp = calc_up_exp(Quality, Level, OldExp),
                            calc_cost_list(T, GoodsStatus, Exp + (UpExp + AddExp) * Num, [{GoodsInfo, Num} | GoodsList]);
                        _ -> {false, ?MISSING_CONFIG}
                    end;
                _ -> {false, 0}
            end;
        _ ->
            {false, ?ERRCODE(err150_no_goods)}
    end;
calc_cost_list([], _, Exp, GoodsList) -> {Exp, GoodsList}.
%% 处理升多级
do_god_equip_upgrade(Goods, IsUp) ->
    #goods{color = Color, extra_data = ExtraData} = Goods,
    Lv = get_god_equip_lv(ExtraData),
    Exp = get_god_equip_exp(ExtraData),
    NewLv = Lv + 1,
    case data_god:get_god_equip_lv_exp(Color, NewLv) of
        NeedExp when is_integer(NeedExp) andalso Exp >= NeedExp ->
            %% 升到某些等级，生成额外属性
            SpLv = ?GOD_EQUIP_SP_LV,
            OldExtraAttr = get_god_equip_sp_attr(ExtraData),
            NewExtraAttr = 
            case NewLv >= SpLv andalso OldExtraAttr == [] of
               true ->
                   case data_god:get_god_equip(Goods#goods.goods_id) of
                       #base_god_equip{extra_attr = SpAttrList} ->
                           case urand:rand_with_weight(SpAttrList) of
                               false -> [];
                               SpAttr -> SpAttr
                           end;
                       _ -> []
                   end;
               false ->
                   OldExtraAttr
           end,
            if NewExtraAttr =/= [] ->
                    UpdateList = [
                        {?GOODS_OTHER_KEY_GOD_EQUIP_EXP, round(Exp - NeedExp)},
                        {?GOODS_OTHER_KEY_GOD_SP_ATTR, NewExtraAttr},
                        {?GOODS_OTHER_KEY_GOD_EQUIP_LV, NewLv}
                    ];
                true ->
                    UpdateList = [
                        {?GOODS_OTHER_KEY_GOD_EQUIP_EXP, round(Exp - NeedExp)},
                        {?GOODS_OTHER_KEY_GOD_EQUIP_LV, NewLv}
                    ]
            end,
            NewExtraData = update_all_god_equip_extra_data(UpdateList, ExtraData),
            do_god_equip_upgrade(Goods#goods{extra_data = NewExtraData}, true);
        _ ->
            {Goods, IsUp}
    end.

%% 进行升级 CostList：[{goods_id, num}|_]
god_equip_upgrade(Player, GoodsId, CostList0) ->
    OldGoodsStatus = lib_goods_do:get_goods_status(),
    case god_check:check_god_equip_upgrade(GoodsId, CostList0, OldGoodsStatus) of
        {false, Err} -> {false, Err};
        {ok, GoodsInfo, AddExp, ToCost} ->
            F = fun() ->
                ok = lib_goods_dict:start_dict(),
                {ok, GoodsStatus1} = goods_del:delete_goods_list(OldGoodsStatus, ToCost),
                ExtraData = GoodsInfo#goods.extra_data,
                OldExp = get_god_equip_exp(ExtraData),
                NewExtraData = update_god_equip_extra_data(?GOODS_OTHER_KEY_GOD_EQUIP_EXP, OldExp + AddExp, ExtraData),
                GoodsInfoTemp = GoodsInfo#goods{extra_data = NewExtraData},
                {GoodsInfo1, IsUp} = do_god_equip_upgrade(GoodsInfoTemp, false),
                % GoodsStatus   = lib_goods_do:get_goods_status(),
                [GoodsInfo2, GoodsStatus2] = goods_logic:change_goods_extra(GoodsInfo1, GoodsStatus1),
                {Dict, GoodsL} = lib_goods_dict:handle_dict_and_notify(GoodsStatus2#goods_status.dict),
                GoodsStatus3 = GoodsStatus2#goods_status{dict = Dict},
                {ok, GoodsStatus3, GoodsL, GoodsInfo2, IsUp}
                end,
            case catch goods_transaction:transaction(F) of
                {ok, NewGoodsStatus, GoodsChangeInfo, NewEquip, EquipChange} ->
                    #player_status{role_god = RoleGod, id = RoleId, figure = #figure{name = Name}} = Player,
                    lib_goods_do:set_goods_status(NewGoodsStatus),
                    lib_goods_api:notify_client(RoleId, GoodsChangeInfo, god_equip),
                    #goods{goods_id = GoodsTypeId, cell = Cell, location = Location, extra_data = NewExtraData} = NewEquip,
                    Exp = get_god_equip_exp(NewExtraData),
                    Lv = get_god_equip_lv(NewExtraData),
                    GodId = Cell div ?CELL_OFFSET,
                    OldEquipExp = get_god_equip_exp(GoodsInfo#goods.extra_data),
                    OldEquipLv  = get_god_equip_lv(GoodsInfo#goods.extra_data),
                    case Location of %% 穿在身上才计算 升级了才计算
                        ?GOODS_LOC_GOD_EQUIP when EquipChange ->
                            [begin
                                 Equip0 = NewEquip#goods{extra_data = update_god_equip_extra_data(?GOODS_OTHER_KEY_GOD_EQUIP_LV, EquipLv, NewExtraData)},
                                 SendCheck = EquipLv rem ?GOD_EQUIP_SP_LV,
                                 case get_sp_attr(Equip0) of
                                     [{AttrId, AttrValue}] ->
                                        if EquipLv == ?GOD_EQUIP_SP_LV ->
                                                lib_chat:send_TV({all}, ?MOD_GOD, 5, [Name, RoleId, GoodsTypeId, EquipLv, AttrId, AttrValue]);
                                            SendCheck == 0 ->
                                                lib_chat:send_TV({all}, ?MOD_GOD, 6, [Name, RoleId, GoodsTypeId, EquipLv, AttrId, AttrValue]);
                                            true ->
                                                skip
                                        end;
                                     _ -> ok
                                 end
                             end || EquipLv <- lists:seq(OldEquipLv+1, Lv), EquipLv rem ?GOD_EQUIP_SP_LV =:= 0],
                            case lists:keyfind(GodId, #god.id, RoleGod#role_god.god_info) of
                                #god{} = God ->
                                    {NewGod, _SuitChange} = when_god_equip_change(God, RoleId, NewGoodsStatus#goods_status.dict),
                                    Player1 = update_god_info(Player, NewGod, true, ?LOG_EQUIP_UP);
                                _ ->
                                    Player1 = Player
                            end;
                        _ -> Player1 = Player
                    end,
                    Cost =
                        [begin
                             CostGoodsLv    = get_god_equip_lv(CostGoods#goods.extra_data),
                             CostGoodsExp   = get_god_equip_exp(CostGoods#goods.extra_data),
                             {CostGoods#goods.goods_id, Num, CostGoods#goods.bind, CostGoodsLv, CostGoodsExp}
                         end || {CostGoods, Num} <- ToCost],
                    log_god_equip_upgrade([RoleId, GoodsTypeId, GodId, Cell, 2, OldEquipLv, Lv, OldEquipExp, Exp, Cost, AddExp]),
                    handle_equip_up_achievement(Player1),
                    {ok, Player1};
                {false, Err} -> {false, Err};
                Error ->
                    ?ERR("god_equip error:~p", [Error]),
                    {false, 0}
            end
    end.

handle_equip_up_achievement(Player) ->
    GoodsStatus = lib_goods_do:get_goods_status(),
    List1 = lib_goods_util:get_goods_list(Player#player_status.id, ?GOODS_LOC_GOD_EQUIP, GoodsStatus#goods_status.dict),
    % List2 = lib_goods_util:get_goods_list(Player#player_status.id, ?GOODS_LOC_GOD_BAG, GoodsStatus#goods_status.dict),
    F = fun(#goods{goods_id = GoodTypeId, extra_data = ExtraData}, TLvList) ->
                case lists:keyfind(?GOODS_OTHER_KEY_GOD_EQUIP_LV, 1, ExtraData) of
                    {_, Lv} -> [{GoodTypeId, Lv}|TLvList];
                    _ -> TLvList
                end;
        (_, TLvList) -> TLvList
        end,
    LvList = lists:foldl(F, [], List1),
    lib_achievement_api:god_equip_up_event(Player, LvList),
    ok.

%%%===================================================================
%%% @doc 式神战斗-解锁位置/上阵(援助)/下阵/召唤(切换下一个)
%%%===================================================================
%% 统计上阵位技能
get_unlock_suit_skill_num(GodInfo) ->
    length([1 || #god{suit_skills = SuitSkills, pos = P} <- GodInfo,
        P > 0, lists:member(?SUIT_SKILL_ADD_POS, SuitSkills)]).
%%--------------------------------------------------------------------
%% @doc 解锁位置
%%--------------------------------------------------------------------
%% 前四个位置不需要手动解锁
unlock_pos(_, Pos) when Pos =< (?DEFAULT_POS + 1) ->
    {false, ?ERRCODE(err173_god_pos_repeat)};

%% 辅助位不需要手动解锁
unlock_pos(_, Pos) when ?IS_SECONDARY_GOD(Pos) ->
    {false, ?ERRCODE(err173_god_pos_repeat)};

%% 第5个位置解锁 套装+钱/代币
unlock_pos(Player, 5) ->
    #player_status{role_god = RoleGod, id = RoleId} = Player,
    #role_god{unlock = Unlock, god_info = GodInfo} = RoleGod,
    case lists:member(5, Unlock) of
        true -> {false, ?ERRCODE(err173_god_pos_repeat)};
        false ->
            SkillNum = get_unlock_suit_skill_num(GodInfo),
            case god_check:pos_is_unlock_by_suit(SkillNum, 5) of
                true ->
                    Cost = data_god:get_kv(god_pos_5),
                    case lib_goods_api:cost_objects_with_auto_buy(Player, Cost, god_unlock_pos, 5) of
                        {true, Player1, _} ->
                            NewUnlock = [5 | Unlock],
                            NewRoleGod = RoleGod#role_god{unlock = NewUnlock},
                            NewPlayer = Player1#player_status{role_god = NewRoleGod},
                            db_save_role_god(RoleId, NewRoleGod),
                            {ok, NewPlayer};
                        {false, Err, _} ->
                            {false, Err}
                    end;
                false ->
                    {false, ?ERRCODE(err173_god_unlock_con_error)}
            end
    end;
unlock_pos(_Player, _Pos) ->
    {false, ?ERRCODE(err173_god_unlock_con_error)}.
%%--------------------------------------------------------------------
%% @doc 式神上阵
%%--------------------------------------------------------------------
god_front(Player, GodId, Pos) ->
    case god_check:check_god_front(Player, GodId, Pos) of
        {ok, TargetGod, OldGod} ->
            #player_status{id = RoleId, role_god = RoleGod} = Player,
            #role_god{god_info = GodInfo} = RoleGod,
            F = fun() ->
                NewGod = TargetGod#god{pos = Pos},
                save_one_god_on_transaction(RoleId, NewGod),
                GodInfo1 = lists:keystore(NewGod#god.id, #god.id, GodInfo, NewGod),
                case OldGod of
                    false when ?IS_PRIMARY_GOD(TargetGod#god.pos) ->
                        %% 假如一个主战式神上阵到一个空位置，则自动下阵该式神的原辅助式神
                        F0 = fun(God, Temp) ->
                            case ?IS_THE_SECONDARY_GOD(TargetGod#god.pos, God#god.pos) of
                                true ->
                                    OldSecondaryGod = God#god{pos = 0},
                                    save_one_god_on_transaction(RoleId, OldSecondaryGod),
                                    [OldSecondaryGod | Temp];
                                false ->
                                    [God | Temp]
                            end end,
                        GodInfo2 = lists:foldl(F0, [], GodInfo1);
                    false -> % 该位置没有式神，只是上阵
                        GodInfo2 = GodInfo1;
                    _ when Pos == 0 -> % 下阵
                        GodInfo2 = GodInfo1;
                    _ ->     % 该位置有式神，交换位置
                        OldChange = OldGod#god{pos = TargetGod#god.pos},
                        save_one_god_on_transaction(RoleId, OldChange),
                        GodInfo2 = lists:keystore(OldChange#god.id, #god.id, GodInfo1, OldChange)
                end,
                %% 主式神变化是不是要下阵第二个神仆
                GodInfo3 = check_to_remove_second_god(GodInfo2, NewGod, Player#player_status.id),
                {ok, GodInfo3, NewGod}
                end,
            case catch goods_transaction:transaction(F) of
                {ok, NewGodInfo, UpdateGod} ->
                    NewRoleGod = RoleGod#role_god{god_info = NewGodInfo},
                    Player1 = Player#player_status{role_god = NewRoleGod},
                    LastPlayer = update_god_info(Player1, UpdateGod, true, ?LOG_GOD_FRONT),
                    handle_god_lv_achievement(LastPlayer),
                    handle_god_equip_achievement(LastPlayer),
                    handle_equip_up_achievement(LastPlayer),
                    {ok, LastPlayer};
                Err ->
                    ?ERR("god_front error:~p", [{RoleId, GodId, Pos, Err}]),
                    {false, 0}
            end;
        {false, Err} -> {false, Err};
        Error ->
            ?ERR("god_logic_error:~w", [Error]),
            {false, 0}
    end.
%% 激活式神的时候有空位置，直接上阵
check_direct_front(Pid, LogType, GodId, GodInfo) ->
    case LogType of
        ?LOG_ACTIVE ->
            is_need_front(Pid, GodId, GodInfo, 1);
        _ -> ok
    end.
is_need_front(_Pid, _GodId, _GodInfo, Pos) when Pos > ?DEFAULT_POS -> ok;
is_need_front(Pid, GodId, GodInfo, Pos) ->
    case lists:keymember(Pos, #god.pos, GodInfo) of
        true -> is_need_front(Pid, GodId, GodInfo, Pos + 1);
        false ->
            lib_player:apply_cast(Pid, ?APPLY_CAST_STATUS, ?MODULE, god_front, [GodId, Pos])
    end.
%%--------------------------------------------------------------------
%% @doc 式神召唤出战
%%--------------------------------------------------------------------
-define(ADD_TIME, 5).  %% 套装技能-套装增加时间
%% 召唤初始化
summon_init(GodInfo) ->
    {GodInfo1, AllSuit} = get_primary_god(GodInfo),
    AllAdd = ?IF(lists:member(?SUIT_SKILL_GOD_CALL, AllSuit), ?ADD_TIME, 0),
    F1 = fun(God, Temp) ->
        NewFightingGod = new_fighting_god(God, AllAdd),
        [NewFightingGod | Temp]
    end,
    %% 恢复升序
    lists:foldl(F1, [], GodInfo1).

%% 补充新召唤上阵的式神(式神超时会移除)
summon_new_fighting_god(God, FightingGods, GodInfo) ->
    #god{id = GodId} = God,
    {GodInfo1, AllSuit} = get_primary_god(GodInfo),
    SortGodInfo = lists:keysort(#god.pos, GodInfo1),
    AllAdd = ?IF(lists:member(?SUIT_SKILL_GOD_CALL, AllSuit), ?ADD_TIME, 0),
    lists:foldr(
     fun
        (#god{id = GodIdX1}, AccFighters) when GodIdX1 == GodId -> 
            NewFightingGod = new_fighting_god(God, AllAdd),
            [NewFightingGod | AccFighters];
        (#god{id = GodIdX2}, AccFighters) ->
            case lists:keyfind(GodIdX2, #god_fighting.id, FightingGods) of
                FightingGod = #god_fighting{} ->
                    [FightingGod | AccFighters];
                _ -> AccFighters
            end
     end, [], SortGodInfo).

new_fighting_god(God, AllAdd) ->
    #god{god_attr = FightAttr, id = Id, skills = FightSkills, suit_skills = FightSuitSkills} = God,
    Time = data_god:get_kv(god_summon_time),
    FightAtt = case lists:keyfind(?ATT, 1, FightAttr) of
                   {_, GodAtt} -> GodAtt;
                   _ -> 0
               end,
    FightDef = case lists:keyfind(?DEF, 1, FightAttr) of
                   {_, GodDef} -> GodDef;
                   _ -> 0
               end,
    FightHp = case lists:keyfind(?HP, 1, FightAttr) of
                  {_, GodHp} -> GodHp;
                  _ -> 0
              end,
    OneAdd = lists:sum([?ADD_TIME || SuitSkillId <- FightSuitSkills, SuitSkillId =:= ?SUIT_SKILL_GOD_CALL_ONE]),
    #god_fighting{
        id = Id
        , att    = round(FightAtt)
        , def    = round(FightDef)
        , hp     = round(FightHp)
        , hp_lim = round(FightHp)
        , skills = FightSkills
        , battle_effect = FightSuitSkills
        , continue = Time + AllAdd + OneAdd
    }.
        
%% GodInfo1 :: 主战式神
%% AllSuit  :: 主战&援助的式神套装技能
get_primary_god(GodInfo) ->
    %% 升序排列
    SortGodInfo = lists:keysort(#god.pos, GodInfo),
    F = fun
            (#god{pos = Pos, suit_skills = SuitSkills} = God, {TempGod, Temp})
                when ?IS_PRIMARY_GOD(Pos) ->    % 主战
                {[God | TempGod], SuitSkills ++ Temp};
            (#god{pos = Pos, suit_skills = SuitSkills}, {TempGod, Temp})
                when ?IS_SECONDARY_GOD(Pos) ->  % 辅助式神只提供套装技能
                {TempGod, SuitSkills ++ Temp};
            (_, {TempGod, Temp}) -> {TempGod, Temp}
        end,
    %% 变为倒序, 且筛选出来只有主战的了
    {GodInfo1, AllSuit} = lists:foldl(F, {[], []}, SortGodInfo),
    {GodInfo1, AllSuit}.

%% 玩家主动召唤式神
god_summon(Player, GodId) ->
    #player_status{role_god = RoleGod} = Player,
    case god_check:check_god_summon(Player, RoleGod, GodId) of
        {false, Err} -> {false, Err};
        {ok, NewRoleGod, SummonType} ->
            Player1 = do_god_summon(Player#player_status{role_god = NewRoleGod}, GodId, SummonType),
            {ok, Player1}
    end.

%% 手动召唤上阵
do_god_summon(Player, GodId, SummonType) ->
    Player1 = role_switch_god(Player, GodId),
    #player_status{id = RoleId, scene = Scene, scene_pool_id = PoolId, role_god = AfterSwitch} = Player1,
    GodSummon = AfterSwitch#role_god.god_summon,
    case SummonType of
        first_summon -> %% 首次召唤
            mod_scene_agent:apply_cast(Scene, PoolId, god_api, scene_summon_god, [RoleId, GodId, GodSummon#god_summon.fighters]);
        exist_summon -> %% 召唤已上阵的
            mod_scene_agent:apply_cast(Scene, PoolId, god_api, scene_summon_exist_god, [RoleId, GodId]);
        new_summon -> %% 召唤新的或者已过时被移除的
            FightingGod = lists:keyfind(GodId, #god_fighting.id, GodSummon#god_summon.fighters),
            GodPos = get_god_pos(AfterSwitch#role_god.god_info),
            mod_scene_agent:apply_cast(Scene, PoolId, god_api, scene_summon_new_god, [RoleId, FightingGod, GodPos])
    end,
    Player1.

get_god_pos(GodInfo) ->
    lists:keysort(1, [{Pos, GodId} || #god{id = GodId, pos = Pos} <- GodInfo]).

%% 切换式神 切换的式神，如果有出战套装效果，则叠加给玩家
%% GodId 手动切换时为唤神id
role_switch_god(Player, GodId) ->
    #player_status{role_god = RoleGod, sid = Sid} = Player,
    #role_god{god_summon = GodSummon, god_info = GodInfo, temp_attr = TempAttr, summon_time = SummonTimeList} = RoleGod,
    GodCfg = data_god:get_god_info(GodId, 0),
    IsManualGod = is_record(GodCfg, base_god_info),
    NewRoleGod =
        case GodSummon of
            #god_summon{fighters = Fighters = [_ | _], ref = OldRef} when IsManualGod -> % 手动操作
                case lists:keytake(GodId, #god_fighting.id, Fighters) of
                    {value, One, T} ->
                        Now     = utime:longunixtime(),
                        NewOne  = One#god_fighting{time = Now},
                        {NewT, _Expire} = delete_god_summon(T),
                        % NewFighters  = sort_god_summon([NewOne] ++ NewT, GodInfo),
                        NewGodSummon = GodSummon#god_summon{
                            ref      = expire_ref(OldRef, NewOne),
                            fighters = [NewOne|NewT]
                        },
                        %% 一些出战才有的属性加成
                        AddAttr = get_attr_when_fighting(NewOne, GodInfo),
                        #god{pos = Pos}   = lists:keyfind(GodId, #god.id, GodInfo),
                        NewSummonTimeList = lists:keystore(Pos, 1, SummonTimeList, {Pos, round(Now/1000)}),
                        RoleGod#role_god{god_summon = NewGodSummon, summon_time = NewSummonTimeList};
                    _ ->
                        AddAttr = [],
                        RoleGod
                end;
            _ ->
                AddAttr = [],
                RoleGod#role_god{god_summon = undefined}
        end,
    case NewRoleGod#role_god.god_summon of
        #god_summon{fighters = [#god_fighting{continue = Continue, id = GodId1} | _]} ->
            GodId1, Continue;
        _ ->
            GodId1 = 0, Continue = 0
    end,
    lib_server_send:send_to_sid(Sid, pt_173, 17313, [1, GodId1, Continue]),
    Player1 = Player#player_status{role_god = NewRoleGod#role_god{temp_attr = AddAttr}},
    case AddAttr of
        TempAttr ->
            Player1;
        _ ->
            Player2 = lib_player:count_player_attribute(Player1, ?MOD_GOD, god_summon, [god_summon]),
            mod_scene_agent:update(Player2, [{battle_attr, Player2#player_status.battle_attr}]),
            Player2
    end.

%% 过滤出当前仍未召唤的唤神
delete_god_summon(Fighters) ->
    lists:foldr(fun(God, {Gods, ExpireGods}) ->
        #god_fighting{time = Time} = God, 
        if Time == 0 -> {[God|Gods], ExpireGods};
            true -> {Gods, [God|ExpireGods]}
        end
    end, {[], []}, Fighters).

%% 按照唤神上阵位置排序
% sort_god_summon(Fighters, GodInfo) ->
%     SortGodInfo = lists:keysort(#god.pos, GodInfo),
%     {_, SortFighters1} = lists:foldl(fun(#god{id = GodId}, {AccFighters, SortFighters}) -> 
%         case lists:keytake(GodId, #god_fighting.id, AccFighters) of
%             {value, God, Rest} ->
%                 {Rest, [God|SortFighters]};
%             _ -> {AccFighters, SortFighters}
%         end
%     end, {Fighters, []}, SortGodInfo),
%     lists:reverse(SortFighters1).

get_attr_when_fighting(One, GodInfo) ->
    case lists:keyfind(One#god_fighting.id, #god.id, GodInfo) of
        #god{suit_info = SuitInfo} ->
            get_suit_effect(SuitInfo, ?TYPE_SUIT_SKILL_FIGHT_ROLE);
        _ ->
            []
    end.

% 定时自动切换到下一式神
% ref_to_next_god(Ref, God) ->
%     util:cancel_timer(Ref),
%     erlang:send_after(God#god_fighting.continue * 1000, self(), {mod, ?MODULE, do_god_summon, [?GOD_SUMMON_NEXT]}).

%% 超时处理
expire_ref(Ref, God) ->
    util:send_after(Ref, God#god_fighting.continue * 1000, self(), {mod, ?MODULE, god_summon_expire, [God#god_fighting.id]}).

%% 召唤的式神超时处理
god_summon_expire(Player, GodId) ->
    #player_status{id = RoleId, scene = Scene, scene_pool_id = ScenePool, role_god = RoleGod} = Player,
    #role_god{god_summon = GodSummon, temp_attr = TempAttr} = RoleGod,
    #god_summon{fighters = FightingGods, ref = OldRef} = GodSummon,
    util:cancel_timer(OldRef),
    {NewFightingGods, _} = delete_god_summon(FightingGods),
    AddAttr = [],
    Player1 = Player#player_status{role_god = RoleGod#role_god{god_summon = GodSummon#god_summon{fighters = NewFightingGods}, temp_attr = AddAttr}},
    case TempAttr of
        AddAttr ->
            Player2 = Player1;
        _ ->
            Player2 = lib_player:count_player_attribute(Player1, ?MOD_GOD, god_summon, [god_summon]),
            mod_scene_agent:update(Player2, [{battle_attr, Player2#player_status.battle_attr}])
    end,
    mod_scene_agent:apply_cast(Scene, ScenePool, god_api, scene_god_expire, [RoleId, GodId]),
    {ok, Player2}.


%%%===================================================================
%%% @doc 式神活动-召唤(单抽/十连抽)/领取次数奖励/领取祝福值奖励
%%%===================================================================
%% 开始抽奖
god_lottery(Player, Type, IsAotuBuy) ->
    case god_check:check_god_lottery(Player, Type, IsAotuBuy) of
        {false, Err} ->
            {false, Err};
        %% 限时抽奖
        {ok, NPlayer, Phase, GodId, Cost, Award, Tv, Count, Blessing, BaseCounts, BaseBlessing} ->
            #player_status{figure = #figure{name = Name}, id = RoleId} = NPlayer,
            god_lottery:lottery(RoleId, Count, Blessing),
            Player2 = lib_goods_api:send_reward(NPlayer, Award, god_lottery),
            [lib_chat:send_TV({all}, ?MOD_GOD, 4, [Name, RoleId, GoodsId, GoodsNum]) || {GoodsId, GoodsNum} <- Tv],
            log_god_lottery([RoleId, Phase, GodId, Type, Blessing, Blessing+BaseBlessing, Count+BaseCounts, Cost, Award]),
            {ok, Player2, [{GoodsId, GoodsNum} || {_, GoodsId, GoodsNum} <- Award], Blessing}
    end.


%%%===================================================================
%%% 数据库操作
%%%===================================================================
db_get_all_god(RoleId) ->
    Sql = io_lib:format(?SELECT_ROLE_GOD_INFO, [RoleId]),
    db:get_all(Sql).

db_get_role_god(RoleId) ->
    Sql = io_lib:format(?SELECT_ROLE_GOD, [RoleId]),
    db:get_row(Sql).

to_save_one_god(LogType, RoleId, God) ->
    case LogType of
        ?LOG_SUIT -> ignore;
        ?LOG_EQUIP_UP -> ignore;
        ?LOG_GOD_FRONT -> ignore;
        _ ->
            db_save_one_god(RoleId, God)
    end.

db_save_one_god(RoleId, God) ->
    #god{
        id = GodId,                 % 式神id
        star = Star,                % 式神星级
        lv = Lv,                    % 式神等级
        exp = Exp,                  % 式神经验
        pos = Pos,                  % 出战位置：0未出战|1-99为出战位置|101-9999为援护位置
        skills = Skills            % 技能等级[{skill_id, lv}|_]
    } = God,
    Sql = io_lib:format(?REPLACE_INTO_ROLE_GOD_INFO,
        [RoleId, GodId, Star, Lv, Exp, Pos, util:term_to_bitstring(Skills)]),
    db:execute(Sql),
    ok.

%% 在有事务字典情况下使用
save_one_god_on_transaction(RoleId, God) ->
    #god{
        id = GodId,                 % 式神id
        star = Star,                % 式神星级
        lv = Lv,                    % 式神等级
        exp = Exp,                  % 式神经验
        pos = Pos,                  % 出战位置：0未出战|1-99为出战位置|101-9999为援护位置
        skills = Skills             % 技能等级[{skill_id, lv}|_]
    } = God,
    Sql = io_lib:format(?REPLACE_INTO_ROLE_GOD_INFO,
        [RoleId, GodId, Star, Lv, Exp, Pos, util:term_to_bitstring(Skills)]),
    goods_transaction:add_sql(Sql).

db_save_role_god(RoleId, RoleGod) ->
    #role_god{unlock = Unlock} = RoleGod,
    Sql = io_lib:format(?REPLACE_INTO_ROLE_GOD,
        [RoleId, util:term_to_bitstring(Unlock)]),
    db:execute(Sql).

operate_log([RoleId, RoleName, GodId, OpType, OldStar, Star, OldLv, Lv, Exp, Skill, Cost]) ->
    lib_log_api:log_god_operate([RoleId, RoleName, GodId, OpType, OldStar, Star, OldLv, Lv, Exp, util:term_to_bitstring(Skill), util:term_to_bitstring(Cost)]).

log_god_equip_upgrade([RoleId, GoodsId, GodId, Cell, Type, OldLv, Lv, OldExp, Exp, Cost, AddExp]) ->
    lib_log_api:log_god_equip_upgrade([RoleId, GoodsId, GodId, Cell, Type, OldLv, Lv, OldExp, Exp, util:term_to_bitstring(Cost), AddExp, utime:unixtime()]).

log_god_lottery([RoleId, Phase, GodId, OpType, AddBlessing, Blessing, Counts, Cost, Award]) ->
    lib_log_api:log_god_lottery([RoleId, Phase, GodId, OpType, AddBlessing, Blessing, Counts, util:term_to_bitstring(Cost), util:term_to_bitstring(Award), utime:unixtime()]).

gm_reset(Player) ->
    #player_status{role_god = RoleGod} = Player,
    Player#player_status{role_god = RoleGod#role_god{summon_time = god_api:init_god_summon_time(RoleGod#role_god.god_info)}}.

god_reset(Status) ->
    #player_status{sid = Sid, role_god = RoleGod} = Status,
    % #role_god{god_summon = GodSummon} = RoleGod,
    % GodSummon /= undefined andalso util:cancel_timer(GodSummon#god_summon.ref),
    NewSummonTimeList = god_api:init_god_summon_time(RoleGod#role_god.god_info),
    lib_server_send:send_to_sid(Sid, pt_173, 17312, [NewSummonTimeList]),
    Status#player_status{role_god = RoleGod#role_god{summon_time = NewSummonTimeList, god_summon = undefined}}.
