%% ---------------------------------------------------------
%% Author:  zmh
%% Created: 2019-11-11
%% Description: 玩家幻光系统
%% --------------------------------------------------------
-module(lib_role_visus).
-compile(export_all).
-include("server.hrl").
-include("role_visus.hrl").
-include("predefine.hrl").
-include("skill.hrl").
-include("figure.hrl").
-include("errcode.hrl").
-include("rec_event.hrl").
-include("def_event.hrl").
-include("def_goods.hrl").
-include("def_module.hrl").
-include("goods.hrl").
-include("activitycalen.hrl").
-include("vip.hrl").
-include("common.hrl").


-export([
    login/1
    ,pack_visus/2
    ,upgrade_visus/2
    ,active_visus/2
    ,trigger_visus/2
    ,trigger_visus/3
    ,check/1
    ,handle_event/2
    ,calc_power/3
    ,get_skills/1
    ,get_skills_for_battle/1        %% 获取玩家正在使用的幻光技能
    ,send_visus_skill/1             %% 发送角色幻光技能
    ,get_visus_attr/1
    ,calc_attr_power/1
    ,handle_spec_skill_achievement/1
    ,gm/1
    ]).



%% 0点处理
handle_event(Status, #event_callback{type_id = ?EVENT_ZERO_CLOCK}) ->
    #player_status{id=RoleID,sid=Sid,role_visus=RoleVisus}=Status,
    Now = utime:unixtime(),
    #role_visus{login_days=Days}=RoleVisus,
    NRoleVisus = RoleVisus#role_visus{refresh_time=Now,login_days=Days+1},
    NStatus0 = Status#player_status{role_visus=NRoleVisus},
    Sql = io_lib:format(?SQL_ROLE_VISUS_INS,[RoleID,Now,Days+1]),
    db:execute(Sql),
    {ok,Bin} = pt_147:write(14708,[Days+1]),
    lib_server_send:send_to_sid(Sid,Bin),

    NStatus = lib_role_visus:trigger_visus(NStatus0, login),

    {ok, NStatus};
%%上线处理
handle_event(Status, #event_callback{type_id = ?EVENT_LOGIN_CAST}) ->
    #player_status{id=RoleID,role_visus=RoleVisus}=Status,

    #role_visus{refresh_time=RTime,login_days=Days}=RoleVisus,
    case utime:is_today(RTime) of
        true->
            NStatus = Status;
        _->
            Now = utime:unixtime(),
            NRoleVisus = RoleVisus#role_visus{refresh_time=Now,login_days=Days+1},
            NStatus0 = Status#player_status{role_visus=NRoleVisus},
            Sql = io_lib:format(?SQL_ROLE_VISUS_INS,[RoleID,Now,Days+1]),
            db:execute(Sql),

            NStatus = lib_role_visus:trigger_visus(NStatus0, login)
    end,

    {ok, NStatus};

%% 充值
handle_event(Status, #event_callback{type_id = ?EVENT_RECHARGE, data = #callback_recharge_data{gold = Gold}}) ->
    NStatus = trigger_visus(Status,recharge,Gold),
    {ok, NStatus};
handle_event(Status, #event_callback{type_id = ?EVENT_VIP}) ->
    NStatus = trigger_visus(Status,vip),
    {ok, NStatus};
handle_event(Status, #event_callback{type_id = ?EVENT_FINISH_TASK, data = TaskId})->
    NStatus = trigger_visus(Status,task,TaskId),
    {ok, NStatus};
handle_event(Status, #event_callback{type_id = ?EVENT_LIVENESS_LV})->
    NStatus = trigger_visus(Status,liveness),
    {ok, NStatus};
handle_event(Status, _) ->
    {ok, Status}.


gm(Status)->
    #player_status{id=RoleID}=Status,
    All = data_visus:get_all_visus(),
    Cells = gm_trans(RoleID,All,[]),
    Status0 = Status#player_status{
        role_visus = #role_visus{visus = Cells}
    },
    Status1 = count_visus_attr(Status0),
    NStatus = lib_player:count_player_attribute(Status1),
    lib_player:send_attribute_change_notify(NStatus, ?NOTIFY_ATTR),
    pp_visus:handle(14700, NStatus, []),
    NStatus.

gm_trans(_RoleID,[],Cells)->
    Cells;
gm_trans(RoleID,[H|T],Cells)->
    Grade = calc_cell_grade(H,0),
    Lv = calc_cell_lv(H,Grade,0),
    Cell = #cell_visus{
        id = H,
        grade = Grade,
        lv = Lv,
        state = 1
    },
    save_role_visus(RoleID,Cell),
    gm_trans(RoleID,T,[Cell|Cells]).


calc_cell_grade(Type,Init)->
    case data_visus:get_visus_lv(Type,Init+1,1) of
        #base_visus_lv{}->
            calc_cell_grade(Type,Init+1);
        _->
            Init
    end.

calc_cell_lv(Type,Grade,Init)->
    case data_visus:get_visus_lv(Type,Grade,Init+1) of
        #base_visus_lv{}->
            calc_cell_lv(Type,Grade,Init+1);
        _->
            Init
    end.





%% ---------------------------------------------------------------------------
%% @doc 获取玩家正在使用的幻光技能
-spec get_skills_for_battle(Role)-> SKills when
    Role        :: #player_status{},
    SKills      :: [{SkillId :: integer(), Lev :: integer()}].
%% ---------------------------------------------------------------------------
get_skills_for_battle(Role)->
    #player_status{role_visus = RoleVisus} = Role,
    #role_visus{skill_id = SkillId} = RoleVisus,
    SKills = get_skills(Role),
    case lists:keyfind(SkillId, 1, SKills) of
        {SkillId, Lev} -> [{SkillId, Lev}];
        _ -> []
    end.


get_skills(Status)->
    #player_status{role_visus=RoleVisus}=Status,
    #role_visus{visus=CellVisues}=RoleVisus,
    SKills = merge_skills(CellVisues,[]),
    SKills.



merge_skills([],SKills)->
    SKills;
merge_skills([H|T],SKills)->
    #cell_visus{id=Vid,state=S}=H,
    case S>0 of
        true->
            #base_visus{skill={SKillID,Lv}}=data_visus:get_visus(Vid),
            case lists:keyfind(SKillID,1,SKills) of
                {_,V} when V>Lv->
                    merge_skills(T,SKills);
                _->
                    NSkills = lists:keystore(SKillID,1,SKills,{SKillID,Lv}),
                    merge_skills(T,NSkills)
            end;
        _->
            merge_skills(T,SKills)
    end.



calc_power(Status, AttrPower, BaseAttr) ->
    #player_status{role_visus=RoleVisus, figure = #figure{lv = RoleLv}}=Status,
    #role_visus{attr=Attrs,visus=CellVisues}=RoleVisus,
    PartialAttr = attr_conv:to_attr_record(Attrs),
    Power = lib_player_attr:calc_attr_power_partial(AttrPower, BaseAttr, PartialAttr),
    NCellVisues = calc_cell_power(CellVisues,AttrPower, BaseAttr,[]),

    Skills = merge_skills(NCellVisues,[]),
    {_SKillAttr,SPower}  = lib_skill_attr:get_passive_skill_attr_and_power(Skills, RoleLv),

    NRoleVisus = RoleVisus#role_visus{combat=Power+SPower,visus=NCellVisues},
    {Status#player_status{role_visus=NRoleVisus},SPower}.

calc_cell_power([],_,_,CellVisues)->
    CellVisues;
calc_cell_power([H|T],AttrPower, BaseAttr,CellVisues)->
    #cell_visus{attr=Attrs}=H,
    PartialAttr = attr_conv:to_attr_record(Attrs),
    Power = lib_player_attr:calc_attr_power_partial(AttrPower, BaseAttr, PartialAttr),
    calc_cell_power(T,AttrPower,BaseAttr,[H#cell_visus{combat=Power}|CellVisues]).

%%玩家上线
login(Status)->
    #player_status{id=RoleID}=Status,
    Sql = io_lib:format(?SQL_PLAYER_VISUS_GET, [RoleID]),
    Visus = case db:get_all(Sql) of
        Visus0 when is_list(Visus0)  ->
            make_visus(Visus0,[]);
        _ ->
            []
    end,
    Sql2 = io_lib:format(?PLAYER_VISUS_SKILL_LOAD, [RoleID]),
    SkillId = case db:get_all(Sql2) of
        [[SkillIdDb] | _] -> SkillIdDb;
        _ -> 0
    end,

    Sql3 = io_lib:format(?SQL_ROLE_VISUS_GET, [RoleID]),
    case db:get_row(Sql3) of
        [RTime,Days]  ->
            skip;
        _ ->
            RTime=0,Days=0
    end,

    Status0 = Status#player_status{
        role_visus = #role_visus{refresh_time=RTime,login_days=Days, visus = Visus, skill_id = SkillId}
    },
    Status1 = count_visus_attr(Status0),
    NStatus = update_role_figure(false,Status1),
    NStatus.

count_visus_attr(Status)->
    #player_status{role_visus=RoleVisus, figure = #figure{lv = RoleLv}}=Status,
    #role_visus{visus=CellVisues}=RoleVisus,
    [Attrs0,NCellVisues] = count_cell_visus_attr(CellVisues),
    Skills = merge_skills(NCellVisues,[]),
    {SKillAttr,_SPower}  = lib_skill_attr:get_passive_skill_attr_and_power(Skills, RoleLv),
    Attrs = util:combine_list(Attrs0++SKillAttr),
    NRoleVisus = RoleVisus#role_visus{attr=Attrs,visus=NCellVisues},
    Status#player_status{role_visus=NRoleVisus}.

count_cell_visus_attr(CellVisues)->
    count_cell_visus_attr(CellVisues,[],[]).

count_cell_visus_attr([],CellVisues,Attrs)->
    [util:combine_list(Attrs),CellVisues];
count_cell_visus_attr([H|T],CellVisues,Attrs)->
    [CellAttrs,NewH] = count_cell_attr(H),
    count_cell_visus_attr(T,[NewH|CellVisues],CellAttrs++Attrs).

count_cell_attr(CellVisus)->
    #cell_visus{
        id = Id,
        grade = Grade,
        lv = Lv,
        state = CurS
    } = CellVisus,
    case CurS>0 of
        true->
            case data_visus:get_visus_lv(Id,Grade,Lv) of
                #base_visus_lv{attrs=Attrs,spe_attrs=SAttrs}->
                    ignore;
                _->
                    Attrs = [],SAttrs=[]
            end,
            NewAttrs = lib_player_attr:partial_attr_convert(Attrs++SAttrs),
            NCellVisus = CellVisus#cell_visus{attr=NewAttrs},
            [NewAttrs,NCellVisus];
        _->
            [[],CellVisus]
    end.


%%数据拼接
make_visus([],Visus)->
    Visus;
make_visus([[Id,Grade,Lv,State,Dis]|T],Visus)->
    Cell  = #cell_visus{
        id = Id,
        grade= Grade,
        lv = Lv,
        state = State,
        display = Dis
    },
    make_visus(T,[Cell|Visus]).


pack_visus(Days,Visus)->
    pack_visus(Days,Visus,[]).
pack_visus(Days,[],Visus)->
    {ok,Bin} = pt_147:write(14700,[Days,Visus]),
    Bin;
pack_visus(Days,[H|T],Visus)->
    #cell_visus{
        id = Id,
        grade = Grade,
        lv = Lv,
        combat = Power,
        state = State,
        display = Dis
    }=H,
    pack_visus(Days,T,[{Id,Grade,Lv,Power,State,Dis}|Visus]).


%%激活
active_visus(Vid,Status)->
    #player_status{
        id=RoleID,
        sid = Sid,
        figure=#figure{name=RName},
        role_visus=RoleVisus
    }=Status,
    #role_visus{visus=CellVisues, skill_id = UseSkillId}=RoleVisus,
    CellVisus = lists:keyfind(Vid,#cell_visus.id,CellVisues),
    VisusCfg = data_visus:get_visus(Vid),
    Cost = case VisusCfg of
        #base_visus{item=Cost0}-> Cost0;
        _-> []
    end,
    LenCost = length(Cost),
    CKList = case LenCost>0 of
        true->
            [{check_can_active,Vid,CellVisus}];
        _->
            [{check_can_active,Vid,CellVisus},{check_condition,{Status,Vid}}]
    end,
    CheckResult = case util:check_lists(?MODULE,CKList) of
        true when LenCost>0 ->
            case lib_goods_api:cost_object_list_with_check(Status, Cost, role_visus, ["used visus"]) of
                {true,Status0,_}->
                    {ok,Status0};
                {false,Err,_}->
                    {false,Err}
            end;
        true->
            {ok,Status};
       {false,Err}->
            {false,Err}
    end,
    case CheckResult of
        {ok, Status2} ->
            NCellVisus  = #cell_visus{id=Vid,state=1},
            NCellVisues = lists:keystore(Vid,#cell_visus.id,CellVisues,NCellVisus),
            #base_visus{skill = {SkillId, SkillIdLev}} = VisusCfg,
            RoleVisus2 = RoleVisus#role_visus{visus=NCellVisues},
            Filter = fun(TCellVisus) -> TCellVisus#cell_visus.state > 0 end,
            lib_achievement_api:visus_event(Status2, erlang:length(lists:filter(Filter, NCellVisues))),
            Status3 = Status2#player_status{role_visus = RoleVisus2},
            save_role_visus(RoleID,NCellVisus),
            Status4 = case UseSkillId of
                0 ->
                    RoleVisus3 = RoleVisus2#role_visus{skill_id = SkillId},
                    save_role_visus_skill(RoleID, SkillId),
                    %% 更新技能到场景以便战斗使用
                    ValueList = [{passive_skill, [{SkillId, SkillIdLev}]}],
                    notice_get_skill(Sid, SkillId, SkillIdLev),
                    mod_scene_agent:update(Status3, ValueList),
                    Status3#player_status{role_visus = RoleVisus3};
                _ ->
                    Status3
            end,
            send_visus_skill(Status4),
            handle_spec_skill_achievement(Status4),
            lib_log_api:log_visus_upgrade(RoleID,RName,0,Vid,0,0,Cost,VisusCfg#base_visus.condition,VisusCfg#base_visus.desc),
            {ok, Status4};
        {false, Reason} ->
            {false, Reason}
    end.

handle_spec_skill_achievement(Status) ->
    #player_status{skill = SkillStatus, vip_status = RoleVip} = Status,
    #status_skill{skill_list = SkillList, skill_passive = PassiveSkills} = SkillStatus,
    #vip_status{sup_vip = SupVip} = RoleVip,
    VipSkills =
    case SupVip#role_sup_vip.type > 0 of
        true -> [{109101, 1}];
        _ -> []
    end,
    VisusSkills = get_skills(Status),
    SpecSkill =  [101091, 102091, 103091, 104091, 109100, 109101, 120001, 120002, 120003],
    F = fun({SkillId, _Lv} = Skill, TList) ->
        case lists:member(SkillId, SpecSkill) of
            true -> [Skill|TList];
            _ -> TList
        end end,
    SpecList = lists:foldl(F, [], lists:ukeysort(1, SkillList++PassiveSkills++VipSkills++VisusSkills)),
    lib_achievement_api:active_spec_skill_event(Status, erlang:length(SpecList)),
    ok.

%%升级
upgrade_visus(Vid,Status)->
    #player_status{
        id=RoleID,
        figure=#figure{name=RName},
        role_visus=RoleVisus
    }=Status,
    #role_visus{visus=CellVisues}=RoleVisus,
    CellVisus = lists:keyfind(Vid,#cell_visus.id,CellVisues),
    CKList = [
        {check_active,CellVisus},
        {check_max,CellVisus}
    ],
    case util:check_lists(?MODULE,CKList) of
        true->
            #cell_visus{grade=CGrade,lv=CLv}=CellVisus,
            #base_visus_lv{next_grade=NGrade,next_lv=NLv,cost=Cost,rate=Rate} = data_visus:get_visus_lv(Vid,CGrade,CLv),
             case lib_goods_api:cost_object_list_with_check(Status, Cost, role_visus, ["used visus"]) of
                {true,Status0,_}->
                    case urand:rand(1,100)=<Rate of
                        true->
                            NCellVisus = CellVisus#cell_visus{grade=NGrade,lv=NLv},
                            NCellVisues = lists:keystore(Vid,#cell_visus.id,CellVisues,NCellVisus),
                            NStatus = Status0#player_status{role_visus=RoleVisus#role_visus{visus=NCellVisues}},
                            save_role_visus(RoleID,NCellVisus),
                            send_visus_skill(NStatus),
                            lib_log_api:log_visus_upgrade(RoleID,RName,1,Vid,CLv,NLv,Cost,[],<<>>),
                            {ok,NCellVisus,NStatus};
                        _->
                            {false,?ERRCODE(err147_fail_upgrade)}
                    end;
                {false,Err,_}->
                    {false,Err}
            end;
       {false,Err}->
            {false,Err}
    end.

%%幻化变更
change_display(Vid,Status)->
    #player_status{
        id=RoleID,
        role_visus=RoleVisus
    }=Status,
    #role_visus{visus=CellVisues}=RoleVisus,
    CellVisus = lists:keyfind(Vid,#cell_visus.id,CellVisues),
    CKList = [
        {check_active,CellVisus},
        {check_display,CellVisus}
    ],
    case util:check_lists(?MODULE,CKList) of
        {ok,Dis}->
            NCellVisus = CellVisus#cell_visus{display=Dis},
            NCellVisues0 = lists:keystore(Vid,#cell_visus.id,CellVisues,NCellVisus),
            NCellVisues  = case Dis =< 0 of
                true->
                    NCellVisues0;
                _->
                    reset_visus_display(RoleID,Vid,NCellVisues0,[])
            end,
            NStatus0 = Status#player_status{role_visus=RoleVisus#role_visus{visus=NCellVisues}},
            save_role_visus(RoleID,NCellVisus),
            NStatus = update_role_figure(NStatus0),
            {ok,Dis,NStatus};
        {false,Err}->
            {false,Err}
    end.

update_role_figure(Status)->
    update_role_figure(true,Status).
update_role_figure(IsUpdate,Status)->
    #player_status{
        id=RoleID,
        role_visus=RoleVisus,
        figure = Figure
    }=Status,
    #role_visus{visus=CellVisues}=RoleVisus,
    Shows = [{Id,Dis}||#cell_visus{id=Id,display=Dis}<-CellVisues,Dis>0],
    case Shows of
        [{CurShow,_}|_]->
            skip;
        _->
            CurShow = 0
    end,
    NFigure = Figure#figure{visus=CurShow},
    IsUpdate andalso  lib_role:update_role_show(RoleID, [{figure,NFigure}]),
    Status#player_status{figure=NFigure}.

reset_visus_display(_RoleID,_Vid,[],CellVisues)->
    CellVisues;
reset_visus_display(RoleID,Vid,[H|T],CellVisues)->
    #cell_visus{
        id = Id,
        display = Dis
    }=H,
    case Id /= Vid of
        true when Dis>0->
            NewH = H#cell_visus{display=0},
            save_role_visus(RoleID,NewH),
            reset_visus_display(RoleID,Vid,T,[NewH|CellVisues]);
        _->
            reset_visus_display(RoleID,Vid,T,[H|CellVisues])
    end.

check({check_display,CellVisus})->
    #cell_visus{display=Dis}=CellVisus,
    case Dis of
        0->
            {ok,1};
        _->
            {ok,0}
    end;
check({check_can_active,Vid,CellVisus})->
    case CellVisus of
        #cell_visus{state=1}->
            {false,?ERRCODE(err147_need_no_active_again)};
        _->
            All = data_visus:get_all_visus(),
            case lists:member(Vid,All) of
                true ->
                    true;
                _->
                    {false,?ERRCODE(config_err)}
            end
    end;

check({check_active,CellVisus})->
    case CellVisus of
        #cell_visus{state=S} when S>0->
            true;
        _->
            {false,?ERRCODE(err147_need_active)}
    end;
check({check_max,CellVisus})->
    #cell_visus{id=Vid,grade=CGrade,lv=CLv}=CellVisus,
    case data_visus:get_visus_lv(Vid,CGrade,CLv) of
        #base_visus_lv{next_grade=0,next_lv=0}->
            {false,?ERRCODE(err147_has_max_lv)};
        #base_visus_lv{}->
            true;
        _->
            {false,?ERRCODE(config_err)}
    end;


% 检查活跃度等级
check({{liveness, NeedLv}, Status}) ->
    #player_status{role_liveness = RoleLives} = Status,
    #role_liveness{lv = Lv} = RoleLives,
    case Lv >= NeedLv of
        false ->
            {false,?ERRCODE(err147_conditions_not_met)};
        _ ->
            true
    end;

% 检查角色是否满足登录天数要求
check({{login, Days}, Status}) ->
    #player_status{role_visus=RoleVisus}=Status,
    #role_visus{login_days=LoginDays}=RoleVisus,
    case LoginDays >= Days of
        false ->
            {false,?ERRCODE(err147_conditions_not_met)};
        _ ->
            true
    end;

%% 检查角色是否满足充值要求
check({{recharge, Num}, Status}) ->
    #player_status{id=RoleID}=Status,
    TotalCharge = lib_recharge_data:get_total(RoleID),
    case TotalCharge >= Num of
        false ->
            {false, ?ERRCODE(err147_conditions_not_met)};
        _ ->
            true
    end;

%% 检查角色是否完成TaskId任务
check({{task, TaskId}, _Status}) ->
    case lib_role_task:is_finish_task_id(TaskId) of
        false ->
            {false, ?ERRCODE(err147_conditions_not_met)};
        _ ->
            true
    end;

%% 检查角色vip等级
check({{vip, Lv}, Status}) ->
    #player_status{figure=Figure} = Status,
    #figure{vip=Vip}=Figure,
    case Vip >= Lv of
        false ->
            {false, ?ERRCODE(err147_conditions_not_met)};
        _ ->
            true
    end;

%% 检查角色是否满足激活这个幻光的条件
check({check_condition,{Status,Vid}}) ->
    #base_visus{
        condition = Condition
    } = data_visus:get_visus(Vid),
    NewCondition = [
        {Cond, Status} || Cond <- Condition
    ],
    check_list(NewCondition).


check_list([]) -> true;
check_list([H|L]) ->
    case check(H) of
        {false, Reason} ->
            {false, Reason};
        true ->
            check_list(L)
    end.


save_role_visus(RoleID,CellVisus)->
    #cell_visus{
        id = Vid,
        grade = Grade,
        lv = Lv,
        state = CurS,
        display = Dis
    }=CellVisus,
    Sql = io_lib:format(?SQL_PLAYER_VISUS_INSERT,[RoleID,Vid,Grade,Lv,CurS,Dis]),
    db:execute(Sql).

save_role_visus_skill(RoleId, SkillId) ->
    Sql = io_lib:format(?PLAYER_VISUS_SKILL_SAVE, [RoleId, SkillId]),
    db:execute(Sql),
    ok.

%%功能触发
trigger_visus(Status,Type)->
    trigger_visus(Status,Type,1).
trigger_visus(Status,Type,_Value)->
    AllVisues  = data_visus:get_all_visus(),
    RoleVisues = get_role_visus_list(Status),
    LessIdList = AllVisues -- RoleVisues,
    NeedCheckList = filter_need_check(LessIdList,Type,[]),
    Actives = check_active_visus(Status,NeedCheckList),
    case length(Actives)>0 of
        true->
            NStatus0 = do_active_visus(Actives,Status),
            NStatus1 = lib_role_visus:count_visus_attr(NStatus0),
            NStatus  = lib_player:count_player_attribute(NStatus1),
            lib_achievement_api:visus_power_event(NStatus,
                calc_attr_power(NStatus1#player_status.role_visus#role_visus.attr)
            ),
            lib_player:send_attribute_change_notify(NStatus, ?NOTIFY_ATTR);
        _->
            NStatus = Status
    end,
    NStatus.

do_active_visus([],Status)->
    Status;
do_active_visus([H|T],Status)->
    #player_status{id=RoleID,role_visus=RoleVisus}=Status,
    #role_visus{visus=CellVisues}=RoleVisus,
    case lists:keyfind(H,#cell_visus.id,CellVisues) of
        false->
            CellVisus  = #cell_visus{id=H},
            NCellVisues = lists:keystore(H,#cell_visus.id,CellVisues,CellVisus),
            NStatus = Status#player_status{role_visus=RoleVisus#role_visus{visus=NCellVisues}},
            save_role_visus(RoleID,CellVisus),
            {ok,Bin} = pt_147:write(14704,[H]),
            lib_server_send:send_to_uid(RoleID,Bin),
            do_active_visus(T,NStatus);
        _->
            do_active_visus(T,Status)
    end.

filter_need_check([],_,Checks)->
    Checks;
filter_need_check([H|T],Type,Checks)->
    #base_visus{condition=Condition}=data_visus:get_visus(H),
    case lists:keymember(Type,1,Condition) of
        true ->
            filter_need_check(T,Type,[H|Checks]);
        false ->
            filter_need_check(T,Type,Checks)
    end.

get_role_visus_list(Status)->
    #player_status{role_visus=RoleVisus}=Status,
    #role_visus{visus=CellVisues}=RoleVisus,
    Lists = [Vid||#cell_visus{id=Vid}<-CellVisues],
    Lists.

check_active_visus(Status,NeedCheckList)->
    check_active_visus(Status,NeedCheckList,[]).
check_active_visus(_Status,[],Actives) ->
    Actives;
check_active_visus(Status,[H|T],Actives) ->
    NActives =
        case check({check_condition,{Status,H}}) of
            true ->
                [H | Actives];
            _ ->
                Actives
        end,
    check_active_visus(Status,T, NActives).



%% ---------------------------------------------------------------------------
%% @doc 切换技能
-spec use_skill(Player, SkillId) ->
    {false, Reason} | {ok, NewPlayer} when
    Player      :: #player_status{},
    SkillId     :: integer(),       %% 技能Id
    Reason      :: integer(),
    NewPlayer   :: #player_status{}.
%% ---------------------------------------------------------------------------
use_skill(Player, SkillId) ->
    case use_skill_logic(Player, SkillId) of
        {false, Reason} ->
            {false, Reason};
        {ok, NewPlayer} ->
            {ok, NewPlayer}
    end.


%% ---------------------------------------------------------------------------
%% @doc 切换技能
-spec use_skill_logic(Player, SkillId) ->
    {false, Reason} | {ok, NewPlayer} when
    Player      :: #player_status{},
    SkillId     :: integer(),       %% 技能Id
    Reason      :: integer(),
    NewPlayer   :: #player_status{}.
%% ---------------------------------------------------------------------------
use_skill_logic(Player, SkillId) ->
    SkillList = get_skills(Player),
    #player_status{role_visus = RoleVisus, id = PlayerId} = Player,
    #role_visus{skill_id = UseSkillId} = RoleVisus,
    SkillInfo = lists:keyfind(SkillId, 1, SkillList),
    if
        SkillId =:= UseSkillId ->
            {ok, Player};
        SkillInfo =:= false ->
            {false, ?ERRCODE(err147_there_is_not_skill)};
        true ->
            NewRoleVisus = RoleVisus#role_visus{skill_id = SkillId},
            NewPlayer = Player#player_status{role_visus = NewRoleVisus},
            save_role_visus_skill(PlayerId, SkillId),
            %% 更新技能到场景以便战斗使用
            ValueList = [{passive_skill, [SkillInfo]}],
            KeyValList = case UseSkillId of
                0 ->
                    ValueList;
                _ ->
                    [{delete_passive_skill, [{UseSkillId, 1}]} | ValueList]
            end,
            mod_scene_agent:update(NewPlayer, KeyValList),
            {ok, NewPlayer}
    end.


%% ---------------------------------------------------------------------------
%% @doc 发送角色幻光技能
-spec send_visus_skill(Role) -> ok when
    Role        :: #player_status{}.
%% ---------------------------------------------------------------------------
send_visus_skill(Role) ->
    #player_status{role_visus = RoleVisus, sid = Sid} = Role,
    #role_visus{skill_id = SkillId} = RoleVisus,
    SkillList = get_skills(Role),
    {ok, BinData} = pt_147:write(14705, [SkillId, SkillList]),
    lib_server_send:send_to_sid(Sid, BinData),
    ok.

get_visus_attr(Status)->
    #player_status{role_visus=RoleVisus}=Status,
    case RoleVisus of
        #role_visus{attr=Attrs}->
            skip;
        _->
            Attrs = []
    end,
    Attrs.

%% 通知获得新技能
notice_get_skill(Sid, SkillId, SkillLv) ->
    {ok, BinData} = pt_147:write(14707, [SkillId, SkillLv]),
    lib_server_send:send_to_sid(Sid, BinData).

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