%% ---------------------------------------------------------------------------
%% @doc lib_mon_ai
%% @author ming_up@foxmail.com
%% @since  2016-09-10
%% @deprecated 怪物ai库函数
%% ---------------------------------------------------------------------------
-module(lib_mon_ai).

-include("scene.hrl").
-include("common.hrl").
-include("attr.hrl").
-include("battle.hrl").
-include("figure.hrl").

-compile(export_all).

% %% 怪物走路ai触发(必须得有分组属性)
% mon_to_mon_ai(Scene, CopyId, Xpx, Ypx, MonId, MonAid, Group) ->
%     case Group /= 0 of
%         true ->
%             {X, Y} = lib_scene_calc:pixel_to_logic_coordinate(Xpx, Ypx),
%             List = case lib_mon:get_ai(Scene, CopyId, X, Y) of
%                        skip -> [];
%                        Other -> Other
%                    end,
%             AiArgs = #{id => MonId, pid => MonAid, x => Xpx, y => Ypx, sign => ?BATTLE_SIGN_MON, group => Group},
%             [Aid ! {'ai', AiArgs} || Aid <- List]; %% 数字1表示是怪物走路
%         false ->
%             skip
%     end.

%% Atter:#battle_return_atter{}|none
born(State, StateName) ->
    Now = utime:longunixtime(),
    AiList = data_mon_ai_born:get(State#ob_act.object#scene_object.config_id),
    do_ai_list(AiList, State, Now, StateName, null).

die(State, Killer, StateName) ->
    Now = utime:longunixtime(),
    AiList = data_mon_ai_die:get(State#ob_act.object#scene_object.config_id),
    do_ai_list(AiList, State, Now, StateName, Killer).

walk_end(State, StateName) ->
    Now = utime:longunixtime(),
    AiList = data_mon_ai_walk_end:get(State#ob_act.object#scene_object.config_id, State#ob_act.path_ai_no),
    do_ai_list(AiList, State, Now, StateName, null).

%% 血量变化ai
hp_change(OldHp, NowHp, State, StateName) ->
    #ob_act{object = Object, hp_ai_min = HpAiMin} = State,
    #battle_attr{hp_lim = HpLim, hp_lim_origin = HpLimOrigin} = Object#scene_object.battle_attr,
    #scene_object{config_id = MonTypeId} = Object,
    IsHpLimitChange = HpLimOrigin =/= HpLim,
    case data_mon_ai_hp:get(MonTypeId) of
        [] ->
            {State, StateName};
        _ when IsHpLimitChange -> %% 血量上限已经被更改了，不再触发血量变化ai
            {State, StateName};
        HpList ->
            OldHpR = OldHp/HpLim,
            NowHpR = NowHp/HpLim,
            case hp_event_help(HpList, OldHpR, NowHpR, MonTypeId, HpAiMin) of
                false -> {State, StateName};
                {true, V} ->
                    case data_mon_ai_hp:get(MonTypeId, V) of
                        [] ->
                            {State, StateName};
                        AiList ->
                            State2 = State#ob_act{hp_ai_min = V},
                            do_ai_list(AiList, State2, utime:longunixtime(), StateName, null)
                    end
            end
    end.

%% 判断可以执行哪个血量AI
hp_event_help(HpList, OldHpR, NowHpR, MonTypeId, HpAiMin) ->
    case data_hp_ai_mon:is_one_off(MonTypeId) of
        1 -> %% 血量AI只执行一次
            hp_event_help(HpList, HpAiMin, NowHpR);
        _ ->
            hp_event_help(HpList, OldHpR, NowHpR)
    end.
hp_event_help([], _OldHpR, _NowHpR) ->
    false;
hp_event_help([V|T], OldHpR, NowHpR) ->
    if
        OldHpR > V andalso NowHpR =< V ->
            {true, V};
        true ->
            hp_event_help(T, OldHpR, NowHpR)
    end.


%% 状态改变效果
wake_up(State, StateName) ->
    Object = State#ob_act.object,
    case data_mon_ai_state:get(Object#scene_object.config_id) of
        [] -> {State, StateName};
        AiList ->
            do_ai_list(AiList, State, utime:longunixtime(), StateName, null)
    end.

% old:
% %% 状态回复变化
% resume(State) ->
%     %% 取消AI定时器
%     util:cancel_timer(State#ob_act.eref),
%     %% 取消特殊AI定时器
%     cancel_special_ai_timer(State#ob_act.special_ai_ref, State),
%     Object = State#ob_act.object,
%     State2 = State#ob_act{eref = [], special_ai_ref = []},
%     case data_mon_ai_resume:get(Object#scene_object.config_id) of
%         [] -> {State2, sleep};
%         AiList -> do_ai_list(AiList, State2, utime:longunixtime(), sleep, null)
%     end.
% 
% %% 取消特殊AI定时器
% cancel_special_ai_timer([], _State) ->
%     ok;
% cancel_special_ai_timer([{AiType, Ref} | T], State) ->
%     case AiType of
%         ai_kill_scene_role ->
%             #ob_act{object = Minfo} = State,
%             #scene_object{
%                 scene = Scene, scene_pool_id = SPoolId, copy_id = CopyId
%                 ,x = X, y = Y
%             } = Minfo,
%             {ok, BinData} = pt_610:write(61059, [0, 0]),
%             lib_server_send:send_to_area_scene(Scene, SPoolId, CopyId, X, Y, BinData);
%         _ ->
%             ok
%     end,
%     util:cancel_timer(Ref),
%     cancel_special_ai_timer(T, State).

%% 状态恢复回休眠状态
resume(State) ->
    #ob_act{
        object = #scene_object{config_id = ObjConfigId},
        general_driven = OldGeneralDriven
    } = State,
    GeneralDriven = mon_state_util:filter_when_resume(OldGeneralDriven),
    NewState = State#ob_act{general_driven = GeneralDriven},
    case data_mon_ai_resume:get(ObjConfigId) of
        [] ->
            {NewState, sleep};
        AiList ->
            do_ai_list(AiList, NewState, utime:unixtime(ms), sleep, null)
    end.

%% 处理AI列表
do_ai_list([], ActState, _NowTimeMS, StateName, _Killer) ->
    % old: {ActState#ob_act{eref = []}, StateName};
    NewActState = mon_state_util:filter_special_event(ActState),
    {NewActState, StateName};
do_ai_list([{Type, Args, Time}|EffList], ActState, NowTimeMS, StateName, Killer) ->
    #ob_act{object = Minfo} = ActState,
    #scene_object{scene=Scene, scene_pool_id=ScenePoolId, copy_id=CopyId, x=X, y=Y, config_id=CfgId,
        battle_attr = BattleAttr} = Minfo,

    Res = case Type of
        msg ->  %% 怪物头上冒泡泡说话
            lib_scene_object_ai:mon_speak(Minfo, Args),
            ok;
        tv_msg -> %% 怪物发送传闻警戒
            lib_scene_object_ai:mon_speak_tv_msg(Minfo, Args),
            ok;
        center_msg -> %% 屏幕中央喊话
          lib_scene_object_ai:mon_center_msg(Minfo, Args),
          ok;

        create_mon -> %% 创建怪物
            ai_create_mon(Minfo, Args);
        create_dynamic_mon -> %% 创建怪物
            [PreMil, Mid, Xmin, Xmax, Ymin, Ymax, IsActive, OtherArgsTemp] = Args,
            AutoLev = case util:is_cls() of
                false -> max(1, util:get_world_lv());
                true  -> 1
            end,
            %% 设置动态创建怪的参数
            OtherArgs = [{auto_lv, AutoLev} | OtherArgsTemp],
            Args2 = [PreMil, Mid, Xmin, Xmax, Ymin, Ymax, IsActive, OtherArgs],
            ai_create_mon(Minfo, Args2);
        remove ->
            % old: erlang:send_after(Args, Minfo#scene_object.aid, {'stop', 1}),
            mon_state_util:update_general_driven(ActState, [{Args, {'stop', 1}}], NowTimeMS);
        die ->
            % old: erlang:send_after(Args, Minfo#scene_object.aid, 'die'),
            mon_state_util:update_general_driven(ActState, [{Args, 'die'}], NowTimeMS);

        clear_scene_mon when is_list(Args) ->
            lib_mon:clear_scene_mon_by_mids(Scene, ScenePoolId, CopyId, 1, Args),
            ok;

        skill ->
            NewMinfo = Minfo#scene_object{skill=Args},
            {EffList, StateName, ActState#ob_act{object = NewMinfo}};

        signed -> %% 标记
            #ob_act{ai_event=AiEvent} = ActState,
            case lists:member({signed, Args}, AiEvent) of
                true -> ok;
                false ->
                    AiEvent1 = [{signed, Args}|AiEvent],
                    {EffList, StateName, ActState#ob_act{ai_event=AiEvent1}}
            end;

        del_sign -> %% 移除标记值
            #ob_act{ai_event=AiEvent} = ActState,
            case lists:member({signed, Args}, AiEvent) of
                true  -> ok;
                false ->
                    {EffList, StateName, ActState#ob_act{ai_event=lists:delete({signed, Args}, AiEvent)}}
            end;

        is_signed -> %% 判断有该值则执行后面的事件
            [Value, N] = Args,
            #ob_act{ai_event=AiEvent} = ActState,
            {_, LeftEffList} = case N < length(EffList) of
                true -> lists:split(N, EffList);
                false -> {EffList, []}
            end,
            NewEffList = case lists:member({signed, Value}, AiEvent) of  %% 怪物ai事件
                false -> LeftEffList;
                true  -> EffList
            end,
            {NewEffList, StateName, ActState};

        rand -> %% 随机执行后面的语句
            [PercentageList, NList] = Args,
            NewEffList = handle_rand_list(PercentageList, NList, EffList),
            {NewEffList, StateName, ActState};

        nochange -> %%不作任何改变
            ok;

        eff_other_mon -> %% 影响同场景的怪物
            [Mids, N] = Args,
            {OtherMonEfflist, LeftEffList} = case N < length(EffList) of
                true -> lists:split(N, EffList);
                false -> {EffList, []}
            end,
            GetItemPattern = [#scene_object.aid, #scene_object.id],
            case lib_mon:get_scene_mon_by_mids(Scene, ScenePoolId, CopyId, Mids, GetItemPattern) of
                [] ->
                    ok;
                EffectML when is_list(EffectML) ->
                    % old: [Aid ! {'special_event', OtherMonEfflist} || Aid <- EffectML];
                    [
                        mon_mgr:send(Aid, MonId, {'special_event', OtherMonEfflist}) ||
                        [Aid, MonId] <- EffectML
                    ];
                _ ->
                    ok
            end,
            {LeftEffList, StateName, ActState};

        state -> %% 状态转变
            NewStateName = Args,
            {EffList, NewStateName, ActState};

        ac_skill -> %% 释放技能
            case Args of
                {act_now, SkillId, SkillLv} ->
                    NewActState = lib_scene_object_ai:object_ac_skill(ActState, SkillId, SkillLv),
                    {EffList, StateName, NewActState};
                {act_now, SkillId, SkillLv, SkillAdjust} ->
                    NewSkillAdjust = skill_adjust_api:valid_skill_adjust(SkillAdjust),
                    NewActState = lib_scene_object_ai:object_ac_skill(ActState, SkillId, SkillLv, NewSkillAdjust),
                    {EffList, StateName, NewActState};
                _ ->
                    TmpAddSkills = filter_ai_skills(Args),
                    NewTmpSkills = Minfo#scene_object.temp_skill ++ TmpAddSkills,
                    NewMinfo =  Minfo#scene_object{temp_skill = NewTmpSkills},
                    {EffList, StateName, ActState#ob_act{object = NewMinfo}}
            end;
        ac_skill_donot_trace -> %% 只释放技能，怪物不会继续追踪目标
            case Args of
                {act_now, SkillId, SkillLv} ->
                    NewActState = lib_scene_object_ai:object_ac_skill_donot_trace(ActState, SkillId, SkillLv),
                    {EffList, StateName, NewActState};
                _ ->
                    TmpAddSkills = filter_ai_skills(Args),
                    NewTmpSkills = Minfo#scene_object.temp_skill ++ TmpAddSkills,
                    NewMinfo = Minfo#scene_object{temp_skill = NewTmpSkills},
                    {EffList, StateName, ActState#ob_act{object = NewMinfo}}
            end;
        ac_skill_can_cancel ->
            case Args of
                {act_now, _, _} ->
                    {EffList, StateName, ActState};
                  _ ->
                    TmpAddSkills = filter_ai_skills(Args),
                    NewTmpSkills = Minfo#scene_object.temp_skill ++ TmpAddSkills,
                    NewMinfo = Minfo#scene_object{temp_skill = NewTmpSkills},
                    {EffList, StateName, ActState#ob_act{object = NewMinfo}}
            end;
        walk -> %% 走到目标位置
            [TX, TY, PathNo] = Args,
            Path = lib_scene_object_ai:dest_path(X, Y, TX, TY, Scene),
            {EffList, walk, ActState#ob_act{path=Path, path_ai_no=PathNo}};
        path -> %% 23:设定怪物路径
            [Path, PathNo] = Args, %% 格式为[{scene_id, x, y}, ....]
            {EffList, walk, ActState#ob_act{path=Path, path_ai_no=PathNo}};

        auto_patrol -> %% 自由巡逻(非野外场景的怪物)
            [Ratio] = Args,
            Path = lib_scene_object_ai:create_auto_patrol_path(X, Y, X, Y, Ratio, BattleAttr#battle_attr.speed, false),
            %% 如果有循环逻辑,则本路径走完之后继续执行下一路径逻辑
            case lists:keyfind(nochange, 1, EffList) of
                {_, _, {patrol_cycle, PathAiNo}} ->
                    skip;
                _ ->
                    PathAiNo = 0
            end,
            {lists:keydelete(nochange, 1, EffList), walk, ActState#ob_act{path = Path, path_ai_no = PathAiNo}};

        ai_id -> %% 获取ai库并且执行
            EffList1 = case data_ai:get(Minfo#scene_object.id) of
                [] -> EffList;
                AIContentL -> AIContentL++EffList
            end,
            {EffList1, StateName, ActState};
        clean_buff_stat -> %% 统计自己创建的小怪死亡数量
            {MonId, Num, SkillIdList} = Args,
            Key = {clean_buff_stat, MonId},
            Event = {Key, {MonId, Num, SkillIdList}},
            AiEvent = lists:keystore(Key, 1, ActState#ob_act.ai_event, Event),
            {EffList, StateName, ActState#ob_act{ai_event = AiEvent}};
        clean_buff_stat_do -> %% 怪物死亡AI执行
            #ob_act{
                object = #scene_object{
                    mon = #scene_mon{from_pid = FromPid, mid = MonTypeId}
                }
            } = ActState,
            %% 通知怪物的相关创建者
            erlang:send(FromPid, {clean_buff_stat, MonTypeId}),
            ok;
        %% Mid 怪物id IsActive是否主动 OtherArgs怪物参数
        add_buff_to_role -> %% 给玩家增加一个buff
            add_buff_to_role_do(ActState, Args),
            ok;
        accumulate_power -> %% 怪物切换到蓄力状态
            LastTime = Args,
            % #ob_act{ref = Ref} = ActState,
            StateName2 = case StateName of
                null -> sleep;
                _    -> StateName
            end,
            % old: lib_scene_object:send_event_after(Ref, LastTime, {accumulate_power_over, StateName2}),
            DelayDrivenInfo = {LastTime, {accumulate_power_over, StateName2}},
            NewActState = mon_state_util:update_state_driven(ActState, DelayDrivenInfo, NowTimeMS),
            {EffList, accumulate_power, NewActState};
        %% {kill_scene_role, {RoleNum, KillTime}, Time}
        kill_scene_role -> %% KillTime后秒杀场景玩家RoleNum个
            {RoleNum, KillTime} = Args,
            % old:
            % #ob_act{special_ai_ref = RefList} = ActState,
            % Msg = {ai_kill_scene_role, RoleNum},
            % RefList2 = special_ai_timer(
            %     ai_kill_scene_role, KillTime, Minfo#scene_object.aid, Msg, RefList
            % ),
            % case RefList2 of
            %     RefList ->
            %         ok;
            %     _ ->
            %         {ok, BinData} = pt_610:write(61059, [1, KillTime]),
            %         #scene_object{
            %             scene = Scene, scene_pool_id = SPoolId, copy_id = CopyId
            %             ,x = X, y = Y
            %         } = Minfo,
            %         lib_server_send:send_to_area_scene(Scene, SPoolId, CopyId, X, Y, BinData)
            % end,
            % {EffList, StateName, ActState#ob_act{special_ai_ref = RefList2}};
            Msg = {ai_kill_scene_role, RoleNum},
            DelayDriven = [{KillTime, Msg, check}],
            #ob_act{general_driven = OldGeneralDriven} = ActState,
            NewGeneralDriven = mon_state_util:update_general_driven(OldGeneralDriven, DelayDriven, NowTimeMS),
            case ulists:list_equal(OldGeneralDriven, NewGeneralDriven) of
                true  -> ignore;
                false ->
                    {ok, BinData} = pt_610:write(61059, [1, KillTime]),
                    #scene_object{
                        scene = Scene, scene_pool_id = SPoolId, copy_id = CopyId
                        ,x = X, y = Y
                    } = Minfo,
                    lib_server_send:send_to_area_scene(Scene, SPoolId, CopyId, X, Y, BinData)
            end,
            {EffList, StateName, ActState#ob_act{general_driven = NewGeneralDriven}};
        set_att_xy -> %% 怪物把目标坐标设置为技能攻击坐标
            #ob_act{att = Att} = ActState,
            Minfo2 = case Att of
                #{id := _AttRoleId, sign := _AttSign, x := AttX, y := AttY} ->
                    UpdateList = [{skill_att_xy, Att}, {skill_att_xy_change, {0, 0}}],
                    lib_scene_object:update(Minfo, UpdateList),
                    Minfo#scene_object{skill_att_xy = {AttX, AttY}};
                _ ->
                    Rand = urand:rand(30, 100),
                    ArtificialAtt = #{id => 0, sign => 0, x => X + Rand, y => Y + Rand},
                    UpdateList = [{skill_att_xy, ArtificialAtt}, {skill_att_xy_change, {0, 0}}],
                    lib_scene_object:update(Minfo, UpdateList),
                    ?DEBUG("set_att_xy missing:~w", [CfgId]),
                    Minfo#scene_object{skill_att_xy = {X + Rand, Y + Rand}}
            end,
            {EffList, StateName, ActState#ob_act{object = Minfo2}};
        add_att_xy -> %% 怪物攻击坐标偏移:{add_att_xy,{Degree, Distance},Time}
            {Degree, Distance} = Args,
            Minfo2 = case Minfo of
                #scene_object{
                    skill_att_xy = {AttX, AttY}
                } when AttX > 0 orelse AttY > 0 ->
                    lib_scene_object:update(Minfo, [{skill_att_xy_change, Args}]),
                    Minfo#scene_object{skill_att_xy_change = {Degree, Distance}};
                _ ->
                    Minfo
            end,
            {EffList, StateName, ActState#ob_act{object = Minfo2}};
        _ ->
            ok
    end,

    %% 识别差异化的返回结果（未来最好抽离到独立的函数，可维护性较高）
    %% 为避免代码继续变得复杂化和不可控，需要控制返回结果的类别，目前支持三类：
    %%      {NewEffList, NewStateName, NewState}
    %%      NewState
    %%      ok
    {LastEffList, LastStateName, ActState1} =
    case Res of
        {EffListX, StateNameX, ActStateX} ->
            {EffListX, StateNameX, ActStateX};
        ActStateX = #ob_act{} ->
            {EffList, StateName, ActStateX};
        _ ->
            {EffList, StateName, ActState}
    end,

    %% 移动路径信息
    LastActState =
    case Minfo#scene_object.mon#scene_mon.kind == ?MON_KIND_WALK_AUTO andalso Type =/= auto_patrol of
        true -> ActState1#ob_act{path = [], path_ai_no = 0};
        _    -> ActState1
    end,

    case Time of
        0     -> do_ai_list(LastEffList, LastActState, NowTimeMS, LastStateName, Killer);
        cycle ->
            case data_mon_ai_cycle:get(CfgId, 0) of
                [] -> {LastActState, LastStateName};
                CycleAiL ->
                    do_ai_list(CycleAiL, LastActState, NowTimeMS, LastStateName, Killer)
            end;
        {cycle, CycleType} ->
            case data_mon_ai_cycle:get(CfgId, CycleType) of
                [] -> {LastActState, LastStateName};
                CycleAiL ->
                    do_ai_list(CycleAiL, LastActState, NowTimeMS, LastStateName, Killer)
            end;
        % 进入自由巡逻状态
        {patrol_cycle, CycleType} ->
            #ob_act{path = PatrolPath} = LastActState,
            case PatrolPath =/= [] of
                true ->
                    {LastActState, LastStateName};
                _ ->
                    case data_mon_ai_walk_end:get(CfgId, CycleType) of
                        [] -> {LastActState, LastStateName};
                        CycleAiL ->
                            do_ai_list(CycleAiL, LastActState, NowTimeMS, LastStateName, Killer)
                    end
            end;
        _ ->
            % old: ERef = send_after(Time, Minfo#scene_object.aid, {'special_event', LastEffList}, LastActState#ob_act.eref),
            DelayDrivenSpecial = [{Time, {'special_event', LastEffList}}],
            LastActStateOver = mon_state_util:update_general_driven(LastActState, DelayDrivenSpecial, NowTimeMS),
            {LastActStateOver, LastStateName}
    end.

%% =========================== 私有函数 ========================================================================================
%% 怪物招怪
ai_create_mon(MonInfo, Args) ->
    #scene_object{
        scene = Scene, scene_pool_id = ScenePoolId, copy_id = CopyId
        ,x = X, y = Y
    } = MonInfo,
    [PreMil, Mid, Xmin, Xmax, Ymin, Ymax, IsActive, OtherArgsTemp] = Args,
    OtherArgs = [{from_pid, self()} | OtherArgsTemp],
    case PreMil ==0 orelse PreMil >= 10000 orelse urand:rand(1, 10000) < PreMil of
        true ->
            case create_mon_xy(Xmin, Xmax, Ymin, Ymax, {Scene, CopyId, X, Y}) of
                %% 在玩家脚下创建N只
                {user_pos, N} ->
                    % mod_scene_agent:apply_cast(SceneId, ScenePoolId, )
                    Data = [X, Y, MonInfo#scene_object.tracing_distance, N],
                    lib_mon:create_mon_on_user(
                        Scene, ScenePoolId, CopyId, Data, Mid, IsActive, OtherArgs
                    );
                {Xzero, Yzero} ->
                    lib_mon:async_create_mon(
                        Mid, Scene, ScenePoolId, Xzero, Yzero, IsActive, CopyId, 1, OtherArgs
                    );
                _ ->
                    skip
            end;
        false -> skip
    end,
    ok.
%% 怪物招怪的坐标选取
create_mon_xy(N, N, N, N, _) when N < 0 ->
    {user_pos, -N};
create_mon_xy(Xmin, Xmax, Ymin, Ymax, {SceneId, _CopyId, MonX, MonY})->
    X = if
        % Xmin < 0 orelse Xmax < 0        -> MonX;                          %% 在目标位置召唤
        Xmin < Xmax                     -> MonX + urand:rand(Xmin, Xmax); %% 在Xmin-Xmax直接随机偏移
        Xmin == Xmax andalso Xmin == 0  -> MonX;                          %% 当Xmin=Xmax=0，直接取父辈值
        Xmin == Xmax                    -> Xmin;                          %% 当Xmin=Xmax/=0，直接取Xmin值
        Xmin > Xmax                     -> MonX + Xmin                    %% 取固定偏移值
    end,
    Y = if
        % Ymin < 0 orelse Ymax < 0        -> MonY;                          %% 同X的取值规则
        Ymin < Ymax                     -> MonY + urand:rand(Ymin, Ymax);
        Ymin == Ymax andalso Ymin == 0  -> MonY;
        Ymin == Ymax                    -> Ymin;
        Ymin > Ymax                     -> MonY + Ymin
    end,
    Xzero = case X > 0 of true -> X; false -> 0 end,
    Yzero = case Y > 0 of true -> Y; false -> 0 end,
    case scene_landform:is_block(SceneId, Xzero, Yzero) of
        false ->
            {Xzero, Yzero};
        true ->
            {MonX, MonY}
    end.

%% 获取随机列表
handle_rand_list(PercentageList, NList, EffList) ->
    TotalN = lists:sum(NList),
    {RandL, LeftL} = lists:split(TotalN, EffList),
    RandR = urand:rand(1, lists:sum(PercentageList)),
    ExcL = handle_rand_list_helper(PercentageList, NList, RandR, 0, 0, RandL),
    ExcL ++ LeftL.

handle_rand_list_helper([], _, _, _, _, _) -> [];
handle_rand_list_helper([Percent|TPercentageList], [N|TNList], RandR, LastPerCentPoint, LastN, EffList) ->
    case RandR =< Percent + LastPerCentPoint of
        true  ->
            {_, LeftEffList} = lists:split(LastN, EffList),
            {RandList, _} = lists:split(N, LeftEffList),
            RandList;
        false ->
            handle_rand_list_helper(TPercentageList, TNList, RandR, Percent + LastPerCentPoint, LastN + N, EffList)
    end.

% old:
% %% 发送事件定时器
% send_after(Time, Pid, Msg, ERef) ->
%     util:cancel_timer(ERef),
%     erlang:send_after(Time, Pid, Msg).

% old:
% %% 启动特殊AI事件定时器
% special_ai_timer(TimerType, Time, Pid, Msg, RefList) ->
%     {IsStart, RefList2} = case lists:keytake(TimerType, 1, RefList) of
%         {value, {TimerType, OldRef}, RestList} ->
%             case erlang:read_timer(OldRef) of
%                 TimerInfo when is_integer(TimerInfo) andalso TimerInfo > 0 ->
%                     {false, RefList};
%                 _ ->
%                     {true, RestList}
%             end;
%         _ ->
%             {true, RefList}
%     end,
%     case IsStart of
%         true ->
%             Ref = erlang:send_after(Time, Pid, Msg),
%             [{TimerType, Ref} | RefList2];
%         false ->
%             RefList2
%     end.

%% 给玩家加buff，buff结束后要执行特殊效果
add_buff_to_role_do(State, AiArgs) ->
    {
        RoleNum, SkillId, SkillLev, [PreMil, Mid, IsActive, OtherArgs], BuffTime
    } = AiArgs,
    MonArgs = #create_mon_args{
        rate = PreMil, mid = Mid, is_active = IsActive, args = OtherArgs
    },
    #ob_act{object = Object} = State,
    #scene_object{
        aid = _Aid, scene = SceneId, scene_pool_id = ScenePoolId, copy_id = CopyId
        ,x = ObjectX, y = ObjectY, warning_range = WarningRange, battle_attr = BA
        ,skill_owner = SkillOwner, id = ObjectId, sign = ObjectSign
    } = Object,
    BuffArgs = #add_buff_to_role_args{
        role_num = max(0, RoleNum), skill_id = SkillId, skill_lev = SkillLev
        ,effect = [MonArgs], buff_time = BuffTime, scene = SceneId
        ,scene_pool_id = ScenePoolId
    },
    {OwnerSign, OwnerId} = lib_scene_object_ai:get_skill_owner_args(SkillOwner),
    Args = {BA#battle_attr.group, ObjectSign, ObjectId, OwnerSign, OwnerId},
    mod_scene_agent:apply_cast_with_scene(
        SceneId, ScenePoolId, lib_scene_calc, ai_add_buff_to_role,
        [CopyId, ObjectX, ObjectY, WarningRange, Args, BuffArgs]
    ),
    ok.
%% 怪物ai秒杀场景内的玩家
kill_scene_role(State, RoleNum) ->
    #ob_act{object = Object} = State,
    #scene_object{
        scene = SceneId, scene_pool_id = ScenePoolId, copy_id = CopyId
        ,x = ObjectX, y = ObjectY, warning_range = WarningRange, battle_attr = BA
        ,skill_owner = SkillOwner, id = ObjectId, sign = ObjectSign, mon = Mon
        ,aid = MonPid, figure = Figure
    } = Object,
    #scene_mon{mid = Mid, kind = Kind} = Mon,
    #figure{name = Name, lv = Lev} = Figure,
    {OwnerSign, OwnerId} = lib_scene_object_ai:get_skill_owner_args(SkillOwner),
    Args = {BA#battle_attr.group, ObjectSign, ObjectId, OwnerSign, OwnerId},
    RoleNum2 = max(0, RoleNum),
    Attacker = #battle_return_atter{
        sign = ObjectSign, id = ObjectId, node = node(), mid = Mid, kind = Kind
        ,pid = MonPid, x = ObjectX, y = ObjectY, real_id = ObjectId
        ,real_sign = ObjectSign, real_name = Name, lv = Lev
    },
    mod_scene_agent:apply_cast_with_scene(
        SceneId, ScenePoolId, lib_scene_calc, ai_kill_scene_role,
        [CopyId, ObjectX, ObjectY, WarningRange, Args, RoleNum2, Attacker]
    ),
    ok.


%% ai配置中，过滤掉无效配置数据，只保留需要临时新增的技能列表
filter_ai_skills(Args = [_|_]) ->
    [{SkillId, SkillLv} || {SkillId, SkillLv} <- Args];
filter_ai_skills(_) ->
    [].

