%% ---------------------------------------------------------------------------
%% @doc mod_team_cast
%% @author ming_up@foxmail.com
%% @since  2016-10-24
%% @deprecated
%% ---------------------------------------------------------------------------
-module(mod_team_cast).
-export([handle_cast/2]).

-include("common.hrl").
-include("server.hrl").
-include("team.hrl").
-include("figure.hrl").
-include("predefine.hrl").
-include("errcode.hrl").
-include("scene.hrl").
-include("def_fun.hrl").
-include("dungeon.hrl").
-include("def_daily.hrl").
-include("def_module.hrl").
-include("skill.hrl").
-include("drop.hrl").
-include("def_recharge.hrl").
-include("recharge_act.hrl").

-export([
        del_rela/3
    ]).

-export([
        %% only for test and verify
        calc_team_skill_buff_num/4
    ]).

handle_cast({Node, {'match_team_request', Mb, Ref}}, State) ->
    #team{free_location = FreeLocation,
        member = MemberList,
        leader_id = LeaderId,
        enlist = #team_enlist{activity_id = ActivityId, subtype_id = SubTypeId},
        is_matching = IsMatching} = State,
    #mb{id = RoleId, online = OL} = Mb,
    IsOnDungeon = lib_team_mod:is_on_dungeon(State),
    %% 有自己的匹配逻辑不能参与一般匹配
    SpecialMatchMod = lib_team_match:get_match_mod(ActivityId, SubTypeId),
    if
        IsMatching =/= 1 orelse SpecialMatchMod =/= undefined orelse
        IsOnDungeon orelse FreeLocation == [] ->
            lib_player:apply_cast(Node, RoleId, ?APPLY_CAST_STATUS, ?NOT_HAND_OFFLINE, lib_team, auto_match_team, [[node(), Ref]]),
            {noreply, State};
        true ->
            case lib_team_mod:common_check(State, Mb) of
                true ->
                    case lists:keyfind(RoleId, #mb.id, MemberList) of
                        false ->
                            case lists:keyfind(LeaderId, #mb.id, MemberList) of
                                #mb{online = OL} ->
                                    handle_cast({Node, {'join_team', Mb}}, State);
                                _A ->
                                    lib_player:apply_cast(Node, RoleId, ?APPLY_CAST_STATUS, ?NOT_HAND_OFFLINE, lib_team, auto_match_team, [[node(), Ref]]),
                                    {noreply, State}
                            end;
                        _ ->
                            {noreply, State}
                    end;
                _CommonCheck ->
                    lib_player:apply_cast(Node, RoleId, ?APPLY_CAST_STATUS, ?NOT_HAND_OFFLINE, lib_team, auto_match_team, [[node(), Ref]]),
                    {noreply, State}
            end
    end;

%% 申请加入队伍
handle_cast({Node, {'join_team_request', Mb}}, State) ->
    #team{
        free_location = FreeLocation, member = MemberList, leader_id = LeaderId,
        leader_node = LeaderNode, join_type = JoinType, reqlist = ReqList, id = TeamId,
        enlist = #team_enlist{activity_id = ActId, subtype_id = ActSubId},
        is_matching = IsMatching
    } = State,
    #mb{
        id = RoleId, server_num = MbServ, figure = Figure, action_lock = Lock
    } = Mb,
    CommonCheck = lib_team_mod:join_team_check(State, Mb),
    SpecialMatchMod = lib_team_match:get_match_mod(ActId, ActSubId),
    if
        CommonCheck =/= true ->
            {false, _OtherErrorCode, MyErrorCode} = CommonCheck,
            {ErrorCodeInt, ErrorCodeArgs} = util:parse_error_code(MyErrorCode),
            {ok, BinData} = pt_240:write(24002, [ErrorCodeInt, ErrorCodeArgs, TeamId]),
            lib_team:send_to_uid(Node, RoleId, BinData),
            {noreply, State};
        FreeLocation == [] ->
            {ok, BinData} = pt_240:write(24002, [?ERRCODE(err240_max_member), [], TeamId]),
            lib_team:send_to_uid(Node, RoleId, BinData),
            {noreply, State};
        IsMatching =/= 0 andalso SpecialMatchMod =/= undefined ->
            {ok, BinData} = pt_240:write(24002, [?ERRCODE(err240_this_team_matching), [], TeamId]),
            lib_team:send_to_uid(Node, RoleId, BinData),
            {noreply, State};
        IsMatching =/= 0 andalso Lock =/= free ->
            {ok, BinData} = pt_240:write(24002, [?ERRCODE(err240_error_team_need_free), [], TeamId]),
            lib_team:send_to_uid(Node, RoleId, BinData),
            {noreply, State};
        true ->
            case lists:keyfind(RoleId, #mb.id, MemberList) of
                false when JoinType == 2 -> %% 自动加入
                    handle_cast({Node, {'join_team_af_response_agree', Mb}}, State);
                false ->
                    %%向队长发送进队申请
                    NewReqList = lists:keystore(RoleId, #mb.id, ReqList, Mb),
                    {ok, BinData1} = pt_240:write(24003, [MbServ, RoleId, Figure]),
                    lib_team:send_to_uid(LeaderNode, LeaderId, BinData1),
                    {ok, BinData2} = pt_240:write(24002, [?SUCCESS, [], TeamId]),
                    lib_team:send_to_uid(Node, RoleId, BinData2),
                    %% lib_player:apply_cast(RoleId, ?APPLY_CAST_SAVE, lib_team, clear_role_reqlist, [])
                    OffLine = ?NOT_HAND_OFFLINE,
                    ApplyType = ?APPLY_CAST_STATUS,
                    lib_player:apply_cast(
                        Node, RoleId, ApplyType, OffLine, lib_team, set_req_team_id, [TeamId]
                    ),
                    {noreply, State#team{reqlist = NewReqList}};
                _ ->
                    {ok, BinData1} = pt_240:write(24002, [?ERRCODE(err240_in_team), [], TeamId]),
                    lib_team:send_to_uid(Node, RoleId, BinData1),
                    {noreply, State}
            end
    end;
handle_cast({Node, {'join_team_request_with_password', Mb, Password}},
    #team{password = Password} = State) ->
    handle_cast({Node, {'join_team_request', Mb}}, State);
handle_cast({Node, {'join_team_request_with_password', Mb, _}}, State) ->
    {ok, BinData2} = pt_240:write(24059, [?ERRCODE(err240_password_error)]),
    lib_team:send_to_uid(Node, Mb#mb.id, BinData2),
    {noreply, State};

handle_cast({Node, {'check_password_before_join_request', Mb, _OpenDay, Password}}, State) ->
    #team{
        password = TeamPassword, enlist = #team_enlist{activity_id = ActId, subtype_id = ActSubId}, id = TeamId
    } = State,
    #team_enlist_cfg{dun_id = DunId} = data_team_ui:get(ActId, ActSubId),
    case lists:member({ActId, ActSubId}, ?OPEN_DAY_LIMITS) of
        true ->
            case data_dungeon:get_dun(DunId) of
                #dun_cfg{} ->
                    case (Password =:= TeamPassword) orelse (TeamPassword =:= <<>>) of
                        false ->
                            {ok, Bin} = pt_240:write(24002, [?ERRCODE(err240_password_error), [], TeamId]),
                            lib_team:send_to_uid(Node, Mb#mb.id, Bin),
                            {noreply, State};
                        _  ->
                            handle_cast({Node, {'join_team_request', Mb}}, State)
                    end;
                _ ->
                    {ok, Bin} = pt_240:write(24002, [?ERRCODE(err416_config_error), [], TeamId]),
                    lib_server_send:send_to_uid(Node, Mb#mb.id, Bin),
                    {noreply, State}
            end;
        _ ->
            case (Password =:= TeamPassword) orelse (TeamPassword =:= <<>>) of
                false ->
                    {ok, Bin} = pt_240:write(24002, [?ERRCODE(err240_password_error), [], TeamId]),
                    lib_team:send_to_uid(Node, Mb#mb.id, Bin),
                    {noreply, State};
                _ ->
                    handle_cast({Node, {'join_team_request', Mb}}, State)
            end
    end;

handle_cast({Node, {'join_team_response', LeaderId, reject_all}}, #team{leader_id = LeaderId} = State) ->
    #team{cls_type=ClsType, reqlist = ReqList, id = TeamId} = State,
    if
        ClsType == ?NODE_GAME ->
            {ok, BinData1} = pt_240:write(24002, [?ERRCODE(err240_leader_reject), [], TeamId]),
            [lib_team:send_to_uid(MNode, Uid, BinData1) || #mb{id = Uid, node = MNode} <- ReqList];
        true ->
            ok
    end,
    {ok, BinData} = pt_240:write(24004, [?SUCCESS]),
    lib_team:send_to_uid(Node, LeaderId, BinData),
    {noreply, State#team{reqlist = []}};

%% 队长回应加入队伍申请
handle_cast({Node, {'join_team_response', Res, Uid, ResponseId}}, State) ->
    #team{
        id=TeamId, cls_type=ClsType, free_location=FreeLocation,
        enlist = #team_enlist{activity_id = ActivityId, subtype_id = SubTypeId},
        leader_id=LeaderId, reqlist = ReqList, is_matching = IsMatching
    } = State,
    SpecialMatchMod = lib_team_match:get_match_mod(ActivityId, SubTypeId),
    ErrCode = if
        Res == 0 andalso ClsType == ?NODE_GAME ->
            {ok, BinData1} = pt_240:write(24002, [?ERRCODE(err240_leader_reject), [], TeamId]),
            lib_team:send_to_uid(Node, Uid, BinData1),
            ?SUCCESS;
        Res == 0 -> ?SUCCESS;
        [] == FreeLocation -> ?ERRCODE(err240_max_member);
        LeaderId /= ResponseId -> ?ERRCODE(err240_not_leader);
        IsMatching /= 0 andalso SpecialMatchMod =/= undefined ->
            ?ERRCODE(err240_change_when_matching);
        ClsType == ?NODE_CENTER ->
            SerId = mod_player_create:get_serid_by_id(Uid),
            ApplyCastArgs = [
                Uid, ?APPLY_CAST_STATUS, lib_team, get_info_and_join_team, [Uid, TeamId, IsMatching]
            ],
            mod_team:cast_to_game(ClsType, SerId, lib_player, apply_cast, ApplyCastArgs),
            ?SUCCESS;
        true ->
            case lib_player:get_player_info(Uid, #player_status.team) of
                false ->
                    {ok, BinData1} = pt_240:write(24030, [?ERRCODE(err240_offline)]),
                    lib_team:send_to_uid(Node, LeaderId, BinData1);
                #status_team{team_id=OtherTeamId} when OtherTeamId > 0 ->
                    {ok, BinData1} = pt_240:write(24030, [?ERRCODE(err240_other_in_team)]),
                    lib_team:send_to_uid(Node, LeaderId, BinData1);
                _ ->
                    lib_player:apply_cast(Uid, ?APPLY_CAST_STATUS, lib_team, get_info_and_join_team, [Uid, TeamId, IsMatching])
            end,
            ?SUCCESS
    end,
    {ok, BinData} = pt_240:write(24004, [ErrCode]),
    lib_team:send_to_uid(Node, ResponseId, BinData),
    NewReqList = lists:keydelete(Uid, #mb.id, ReqList),
    {noreply, State#team{reqlist = NewReqList}};

handle_cast({Node, {'join_team_af_response_agree', Mb}}, State) ->
    #team{leader_id = LeaderId} = State,
    CommonCheck = lib_team_mod:common_check(State, Mb),
    if
        CommonCheck =/= true ->
            {false, OtherErrorCode, _MyErrorCode} = CommonCheck,
            {ErrorCodeInt, ErrorCodeArgs} = util:parse_error_code(OtherErrorCode),
            {ok, BinData} = pt_240:write(24038, [ErrorCodeInt, ErrorCodeArgs]),
            lib_team:send_to_uid(Node, LeaderId, BinData),
            {noreply, State};
        true ->
            handle_cast({Node, {'join_team', Mb}}, State)
    end;

%% 系统获取信息并让玩家进入队伍
handle_cast({_Node, {'join_team', Mb}}, State) ->
    #team{free_location = FreeLocation} = State,
    IsOnDungeon = lib_team_mod:is_on_dungeon(State),
    if
        [] == FreeLocation -> {noreply, State};
        IsOnDungeon -> {noreply, State};
        true ->
            StateAfInterrupt = lib_team_mod:auto_interrupt_arbitrate(State),
            NewState = join_team(_Node, Mb, StateAfInterrupt),
            {noreply, NewState}
    end;

%%任务完成 任务队伍需解散退出队伍
handle_cast({Node, {'quit_team', RoleId, 2}}, State) ->
    #team{is_task=IsTask} = State,
    case IsTask == true of
        true->
            handle_cast({Node, {'quit_team', RoleId, 0}}, State);
        _->
             {noreply, State}
    end;
handle_cast({Node, {'quit_team', RoleId, 4}}, State) ->
    #team{enlist = #team_enlist{activity_id = ActId}, member = Member, is_matching = IsMatching} = State,
    L = length(Member),
    if
        L =:= 1 andalso IsMatching =:= 0 -> {noreply, State};
        not (ActId =:= 2) -> {noreply, State};
        true ->
            handle_cast({Node, {'quit_team', RoleId, 0}}, State)
    end;
handle_cast({Node, {'quit_team', RoleId, 5}}, State) ->
    #team{enlist = #team_enlist{activity_id = ActId}} = State,
    if
        not (ActId =:= 2 orelse ActId =:= 4) -> {noreply, State};
        true ->
            handle_cast({Node, {'quit_team', RoleId, 0}}, State)
    end;
%% 退出队伍 0普通|1离线|2任务|3静默（不提醒）|4进入互斥场景退队|5多人本出来直接退队
handle_cast({Node, {'quit_team', RoleId, QuitType}}, State) ->
    #team{
        id=TeamId, cls_type=ClsType, member=MemberList, leader_id=LeaderId,
        free_location=FreeLocation, rela=OldRela
    } = State,
    MemberLen = length(MemberList),
    Mb = lists:keyfind(RoleId, #mb.id, MemberList),
    IsOnDungeon = lib_team_mod:is_on_dungeon(State),
    if
        Mb =:= false -> {noreply, State};
        %% 在副本中无法普通退出副本
        QuitType == 0 andalso IsOnDungeon andalso Mb#mb.dungeon_id > 0 ->
            {noreply, State};
        MemberLen < 2 -> %% 最后一个玩家退出组队，组队进程退出
            StateAfInterrupt0 = lib_team_mod:interrupt_special_match(State),
            StateAfInterrupt = lib_team_mod:auto_interrupt_arbitrate(StateAfInterrupt0),
            {ok, BinData1} = pt_240:write(24030, [?ERRCODE(err240_self_out_team)]),
            QuitType =/= 3 andalso lib_team:send_to_uid(Node, RoleId, BinData1),
            lib_team_mod:set_member_attr(StateAfInterrupt, Mb#mb.node, RoleId, 0, 0, ""),
            mod_team:cast_to_game(
                ClsType, Mb#mb.node, lib_player, update_player_info, [RoleId, [{team_skill, {0, 0}}]]
            ),
            mod_team_enlist:change_team(ClsType, TeamId, [{quit_partner, RoleId}]),
            {ok, BinData} = pt_240:write(24005, [?SUCCESS]),
            QuitType =/= 3 andalso lib_team:send_to_uid(Node, RoleId, BinData),
            {stop, normal, StateAfInterrupt#team{member = []}};
        true ->
            StateAfInterrupt0 = lib_team_mod:interrupt_special_match(State),
            StateAfInterrupt = lib_team_mod:auto_interrupt_arbitrate(StateAfInterrupt0),
            %% 更新玩家进程和场景进程的数据，并告诉附近的玩家.
            lib_team_mod:set_member_attr(StateAfInterrupt, Mb#mb.node, RoleId, 0, 0, ""),
            #mb{node = MbNode, location = Location} = Mb,
            mod_team:cast_to_game(
                ClsType, MbNode, lib_player, update_player_info, [RoleId, [{team_skill, {0, 0}}]]
            ),
            %% 重新设置空闲位置
            Free = lists:sort([Location | FreeLocation]),
            %% 处理跟随状态
            FollowState = lib_team:cancel_follow(StateAfInterrupt, RoleId),
            FollowsState = lib_team:cancel_follows(FollowState, RoleId),

            NewMembers = lists:keydelete(RoleId, #mb.id, FollowsState#team.member),
            Rela = del_rela(OldRela, RoleId, []),
            %% 技能更新
            NewTeamSkill = set_member_team_skill(ClsType, NewMembers),
            NewState = FollowsState#team{
                member = NewMembers, free_location = Free, rela=Rela, team_skill = NewTeamSkill
            },
            mod_team_enlist:change_team(ClsType, TeamId, [{num, -1},{quit_partner, RoleId}]),
            {ok, BinData} = pt_240:write(24014, [RoleId]),
            case QuitType =:= 3 of
                true  -> lib_team:send_team(NewState, BinData, RoleId);
                false -> lib_team:send_team(NewState, BinData)
            end,
            {ok, BinData2} = pt_240:write(24005, [?SUCCESS]),
            QuitType =/= 3 andalso lib_team:send_to_uid(Node, RoleId, BinData2),
            QuitType =/= 3 andalso lib_team:notify_team_change(
                Node, ?ERRCODE(err240_self_out_team), ?ERRCODE(err240_out_team), 5, Mb, NewState
            ),
            NewState0 = if
                LeaderId =:= RoleId ->
                    %% util:cancel_timer(Mb#mb.onhook_ref),
                    delegate_leader(NewState);
                true ->
                    NewState
            end,
            NewState1 = lib_team_mod:delay_notify_teammates_update(NewState0),
            {noreply, NewState1}
    end;

handle_cast({Node, {already_joined_in_another, RoleId}}, State) ->
    #team{
        id=TeamId, cls_type=ClsType, member=MemberList, leader_id=LeaderId,
        free_location=FreeLocation, rela=OldRela
    } = State,
    MemberLen = length(MemberList),
    Mb = lists:keyfind(RoleId, #mb.id, MemberList),
    %% IsTsmaps = lib_team_mod:is_dun_tsmaps(State),
    if
        Mb =:= false -> {noreply, State};
        MemberLen < 2 ->
            StateAfInterrupt0 = lib_team_mod:interrupt_special_match(State),
            StateAfInterrupt = lib_team_mod:auto_interrupt_arbitrate(StateAfInterrupt0),
            {stop, normal, StateAfInterrupt#team{member = []}};
        true ->
            StateAfInterrupt0 = lib_team_mod:interrupt_special_match(State),
            StateAfInterrupt = lib_team_mod:auto_interrupt_arbitrate(StateAfInterrupt0),
            %% 更新玩家进程和场景进程的数据，并告诉附近的玩家.
            lib_team_mod:set_member_attr(StateAfInterrupt, Mb#mb.node, RoleId, 0, 0, ""),
            mod_team:cast_to_game(ClsType, Mb#mb.node, lib_player, update_player_info, [RoleId, [{team_skill, {0, 0}}]]),
            %% 重新设置空闲位置
            Free = lists:sort([Mb#mb.location | FreeLocation]),
            %% 处理跟随状态
            FollowState = lib_team:cancel_follow(StateAfInterrupt, RoleId),
            FollowsState = lib_team:cancel_follows(FollowState, RoleId),

            NewMembers = lists:keydelete(RoleId, #mb.id, FollowsState#team.member),
            Rela = del_rela(OldRela, RoleId, []),
            %% 技能更新
            NewTeamSkill = set_member_team_skill(ClsType, NewMembers),
            NewState = FollowsState#team{member = NewMembers, free_location = Free, rela=Rela, team_skill = NewTeamSkill},
            mod_team_enlist:change_team(ClsType, TeamId, [{num, -1}]),
            {ok, BinData} = pt_240:write(24014, [RoleId]),
            lib_team:send_team(NewState, BinData, RoleId),
            lib_team:notify_team_change(Node, ?ERRCODE(err240_self_out_team), ?ERRCODE(err240_out_team), 5, Mb#mb{sid = undefined}, NewState),
            NewState1 = lib_team_mod:delay_notify_teammates_update(NewState),
            NewState2 = if
                LeaderId =:= RoleId ->
                    delegate_leader(NewState1);
                true ->
                    NewState1
            end,
            {noreply, NewState2}
    end;

%% 邀请加入组队
handle_cast({Node, {'invite_request', InviteList, InviterId, InviteScene, ActivityId, SubTypeId, LvMin, LvMax, MentorArgs}}, State) ->
    handle_cast({Node, {'invite_request', InviteList, InviterId, InviteScene, ActivityId, SubTypeId, LvMin, LvMax, 0, MentorArgs}}, State);
handle_cast(
    {Node, {'invite_request', _InviteList, RoleId, _InviteScene, ActivityId, SubTypeId, LvMin, LvMax, _InviteType, MentorArgs}} = Msg,
    #team{enlist = #team_enlist{activity_id=ActivityId0, subtype_id=SubTypeId0}} = State
) when ActivityId =/= ActivityId0 orelse SubTypeId =/= SubTypeId0 ->
    #team{
        is_matching = IsMatching, free_location = FreeLocation, leader_id = LeaderId
        ,join_type = JoinType, password = Password
    } = State,
    SpecialMatchMod = lib_team_match:get_match_mod(ActivityId, SubTypeId),
    if
        [] == FreeLocation ->
            {ok, BinData} = pt_240:write(24006, [?ERRCODE(err240_max_member)]),
            lib_team:send_to_uid(Node, RoleId, BinData),
            {noreply, State};
        IsMatching =/= 0 andalso SpecialMatchMod =/= undefined ->
            {ok, BinData} = pt_240:write(24006, [?ERRCODE(err240_change_when_matching)]),
            lib_team:send_to_uid(Node, RoleId, BinData),
            {noreply, State};
        LeaderId =/= RoleId ->
            {ok, BinData} = pt_240:write(24006, [?ERRCODE(err240_invite_diff_target_error)]),
            lib_team:send_to_uid(Node, RoleId, BinData),
            {noreply, State};
        true ->
            case lib_team_mod:check_change_team_enlist(State, RoleId, ActivityId, SubTypeId, LvMin, LvMax, MentorArgs) of
                {true, Cfg} ->
                    %% 先改目标
                    ChangedState = lib_team_mod:change_team_enlist(State, Cfg, 0, LvMin, LvMax, Password),
                    {ok, BinData} = pt_240:write(24017, [?SUCCESS, ActivityId, SubTypeId, 0, LvMin, LvMax, JoinType, Password]),
                    lib_team:send_team(ChangedState, BinData),
                    handle_cast(Msg, ChangedState);
                {false, Code} ->
                    {ok, BinData} = pt_240:write(24006, [Code]),
                    lib_team:send_to_uid(Node, RoleId, BinData),
                    {noreply, State};
                {take_over, TargetClsType} ->
                    TakeOverInfo = [{lv, [LvMin, LvMax]}, {take_over, [self(), {invite_request, Msg}, invite_request]}],
                    FailReturn = {invite_request, Node, RoleId},
                    TmpState = take_over(ActivityId, SubTypeId, 0, TakeOverInfo, FailReturn, Node, TargetClsType, State),
                    {noreply, TmpState}
            end
    end;

handle_cast({Node, {'invite_request', InviteList, InviterId, InviteScene, ActivityId, SubTypeId, LvMin, LvMax, InviteType, _MentorArgs}}, State) ->
    #team{
        id = TeamId, is_matching = IsMatching,
        enlist = #team_enlist{activity_id=ActivityId, subtype_id=SubTypeId, scene_id=SceneId, dun_id = DunId},
        member = MemberList, cls_type = ClsType,
        free_location = FreeLocation} = State,
    MbInfo = lists:keyfind(InviterId, #mb.id, MemberList),
    MbLen = length(MemberList),
    SpecialMatchMod = lib_team_match:get_match_mod(ActivityId, SubTypeId),
    Res = if
        [] == FreeLocation ->
            ?ERRCODE(err240_max_member);
        IsMatching /= 0 andalso SpecialMatchMod =/= undefined ->
            ?ERRCODE(err240_change_when_matching);
        MbInfo == false ->
            ?ERRCODE(err240_team_disappear);
        true ->
            Data = [TeamId, MbLen, ActivityId, SubTypeId, SceneId, InviterId, MbInfo#mb.figure, InviteScene, InviteType],
            {ok, BinData} = pt_240:write(24007, Data),
            case ClsType =:= ?NODE_CENTER of
                true->
                    F = fun(ToId) ->
                            case lists:keyfind(ToId, #mb.id, MemberList) of
                                false ->
                                    ToNode = clusters_center:get_node_by_role_id(ToId),
                                    lib_team:send_to_uid(ToNode, ToId, BinData);
                                _ -> skip
                            end
                    end,
                    [F(EId) || EId <- InviteList],
                    ?SUCCESS;
                false->
                    case InviteList /= [] of
                        true->
                            Results =
                            [case lists:keyfind(ToId, #mb.id, MemberList) of
                                false ->
                                    case lib_player:is_online_global(ToId) of
                                        true->
                                            [#status_team{team_id = Tid}, #figure{lv = Lv}, DungeonInfo] =
                                                lib_player:get_player_info(ToId,[#player_status.team, #player_status.figure, #player_status.dungeon]),
                                            Bool = case {ActivityId, SubTypeId} of
                                                {2, 41} -> true;
                                                {2, 42} -> true;
                                                {2, 43} -> true;
                                                _ ->
                                                    false
                                            end,
                                            CoupleCheck = case Bool of
                                                true  ->
                                                    CountType = case data_dungeon:get_dun(DunId) of
                                                        #dun_cfg{type = DunType} ->
                                                            lib_dungeon_api:get_daily_count_type(DunType, DunId);
                                                        _ ->
                                                            0
                                                    end,
                                                    case lists:keyfind(CountType, 1, DungeonInfo) of
                                                        {_, ItId} when ItId >= DunId -> false;
                                                        _ -> true
                                                    end;
                                                false -> false
                                            end,
                                            if
                                                Tid >0 ->
                                                    ok;
                                                Bool andalso CoupleCheck ->
                                                    false;
                                                Lv < LvMin orelse Lv > LvMax ->
                                                    ok;
                                                true->
                                                    lib_server_send:send_to_uid(ToId, BinData),
                                                    ok
                                            end;
                                        false->
                                            ok
                                    end;
                                _ -> ok
                            end || ToId <- InviteList],
                            case lists:member(false, Results) of
                                true  -> ?ERRCODE(err240_the_other_not_pre_dun);
                                false ->
                                    ?SUCCESS
                            end;
                        false->
                            ?SUCCESS
                    end
            end
    end,
    %% ?PRINT("invite_request ~p~n", [{MbLen, MbInfo, Res, FreeLocation}]),
    {ok, BinData1} = pt_240:write(24006, [Res]),
    lib_team:send_to_uid(Node, InviterId, BinData1),
    {noreply, State};

%% 被邀请人回应加入队伍请求
handle_cast({Node, {'invite_response', Res, MbInfo, _Args, Lock}}, State) ->
    #team{
        free_location=FreeLocation, member=MemberList, is_matching = IsMatching
        ,enlist = #team_enlist{activity_id = ActivityId, subtype_id = SubTypeId}
        ,leader_id = LeaderId
    } = State,
    IsOnDungeon = lib_team_mod:is_on_dungeon(State),
    InTeam = lists:keymember(MbInfo#mb.id, #mb.id, MemberList),
    CommonCheck = lib_team_mod:common_check(State, MbInfo),
    SpecialMatchMod = lib_team_match:get_match_mod(ActivityId, SubTypeId),
    ErrCode = if
        InTeam -> ?ERRCODE(err240_in_team);
        Res == 0 -> ?SUCCESS;
        [] == FreeLocation -> ?ERRCODE(err240_max_member);
        IsMatching /= 0 andalso SpecialMatchMod =/= undefined ->
            ?ERRCODE(err240_this_team_matching);
        IsMatching /= 0 andalso Lock /= free ->
            ?ERRCODE(err240_error_team_need_free);
        CommonCheck =/= true ->
            {false, _OtherErrorCode, MyErrorCode} = CommonCheck,
            MyErrorCode;
        IsOnDungeon ->
            ?ERRCODE(err240_this_team_on_dungeon);
        true ->
            StateAfInterrupt = lib_team_mod:auto_interrupt_arbitrate(State),
            {ok, join_team(Node, MbInfo, StateAfInterrupt)}
    end,
    #mb{id = ResponseRoleId, figure = #figure{name = ResName}} = MbInfo,
    #mb{node = LeaderNode} = lists:keyfind(LeaderId, #mb.id, MemberList),
    %% 回应结果
    IsYes = case ErrCode of
        {ok, _} -> 1;
        _ -> 0
    end,
    {ok, LeaderBin} = pt_240:write(24056, [ResponseRoleId, ResName, IsYes]),
    lib_team:send_to_uid(LeaderNode, LeaderId, LeaderBin),
    case ErrCode of
        {ok, NewState} ->
            {ok, BinData} = pt_240:write(24008, [?SUCCESS, []]),
            lib_team:send_to_uid(Node, MbInfo#mb.id, BinData),
            {noreply, NewState};
        _ ->
            {ErrorCodeInt, ErrorCodeArgs} = util:parse_error_code(ErrCode),
            % ?PRINT("invite_response ~p~n", [[ErrCode, {ErrorCodeInt, ErrorCodeArgs}]]),
            {ok, BinData} = pt_240:write(24008, [ErrorCodeInt, ErrorCodeArgs]),
            lib_team:send_to_uid(Node, MbInfo#mb.id, BinData),
            {noreply, State}
    end;

%% 请求队伍信息
handle_cast({Node, {'get_team_info', Id}}, State) ->
    lib_team:send_to_uid(Node, Id, lib_team:get_team_info_bin(State)),
    {noreply, State};

%% 踢出队伍
%% @param _Type 正常
handle_cast({Node, {'kick_out', KickId, RoleId, _Type}}, State) ->
    #team{cls_type=ClsType, id=TeamId, leader_id = LeaderId, member = Members,
        free_location = FreeLocation, rela=OldRela} = State,
    Mb = lists:keyfind(KickId, #mb.id, Members),
    IsOnDungeon = lib_team_mod:is_on_dungeon(State),
    {Result, RNewState} = if
        %% IsFlagwar == 1 -> {?ERR240_41_IN_FLAGWAR, State};
        KickId == LeaderId -> {?ERRCODE(err240_not_kick_leader), State};
        % 在副本无法踢人
        IsOnDungeon -> {?ERRCODE(err240_on_dungeon_not_to_do), State};
        LeaderId /= RoleId -> {?ERRCODE(err240_not_leader), State};
        Mb == false -> {?FAIL, State};
        true ->
            StateAfInterrupt0 = lib_team_mod:interrupt_special_match(State),
            StateAfInterrupt = lib_team_mod:auto_interrupt_arbitrate(StateAfInterrupt0),
            %% 更新玩家进程
            case lib_team:is_fake_mb(Mb) of
                false ->
                    lib_team_mod:set_member_attr(StateAfInterrupt, Mb#mb.node, KickId, 0, 0, "");
                _ ->
                    ok
            end,
            Free = lists:sort([Mb#mb.location | FreeLocation]),
            FollowState = lib_team:cancel_follow(StateAfInterrupt, KickId),
            FollowsState = lib_team:cancel_follows(FollowState, KickId),

            NewMembers = lists:keydelete(KickId, #mb.id, Members),
            Rela = del_rela(OldRela, KickId, []),
            %% 技能更新
            NewTeamSkill = set_member_team_skill(ClsType, NewMembers),
            NewState = FollowsState#team{member = NewMembers, free_location = Free, rela=Rela, team_skill = NewTeamSkill},

            mod_team_enlist:change_team(ClsType, TeamId, [{num, -1},{quit_partner,KickId}]),
            %% 发送离开队员id
            {ok, BinData} = pt_240:write(24014, [KickId]),
            lib_team:send_team(State, BinData),
            %% BonfireState = lib_team:handle_barbecue_buff(NewState, 2),
            lib_team:notify_team_change(Node, ?ERRCODE(err240_self_shot_of_team), ?ERRCODE(err240_shot_of_team), 6, Mb, NewState),
            NewState1 = lib_team_mod:delay_notify_teammates_update(NewState),
            {?SUCCESS, NewState1}
    end,
    {ok, BinData2} = pt_240:write(24009, [Result]),
    lib_team:send_to_uid(Node, RoleId, BinData2),
    {noreply, RNewState};

%% 委任队长
handle_cast({Node, {'change_leader', RoleId, LeaderId}}, State) ->
    #team{id=TeamId, cls_type=ClsType, leader_id = OldLeaderId, member = MemberList} = State,
    OldLeaderInfo = lists:keyfind(LeaderId, #mb.id, MemberList),
    NewLeaderInfo = lists:keyfind(RoleId, #mb.id, MemberList),
    IsOnDungeon = lib_team_mod:is_on_dungeon(State),
    {Code, RNewState} = if
        %% IsFlagwar == 1 -> {?ERR240_41_IN_FLAGWAR, State};
        LeaderId =/= OldLeaderId -> {?ERRCODE(err240_not_leader), State};
        % 在副本无法委任队长
        IsOnDungeon -> {?ERRCODE(err240_on_dungeon_not_to_do), State};
        OldLeaderInfo == false -> {?FAIL, State};
        NewLeaderInfo == false -> {?FAIL, State};
        true ->
            StateAfInterrupt = lib_team_mod:auto_interrupt_arbitrate(State),
            OldLearderMb = lists:keyfind(OldLeaderId, #mb.id, MemberList),

            #mb{
                id = NewLeaderId, pid = NewLeaderPid, node=NewLeaderNode, figure=NewLeaderFigure, server_num = ServerNum
                ,scene = Scene, x = X, y = Y
            } = NewLeaderInfo,
            #figure{name = LeaderName} = NewLeaderFigure,
            NewState = StateAfInterrupt#team{
                leader_id = NewLeaderId, leader_pid = NewLeaderPid, leader_node=NewLeaderNode
                ,leader_name = LeaderName
            },

            %% 设置属性
            lib_team_mod:set_member_attr(NewState, OldLearderMb#mb.node, OldLeaderId, ?TEAM_MEMBER, TeamId, LeaderName),
            lib_team_mod:set_member_attr(NewState, NewLeaderInfo#mb.node, RoleId, ?TEAM_LEADER, TeamId, LeaderName),
            lib_team_mod:set_member_leader_name(NewState),
            %% 发送队长变更信息
            {ok, BinData1} = pt_240:write(24015, [NewLeaderId]),
            lib_team:send_team(NewState, BinData1),
            UpdateList = [
                {leader_position_xy, {NewLeaderId, Scene, X, Y}}
                ,{leader, {NewLeaderFigure, ServerNum}}, {quit_partner,RoleId}
                ,{add_partner,OldLeaderInfo#mb.figure}
            ],
            mod_team_enlist:change_team(ClsType, TeamId, UpdateList),
            {?SUCCESS, NewState}
    end,
    {ok, BinData} = pt_240:write(24011, [Code]),
    lib_team:send_to_uid(Node, LeaderId, BinData),
    {noreply, RNewState};

%% 队长召集队友
handle_cast({Node, {call_together, RoleId, Scene, _ScenePoolId, _CopyId, X, Y}}, State) ->
    #team{leader_id = LeaderId, leader_name = LeaderName} = State,
    {Code, NewState} = if
        RoleId =/= LeaderId ->
            {?ERRCODE(err240_not_leader), State};
        true ->
            %% 广播召集
            ProData = [RoleId, 0, LeaderName, Scene, X, Y],
            {ok, BinData1} = pt_240:write(24046, ProData),
            lib_team:send_team(State, BinData1, LeaderId),
            {?SUCCESS, State}
    end,
    {ok, BinData} = pt_240:write(24045, [Code]),
    lib_team:send_to_uid(Node, RoleId, BinData),
    {noreply, NewState};

%% 更改队伍目标
handle_cast({Node, {'change_team_enlist', RoleId, TeamArgs}}, State) ->
    #team_args{
        act_id = ActivityId, act_sub_id = SubTypeId, scene_id = SceneId, lev_min = LvMin
        ,lev_max = LvMax, join_type = JoinType, password = Password
    } = TeamArgs,
    #team{is_matching = IsMatching} = State,
    if
        IsMatching =/= 0 ->
            {_, TmpState0} = handle_cast({Node, {'set_matching_state', RoleId, 0}}, State);
        true ->
            TmpState0 = State
    end,
    SuccessCode = ?SUCCESS,
    {Code, State2}
    = case lib_team_mod:check_change_team_enlist(TmpState0, RoleId, ActivityId, SubTypeId, LvMin, LvMax, []) of
        {true, Cfg} ->
            TmpState = lib_team_mod:change_team_enlist(TmpState0, Cfg, SceneId, LvMin, LvMax, Password),
            {SuccessCode, TmpState};
        {false, ErrCode} ->
            {ErrCode, State};
        {take_over, TargetClsType} ->
            PtArgs = [ActivityId, SubTypeId, SceneId, LvMin, LvMax, JoinType, Password],
            TakeOverInfo = [{lv, [LvMin, LvMax]}, {take_over, [self(), {change_team_enlist, PtArgs}, change_team_enlist]}],
            FailReturn = {change_team_enlist, Node, RoleId, PtArgs},
            TmpState = take_over(ActivityId, SubTypeId, SceneId, TakeOverInfo, FailReturn, Node, TargetClsType, TmpState0),
            {take_over, TmpState}
    end,
    NewState = case Code of
        SuccessCode ->
            {ok, BinData} = pt_240:write(24017, [Code, ActivityId, SubTypeId, SceneId, LvMin, LvMax, JoinType, Password]),
            State3 = State2#team{join_type = JoinType, password = Password},
            lib_team:send_team(State3, BinData),
            lib_team:send_team_info(State3),
            State3;
        take_over ->
            State2;
        _ ->
            {ok, BinData} = pt_240:write(24017, [Code, ActivityId, SubTypeId, SceneId, LvMin, LvMax, JoinType, Password]),
            lib_team:send_to_uid(Node, RoleId, BinData),
            State2
    end,
    {noreply, NewState};

%% 申请仲裁
handle_cast({Node, {'arbitrate_req', RoleId, ActivityId, SubTypeId, Data}}, State) ->
    #team{is_matching = IsMatching, leader_id = LeaderId} = State,
    if
        IsMatching =/= 0 ->
            {_, TmpState} = handle_cast({Node, {'set_matching_state', LeaderId, 0}}, State);
        true ->
            TmpState = State
    end,
    {ok, NewState} = lib_team_mod:arbitrate_req(TmpState, RoleId, Node, ActivityId, SubTypeId, Data),
    {noreply, NewState};

%% 回应仲裁
handle_cast({Node, {'arbitrate_res', RoleId, ArbitrateId, Res}}, State) ->
    {ok, NewState} = lib_team_mod:arbitrate_res(State, RoleId, ArbitrateId, Res, Node),
    {noreply, NewState};

% %% 登录马上归队 %%暂时没用了
% handle_cast({'login_back_to_team', MbInfo}, State) ->
%     #mb{id = RoleId} = MbInfo,
%     #team{member = Members, cls_type = ClsType, free_location = FreeLocation} = State,
%     case lists:keyfind(RoleId, #mb.id, Members) of
%         false ->
%             %% case lists:any(fun
%             %%     (#mb{online = Online}) ->
%             %%         Online =:= 1
%             %% end, Members) of
%             %%     true -> %% 有人在线
%             [Use | Free] = FreeLocation,
%             NewMemberList = State#team.member ++ [MbInfo#mb{location = Use}],
%             %% 技能更新
%             NewTeamSkill = set_member_team_skill(ClsType, NewMemberList),
%             NewState = State#team{member = NewMemberList, free_location = Free, team_skill = NewTeamSkill},
%             %% NewState2 = lib_team:extand_exp(RoleId ,NewState),
%             %% 更新域外战场分享概率
%             NewState2 = lib_team:extand_share_ratio(NewState),
%             %% 设置队伍的好友亲密度buff
%             lib_relationship:deal_intimacy_buff_in_team(Members, NewMemberList),
%             NewState3 = delay_notify_teammates_update(NewState2),
%             %%  _ ->
%             %%         case lists:keytake(?TEAM_LEADER, #mb.positon, Members) of
%             %%             {value, OldLearderMb, OtherMb} ->

%             %%         end
%             %% end,

%             {noreply, NewState3};
%         _ ->
%             {noreply, State}
%     end;

%% 上线归队
% handle_cast({'back_to_team', MbInfo}, State) ->
%     #mb{id = RoleId, pid = RolePid, figure=#figure{name=Name}} = MbInfo,
%     #team{member = Members, leader_id = LeaderId, max_num = MaxMemberNum} = State,
%     case lists:keyfind(RoleId, #mb.id, Members) of
%         false ->
%             {ok, BinData} = pt_110:write(11020, data_team_text:get_team_msg(13)),
%             lib_server_send:send_to_uid(RoleId, BinData),
%             {noreply, State};
%         _ ->
%             case length(Members) > MaxMemberNum of
%                 false ->
%                     %% 3.更新玩家进程和场景进程的数据，并告诉附近的玩家.
%                     case LeaderId =:= RoleId of
%                         true ->
%                             gen_server:cast(RolePid, {'set_team', self(), 1, LeaderId});
%                         false ->
%                             gen_server:cast(RolePid, {'set_team', self(), 2, LeaderId})
%                     end,
%                     %% 4.对其他队员进行队伍信息广播.
%                     lib_team:send_team_info(State),
%                     %% 5.发送通知：归队了.
%                     {ok, BinData1} = pt_110:write(11020, lists:concat([Name, data_team_text:get_team_msg(7)])),
%                     lib_team:send_team(State, BinData1),
%                     %% 6.发送通知：你成功进入离线前的队伍.
%                     {ok, BinData2} = pt_110:write(11020, data_team_text:get_team_msg(8)),
%                     lib_chat:rpc_send_msg_one(RoleId, BinData2),
%                     {noreply, State};
%                 true ->
%                     {noreply, State}
%             end
%     end;

handle_cast({_Node, {'send_to_team', Bin}}, State) ->
    lib_team:send_team(State, Bin),
    {noreply, State};

handle_cast({_Node, {'send_to_team', SceneId, ScenePoolId, CopyId, Bin}}, State) ->
    lib_team:send_team(State, SceneId, ScenePoolId, CopyId, Bin),
    {noreply, State};

handle_cast({_Node, {'alloc_drop', MonStatus, Alloc, TeamRoles, KList}}, State) ->
    #mon_args{boss = Boss} = MonStatus,
    %% 星域幻魔特殊处理
    case lists:member(Boss, ?BOSS_TYPE_LIST) of
        true ->
            #team{member = Member} = State,
            Now = utime:unixtime(),
            F = fun(#mb{id = Rid, welfare = Welfare}, Add) ->
                case lists:keyfind(Rid, #mon_atter.id, TeamRoles) of
                    #mon_atter{} ->
                        TypeList = [Type || {Type, EndTime}<- Welfare, EndTime >= Now andalso Type =/= ?WELFARE_SUBTYPE_WEEK],
                        NAdd =
                        case TypeList of
                            [_Type1,_Type2|_] -> ?WELFARE_MONTH_AND_QUARTER_ADD;
                            [?WELFARE_SUBTYPE_MONTH|_] ->  ?WELFARE_MONTH_ADD;
                            [?WELFARE_SUBTYPE_QUARTER|_] ->  ?WELFARE_QUARTER_ADD;
                            _ -> 0
                        end,
                        if
                            NAdd > Add -> NAdd;
                            true -> Add
                        end;
                    _ ->
                        Add
                end
                 end,
            Radio = lists:foldl(F, 0, Member);
        false ->
            Radio = 0
    end,
    case catch drop:alloc_drop_in_team(MonStatus, Alloc, TeamRoles, KList, Radio) of
        {'EXIT', Reason} -> ?ERR("alloc_drop error MonStatus=~p,~nAlloc=~p~n Reason: ~p", [ MonStatus, Alloc, Reason]);
        _ -> skip
    end,
    {noreply, State};

handle_cast({_Node, {'alloc_hunting_award', _Color}}, State) ->
    % #team{leader_id=LeaderId, member=MemberList} = State,
    % case catch lib_hunting_mod:alloc_hunting_award_in_team(Color, LeaderId, MemberList) of
    %    {'EXIT', Reason} -> ?ERR("alloc_hunting_award error Color=~p~n Reason: ~p", [Color, Reason]);
    %    _ -> skip
    % end,
    {noreply, State};

%% 调用队员lib_player:update_player_info/2函数
handle_cast({_Node, {'update_mb_info', Args}}, State) ->
    F = fun({bonfire_exp, _}, L) -> L;
        (T, L) -> [T|L]
    end,
    [begin
                %% 所有助战都没有篝火加成
                case Mb#mb.help_type == ?HELP_TYPE_YES of
                    true -> NewArgs = lists:reverse(lists:foldl(F, [], Args));
                    false -> NewArgs = Args
                end,
                %% ?PRINT("update_mb_info ID:~p NewArgs:~p", [Mb#mb.id, NewArgs]),
                lib_team:update_mb_info(State#team.cls_type, Mb, NewArgs)
        end|| Mb <- State#team.member],
    {noreply, State};

%% 更改队员场景
handle_cast({_Node, {'change_my_position', Id, Scene, ScenePoolId, CopyId, X, Y}}, State) ->
    #team{member=Mbs, leader_id = LeaderId, enlist = Enlist, cls_type = ClsType}=State,
    case lists:keyfind(Id, #mb.id, Mbs) of
        false -> {noreply, State};
        _ ->
            DungeonScene = case Enlist of
                #team_enlist{scene_id = SceneIdTemp} -> SceneIdTemp;
                _ -> 0
            end,
            F = fun
                (M) ->
                    case M#mb.id =:= Id orelse (Id =:= LeaderId andalso lib_team:is_fake_mb(M) andalso DungeonScene == Scene)  of
                        true ->
                            M#mb{scene=Scene, scene_pool_id=ScenePoolId, copy_id=CopyId, x = X, y = Y};
                        _ ->
                            M
                    end
            end,
            NewMbs = [F(M) || M <- Mbs],
            NewState = State#team{member = NewMbs},
            {ok, BinData} = pt_240:write(24051, [Id, Scene]),
            lib_team:send_team(NewState, BinData),
            NewState2 = lib_team_mod:delay_notify_teammates_update(NewState),
            set_member_team_skill(ClsType, NewMbs),
            {noreply, NewState2}
    end;

%% 获取队员场景信息
handle_cast({_Node, {'get_mb_scene', Id, InfoId}}, State) ->
    #team{cls_type=ClsType, member = Mbs} = State,
    case ClsType of
        ?NODE_CENTER -> {noreply, State};
        _ ->
            case lists:keyfind(InfoId, #mb.id, Mbs) of
                false -> {noreply, State};
                #mb{node = MNode} ->
                    IsFollow = case lists:keyfind(Id, #mb.id, Mbs) of
                        #mb{follow_id=InfoId} -> 1;
                        _ -> 0
                    end,
                    lib_player:apply_cast(MNode, InfoId, ?APPLY_CAST_STATUS, ?NOT_HAND_OFFLINE, lib_team, get_mb_scene, [Id, IsFollow]),
                    {noreply, State}
            end
    end;

%% 跟战
handle_cast({_Node, {'follow_someone', Type, Id, FollowId}}, State) ->
    #team{cls_type=ClsType, member = Mbs} = State,
    case ClsType of
        ?NODE_CENTER -> {noreply, State};
        _ ->
            case Type == 1 of
                true ->
                    case lists:keyfind(FollowId, #mb.id, Mbs) of
                        false -> {noreply, State};
                        Mb ->
                            NewMbs = case lists:keyfind(Id, #mb.id, Mbs) of
                                false -> Mbs;
                                MyMb  -> lists:keyreplace(Id, #mb.id, Mbs, MyMb#mb{follow_id=FollowId})
                            end,

                            {ok, BinData} = pt_240:write(24024, [1, FollowId]),
                            lib_server_send:send_to_uid(Id, BinData),

                            Follows = [Id | lists:delete(Id, Mb#mb.follows)],
                            lib_player:update_player_info(FollowId, [{follows, Follows}]),
                            NewMbs1 = lists:keyreplace(FollowId, #mb.id, NewMbs, Mb#mb{follows=Follows}),

                            {noreply, State#team{member=NewMbs1}}
                    end;
                false ->
                    NewState = lib_team:cancel_follow(State, Id),
                    {noreply, NewState}
            end
    end;

%% 取消别人跟战
handle_cast({_Node, {'cancel_other_follow', RoleId}}, State) ->
    #team{cls_type=ClsType, member = Mbs} = State,
    case ClsType of
        ?NODE_CENTER -> {noreply, State};
        _ ->
            F = fun(#mb{id = Id, follow_id = FollowId}, {Num,TempState})->
                    case FollowId =:= RoleId of
                        true ->
                            NewState = lib_team:cancel_follow(TempState, Id),
                            {Num+1, NewState};
                        false ->
                            {Num, TempState}
                    end
            end,
            {Result,LastState} = lists:foldl(F, {0,State}, Mbs),
            case Result == 0 of
                true->
                    {ok, BinData} = pt_240:write(24039, [?ERRCODE(err240_no_member_follow)]),
                    lib_team:send_to_uid(_Node, RoleId, BinData);
                false->
                    {ok, BinData} = pt_240:write(24039, [?ERRCODE(err240_cancel_follow_success)]),
                    lib_team:send_to_uid(_Node, RoleId, BinData)
            end,
            {noreply, LastState}
    end;

%% 获取跟随着的玩家id
handle_cast({_Node, {'get_follow_id', Id}}, State) ->
    #team{cls_type=ClsType, member = Mbs} = State,
    case ClsType of
        ?NODE_CENTER -> {noreply, State};
        _ ->
            case lists:keyfind(Id, #mb.id, Mbs) of
                false -> {noreply, State};
                Mb    ->
                    % ?PRINT("follow_id ~p~n", [Mb#mb.follow_id]),
                    {ok, BinData} = pt_240:write(24026, [Mb#mb.follow_id]),
                    lib_server_send:send_to_uid(Id, BinData),
                    {noreply, State}
            end
    end;

%% 助战
handle_cast({_Node, {'set_help_type', RoleId, DunId, HelpType}}, State) ->
    #team{member = Mbs, leader_id = Leader, cls_type = ClsType, id = TeamId, enlist = Enlist} = State,
    case Enlist of
        #team_enlist{dun_id = DunId} ->
            case lists:keyfind(RoleId, #mb.id, Mbs) of
                false -> {noreply, State};
                Mb  ->
                    Leader =:= Mb#mb.id andalso mod_team_enlist:change_team(ClsType, TeamId, [{set_help_type, {RoleId, HelpType}}]),
                    NewMbs = lists:keyreplace(RoleId, #mb.id, Mbs, Mb#mb{help_type = HelpType}),
                    NewState = State#team{member = NewMbs},
                    {ok, BinData2} = pt_240:write(24034, [[{RoleId, HelpType}]]),
                    lib_team:send_team(NewState, BinData2),
                    {noreply, NewState}
            end;
        _ ->
            {noreply, State}
    end;

%% 与赏金怪物对话
handle_cast({_Node, {'talk_to_mon', Scene, ScenePoolId, RoleId, MonId}}, State) ->
    #team{member=MemberList} = State,
    MemberIdList = [Id||#mb{id = Id} <- MemberList],
    MemberLen = length(MemberIdList),
    NeedNum   = 0, % lib_hunting_api:get_need_member_num(),
    if
        MemberLen>=NeedNum ->
            mod_scene_agent:apply_cast(Scene, ScenePoolId, lib_battle, talk_to_mon, [RoleId, MemberIdList, MonId]);
        true ->
            lib_server_send:send_to_uid(RoleId, pt_200, 20011, [4])
    end,
    {noreply, State};

%% 处理升级回调事件
handle_cast({_Node, {'event_lv_up', PlayerId, Lv} }, State) ->
    #team{member=Mbs}=State,
    case lists:keyfind(PlayerId, #mb.id, Mbs) of
        false -> {noreply, State};
        Mb    ->
            Figure = Mb#mb.figure,
            NewMbs = lists:keyreplace(PlayerId, #mb.id, Mbs, Mb#mb{figure = Figure#figure{lv = Lv}}),
            NewState = State#team{member = NewMbs},
            {noreply, NewState}
    end;

%% 处理角色改名回调事件
handle_cast({_Node, {'event_rename', PlayerId, Name} }, State) ->
    #team{member=Mbs}=State,
    case lists:keyfind(PlayerId, #mb.id, Mbs) of
        false -> {noreply, State};
        Mb    ->
            Figure = Mb#mb.figure,
            NewMbs = lists:keyreplace(PlayerId, #mb.id, Mbs, Mb#mb{figure = Figure#figure{name = Name}}),
            NewState = State#team{member = NewMbs},
            lib_team:send_team_info(NewState),
            {noreply, NewState}
    end;

%% 更新数据
handle_cast({_Node, {'update_team_mb', RoleId, AttrList} }, State) ->
    {ok, NewState} = lib_team_mod:update_team_mb(State, RoleId, AttrList),
    {noreply, NewState};

%% 更新玩家的在线状态
handle_cast({_Node, {'online_flag', RoleId, Online, NewSid}}, State) ->
    #team{leader_id = LeaderId, member = Mbs, cls_type = ClsType, id = TeamId}=State,
    case lists:keyfind(RoleId, #mb.id, Mbs) of
        false -> {noreply, State};
        #mb{online = Online} -> {noreply, State};
        #mb{} = Mb ->
            Sid = NewSid,
            NewMbs = lists:keyreplace(RoleId, #mb.id, Mbs, Mb#mb{online = Online, sid = Sid}),
            RoleId == LeaderId andalso mod_team_enlist:change_team(ClsType, TeamId, [{leader_online, {LeaderId, Online}}]),
%%            if
%%                RoleId == LeaderId andalso IsMatching == 1->
%%                    MatchingState = 0,
%%                    {_Code, NewState} = lib_team_mod:set_team_matching_state(State, MatchingState),
%%                    #team{enlist = #team_enlist{activity_id = ActivityId, subtype_id = SubTypeId}} = NewState,
%%                    {ok, BinData} = pt_240:write(24048, [1, MatchingState, ActivityId, SubTypeId, RoleId]),
%%                    lib_team:send_team(NewState, BinData, RoleId);
%%                true ->
%%                    NewState = State
%%            end,
            NewState1 = lib_team_mod:delay_notify_teammates_update(State#team{member = NewMbs}),
            {ok, Bin} = pt_240:write(24052, [RoleId, Online]),
            lib_team:send_team(NewState1, Bin, RoleId),
            {noreply, NewState1}
    end;

%% socket重新连接
%% handle_cast({_Node, {'inerrupt_follow', Id}}, State) ->
%%     #team{member=Mbs}=State,
%%     case lists:keyfind(Id, #mb.id, Mbs) of
%%         false -> {noreply, State};
%%         _Mb ->
%%             NewState = lib_team:cancel_follow(State, Id),
%%             {noreply, NewState}
%%     end;

%% 跟踪目标返回移动数据
handle_cast({_Node, {'change_location', Id, SceneId, ScenePoolId, CopyId, X, Y}}, State) ->
    #team{cls_type = ClsType, member = Mbs, id = TeamId, leader_id = LeaderId} = State,
    case lists:keyfind(Id, #mb.id, Mbs) of
        Mb = #mb{} ->
            case ClsType of
                ?NODE_CENTER -> ignore;
                _ ->
                    [
                        lib_player:update_player_info(
                            EId,
                            [{change_location, [SceneId, ScenePoolId, CopyId, X, Y]}]
                        ) || EId <- Mb#mb.follows
                    ],
                    Id =:= LeaderId andalso mod_team_enlist:change_team(
                        ClsType, TeamId, [{leader_position_xy, {LeaderId, SceneId, X, Y}}]
                    )
            end;
        _False ->
            ignore
    end,
    {noreply, State};

%% 更新技能
handle_cast({_Node, {update_skill, RoleId, SkillId}}, State = #team{member = MemberList, cls_type = ClsType}) ->
    case lists:keyfind(RoleId, #mb.id, MemberList) of
        #mb{skill = SkillId} ->
            {noreply, State};
        #mb{} = Mb ->
            NewMb = Mb#mb{skill = SkillId},
            NewMemberList = lists:keystore(RoleId, #mb.id, MemberList, NewMb),
            NewState = State#team{member = NewMemberList},
            set_member_team_skill(ClsType, NewMemberList),
            {noreply, NewState};
        _ ->
            {noreply, State}
    end;

%% 分享队员经验
handle_cast({_Node, {'share_mon_exp', FromId, Exp, SceneId, ScenePoolId, CopyId}}, State) ->
    #team{rela = Rela, member=Members} = State,
    F = fun(Mb) ->
            case Mb of
                #mb{id=TmpId, scene=SceneId, scene_pool_id=ScenePoolId, copy_id=CopyId, node = MNode} ->
                    Args = case find_intimacy(Rela, FromId, TmpId) of
                        0 -> [];
                        Intimacy -> [{intimacy, Intimacy}]
                    end,
                    lib_player:apply_cast(MNode, TmpId, ?APPLY_CAST_SAVE, ?NOT_HAND_OFFLINE, lib_player, add_exp, [Exp, 5, Args]);
                _ -> skip
            end
    end,
    lists:foreach(F, Members),
    {noreply, State};

%% 分享队员经验
handle_cast({_Node, {'kill_mon',AtterId,Mid}}, #team{cls_type = ?NODE_GAME} = State) ->
    #team{member=Members} = State,
    [ begin
        lib_task_api:kill_mon(Mb#mb.id, Mid),
        case data_mon:get(Mid) of
            #mon{boss=Boss}->
                lib_task_api:kill_boss(Mb#mb.id, Mb#mb.scene, Boss);
            _->
                skip
        end
    end ||Mb<-Members, Mb#mb.id =/= AtterId],
    {noreply, State};

%% 跨服的不管 20181205 不管不行
handle_cast({_Node, {'kill_mon',AtterId,Mid}}, State) ->
    #team{member=Members} = State,
    case lists:keyfind(AtterId,#mb.id,Members) of
        #mb{platform=PForm,server_num=SerN,scene=Scene}->
            [begin
                #mb{id=Rid,node=Node0,platform=PForm0,server_num=SerN0,scene=Scene0}=Mb0,
                case PForm0==PForm andalso SerN0==SerN andalso Scene0==Scene of
                    true->
                        clusters_center:apply_cast(Node0, lib_task_api, kill_mon, [Rid,Mid]),
                        case data_mon:get(Mid) of
                            #mon{boss=Boss}->
                                clusters_center:apply_cast(Node0, lib_task_api, kill_boss, [Rid,Scene0,Boss]);
                            _->
                                skip
                        end;
                    _->
                        skip
                end
            end || Mb0<-Members, Mb0#mb.id =/= AtterId];
        _->
            skip
    end,
    {noreply, State};

%% 广播野外修炼
handle_cast({_Node, {'outdoor_training', SceneId, MonId, X, Y}}, State) ->
    {ok, BinData} = pt_240:write(24043, [SceneId, MonId, X, Y]),
    lib_team:send_team(State, BinData),
    {noreply, State};

handle_cast({Node, {'get_reqlist', RoleId}}, State) ->
    #team{leader_id = LeaderId, reqlist = ReqList} = State,
    if
        RoleId =:= LeaderId ->
            Data = [{MbServ, MbId, Figure} || #mb{id = MbId, server_num = MbServ, figure = Figure} <- ReqList],
            {ok, BinData} = pt_240:write(24047, [Data]),
            lib_team:send_to_uid(Node, RoleId, BinData);
        true ->
            skip
    end,
    {noreply, State};

handle_cast({_Node, {'clear_teams_reqlist_by_id', RoleId}}, State) ->
    #team{reqlist = ReqList} = State,
    case lists:keyfind(RoleId, #mb.id, ReqList) of
        false ->
            {noreply, State};
        _ ->
            NewReqList = lists:keydelete(RoleId, #mb.id, ReqList),
            {noreply, State#team{reqlist = NewReqList}}
    end;

%% 取消匹配状态时直接处理
handle_cast({_Node, {'set_matching_state', RoleId, 0}}, State) ->
    NewState = lib_team_mod:set_matching_state(State, RoleId, 0),
    {noreply, NewState};

%% 开始匹配状态时需要判断其他人的状态
handle_cast({_Node, {'set_matching_state', RoleId, 1}}, State) ->
    NeedToCheck = [ {Node, Id}|| #mb{id = Id, node = Node} = One <- State#team.member, Id /= RoleId, not lib_team:is_fake_mb(One)],
    handle_cast({_Node, {'do_set_matching_state', RoleId, NeedToCheck, {RoleId, free, ?SCENE_TYPE_OUTSIDE}}}, State);

%%
handle_cast({_Node, {'do_set_matching_state', RoleId, NeedToCheck, {From, Lock, SceneType}}}, State) ->
    Res = if
        SceneType =/= ?SCENE_TYPE_OUTSIDE -> false;
        Lock =/= free -> false;
        true -> true
    end,
    case Res of
        true ->
            case NeedToCheck of
                [] ->
                    NewState = lib_team_mod:set_matching_state(State, RoleId, 1),
                    {noreply, NewState};
                _  ->
                    lib_team:check_can_match(RoleId, State#team.cls_type, NeedToCheck),
                    {noreply, State}
            end;
        false ->
            #team{enlist = #team_enlist{activity_id = ActivityId, subtype_id = SubTypeId}} = State,
            {ok, BinData} = pt_240:write(24048, [?FAIL, 1, ActivityId, SubTypeId, From]),
            lib_team:send_team(State, BinData),
            {noreply, State}
    end;

handle_cast({Node, {'set_join_type', RoleId, JoinType}}, State)
when (JoinType =:= 1 orelse JoinType =:= 2) andalso JoinType /= State#team.join_type->
    if
        RoleId /= State#team.leader_id ->
            {noreply, State};
        true ->
            NewState = State#team{join_type = JoinType},
            #team{cls_type=ClsType, id = TeamId} = NewState,
            {ok, BinData} = pt_240:write(24055, [JoinType]),
            lib_team:send_to_uid(Node, RoleId, BinData),
            mod_team_enlist:change_team(ClsType, TeamId, [{join_type, JoinType}]),
            {noreply, NewState}
    end;

handle_cast({Node, {'force_set_join_type', EnterType, RoleId, JoinType}}, State)
when (JoinType == 1 orelse JoinType == 2) ->
    #team{join_type = OldJoinType, member = Members} = State,
    if EnterType == enter_boss_scene ->
            NewState = State#team{join_type = JoinType};
        EnterType == exit_boss_scene ->
            case lists:any(fun(#mb{scene = Scene}) -> 
                    IsDesertedScene = local_boss_api:is_deserted_boss_scene(Scene), 
                    IsRewardScene = local_boss_api:is_reward_boss_scene(Scene),
                    IsDesertedScene orelse IsRewardScene end, Members) of
                true ->
                    NewState = State;
                _ ->
                    NewState = State#team{join_type = OldJoinType}
            end
    end,
    #team{cls_type = ClsType, id = TeamId} = NewState,
    {ok, BinData} = pt_240:write(24055, [JoinType]),
    lib_team:send_to_uid(Node, RoleId, BinData),
    mod_team_enlist:change_team(ClsType, TeamId, [{join_type, JoinType}]),
    {noreply, NewState};

handle_cast({Node, {'set_matching', RoleId, ActivityId, SubTypeId, MentorArgs}}, #team{is_matching = 0} = State) ->
    #team{enlist = EnList, join_type = JoinType, password = Password} = State,
    case EnList of
        #team_enlist{activity_id = ActivityId, subtype_id = SubTypeId} ->
            handle_cast({Node, {'set_matching_state', RoleId, 1}}, State);
        _ ->
            CheckState = State#team{enlist = EnList#team_enlist{activity_id = ActivityId, subtype_id = SubTypeId}},
            case lib_team_mod:check_team_matching_state(CheckState, RoleId, State) of
                true ->
                    #team_enlist_cfg{default_lv_min = LvMin, default_lv_max = LvMax} = data_team_ui:get(ActivityId, SubTypeId),
                    case lib_team_mod:check_change_team_enlist(State, RoleId, ActivityId, SubTypeId, LvMin, LvMax, MentorArgs) of
                        {true, Cfg} ->
                            %% 先改目标
                            ChangedState = lib_team_mod:change_team_enlist(State, Cfg, 0, LvMin, LvMax, Password),
                            {ok, BinData} = pt_240:write(24017, [?SUCCESS, ActivityId, SubTypeId, 0, LvMin, LvMax, JoinType, Password]),
                            lib_team:send_team(ChangedState, BinData),
                            %% 设置匹配
                            {Code, NewState} = lib_team_mod:set_team_matching_state(ChangedState, 1),
                            if
                                Code =:= skip ->
                                    skip;
                                true ->
                                    {ok, BinData1} = pt_240:write(24048, [Code, 1, ActivityId, SubTypeId, RoleId]),
                                    lib_team:send_team(NewState, BinData1)
                            end,
                            {noreply, NewState};
                        {false, Code} ->
                            {ok, BinData} = pt_240:write(24048, [Code, 1, ActivityId, SubTypeId, RoleId]),
                            lib_team:send_to_uid(Node, RoleId, BinData),
                            {noreply, State};
                        {take_over, TargetClsType} ->
                            PtArgs = [1, ActivityId, SubTypeId, RoleId],
                            TakeOverInfo = [{lv, [LvMin, LvMax]}, {take_over, [self(), {set_matching, PtArgs}, set_matching]}],
                            FailReturn = {set_matching, Node, RoleId, PtArgs},
                            TmpState = take_over(ActivityId, SubTypeId, 0, TakeOverInfo, FailReturn, Node, TargetClsType, State),
                            {noreply, TmpState}
                    end;
                {false, Code} ->
                    {ok, BinData} = pt_240:write(24048, [Code, 1, ActivityId, SubTypeId, RoleId]),
                    lib_team:send_to_uid(Node, RoleId, BinData),
                    {noreply, State}
            end
    end;

%% 队长离线挂机进入自动匹配队列
handle_cast({_Node, {'onhook_team_to_match', RoleId}}, State) ->
    #team{
        id = TeamId, cls_type=ClsType, member = Members, target_enlist = Target, max_num = MaxMemberNum
        ,join_type = JoinType, password = Password
    } = State,
    case lists:keyfind(RoleId, #mb.id, Members) of
        false -> {noreply, State};
        #mb{scene = SceneId} = _Mb ->
            {NewTarget, LvMin, LvMax} = lib_team:get_onhook_target_type(SceneId),
            #team_enlist{ activity_id = ActId, subtype_id = SubTypeId} = NewTarget,
            mod_team_enlist:change_team(ClsType, TeamId, [{enlist, Target, NewTarget}, {lv, LvMin, LvMax}]),
            {ok, BinData} = pt_240:write(24017, [1, ActId, SubTypeId, SceneId, LvMin, LvMax, JoinType, Password]),
            lib_team:send_team(State, BinData),
            case length(Members) >= MaxMemberNum of
                true ->
                    {noreply, State#team{enlist = NewTarget, target_enlist = NewTarget, lv_limit_min = LvMin, lv_limit_max = LvMax}};
                false ->
                    NewState = State#team{enlist = NewTarget, target_enlist = NewTarget, lv_limit_min = LvMin, lv_limit_max = LvMax},
                    handle_cast({_Node, {'set_matching_state', RoleId, 1}}, NewState)
            end
    end;

handle_cast({_Node, {'ready_for_match', RoleId, Data}}, State) ->
    #team{member = Mbs, is_matching = MatchingState, enlist = EnList} = State,
    if
        MatchingState > 255 ->
            case lists:keyfind(RoleId, #mb.id, Mbs) of
                Mb when is_record(Mb, mb) ->
                    NewMbs = lists:keystore(RoleId, #mb.id, Mbs, Mb#mb{match_ok = 1, target_start_data = Data}),
                    NewState = State#team{member = NewMbs},
                    case lists:all(fun (#mb{match_ok = Ok}) -> Ok =:= 1 end, NewMbs) of
                        true ->
                            #team_enlist{activity_id = ActivityId, subtype_id = SubTypeId} = EnList,
                            {ok, BinData} = pt_240:write(24023, [?SUCCESS, ActivityId, SubTypeId]),
                            lib_team:send_team(NewState, BinData),
                            case lib_team_match:get_match_mod(ActivityId, SubTypeId) of
                                undefined ->
                                    {noreply, NewState};
                                Mod ->
                                    NewState1 = Mod:all_ready_for_match(NewState),
                                    {noreply, NewState1}
                            end;
                        _ ->
                            {noreply, NewState}
                    end;
                _ ->
                    {noreply, State}
            end;
        true ->
            {noreply, State}
    end;

handle_cast({_Node, {'fail_for_match', RoleId, OtherErrorCode}}, State) ->
    #team{member = Mbs, is_matching = MatchingState} = State,
    if
        MatchingState > 255 ->
            case lists:keyfind(RoleId, #mb.id, Mbs) of
                Mb when is_record(Mb, mb) ->
                    NewMbs = [M#mb{match_ok = 0, target_start_data = []} || M <- Mbs],
                    NewState = State#team{member = NewMbs, is_matching = 0},
                    {ErrorCodeInt, ErrorCodeArgs} = util:parse_error_code(OtherErrorCode),
                    {ok, BinData} = pt_240:write(24038, [ErrorCodeInt, ErrorCodeArgs]),
                    lib_team:send_team(NewState, BinData),
                    {noreply, NewState};
                _ ->
                    {noreply, State}
            end;
        true ->
            {noreply, State}
    end;

%% 提醒队长开车
handle_cast({_Node, {notice_leader_go, Sid}}, State) ->
    #team{leader_id = Leader, leader_node = LeaderNode} = State,
    {ok, Bin} = pt_240:write(24057, [?SUCCESS]),
    lib_server_send:send_to_uid(LeaderNode, Leader, Bin),
    lib_server_send:send_to_sid(Sid, pt_240, 24056, [1]),
    {noreply, State};
%% 助战完后，刷新队伍里面的助战次数
handle_cast({_Node, {update_help_counts, RoleId, LeftNum}}, State) ->
    #team{leader_id = Leader, cls_type = ClsType, id = TeamId} = State,
    RoleId =:= Leader andalso mod_team_enlist:change_team(ClsType, TeamId, [{help_counts, {RoleId, LeftNum}}]),
    {noreply, State};

%% 设置密码和战力限制
handle_cast({_Node, {'set_up_password', _Node1, _RoleId, Password, Power}}, State) ->
    NewState = State#team{power_limit = Power, password = Password},
    Bin = lib_team:get_team_info_bin(NewState),
    lib_team:send_team(NewState, Bin),
    {noreply, NewState};

handle_cast(stop, State) ->
    {stop, normal, State};

handle_cast(_R, State) ->
    {noreply, State}.


%% 设置玩家的被动技能
set_member_team_skill(ClsType, MemberList)->
    Fun = fun(#mb{id = RoleId, skill = SkillId}, TSkills) ->
            ?IF(SkillId == 0, TSkills, [{RoleId, SkillId}|TSkills])
    end,
    case lists:foldl(Fun, [], MemberList) of
        [] -> [];
        TeamSkills ->
            %% 计算跟自己的同场景的玩家，有技能的玩家
            F = fun(#mb{id = RoleId, node = Node} = Mb) ->
                    %% 计算自己同场景的玩家
                    {SetSkillId, SkillBuffNum} = calc_team_skill_buff_num(MemberList, Mb, 0, 0),
                    mod_team:cast_to_game(ClsType, Node, lib_player, update_player_info, [RoleId, [{team_skill, {SetSkillId, SkillBuffNum}}]])
            end,
            [F(M) || M <- MemberList],
            TeamSkills
    end.

%% 计算同场景的玩家数据
calc_team_skill_buff_num([], _Mb, SkillId, BuffNum) ->
    {SkillId, BuffNum};
calc_team_skill_buff_num([H|T], Mb, TSkillId, BuffNum)->
    #mb{id = HRoleId, skill = HSkillId, scene = HScene, scene_pool_id = HPoolId, copy_id = HCopyId} = H,
    #mb{id = RoleId, scene = Scene, scene_pool_id = PoolId, copy_id = CopyId} = Mb,
    if
        HRoleId =:= RoleId andalso HSkillId =:= 0 ->
            %% 自己无技能
            calc_team_skill_buff_num(T, Mb, TSkillId, BuffNum);
        HRoleId =:= RoleId ->
            %% 自己有技能
            calc_team_skill_buff_num(T, Mb, HSkillId, BuffNum + 1);
        HSkillId =:= 0 ->
            %% 其他人，没有技能
            calc_team_skill_buff_num(T, Mb, TSkillId, BuffNum);
        {HScene, HPoolId, HCopyId} =/= {Scene, PoolId, CopyId} ->
            %% 其他人，不在同一场景
            calc_team_skill_buff_num(T, Mb, TSkillId, BuffNum);
        true ->
            %% 其他人，在同场景且有技能
            calc_team_skill_buff_num(T, Mb, HSkillId, BuffNum + 1)
    end.

%% 加入队伍
join_team(Node, MbInfo, State) ->
    #team{id = TeamId, enlist = EnList} = State,
    #mb{help_type = HelpType, pid = RolePid} = MbInfo,
    %% 先变更玩家角色组队状态，防止角色同时加入多个组队
    %% 只等待2s，超时算失败
    Args = [TeamId, EnList, HelpType],
    MFA = {lib_team, join_team_success, Args},
    try gen_server:call(RolePid, {fast_call, MFA}, 2000) of
        {false, _Rea} -> %% 角色已经加入其它组队
            State;
        {ok} ->
            join_team_do(Node, MbInfo, State);
        _Err ->
            ?ERR("~w:join_team_error:~p~n", [?MODULE, _Err]),
            State
        catch Class:Reason -> %% 超时之类的
            Error = {Class, Reason, erlang:get_stacktrace()},
            ?ERR("~w:join_team_error:~p~n", [?MODULE, Error]),
            State
    end.
join_team_do(Node, MbInfo, State) ->
    #team{
        id = TeamId, cls_type = ClsType, free_location = FreeLoaction, member = MemberList
        ,rela = OldRela, pre_num_full = OldPreNumFull, his_teammate = HisTeammate
        ,is_matching = IsMatching, leader_name = LeaderName
    } = State,
    #mb{id=RoleId} = MbInfo,
    lib_team:notify_team_change(
        Node, ?ERRCODE(err240_join_team), ?ERRCODE(err240_new_member), 2, MbInfo, State
    ),
    [Free | T] = FreeLoaction,
    lib_team_mod:set_member_attr(State, MbInfo#mb.node, MbInfo#mb.id, ?TEAM_MEMBER, TeamId, LeaderName),
    %% MbInfoAfHelp = lib_team_mod:auto_trans_help_type_by_mb(MbInfo, EnList, ?HELP_TYPE_TRANS_ANY),
    NewMemberList = [MbInfo#mb{location = Free} | MemberList],
    PreNumFull = get_pre_num_full(OldPreNumFull, NewMemberList),
    Rela = ?IF(ClsType =:= ?NODE_GAME, handle_rela(MbInfo, MemberList, OldRela), OldRela),
    TeamSkills = set_member_team_skill(ClsType, NewMemberList),
    NewState1 = lib_team_mod:delay_notify_teammates_update(State),

    NewState0 = NewState1#team{
        free_location=T, member=NewMemberList, rela=Rela, team_skill = TeamSkills,
        pre_num_full=PreNumFull, his_teammate=lists:usort([MbInfo#mb.id|HisTeammate])
    },
    %% lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, lib_team, send_ac_left_time, [EnList#team_enlist.activity_id]),
    mod_team_enlist:change_team(
        ClsType, TeamId, [{num, 1},{add_partner, MbInfo#mb.figure}]
    ),
    if
        T =:= [] andalso IsMatching =:= 1 ->
            mod_team_enlist:change_team(ClsType, TeamId, [{matching, 0}]),
            lib_team:when_change_match_status(NewState0, 0),
            NewState = case lib_team:handle_match_complete(NewState0) of
                {ok, S} ->
                    util:cancel_timer(State#team.fake_mb_ref),
                    S#team{is_matching = 0};
                _ ->
                    util:cancel_timer(State#team.fake_mb_ref),
                    NewState0#team{is_matching = 0}
            end;
        true ->
            IsMatching =:= 1 andalso lib_team:add_role_match(ClsType, Node, RoleId),
            NewState = NewState0
    end,

    lib_team:send_team_info(NewState),
    %% lib_team:handle_barbecue_buff(NewState, 2).
    NewState.

%% 加入亲密度
handle_rela(MbInfo, OldMembers, OldIntimacyL) ->
    RelaList = lib_relationship_api:get_rela_and_intimacy(MbInfo#mb.id, [Mb#mb.id|| Mb <- OldMembers]),
    F = fun({Id, _, Intimacy}, TmpIntimacyL) ->
            case Intimacy > 0 of
                true -> [{MbInfo#mb.id, Id, Intimacy} | TmpIntimacyL];
                _ -> TmpIntimacyL
            end
    end,
    lists:foldl(F, OldIntimacyL, RelaList).

%% 移除亲密度记录
del_rela([{IdA, IdB, _}|T], Id, Result) when IdA==Id orelse IdB==Id ->
    del_rela(T, Id, Result);
del_rela([H|T], Id, Result) ->
    del_rela(T, Id, [H|Result]);
del_rela([], _Id, Result) -> %?PRINT("DEL RELA ======= ~p~n", [Result]),
    Result.

%% 查找亲密度
find_intimacy([{IdA, IdB, Intimacy}|_], FromId, ToId) when (IdA==FromId andalso IdB==ToId) orelse (IdA==ToId andalso IdB==FromId) ->
    Intimacy;
find_intimacy([_|T], FromId, ToId) -> find_intimacy(T, FromId, ToId);
find_intimacy([], _, _) -> 0.

%% 队伍首次满4人之后不让再加人进入队伍
get_pre_num_full(OldPreNumFull, NewMemberList) ->
    case OldPreNumFull == 1 of
        true -> 1;
        _ ->
            case length(NewMemberList)>=4 of
                true -> 1;
                _ -> 0
            end
    end.

take_over(ActivityId, SubTypeId, SceneId, TakeOverInfo, FailReturn, Node, ClsType, State) ->
    #team{
        join_type = JoinType, member = Mbs, leader_id = LeaderId, power_limit = Power
        ,password = Password, lv_limit_max = LvMax, lv_limit_min = LvMin
        ,is_allow_mem_invite = IsInvite, is_task = IsTask, is_matching = AutoMatch
    } = State,
    RoleList = case Mbs of
        [#mb{id = LeaderId}|_] ->
            Mbs;
        _ ->
            {value, Leader, Others} = lists:keytake(LeaderId, #mb.id, Mbs),
            [Leader|Others]
    end,
    From = self(),
    TeamArgs = #team_args{
        create_type = ?CREATE_TYPE_TAKE_OVER, act_id = ActivityId
        ,act_sub_id = SubTypeId, scene_id = SceneId, join_type = JoinType
        ,password = Password, member = RoleList
        ,key_value_list = TakeOverInfo, lev_min = LvMin, lev_max = LvMax
        ,is_allow_mem_invite = IsInvite, is_task = IsTask, power = Power
        ,is_matching = AutoMatch
    },
    TargetNode = if
        ClsType =:= ?NODE_GAME ->
            Node;
        true ->
            config:get_cls_node()
    end,
    unode:apply(TargetNode, mod_team_create, create_for_take_over, [TeamArgs, From, FailReturn]),
    WaitingStatus = #waiting_status{time = utime:unixtime(), info = take_over},
    State#team{waiting_status = WaitingStatus}.

fake_mb_leave(Mbs, 0) ->
    [
        self() ! {fake_mb_leave, RoleId} || #mb{id = RoleId} = M <- Mbs, lib_team:is_fake_mb(M)
    ];

fake_mb_leave(_Mbs, _) -> ok.

%% 委任队长
delegate_leader(State) ->
    #team{
        id = TeamId, member = Mbs, cls_type = ClsType, enlist = #team_enlist{dun_id = DunId}
    } = State,
    case lists:keysort(#mb.join_time, [M || M <- Mbs, lib_team:is_fake_mb(M) =:= false]) of
        [NewLeaderInfo|_OtherMb] ->%% 新队长数据
            #mb{
                id = NewLeaderId, pid = NewLeaderPid, node = NewLeaderNode, figure=NewLeaderFigure,
                online = Online, help_type = HelpType, server_num = ServerNum
                ,scene = Scene, x = X, y = Y
            } = NewLeaderInfo,
            #figure{name = LeaderName} = NewLeaderFigure,
            NewState = State#team{
                leader_id = NewLeaderId, leader_pid = NewLeaderPid, leader_node = NewLeaderNode
                ,leader_name = LeaderName
            },
            lib_team_mod:set_member_attr(NewState, NewLeaderInfo#mb.node, NewLeaderId, ?TEAM_LEADER, TeamId, LeaderName),
            ChangeTeamArgs = [
                {leader, {NewLeaderFigure, ServerNum}},{quit_partner, NewLeaderId},
                {leader_online, {NewLeaderId, Online}}, {set_help_type, {NewLeaderId, HelpType}}
                ,{leader_position_xy, {NewLeaderId, Scene, X, Y}}
            ],
            mod_team_enlist:change_team(ClsType, TeamId, ChangeTeamArgs),
            lib_player:apply_cast(
                NewLeaderNode, NewLeaderId, ?APPLY_CAST_STATUS, ?NOT_HAND_OFFLINE
                ,lib_team, update_help_type, [DunId, TeamId, HelpType]
            ),
            lib_team_mod:set_member_leader_name(NewState),
            %% 发送队长变更信息
            {ok, BinData1} = pt_240:write(24015, [NewLeaderId]),
            lib_team:send_team(NewState, BinData1);
        _ ->
            NewState = State#team{
                leader_id = 0, leader_pid = undefined, leader_node = undefined
                ,leader_name = <<>>
            }
    end,
    fake_mb_leave(NewState#team.member, NewState#team.leader_id),
    NewState.
