%% ---------------------------------------------------------------------------
%% @doc lib_team
%% @author ming_up@foxmail.com
%% @since  2016-11-01
%% @deprecated 组队库函数
%% ---------------------------------------------------------------------------
-module(lib_team).

%% 公共函数：外部模块调用.
-export([
         create_cast/5                     %% 创建队伍
        , send_to_member/2                 %% 广播给队员
        , send_to_member/5                 %% 广播给队员
        , join_player_team/2               %% 响应加入指定玩家队伍
        , send_scene_users_without_team/2  %% 场景进程调用 发送附近的人
        , get_onhook_target_type/1
        , get_max_team_member_num/2
        , calc_location/2
        , is_cls_target/2
        , get_team_cls_type/1
        , my_code_to_other_code/2   %% 将错误信息转化成给队友看的
        , calc_join_type/2
        ]).

%% 内部函数：组队服务本身调用.
-export([
         send_team_info/1              %% 向队伍所有成员发送队伍信息
        , send_team/2                  %% 向所有队员发送信息
        , send_team/3                  %% 向除了指定的队员之外的人发送信息
        , send_team/5                  %% 向符合条件队员发送信息
        , pack_member/6                %% 组装队员列表
        , send_to_uid/3                %% 发送信息给玩家
        , team_add_exp/3               %% 组队分成经验
        , update_ets_team/1            %% 更新组队进程pid缓存表
        , delete_ets_team/1            %% 移除组队进程pid缓存表
        , get_info_and_join_team/4     %% 获取信息并且回复队伍进程
        , update_mb_info/3             %% 调用member的lib_player:update_player_info/2函数
         %% , handle_barbecue_buff/2
         %% , handle_barbecue_buff/3   %% 处理篝火buff
        , handle_match_complete/1      %% 处理自动匹配完成
        , cancel_follow/2              %% 取消跟随
        , cancel_follows/2             %% 跟随目标取消跟随者的跟随
        , get_mb_scene/3               %% 获取队员信息
        , notify_team_change/6         %% 队伍成员变更提示
        , common_check/3               %% 通用检查
        , check_for_create_team/3      %% 创建检查
        , transfer_create_team_errcode/1   %% 转换错误码
        , send_ac_left_time/2          %% 发送活动剩余次数
        , lock_login/3                 %%
        , members_apply_cast/6         %% 队员远程调用
        , take_over_team/2              %% 接管队伍
        , handle_message/2              %% 处理在队伍挂起的时候积累的消息
        , make_fake_mb/2                %% 伪造一个假的队员
        , is_fake_mb/1                  %% 是否一个假的队员
        , get_team_info_bin/1           %% 序列化队伍信息
        , when_change_match_status/2    %% 修改匹配状态
        , cancel_role_match/3
        , add_role_match/3
        , role_cancel_match/1
        , role_add_match/1
        , check_can_match/3
        , update_help_counts/4
        ]).

%% 玩家进程调用
-export ([
          join_team_success/5        %% 清理申请的列表
         , set_req_team_id/2         %% 设置玩家身上的申请列表
         , auto_match_team/2         %% 自动匹配队伍
         , change_teammate_in_team/5   %% 经验加成改变
         , change_team_enlist/4      %% 组队目标改变
         , create_team_done/3        %% 创建队伍完成
         , create_team_respond/2     %% 创建队伍返回
         , create_team_respond/4     %% 创建队伍返回
         , start_arbitrate/2         %% 开始投票
         , check_start_team_target/3 %% 检查投票的条件
         , auto_arbitrate/4          %% 匹配完成后自动投票
         , cancel_role_match/1       %% 取消没有组队的玩家的匹配
         , start_arbitrate_silent/2  %% 静默匹配
         , check_for_other_match/4   %% 为特定匹配检查自己
         , update_help_type/4   %% 为特定匹配检查自己
         , update_team_flag/2        %% 更新队伍信息
         , update_team_leader_name/2
         , handle_noteam_for_match/3        %% 无队伍匹配
         , create_team/2             %% 创建队伍
         , role_check_can_match/3
         , update_help_counts_to_team/4
         , when_team_change/2
         , transfer_to_leader_scene/3
         , check_can_approach_me/4
         , transfer_to_leader_scene_do/6
         ]).

-include("common.hrl").
-include("server.hrl").
-include("scene.hrl").
-include("team.hrl").
-include("def_module.hrl").
-include("figure.hrl").
-include("activitycalen.hrl").
-include("errcode.hrl").
-include("predefine.hrl").
-include("language.hrl").
-include("goods.hrl").
-include("buff.hrl").
-include("relationship.hrl").
-include("attr.hrl").
-include("def_fun.hrl").
-include("def_event.hrl").
-include("unite.hrl").
-include("guild.hrl").
%% --------------------------------- 公共函数 ----------------------------------
%% 模块外请调用lib_team_api:create_cast/6
create_cast(ActivityId, SubTypeId, SceneId, Mbs, Args) ->
    TeamId = mod_team_create:get_new_id(),
    {ok, _} = mod_team:start([TeamId, 0, ActivityId, SubTypeId, SceneId, "", 0, 0, Mbs, Args, false]),
    TeamId.

%% 广播给队员
send_to_member(TeamId, Bin) ->
    case TeamId > 0 andalso is_binary(Bin) of
        false -> false;
        true -> mod_team:cast_to_team(TeamId, {'send_to_team', Bin})
    end.

send_to_member(TeamId, SceneId, ScenePoolId, CopyId, Bin) ->
    case TeamId > 0 andalso is_binary(Bin) of
        false -> false;
        true -> mod_team:cast_to_team(TeamId, {'send_to_team', SceneId, ScenePoolId, CopyId, Bin})
    end.

%% 队长回应申请后，玩家进入队伍
get_info_and_join_team(PS, _Uid, TeamId, IsMatching) ->
    #player_status{team = #status_team{team_id = SelfTeamId}, action_lock = Lock } = PS,
    if
        IsMatching =/= 0 andalso Lock =/= free -> skip;
        SelfTeamId == 0  ->
            Mb = lib_team_api:thing_to_mb(PS),
            mod_team:cast_to_team(TeamId, {'join_team_af_response_agree', Mb});
        true ->
            skip
    end.

%% 对方玩家进程响应12003,这里只处理本服玩家
join_player_team(PS, Mb) ->
    #status_team{team_id=TeamId} = PS#player_status.team,
    case TeamId of
        0 ->
            {ok, BinData} = pt_240:write(24016, [?ERRCODE(err240_no_team)]),
            send_to_uid(Mb#mb.node, Mb#mb.id, BinData);
        _ ->
            % mod_team:cast_to_team(TeamId, {'join_team_request', Mb})
            OpenDay = util:get_open_day(),
            mod_team:cast_to_team(TeamId, {'check_password_before_join_request', Mb, OpenDay})
    end.

%% 传送到队长位置
transfer_to_leader_scene(Player, Leader, Scene) ->
    #player_status{team=#status_team{team_id=TeamId}} = Player,
    case lib_scene:is_transferable(Player) of
        {false, Error} -> {false, Error};
        {true, 1} ->
            case lib_player:apply_cast(Leader, ?APPLY_CAST_STATUS, ?MODULE, check_can_approach_me, [Scene, TeamId, Player#player_status.id]) of
                skip -> {false, ?ERRCODE(err240_offline)};
                _ -> ok
            end
    end.

%% 在队长进程判断
check_can_approach_me(Player, Scene, TeamId, FromId) ->
    #player_status{
        team=#status_team{team_id=MyTeamId},
        scene = MyScene, scene_pool_id = PoolId,
        copy_id = CopyId, x = X, y = Y
    } = Player,
    Res =
    if
        MyTeamId =/= TeamId -> {false, ?ERRCODE(err240_member_call_overdue)};
        Scene =/= MyScene -> {false, ?ERRCODE(err240_member_call_overdue)};
        true ->
            true
    end,
    case Res of
        {false, Err} ->
            lib_server_send:send_to_uid(FromId, pt_240, 24048, [Err, 0, 0]);
        true ->
            lib_player:apply_cast(FromId, ?APPLY_CAST_STATUS, ?MODULE, transfer_to_leader_scene_do, [MyScene, PoolId, CopyId, X, Y])
    end,
    Player.

%% 回到玩家进程处理
transfer_to_leader_scene_do(#player_status{scene = Scene, scene_pool_id = PoolId, copy_id = CopyId} = Player,
    Scene, PoolId, CopyId, X, Y) ->
    lib_server_send:send_to_sid(Player#player_status.sid, pt_240, 24048, [1, X, Y]),
    ok;
transfer_to_leader_scene_do(Player, Scene, PoolId, CopyId, X, Y) ->
    case data_scene:get(Scene) of
        #ets_scene{type = ?SCENE_TYPE_OUTSIDE} ->
            %% 大世界直接传送过去
            lib_scene:change_scene(Player, Scene, PoolId, CopyId, X, Y, false, []);
        #ets_scene{type = ?SCENE_TYPE_WORLD_BOSS} ->
            %% BOSS场景直接过去
            pp_local_boss:handle(46016, Player, [PoolId]);
        #ets_scene{type = ?SCENE_TYPE_REWARD_BOSS} ->
            %% BOSS场景直接过去
            pp_local_boss:handle(46016, Player, [PoolId]);
        #ets_scene{type = ?SCENE_TYPE_DESERTED_BOSS} ->
            %% BOSS场景直接过去
            pp_local_boss:handle(46016, Player, [PoolId]);
        #ets_scene{type = ?SCENE_TYPE_GUILD} ->
            %% 公会场景
            #player_status{guild = #status_guild{id = GuildId}} = Player,
            case GuildId =:= CopyId of
                true  ->
                    pp_guild:handle(40044, Player, [?ERRCODE(err240_cannot_enter), X, Y]);
                false ->
                    lib_server_send:send_to_sid(Player#player_status.sid, pt_240, 24048, [?ERRCODE(err240_cannot_enter), X, Y])
            end;
        _ ->
            %% 其他场景不能进去
            lib_server_send:send_to_sid(Player#player_status.sid, pt_240, 24048, [?ERRCODE(err240_cannot_enter), X, Y]),
            ok
    end.
%% --------------------------------- 内部函数 ----------------------------------


%% 向队伍所有成员发送队伍信息
send_team_info(Team) ->
    send_team(Team, get_team_info_bin(Team)).

get_team_info_bin(Team) ->
    #team{
        id = TeamId, member = Members, enlist=EnList, leader_id=LeaderId,
        cls_type = ClsType, pre_num_full=PreNullFull, is_matching = IsMatching,
        lv_limit_min = LvMin, lv_limit_max = LvMax, power_limit = PowerLimit,
        password = Password
    } = Team,
    % NeedPassword = if Password == 0 -> 0; true -> 1 end, ?ERR("~p ~p", [Password, NeedPassword]),
    Data = [
        TeamId, EnList#team_enlist.activity_id, EnList#team_enlist.subtype_id, EnList#team_enlist.scene_id,
        PreNullFull, IsMatching, LvMin, LvMax, Password, PowerLimit, 0,
        pack_member(ClsType, LeaderId, Members, EnList#team_enlist.dun_id, EnList#team_enlist.activity_id, EnList#team_enlist.subtype_id)
    ],
    {ok, BinData} = pt_240:write(24010, Data),
    BinData.

%% 向所有队员发送信息
send_team(Team, Bin) ->
    F = fun(Node, MemberId) ->
        mod_team:cast_to_game(Team#team.cls_type, Node, lib_server_send, send_to_uid, [MemberId, Bin])
    end,
    [F(M#mb.node, M#mb.id)||M <- Team#team.member, not is_fake_mb(M)].

%% 向所有队员发送信息
send_team(Team, Bin, SkipId) ->
    F = fun(MemberNode, MemberId) ->
        mod_team:cast_to_game(Team#team.cls_type, MemberNode, lib_server_send, send_to_uid, [MemberId, Bin])
    end,
    [F(Node, Id)||#mb{node = Node, id = Id} = M <- Team#team.member, Id =/= SkipId andalso not is_fake_mb(M)].

send_team(Team, SceneId, ScenePoolId, CopyId, Bin) ->
    F = fun(MemberNode, MemberId) ->
                mod_team:cast_to_game(Team#team.cls_type, MemberNode, lib_server_send, send_to_uid, [MemberId, Bin])
        end,
    [F(M#mb.node, M#mb.id)||M <- Team#team.member,
                            M#mb.scene == SceneId andalso M#mb.scene_pool_id == ScenePoolId andalso M#mb.copy_id ==CopyId andalso not is_fake_mb(M)].

%% 组装队员列表
pack_member(_ClsType, LeaderId, MemberList, _DunId, _ActivityId, _SubTypeId) when is_list(MemberList) ->
    F = fun(Mb) ->
        Position = case Mb#mb.id of
           LeaderId ->
               ?TEAM_LEADER;
           _ ->
                case is_fake_mb(Mb) of
                    true ->
                        ?TEAM_FAKER;
                    _ ->
                        ?TEAM_MEMBER
                end
        end,
        {
            Mb#mb.id, Position, Mb#mb.figure, Mb#mb.help_type, Mb#mb.scene
            ,Mb#mb.join_time,Mb#mb.power, Mb#mb.online, Mb#mb.server_num
         }
    end,
    lists:map(F, MemberList).

%% 更新缓存
update_ets_team(Team) ->
    #team{id=TeamId, pid=Pid} = Team,
    ets:insert(?ETS_TEAM, #ets_team{team_id=TeamId, pid=Pid}).

delete_ets_team(TeamId) ->
    ets:delete(?ETS_TEAM, TeamId).

%% 发送信息给玩家
send_to_uid(undefined, Id, Bin) -> lib_server_send:send_to_uid(Id, Bin);
send_to_uid(Node, Id, Bin) ->
    case node() of
        Node ->
            lib_server_send:send_to_uid(Id, Bin);
        _ ->
            clusters_api:send_to_uid(Node, Id, Bin)
    end.

update_mb_info(ClsType, Mb, Args) ->
    mod_team:cast_to_game(ClsType, Mb#mb.node, lib_player, update_player_info, [Mb#mb.id, Args]).

%% 组队分成经验
team_add_exp({PlayerStatus, ExpX}, MemExp, _Llpt) ->
    gen_server:cast(PlayerStatus#player_status.pid, {'EXP', MemExp * ExpX}).


handle_match_complete(State) ->
    #team{
        id = TeamId, leader_node = LeadeNode, leader_id = LeaderId,
        enlist = #team_enlist{dun_id = DunId, activity_id = ActivityId, subtype_id = SubTypeId}
    } = State,
    case lib_team_match:get_match_mod(ActivityId, SubTypeId) of
        undefined ->
            if
                DunId > 0 ->
                    {ok, BinData} = pt_240:write(24048, [?SUCCESS, 2, ActivityId, SubTypeId, LeaderId]),
                    lib_team:send_team(State, BinData),
                    lib_player:apply_cast(LeadeNode, LeaderId, ?APPLY_CAST_STATUS, ?NOT_HAND_OFFLINE, lib_team, auto_arbitrate, [TeamId, ActivityId, SubTypeId]);
                true ->
                    ok
            end;
        Mod ->
            Mod:handle_match_complete(State)
    end.

%% 取消跟随
cancel_follow(Team, Id) ->
    #team{member=Mbs} = Team,
    NewMbs = case lists:keyfind(Id, #mb.id, Mbs) of
                 #mb{follow_id=MyFollowId, node = MyNode}=MyMb when MyFollowId > 0 ->
                     FollowMbs = case lists:keyfind(MyFollowId, #mb.id, Mbs) of
                                     false    -> Mbs;
                                     FollowMb ->
                                        Follows = lists:delete(Id, FollowMb#mb.follows),
                                        unode:apply(FollowMb#mb.node, lib_player, update_player_info, [MyFollowId, [{follows, Follows}]]),
                                        % lib_player:update_player_info(MyFollowId, [{follows, Follows}]),
                                        {ok, BinData} = pt_240:write(24024, [1, 0]),
                                        lib_team:send_to_uid(MyNode, Id, BinData),
                                        lists:keyreplace(MyFollowId, #mb.id, Mbs, FollowMb#mb{follows=Follows})
                                 end,
                     lists:keyreplace(Id, #mb.id, FollowMbs, MyMb#mb{follow_id=0});
                 _ -> Mbs
             end,
    Team#team{member=NewMbs}.

%% 取消跟踪我（Id）的人
cancel_follows(Team, Id) ->
    #team{member=Mbs} = Team,
    NewMbs = case lists:keyfind(Id, #mb.id, Mbs) of
                 #mb{follows=MyFollows, node = MyNode}=MyMb when is_list(MyFollows), MyFollows /= [] ->
                     {ok, BinData} = pt_240:write(24025, [0,0,0,0,0,0]),
                     F = fun(FollowId, TmpMbs) ->
                                 case lists:keyfind(FollowId, #mb.id, TmpMbs) of
                                     false    -> TmpMbs;
                                     FollowMb ->
                                         lib_team:send_to_uid(FollowMb#mb.node, FollowId, BinData),
                                         lists:keyreplace(FollowId, #mb.id, TmpMbs, FollowMb#mb{follow_id=0})
                                 end
                         end,
                     CleanFollowMbs = lists:foldl(F, Mbs, MyFollows),
                     unode:apply(MyNode, lib_player, update_player_info, [Id, [{follows, []}]]),
                     % lib_player:update_player_info(Id, [{follows, []}]),
                     lists:keyreplace(Id, #mb.id, CleanFollowMbs, MyMb#mb{follows=[]});
                 _ -> Mbs
             end,
    Team#team{member=NewMbs}.

%% 获取队员信息
get_mb_scene(TPS, Id, IsFollow) ->
    #player_status{id = RoleId, scene = SceneId, x = X, y = Y} = TPS,
    % IsValhallaScene = lib_valhalla_api:is_valhalla_scene(SceneId),
    if
        % IsValhallaScene ->
        %     mod_valhalla:get_mb_scene(RoleId, SceneId, X, Y, IsFollow, Id);
        true ->
            {ok, BinData} = pt_240:write(24025, [RoleId, SceneId, X, Y, IsFollow, 0]),
            lib_server_send:send_to_uid(Id, BinData)
    end.

%% 通知队伍变更消息--zzy
notify_team_change(_Node, SelfErrcode, MemberErrcode, TvId, Mb, State) ->
    #team{id=TeamId, member=MemberList} = State,
    RoleName = Mb#mb.figure#figure.name,
    %%自身提示
    case is_fake_mb(Mb) of
        false ->
            {ok, BinData} = pt_240:write(24030, [SelfErrcode]),
            lib_team:send_to_uid(Mb#mb.node, Mb#mb.id, BinData);
        _ ->
            ok
    end,
    %%其他人提示
    {ErrorCodeInt, ErrorCodeArgs} = util:parse_error_code({MemberErrcode, [RoleName]}),
    {ok, BinData1} = pt_240:write(24038, [ErrorCodeInt, ErrorCodeArgs]),
    F = fun(M)->
            case M#mb.id =/= Mb#mb.id andalso not is_fake_mb(M) of
                true ->
                    lib_team:send_to_uid(M#mb.node, M#mb.id, BinData1);
                _ ->
                    ok
            end
    end,
    lists:map(F,MemberList),
    lib_chat:send_TV({team, TeamId}, 240, TvId, [RoleName]).

%% 发送活动剩余次数--zzy
send_ac_left_time(PS,ActivityId) ->
    #player_status{ sid = Sid} = PS,
    List = data_team_ui:get_keylist_with_module(?MOD_TEAM),
    case lists:keyfind(ActivityId,1,List) of
        false-> ok;
        {_,SubId} ->
            #team_enlist_cfg{module_id = ModuleId,sub_module = SubModId} = data_team_ui:get(ActivityId,SubId),
            case ModuleId > 0 of
                true->
                    case data_activitycalen:get_ac_sub(ModuleId,SubModId) of
                        [_|_] = SubList ->
                            SubList = data_activitycalen:get_ac_sub(ModuleId,SubModId),
                            AcSub = lists:min(SubList),
                            BaseAc = data_activitycalen:get_ac(ModuleId, SubModId, AcSub),
                            NumList = data_activitycalen_m:get_extra(PS, BaseAc),
                            {_,Max,Num} = lists:keyfind(?ACTIVITY_COUNT_TYPE_NORMAL,1,NumList),
                            %%区分是否为不限
                            {Type, LeftTime} = case Max == 0 of
                                true-> {2, 0};
                                false-> {1, Max - Num}
                            end,
                            {ok, BinData} = pt_240:write(24042, [Type,LeftTime]),
                            lib_server_send:send_to_sid(Sid, BinData);
                        _ ->
                            {ok, BinData} = pt_240:write(24042, [2,0]),
                            lib_server_send:send_to_sid(Sid, BinData)
                    end;
                false->
                    {ok, BinData} = pt_240:write(24042, [2,0]),
                    lib_server_send:send_to_sid(Sid, BinData)
            end
    end.

set_req_team_id(PS, TeamId) ->
    case PS#player_status.team of
        #status_team{reqlist = ReqList} = TeamStatus ->
            case lists:member(TeamId, ReqList) of
                false ->
                    {ok, PS#player_status{team = TeamStatus#status_team{reqlist = [TeamId|ReqList]}}};
                _ ->
                    ok
            end;
        _ ->
            ok
    end.


%% ---------------------------------------------------------------------------
%% @doc 组队进程确认可以加入队伍（组队进程回调）
%% 注意！！需要调用gen_server:reply/2
-spec join_team_success(Role, From, TeamId, EnList, HelpType) ->
    ok | {ok, NewRole} when
    Role        :: #player_status{},
    From        :: tuple(),
    TeamId      :: integer(),
    EnList      :: #team_enlist{},
    HelpType    :: integer(),
    NewRole     :: #player_status{}.
%% ---------------------------------------------------------------------------
join_team_success(Role, From, TeamId, EnList, HelpType) ->
    #player_status{team = #status_team{team_id = RoleTeamId}} = Role,
    case RoleTeamId > 0 andalso RoleTeamId =/= TeamId of
        true ->
            gen_server:reply(From, {false, already_joined_team}),
            %% mod_team:cast_to_team(TeamId, {already_joined_in_another, RoleId})
            ok;
        false ->
            gen_server:reply(From, {ok}),
            join_team_success_do(Role, [TeamId, EnList, HelpType])
    end.

join_team_success_do(PS, [TeamId, EnList, HelpType]) ->
    #player_status{team = TeamStatus, id = RoleId} = PS,
    case PS#player_status.team of
        #status_team{reqlist = ReqList} = TeamStatus when is_list(ReqList) andalso length(ReqList) > 1 ->
            mod_team_enlist:clear_teams_reqlist_by_id(RoleId, lists:delete(TeamId, ReqList));
        _ ->
            ok
    end,
    mod_team_enlist:clear_role_match(RoleId),
    lib_team:send_ac_left_time(PS, EnList#team_enlist.activity_id),
    PS1 = update_help_type(PS, EnList#team_enlist.dun_id, TeamId, HelpType),
    add_team_event_listener(),
    mod_chat_agent:update(RoleId, [{team_id, TeamId}]),
    TeamStatus2 = TeamStatus#status_team{reqlist = [], match_info = []},
    {ok, PS1#player_status{team = TeamStatus2}}.

auto_match_team(PS, Args) ->
    case PS of
        #player_status{team=#status_team{team_id = TeamId}} when TeamId =:= 0 ->
            Mb = lib_team_api:thing_to_mb(PS),
            mod_team_enlist:match_next(Mb, Args);
        _ ->
            ok
    end.

handle_noteam_for_match(Player, ActivityId, SubTypeId) ->
    #player_status{
        figure = #figure{lv = Lv}, scene = Scene, scene_pool_id = ScenePoolId, x = X, y = Y
    } = Player,
    IsTask = case lists:member({ActivityId,SubTypeId},[{2,1}]) of
        true when 75=<Lv andalso Lv=<104 ->
            lib_role_task:is_during_task(10006000);
        _->
            false
    end,
    case data_team_ui:get(ActivityId, SubTypeId) of
        #team_enlist_cfg{default_lv_min = LMin, default_lv_max = LMax} ->
            TeamArgs = #team_args{
                act_id = ActivityId, act_sub_id = SubTypeId, scene_id = Scene, lev_min = LMin
                ,lev_max = LMax, join_type = 2, is_task = IsTask, leader_scene_id = Scene
                ,leader_scene_pool_id = ScenePoolId, leader_x = X, leader_y = Y
            },
            case create_team(Player, TeamArgs) of
                {ok, NewPlayer} ->
                    {ok, NewPlayer};
                _ ->
                    ok
            end;
        _ ->
            ok
    end.


%% ---------------------------------------------------------------------------
%% @doc 创建组队
-spec create_team(Player, TeamArgs) -> {false, Reason} | {ok, NewPlayer} when
    Player      :: #player_status{},
    TeamArgs    :: #team_args{},
    Reason      :: integer(),
    NewPlayer   :: #player_status{}.
%% ---------------------------------------------------------------------------
create_team(Player, TeamArgs) ->
    #player_status{figure = #figure{lv = Lv}, id = RoleId, team = TeamInfo} = Player,
    #status_team{
        team_id = OldTeamId, reqlist = ReqList, cls_create_time = LastClsCreateTime
    } = TeamInfo,
    ?IF(ReqList == [], ok, mod_team_enlist:clear_teams_reqlist_by_id(RoleId, ReqList)),
    #team_args{
        act_id = ActivityId, act_sub_id = SubTypeId, lev_min = LvMin, lev_max = LvMax
        ,is_task = IsTask
    } = TeamArgs,
    {ChooseLvError} = case data_team_ui:get(ActivityId, SubTypeId) of
        #team_enlist_cfg{default_lv_min = LMin, default_lv_max = LMax} ->
            if
                LMin > LvMin orelse LvMax < LvMin -> {true};
                LMax > 0 andalso LvMax > LMax -> {true};
                true -> {false}
            end;
        _ ->
            {false}
    end,
    CreateTime  = utime:unixtime(),
    CommonCheck = lib_team:check_for_create_team(Player, ActivityId, SubTypeId),
    OpenLv = lib_module:get_open_lv(?MOD_TEAM),
    if
        OldTeamId =/= 0 ->
            {false, ?ERRCODE(err240_in_team)};
        Lv < OpenLv ->
            {false, ?ERRCODE(err240_not_enough_lv_to_create_team)};
        ChooseLvError ->
            {false, ?ERRCODE(err240_choose_lv_error)};
        CreateTime - LastClsCreateTime < 5 ->
            {false, ?ERRCODE(err240_team_create_unfinished)};
        CommonCheck =/= true ->
            {false, _OtherErrorCode, MyErrorCode} = CommonCheck,
            {false, MyErrorCode};
        true ->
            Leader = lib_team_api:thing_to_mb(Player),
            NewPlayer = case lib_team:is_cls_target(ActivityId, SubTypeId) of
                false ->
                    TeamId = mod_team_create:get_new_id(),
                    NewTeamArgs = TeamArgs#team_args{id = TeamId, member = [Leader]},
                    _NewPidTeam = mod_team:start([NewTeamArgs]),
                    create_team_done(Player, TeamId, ActivityId);
                true when IsTask =:= true ->
                    TeamId = mod_team_create:get_new_id(),
                    NewTeamArgs = TeamArgs#team_args{id = TeamId, member = [Leader]},
                    _NewPidTeam = mod_team:start([NewTeamArgs]),
                    create_team_done(Player, TeamId, ActivityId);
                true ->
                    Node = clusters_node:get_node(),
                    NewTeamArgs = TeamArgs#team_args{member = [Leader]},
                    Agrs = [Node, RoleId, CreateTime, ActivityId, [NewTeamArgs]],
                    clusters_node:apply_cast(mod_team_create, create_team, Agrs),
                    Player#player_status{team = #status_team{cls_create_time = CreateTime}}
            end,
            {ok, NewPlayer}
    end.

%% 检查
%% @returns true | {false, OtherErrorCode, MyErrorCode}
%% OtherErrorCode, MyErrorCode :: is_integer()|{is_integer(), is_list()}
common_check(Player, ActivityId, SubTypeId) ->
    CheckList = [lv, power, open_day],
    do_common_check(CheckList, Player, ActivityId, SubTypeId).

check_for_create_team(Player, ActivityId, SubTypeId) ->
    CheckList = [lv, power, open_day],
    do_common_check(CheckList, Player, ActivityId, SubTypeId).

%% 重连数据处理
do_common_check([], _Player, _ActivityId, _SubTypeId) -> true;
do_common_check([H|T], Player, ActivityId, SubTypeId) ->
    case common_check_help(H, Player, ActivityId, SubTypeId) of
        true -> do_common_check(T, Player, ActivityId, SubTypeId);
        {false, OtherErrorCode, MyErrorCode} -> {false, OtherErrorCode, MyErrorCode}
    end.

common_check_help(lv, Player, ActivityId, SubTypeId) ->
    case data_team_ui:get(ActivityId, SubTypeId) of
        [] ->
            true;
        #team_enlist_cfg{default_lv_min = Min, default_lv_max = Max} ->
            #player_status{ figure = #figure{name = Name, lv = Lv}} = Player,
            if
                Lv < Min ->
                    {false,
                     {?ERRCODE(err240_not_enough_lv_to_enter_target_with_name), [Name]},
                     {?ERRCODE(player_lv_less), [Min]}
                    };
                Max > 0 andalso Lv > Max ->
                    {false,
                     {?ERRCODE(err240_not_enough_lv_to_enter_target_with_name), [Name]},
                     {?ERRCODE(player_lv_large), [Max]}
                    };
                true ->
                    true
            end
    end;

common_check_help(power, Player, ActivityId, SubTypeId) ->
    case data_team_ui:get(ActivityId, SubTypeId) of
        #team_enlist_cfg{power_limit = PowerLimit} ->
            if Player#player_status.figure#figure.power >= PowerLimit ->
                    true;
                true ->
                    {false, ?ERRCODE(err240_lower_power), ?ERRCODE(err240_lower_power)}
            end;
        _ ->
            true
    end;
common_check_help(open_day, _Player, ActivityId, SubTypeId) ->
    case lists:member({ActivityId, SubTypeId}, ?OPEN_DAY_LIMITS) of
        true ->
            {false, ?ERRCODE(data_error)};
        _ ->
            true
    end.



%% 转换创建队伍的错误码
transfer_create_team_errcode(ErrorCode) ->
    NoCountErr = ?ERRCODE(err610_have_no_count_to_enter_target),
    NotEnoughLvErr = ?ERRCODE(err240_not_enough_lv_to_enter_target),
    case ErrorCode of
        NoCountErr -> ?ERRCODE(err610_have_no_count_to_create_target);
        NotEnoughLvErr -> ?ERRCODE(err240_not_enough_lv_to_create_target);
        _ -> ErrorCode
    end.


lock_login(Player, TeamId, Position) ->
    #player_status{team = StatusTeam} = Player,
    NewTeam = StatusTeam#status_team{team_id = TeamId, positon = Position},
    NewPlayer = Player#player_status{team = NewTeam},
    lib_team:when_team_change(NewPlayer, StatusTeam),
    {ok, NewPlayer}.

%% lib_player:apply_cast(InfoId, ?APPLY_CAST_STATUS, lib_team, get_mb_scene, [Id, IsFollow]),
members_apply_cast(ClsType, Mbs, ApplyCastType, Mod, Fun, Args) ->
    F = fun(MemberNode, MemberId) ->
                mod_team:cast_to_game(ClsType, MemberNode, lib_player, apply_cast, [MemberId, ApplyCastType, Mod, Fun, Args])
        end,
    [F(M#mb.node, M#mb.id)||M <- Mbs, not is_fake_mb(M)].

change_teammate_in_team(#player_status{team = #status_team{team_id = TeamId}} = PS, TeamId, ActivityId, SubTypeId, MemberInfos) ->
    ExpPS = update_exp_scale_change(PS, MemberInfos, ActivityId, SubTypeId),
    IntimacyPS = update_intimacy_change(ExpPS, MemberInfos),
    {ok, IntimacyPS};
change_teammate_in_team(_PS, _, _, _, _) -> ok.

update_exp_scale_change(PS, MemberInfos, ActivityId, SubTypeId) ->
    #player_status{team = StatusTeam, scene = SceneId, sid = Sid, server_num = ServerNum} = PS,
    case data_team_ui:get(ActivityId, SubTypeId) of
        #team_enlist_cfg{activity_id=2,subtype_id=1}-> %%经验本
            Num = length(MemberInfos);
        #team_enlist_cfg{exp_scale_type = 1, scene_id = ActScene} ->
            case SceneId =:= ActScene of
                true  ->
                    Num = length([1 || #slim_mb{scene = S} <- MemberInfos, S =:= SceneId]);
                false ->
                    Num = length([1 || #slim_mb{scene = S, server = Server} <- MemberInfos, S =:= SceneId, Server =:= ServerNum])
            end;
        #team_enlist_cfg{exp_scale_type = 2} ->
            Num = length(MemberInfos);
        _ ->
            Num = 0
    end,
    ExpScale = if
          Num > 0 ->
              data_team_ui:get_exp_scale(Num);
          true ->
              0
      end,
    {ok, BinData} = pt_240:write(24050, [ExpScale]),
    lib_server_send:send_to_sid(Sid, BinData),
    PS2 = PS#player_status{team = StatusTeam#status_team{exp_scale = ExpScale}},
    PS3 = lib_player:update_exp_add_ratio(PS2),
    PS3.


update_intimacy_change(#player_status{team = #status_team{intimacy_lv = 0}} = PS, [_JustOne]) ->
    PS;
update_intimacy_change(PS, [_JustOne]) ->
    #player_status{team = StatusTeam} = PS,
    TmpPS = PS#player_status{team = StatusTeam#status_team{intimacy_lv = 0}},
    lib_goods_buff:remove_buff(TmpPS, ?BUFF_INTIMACY);
update_intimacy_change(PS, MemberInfos) ->
    #player_status{team = StatusTeam, id = RoleId} = PS,
    Intimacy
    = case [X || {_, _, X} <- lib_relationship:get_rela_and_intimacy_online(RoleId, [Id || #slim_mb{id = Id, online = ?ONLINE_ON} <- MemberInfos, Id =/= RoleId])] of
        [] ->
            0;
        List ->
            lists:max(List)
    end,
    #status_team{intimacy_lv = IntimacyLv} = StatusTeam,
    % case 10 of
    case data_relationship:get_intimacy_lv(Intimacy) of
        IntimacyLv ->
            PS;
        NewIntimacyLv ->
            TmpPS = PS#player_status{team = StatusTeam#status_team{intimacy_lv = NewIntimacyLv}},
            case data_rela:get_intimacy_lv_cfg(NewIntimacyLv) of
                #intimacy_lv_cfg{attr = [_|_] = Attr} ->
                    lib_goods_buff:add_buff(TmpPS, ?BUFF_INTIMACY, [{attr, Attr}], 0);
                _ ->
                    lib_goods_buff:remove_buff(TmpPS, ?BUFF_INTIMACY)
            end
    end.

change_team_enlist(Player, TeamId, EnList, HelpType) ->
    #player_status{team = #status_team{team_id = TeamId0}} = Player,
    if
        TeamId0 =:= TeamId ->
            send_ac_left_time(Player, EnList#team_enlist.activity_id),
            #team_enlist{dun_id = DunId} = EnList,
            Player1 = update_help_type(Player, DunId, TeamId, HelpType),
            {ok, Player1};
        true ->
            ok
    end.

update_help_type(Player, _DunId, _TeamId, _HelpType) ->
    Player.

send_scene_users_without_team(CopyId, SocketId) ->
    SceneUserList = lib_scene_agent:get_scene_user(CopyId),
    % Num = length(SceneUserList),
    List = [
        begin
            #ets_scene_user{platform = Platform, figure = Figure, server_num = SerNum, id = RoleId} = U,
            #figure{name = Name, sex = Sex, realm = Realm, career = Career, lv = Lv, picture = Pic, picture_ver = PicVer, turn = TurnNum} = Figure,
            {Platform, SerNum, RoleId, Sex, Realm, Career, Lv, Name, Pic, PicVer, TurnNum}
        end || #ets_scene_user{team = #status_team{team_id = TeamId},sid = Sid} = U <- SceneUserList,
        Sid =/= SocketId andalso TeamId =:= 0
    ],
    % ?PRINT("24053 >>> ~p~n", [List]),
    {ok, BinData} = pt_240:write(24053, [List]),
    lib_server_send:send_to_sid(SocketId, BinData).


%% 获取离线挂机时候的队伍野外挂机目标
get_onhook_target_type(SceneId)->
    Type = 3,
    SubIds = data_team_ui:get_activity_subtype_ids(Type),
    F = fun(SubId, TL) ->
                case data_team_ui:get(Type, SubId) of
                    #team_enlist_cfg{scene_id = SceneId} = E -> [E|TL];
                    _ -> TL
                end
        end,
    case lists:foldl(F, [], SubIds) of
        [] ->
            case data_team_ui:get(1, 0) of
                #team_enlist_cfg{module_id=Module, sub_module=SubModule, dun_id = DunId,
                                 scene_id = SceneId, default_lv_min = LvMin, default_lv_max = LvMax} ->
                    {#team_enlist{activity_id=1, subtype_id=0, module_id=Module,
                                  sub_module=SubModule, scene_id=SceneId, dun_id = DunId}, LvMin, LvMax};
                _ ->
                    {#team_enlist{},  0, 0}
            end;
        [#team_enlist_cfg{subtype_id = SubId, module_id=Module, sub_module=SubModule, dun_id = DunId,
                          scene_id = SceneId, default_lv_min = LvMin, default_lv_max = LvMax}|_] ->
            {#team_enlist{activity_id=Type, subtype_id=SubId,
                          module_id=Module, sub_module=SubModule, scene_id=SceneId, dun_id = DunId}, LvMin, LvMax}
    end.

get_max_team_member_num(ActivityId, SubTypeId) ->
    case data_team_ui:get(ActivityId, SubTypeId) of
        #team_enlist_cfg{num = MaxNum} ->
            MaxNum;
        _ ->
            ?TEAM_MEMBER_MAX
    end.

calc_location(Members, MaxMemberNum) ->
    F = fun(Mb, {MemberList, Location}) ->
            {MemberList++[Mb#mb{location=Location}], Location+1}
    end,
    {NewMemberList, Acc} = lists:foldl(F, {[], 1}, Members),
    FreeLocations = case Acc > MaxMemberNum of true -> []; false -> lists:seq(Acc, MaxMemberNum) end,
    {NewMemberList, FreeLocations}.

%% 是否跨服目标
is_cls_target(ActivityId, SubTypeId) ->
    case data_team_ui:get(ActivityId, SubTypeId) of
        #team_enlist_cfg{scene_id = SceneId} ->
            case data_scene:get(SceneId) of
                #ets_scene{cls_type=?SCENE_CLS_TYPE_CENTER} ->
                    true;
                _ ->
                    false
            end;
        _ ->
            false
    end.

get_team_cls_type(TeamId) ->
    case TeamId rem 2 of
        0 ->
            ?NODE_CENTER;
        _ ->
            ?NODE_GAME
    end.

create_team_done(PS, TeamId, ActivityId) ->
    #player_status{sid = Sid, id = RoleId} = PS,
    lib_team:send_ac_left_time(PS, ActivityId),
    {ok, BinData} = pt_240:write(24000, [?SUCCESS, []]),
    lib_server_send:send_to_sid(Sid, BinData),
    add_team_event_listener(),
    mod_chat_agent:update(RoleId, [{team_id, TeamId}]),
    PS#player_status{team=#status_team{team_id = TeamId, positon = ?TEAM_LEADER}}.

create_team_respond(Node, RoleId, CreateTime, Res) ->
    case lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, create_team_respond, [[Node, CreateTime, Res]]) of
        skip when Res =/= fail ->
            [TeamId|_] = Res,
            unode:apply(Node, mod_team_create, remove_created_team, [TeamId, CreateTime, ?FAIL]);
        _ ->
            ok
    end.

create_team_respond(PS, [Node, CreateTime, Res]) ->
    case PS#player_status.team of
        #status_team{cls_create_time = CreateTime} ->
            case Res of
                [TeamId, ActivityId] ->
                    unode:apply(Node, mod_team_create, remove_created_team, [TeamId, CreateTime, ?SUCCESS]),
                    create_team_done(PS, TeamId, ActivityId);
                _ ->
                    PS
            end;
        _ ->
            case Res of
                [TeamId|_] ->
                    unode:apply(Node, mod_team_create, remove_created_team, [TeamId, CreateTime, ?FAIL]);
                _ ->
                    ok
            end,
            PS
    end.


start_arbitrate(Player, [TeamId, ActivityId, SubTypeId, SceneId, ArbitrateId, EndTime]) ->
    #player_status{team = StatusTeam, sid = Sid} = Player,
    case StatusTeam of
        #status_team{team_id = TeamId} ->
            {ok, BinData} = pt_240:write(24035, [ActivityId, SubTypeId, SceneId, ArbitrateId, EndTime]),
            lib_server_send:send_to_sid(Sid, BinData),
            NewStatusTeam = StatusTeam#status_team{arbitrate_info = [ActivityId, SubTypeId, ArbitrateId]},
            Player#player_status{team = NewStatusTeam};
        _ ->
            Player
    end.

start_arbitrate_silent(Player, [TeamId, ActivityId, SubTypeId, _SceneId, ArbitrateId, _EndTime]) ->
    #player_status{team = StatusTeam, id = RoleId} = Player,
    case StatusTeam of
        #status_team{team_id = TeamId} ->
            case lib_team:check_start_team_target(Player, ActivityId, SubTypeId) of
                {ok, Data} ->
                    mod_team:cast_to_team(TeamId, {'arbitrate_res', RoleId, ArbitrateId, {1, {ok, Data}}});
                {false, Code} ->
                    OtherErrorCode = lib_team:my_code_to_other_code(Player#player_status.figure#figure.name, Code),
                    Error = {false, OtherErrorCode, Code},
                    mod_team:cast_to_team(TeamId, {'arbitrate_res', RoleId, ArbitrateId, {0, Error}});
                {false, _Code, _MyErrorCode} = Error ->
                    mod_team:cast_to_team(TeamId, {'arbitrate_res', RoleId, ArbitrateId, {0, Error}})
            end,
            Player;
        _ ->
            Player
    end.

%% return {ok, Data} | {false, Code} | {false, OtherCode, Code}
check_start_team_target(Player, _ActivityId, _SubTypeId) ->
    case lib_player_check:check_all(Player) of
        true ->
            {ok, []};
        {false, Code} ->
            {false, ?FAIL, Code}
    end.

auto_arbitrate(Player, TeamId, ActivityId, SubTypeId) ->
    case Player of
        #player_status{team = #status_team{team_id = TeamId}} ->
            pp_team:handle(24020, Player, [ActivityId, SubTypeId]);
        _ ->
            ok
    end.

check_for_other_match(Player, TeamId, ActivityId, SubTypeId) ->
    case Player of
        #player_status{team = #status_team{team_id = TeamId}, id = RoleId} ->
            case lib_team:check_start_team_target(Player, ActivityId, SubTypeId) of
                {ok, Data} ->
                    mod_team:cast_to_team(TeamId, {'ready_for_match', RoleId, Data});
                {false, Code} ->
                    OtherErrorCode = lib_team:my_code_to_other_code(Player#player_status.figure#figure.name, Code),
                    mod_team:cast_to_team(TeamId, {'fail_for_match', RoleId, OtherErrorCode});
                {false, OtherErrorCode, _Code} ->
                    mod_team:cast_to_team(TeamId, {'fail_for_match', RoleId, OtherErrorCode})
            end;
        _ ->
            ok
    end.

my_code_to_other_code(MyName, Code) ->
    Msg = util:make_error_code_msg(Code),
    {?ERRCODE(err240_me_to_other), [MyName, Msg]}.

cancel_role_match(Player) ->
    #player_status{team = StatusTeam, id = RoleId, sid = Sid} = Player,
    case StatusTeam#status_team.match_info of
        [] ->
            {ok, BinData} = pt_240:write(24048, [?SUCCESS, 0, 0, 0, RoleId]),
            lib_server_send:send_to_sid(Sid, BinData);
        [{ActivityId, SubTypeId}] ->
            case lib_team_match:get_match_mod(ActivityId, SubTypeId) of
                undefined ->
                    {ok, BinData} = pt_240:write(24048, [?SUCCESS, 0, ActivityId, SubTypeId, RoleId]),
                    lib_server_send:send_to_sid(Sid, BinData),
                    mod_team_enlist:clear_role_match(RoleId),
                    {ok, role_cancel_match(Player#player_status{team = StatusTeam#status_team{match_info = []}})};
                Mod ->
                    Mod:clear_role_match(Player)
            end;
        _ ->
            {ok, BinData} = pt_240:write(24048, [?SUCCESS, 0, 0, 0, RoleId]),
            lib_server_send:send_to_sid(Sid, BinData),
            mod_team_enlist:clear_role_match(RoleId),
            {ok, role_cancel_match(Player#player_status{team = StatusTeam#status_team{match_info = []}})}
    end.

take_over_team(State, {change_team_enlist, Args}) ->
    {ok, BinData} = pt_240:write(24017, [?SUCCESS|Args]),
    lib_team:send_team(State, BinData),
    State;

take_over_team(State, {set_matching, PtArgs}) ->
    {Code, NewState} = lib_team_mod:set_team_matching_state(State, 1),
    if
        Code =:= skip ->
            skip;
        true ->
            {ok, BinData} = pt_240:write(24048, [Code|PtArgs]),
            lib_team:send_team(NewState, BinData)
    end,
    NewState;

take_over_team(State, {invite_request, Msg}) ->
    gen_server:cast(self(), Msg),
    State.

handle_message(State, [{cast, Msg}|List]) ->
    case mod_team_cast:handle_cast(Msg, State) of
        {noreply, NewState} ->
            handle_message(NewState, List);
        Otherwise ->
            Otherwise
    end;

handle_message(State, [{info, Msg}|List]) ->
    case mod_team_info:handle_info(Msg, State) of
        {noreply, NewState} ->
            handle_message(NewState, List);
        Otherwise ->
            Otherwise
    end;

handle_message(State, []) ->
    {noreply, State}.

update_team_flag(Player, {_OrderTeamId, TeamPosition, TeamId, LeaderName}) ->
    Team = Player#player_status.team,
    TeamPlayer = Player#player_status{team = Team#status_team{team_id=TeamId, positon=TeamPosition, leader_name = LeaderName}},
    lib_team:when_team_change(TeamPlayer, Team),

    {ok, BinData} = pt_240:write(24013, [Player#player_status.id, TeamId, TeamPosition]),
    lib_server_send:send_to_area_scene(Player#player_status.scene, Player#player_status.scene_pool_id, Player#player_status.copy_id,
        Player#player_status.x, Player#player_status.y, BinData),
    %% {ok, TeamStatus1} = lib_player_event:dispatch(TeamStatus, ?EVENT_JOIN_TEAM),
    if
        Team#status_team.team_id > 0 andalso TeamId == 0 ->
            mod_chat_agent:update(Player#player_status.id, [{team_id, 0}]),
            handle_quit_team(TeamPlayer, [events, intimacy_buff, exp_scale, action_lock]);
        true ->
            TeamPlayer
    end.

%% 更新队长名字
update_team_leader_name(Player, LeaderName) ->
    Team = Player#player_status.team,
    TeamPlayer = Player#player_status{team = Team#status_team{leader_name = LeaderName}},
    when_team_change(TeamPlayer, Team),
    TeamPlayer.

%% 玩家队伍信息变更，同步更新场景内队伍数据/然后同步其他玩法内队伍数据
when_team_change(Player, OldTeam) ->
    NewTeam = Player#player_status.team,
    mod_scene_agent:update(Player, [{team_flag, Player#player_status.team}]),
    case (OldTeam#status_team.team_id =/= NewTeam#status_team.team_id
        orelse OldTeam#status_team.leader_name =/= NewTeam#status_team.leader_name) of
        true  ->
            %% 赏金BOSS伤害列表更新
            local_boss_api:user_team_change(Player, OldTeam#status_team.team_id),
            %% 我的协助者更新数据
            lib_guild_support_mod:update_team_info(Player);
        false ->
            ok
    end.

add_team_event_listener() ->
    lib_player_event:add_listener(?EVENT_COMBAT_POWER, lib_team_api, handle_event),
    lib_player_event:add_listener(?EVENT_RENAME, lib_team_api, handle_event),
    lib_player_event:add_listener(?EVENT_LV_UP, lib_team_api, handle_event).

remove_team_event_listener() ->
    lib_player_event:remove_listener(?EVENT_COMBAT_POWER, lib_team_api, handle_event),
    lib_player_event:remove_listener(?EVENT_RENAME, lib_team_api, handle_event),
    lib_player_event:remove_listener(?EVENT_LV_UP, lib_team_api, handle_event).

handle_quit_team(Player, [events|T]) ->
    remove_team_event_listener(),
    handle_quit_team(Player, T);

handle_quit_team(Player, [intimacy_buff|T]) ->
    case Player#player_status.team of
        #status_team{intimacy_lv = Lv} = StatusTeam when Lv > 0 ->
            NewPlayer = lib_goods_buff:remove_buff(Player, ?BUFF_INTIMACY),
            handle_quit_team(NewPlayer#player_status{team = StatusTeam#status_team{intimacy_lv = 0}}, T);
        _ ->
            handle_quit_team(Player, T)
    end;

handle_quit_team(Player, [exp_scale|T]) ->
    case Player#player_status.team of
        #status_team{exp_scale = ExpScale} = StatusTeam when ExpScale > 0 ->
            {ok, BinData} = pt_240:write(24050, [0]),
            lib_server_send:send_to_sid(Player#player_status.sid, BinData),
            % NewPlayer = lib_goods_buff:remove_buff(Player#player_status{team = StatusTeam#status_team{exp_scale = 0}}, ?BUFF_TEAM_EXP),
            NewPlayer = Player#player_status{team = StatusTeam#status_team{exp_scale = 0}},
            handle_quit_team(NewPlayer, T);
        _ ->
            handle_quit_team(Player, T)
    end;

handle_quit_team(Player, [action_lock|T]) ->
    NewPlayer = role_cancel_match(Player),
    handle_quit_team(NewPlayer, T);

handle_quit_team(Player, []) -> Player.

make_fake_mb(Mb, ClsType) ->
    #mb{figure = #figure{lv = Lv} = Figure, power = Power, server_num = ServerNum} = Mb,
    FakeServer = case ClsType of
        ?NODE_CENTER  ->
            AllServer = clusters_center:get_nodes_server_id(),
            case AllServer of
                [ServerNum] -> ServerNum;
                _ -> urand:list_rand(AllServer -- [ServerNum])
            end;
        _ -> ServerNum
    end,
    Mb#mb{
        id = 0, %% 会加上location作为id
        node = undefined,
        figure=lib_dummy_api:change_figure(Figure#figure{lv = Lv + urand:rand(0,10),sex= urand:list_rand([1,2]),career = 1,id = 0}, [create_name,rand_fashion]),%% 形象
        pid = undefined,                            %% 队员pid
        sid = undefined,                            %% 玩家sid
        power = Power + urand:rand(0, trunc(0.1*Power)),                          %% 战力
        picture = <<>>,                     %% 玩家上传的头像
        help_type = ?HELP_TYPE_YES,                      %% 助战类型
        % join_time = undefined,              %% 入伍时间
        scene = 0,
        server_num = FakeServer,
        target_start_data = []              %% 开始参数
    }.

is_fake_mb(Mb) -> Mb#mb.sid == undefined.

%% 修改匹配状态时:队伍设置匹配状态/队伍加满人取消匹配
when_change_match_status(Team, Match) ->
    case Match of
        1  ->
            [add_role_match(Team#team.cls_type, M#mb.node, M#mb.id)||M <- Team#team.member, not is_fake_mb(M)];
        0  ->
            [cancel_role_match(Team#team.cls_type, M#mb.node, M#mb.id)||M <- Team#team.member, not is_fake_mb(M)]
    end.

%% 取消玩家匹配状态
cancel_role_match(ClsType, Node, RoleId) ->
    mod_team:cast_to_game(ClsType, Node, lib_player, apply_cast,
        [RoleId, ?APPLY_CAST_STATUS, ?MODULE, role_cancel_match, []]).
%% 设置玩家匹配状态
add_role_match(ClsType, Node, RoleId) ->
    mod_team:cast_to_game(ClsType, Node, lib_player, apply_cast,
        [RoleId, ?APPLY_CAST_STATUS, ?MODULE, role_add_match, []]).
%% 玩家取消匹配状态
role_cancel_match(Player) ->
    Lock = Player#player_status.action_lock,
    case Lock of
        lock ->
            lib_player:break_action_lock(Player, Lock);
        _ -> Player
    end.
%% 玩家设置匹配状态
role_add_match(Player) ->
    Lock = Player#player_status.action_lock,
    case Lock of
        free ->
            lib_player:setup_action_lock(Player, lock);
        _ -> Player
    end.


%% 判断队员的状态能否进行匹配
check_can_match(Owner, ClsType, [{Node, RoleId}|T]) ->
    mod_team:cast_to_game(ClsType, Node, lib_player, apply_cast,
        [RoleId, ?APPLY_CAST_STATUS, ?MODULE, role_check_can_match, [T, Owner]]).

role_check_can_match(Player, T, Owner) ->
    #player_status{team=#status_team{team_id=TeamId}, action_lock = Lock, id = RoleId, scene = Scene} = Player,
    SceneType = lib_scene:get_scene_type(Scene),
    mod_team:cast_to_team(TeamId, {'do_set_matching_state', Owner, T, {RoleId, Lock, SceneType}}),
    Player.

%% 助战次数更新
update_help_counts(RoleId, TeamId, ActId, SubId) ->
    lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, update_help_counts_to_team, [TeamId, ActId, SubId]).
update_help_counts_to_team(Player, _TeamId, _ActId, _SubId) ->
    Player.

%% 处于废都和赏金幻魔,无法自动加入队伍,避免有玩家蹭归属掉落
%% 1不自动通过申请|2自动通过申请
calc_join_type(SceneId, OldJoinType) ->
    IsDesertedScene = local_boss_api:is_deserted_boss_scene(SceneId),
    IsRewardScene   = local_boss_api:is_reward_boss_scene(SceneId),
    if IsDesertedScene orelse IsRewardScene ->
            1;
        true ->
            OldJoinType
    end.
