%%%-------------------------------------------------------------------
%%% @author liushl
%%% @copyright (C) 2020, <COMPANY>
%%% @doc
%%%     本服BOSS
%%% @end
%%% Created : 24. 2月 2020 11:46
%%%-------------------------------------------------------------------
-module(local_boss_api).
-author("liushl").

-include("scene.hrl").
-include("def_event.hrl").
-include("rec_event.hrl").
-include("server.hrl").
-include("def_module.hrl").
-include("local_boss.hrl").
-include("battle.hrl").
-include("attr.hrl").
-include("figure.hrl").
-include("attr.hrl").
-include("predefine.hrl").
-include("def_act_label.hrl").
-include("guild.hrl").
-include("language.hrl").
-include("def_fun.hrl").
-include("errcode.hrl").
-include("team.hrl").
-include("def_goods.hrl").
-include("drop.hrl").
-include("common.hrl").
-include("skill.hrl").
-include("daily.hrl").
-include("deserted_boss.hrl").
-include("goods.hrl").
-include("recharge_act.hrl").
-include("rec_recharge.hrl").
%% API
-export([
    login/1,                            %% 登陆初始化
    handle_event/2,                     %% 事件处理
    change_scene_callback/4,            %% 离开BOSS场景
    leave_scene_auto_pick_up/3,
    one_local_boss_die/2,               %% 一只BOSS死亡了
    is_forbid_battle/3,                 %% 赏金BOSS场景判断能否战斗
    mon_is_forbid_attack_man/2,         %% 赏金BOSS是否禁止攻击玩家
    get_reward_boss_tired/1,            %% 获得赏金BOSS疲劳值
    get_deserted_boss_tired/1,          %% 获得废都BOSS疲劳值
    reward_boss_is_tired/1,             %% 玩家是否疲劳了
    deserted_boss_is_tired/1,           %% 废都BOSS是否疲劳
    clean_reward_boss_tired/1,          %% 清除赏金BOSS疲劳值
    cost_reward_boss_daily_count/2,     %% 赏金BOSS消耗次数
    update_reward_boss_daily_info/1,    %% 上线更新奖励次数
    get_daily_used/1,                   %% 赏金BOSS今日次数
    update_act_label/5,                 %% 更改玩家头顶标识
    user_team_change/2,                 %% 玩家队伍信息变更
    successful_enter_reward_boss/4,
    ask_enter_boss_scene/3,
    focus_check/2,
    notify_boss_tired/2,
    %% BOSS场景判断
    is_local_boss_scene_type/1,
    is_local_boss_scene/1,
    is_world_boss_scene_type/1,
    is_world_boss_scene/1,
    is_reward_boss_scene_type/1,
    is_reward_boss_scene/1,
    is_deserted_boss_scene_type/1,
    is_deserted_boss_scene/1,
    is_deserted_mon_tried/2,
    is_home_boss_scene_type/1,
    is_home_boss_scene/1,
    is_allow_fly_shoes/1,
    check_can_use_protect_time/1,
    save_db_protect_time/3,
    is_rb_protect_time/2,
    is_deb_protect_time/2,
    waiting_for_protect_time_over/4,
    update_protect_time/3,
    protect_time_over/2,

    check_role_num_limit/3,

    restat_hurt_list/2,
    %% 活动BOSS
    act_boss_enter/3,
    enter_act_boss/3,
    %% BOSS场景处理
    send_tv/2,                           %% BOSS传闻
    %% 废都幻魔
    deserted_boss_enter/3,
    use_goods_cut_tired/3,              %% 使用幻魔次数卡
    use_goods_refresh_boss/3,           %% 使用幻魔刷新卡
    kill_player/5,
    cls_kill_player_logic/6,
    broad_cast_kill_tv/1,
    role_join_team_cancel_support/1,
    leave_boss_distance_trigger/3,      %% 脱离boss范围触发协助取消
    calc_boss_crush_r/3,

    %% 幻魔之家
    enter_home_boss/3,

    plus_inspire_count/3,
    kill_boss_refresh_ta_data/3,

    notice_goods_drop/3,

    gm_change_boss_scene/2
]).

%% 登陆初始化
login(Player) ->
    #player_status{id = RoleId} = Player,
    Tired = update_reward_boss_daily_info(RoleId),
    FocusL = db:get_all(?SQL_GET_BOSS_FOCUS, [RoleId]),
    BossFocus = lists:foldl(fun([BossId, BossType], Acc) ->
        case lists:keyfind(BossType, 1, Acc) of
            {_, TypeFocusL} ->
                lists:keystore(BossType, 1, Acc, {BossType, [BossId|TypeFocusL]});
            _ ->
                [{BossType, [BossId]}|Acc]
        end
    end, [], FocusL),
    CountL = [{?MOD_DESERTED_BOSS, ?DEFAULT_SUB_MODULE, 1}, {?MOD_DESERTED_BOSS, ?DEFAULT_SUB_MODULE, 2}],
    [{_, DesertedBossTired}, {_, DesertedEliteTired}|_] = lib_daily:get_count(RoleId, CountL),
    StatusBoss = #status_local_boss{
        reward_boss_tired = Tired,
        boss_focus = BossFocus,
        deserted_boss_tired = DesertedBossTired,
        deserted_elite_tired = DesertedEliteTired
    },
    NewPlayer = login_protect_time(Player#player_status{local_boss = StatusBoss}),
    NewPlayer.

%% 事件处理:进入boss场景 通知BOSS管理进程
%% 如果我是来协助别人的，那就到公会管理去找到被协助者
handle_event(Player = #player_status{scene = SceneId, id = RoleId, scene_pool_id = BossId},
    #event_callback{type_id = ?EVENT_FIN_CHANGE_SCENE}) ->
    case data_scene:get(SceneId) of
        #ets_scene{type = ?SCENE_TYPE_WORLD_BOSS} ->
            is_integer(BossId) andalso
                begin
                    world_boss_mgr:enter_scene(RoleId, BossId),
                    notice_boss_id(Player)
                end,
            Player1 = Player;
        #ets_scene{type = ?SCENE_TYPE_REWARD_BOSS} ->
            #player_status{
                battle_attr = #battle_attr{attr = Attr},
                figure = #figure{lv = Lv},
                combat_power = Power
            } = Player,
            is_integer(BossId)
                andalso begin
                            reward_boss_mgr:enter_scene(RoleId, BossId),
                            notice_boss_id(Player)
                        end,
            %% 疲劳标识
            LeftCount = lib_counter:get_count(RoleId, ?MOD_LOCAL_BOSS, ?COUNT_REWARD_BOSS_COUNTER_KILL, BossId),
            IsTired = reward_boss_is_tired(Player),
            LeftCount > 0 andalso IsTired andalso
                lib_scene:change_scene_act_label(Player, ?ACT_LABEL_BOSS_TIRED, 1),
            %% 添加BOSS碾压系数
            CrushPower = get_reward_boss_crush_power(?MON_REWARD_BOSS, BossId, Power),
            CrushAttr  = get_reward_boss_crush_attr(?MON_REWARD_BOSS, BossId, Attr),
            CrushLv    = get_reward_boss_crush_lv(?MON_REWARD_BOSS, BossId, Lv),
            CrushR     = CrushPower + CrushAttr + CrushLv,
            %% 如果是首杀，则可以默认可以打
            case LeftCount =:= 0 andalso IsTired of
                true  ->
                    Arg = [{boss_tired, 0}];
                false ->
                    Arg = []
            end,
            mod_scene_agent:update(Player, Arg ++ [{boss_crush_r, 1 + CrushR}]),
            Player1 = refresh_enter_scene_time(Player, ?MON_REWARD_BOSS);
        #ets_scene{type = ?SCENE_TYPE_DESERTED_BOSS} ->
            Player1 = refresh_enter_scene_time(Player, ?MON_DESERTED_BOSS);
        #ets_scene{type = ?SCENE_TYPE_HOME_BOSS} ->
            Player1 = refresh_enter_scene_time(Player, ?MON_HOME_BOSS);
        _ ->
            Player1 = Player
    end,
    %% 更新免战时间
    {ok, NewPlayer} = change_scene_update_protect_time(Player1),
    {ok, NewPlayer};

%% 战力变更
handle_event(Player = #player_status{id = RoleId, combat_power = Power}, #event_callback{type_id = ?EVENT_COMBAT_POWER}) ->
    world_boss_mgr:refresh_power(RoleId, Power),
    {ok, Player};

%% 四点重置
handle_event(Player, #event_callback{type_id = ?EVENT_FOUR_CLOCK}) ->
    NewPlayer = clean_reward_boss_tired(Player),
    {ok, NewPlayer};

%% 取消协助
handle_event(Player, #event_callback{type_id = ?EVENT_CANCEL_SUPPORT}) ->
    #player_status{scene = Scene, id = RoleId, scene_pool_id = BossId} = Player,
    is_reward_boss_scene(Scene) andalso
        is_integer(BossId) andalso
        reward_boss_mgr:role_cancel_support(RoleId, BossId),
    {ok, Player};

%% 拾取掉落
handle_event(Player, #event_callback{type_id = ?EVENT_DROP_CHOOSE,
    data = #{mon_id := MonId, goods := [{_, GoodsId, Num}|_] = DropReward, scene := DropSceneId}}) ->
    #player_status{scene = SceneId, figure = #figure{guild_id = GuildId, name = Name}, id = RoleId} = Player,
    %% BOSS拾取的橙色品质物品上墙
    IsDesertedBossScene = local_boss_api:is_deserted_boss_scene(SceneId),
    IsHomeBossScene     = is_home_boss_scene(SceneId),
    if
        IsDesertedBossScene ->
            ta_agent_fire:equip_get(Player, GoodsId, 4),
            deserted_boss_mgr:add_mon_drop_log(RoleId, config:get_server_num(), Name, SceneId, MonId, DropReward);
        IsHomeBossScene ->
            %% 掉落判断
            ta_agent_fire:equip_get(Player, GoodsId, 5),
            SubModule = home_boss_mgr:mon_sub_module_type(MonId),
            #mon{name = BossName} = data_mon:get(MonId),
            case data_goods_type:get(GoodsId) of
                #ets_goods_type{type = ?GOODS_TYPE_EQUIP, color = Color} when Color >= ?PURPLE ->
                    lib_chat:send_TV({all}, ?MOD_HOME_BOSS, 1, [Name, RoleId, BossName, GoodsId]);
                #ets_goods_type{color = Color} when Color >= ?ORANGE ->
                    lib_chat:send_TV({all}, ?MOD_HOME_BOSS, 1, [Name, RoleId, BossName, GoodsId]);
                _ -> skip
            end,
            home_boss_mgr:add_mon_drop_log(SubModule, [RoleId, GuildId, Name, SceneId, MonId, DropReward]);
        true ->
            case data_mon:get(MonId) of
                #mon{boss = Boss} when Boss =:= ?MON_REWARD_BOSS
                    orelse Boss == ?MON_DESERTED_BOSS
                    orelse Boss == ?MON_DESERTED_ELITE
                    orelse Boss == ?MON_DUN_BOSS ->
                    case Boss of
                        ?MON_REWARD_BOSS  ->
                            ta_agent_fire:equip_get(Player, GoodsId, 2);
                        ?MON_DUN_BOSS ->
                            ta_agent_fire:equip_get(Player, GoodsId, 3);
                        _ ->
                            ok
                    end,
                    
                    case data_goods_type:get(GoodsId) of
                        #ets_goods_type{color = Color} when Color >= ?ORANGE ->
                            Log = #boss_drop_log{
                                name = Name
                                , svr_num = 0
                                , scene = DropSceneId
                                , boss = MonId
                                , boss_type = Boss
                                , goods_id = GoodsId
                                , time = utime:unixtime()
                            },
                            reward_boss_mgr:add_reward_boss_drop_log(Log);
                        _ ->
                            ok
                    end;
                _ ->
                    ok
            end
    end,
    notice_goods_drop(Player, DropSceneId, [{GoodsId, Num}]),
    {ok, Player};

%% 复活
handle_event(Player, #event_callback{type_id = ?EVENT_REVIVE, data = 3}) ->
    #player_status{
        scene = Scene, scene_pool_id = ScenePoolId, last_be_kill = KillerInfo,
        x = X, y = Y, id = RoleId, copy_id = CopyId} = Player,
    IsRewardBossScene   = is_reward_boss_scene(Scene),
    IsDesertedBossScene = is_deserted_boss_scene(Scene),
    IsHomeBossScene     = is_home_boss_scene(Scene),
    Node = node(),
    if
        IsRewardBossScene andalso is_integer(ScenePoolId) ->
            reward_boss_mgr:revive(RoleId, ScenePoolId),
            Player1 = refresh_revive_count(Player, ?MON_REWARD_BOSS);
        IsDesertedBossScene ->
            case lists:keyfind(mid, 1, KillerInfo) of
                {_, MonId} -> ok;
                _ -> MonId = 0
            end,
            case lists:keyfind(sign, 1, KillerInfo) of
                {_, Sign} -> ok;
                _ -> Sign = 0
            end,
            MonId > 0 andalso Sign == ?BATTLE_SIGN_MON andalso
                deserted_boss_mgr:revive(MonId, RoleId, Node, Scene, ScenePoolId, CopyId, X, Y),
            Player1 = refresh_revive_count(Player, ?MON_DESERTED_BOSS);
        IsHomeBossScene ->
            Player1 = refresh_revive_count(Player, ?MON_HOME_BOSS);
        true ->
            Player1 = Player
    end,
    {ok, Player1};

%% 复活处理
handle_event(Player, #event_callback{type_id = ?EVENT_REVIVE, data = 1}) ->
    #player_status{scene = Scene, scene_pool_id = ScenePoolId, copy_id = CopyId,
         id = RoleId, last_be_kill = KillerInfo, x = X, y = Y} = Player,
    IsDesertedBossScene = is_deserted_boss_scene(Scene),
    IsRewardBossScene   = is_reward_boss_scene(Scene),
    IsHomeBossScene     = is_home_boss_scene(Scene),
    if
        IsDesertedBossScene ->
            case lists:keyfind(mid, 1, KillerInfo) of
                {_, MonId} -> ok;
                _ -> MonId = 0
            end,
            case lists:keyfind(sign, 1, KillerInfo) of
                {_, Sign} -> ok;
                _ -> Sign = 0
            end,
            MonId > 0 andalso Sign == ?BATTLE_SIGN_MON andalso
                deserted_boss_mgr:revive(MonId, RoleId, node(), Scene, ScenePoolId, CopyId, X, Y),
            Player1 = refresh_revive_count(Player, ?MON_DESERTED_BOSS);
        IsRewardBossScene ->
            Player1 = refresh_revive_count(Player, ?MON_REWARD_BOSS);
        IsHomeBossScene ->
            Player1 = refresh_revive_count(Player, ?MON_HOME_BOSS);
        true ->
            Player1 = Player
    end,
    {ok, Player1};

%% 离线
handle_event(Player, #event_callback{type_id = ?EVENT_DISCONNECT}) ->
    #player_status{scene = Scene, scene_pool_id = ScenePoolId, id = RoleId} = Player,
    case is_reward_boss_scene(Scene) of
        true when is_integer(ScenePoolId)  ->
            reward_boss_mgr:leave_scene(RoleId, ScenePoolId);
        _ ->
            ok
    end,
    {ok, NewPlayer} = clean_shield(Player),
    {ok, NewPlayer};

%% 成功击杀BOSS-有获得奖励才算
handle_event(Player, #event_callback{type_id = ?EVENT_KILL_LOCAL_BOSS, data = [BossId, IsFirstKill]}) ->
    case data_mon:get(BossId) of
        #mon{boss=?MON_REWARD_BOSS}->
            lib_custom_act_slices:task_event(Player,?MOD_LOCAL_BOSS,3),
            IsFirstKill =/= 1 andalso
                lib_activitycalen_api:role_success_end_activity(Player#player_status.id, ?MOD_LOCAL_BOSS, 3),
            custom_act_journey:trigger_act_task(Player,boss,1),
            lib_role_legion:trigger_task(Player, ?MOD_LOCAL_BOSS, 3),
            Player1 = equipment_logic:kill_reward_boss(Player),
            Player2 = boss_first_blood_logic:boss_die(Player1, BossId),
            custom_act_mobilize:update_mobilize_task(Player2, killboss, 1),
            {ok, Player2};
        #mon{boss=?MON_WORLD_BOSS}->
            {ok, Player1} = lib_achievement_api:kill_world_boss_event(Player, 1),
            mod_hi_point:success_end(Player#player_status.id, ?MOD_LOCAL_BOSS, 2),
            custom_act_adventure:do_trigger_adventure_task(Player#player_status.id, ?MOD_LOCAL_BOSS, 2),
            lib_activitycalen_api:role_success_end_activity(Player#player_status.id, ?MOD_LOCAL_BOSS, 2),
            lib_custom_act_slices:task_event(Player1,?MOD_LOCAL_BOSS, 2),
            custom_act_days_plan:update_days_plan_task(Player#player_status.id,5,1),
            {ok, Player1};
        _->
            {ok, Player}
    end;

%% 世界BOSS最后一击
handle_event(Player, #event_callback{type_id = ?EVENT_WORLD_BOSS_LAST_HIT}) ->
    {ok, Player1} = lib_achievement_api:world_boss_last_att_event(Player, 1),
    {ok, Player1};

%% 赏金BOSS参与击杀-不管有没有获得奖励和扣次数
handle_event(Player, #event_callback{type_id = ?EVENT_REWARD_BOSS_PART}) ->
    Player1 = lib_child_task:finish_kill_reward_boss(Player),
    {ok, Player2} = lib_achievement_api:kill_reward_boss_event(Player1, 1),
    lib_task_api:kill_boss(Player, 3),
    contract_task_api:kill_reward_boss_trigger(Player#player_status.id, 1),
    phantom_task_api:kill_reward_boss_trigger(Player),
    mod_hi_point:success_end(Player#player_status.id, ?MOD_LOCAL_BOSS, 3),
    custom_act_adventure:do_trigger_adventure_task(Player#player_status.id, ?MOD_LOCAL_BOSS, 3),
    {ok, Player2};

handle_event(Player, _) ->
    {ok, Player}.

%% BOSS场景切换
change_scene_callback(Player, {OldSceneId, OldScenePoolId, OldCopyId, _OldX, _OldY}, OldSceneData, NewSceneInfo) ->
    #player_status{id = RoleId} = Player,
    RewardBossScene = is_reward_boss_scene(OldSceneData),
    NewRewardBossScene = is_reward_boss_scene(NewSceneInfo),
    if
        RewardBossScene  -> %% 赏金boss场景切出
            %% 如果有未拾取的掉落，则帮玩家捡起来
            mod_drop:pick_all(node(), RoleId, OldSceneId, OldScenePoolId, OldCopyId, undefined),
            reward_boss_mgr:leave_scene(RoleId, OldScenePoolId),
            %% 清理BUFF
            {ok, Player1} = lib_skill_buff:clean_buff(Player, ?SP_SKILL_BUFF_ENCOURAGE),
            Player2 = change_out_boss_scene(Player1, ?MON_REWARD_BOSS),
            case NewRewardBossScene of
                true  ->
                    %% 从赏金BOSS切入另一个赏金BOSS，不需要重复加锁了
                    NewPlayer = Player2;
                false ->
                    case NewSceneInfo of
                        #ets_scene{type = ?SCENE_TYPE_DUNGEON} -> %% 赏金boss切个人boss,不需要加锁了
                           NewPlayer = Player2;
                        _ ->
                            NewPlayer = lib_player:break_action_lock(Player2, ?ERRCODE(err460_in_reward_boss))
                    end
            end;
        not RewardBossScene andalso NewRewardBossScene -> %% 切入赏金boss场景
            NewPlayer = lib_player:setup_action_lock(Player, ?ERRCODE(err460_in_reward_boss));
        true -> %% 和boss无关
            DesertedBossScene = is_deserted_boss_scene(OldSceneData),
            NewDesertedBossScene = is_deserted_boss_scene(NewSceneInfo),
            HomeBossScene     = is_home_boss_scene(OldSceneData),
            NewHomeBossScene  = is_home_boss_scene(NewSceneInfo),
            if
                DesertedBossScene andalso not NewDesertedBossScene -> %% 切出星域幻魔
                    NewPlayer = change_out_boss_scene(Player, ?MON_DESERTED_BOSS);
                HomeBossScene andalso not NewHomeBossScene ->
                    NewPlayer = change_out_boss_scene(Player, ?MON_HOME_BOSS);
                true ->
                    NewPlayer = Player
            end
    end,
    {ok, NewPlayer}.

%% 玩家离开场景自动发放未捡起的掉落
leave_scene_auto_pick_up(RoleId, SceneId, Award) ->
    case is_reward_boss_scene(SceneId) of
        true  ->
            Info = [{Id, Num} || {_, Id, Num} <- Award],
            lib_server_send:send_to_uid(RoleId, pt_460, 46022, [Info]);
        false ->
            ok
    end.

%% 玩家队伍信息变更
user_team_change(Player, OldTeamId) ->
    #player_status{id = RoleId, scene_pool_id = BossId, scene = Scene, team = Team, figure = #figure{guild_id = GuildId}} = Player,
    IsRewardBossScene = is_reward_boss_scene(Scene),
    IsDesertedBossScene = is_deserted_boss_scene(Scene),
    IsHomeBossScene     = is_home_boss_scene(Scene),
    if
        IsRewardBossScene  ->
            reward_boss_mgr:team_change(BossId, RoleId, Team#status_team.team_id, Team#status_team.leader_name);
        IsDesertedBossScene ->
            deserted_boss_mgr:team_change(RoleId, Scene, Team#status_team.team_id, Team#status_team.leader_name);
        IsHomeBossScene ->
            SubModule = home_boss_mgr:mod_sub_module_type_by_scene(Scene),
            home_boss_mgr:team_change(SubModule, [RoleId, GuildId, Scene, Team#status_team.team_id, Team#status_team.leader_name]);
        true ->
            act_boss_mgr:team_change(RoleId, Team#status_team.team_id, Team#status_team.leader_name)
    end,
    if IsRewardBossScene orelse IsDesertedBossScene ->
            if OldTeamId == 0 andalso Team#status_team.team_id =/= 0 -> %% 加入新队伍
                    case is_support_boss(Player) of
                        true -> 
                            lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, role_join_team_cancel_support, []);
                        _ -> skip
                    end;
                true -> skip
            end;
        true -> skip
    end.

%% 赏金&星域幻魔入队取消协助
role_join_team_cancel_support(Player) ->
    NewPlayer = lib_guild_support_mod:cancel_support(Player),
    {ok, NewPlayer}.

%% 是否处于星域幻魔协助或者赏金幻魔协助
is_support_boss(Player) ->
    case lib_guild_support_mod:role_is_supporting(Player) of
        true ->
            #player_status{guild = StatusGuild} = Player,
            #status_guild{support_cfg_id = SupportCfgId} = StatusGuild,
            %% 处于星域幻魔&赏金幻魔协助中
            SupportCfgId == 4 orelse SupportCfgId == 1;
        false ->
            false
    end.

%% 一只BOSS死亡了：处于BOSS管理进程
one_local_boss_die(_BossType, BossId) ->
    case _BossType of
        ?MON_REWARD_BOSS ->
            case data_local_boss:get_reward_boss_info(BossId) of
                #base_reward_boss_info{boss_scene = SceneId} ->
                    mod_scene_agent:apply_cast_scene_user(SceneId, BossId, 0, lib_guild_support_mod, finish_normal_game_play, [none]);
                _ ->
                    skip
            end;
        _ ->
            skip
    end,
    ok.

%% 更改玩家头顶标识
update_act_label(RoleId, Scene, PoolId, LabelId, Status) when is_integer(RoleId) ->
    lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, update_act_label, [Scene, PoolId, LabelId, Status]);
update_act_label(#player_status{scene = Scene, scene_pool_id = PoolId} = Player, Scene, PoolId, LabelId, Status) ->
    lib_scene:change_scene_act_label(Player, LabelId, Status),
    Player;
update_act_label(Player, _Scene, _PoolId, _LabelId, _Status) ->
    Player.

notice_boss_id(Player) ->
    #player_status{sid = Sid, scene_pool_id = BossId} = Player,
    {ok, Bin} = pt_460:write(46023, [BossId]),
    lib_server_send:send_to_sid(Sid, Bin).
%%%-------------------------------------------------------------------
%%% @doc 请求进入BOSS场景
%%%-------------------------------------------------------------------
ask_enter_boss_scene(Player, BossId, Force) ->
    #player_status{scene = SceneId, scene_pool_id = ScenePoolId} = Player,
    MonInfo = data_mon:get(BossId),
    if
        not is_record(MonInfo, mon) -> ignore;
        ScenePoolId =:= BossId -> ignore;
        true ->
            IsRewardBoss = ?ERRCODE(err460_in_reward_boss),
            IsDesertedBossScene = is_deserted_boss_scene(SceneId),
            case lib_scene:is_transferable(Player) of
                {true, _Success} ->
                    ask_enter_boss_scene_do(Player, MonInfo, Force);
                {false, IsRewardBoss} when (MonInfo#mon.boss =:= ?MON_REWARD_BOSS orelse MonInfo#mon.boss =:= ?MON_WORLD_BOSS)
                 andalso (not IsDesertedBossScene) ->
                    ask_enter_boss_scene_do(Player, MonInfo, Force);
                {false, Err} ->
                    if Err == IsRewardBoss andalso IsDesertedBossScene ->
                            {false, ?ERRCODE(err461_pls_quit_scene)};
                        true ->
                            {false, Err}
                    end
            end
    end.
ask_enter_boss_scene_do(Player, #mon{boss = ?MON_REWARD_BOSS, id = BossId}, Force) ->
    #player_status{figure = #figure{lv = Lv}, id = RoleId} = Player,
    case data_local_boss:get_reward_boss_info(BossId) of
        #base_reward_boss_info{enter_lv = EnterLv} ->
            case Lv < EnterLv of
                true  ->
                    {false, ?ERRCODE(err460_no_lv)};
                false ->
                    reward_boss_mgr:ask_enter_reward_boss_scene(RoleId, BossId, Force),
                    ok
            end;
        _ ->
            ok
    end;
ask_enter_boss_scene_do(Player, #mon{boss = ?MON_WORLD_BOSS, id = BossId}, _Force) ->
    #player_status{figure = #figure{lv = Lv}} = Player,
    case data_local_boss:get_world_boss_info(BossId) of
        #base_world_boss_info{boss_lv = EnterLv, boss_scene = SceneId} ->
            case Lv < EnterLv of
                true  ->
                    {false, ?ERRCODE(err460_no_lv)};
                false ->
                    case check_role_num_limit(SceneId, BossId, ?BOSS_SCENE_ROLE_NUM) of
                        true  ->
                            {true, lib_scene:change_scene(Player, SceneId, BossId, 0, 0, 0, [])};
                        Others ->
                            Others
                    end
            end;
        _ ->
            ok
    end;
ask_enter_boss_scene_do(_, _, _Force) -> ok.

%% 判断能否进入
check_role_num_limit(SceneId, PoolId, MaxNum) ->
    case ets:lookup(?SCENE_ROLE_COUNT, {SceneId, PoolId}) of
        [#scene_role_count{num = RoleCount}] when MaxNum > RoleCount ->
            true;
        _ ->
            {false, ?ERRCODE(err460_too_many_roles)}
    end.

%% 成功进入赏金BOSS场景
%% 强制进入：一般是协助进去
successful_enter_reward_boss(Player, Scene, BossId, true) ->
    Player1 = lib_scene:change_scene(Player, Scene, BossId, 0, []),
    Player1;
%% 非强制，则判断次数
successful_enter_reward_boss(Player, Scene, BossId, _) ->
    %% 如果是第一次，则可以进去
    Count = lib_counter:get_count(Player#player_status.id, ?MOD_LOCAL_BOSS, ?COUNT_REWARD_BOSS_COUNTER_KILL, BossId),
    Res =
        case Count =:= 0 of
            true  ->
                {true, Player};
            false ->
                enter_reward_boss_check_buy(Player)
        end,
    case Res of
        {false, Error} ->
            {ok, Bin} = pt_460:write(46016, [Error, BossId]),
            lib_server_send:send_to_sid(Player#player_status.sid, Bin),
            Player;
        {true, Player1} ->
            Player2 = lib_scene:change_scene(Player1, Scene, BossId, 0, []),
            Player2
    end.

enter_reward_boss_check_buy(Player) ->
    case reward_boss_is_tired(Player) of
        true  ->
            DailyBuy = lib_daily:get_count(Player#player_status.id, ?MOD_LOCAL_BOSS, ?COUNT_REWARD_BOSS_BUY),
            Cfg = data_local_boss:get_local_boss_kv(reward_boss_count_recovery),
            case lists:keyfind(DailyBuy + 1, 1, Cfg) of
                {_, Price} ->
                    case lib_goods_api:cost_object_list_with_check(Player, [{?TYPE_BGOLD, 0, Price}], reward_buy, "") of
                        {true, Player1, _} ->
                            #player_status{local_boss = LocalBoss, id = RoleId, figure = #figure{name = RoleName}} = Player,
                            #status_local_boss{reward_boss_tired = Tired} = LocalBoss,
                            %% 使用次数-1
                            NewTired = Tired - 1,
                            lib_daily:increment(Player#player_status.id, ?MOD_LOCAL_BOSS, ?COUNT_REWARD_BOSS_BUY),
                            lib_daily:set_count(RoleId, ?MOD_LOCAL_BOSS, ?COUNT_REWARD_BOSS_DAILY_USE, NewTired),
                            LocalBoss1 = LocalBoss#status_local_boss{reward_boss_tired = NewTired},
                            Player2 = Player1#player_status{local_boss = LocalBoss1},
                            lib_log_api:log_boss_change([RoleId, RoleName, ?MON_REWARD_BOSS, NewTired, Tired, 2, 0, utime:unixtime()]),
                            {true, Player2};
                        {false, Error, _} ->
                            {false, Error}
                    end;
                _ ->
                    {false, ?ERRCODE(err460_buy_count_limit)}
            end;
        false ->
            %% 有次数直接进
            {true, Player}
    end.

%%%-------------------------------------------------------------------
%%% @doc 赏金BOSS逻辑处理
%%%-------------------------------------------------------------------
%% 赏金BOSS场景判断能否战斗：这里只判断疲劳值和协助状态
is_forbid_battle(Aer, Der, EtsScene) ->
    case EtsScene of
        #ets_scene{type = SceneType} when SceneType == ?SCENE_TYPE_REWARD_BOSS
         orelse SceneType == ?SCENE_TYPE_DESERTED_BOSS ->
            #battle_status{sign = InitAerSign, boss = AerBoss} = Aer,
            #battle_status{sign = DerSign, boss = DerBoss} = Der,
            AerSign = mod_battle:calc_real_sign(InitAerSign),
            case {AerSign, DerSign} of
                {?BATTLE_SIGN_PLAYER, ?BATTLE_SIGN_MON} -> %% 人打怪：疲劳不足，不能打BOSS
                    mon_is_forbid_attack_man(Aer, DerBoss);
                {?BATTLE_SIGN_MON, ?BATTLE_SIGN_PLAYER} -> %% 怪打人：受击者非协助时，如果疲劳不足，不能被攻击
                    mon_is_forbid_attack_man(Der, AerBoss);
                _ ->
                    false
            end;
        _ ->
            false
    end.

%% 赏金&废都BOSS是否禁止攻击玩家：怪物禁止攻击玩家，同样玩家也禁止攻击怪物
mon_is_forbid_attack_man(#ets_scene_user{support_id = AerSId, support_team = AerSTeam, boss_tired = AerBossTired,unite_buffs=UniteBuffs}, ?MON_REWARD_BOSS) ->
    compare_parameter(?MON_REWARD_BOSS, AerSId, AerSTeam, AerBossTired,UniteBuffs);
mon_is_forbid_attack_man(#battle_status{support_id = AerSId, support_team = AerSTeam, boss_tired = AerBossTired,unite_buffs=UniteBuffs}, ?MON_REWARD_BOSS) ->
    compare_parameter(?MON_REWARD_BOSS, AerSId, AerSTeam, AerBossTired,UniteBuffs);

mon_is_forbid_attack_man(#ets_scene_user{support_id = AerSId, support_team = AerSTeam, deserted_boss_tired = {AerBossTired, AerEliteTired},unite_buffs=UniteBuffs}, BossType)
 when BossType == ?MON_DESERTED_BOSS orelse BossType == ?MON_DESERTED_ELITE ->
    compare_parameter(BossType, AerSId, AerSTeam, {AerBossTired, AerEliteTired},UniteBuffs);
mon_is_forbid_attack_man(#battle_status{support_id = AerSId, support_team = AerSTeam, deserted_boss_tired = {AerBossTired, AerEliteTired},unite_buffs=UniteBuffs}, BossType)
 when BossType == ?MON_DESERTED_BOSS orelse BossType == ?MON_DESERTED_ELITE ->
    compare_parameter(BossType, AerSId, AerSTeam, {AerBossTired, AerEliteTired},UniteBuffs);

mon_is_forbid_attack_man(_, _) ->
    false.

compare_parameter(?MON_REWARD_BOSS, AerSId, AerSTeam, AerBossTired,UniteBuffs) ->
    Buffs  = maps:get(boss_refresh,UniteBuffs,[{?MON_REWARD_BOSS,0}]),
    {_,Add}  = lists:keyfind(?MON_REWARD_BOSS,1,Buffs),
    AerSId =:= 0 andalso AerSTeam =:= 0 andalso is_max_tired(AerBossTired,Add);

compare_parameter(BossType, AerSId, AerSTeam, {AerBossTired, AerEliteTired},UniteBuffs)
 when BossType == ?MON_DESERTED_BOSS orelse BossType == ?MON_DESERTED_ELITE ->
    Buffs  = maps:get(boss_refresh,UniteBuffs,[{?MON_DESERTED_BOSS,0}]),
    {_,Add} = lists:keyfind(?MON_DESERTED_BOSS,1,Buffs),
    IsTired = ?IF(BossType == ?MON_DESERTED_BOSS,
        is_deserted_boss_tired(AerBossTired,Add), is_deserted_elite_tired(AerEliteTired)
    ),
    AerSId =:= 0 andalso AerSTeam =:= 0 andalso IsTired.

%% 获得赏金BOSS疲劳值
get_reward_boss_tired(Player) ->
    ExtraTimes = lib_daily:get_count(Player#player_status.id, ?MOD_LOCAL_BOSS, 0, ?COUNT_REWARD_BOSS_TOTAL_TIMES),
    Player#player_status.local_boss#status_local_boss.reward_boss_tired - ExtraTimes.

%% 获得废都BOSS疲劳值
get_deserted_boss_tired(Player) ->
    #player_status{local_boss = #status_local_boss{
        deserted_boss_tired = BossTired,
        deserted_elite_tired = EliteTired
    }} = Player,
    {BossTired, EliteTired}.

%% 玩家是否疲劳了
reward_boss_is_tired(Player) ->
    Add = custom_unite_buff:check_times(Player,boss_refresh,?MON_REWARD_BOSS),
    is_max_tired(get_reward_boss_tired(Player),Add).

deserted_boss_is_tired(Player) ->
    Add = custom_unite_buff:check_times(Player,boss_refresh,?MON_DESERTED_BOSS),
    is_tired_limit(get_deserted_boss_tired(Player),Add).

is_max_tired(Tired,Add)->
    Max = data_local_boss:get_local_boss_kv(reward_boss_count)+Add,
    Tired >= Max.

is_tired_limit({BossTired, _EliteTired},Add) ->
    is_deserted_boss_tired(BossTired,Add).

is_deserted_mon_tried(?MON_DESERTED_BOSS, {BossTired, _EliteTired}) ->
    is_deserted_boss_tired(BossTired);
is_deserted_mon_tried(?MON_DESERTED_ELITE, {_BossTired, EliteTired}) ->
    is_deserted_elite_tired(EliteTired);
is_deserted_mon_tried(_, _) ->
    false.

is_deserted_boss_tired(BossTired) ->
    is_deserted_boss_tired(BossTired,0).
is_deserted_boss_tired(BossTired,Add) ->
    BossLimit = data_deserted_boss:get_kv(feidu_boss_times)+Add,
    BossTired >= BossLimit.

is_deserted_elite_tired(EliteTired) ->
    EliteLimit = data_deserted_boss:get_kv(feidu_elite_times),
    EliteTired >= EliteLimit.

%% 清除赏金BOSS疲劳值
clean_reward_boss_tired(Player) ->
    LocalBoss = Player#player_status.local_boss,
    NewPlayer = Player#player_status{
     local_boss = LocalBoss#status_local_boss{
        reward_boss_tired = 0,
        deserted_boss_tired = 0,
        deserted_elite_tired = 0}
    },
    notify_boss_tired(all, NewPlayer),
    NewPlayer.

%% 赏金BOSS消耗次数
cost_reward_boss_daily_count(Player, BossId) ->
    #player_status{id = RoleId, figure = #figure{name = RoleName}, local_boss = LocalBoss} = Player,
    #status_local_boss{reward_boss_tired = OldTired} = LocalBoss,
    LeftCount = lib_counter:get_count(RoleId, ?MOD_LOCAL_BOSS, ?COUNT_REWARD_BOSS_COUNTER_KILL, BossId),
    %% 赏金BOSS每日击杀次数，统计用
    lib_daily:increment(RoleId, ?MOD_LOCAL_BOSS, ?COUNT_REWARD_BOSS_DAILY_KILL),
    case LeftCount =:= 0 of
        true  ->
            %% 首杀不扣次数
            lib_counter:increment(RoleId, ?MOD_LOCAL_BOSS, ?COUNT_REWARD_BOSS_COUNTER_KILL, BossId),
            lib_log_api:log_boss_change([RoleId, RoleName, ?MON_REWARD_BOSS, OldTired, OldTired, 4, BossId, utime:unixtime()]),
            Player;
        false ->
            UniteNum  = custom_unite_buff:check_times(Player,boss_refresh,?MON_REWARD_BOSS),
            case UniteNum>0 of
                true->%%优先扣除
                    custom_unite_buff:cost_times(Player,boss_refresh,?MON_REWARD_BOSS),
                    custom_unite_buff:scene_cost_times(Player,boss_refresh,?MON_REWARD_BOSS),
                    lib_log_api:log_boss_change([RoleId, RoleName, ?MON_REWARD_BOSS, OldTired, OldTired, 5, BossId, utime:unixtime()]),
                    Player;
                _->
                    %% 疲劳值+1
                    NewTired = OldTired + 1,
                    lib_daily:set_count(RoleId, ?MOD_LOCAL_BOSS, ?COUNT_REWARD_BOSS_DAILY_USE, NewTired),
                    LocalBoss1 = LocalBoss#status_local_boss{reward_boss_tired = NewTired},
                    Player1 = Player#player_status{local_boss = LocalBoss1},
                    notify_boss_tired(boss_tired, Player1),
                    %% 疲劳标识
                    reward_boss_is_tired(Player1) andalso
                        lib_scene:change_scene_act_label(Player, ?ACT_LABEL_BOSS_TIRED, 1),
                    lib_log_api:log_boss_change([RoleId, RoleName, ?MON_REWARD_BOSS, NewTired, OldTired, 1, BossId, utime:unixtime()]),
                    Player1
            end
    end.


%% 上线更新奖励次数
update_reward_boss_daily_info(RoleId) ->
    {DailyAward, _TotalTimes} = get_daily_used(RoleId),
    DailyAward.

%% 赏金BOSS今日次数
get_daily_used(RoleId) ->
    [
        {_, DailyAward},
        {_, TotalTimes}
    ] =
        lib_daily:get_count(RoleId,
            [
                {?MOD_LOCAL_BOSS, 0, ?COUNT_REWARD_BOSS_DAILY_USE},
                {?MOD_LOCAL_BOSS, 0, ?COUNT_REWARD_BOSS_TOTAL_TIMES}
            ]),
    {DailyAward, TotalTimes}.

%% 疲劳值通知
notify_boss_tired(boss_tired, Player) ->
    Tired = Player#player_status.local_boss#status_local_boss.reward_boss_tired,
    mod_scene_agent:update(Player, [{boss_tired, Tired}]),
    pp_local_boss:handle(46011, Player, []);
notify_boss_tired(deserted_boss_tired, Player) ->
    {BossTired, EliteTired} = get_deserted_boss_tired(Player),
    mod_scene_agent:update(Player, [{deserted_boss_tired, {BossTired, EliteTired}}]),
    {ok, BinData} = pt_461:write(46102, [BossTired, EliteTired]),
    lib_server_send:send_to_sid(Player#player_status.sid, BinData);
notify_boss_tired(all, Player) ->
    notify_boss_tired(boss_tired, Player),
    notify_boss_tired(deserted_boss_tired, Player).

%% 赏金BOSS属性碾压
get_reward_boss_crush_attr(?MON_REWARD_BOSS, BossId, Attr) ->
    AttrList = attr_conv:to_attr_tuple_list(Attr),
    BaseAttrList = lib_player_attr:get_list_base_attr_kv(AttrList),
    case data_local_boss:get_reward_boss_info(BossId) of
        #base_reward_boss_info{recommend_attr = CrushAttr} ->
            get_attr_crush(BaseAttrList, CrushAttr);
        _ -> 0
    end;
get_reward_boss_crush_attr(?MON_DESERTED_BOSS, BossId, Attr) ->
    AttrList = attr_conv:to_attr_tuple_list(Attr),
    BaseAttrList = lib_player_attr:get_list_base_attr_kv(AttrList),
    case data_deserted_boss:get_boss_cfg(BossId) of
        #base_deserted_boss_info{recommend_attr = CrushAttr} ->
            get_attr_crush(BaseAttrList, CrushAttr);
        _ -> 0
    end;
get_reward_boss_crush_attr(BossType, BossId, Attr) when
 BossType == ?MON_HOME_BOSS orelse BossType == ?MON_HOME_GBOSS ->
    AttrList = attr_conv:to_attr_tuple_list(Attr),
    BaseAttrList = lib_player_attr:get_list_base_attr_kv(AttrList),
    SubModule = home_boss_mgr:mon_sub_module_type(BossId),
    case data_home_boss:get_boss_info(SubModule, BossId) of
        #base_home_boss{recommend_attr = CrushAttr} ->
            get_attr_crush(BaseAttrList, CrushAttr);
        _ -> 0
    end;
get_reward_boss_crush_attr(_, _, _) -> 0.

%% 获得属性碾压
get_attr_crush(_BaseAttrList, []) -> 0;
get_attr_crush([], _CrushAttr) -> 0;
get_attr_crush(BaseAttrList, CrushAttr) ->
    [{AttrId, AttrVal}|_] = CrushAttr,
    CrushAttr1 = [{AttrId, AttrVal}],
    Fun1 = fun({Key, Val}, CalcList)->
        case lists:keyfind(Key, 1, BaseAttrList) of
            {_, SumVal} when SumVal < Val ->
                DiffRatio = (Val - SumVal) / Val,
                [{Key, DiffRatio} | CalcList];
            _ -> CalcList
        end
           end,
    case lists:foldl(Fun1, [], CrushAttr1) of
        [] -> 0;
        List -> get_attr_crush_r(List, 0)
    end.
get_attr_crush_r([], Ratio) -> Ratio;
get_attr_crush_r([{Key, DiffRatio} | T], Ratio) ->
    case data_local_boss:get_reward_boss_crush_attr(Key, DiffRatio) of
        [] -> get_attr_crush_r(T, Ratio);
        CrushR -> get_attr_crush_r(T, Ratio + CrushR)
    end.

%% 赏金&废都BOSS等级碾压
get_reward_boss_crush_lv(_, BossId, RoleLv) ->
    case data_mon:get(BossId) of
        #mon{lv = MonLv} when RoleLv < MonLv->
            data_local_boss:get_reward_boss_crush_lv(RoleLv, MonLv - RoleLv);
        _ -> 0
    end.

%% 赏金&废都BOSS战力碾压
get_reward_boss_crush_power(?MON_REWARD_BOSS, BossId, CombatPower) ->
    case data_local_boss:get_reward_boss_info(BossId) of
        #base_reward_boss_info{recommend_power = RecommendPower} when RecommendPower > 0 ->
            DiffRatio = (RecommendPower - CombatPower) / RecommendPower,
            case data_local_boss:get_reward_boss_crush_power(DiffRatio) of
                [] -> 0;
                CrushR when DiffRatio > 0 -> CrushR;
                _ -> 0
            end;
        _ -> 0
    end;
get_reward_boss_crush_power(?MON_DESERTED_BOSS, BossId, CombatPower) ->
    case data_deserted_boss:get_boss_cfg(BossId) of
        #base_deserted_boss_info{recommend_power = RecommendPower} when RecommendPower > 0 ->
            DiffRatio = (RecommendPower - CombatPower) / RecommendPower,
            case data_local_boss:get_reward_boss_crush_power(DiffRatio) of
                [] -> 0;
                CrushR when DiffRatio > 0 -> CrushR;
                _  -> 0
            end;
        _ -> 0
    end;
get_reward_boss_crush_power(BossType, BossId, CombatPower) when BossType == ?MON_HOME_BOSS orelse
 BossType== ?MON_HOME_GBOSS ->
    SubModule = home_boss_mgr:mon_sub_module_type(BossId),
    case data_home_boss:get_boss_info(SubModule, BossId) of
        #base_home_boss{recommend_power = RecommendPower} when RecommendPower > 0 ->
            DiffRatio = (RecommendPower - CombatPower) / RecommendPower,
            case data_local_boss:get_reward_boss_crush_power(DiffRatio) of
                [] -> 0;
                CrushR when DiffRatio > 0 -> CrushR;
                _  -> 0
            end;
        _ -> 0
    end;
get_reward_boss_crush_power(_, _, _) -> 0.

calc_boss_crush_r(BossType, BossId, [RolePower, RoleLv, RoleAttr]) ->
    CrushPower = get_reward_boss_crush_power(BossType, BossId, RolePower),
    CrushAttr  = get_reward_boss_crush_attr(BossType, BossId, RoleAttr),
    CrushLv    = get_reward_boss_crush_lv(BossType, BossId, RoleLv),
    CrushR     = 1 + CrushPower + CrushAttr + CrushLv,
    CrushR.


%% 怪物进程调用
restat_hurt_list(Boss = ?MON_REWARD_BOSS, State) ->
    reward_boss_mgr:re_statistics_hurt_list_by_team(Boss, State);
restat_hurt_list(?MON_DESERTED_BOSS, State) ->
    deserted_boss_mgr:restat_when_hurt_change(State);
restat_hurt_list(?MON_HOME_BOSS, State) ->
    home_boss_mgr:restat_when_hurt_change(State);
restat_hurt_list(?MON_HOME_GBOSS, State) ->
    home_boss_mgr:restat_when_hurt_change(State);
restat_hurt_list(_, State) ->
    State.

leave_boss_distance_trigger(LeaveIds, BossType, MonId) ->
    if BossType == ?MON_DESERTED_BOSS orelse BossType == ?MON_DESERTED_ELITE ->
            deserted_boss_mgr:leave_boss_distance_trigger(LeaveIds, BossType, MonId);
        true ->
            skip
    end.


%%%-------------------------------------------------------------------
%%% @doc BOSS对外接口
%%%-------------------------------------------------------------------
%% 是否BOSS场景
is_local_boss_scene_type(SceneType) ->
    SceneType =:= ?SCENE_TYPE_WORLD_BOSS orelse SceneType =:= ?SCENE_TYPE_REWARD_BOSS orelse SceneType == ?SCENE_TYPE_DESERTED_BOSS.

is_local_boss_scene(SceneId) when is_integer(SceneId) ->
    is_local_boss_scene(data_scene:get(SceneId));
is_local_boss_scene(Scene) ->
    check_scene(Scene, ?SCENE_TYPE_WORLD_BOSS) orelse
    check_scene(Scene, ?SCENE_TYPE_REWARD_BOSS) orelse
    check_scene(Scene, ?SCENE_TYPE_DESERTED_BOSS) orelse
    check_scene(Scene, ?SCENE_TYPE_HOME_BOSS).

%% 是否世界BOSS场景
is_world_boss_scene_type(SceneType) -> SceneType =:= ?SCENE_TYPE_WORLD_BOSS.
is_world_boss_scene(SceneId) when is_integer(SceneId)  ->
    is_world_boss_scene(data_scene:get(SceneId));
is_world_boss_scene(Scene) ->
    check_scene(Scene, ?SCENE_TYPE_WORLD_BOSS).

%% 是否赏金BOSS场景
is_reward_boss_scene_type(SceneType) -> SceneType =:= ?SCENE_TYPE_REWARD_BOSS.
is_reward_boss_scene(SceneId) when is_integer(SceneId)  ->
    is_reward_boss_scene(data_scene:get(SceneId));
is_reward_boss_scene(Scene) ->
    check_scene(Scene, ?SCENE_TYPE_REWARD_BOSS).

%% 是否是废都BOSS场景
is_deserted_boss_scene_type(SceneType) -> SceneType == ?SCENE_TYPE_DESERTED_BOSS.
is_deserted_boss_scene(SceneId) when is_integer(SceneId) ->
    is_deserted_boss_scene(data_scene:get(SceneId));
is_deserted_boss_scene(Scene) ->
    check_scene(Scene, ?SCENE_TYPE_DESERTED_BOSS).

is_home_boss_scene_type(SceneType) -> SceneType == ?SCENE_TYPE_HOME_BOSS.
is_home_boss_scene(SceneId) when is_integer(SceneId) ->
    is_home_boss_scene(data_scene:get(SceneId));
is_home_boss_scene(Scene) ->
    check_scene(Scene, ?SCENE_TYPE_HOME_BOSS).

check_scene(#ets_scene{type = SceneType}, SceneType) -> true;
check_scene(_, _) -> false.

%% =================================================================================
%% @doc 免战时间 @end
%% =================================================================================
%% 是否保护时间内
is_rb_protect_time(Player, Now) ->
    #player_status{scene = SceneId, reb_protect_time = NewProtectTime} = Player,
    is_reward_boss_scene(SceneId) andalso NewProtectTime > Now.

is_deb_protect_time(Player, Now) ->
    #player_status{scene = SceneId, deb_protect_time = NewProtectTime} = Player,
    is_deserted_boss_scene(SceneId) andalso NewProtectTime > Now.

%% 登录初始化时间
login_protect_time(Player) ->
    Sql = io_lib:format(?SQL_GET_BOSS_PROTECT_TIME, [Player#player_status.id]),
    case db:get_all(Sql) of
        [_|_] = InfoList ->
            NowTime = utime:unixtime(),
            F = fun(Info, {TRBTime, TDBTime}) ->
                case Info of
                    [BossType, ProtectTime] when ProtectTime > NowTime ->
                        case BossType of
                            1 -> {ProtectTime, TDBTime};
                            _ -> {TRBTime, ProtectTime}
                        end;
                    _ -> {TRBTime, TDBTime}
                end end,
            {RBTime, DBTime} = lists:foldl(F, {0, 0}, InfoList),
            Player#player_status{reb_protect_time = RBTime, deb_protect_time = DBTime};
        _ ->
            Player
    end.

save_db_protect_time(RoleId, BossType, ProtectTime) ->
    Sql = io_lib:format(?SQL_SAVE_BOSS_PROTECT_TIME, [RoleId, BossType, ProtectTime]),
    db:execute(Sql),
    ok.

%% 检查是否可以使用免战
check_can_use_protect_time(Player) ->
    #player_status{recharge_act_status = RechargeAct} = Player,
    #recharge_act_status{welfare = Welfare} = RechargeAct,
    ProductIds = [Id || #recharge_goods{product_id = Id} <- Welfare],
    ExistId = lists:foldl(fun(Id, Exist) ->
        case data_recharge:get_product(Id) of
            #base_recharge_product{product_type = 2, product_subtype = ProductType}
                when ProductType == 2 orelse ProductType == 3 ->
                Id;
            _ ->
                Exist
        end end, 0, ProductIds),
    case ExistId > 0 of
        true->
            true;
        _ ->
            false
    end.

%% 切换场景后更新免战时间
change_scene_update_protect_time(#player_status{scene = SceneId} = Player) ->
    %% 判断场景是赏金/星域幻魔才更新
    case data_scene:get(SceneId) of
        #ets_scene{type = SceneType} -> ok;
        _ -> SceneType = 0
    end,
    case lists:member(SceneType, [?SCENE_TYPE_REWARD_BOSS, ?SCENE_TYPE_DESERTED_BOSS]) of
        true ->
            NowTime = utime:unixtime(),
            RebProtectTime = Player#player_status.reb_protect_time,
            DebProtectTime = Player#player_status.deb_protect_time,
            RebRef = waiting_for_protect_time_over([], RebProtectTime, NowTime, ?REWARD_BOSS_PROTECT_TIME),
            DebRef = waiting_for_protect_time_over([], DebProtectTime, NowTime, ?DESERTED_BOSS_PROTECT_TIME),
            Player1 =
            case RebProtectTime > NowTime of
                true -> local_boss_api:update_protect_time(Player, RebProtectTime, ?REWARD_BOSS_PROTECT_TIME);
                _ when RebProtectTime =/= 0 ->
                    local_boss_api:update_protect_time(Player, 0, ?REWARD_BOSS_PROTECT_TIME);
                _ -> Player
            end,
            Player2 =
            case DebProtectTime > NowTime of
                true -> local_boss_api:update_protect_time(Player1, DebProtectTime, ?DESERTED_BOSS_PROTECT_TIME);
                _ when DebProtectTime =/= 0 ->
                    local_boss_api:update_protect_time(Player1, 0, ?DESERTED_BOSS_PROTECT_TIME);
                _ -> Player1
            end,
            {ok, Player2#player_status{reb_protect_ref = RebRef, deb_protect_ref = DebRef}};
        _ ->
            {ok, Player}
    end.

%% 等待免战时间结束
waiting_for_protect_time_over(Ref, ProtectTime, Now, Type) ->
    util:cancel_timer(Ref),
    TimeGap = ProtectTime - Now,
    case TimeGap > 0 of
        false  -> [];
        true   ->
            erlang:send_after(TimeGap*1000, self(), {mod, ?MODULE, protect_time_over, [Type]})
    end.
protect_time_over(Player, Type) ->
    update_protect_time(Player, 0, Type).

update_protect_time(Player, NewProtectTime, Type) ->
    #player_status{
        id = RoleId,
        scene = Scene, copy_id = CopyId,
        scene_pool_id = ScenePoolId, x = X, y = Y
    } = Player,
    %% 判断场景是赏金/星域幻魔才更新
    case data_scene:get(Scene) of
        #ets_scene{type = SceneType} -> ok;
        _ -> SceneType = 0
    end,
    case lists:member(SceneType, [?SCENE_TYPE_REWARD_BOSS, ?SCENE_TYPE_DESERTED_BOSS]) of
        true ->
            case Type of
                ?REWARD_BOSS_PROTECT_TIME ->
                    {ok, Bin} = pt_120:write(12016, [?MOD_LOCAL_BOSS, 1, RoleId, NewProtectTime]),
                    lib_server_send:send_to_area_scene(Scene, ScenePoolId, CopyId, X, Y, Bin),
                    NewProtectTime == 0 andalso lib_server_send:send_to_uid(RoleId, pt_460, 46035, [1]),
                    mod_scene_agent:update(Player, [{reb_protect_time, NewProtectTime}]),
                    Player#player_status{reb_protect_time = NewProtectTime};
                _ ->
                    {ok, Bin} = pt_120:write(12016, [?MOD_DESERTED_BOSS, 1, RoleId, NewProtectTime]),
                    lib_server_send:send_to_area_scene(Scene, ScenePoolId, CopyId, X, Y, Bin),
                    NewProtectTime == 0 andalso lib_server_send:send_to_uid(RoleId, pt_461, 46113, [1]),
                    mod_scene_agent:update(Player, [{deb_protect_time, NewProtectTime}]),
                    Player#player_status{deb_protect_time = NewProtectTime}
            end;
        _ ->
            Player
    end.

%% 离线取消定时器
clean_shield(Player) ->
    #player_status{reb_protect_ref = RebRef, deb_protect_ref = DebRef} = Player,
    util:cancel_timer(RebRef),
    util:cancel_timer(DebRef),
    {ok, Player#player_status{reb_protect_ref = [], deb_protect_ref = []}}.

%% =================================================================================

%% BOSS传闻
send_tv(Type, Arg) ->
    case Type of
        reward_boss_reborn ->
            lib_chat:send_TV({all}, ?MOD_LOCAL_BOSS, ?LAN_TV_REWARD_BOSS_REBORN, Arg);
        world_boss_max_hurt ->
            lib_chat:send_TV({all}, ?MOD_LOCAL_BOSS, ?LAN_TV_WORLD_BOSS_MAX_HURT, Arg);
        world_boss_last_hit ->
            lib_chat:send_TV({all}, ?MOD_LOCAL_BOSS, ?LAN_TV_WORLD_BOSS_LAST_HIT, Arg);
        reward_boss_max_hurt_role ->
            lib_chat:send_TV({all}, ?MOD_LOCAL_BOSS, ?LAN_TV_REWARD_BOSS_MAX_HURT_ROLE, Arg);
        reward_boss_max_hurt_team ->
            lib_chat:send_TV({all}, ?MOD_LOCAL_BOSS, ?LAN_TV_REWARD_BOSS_MAX_HURT_TEAM, Arg);
        world_boss_shield_award ->
            lib_chat:send_TV({all}, ?MOD_LOCAL_BOSS, ?LAN_TV_WORLD_BOSS_SHIELD_AWARD, Arg);
        world_boss_assists_award ->
            lib_chat:send_TV({all}, ?MOD_LOCAL_BOSS, ?LAN_TV_WORLD_BOSS_ASSISTS_AWARD, Arg);
        reward_boss_extra_award ->
            lib_chat:send_TV({all}, ?MOD_LOCAL_BOSS, ?LAN_TV_REWARD_BOSS_EXTRA_AWARD, Arg);
        _ ->
            ok
    end.

focus_check(#base_reward_boss_info{enter_lv = EnterLv}, Lv) ->
    Lv >= EnterLv;
focus_check(#base_deserted_boss_info{level = Level}, Lv) ->
    case data_deserted_boss:get_level(Level) of
        #base_deserted_level{open_lv = OpenLv} ->
            Lv >= OpenLv;
        _ ->
            false
    end;
focus_check(_, _Lv) ->
    false.


%% 只有场景内的协助者可以使用飞鞋
is_allow_fly_shoes(Player) ->
    #player_status{scene = SceneId, guild = StatusGuild} = Player,
    case StatusGuild of
        #status_guild{is_in_support = 1, is_support_asker = 0} ->
            case is_deserted_boss_scene(SceneId) of
                true ->
                    true;
                _ ->
                    false
            end;
        _ ->
            false
    end.

%%%-------------------------------------------------------------------
%%% @doc 活动BOSS接口
%%%-------------------------------------------------------------------
act_boss_enter(RoleId, SceneId, PoolId) ->
    lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, enter_act_boss, [SceneId, PoolId]).

enter_act_boss(#player_status{scene = SceneId, scene_pool_id = PoolId} = Player, SceneId, PoolId) ->
    Player;
enter_act_boss(Player, SceneId, PoolId) ->
    case ets:lookup(?SCENE_ROLE_COUNT, {SceneId, PoolId}) of
        [#scene_role_count{num = RoleCount}] ->
            case RoleCount >= ?BOSS_SCENE_ROLE_NUM of
                true  ->
                    Error = ?ERRCODE(err120_too_many_people),
                    {ok, Bin} = pt_460:write(46028, [Error]),
                    lib_server_send:send_to_sid(Player#player_status.sid, Bin),
                    Player;
                false ->
                    lib_scene:change_scene(Player, SceneId, PoolId, 0, false, [])
            end;
        _ ->
            lib_scene:change_scene(Player, SceneId, 0, 0, [])
    end.

%% -------------------------------------------------------------------
%% @doc 废都boss/古战场boss接口
%% -------------------------------------------------------------------
-spec deserted_boss_enter(Player, MonCfg, EnterArgs) -> Ret when
    Player :: #player_status{},
    MonCfg :: #mon{} | integer(),
    EnterArgs :: list(),
    Ret    :: {true, NewPlayer} | {false, Error} | ignore | clusters,
    NewPlayer :: #player_status{},
    Error  :: integer().
deserted_boss_enter(Player, BossId, EnterArgs) ->
    #player_status{scene = SceneId, scene_pool_id = ScenePoolId} = Player,
    MonInfo = data_mon:get(BossId),
    IsDesertedBossScene = is_deserted_boss_scene(SceneId),
    if
        not is_record(MonInfo, mon) -> ignore;
        IsDesertedBossScene andalso ScenePoolId =:= BossId -> ignore;
        true ->
            IsRewardBoss = ?ERRCODE(err460_in_reward_boss),
            case lib_scene:is_transferable(Player) of
                {true, _Success} ->
                    deserted_boss_enter_do(Player, MonInfo, EnterArgs);
                {false, IsRewardBoss} when IsDesertedBossScene == true ->
                    deserted_boss_enter_do(Player, MonInfo, EnterArgs);
                {false, Err} ->
                    if Err == IsRewardBoss ->
                            {false, ?ERRCODE(err461_pls_quit_scene)};
                        true ->
                            {false, Err}
                    end
            end
    end.

deserted_boss_enter_do(Player, #mon{id = BossId}, EnterArgs) ->
    #player_status{
        id = RoleId, guild = #status_guild{support_id = _SupportSid},
        figure = #figure{lv = Lv, guild_id = GuildId}, sid = Sid
    } = Player,
    SupportSid =
    case EnterArgs of
        [support_enter,[Value, _, _]] -> Value;
        _ -> 0
    end,
    BossCfgRet = data_deserted_boss:get_boss_cfg(BossId),
    if
        not is_record(BossCfgRet, base_deserted_boss_info) ->
            {false, ?MISSING_CONFIG};
        true ->
            #base_deserted_boss_info{level = Level, born_pos = {RebornX, RebornY}} = BossCfgRet,
            BossLvRet = data_deserted_boss:get_level(Level),
            if
                not is_record(BossLvRet, base_deserted_level) ->
                    {false, ?MISSING_CONFIG};
                true ->
                    #base_deserted_level{open_lv = OpenLv, scene = SceneId, cls_scene = ClsScene} = BossLvRet,
                    if OpenLv > Lv ->
                            {false, ?ERRCODE(err460_no_lv)};
                        true ->
                            {ZoneRet, ZoneId, FacId} = deserted_boss_mgr:check_cls_deserted_boss(),
                            TarScene = ?IF(ZoneRet == true, ClsScene, SceneId),
                            SceneRet = data_scene:get(TarScene),
                            [X, Y] = lib_scene:get_born_xy(TarScene),
                            if
                                not is_record(SceneRet, ets_scene) ->
                                    {false, ?FAIL};
                                true ->
                                    %?ERR("~p ~p", [ZoneRet, SupportSid]),
                                    if
                                        not ZoneRet ->
                                            case check_role_num_limit(TarScene, 0, ?DESERTED_BOSS_NUM) of
                                                true ->
                                                    if SupportSid == 0 ->
                                                            {true, lib_scene:change_scene(Player, TarScene, 0, 0, X, Y, [])};
                                                        true ->
                                                            % RandX = RebornX + urand:rand(-200, 200),
                                                            % RandY = RebornY + urand:rand(-200, 200),
                                                            {true, lib_scene:change_scene(Player, TarScene, 0, 0, X, Y, [])}
                                                    end;
                                                Others ->
                                                    Others
                                            end;
                                        true -> %% 跨服玩法
                                            Args = [TarScene, node(), RoleId, Sid, GuildId, SupportSid, BossId, X, Y, RebornX, RebornY, EnterArgs],
                                            Msg = {enter_deserted_boss_scene, Args},
                                            {Mod, Fun, FunArgs} = {deserted_boss_mgr, cast, [ZoneId, FacId, Msg]},
                                            clusters_node:apply_cast({Mod, Fun, FunArgs}),
                                            clusters
                                    end
                            end
                    end
            end
    end.

enter_home_boss(Player, SubModule, BossId) ->
    #player_status{id = RoleId, sid = Sid, scene = NowScene, 
        figure = #figure{lv = RoleLv, vip = Vip, guild_id = GuildId}} = Player,
    ModuleOpenLv = lib_module:get_open_lv(?MOD_HOME_BOSS, SubModule),
    BossCfgRet = data_home_boss:get_boss_info(SubModule, BossId),
    IsHomeBossScene = is_home_boss_scene(NowScene),
    IsTransferable = lib_scene:is_transferable(Player),
    if RoleLv < ModuleOpenLv ->
            lib_server_send:send_to_sid(Sid, pt_462, 46204, [?ERRCODE(lv_limit), SubModule, BossId]);
        not is_record(BossCfgRet, base_home_boss) ->
            lib_server_send:send_to_sid(Sid, pt_462, 46204, [?FAIL, SubModule, BossId]);
        IsHomeBossScene ->
            ignore;
        IsTransferable =/= {true, 1} ->
            {_, ErrorCode} = IsTransferable,
            lib_server_send:send_to_sid(Sid, pt_462, 46204, [ErrorCode, SubModule, BossId]);
        true ->
        #base_home_boss{level = Level} = BossCfgRet,
            case data_home_boss:get_home_boss_level(SubModule, Level) of
                #base_home_boss_level{scene = SceneId, enter_lv = EnterLv, condition = Condition, cost = Cost} ->
                    case Condition of
                        [{vip, VipLv}|_] -> ok;
                        _ -> VipLv = 0
                    end,
                    if RoleLv < EnterLv ->
                            lib_server_send:send_to_sid(Sid, pt_462, 46204, [?ERRCODE(lv_limit), SubModule, BossId]);
                        true ->
                            Ret =
                            if 
                                Vip < VipLv andalso Cost =/= [] ->
                                    case lib_goods_api:check_object_list(Player, Cost, enter_home_boss_cost) of
                                        true -> {true, Cost};
                                        {false, ErrorCode} -> {false, ErrorCode}
                                    end;
                                Vip < VipLv ->
                                    {false, ?ERRCODE(vip_limit)};
                                true -> {true, []}
                            end,
                            case Ret of
                                {true, Cost1} ->
                                    #ets_scene{x = X, y = Y} = data_scene:get(SceneId),
                                    home_boss_mgr:enter_home_boss(SubModule, GuildId, RoleId, BossId, {SceneId, X, Y}, Cost1),
                                    ok;
                                {false, ErrorCode2} ->
                                    lib_server_send:send_to_sid(Sid, pt_462, 46204, [ErrorCode2, SubModule, BossId])
                            end
                    end;
                _ ->
                    lib_server_send:send_to_sid(Sid, pt_462, 46204, [?FAIL, SubModule, BossId])
            end
    end.

%% 使用幻魔次数卡增加总次数或减少疲劳值
use_goods_cut_tired(Player, ?BOSS_TIMES_CARD_1, GoodsNum) ->
    #player_status{id = RoleId, figure = #figure{name = RoleName}, scene = SceneId, local_boss = LocalBoss} = Player,
    lib_goods_api:cost_object_list(Player, [{0, ?BOSS_TIMES_CARD_1, GoodsNum}], goods_use, ""),
    ExtraTimes = lib_daily:get_count(RoleId, ?MOD_LOCAL_BOSS, 0, ?COUNT_REWARD_BOSS_TOTAL_TIMES),
    NewTimes = ExtraTimes + GoodsNum,
    lib_daily:set_count(RoleId, ?MOD_LOCAL_BOSS, ?COUNT_REWARD_BOSS_TOTAL_TIMES, NewTimes),
    case data_scene:get(SceneId) of
        #ets_scene{type = ?SCENE_TYPE_REWARD_BOSS} ->
            #status_local_boss{reward_boss_tired = Tired} = LocalBoss,
            mod_scene_agent:update(Player, [{boss_tired, Tired - NewTimes}]),
            lib_scene:change_scene_act_label(Player, ?ACT_LABEL_BOSS_TIRED, 0);
        _ -> skip
    end,
    lib_log_api:log_boss_change([RoleId, RoleName, ?MON_REWARD_BOSS, max(0, LocalBoss#status_local_boss.reward_boss_tired - NewTimes), LocalBoss#status_local_boss.reward_boss_tired, 3, 0, utime:unixtime()]),
    pp_local_boss:handle(46011, Player, []),
    {ok, Player, GoodsNum};
use_goods_cut_tired(Player, ?BOSS_TIMES_CARD_3, GoodsNum) ->
    #player_status{id = RoleId, figure = #figure{name = RoleName}, local_boss = LocalBoss} = Player,
    #status_local_boss{deserted_boss_tired = Tired, deserted_elite_tired = EliteTired} = LocalBoss,
    if
        Tired =< 0 ->
            {fail, ?ERRCODE(err461_has_max_times)};
        GoodsNum > Tired ->
            {fail, ?FAIL};
        true ->
            lib_goods_api:cost_object_list(Player, [{0, ?BOSS_TIMES_CARD_3, GoodsNum}], goods_use, ""),
            NTired = Tired - GoodsNum,
            lib_daily:set_count(RoleId, ?MOD_DESERTED_BOSS, 1, NTired),
            NLocalBoss = LocalBoss#status_local_boss{deserted_boss_tired = NTired},
            NPlayer = Player#player_status{local_boss = NLocalBoss},
            mod_scene_agent:update(Player, [{deserted_boss_tired, {NTired, EliteTired}}]),
            lib_log_api:log_boss_change([RoleId, RoleName, ?MON_REWARD_BOSS, max(0, NTired), Tired, 3, 0, utime:unixtime()]),
            pp_local_boss:handle(46102, NPlayer, []),
            {ok, NPlayer, GoodsNum}
    end.

%% 使用幻魔刷新卡复活幻魔 Type: 1次元幻魔 2星域幻魔
use_goods_refresh_boss(Player, Type, BossId) ->
    if
        Type == 1 ->
            RebornTime = reward_boss_mgr:get_boss_reborn_time(BossId),
            Cost = [{?TYPE_GOODS, ?BOSS_REFRESH_1, 1}],
            About = io_lib:format("~w,~w", [?BOSS_REFRESH_1, BossId]);
        true ->
            RebornTime = deserted_boss_mgr:get_boss_reborn_time(BossId),
            Cost = [{?TYPE_GOODS, ?BOSS_REFRESH_2, 1}],
            About = io_lib:format("~w,~w", [?BOSS_REFRESH_2, BossId])
    end,
    NowTime = utime:unixtime(),
    if
        RebornTime == false ->
            {?ERRCODE(err460_not_this_boss), Player};
        RebornTime < NowTime ->
            %% boss不是处于等待重生期间
            {?ERRCODE(err460_boss_not_die), Player};
        true ->
            case lib_goods_api:cost_object_list_with_check(Player, Cost, reborn_boss, About) of
                {true, NewPs, _} when Type == 1 ->
                    reward_boss_mgr:boss_revive(BossId),
                    {?SUCCESS, NewPs};
                {true, NewPs, _} ->
                    deserted_boss_mgr:boss_revive(BossId),
                    {?SUCCESS, NewPs};
                {false, ErrorCode, NewPs} ->
                    {ErrorCode, NewPs}
            end
    end.

%% 混乱星域玩家被击杀传闻
kill_player(RoleId, RoleName, AttId, AttName, AttSvrId) ->
    SvrId = config:get_server_id(),
    if SvrId == AttSvrId -> %% 本服传闻
            SvrNum = config:get_server_num(),
            broad_cast_kill_tv([SvrNum, RoleName, RoleId, SvrNum, AttName, AttId]);
        true -> %% 跨服传闻(击杀者和被击杀者)
            clusters_node:apply_cast(?MODULE, cls_kill_player_logic, [RoleId, RoleName, SvrId, AttId, AttName, AttSvrId])
    end.

cls_kill_player_logic(RoleId, RoleName, SvrId, AttId, AttName, AttSvrId) ->
    KilledSvrNum = clusters_center:find_server_num(SvrId),
    AttSvrNum    = clusters_center:find_server_num(AttSvrId),
    clusters_center:apply_cast(SvrId, {?MODULE, broad_cast_kill_tv, [[KilledSvrNum, RoleName, RoleId, AttSvrNum, AttName, AttId]]}),
    clusters_center:apply_cast(AttSvrId, {?MODULE, broad_cast_kill_tv, [[KilledSvrNum, RoleName, RoleId, AttSvrNum, AttName, AttId]]}).

broad_cast_kill_tv(TVArgs) ->
    lib_chat:send_TV({all}, ?MOD_DESERTED_BOSS, 6, TVArgs),
    ok.

gm_change_boss_scene(Status, BossLevel) ->
    case data_deserted_boss:get_level(BossLevel) of
        #base_deserted_level{} ->
            BossList     = data_deserted_boss:get_all_boss(),
            RandBossList = ulists:list_shuffle(BossList),
            BossId = calc_rand_boss(RandBossList, BossLevel),
            case pp_local_boss:handle(46106, Status, [BossId]) of
                {ok, NewStatus} ->
                    NewStatus;
                _A ->
                    ?ERR("~p", [_A]),
                    Status
            end;
        _A ->
            ?ERR("~p", [_A]),
            Status
    end.

calc_rand_boss([], _) -> 0;
calc_rand_boss([BossId|Rest], BossLevel) ->
    case data_deserted_boss:get_boss_cfg(BossId) of
        #base_deserted_boss_info{level = BossLevel} ->
            BossId;
        _ ->
            calc_rand_boss(Rest, BossLevel)
    end.

refresh_enter_scene_time(Player, BossType) ->
    Kvalues = [{?ENTER_TIME, utime:unixtime()}],
    refresh_boss_ta_data(Player, BossType, Kvalues).

change_out_boss_scene(Player, BossType = ?MON_REWARD_BOSS) ->
    Kvalues = [{?ENTER_TIME, 0}, {?REVIVE_TIME, 0}, {?INSPIRE_GOLD, 0}, {?INSPIRE_BGOLD, 0}],
    refresh_boss_ta_data(Player, BossType, Kvalues);
change_out_boss_scene(Player, BossType = ?MON_DESERTED_BOSS) ->
    Kvalues = [{?ENTER_TIME, 0}, {?REVIVE_TIME, 0}],
    refresh_boss_ta_data(Player, BossType, Kvalues);
change_out_boss_scene(Player, BossType = ?MON_HOME_BOSS) ->
    Kvalues = [{?ENTER_TIME, 0}, {?REVIVE_TIME, 0}],
    refresh_boss_ta_data(Player, BossType, Kvalues).

plus_inspire_count(Player, BossType, CountTpye) ->
    Kvalues = [{plus, CountTpye, 1}],
    refresh_boss_ta_data(Player, BossType, Kvalues).

refresh_revive_count(Player, BossType) ->
    Kvalues = [{plus, ?REVIVE_TIME, 1}],
    refresh_boss_ta_data(Player, BossType, Kvalues).

kill_boss_refresh_ta_data(Player, BossType = ?MON_REWARD_BOSS, Time) ->
    Kvalues = [{?ENTER_TIME, Time}, {?REVIVE_TIME, 0}, {?INSPIRE_GOLD, 0}, {?INSPIRE_BGOLD, 0}, {?INSPIRE_TICK, 0}],
    refresh_boss_ta_data(Player, BossType, Kvalues);
kill_boss_refresh_ta_data(Player, BossType = ?MON_DESERTED_BOSS, Time) ->
    Kvalues = [{?ENTER_TIME, Time}, {?REVIVE_TIME, 0}],
    refresh_boss_ta_data(Player, BossType, Kvalues);
kill_boss_refresh_ta_data(Player, BossType = ?MON_HOME_BOSS, Time) ->
    Kvalues = [{?ENTER_TIME, Time}, {?REVIVE_TIME, 0}],
    refresh_boss_ta_data(Player, BossType, Kvalues).

refresh_boss_ta_data(Player, BossType, Kvalues) ->
    #player_status{local_boss = StatusLocBoss} = Player,
    #status_local_boss{ta_data = BossTAData} = StatusLocBoss,
    BossData = maps:get(BossType, BossTAData, #{}),
    NewBossData = do_refresh_boss_ta_data(BossData, Kvalues),
    NewBossTAData = maps:put(BossType, NewBossData, BossTAData),
    NewStatusLocBoss = StatusLocBoss#status_local_boss{ta_data = NewBossTAData},
    Player#player_status{local_boss = NewStatusLocBoss}.

do_refresh_boss_ta_data(BossData, []) -> BossData;
do_refresh_boss_ta_data(BossData, [{plus, K, Plus}|Rest]) ->
    Count = maps:get(K, BossData, 0),
    NewBossData = maps:put(K, Count+Plus, BossData),
    do_refresh_boss_ta_data(NewBossData, Rest);
do_refresh_boss_ta_data(BossData, [{K, V}|Rest]) ->
    NewBossData = maps:put(K, V, BossData),
    do_refresh_boss_ta_data(NewBossData, Rest);
do_refresh_boss_ta_data(BossData, [_|Rest]) ->
    do_refresh_boss_ta_data(BossData, Rest).

notice_goods_drop(Player, Scene, GoodsInfo) ->
    case local_boss_api:is_reward_boss_scene(Scene) of
        true  ->
            {ok, Bin} = pt_460:write(46022, [GoodsInfo]),
            lib_server_send:send_to_sid(Player#player_status.sid, Bin);
        false ->
            ok
    end.