源战役
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

2546 lines
115 KiB

%%%-----------------------------------
%%% @Module : lib_task
%%% @Author : xyao
%%% @Created : 2010.05.05
%%% @Description: 任务
%%%-----------------------------------
-module(lib_task).
-compile(export_all).
-include("scene.hrl").
-include("common.hrl").
-include("server.hrl").
-include("task.hrl").
-include("figure.hrl").
-include("team.hrl").
-include("errcode.hrl").
-include("predefine.hrl").
-include("def_module.hrl").
-include("goods.hrl").
-include("daily.hrl").
-include("def_fun.hrl").
-include("def_goods.hrl").
-include("guild_labor.hrl").
-include("dungeon.hrl").
-include("local_boss.hrl").
-define(LIMIT_TIME1, 900).
-define(LIMIT_TIME2, 1800).
%% 获取我的任务列表
get_my_task_list(TaskArgs)->
get_my_task_list(0,TaskArgs).
get_my_task_list(Type,#task_args{id = RoleId, sid=Sid}=TaskArgs) ->
%% 可接任务
F = fun(TD, TmpActiveList) ->
case Type == 0 orelse TD#task.type == Type of
true ->
[{TD#task.id, get_tip(active, TD#task.id, TaskArgs)} | TmpActiveList];
false ->
TmpActiveList
end
end,
ActiveList = lists:foldl(F, [], get_active()),
%% 已接任务
NowTime = utime:unixtime(),
F1 = fun(RT, {TL, CL}) ->
#role_task{task_id = TaskId, type = TaskType, trigger_time = TriggerTime, mark = Mark} = RT,
if
Type =/= 0 andalso TaskType =/= Type ->
{TL, CL};
TaskType == ?TASK_TYPE_CHAPTER ->
LimitTime = ?IF(TaskId == 101 orelse TaskId == 102, ?LIMIT_TIME1, ?LIMIT_TIME2),
if
NowTime > TriggerTime + LimitTime -> %% 大于限时
case is_finish_mark(Mark, TaskArgs) of
false -> {TL, [RT|CL]};
true ->
TipList = get_tip(trigger, TaskId, TaskArgs),
{WitchState, NeedNum, NowNum} = get_mon_or_goods_nums(TipList),
{[{TaskId, TipList, WitchState, NeedNum, NowNum, TriggerTime}|TL], CL}
end;
true ->
TipList = get_tip(trigger, TaskId, TaskArgs),
{WitchState, NeedNum, NowNum} = get_mon_or_goods_nums(TipList),
{[{TaskId, TipList, WitchState, NeedNum, NowNum, TriggerTime}|TL], CL}
end;
true ->
TipList = get_tip(trigger, TaskId, TaskArgs),
{WitchState, NeedNum, NowNum} = get_mon_or_goods_nums(TipList),
{[{TaskId, TipList, WitchState, NeedNum, NowNum, TriggerTime}|TL], CL}
end
end,
{TriggerList, NeedToDelTask} = lists:foldl(F1, {[], []}, get_trigger()),
%% 删除需要去掉的限时章节任务
F2 = fun(RT) ->
#role_task{task_id = TaskId, type = TaskType, trigger_time = TriggerTime} = RT,
add_log(RoleId, TaskId, TaskType, TriggerTime, 0, 0) %% 完成时间是0就代表过时
end,
lists:map(F2, NeedToDelTask),
{ok, BinData} = pt_300:write(30000, [Type, ActiveList, TriggerList]),
lib_server_send:send_to_sid(Sid, BinData).
%% 获取任务是否完成
get_task_finish_state(TaskId, TaskArgs)->
case get_one_trigger(TaskId) of
false -> ?ERRCODE(err300_no_task_trigger); %% 没接这个任务
RT -> ?IF(is_finish(RT, TaskArgs), true, ?ERRCODE(err300_task_no_finish))
end.
%% 获取任务类型
get_task_type(TaskId) ->
TD = get_data(TaskId),
?IF(TD == null, 0, TD#task.type).
%% 升级自动触发任务
lv_up(TaskArgs) ->
%% 刷新缓存可以优化一下
refresh_active(TaskArgs),
case auto_trigger(TaskArgs) of
true -> skip;
_ ->
skip
end,
get_my_task_list(0, TaskArgs),
refresh_npc_ico(TaskArgs).
%% ================================= 登录加载数据 =================================
flush_role_task(TaskArgs) ->
#task_args{id = Id} = TaskArgs,
%% 所有已经触发的任务列表
F1 = fun([Tid, Tt, S ,ES, M, TP, Lv], AllTask) ->
case data_task:get(Tid) of
null ->
del_trigger_from_sql(Id, Tid), %% 移除无效的已接任务
AllTask;
_ ->
Kind = case data_task_condition:get(Tid) of
null -> 0;
TD -> TD#task_condition.kind
end,
case util:bitstring_to_term(M) of
undefined -> AllTask;
Mark ->
[#role_task{role_id=Id, lv = Lv, task_id=Tid, trigger_time = Tt,
state = S, end_state = ES, mark = Mark, type=TP, kind = Kind}|AllTask]
end
end
end,
RoleTaskList = db:get_all(io_lib:format("select task_id, trigger_time, state, end_state, mark, type, lv from task_bag where role_id=~w", [Id])),
RoleTaskListRed = lists:foldl(F1, [], RoleTaskList),
set_task_bag_list(RoleTaskListRed),
%% 所有已经完成的任务列表
F2 = fun([Tid2, Ty2]) ->
put_task_log_list(Tid2,#role_task_log{type= Ty2})
end,
RoleTaskLogList = db:get_all(io_lib:format("select task_id, type from task_log where role_id=~w", [Id])),
lists:map(F2, RoleTaskLogList),
refresh_active(TaskArgs),
get_my_task_list(0, TaskArgs),
%% 自动接取任务
auto_trigger(TaskArgs),
auto_finish(TaskArgs),
login_after(TaskArgs),
ok.
login_after(TaskArgs) ->
%%同步转生任务id
case get_task_bag_id_list_type(?TASK_TYPE_TURN) of
[#role_task{task_id = TaskId} | _T] ->
lib_task_event:trigger_after(data_task:get(TaskId), TaskArgs);
_ -> ok
end.
%%上线处理已完成的触发任务
handle_refresh_trigger(TaskArgs)->
RoleTaskList = get_task_bag_id_list(),
%%纠正配置不匹配任务
case catch do_refresh_conflict_trigger(RoleTaskList, TaskArgs, []) of
UpdateList when is_list(UpdateList) ->
case UpdateList =/= [] of
true ->
refresh_task(TaskArgs);
false -> ok
end;
_Rson ->
?ERR("do_refresh_conflict_trigger~p~n",[_Rson])
end,
NewRoleTaskList = get_task_bag_id_list(),
%%自动完成已接取的特殊支线任务和可能离线完成的主线特殊任务(副本)
case catch do_handle_refresh_trigger(NewRoleTaskList, TaskArgs, []) of
[] -> ok;
EventList when is_list(EventList) ->
lib_player:apply_cast(TaskArgs#task_args.id, ?APPLY_CAST_STATUS, lib_task_api, cast_handle_refresh_trigger, [EventList]);
_Reason ->
Rid = TaskArgs#task_args.id,
?ERR("do_handle_refresh_trigger~p:~p~n",[Rid, _Reason])
end.
%%纠正配置不匹配任务
do_refresh_conflict_trigger([], _TaskArgs, UpdateList) -> UpdateList;
do_refresh_conflict_trigger([RT | T], TaskArgs, UpdateList) ->
TD = data_task:get(RT#role_task.task_id),
NewUpdateList = do_conflict_correct(TD, TaskArgs, RT, UpdateList),
do_refresh_conflict_trigger(T, TaskArgs, NewUpdateList).
%%检测条件
% 等级不匹配:直接清任务
% 任务内容不匹配:替换更新任务
do_conflict_correct(#task{type = Type} = TD, TaskArgs, RT, UpdateList)
when Type == ?TASK_TYPE_MAIN orelse Type == ?TASK_TYPE_SIDE orelse
Type == ?TASK_TYPE_TURN orelse Type == ?TASK_TYPE_CHAPTER orelse
Type == ?TASK_TYPE_NUCLEON ->
CheckList = [lv, content],
case check_conflict(CheckList, TaskArgs, TD, RT) of
{true, Reason, NewRT} ->
do_conflict_correct_help(Reason, RT, NewRT),
[1|UpdateList];
_ -> UpdateList
end;
do_conflict_correct(_, _TaskArgs, _RT, UpdateList) -> UpdateList.
check_conflict([], _TaskArgs, _TD, _RT) -> true;
check_conflict([lv | T], TaskArgs, TD, RT) ->
Lv = TaskArgs#task_args.figure#figure.lv,
case Lv < TD#task.level of
true -> {true, del, RT};
false -> check_conflict(T, TaskArgs, TD, RT)
end;
check_conflict([content | T], TaskArgs, #task{content = Content} = TD, RT) ->
CfgTaskMark = [content_to_mark(E, TaskArgs)|| E <- Content]
++ case TD#task.end_talk of
0 -> []; %% end_talk = 0则直接提交任务
_ ->
[content_to_mark([TD#task.state, ?TASK_CONTENT_END_TALK, TD#task.end_npc,
TD#task.end_talk, 0, 0, 0, TD#task.finish_pathfind], TaskArgs)]
end,
Mark = RT#role_task.mark,
%%检测任务内容冲突(主要存在情况)
case check_content_conflict(CfgTaskMark, Mark, RT, []) of
{true, Mark, _NewRT} -> check_conflict(T, TaskArgs, TD, RT);
{true, _NewMark, NewRT} -> %%与配置有出入,处理
% ?ERR("do_conflict_trigger~p,~p,~p~n", [TaskArgs#task_args.id, NewMark, Mark]),
{true, update, NewRT};
_ -> check_conflict(T, TaskArgs, TD, RT)
end;
check_conflict([_H | T], TaskArgs, TD, RT) ->
check_conflict(T, TaskArgs, TD, RT).
check_content_conflict([], [], RT, NewMark) -> {true, NewMark, RT#role_task{mark = NewMark}};
check_content_conflict([], _, RT, NewMark) -> {true, NewMark, RT#role_task{mark = NewMark}};
check_content_conflict([CfgE | CfgT], [ME | MET], RT, NewMark) ->
[State, _, ContentType, Id, NeedNum, RealSceneId, RealX, RealY, _, PathFind] = CfgE,
case ME of
[State, _Finish, ContentType, Id, NeedNum, RealSceneId, RealX, RealY, _Num, _PathFind] -> %%相同不处理
NewMark1 = NewMark ++ [ME],
check_content_conflict(CfgT, MET, RT, NewMark1);
[_, _, ContentType, Id, _, _, _, _, Num, _] -> %% 类型和id相同,保持数量不变,纠正其它信息
case Num >= NeedNum of
true ->
NewMark1 = NewMark ++ [[State, 1, ContentType, Id, NeedNum, RealSceneId, RealX, RealY, Num, PathFind]];
false ->
FinishState = ?IF(ContentType == ?TASK_CONTENT_END_TALK, 1, 0),
NewMark1 = NewMark ++ [[State, FinishState, ContentType, Id, NeedNum, RealSceneId, RealX, RealY, Num, PathFind]]
end,
check_content_conflict(CfgT, MET, RT, NewMark1);
[_, _, _, _, _, _, _, _, _, _] -> %% 纠正所有信息
NewMark1 = NewMark ++ [CfgE],
check_content_conflict(CfgT, MET, RT, NewMark1);
_ -> ok %%异常
end;
check_content_conflict([CfgE | CfgT], [], RT, NewMark) ->
NewMark1 = NewMark ++ [CfgE],
check_content_conflict(CfgT, [], RT, NewMark1).
%%处理冲突的任务
do_conflict_correct_help(update, _OldRT, NewRT) ->
#role_task{role_id = RId, task_id = TaskId, mark = Mark, end_state = EndState} = NewRT,
NoFinishState = [EachState || [EachState, 0|_ ] <- Mark],
if
NoFinishState == [] -> NewState = EndState;
true -> NewState = lists:min(NoFinishState)
end,
?IF(NewState == 0, ok, refresh_npc_ico(RId)),
upd_trigger(RId, TaskId, NewState, Mark),
put_task_bag_list(NewRT#role_task{write_db = 0, state = NewState}),
case NewState == EndState of
true ->
case lists:last(Mark) of
[_, 1, ?TASK_CONTENT_END_TALK|_] -> ok;
_R -> auto_finish_task(RId, TaskId)
end;
_ -> ok
end;
do_conflict_correct_help(del, _OldRT, NewRT) ->
#role_task{role_id = RId, task_id = TaskId} = NewRT,
%% 删除缓存
delete_task_bag_list(TaskId),
%% 删除数据库
del_trigger_from_sql(RId, TaskId),
%% 刷新npc头图标
refresh_npc_ico(RId),
ok;
do_conflict_correct_help(_, _OldRT, _NewRT) -> ok.
%%处理已完成的触发支线任务
do_handle_refresh_trigger([], _TaskArgs, EventList) -> EventList;
do_handle_refresh_trigger([#role_task{type = ?TASK_TYPE_SIDE, task_id = TaskId, mark = TaskMark} |T], TaskArgs, OEventList) ->
EventList = handle_finish_before_trigger(TaskId, TaskMark, TaskArgs, []),
do_handle_refresh_trigger(T, TaskArgs, OEventList ++ EventList);
do_handle_refresh_trigger([#role_task{type = ?TASK_TYPE_MAIN, task_id = TaskId, mark = [ [_State, 0, ?TASK_CONTENT_DUNGEON|_T1] | _T2 ] = TaskMark } |T], TaskArgs, OEventList) ->
EventList = handle_finish_before_trigger(TaskId, TaskMark, TaskArgs, []),
do_handle_refresh_trigger(T, TaskArgs, OEventList ++ EventList);
do_handle_refresh_trigger([_RT |T], TaskArgs, EventList) ->
do_handle_refresh_trigger(T, TaskArgs, EventList).
%% 刷新任务并发送更新列表
refresh_task(#task_args{id=Id}=TaskArgs) ->
refresh_active(TaskArgs),
refresh_npc_ico(Id),
{ok, BinData} = pt_300:write(30006, []),
lib_server_send:send_to_uid(Id, BinData).
%% 遍历所有任务看是否可接任务
refresh_active(TaskArgs) ->
#task_args{figure=#figure{lv=Lv}} = TaskArgs,
Tids = data_task_lv:get_ids(Lv),
F = fun(Tid) -> get_data(Tid) end,
QueryCacheListRed = [F(Tid) || Tid <- Tids, check_task_type(Tid), can_trigger(Tid, TaskArgs) == true],
set_query_cache_list(QueryCacheListRed).
%% 日常和公会任务不会进入可接缓存
check_task_type(Tid)->
#task{type = TaskType} = get_data(Tid),
?IF(TaskType == ?TASK_TYPE_DAILY orelse TaskType == ?TASK_TYPE_GUILD, false, true).
%% 刷新悬赏任务和公会周任务
refresh_trigger_by_type(TaskArgs, TaskType) ->
TriggerTasks = get_trigger(),
F1 = fun(RT, L) -> ?IF(RT#role_task.type =/= TaskType, [RT|L], L) end,
NewTriggerList0 = lists:foldl(F1, [], TriggerTasks),
KfDay = data_key_value:get(1030001),
NewTriggerList = case util:get_open_day()>= KfDay of
true->
fix_task_npc(NewTriggerList0,[],TaskArgs);
_->
NewTriggerList0
end,
set_task_bag_list(NewTriggerList).
%% 获取任务详细数据
get_data(TaskId) ->
TD = data_task:get(TaskId),
?IF(TD == null, #task{}, TD).
%% 获取玩家能在该Npc接任务或者交任务
get_npc_task_list(NpcId, TaskArgs) ->
{CanTrigger, Link, UnFinish, Finish} = get_npc_task(NpcId, TaskArgs),
F1 = fun({Tid,TriTime,ShowTalk}, NS) -> TD = get_data(Tid), {Tid, NS, TD#task.name, TD#task.type,TriTime,ShowTalk} end,
F2 = fun(TD, NS) -> {TD#task.id, NS, TD#task.name, TD#task.type,0,0} end,
L1 = [F2(T1, 1) || T1 <- CanTrigger, T1#task.level =< TaskArgs#task_args.figure#figure.lv],
L2 = [F1(T2, 4) || T2 <- Link],
L3 = [F1(T3, 2) || T3 <- UnFinish],
L4 = [F1(T4, 3) || T4 <- Finish],
L1++L2++L3++L4.
%% 动态控制npc
do_dynamic_npc(TaskArgs, []) -> TaskArgs;
do_dynamic_npc(#task_args{id=Id, npc_info=NpcInfo}=TaskArgs, NpcShow) ->
NewNpcInfo = lib_npc:change_role_npc_info(Id, NpcInfo, NpcShow),
lib_player:apply_cast(Id, ?APPLY_CAST_STATUS, lib_npc, update_role_npc_info, [NewNpcInfo]),
TaskArgs#task_args{npc_info=NewNpcInfo}.
%% 更新场景上npc的任务图标
refresh_npc_ico(#task_args{scene=Scene, sid=Sid, npc_info=NpcInfo}=TaskArgs) ->
NpcList = lib_npc:get_scene_npc(Scene, NpcInfo),
F = fun({Id, _, _, _, _, _}) ->
S = ?IF(Id == 0, 0, get_npc_state(Id, TaskArgs)),
[Id, S]
end,
L = lists:map(F, NpcList),
{ok, BinData} = pt_120:write(12020, [L]),
lib_server_send:send_to_sid(Sid, BinData);
refresh_npc_ico(#player_status{} = PS) ->
TaskArgs = lib_task_api:ps2task_args(PS),
refresh_npc_ico(TaskArgs);
refresh_npc_ico(PlayerId) ->
case misc:get_player_process(PlayerId) of
Pid when is_pid(Pid) -> lib_player:apply_cast(Pid, ?APPLY_CAST_STATUS, ?NOT_HAND_OFFLINE, lib_task, refresh_npc_ico, []);
_ -> skip
end.
%% 获取npc任务状态
get_npc_state(NpcId, TaskArgs) ->
{CanTrigger, Link, UnFinish, Finish} = get_npc_task(NpcId, TaskArgs),
%% 0表示什么都没有,1表示有可接任务,2表示已接受任务但未完成,3表示有完成任务,4表示有任务相关
case length(Finish) > 0 of
true -> 3;
false ->
case length(Link)>0 of
true-> 4;
false->
case length([0 || RT <- CanTrigger, RT#task.level =< TaskArgs#task_args.figure#figure.lv])>0 of
true -> 1;
false ->
case length(UnFinish)>0 of
true -> 2;
false -> 0
end
end
end
end.
%% 获取npc任务关联
%%{可接任务,关联,任务未完成,完成任务}
get_npc_task(NpcId, TaskArgs)->
CanTrigger = [ TS || TS <- get_query_cache_list(), lib_role_task:exchange_npc(TS#task.start_npc) =:= NpcId],
%% 已经接了的任务处理
{Link, Unfinish, Finish} = get_npc_other_link_task(NpcId, TaskArgs),
{CanTrigger, Link, Unfinish, Finish}.
%% 获取已触发任务
get_npc_other_link_task(NpcId, TaskArgs) ->
get_npc_other_link_task(get_task_bag_id_list(), {[], [], []}, NpcId, TaskArgs).
get_npc_other_link_task([], Result, _, _) -> Result;
get_npc_other_link_task([RT | T], {Link, Unfinish, Finish}, NpcId, TaskArgs) ->
TD = get_data(RT#role_task.task_id),
case is_finish(RT, TaskArgs) andalso get_end_npc_id(RT) =:= NpcId of %% 判断是否完成
true -> get_npc_other_link_task(T, {Link, Unfinish, Finish++[{RT#role_task.task_id,RT#role_task.trigger_time,filter_show_talk(RT#role_task.mark)}]}, NpcId, TaskArgs);
false ->
case task_talk_to_npc(RT, NpcId) of %% 判断是否和NPC对话
true -> get_npc_other_link_task(T, {Link++[{RT#role_task.task_id,RT#role_task.trigger_time,filter_show_talk(RT#role_task.mark)}], Unfinish, Finish}, NpcId, TaskArgs);
false ->
%% 获取npc未完成
case get_start_npc(TD#task.start_npc, TaskArgs#task_args.figure#figure.career) =:= NpcId of %% 判断是否接任务NPC
true -> get_npc_other_link_task(T, {Link, Unfinish++[{RT#role_task.task_id,RT#role_task.trigger_time,filter_show_talk(RT#role_task.mark)}], Finish}, NpcId, TaskArgs);
false -> get_npc_other_link_task(T, {Link, Unfinish, Finish}, NpcId, TaskArgs)
end
end
end.
%%过滤对话选项任务的完成TalkId
filter_show_talk([])->
0;
filter_show_talk([H|T])->
case H of
[_, _, ?TASK_CONTENT_CHOOSE_TALK, _NeedId, ShowTalk, _Scene, _X, _Y,_Talk, _PathFind]->
ShowTalk;
_->
filter_show_talk(T)
end.
%%检查任务的下一内容是否为与某npc的对话
task_talk_to_npc(RT, NpcId)->
Temp = [0 || [State, Fin, CType, Nid|_] <- RT#role_task.mark, State =:= RT#role_task.state, Fin =:= 0,lib_role_task:exchange_npc(Nid) =:= NpcId,lists:member(CType,[?TASK_CONTENT_TALK,?TASK_CONTENT_CHOOSE_TALK,?TASK_CONTENT_MAILER_RUN])],
length(Temp)>0.
%% 获取任务对话id
get_npc_task_talk_id(TaskId, NpcId, TaskArgs) ->
case get_data(TaskId) of
null -> {none, 0};
TD ->
{CanTrigger, Link, UnFinish, Finish} = get_npc_task(NpcId, TaskArgs),
case {lists:keymember(TaskId, #task.id, CanTrigger), lists:keymember(TaskId,1,Link),
lists:keymember(TaskId,1,UnFinish), lists:keymember(TaskId,1,Finish) } of
{true, _, _, _} -> {start_talk, TD#task.start_talk}; %% 任务触发对话
{_, true, _, _} -> %% 关联对话
case get_one_trigger(TaskId) of
false ->
{none, 0};
RT ->
[Fir|_] = [TalkId || [State,Fin,CType,Nid,TalkId|_] <- RT#role_task.mark,
State=:= RT#role_task.state, Fin=:=0, lib_role_task:exchange_npc(Nid) =:= NpcId,lists:member(CType,[?TASK_CONTENT_TALK,?TASK_CONTENT_CHOOSE_TALK,?TASK_CONTENT_MAILER_RUN])],
{link_talk, Fir}
end;
{_, _, true, _} -> {unfinished_talk, TD#task.unfinished_talk}; %% 未完成对话
{_, _, _, true} -> %% 提交任务对话
case get_one_trigger(TaskId) of
false ->
{none, 0};
RT ->
[Fir|_] = [TalkId || [_,_,?TASK_CONTENT_END_TALK,Nid,TalkId|_] <- RT#role_task.mark, lib_role_task:exchange_npc(Nid) == NpcId],
{end_talk, Fir}
end;
_ -> {none, 0}
end
end.
%% 获取提示信息
%% 可接任务会有开始npc对话
get_tip(active, TaskId, #task_args{figure=#figure{career=Career}}=TaskArgs) ->
TD = get_data(TaskId),
case get_start_npc(TD#task.start_npc, Career) of
0 -> [];
StartNpcId ->
[content_to_mark([0, ?TASK_CONTENT_TALK, StartNpcId, TD#task.start_talk, 0, 0, 0, TD#task.trigger_pathfind], TaskArgs)]
end;
get_tip(trigger, TaskId, TaskArgs) ->
RT = get_one_trigger(TaskId),
[mark_refresh(TaskMark, TaskArgs) || TaskMark <- RT#role_task.mark].
%% 任务阶段内容 转为 任务完成情况记录
%% 任务内容格式:[State(阶段), ContentType(内容类型), Id(任务id), Num(采集或者杀怪的需要数量), ScneId, X, Y, PathFind]
%% 任务内存格式:[State(阶段), IsFinish(是否完成) ContentType(内容类型), Id(任务id), Num(采集或者杀怪的需要数量), ScneId, X, Y, RealNum(收集或者杀怪的完成数量), PathFind]
content_to_mark([State, ContentType, Id, Num, SceneId, X, Y, PathFind], TaskArgs) ->
content_to_mark([State, ContentType, Id, Num, SceneId, X, Y, PathFind], [],TaskArgs).
content_to_mark([State, ContentType, Id, Num, SceneId, X, Y, PathFind], _Contents, TaskArgs)->
case ContentType of
?TASK_CONTENT_START_TALK ->
NewId=lib_role_task:exchange_npc(Id),
{RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
[State, 0, ContentType, NewId, Num, RealSceneId, RealX, RealY, 0, PathFind];
?TASK_CONTENT_END_TALK ->
NewId=lib_role_task:exchange_npc(Id),
{RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
[State, 1, ContentType, NewId, Num, RealSceneId, RealX, RealY, 0, PathFind];
?TASK_CONTENT_TALK ->
NewId=lib_role_task:exchange_npc(Id),
{RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
[State, 0, ContentType, NewId, Num, RealSceneId, RealX, RealY, 0, PathFind];
?TASK_CONTENT_ITEM ->
#task_args{id = RoleId, gs_dict = GsDict} = TaskArgs,
case data_goods_type:get(Id) of
#ets_goods_type{bag_location = BagLocation} ->
GoodsList = lib_goods_util:get_type_goods_list(RoleId, Id, BagLocation, GsDict, 0),
TotalNum = lib_goods_util:get_goods_total_num(GoodsList);
_ ->
?ERR("goods_num err: goods_type_id = ~p err_config", [Id]),
TotalNum = 0
end,
{Finish, NowNum} = ?IF(TotalNum >= Num, {1, Num}, {0, TotalNum}),
[State, Finish, ContentType, Id, Num, SceneId, X, Y, NowNum, PathFind];
?TASK_CONTENT_MAILER_RUN ->
NewId=lib_role_task:exchange_npc(Id),
{RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
[State, 0, ContentType, NewId, Num, RealSceneId, RealX, RealY, 0, PathFind];
_ ->
[State, 0, ContentType, Id, Num, SceneId, X, Y, 0, PathFind]
end;
content_to_mark(_, _Contents, _TaskArgs) -> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0].
%% 异常时刷新
mark_refresh([State, Fin, ContentType, Id, Num, Scene, _X, _Y, Count, PathFind]=Mark, TaskArgs) ->
if
Scene == 0 andalso (ContentType == ?TASK_CONTENT_START_TALK orelse
ContentType == ?TASK_CONTENT_END_TALK orelse
ContentType == ?TASK_CONTENT_TALK) ->
NewNpc=lib_role_task:exchange_npc(Id),
{RealSceneId, RealX, RealY} = get_npc_info(NewNpc, TaskArgs#task_args.npc_info),
[State, Fin, ContentType, NewNpc, Num, RealSceneId, RealX, RealY, Count, PathFind];
ContentType =:= ?TASK_CONTENT_CHOOSE_TALK ->
NewNpc = lib_role_task:exchange_npc(Id),
{RealSceneId, RealX, RealY} = get_npc_info(NewNpc, TaskArgs#task_args.npc_info),
[State, Fin, ContentType, NewNpc, Num, RealSceneId, RealX, RealY, Count, PathFind];
true ->
Mark
end.
%% 获取奖励
get_award_item(TD, TaskArgs) ->
SL = get_special_reward_item(TD#task.special_goods_list, TaskArgs, []),
F = fun(E, LL) ->
case E of
{?TYPE_GOODS, GoodsTypeId, Num} -> [{?TYPE_BIND_GOODS, GoodsTypeId, Num}|LL];
_ -> [E|LL]
end
end,
lists:foldl(F, SL, TD#task.award_list).
%% 获取特殊奖励
get_special_reward_item([], _TaskArgs, Rewards) -> Rewards;
get_special_reward_item([{Career, Sex, GoodsTypeId, Num}|SpecialGoods], TaskArgs, Rewards) ->
if
Career == 0 andalso Sex == 0 ->
get_special_reward_item(SpecialGoods, TaskArgs, [{?TYPE_BIND_GOODS, GoodsTypeId, Num}|Rewards]);
Career == TaskArgs#task_args.figure#figure.career andalso Sex == 0->
get_special_reward_item(SpecialGoods, TaskArgs, [{?TYPE_BIND_GOODS, GoodsTypeId, Num}|Rewards]);
Sex == TaskArgs#task_args.figure#figure.sex andalso Career == 0 ->
get_special_reward_item(SpecialGoods, TaskArgs, [{?TYPE_BIND_GOODS, GoodsTypeId, Num}|Rewards]);
Career == TaskArgs#task_args.figure#figure.career andalso Sex == TaskArgs#task_args.figure#figure.sex ->
get_special_reward_item(SpecialGoods, TaskArgs, [{?TYPE_BIND_GOODS, GoodsTypeId, Num}|Rewards]);
true ->
get_special_reward_item(SpecialGoods, TaskArgs, Rewards)
end;
get_special_reward_item([_|SpecialGoods], TaskArgs, Rewards) ->
get_special_reward_item(SpecialGoods, TaskArgs, Rewards).
%% 获取开始npc的id
%% 如果需要判断职业才匹配第2,3
get_start_npc(StartNpc, _) when is_integer(StartNpc) ->
lib_role_task:exchange_npc(StartNpc);
get_start_npc([], _) -> 0;
get_start_npc([{career, Career, NpcId}|T], RoleCareer) ->
case Career =:= RoleCareer of
false -> get_start_npc(T, RoleCareer);
true -> lib_role_task:exchange_npc(NpcId)
end.
%%获取当前NPC所在的场景(自动寻路用)
get_npc_info(NpcId, NpcInfo) ->
case lists:keyfind(NpcId, 1, NpcInfo) of
{_, _IsShow, Scene, X, Y, _} -> {Scene, X, Y};
false ->
case lib_npc:get_npc_info_by_id(NpcId) of
[] -> {0, 0, 0};
Npc -> {Npc#ets_npc.scene, Npc#ets_npc.x, Npc#ets_npc.y}
end
end.
%%获取当前怪物所在的场景
get_mon_info(MonId) ->
case mod_scene_mon:lookup(MonId) of
[] -> {0, 0, 0};
D -> {D#ets_scene_mon.scene, D#ets_scene_mon.x, D#ets_scene_mon.y}
end.
%% 指定id任务是否可接
in_active(TaskId) ->
find_query_cache_exits(TaskId).
get_active() ->
get_query_cache_list().
get_active(type, Type) ->
get_query_cache_list_type(Type).
%% 获取已触发任务列表
get_trigger() ->
get_task_bag_id_list().
%% 获取该阶段任务内容
get_phase(RT)->
[[State | T] || [State | T] <- RT#role_task.mark, RT#role_task.state =:= State].
%% 获取任务阶段的未完成内容:改成这个任务没有最终完成的
%% get_phase_unfinish(RT)->
%% [[State, Fin | T] || [State, Fin |T] <- RT#role_task.mark].
get_one_trigger(TaskId) ->
find_task_bag_list(TaskId).
%% 查看是否领取了指定的任务ID:是:true 否:false
is_trigger_task_id(TaskId) ->
case find_task_bag_list(TaskId) of
false -> false;
_ -> true
end.
%% 查看是否领取了指定的任务ID:是:true 否:false
is_during_task(TaskId) ->
case find_task_bag_list(TaskId) of
#role_task{state=S} when S=<0->
true;
_ ->
false
end.
%% 只能在任务进程调用
%% 查看是否完成了指定的任务ID:是:true 否:false
is_finish_task_id(TaskId) ->
case find_task_log_list(TaskId) of
false -> false;
_ -> true
end.
%% 只能在任务进程调用
%% 查看是否完成了多个指定的任务ID:
%% return 已完成的TaskId的Bin形式
%% 是否完成多个任务
%% TaskIds可以是列表形式:[TaskId]
%% TaskIds也可以打包形式(Bin形式):lib_task:pack_task_id([TaskId])
is_finish_task_ids(BinTaskIds) when is_binary(BinTaskIds)->
TaskIds = unpack_task_id(BinTaskIds),
FinishIds = is_finish_task_ids(TaskIds),
pack_task_id(FinishIds);
%% return 已完成的TaskId
is_finish_task_ids(TaskIds) ->
F = fun(TaskId, TmpList)->
case find_task_log_list(TaskId) of
false -> TmpList;
_ -> [TaskId|TmpList]
end
end,
FinishIds = lists:foldl(F, [], TaskIds),
FinishIds.
%% 只能在任务进程调用
%% 是否完成对应章节的所有主线任务
is_finish_chapter_all_task(Chapter) ->
List = data_task:get_ids_by_chapter(Chapter),
F = fun(TaskId) ->
is_finish_task_id(TaskId)
end,
lists:all(F, List).
%% 获取结束任务的npcid
get_end_npc_id(RT) when is_record(RT, role_task)->
get_end_npc_id(RT#role_task.mark);
get_end_npc_id(TaskId) when is_integer(TaskId) ->
case get_one_trigger(TaskId) of
false -> 0;
RT -> get_end_npc_id(RT)
end;
get_end_npc_id([]) -> 0;
get_end_npc_id(Mark) ->
case lists:last(Mark) of
[_, _, ?TASK_CONTENT_END_TALK, NpcId|_] -> lib_role_task:exchange_npc(NpcId);
_ -> 0 %% 这里是异常
end.
%% ================================= 任务触发检查 =================================
%% 检查是否可以触发任务
can_trigger(TaskId, TaskArgs) ->
#figure{lv = PlayerLv, career = PlayerCareer, realm = PlayerRealm,
turn = PlayerTurn, guild_id = PlayerGuilId} = TaskArgs#task_args.figure,
case find_task_bag_exits(TaskId) of
true ->
{false, ?ERRCODE(err300_task_trigger)}; %%已经触发过了
false ->
case data_task_condition:get(TaskId) of
null ->
{false, ?ERRCODE(err300_task_config_null)};
#task_condition{type = TaskType, level = Level, level_max = MaxLevel, realm = Realm,
career = Career, turn = Turn, prev = Prev, repeat = Repeat, condition = Condition} = _TD ->
if
(TaskType ==?TASK_TYPE_DAILY orelse TaskType == ?TASK_TYPE_GUILD) andalso
(PlayerLv > MaxLevel orelse PlayerLv < Level)->
{false, ?ERRCODE(err300_lv_not_enough)}; %% 等级不足
PlayerLv < Level ->
{false, ?ERRCODE(err300_lv_not_enough)}; %% 等级不足
TaskType == ?TASK_TYPE_GUILD andalso PlayerGuilId == 0 -> %% 没有帮派
{false, ?ERRCODE(err300_not_guild)};
Realm /=0 andalso PlayerRealm /= Realm ->
{false, ?ERRCODE(err300_realm_diff)}; %% 阵营不符合
Career /= 0 andalso PlayerCareer /= Career ->
{false, ?ERRCODE(err300_career_diff)}; %% 阵营不符合
Turn /= 0 andalso PlayerTurn < Turn ->
{false, ?ERRCODE(err300_turn_diff)}; %% 转生次数不符合(向下兼容)
TaskType == ?TASK_TYPE_TURN andalso PlayerTurn > Turn andalso PlayerTurn > 0 ->
{false, ?ERRCODE(err300_turn_diff)}; %% 如果是转生任务 但是玩家的转生次数已经超过了任务的转生次数则不能重复触发
true ->
case check_prev_task(Prev) of
false -> {false, ?ERRCODE(err300_prev_not_fin)}; %% 前置任务未完成
true ->
case check_repeat(TaskId, Repeat) of
false -> {false, ?ERRCODE(err300_fin)};
true ->
case length([1||ConditionItem <- Condition, check_condition(ConditionItem, TaskId, TaskArgs)=:=false]) =:= 0 of
true -> true;
false -> {false, ?ERRCODE(err300_condition_err)}
end
end
end
end
end
end.
% %% 获取下一等级的任务
% next_lev_list(PS) ->
% Tids = data_task:get_ids(),
% F = fun(Tid) -> TD = get_data(Tid), (PS#player_status.figure#figure.lv + 1) =:= TD#task.level end,
% [XTid || XTid<-Tids, F(XTid)].
%% 是否重复可以接
check_repeat(TaskId, Repeat) ->
case Repeat =:= 0 of
true -> find_task_log_exits(TaskId) =/= true;
false -> true
end.
%% 前置任务
check_prev_task(PrevId) ->
case PrevId =:= 0 of
true -> true;
false -> find_task_log_exits(PrevId)
end.
%% 任务条件建检查
%% 是否完成任务
check_condition({task, TaskId}, _, _) -> find_task_log_exits(TaskId);
%% 是否完成其中之一的任务
check_condition({task_one, TaskList}, _, _) -> lists:any(fun(Tid)-> find_task_log_exits(Tid) end, TaskList);
%% 今天的任务次数是否过多
check_condition({daily_limit, Num}, TaskId, _) ->
case find_task_log_list(TaskId) of false -> true; RTL -> RTL#role_task_log.count < Num end;
%%验证开服天数
check_condition({open_day,Day},_,_)->
OpDay = util:get_open_day(),
OpDay>=Day;
%% 容错
check_condition(_Other, _, _TaskArgs) -> false.
%% ================================= 触发任务 =================================
%% 自动触发任务
auto_trigger(TaskArgs) ->
ActiveTasks = get_active(), %% 获取可以接的任务
do_auto_trigger(TaskArgs,ActiveTasks).
auto_trigger(Type,TaskArgs)->
ActiveTasks = get_active(type,Type),
do_auto_trigger(TaskArgs,ActiveTasks).
do_auto_trigger(TaskArgs,ActiveTasks)->
F = fun(TD, Bool) ->
case TD#task.start_npc == 0 andalso TD#task.start_talk == 0 of
true -> trigger(TD#task.id, TaskArgs), true;
false -> Bool
end
end,
lists:foldl(F, false, ActiveTasks).
%% 手动触发任务
%% return true | {false, Code}
trigger(TaskId, TaskArgs) ->
%% 注: 给机器人放行逻辑
IsRobot = lib_robot:is_robot(TaskArgs),
CanTrigger = case can_trigger(TaskId, TaskArgs) of
{false, _ErrCode} when IsRobot == true -> true;
{false, ErrCode} -> {false, ErrCode};
true -> true
end,
case CanTrigger of
{false, Res} -> {false, Res};
true ->
TD = get_data(TaskId),
TaskMark = [content_to_mark(E, TaskArgs)||E<-TD#task.content]
++ case TD#task.end_talk of
0 -> []; %% end_talk = 0则直接提交任务
_ -> [content_to_mark([TD#task.state, ?TASK_CONTENT_END_TALK, TD#task.end_npc,
TD#task.end_talk, 0, 0, 0, TD#task.finish_pathfind], TaskArgs)]
end,
Now = utime:unixtime(),
add_trigger(TaskArgs#task_args.id, TaskId, Now, 0, TD#task.state,
TaskMark, TD#task.type, TD#task.kind, TaskArgs#task_args.figure#figure.lv),
case handle_finish_before_trigger(TaskId, TaskMark, TaskArgs, []) of
EventList when is_list(EventList) andalso EventList =/= [] ->
lib_player:apply_cast(TaskArgs#task_args.id, ?APPLY_CAST_SAVE, lib_task_api, cast_handle_refresh_trigger, [EventList]);
_ -> ok
end,
%% 转生任务接取了要通知其他模块
?IF(TD#task.type =/= ?TASK_TYPE_TURN, skip,
lib_player:apply_cast(TaskArgs#task_args.id, ?APPLY_CAST_SAVE, transform, trigger_task, [TD#task.id])),
get_my_task_list(TD#task.type, TaskArgs),
refresh_npc_ico(TaskArgs),
lib_task_event:trigger_after(TD, TaskArgs),
%lib_player:apply_cast(TaskArgs#task_args.id, ?APPLY_CAST_SAVE, ta_agent_fire, task_completed, [Now, [TD#task.id, 1, 0]]),
true
end.
%% 有部分支线任务内容在触发时候判断
%% 增加的对应类型,要同步在lib_task_api:make_action_list()增加类型支持
handle_finish_before_trigger(_TaskId, [], _TaskArgs, EventList) -> EventList;
%%转生任务
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_TURN, Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_TURN,Id} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%好友数量
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_ADD_FRIEND, _Id, Num, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_ADD_FRIEND, Num, NowNum} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%副本进度
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_DUN_WAVE, Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_DUN_WAVE, Id} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%某个副本
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_DUNGEON, Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_DUNGEON, Id} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%副本类型
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_DUNGEON_TYPE, Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_DUNGEON_TYPE, Id} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%指定BOSS
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_KILL_BOSS, Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_KILL_BOSS, Id} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%装备进化
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_ERISE, _Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_ERISE} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%装备强化
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_STREN, _Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_STREN} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%装备附能
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_EMPOWER, _Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_EMPOWER} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%活跃度
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_DAY_ACTIVITY, _Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_DAY_ACTIVITY} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%副本类型特定经验
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_DUNGEON_EXP, Id, Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_DUNGEON_EXP, Id, Num} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%层级副本类型
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_DUNGEON_RUNE, DunType, DunId, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_DUNGEON_RUNE, DunType, DunId} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%动态积分购买
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_SCORE_BUY, Item,_Num, _Scene, ShopId, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_SCORE_BUY, Item, ShopId} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%好友度
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_FRIEND_EXP, _Id,_Num, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_FRIEND_EXP, NowNum} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%竞技场
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_ARENA_TIMES, _Id,_Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_ARENA_TIMES} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%装备套装
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_EQUIP_SUIT, _Id,_Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_EQUIP_SUIT} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%进阶系统
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_FOSTER_GRADE, Type,_Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_FOSTER_GRADE, Type} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%预期任务
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_EXPECT_TASK, ExpectTask,_Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId,?TASK_CONTENT_EXPECT_TASK,ExpectTask}| EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%宝宝同心值
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_CHILD_HEART, _Id,_Num, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_CHILD_HEART,NowNum} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%战力任务
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_COMBAT, _Id,_Num, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_COMBAT,NowNum} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%任意主动技能升级次
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_ACTIVE_SKILL_LV_TIMES, _Id,_Num, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_ACTIVE_SKILL_LV_TIMES,NowNum} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%指定商定购买技能书
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_SOME_SHOP_BUY_BOOK, ShopId,NeedNum, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_SOME_SHOP_BUY_BOOK,ShopId,NowNum,NeedNum} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%任意商定购买技能书
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_ANY_SHOP_BUY_BOOK, _Id,NeedNum, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
NewEventList = [{TaskId, ?TASK_CONTENT_ANY_SHOP_BUY_BOOK,NowNum,NeedNum} | EventList],
handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
handle_finish_before_trigger(TaskId, [_|T], TaskArgs, EventList) -> handle_finish_before_trigger(TaskId, T, TaskArgs, EventList).
%% ================================= 完成任务 =================================
%% 自动完成
auto_finish(TaskArgs) when TaskArgs#role_task.type =/= ?TASK_TYPE_SIDE->
TriggerTasks = get_trigger(),
F = fun(RT, Bool) ->
case RT#role_task.state == RT#role_task.end_state of
true ->
case lists:last(RT#role_task.mark) of
[_, 1, ?TASK_CONTENT_END_TALK|_] -> Bool;
_ ->
case finish(RT#role_task.task_id, [], TaskArgs) of
{false, _} -> Bool;
true -> true;
{ok, _} -> true
end
end;
false -> Bool
end
end,
case lists:foldl(F, false, TriggerTasks) of
false -> true;
true -> auto_trigger(TaskArgs) %% 这里是个递归,可能会继续触发完成
end;
auto_finish(_TaskArgs) ->
true.
%% return true | {false, Code} | {ok, 1}
finish(TaskId, ParamList, TaskArgs) ->
case is_finish(TaskId, TaskArgs) of
false ->
#task{type = Type} = get_data(TaskId),
if
ParamList == cost_finish andalso %% 花费完成
(Type == ?TASK_TYPE_DAILY orelse Type == ?TASK_TYPE_GUILD orelse Type == ?TASK_TYPE_SIDE)->
do_normal_finish(TaskId, ParamList, TaskArgs);
true ->
%% ?ERR("error no finish task id:~p~n", [TaskId]),
{false, ?ERRCODE(err300_task_no_finish)}
end;
true ->
do_normal_finish(TaskId, ParamList, TaskArgs)
end.
do_normal_finish(TaskId, ParamList, TaskArgs) ->
#task_args{id = Id} = TaskArgs,
TD = get_data(TaskId),
RT = get_one_trigger(TaskId),
%% 奖励物品
if
TD#task.type == ?TASK_TYPE_DAILY orelse TD#task.type == ?TASK_TYPE_GUILD ->
Items0 = calc_task_type_reward(TD#task.type, RT#role_task.lv),
BaseItems = get_award_item(TD, TaskArgs),
Items = calc_extra_ratio_type_reward(TD#task.type, BaseItems, TaskArgs)++Items0;
TD#task.type == ?TASK_TYPE_MAIN -> %%计算双倍奖励
BaseItems = get_award_item(TD, TaskArgs),
Items = calc_dobule_reward(BaseItems, ParamList);
true ->
Items = get_award_item(TD, TaskArgs)
end,
LogType = get_log_type(TD#task.type),
Produce=#produce{
type=LogType, subtype = TaskId, title=data_language:get(145),
content=data_language:get(146), reward=Items, show_tips=3,
remark = lists:concat(["task_id:", TaskId])
},
lib_goods_api:send_reward_with_mail(Id, Produce, ?MOD_TASK),
{ok, BinData} = pt_300:write(30004, [TaskId, 1, Items]),
lib_server_send:send_to_sid(TaskArgs#task_args.sid, BinData),
%% 判断特殊类型的任务完成
if
TD#task.type == ?TASK_TYPE_DAILY orelse TD#task.type == ?TASK_TYPE_GUILD ->
finish_task_type(TD#task.type, Id, TaskArgs, RT);
true ->
%% 数据库回写
Time = utime:unixtime(),
add_log(Id, TaskId, TD#task.type, RT#role_task.trigger_time, Time, 0),
%% 刷新任务
refresh_active(TaskArgs),
%% 完成任务事件
TalkId = filter_task_talk(RT#role_task.mark),
lib_task_event:async_finish(Id, TaskId, TalkId),
case auto_trigger(TaskArgs) of
true ->
get_my_task_list(TD#task.type, TaskArgs),
%%主线需要补充更新推送
case TD#task.type =:= ?TASK_TYPE_MAIN of
true->
refresh_npc_ico(TaskArgs);
_->
skip
end,
trigger_next_special_task(TD, RT),
true;
_ ->
get_my_task_list(TD#task.type, TaskArgs),
refresh_npc_ico(TaskArgs),
%% check some special task
trigger_next_special_task(TD, RT),
true
end
end.
get_log_type(?TASK_TYPE_DAILY) -> finish_daily_task;
get_log_type(?TASK_TYPE_GUILD) -> finish_guild_task;
get_log_type(_) -> task.
trigger_next_special_task(TD, RT)->
#task{type = Type, kind = Kind, next = NextTaskId} = TD,
case Type == ?TASK_TYPE_SIDE andalso NextTaskId > 0 of
false -> skip;
true ->
#role_task{mark = Mark} = RT,
if
Kind == ?TASK_KIND_STREN ->
lib_player:apply_cast(RT#role_task.role_id, ?APPLY_CAST_STATUS, lib_task_api, auto_stren_equip, []);
Kind == ?TASK_KIND_RUNE_DUN ->
case get_mark_content_type_num(Mark, ?TASK_CONTENT_DUNGEON_RUNE) of
{DunType, DunId} ->
lib_player:apply_cast(RT#role_task.role_id, ?APPLY_CAST_STATUS, lib_task_api, fin_level_dun, [DunType, DunId]);
_ -> skip
end;
Kind == ?TASK_KIND_EXP_DUN ->
case get_mark_content_type_num(Mark, ?TASK_CONTENT_DUNGEON_EXP) of
[] -> skip;
{DunType, Exp} -> lib_player:apply_cast(RT#role_task.role_id, ?APPLY_CAST_STATUS, lib_task_api, fin_dun_exp, [DunType, Exp])
end;
true ->
skip
end
end.
get_mark_content_type_num([[_, _, ?TASK_CONTENT_DUNGEON_RUNE, DunType, _, _, _, _, RuneDunId, _]|_Mark], ?TASK_CONTENT_DUNGEON_RUNE)-> {DunType, RuneDunId};
get_mark_content_type_num([[_, _, ?TASK_CONTENT_DUNGEON_EXP, DunType, _, _, _, _, NowExpNum, _]|_Mark], ?TASK_CONTENT_DUNGEON_EXP) -> {DunType, NowExpNum};
get_mark_content_type_num([_H|Mark], ContentType) -> get_mark_content_type_num(Mark, ContentType);
get_mark_content_type_num([], _ContentType)-> [].
%% 完成悬赏和公会周任务
finish_task_type(TaskType, RoleId, TaskArgs, RT)->
case data_task_lv_dynamic:get_task_type(TaskType) of
#task_type{count = Count, module_id = ModuleId, counter_id = CounterId} ->
% mod_guild:add_growth(RoleId, Figure#figure.guild_id, 1, finish_guild_task, {task_type, TaskType}),
FinishCount = lib_daily:get_count(RoleId, ModuleId, CounterId)+1,
ProduceType = ?IF(TaskType == ?TASK_TYPE_GUILD, finish_guild_task, finish_daily_task),
lib_daily:increment(RoleId, ModuleId, CounterId),
%% 数据库回写
Time = utime:unixtime(),
LogType = ?IF(lists:member(TaskArgs#task_args.figure#figure.lv, ?DAILY_SPECIAL_LV) andalso TaskType == ?TASK_TYPE_DAILY, 1, TaskType),
add_log(TaskArgs#task_args.id, RT#role_task.task_id, LogType, RT#role_task.trigger_time, Time, FinishCount),
%% 完成任务事件
lib_task_event:async_finish(TaskArgs#task_args.id, RT#role_task.task_id,0),
case calc_extra_task_type_reward(RT#role_task.task_id, TaskType, FinishCount, RT#role_task.lv) of
[] -> skip;
Reward ->
Produce=#produce{
type=ProduceType, subtype = RT#role_task.task_id, title=data_language:get(145),
content=data_language:get(146), reward=Reward, show_tips=3,
remark = lists:concat(["task_id:", RT#role_task.task_id])
},
lib_goods_api:send_reward_with_mail(TaskArgs#task_args.id, Produce, ?MOD_TASK)
% lib_goods_api:send_reward_by_id(Reward, ProduceType, RT#role_task.task_id, TaskArgs#task_args.id)
end,
TaskType == ?TASK_TYPE_GUILD andalso guild_run_assist:check_run_assist_trigger(TaskArgs#task_args.id),
if
FinishCount >= Count ->
%% ?ERR("finish task type:~p~n FinishCount:~p~n", [TaskType, FinishCount]),
get_my_task_list(TaskType, TaskArgs),
refresh_npc_ico(TaskArgs),
if
TaskType == ?TASK_TYPE_DAILY -> {ok, ?ERRCODE(err300_daily_task_finished)};
true -> {ok, ?ERRCODE(err300_guild_task_finished)}
end;
true ->
lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, finish_task_type_after, [TaskType]),
{ok, ?SUCCESS}
% trigger_type_task(TaskType, TaskArgs)
end;
_R ->
?ERR("error task type:~p~n _R:~p~n", [TaskType, _R]),
{false, ?FAIL}
end.
finish_task_type_after(PS, ?TASK_TYPE_DAILY) ->
TaskArgs = lib_task_api:ps2task_args(PS),
case get_task_bag_id_list_type(?TASK_TYPE_DAILY) of
[] ->
{_, Code} = trigger_type_task(?TASK_TYPE_DAILY, TaskArgs),
{ok, Bin} = pt_300:write(30009, [Code]),
lib_server_send:send_to_uid(TaskArgs#task_args.id, Bin),
PS;
_->
PS
end;
finish_task_type_after(PS, TaskType) ->
TaskArgs = lib_task_api:ps2task_args(PS),
{_, Code} = trigger_type_task(TaskType, TaskArgs),
{ok, Bin} = pt_300:write(30009, [Code]),
lib_server_send:send_to_uid(TaskArgs#task_args.id, Bin),
PS.
%% 检查扣除物品
%% check_task_cost_goods(TD, RT, ParamList, TaskArgs) ->
%% #task_args{id = Id, gs_dict = GsDict} = TaskArgs,
%% %% 删除回收物品
%% if
%% TD#task.end_item == [] -> ok;
%% ParamList == cost_finish -> ok; %% 特殊任务消耗直接完成不需要扣除物品
%% true ->
%% case get_task_cost_goods(TD, RT) of
%% [] -> ok;
%% [{GoodsId, Num}|_] ->
%% case data_goods_type:get(GoodsId) of
%% #ets_goods_type{bag_location = BagLocation} ->
%% GoodsList = lib_goods_util:get_type_goods_list(Id, GoodsId, BagLocation, GsDict),
%% TotalNum = lib_goods_util:get_goods_totalnum(GoodsList),
%% if
%% TotalNum >= Num ->
%% lib_player:apply_cast(Id, ?APPLY_CAST_STATUS, lib_goods_api, goods_delete_type_list, [[{GoodsId, Num}], finish_task]),
%% ok;
%% true ->
%% {false, ?ERRCODE(goods_not_enough)}
%% end;
%% _ ->
%% {false, ?ERRCODE(err150_no_goods)}
%% end
%% end
%% end.
%% 根据任务内容去扣除物品
%% get_task_cost_goods(TD, RT) ->
%% if
%% TD#task.type == ?TASK_TYPE_DAILY orelse TD#task.type == ?TASK_TYPE_GUILD ->
%% #role_task{mark = Mark, kind = _Kind} = RT,
%% case lists:keyfind(?TASK_CONTENT_ITEM, 3, Mark) of
%% false -> [];
%% {_State, _, _CType, Id, Num, _SceneId, _X, _Y, _Num, _FindPath} ->
%% [{Id, Num}]
%% end;
%% true ->
%% TD#task.end_item
%% end.
%% 经验双倍奖励
calc_dobule_reward(BaseItems, [{double_type, _}|_T]) ->
lists:foldl(
fun ({?TYPE_EXP, GoodsId, Num}, AccList) -> %%经验双倍奖励
[{?TYPE_EXP, GoodsId, Num * 2} | AccList];
({_TypeId, _GoodsId, _Num} = Info, AccList) ->
[Info| AccList];
(_, AccList) -> AccList
end,
[],
BaseItems
);
calc_dobule_reward(BaseItems, _ParamList) -> BaseItems.
%% 赏金任务
calc_task_type_reward(?TASK_TYPE_DAILY, Lv)->
ExpValue0 = data_exp_base:get(Lv),
LvExtra = data_award_exp:get_exp_extra(?MOD_TASK,1,Lv),
[{?TYPE_EXP, ?GOODS_ID_EXP, round(ExpValue0*LvExtra/10000)}];
%% 公会周任务
calc_task_type_reward(?TASK_TYPE_GUILD, Lv) ->
ExpValue0 = data_exp_base:get(Lv),
LvExtra = data_award_exp:get_exp_extra(?MOD_TASK,2,Lv),
[{?TYPE_EXP, ?GOODS_ID_EXP, round(ExpValue0*LvExtra/10000)}];
calc_task_type_reward(_, _) -> [].
%% 计算赏金和公会周任务额外奖励
calc_extra_task_type_reward(TaskId, _TaskType, FinishCount, Lv) ->
case FinishCount rem 5 of %% 每十次一个
0 when FinishCount /= 0->
case data_task_lv_dynamic:get_type_task_dynamic(TaskId, Lv) of
#task_lv_dynamic_content{extra_reward = ExtraReward} ->
case lists:keyfind(FinishCount, 1, ExtraReward) of
{_, Rewards} when is_list(Rewards)-> Rewards;
_ -> []
end;
_ -> []
end;
_ -> []
end.
%% 计算公会任务的加成奖励
calc_extra_ratio_type_reward(?TASK_TYPE_GUILD, Items, _TaskArgs) ->
Rewards = lib_goods_api:make_reward_unique(Items),
Rewards;
calc_extra_ratio_type_reward(?TASK_TYPE_DAILY, Items, TaskArgs) ->
Rewards = lib_goods_api:make_reward_unique(Items),
#task_args{figure = #figure{vip_type = _VipType, vip = _VipLv}} = TaskArgs,
% VipRatio = lib_vip:get_vip_privilege(VipType, VipLv, ?MOD_TASK, 3),
VipRatio = 0,
Fun = fun
({?TYPE_EXP, GoodTypeId, Num})->
{?TYPE_EXP, GoodTypeId, trunc(Num * (10000 + VipRatio) / 10000 )};
(Element) -> Element
end,
[Fun(Item) || Item <- Rewards];
calc_extra_ratio_type_reward(_, Items, _) -> Items.
%% 放弃任务
abnegate(TaskId, TaskArgs) ->
case get_one_trigger(TaskId) of
false -> Code = 0;
_RT ->
%% 删除缓存
delete_task_bag_list(TaskId),
%% 删除数据库
del_trigger_from_sql(TaskArgs#task_args.id, TaskId),
%% 刷新
refresh_active(TaskArgs),
refresh_npc_ico(TaskArgs),
Code = 1
end,
{ok, BinData} = pt_300:write(30005, [Code]),
lib_server_send:send_to_sid(TaskArgs#task_args.sid, BinData).
%% 有部分任务内容在触发的时候可能就完成了
%% preact_finish(Rid) ->
%% lists:member(true, [preact_finish(RT, Rid) || RT <- get_task_bag_id_list()]).
%% preact_finish(TaskId, Rid) when is_integer(TaskId) ->
%% RT = get_one_trigger(TaskId),
%% case RT of
%% false -> skip;
%% _ -> preact_finish(RT, Rid)
%% end;
%% preact_finish(RT, Rid) ->
%% lists:member(true, [preact_finish_check([State, Fin | T], Rid) || [State, Fin | T] <- RT#role_task.mark, State =:= RT#role_task.state, Fin =:= 0]).
%% %% 装备武器
%% preact_finish_check([_, 0, equip, _ItemId | _], PS) when is_record(PS, player_status)->
%% false;
%% %% 加入帮派
%% preact_finish_check([_, 0, join_guild | _], PS) when is_record(PS, player_status)->
%% false;
%% %% 购买武器
%% preact_finish_check([_, 0, buy_equip, _ItemId | _], _PS) when is_record(_PS, player_status)->
%% skip;
%% %% 学习技能
%% preact_finish_check([_, 0, learn_skill, _SkillId | _], PS) when is_record(PS, player_status)->
%% false;
%% %% 收集物品
%% preact_finish_check([_, 0, item, ItemId, _, NowNum | _], PS) when is_record(PS, player_status) ->
%% Dict = lib_goods_dict:get_player_dict(PS),
%% Num = lib_goods_util:get_task_goods_num(PS#player_status.id, ItemId, Dict),
%% case Num > NowNum of
%% false -> false;
%% true -> action(PS#player_status.id, item, [[{ItemId, Num}]])
%% end;
%% preact_finish_check(_, _) ->
%% false.
%% 检测任务是否完成
is_finish(TaskId, TaskArgs) when is_integer(TaskId) ->
case get_one_trigger(TaskId) of
false -> false;
RT ->
IsFinish = is_finish(RT, TaskArgs),
% ?PRINT("####### is_finish:~p~n", [{TaskArgs#task_args.id, TaskArgs#task_args.figure#figure.lv, TaskArgs#task_args.source, TaskId, IsFinish, lib_robot:is_robot(TaskArgs)}]),
%% 注: 给机器人放行逻辑
case {IsFinish, lib_robot:is_robot(TaskArgs)} of
{false, true} -> true;
_ -> IsFinish
end
end;
is_finish(RT, TaskArgs) when is_record(RT, role_task) ->
is_finish_mark(RT#role_task.mark, TaskArgs);
is_finish(Mark, TaskArgs) when is_list(Mark) ->
is_finish_mark(Mark, TaskArgs).
is_finish_mark([], _) -> true;
is_finish_mark([[_, 1|_] | T], TaskArgs) -> is_finish_mark(T, TaskArgs);
is_finish_mark([MK|_T], _TaskArgs) when is_list(MK) -> false;
is_finish_mark([MK|_T], _TaskArgs) -> ?ERR("error task mark:~p~n", [MK]), false.
%% ================================= 任务进度更新 =================================
%% 批量刷新任务过程
action_more(EventList) ->
[action(TaskId, Rid, Event, ParamList) || {TaskId, Event, ParamList, Rid} <- EventList].
%% 已接所有任务更新判断
action(Rid, Event, ParamList) ->
case get_task_bag_id_list() of
[] -> false;
RTL ->
Result = [action_one(RT, Rid, Event, ParamList)|| RT<- RTL],
lists:member(true, Result)
end.
%% 单个任务更新判断
action(TaskId, Rid, Event, ParamList)->
case get_one_trigger(TaskId) of
false -> false;
RT -> action_one(RT, Rid, Event, ParamList)
end.
%% 触发任务
%% 如果是减少:
%% 判断:阶段:后退,保持,前进;
%% 变成没有完成状态
action_one(RT, Rid, Event, ParamList) ->
NowTime = utime:unixtime(),
#role_task{task_id = TaskId, type = TaskType, trigger_time = TriggerTime} = RT,
if
TaskType == ?TASK_TYPE_CHAPTER ->
LimitTime = ?IF(TaskId == 101 orelse TaskId == 102, ?LIMIT_TIME1, ?LIMIT_TIME2);
true -> LimitTime = 0
end,
if
TaskType == ?TASK_TYPE_CHAPTER andalso NowTime > TriggerTime + LimitTime -> %% 限时章节任务,大于限时后不做触发
false;
true ->
F = fun(MarkItem, Update) ->
{NewMarkItem, NewUpdate} = content(MarkItem, RT#role_task.state, Event, ParamList),
case NewUpdate of
true -> {NewMarkItem, true};
false -> {NewMarkItem, Update}
end
end,
{NewMark, UpdateAble} = lists:mapfoldl(F, false, RT#role_task.mark),
case UpdateAble of
false ->
false;
true ->
NoFinishState = [EachState || [EachState, 0|_ ] <- NewMark],
if
NoFinishState == [] -> NewState = RT#role_task.end_state;
true -> NewState = lists:min(NoFinishState)
end,
%% 更新任务记录和任务状态
%% 更新数据,但是不更新步骤状态,先缓存,下线的时候再记录数据库
NewRT = if
RT#role_task.type == ?TASK_TYPE_TURN -> %% 转生任务比较难,默认保存数据
upd_trigger(RT#role_task.role_id, RT#role_task.task_id, NewState, NewMark),
RT#role_task{write_db = 0, state = NewState, mark = NewMark};
RT#role_task.state == NewState ->
RT#role_task{write_db = 1, mark = NewMark};
true ->
upd_trigger(RT#role_task.role_id, RT#role_task.task_id, NewState, NewMark),
RT#role_task{write_db = 0, state = NewState, mark = NewMark}
end,
put_task_bag_list(NewRT),
?IF(NewState == RT#role_task.state, ok, refresh_npc_ico(Rid)),
% TEST
% Ticket = config:get_ticket(),
% case Ticket =:= ?INTERNAL_TICKET of
% true -> auto_finish_task(Rid, RT#role_task.task_id);
% false ->skip
% end,
case NewState == RT#role_task.end_state of
true ->
case lists:last(NewMark) of
[_, 1, ?TASK_CONTENT_END_TALK|_] ->
notify_client_new_mark(RT#role_task.task_id, Rid, NewState, NewMark);
_R when TaskType =:= ?TASK_TYPE_NUCLEON ->
notify_client_new_state_mark(RT#role_task.task_id, Rid, NewState, NewMark);
_R when TaskType =:= ?TASK_TYPE_FOUR ->
notify_client_new_state_mark(RT#role_task.task_id, Rid, NewState, NewMark);
_R when TaskType =:= ?TASK_TYPE_DAILY ->
notify_client_new_state_mark(RT#role_task.task_id, Rid, NewState, NewMark);
_R when TaskType =:= ?TASK_TYPE_GUILD ->
notify_client_new_state_mark(RT#role_task.task_id, Rid, NewState, NewMark);
_R when TaskType =/= ?TASK_TYPE_SIDE ->
auto_finish_task(Rid, RT#role_task.task_id);
_R ->
notify_client_new_state_mark(RT#role_task.task_id, Rid, NewState, NewMark)
end,
%lib_player:apply_cast(RT#role_task.role_id, ?APPLY_CAST_STATUS, ta_agent_fire, task_completed,
% [NowTime, [RT#role_task.task_id, 2, NowTime - TriggerTime]]),
true;
_ ->
notify_client_new_mark(RT#role_task.task_id, Rid, NewState, NewMark),
true
end
end
end.
%% 通知客户端刷新任务栏
notify_client_new_mark(TaskId, Rid, NowState, Mark) ->
{WitchState, NeedNum, NowNum} = get_mon_or_goods_nums(Mark),
F = fun([EState|_]) -> EState == NowState end,
{ok, BinData} = pt_300:write(30001, [TaskId, lists:filter(F, Mark), WitchState, NeedNum, NowNum]),
lib_server_send:send_to_uid(Rid, BinData).
%% 通知客户端刷新任务已完成状态
notify_client_new_state_mark(TaskId, Rid, _NowState, Mark) ->
{WitchState, NeedNum, NowNum} = get_mon_or_goods_nums(Mark),
F = fun([_, EState|_T]) -> EState >0 end,
{ok, BinData} = pt_300:write(30001, [TaskId, lists:filter(F, Mark), WitchState, NeedNum, NowNum]),
lib_server_send:send_to_uid(Rid, BinData).
get_mon_or_goods_nums([]) -> {0, 0, 0};
get_mon_or_goods_nums([H|Mark])->
case H of
[State, _, ContentType, Id, NeedNum, _, _, _, NowNum, _] when
ContentType == ?TASK_CONTENT_KILL;
ContentType == ?TASK_CONTENT_DUNGEON;
ContentType == ?TASK_CONTENT_ITEM;
ContentType == ?TASK_CONTENT_COLLECT;
ContentType == ?TASK_CONTENT_GOODS_COMPOSE;
ContentType == ?TASK_CONTENT_DAY_ACTIVITY;
ContentType == ?TASK_CONTENT_STREN;
ContentType == ?TASK_CONTENT_ARENA_TIMES;
ContentType == ?TASK_CONTENT_COMBAT ->
if
ContentType == ?TASK_CONTENT_STREN ->
{State, Id, NowNum};
NeedNum == 0 andalso NowNum == 0 ->
get_mon_or_goods_nums(Mark);
true ->
{State, NeedNum, NowNum}
end;
_ ->
get_mon_or_goods_nums(Mark)
end.
%% 自动完成任务
auto_finish_task(Player, TaskId) when is_record(Player, player_status) ->
TaskArgs = lib_task_api:ps2task_args(Player),
%% CellNum = lib_goods_api:get_cell_num(Player),
lib_role_task:finish(TaskId, [], TaskArgs),
ok;
auto_finish_task(PlayerId, TaskId) ->
case misc:get_player_process(PlayerId) of
Pid when is_pid(Pid) -> lib_player:apply_cast(Pid, ?APPLY_CAST_STATUS, ?NOT_HAND_OFFLINE, lib_task, auto_finish_task, [TaskId]);
_ -> skip
end.
%% 检查物品是否为任务需要 返回所需要的物品ID列表
can_gain_item() ->
case get_task_bag_id_list() of
[] -> [];
RTL ->
F = fun(RT) ->
%% MarkList = get_phase_unfinish(RT),
[Id || [_, _, ?TASK_CONTENT_ITEM, Id, Num, _SceneId, _X, _Y, NowNum | _T] <- RT#role_task.mark, NowNum =< Num]
end,
List = lists:flatmap(F, RTL),
List
end.
%% after_event(Rid) ->
%% %% TODO 后续事件提前完成检测
%% case preact_finish(Rid) of
%% true -> ok;
%% false ->
%% %% TODO 通知角色数据更新
%% refresh_npc_ico(Rid),
%% {ok, BinData} = pt_300:write(30006, []),
%% lib_server_send:send_to_uid(Rid, BinData)
%% end.
%% 兼容可以从完成状态变成没有完成状态
%% 到达某个位置
content([State, 0, ?TASK_CONTENT_ENTER_SCENE, Id, Num, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_ENTER_SCENE, {PlayerScene, PlayerX, PlayerY}) ->
case Scene == PlayerScene andalso abs(X - PlayerX) < 300 andalso abs(Y - PlayerY) < 300 of
true -> {[State, 1, ?TASK_CONTENT_ENTER_SCENE, Id, Num, Scene, X, Y, NowNum, PathFind], true};
false -> {[State, 0, ?TASK_CONTENT_ENTER_SCENE, Id, Num, Scene, X, Y, NowNum, PathFind], false}
end;
%% 装备套装中id是 X代, NeedNum是Y件, EqStrenList = [{代,品质,件数}]
content([State, 0, ?TASK_CONTENT_EQUIP_SUIT, Series, NeedNum, Color, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_EQUIP_SUIT, {id_num_list, SCNList}) ->
case check_equip_suit_con(SCNList, Series, Color, NeedNum, 0) of
{false, NowNum} ->
{[State, 0, ?TASK_CONTENT_EQUIP_SUIT, Series, NeedNum, Color, X, Y, NowNum, PathFind], false};
{false, Count} ->
{[State, 0, ?TASK_CONTENT_EQUIP_SUIT, Series, NeedNum, Color, X, Y, Count, PathFind], true};
{true, Count}->
{[State, 1, ?TASK_CONTENT_EQUIP_SUIT, Series, NeedNum, Color, X, Y, Count, PathFind], true}
end;
%% 装备强化中id是x级, NeedNum是y件, EqStrenList = [{lv, 件数}]
content([State, 0, ?TASK_CONTENT_STREN, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_STREN, {id_num_list, EqStrenList}) ->
case check_equip_num_con(EqStrenList, Id, NeedNum, 0) of
{false, NowNum} ->
{[State, 0, ?TASK_CONTENT_STREN, Id, NeedNum, Scene, X, Y, NowNum, PathFind], false};
{false, Count} ->
{[State, 0, ?TASK_CONTENT_STREN, Id, NeedNum, Scene, X, Y, Count, PathFind], true};
{true, Count}->
{[State, 1, ?TASK_CONTENT_STREN, Id, NeedNum, Scene, X, Y, Count, PathFind], true}
end;
%% 装备强化中id是x级, NeedNum是y件, EqStrenList = [{lv, 件数}]
content([State, 0, ?TASK_CONTENT_EMPOWER, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_EMPOWER, {id_num_list, EqStrenList}) ->
case check_equip_num_con(EqStrenList, Id, NeedNum, 0) of
{false, NowNum} ->
{[State, 0, ?TASK_CONTENT_EMPOWER, Id, NeedNum, Scene, X, Y, NowNum, PathFind], false};
{false, Count} ->
{[State, 0, ?TASK_CONTENT_EMPOWER, Id, NeedNum, Scene, X, Y, Count, PathFind], true};
{true, Count}->
{[State, 1, ?TASK_CONTENT_EMPOWER, Id, NeedNum, Scene, X, Y, Count, PathFind], true}
end;
%% 单次发条密室副本中获得xxx经验
content([State, 0, ?TASK_CONTENT_DUNGEON_EXP, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_DUNGEON_EXP, {num, Id, Num}) ->
%% 密室副本id是副本类型, num是所需要的经验
case Num >= NeedNum of
true -> {[State, 1, ?TASK_CONTENT_DUNGEON_EXP, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
_ -> {[State, 0, ?TASK_CONTENT_DUNGEON_EXP, Id, NeedNum, Scene, X, Y, NowNum, PathFind], false}
end;
content([State,0,?TASK_CONTENT_DUN_WAVE,Id,NeedNum,Scene,X,Y,NowNum, PathFind],State,?TASK_CONTENT_DUN_WAVE,{num, Id, Num})->
%%Num是波数
case Num >= NeedNum of
true -> {[State, 1, ?TASK_CONTENT_DUN_WAVE, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
_ -> {[State, 0, ?TASK_CONTENT_DUN_WAVE, Id, NeedNum, Scene, X, Y, max(NowNum,Num), PathFind], true}
end;
%% 符文之塔的触发
content([State, _Finish, ?TASK_CONTENT_DUNGEON_RUNE, DunType, DId, Scene, X, Y, Id, PathFind], _State, ?TASK_CONTENT_DUNGEON_RUNE, {id, DunType, DunId}) ->
case DunId >= DId of
true ->
if
_Finish == 1 ->
{[State, 1, ?TASK_CONTENT_DUNGEON_RUNE, DunType, DId, Scene, X, Y, DunId, PathFind], false};
true ->
{[State, 1, ?TASK_CONTENT_DUNGEON_RUNE, DunType, DId, Scene, X, Y, DunId, PathFind], true}
end;
_ ->
{[State, 0, ?TASK_CONTENT_DUNGEON_RUNE, DunType, DId, Scene, X, Y, Id, PathFind], false}
end;
%% 符文之塔的触发
%% content([ContentState, 1, ?TASK_CONTENT_DUNGEON_RUNE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], _FState, ?TASK_CONTENT_DUNGEON_RUNE, {id, DunId}) ->
%% case DunId >= Id of
%% true -> {[ContentState, 1, ?TASK_CONTENT_DUNGEON_RUNE, Id, NeedNum, Scene, X, Y, DunId, PathFind], false};
%% _ -> {[ContentState, 1, ?TASK_CONTENT_DUNGEON_RUNE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], false}
%% end;
%% 公会回收装备(提交x阶y品质及以上品质装备完成任务(id=x阶,NeedNum = y品质)
content([State, 0, ?TASK_CONTENT_GUILD_EQ_RECYCLE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_GUILD_EQ_RECYCLE, {num, Stage, Color}) ->
case Stage >= Id andalso Color >= NeedNum of
true -> {[State, 1, ?TASK_CONTENT_GUILD_EQ_RECYCLE, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
_ -> {[State, 0, ?TASK_CONTENT_GUILD_EQ_RECYCLE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], false}
end;
%% 吞噬装备(吞噬x阶y品质及以上品质装备完成任务(id=x阶,NeedNum = y品质)
content([State, 0, ?TASK_CONTENT_DEVOUR, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_DEVOUR, {num, Stage, Color}) ->
case Stage >= Id andalso Color >= NeedNum of
true -> {[State, 1, ?TASK_CONTENT_DEVOUR, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
_ -> {[State, 0, ?TASK_CONTENT_DEVOUR, Id, NeedNum, Scene, X, Y, NowNum, PathFind], false}
end;
%% 装备进化
content([State, 0, ?TASK_CONTENT_ERISE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_ERISE, {num, Num}) ->
if
Num >= NeedNum ->
{[State, 1, ?TASK_CONTENT_ERISE, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
Num > NowNum ->
{[State, 0, ?TASK_CONTENT_ERISE, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
true ->
{[State, 0, ?TASK_CONTENT_ERISE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], true}
end;
%% 竞技场
content([State, 0, ?TASK_CONTENT_ARENA_TIMES, Id, NeedNum, Scene, X, Y, _NowNum, PathFind], State, ?TASK_CONTENT_ARENA_TIMES, {num, Num}) ->
if
Num >= NeedNum ->
{[State, 1, ?TASK_CONTENT_ARENA_TIMES, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
true->
{[State, 0, ?TASK_CONTENT_ARENA_TIMES, Id, NeedNum, Scene, X, Y, Num, PathFind], true}
end;
%% 战魂升级
content([State, 0, ?TASK_CONTENT_WAR_SOUL_LV, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_WAR_SOUL_LV, {num, Num}) ->
if
Num >= NeedNum ->
{[State, 1, ?TASK_CONTENT_WAR_SOUL_LV, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
Num > NowNum ->
{[State, 0, ?TASK_CONTENT_WAR_SOUL_LV, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
true ->
{[State, 0, ?TASK_CONTENT_WAR_SOUL_LV, Id, NeedNum, Scene, X, Y, NowNum, PathFind], true}
end;
%% 羁绊缔结就行
content([State, 0, ?TASK_CONTENT_MATE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_MATE, {num, Num}) ->
if
Num >= NeedNum ->
{[State, 1, ?TASK_CONTENT_MATE, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
Num > NowNum ->
{[State, 0, ?TASK_CONTENT_MATE, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
true ->
{[State, 0, ?TASK_CONTENT_MATE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], true}
end;
%% 完成次数就行
content([State, 0, ?TASK_CONTENT_DAY_ACTIVITY, Id, NeedNum, Scene, X, Y, _NowNum, PathFind], State, ?TASK_CONTENT_DAY_ACTIVITY, {num, Num}) ->
if
Num >= NeedNum ->
{[State, 1, ?TASK_CONTENT_DAY_ACTIVITY, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
true->
{[State, 0, ?TASK_CONTENT_DAY_ACTIVITY, Id, NeedNum, Scene, X, Y, Num, PathFind], true}
end;
%% 完成亲密度就行
content([State, 0, ?TASK_CONTENT_FRIEND_EXP, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_FRIEND_EXP, {num, Num}) ->
if
Num >= NeedNum ->
{[State, 1, ?TASK_CONTENT_FRIEND_EXP, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
Num > NowNum ->
{[State, 0, ?TASK_CONTENT_FRIEND_EXP, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
true ->
{[State, 0, ?TASK_CONTENT_FRIEND_EXP, Id, NeedNum, Scene, X, Y, NowNum, PathFind], true}
end;
%% 完成同心值就行
content([State, 0, ?TASK_CONTENT_CHILD_HEART, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_CHILD_HEART, {num, Num}) ->
if
Num >= NeedNum ->
{[State, 1, ?TASK_CONTENT_CHILD_HEART, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
Num > NowNum ->
{[State, 0, ?TASK_CONTENT_CHILD_HEART, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
true ->
{[State, 0, ?TASK_CONTENT_CHILD_HEART, Id, NeedNum, Scene, X, Y, NowNum, PathFind], true}
end;
%战力任务
content([State, 0, ?TASK_CONTENT_COMBAT, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_COMBAT, {num, Num}) ->
if
Num >= NeedNum ->
{[State, 1, ?TASK_CONTENT_COMBAT, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
Num > NowNum ->
{[State, 0, ?TASK_CONTENT_COMBAT, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
true ->
{[State, 0, ?TASK_CONTENT_COMBAT, Id, NeedNum, Scene, X, Y, NowNum, PathFind], true}
end;
%%选项对话任务
content([State, 0, ?TASK_CONTENT_CHOOSE_TALK, NeedId, NeedNum, Scene, X, Y, _NowNum, PathFind], _, ?TASK_CONTENT_CHOOSE_TALK, {num,Id,TalkId}) ->
NewNpc = lib_role_task:exchange_npc(NeedId),
case NewNpc =:= Id of
true->
{[State, 1, ?TASK_CONTENT_CHOOSE_TALK, Id, NeedNum, Scene, X, Y, TalkId, PathFind], true};
_->
{[State, 0, ?TASK_CONTENT_CHOOSE_TALK, Id, NeedNum, Scene, X, Y, _NowNum, PathFind], false}
end;
%% 任务对话
content([State, 0, ?TASK_CONTENT_TALK, NeedId, Num, Scene, X, Y, _NowNum, PathFind], State, ?TASK_CONTENT_TALK, {id, Id}) ->
NewNpc = lib_role_task:exchange_npc(NeedId),
case NewNpc =:= NeedId of
true->%%无变化
case NewNpc =:= Id of
true->
{[State, 1, ?TASK_CONTENT_TALK, Id, Num, Scene, X, Y, Num, PathFind], true};
_->
{[State, 0, ?TASK_CONTENT_TALK, Id, Num, Scene, X, Y, _NowNum, PathFind], false}
end;
_->
case NewNpc =:= Id of
true->
{[State, 1, ?TASK_CONTENT_TALK, NewNpc, Num, Scene, X, Y, Num, PathFind], true};
_->
{[State, 0, ?TASK_CONTENT_TALK, NewNpc, Num, Scene, X, Y, _NowNum, PathFind], false}
end
end;
%% 个人幻魔处理 数据初始
content([State, 0, ?TASK_CONTENT_DUNGEON_TYPE, ?DUNGEON_TYPE_PER_BOSS, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_DUNGEON_TYPE, {init, ?DUNGEON_TYPE_PER_BOSS, Num}) ->
if Num >= NeedNum ->
{[State, 1, ?TASK_CONTENT_DUNGEON_TYPE, ?DUNGEON_TYPE_PER_BOSS, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
Num>NowNum->
{[State, 0, ?TASK_CONTENT_DUNGEON_TYPE, ?DUNGEON_TYPE_PER_BOSS, NeedNum, Scene, X, Y, Num, PathFind], true};
true->
{[State, 0, ?TASK_CONTENT_DUNGEON_TYPE, ?DUNGEON_TYPE_PER_BOSS, NeedNum, Scene, X, Y, NowNum, PathFind], false}
end;
%% 次元幻魔处理 数据初始
content([State, 0, ?TASK_CONTENT_KILL_BOSS, ?MON_REWARD_BOSS, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_KILL_BOSS, {init, ?MON_REWARD_BOSS, Num}) ->
if Num >= NeedNum ->
{[State, 1, ?TASK_CONTENT_KILL_BOSS, ?MON_REWARD_BOSS, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
Num>NowNum->
{[State, 0, ?TASK_CONTENT_KILL_BOSS, ?MON_REWARD_BOSS, NeedNum, Scene, X, Y, Num, PathFind], true};
true->
{[State, 0, ?TASK_CONTENT_KILL_BOSS, ?MON_REWARD_BOSS, NeedNum, Scene, X, Y, NowNum, PathFind], false}
end;
%% 进阶 数据初始
content([State, 0, ?TASK_CONTENT_FOSTER_GRADE, Type, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_FOSTER_GRADE, {num, Type, Num}) ->
if Num >= NeedNum ->
{[State, 1, ?TASK_CONTENT_FOSTER_GRADE, Type, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
Num>NowNum->
{[State, 0, ?TASK_CONTENT_FOSTER_GRADE, Type, NeedNum, Scene, X, Y, Num, PathFind], true};
true->
{[State, 0, ?TASK_CONTENT_FOSTER_GRADE, Type, NeedNum, Scene, X, Y, NowNum, PathFind], false}
end;
%%指定对话
content([State, 0, ?TASK_CONTENT_TALK, NeedId, TalkId, Scene, X, Y, _NowNum, PathFind], State, ?TASK_CONTENT_TALK, {id,TalkId,Id}) ->
NewNpc = lib_role_task:exchange_npc(NeedId),
case NewNpc =:= NeedId of
true->%%无变化
case NewNpc =:= Id of
true->
{[State, 1, ?TASK_CONTENT_TALK, Id, TalkId, Scene, X, Y, 1, PathFind], true};
_->
{[State, 0, ?TASK_CONTENT_TALK, Id, TalkId, Scene, X, Y, 1, PathFind], false}
end;
_->
case NewNpc =:= Id of
true->
{[State, 1, ?TASK_CONTENT_TALK, NewNpc, TalkId, Scene, X, Y, 1, PathFind], true};
_->
{[State, 0, ?TASK_CONTENT_TALK, NewNpc, TalkId, Scene, X, Y, 1, PathFind], false}
end
end;
%% 送信任务
content([State, 0, ?TASK_CONTENT_MAILER_RUN, NeedId, NeedNum, Scene, X, Y, _NowNum, PathFind], State, ?TASK_CONTENT_MAILER_RUN, {id,Id}) ->
NewNpc = lib_role_task:exchange_npc(NeedId),
case NewNpc =:= NeedId of
true->%%无变化
case NewNpc =:= Id of
true->
{[State, 1, ?TASK_CONTENT_MAILER_RUN, NewNpc, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
_->
{[State, 0, ?TASK_CONTENT_MAILER_RUN, NewNpc, NeedNum, Scene, X, Y, _NowNum, PathFind], false}
end;
_->
case NewNpc =:= Id of
true->
{[State, 1, ?TASK_CONTENT_MAILER_RUN, NewNpc, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
_->
{[State, 0, ?TASK_CONTENT_MAILER_RUN, NewNpc, NeedNum, Scene, X, Y, _NowNum, PathFind], false}
end
end;
%% 某个特定的id(特定的副本,特定的活动)
content([State, 0, ContentType, Id, Num, Scene, X, Y, _NowNum, PathFind], State, ContentType, {id, Id}) ->
{[State, 1, ContentType, Id, Num, Scene, X, Y, Num, PathFind], true};
%% 完成次数就行
content([State, 0, ContentType, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ContentType, {num, Num}) ->
case NowNum + Num >= NeedNum of
true -> {[State, 1, ContentType, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
_ -> {[State, 0, ContentType, Id, NeedNum, Scene, X, Y, NowNum + Num, PathFind], true}
end;
%% 通用的id和次数
content([State, 0, ContentType, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ContentType, {num, Id, Num}) ->
case NowNum + Num >= NeedNum of
true -> {[State, 1, ContentType, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
_ -> {[State, 0, ContentType, Id, NeedNum, Scene, X, Y, NowNum + Num, PathFind], true}
end;
%% 列表类型id和次数
content([State, 0, ContentType, Id, NeedNum, Scene, X, Y, NowNum, PathFind]=H, _Taskstate, ContentType, {id_num_list, IdNumList}) ->
case lists:keyfind(Id, 1, IdNumList) of
false -> {H, false};
{Id, Num} ->
case NowNum + Num >= NeedNum of
true -> {[State, 1, ContentType, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
_ -> {[State, 0, ContentType, Id, NeedNum, Scene, X, Y, NowNum + Num, PathFind], true}
end
end;
%% 收集物品减少触发状态变成
content([State, _Finsh, ?TASK_CONTENT_ITEM, Id, NeedNum, Scene, X, Y, _NowNum, PathFind]=H, _TaskState, ?TASK_CONTENT_ITEM, {reduce_id_num_list, IdNumList}) ->
case lists:keyfind(Id, 1, IdNumList) of
false -> {H, false};
{Id, _Num, GAllNum} ->
NewNowNum = min(GAllNum, NeedNum),
case NewNowNum >= NeedNum of
true -> {[State, 1, ?TASK_CONTENT_ITEM, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
_ -> {[State, 0, ?TASK_CONTENT_ITEM, Id, NeedNum, Scene, X, Y, NewNowNum, PathFind], true}
end
end;
%% 完成次数就行
content([State, 0, ContentType, Id, NeedNum, Scene, X, Y, _NowNum, PathFind], State, ContentType, {value, Num}) ->
case Num >= NeedNum of
true -> {[State, 1, ContentType, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
_ -> {[State, 0, ContentType, Id, NeedNum, Scene, X, Y, Num, PathFind], true}
end;
%% 通用的id和次数
content([State, 0, ContentType, Id, NeedNum, Scene, X, Y, _NowNum, PathFind], State, ContentType, {value, Id, Num}) ->
case Num >= NeedNum of
true -> {[State, 1, ContentType, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
_ -> {[State, 0, ContentType, Id, NeedNum, Scene, X, Y, Num, PathFind], true}
end;
%% 容错
content(MarkItem, _State, _Event, _Args) ->
{MarkItem, false}.
%% 检查装备的件数和强化数
check_equip_num_con([], _StrenNum, Num, Count)->
{Count >= Num, Count};
check_equip_num_con(_EqStrenList, _StrenNum, Num, Num)->
{true, Num};
check_equip_num_con([{StrNum, N}|EqStrenList], StrenNum, Num, Count)->
if
StrNum >= StrenNum andalso N >= Num ->
{true, Num};
StrNum >= StrenNum ->
check_equip_num_con(EqStrenList, StrenNum, Num, Count+N);
true ->
check_equip_num_con(EqStrenList, StrenNum, Num, Count)
end.
%%检查套件中装备品质数
check_equip_suit_con([], _Series, _Color, NeedNum, Count)->
{Count >= NeedNum, Count};
check_equip_suit_con(_SCNList, _Series, _Color, NeedNum, Count) when Count>=NeedNum->
{true, NeedNum};
check_equip_suit_con([{S,C,N}|SCNList], Series, Color, NeedNum, Count)->
if
S =:= Series andalso C>=Color ->
check_equip_suit_con(SCNList,Series,Color,NeedNum,Count+N);
true->
check_equip_suit_con(SCNList,Series,Color,NeedNum,Count)
end.
% %% 任务失败,算完成了任务一次(超时或者放弃)
% task_fail(PS, RT) ->
% add_log(PS#player_status.id, RT#role_task.task_id, RT#role_task.type, RT#role_task.trigger_time, utime:unixtime(), 0),
% refresh_active(PS).
%% ------------------------------
%% 自动完成任务
%% ------------------------------
%% 检测任务是否完成
% auto_finish(TaskId, Id) when is_integer(TaskId) ->
% case get_one_trigger(TaskId) of
% false ->
% Msg = data_task_text:get_auto_finish(1),
% {ok, BinData} = pt_300:write(30004, [0, Msg, []]),
% lib_server_send:send_to_uid(Id, BinData),
% false;
% RT ->
% case RT#role_task.state > 0 of
% true ->
% Msg = data_task_text:get_auto_finish(2),
% {ok, BinData} = pt_300:write(30004, [0, Msg, []]),
% lib_server_send:send_to_uid(Id, BinData),
% false;
% false ->
% auto_finish(RT, Id)
% end
% end;
% auto_finish(RT, Id) when is_record(RT, role_task) ->
% NewMark = auto_finish_mark(RT#role_task.mark, []),
% put_task_bag_list(RT#role_task{mark = NewMark, state=RT#role_task.state + 1}),
% %% 通知客户端刷新任务栏
% refresh_npc_ico(Id),
% TipList = get_tip(trigger, RT#role_task.task_id, Id),
% {ok, BinData} = pt_302:write(30200, [RT#role_task.task_id, TipList]),
% lib_server_send:send_to_uid(Id, BinData),
% true.
auto_finish_mark([], NewMark) ->
NewMark;
auto_finish_mark([MarkItem | T], NewMark) ->
auto_finish_mark(T, NewMark ++ [auto_check_content(MarkItem)]).
%% 检测任务内容是否完成
auto_check_content([D1, _Finish, kill, D2, Num, _NowNum]) ->
[D1, 1, kill, D2, Num, Num];
auto_check_content([D1, _Finish, item, D2, Num, _NowNum]) ->
[D1, 1, item, D2, Num, Num];
auto_check_content([D1, _Finish | D2]) ->
[D1, 1 | D2];
auto_check_content(Other) ->
Other.
%% ================================= 进程字段记录 =================================
put_task_log_list(TaskId,TaskInfo) ->
LogIdList = get_task_log_id_list(),
case find_task_log_list(TaskId) of
false ->
put(log_id_list,[TaskId|LogIdList]),
put({log, TaskId}, TaskInfo);
Data ->
C = Data#role_task_log.count + 1,
put({log, TaskId}, TaskInfo#role_task_log{count = C})
end.
find_task_log_list(TaskId) ->
case get({log, TaskId}) of
undefined -> false;
Data -> Data
end.
%% 已经完成任务的ID列表
get_task_log_id_list() ->
case get(log_id_list) of
undefined -> [];
Data -> Data
end.
find_task_log_exits(TaskId) ->
?IF(find_task_log_list(TaskId) == false, false, true).
delete_task_log_list(TaskId) ->
erase({log, TaskId}).
get_task_bag_id_list() ->
get("lib_task_task_bag_id_list").
set_task_bag_list(Data) ->
put("lib_task_task_bag_id_list", Data).
%% 按type类型
get_task_bag_id_list_type(Type)->
L = get_task_bag_id_list(),
[ T || T <- L, T#role_task.type =:= Type].
%% 按TaskId类型
get_task_bag_id_list_task_id(TaskId)->
L = get_task_bag_id_list(),
[ T || T <- L, T#role_task.task_id =:= TaskId].
%% 按kind类型
get_task_bag_id_list_kind(Kind)->
L = get_task_bag_id_list(),
[ T || T <- L, T#role_task.kind =:= Kind].
put_task_bag_list(TaskInfo) ->
%% upd_trigger(TaskInfo#role_task.role_id, TaskInfo#role_task.task_id, TaskInfo#role_task.state, TaskInfo#role_task.mark),
List = lists:keydelete(TaskInfo#role_task.task_id, #role_task.task_id, get_task_bag_id_list()),
put("lib_task_task_bag_id_list", [TaskInfo|List]).
find_task_bag_list(TaskId) ->
lists:keyfind(TaskId, #role_task.task_id, get_task_bag_id_list()).
find_task_bag_exits(TaskId) ->
?IF(find_task_bag_list(TaskId) == false, false, true).
%% 获取任务接取时间
get_trigger_time(TaskId) ->
case find_task_bag_list(TaskId) of
false -> false;
RT -> RT#role_task.trigger_time
end.
delete_task_bag_list(TaskId) ->
put("lib_task_task_bag_id_list", lists:keydelete(TaskId, #role_task.task_id, get_task_bag_id_list())).
get_query_cache_list() ->
get("lib_task_query_cache_list").
set_query_cache_list(Data) ->
put("lib_task_query_cache_list", Data).
%% 按类型
get_query_cache_list_type(Type)->
[ T || T <- get_query_cache_list(), T#task.type =:= Type].
put_query_cache_list(TaskInfo) ->
List = lists:keydelete(TaskInfo#task.id, 2, get_query_cache_list()),
List1 = List ++ [TaskInfo],
put("lib_task_query_cache_list", List1).
find_query_cache_list(TaskId) ->
lists:keyfind(TaskId, 2, get_query_cache_list()).
find_query_cache_exits(TaskId) ->
?IF(find_query_cache_list(TaskId) == false, false, true).
delete_query_cache_list(TaskId) ->
put("lib_task_query_cache_list", lists:keydelete(TaskId, #task.id, get_query_cache_list())).
%% ================================= db op =================================
%% Type:1 2 3 4需要永久保存的,事物执行task 删除和记录日志操作
add_log(Rid, Tid, Type, TriggerTime, FinishTime, Count) ->
%% 删除已触发的任务缓存
delete_task_bag_list(Tid),
%% 记录任务日志缓存
put_task_log_list(Tid,#role_task_log{type = Type}),
%% db操作
F = fun() ->
if
Type =/= ?TASK_TYPE_MAIN -> skip;
true -> db:execute(io_lib:format(<<"update player_state set last_task_id = ~p where id= ~p">>, [Tid, Rid]))
end,
if
Type == ?TASK_TYPE_MAIN; Type == ?TASK_TYPE_SIDE;
Type == ?TASK_TYPE_TURN; Type == ?TASK_TYPE_CHAPTER;
Type == ?TASK_TYPE_NUCLEON; Type == ?TASK_TYPE_FOUR->
db:execute(lists:concat(["insert into `task_log`(`role_id`,`task_id`,`type`,`trigger_time`,`finish_time`)
values(",Rid,",",Tid,",",Type,",",TriggerTime,",",FinishTime,")"]));
true ->
db:execute(lists:concat(["insert into `task_log_clear`(`role_id`, `task_id`, `type`, `trigger_time`, `finish_time`, `count`)
values(",Rid,",",Tid,",",Type,",",TriggerTime,",",FinishTime,",",Count,")"]))
end,
db:execute(lists:concat(["delete from `task_bag` where role_id=", Rid, " and task_id=", Tid]))
end,
db:transaction(F).
%% 删除完成日志
del_log(Rid, Tid, Type) when Type == ?TASK_TYPE_MAIN; Type == ?TASK_TYPE_SIDE;
Type == ?TASK_TYPE_TURN; Type == ?TASK_TYPE_CHAPTER;
Type == ?TASK_TYPE_NUCLEON; Type == ?TASK_TYPE_FOUR ->
db:execute(lists:concat(["delete from `task_log` where role_id=",Rid," and task_id=",Tid]));
del_log(Rid, Tid, _Type) ->
db:execute(lists:concat(["delete from `task_log_clear` where role_id=",Rid," and task_id=",Tid])).
%% 删除完成日志
del_log_type(Type) when Type == ?TASK_TYPE_FOUR ->
db:execute(io_lib:format("delete from `task_log` where `type` = ~p", [Type]));
del_log_type(_Type) ->
ok.
%% 添加触发,新+到任务背包
add_trigger(Rid, Tid, TriggerTime, TaskState, TaskEndState, TaskMark, Type, Kind, RoleLv) ->
put_task_bag_list(#role_task{role_id = Rid, task_id = Tid, trigger_time = TriggerTime, lv = RoleLv,
state=TaskState, type=Type, kind=Kind, end_state=TaskEndState, mark = TaskMark}),
delete_query_cache_list(Tid),
db:execute( io_lib:format(<<"insert into `task_bag`(`role_id`, `task_id`, `trigger_time`, `state`,
`end_state`, `mark`, `type`, `lv`) values(~p,~p,~p,~p,~p,'~s',~p, ~p)">>,
[Rid, Tid, TriggerTime, TaskState, TaskEndState, util:term_to_bitstring(TaskMark), Type, RoleLv])).
%% 更新任务记录器
upd_trigger(Rid, Tid, TaskState, TaskMark) ->
db:execute(io_lib:format(<<"update `task_bag` set state=~p,mark='~s' where role_id=~p and task_id=~p">>, [TaskState, util:term_to_bitstring(TaskMark), Rid, Tid])).
%% 玩家下线更新需要保存数据库的操作
task_offline_up(RoleTaskList)->
F = fun(TaskInfo, Args) ->
case TaskInfo#role_task.write_db =/= 1 of
true->
Args;
_->
[TaskInfo|Args]
end
end,
Tasks = lists:foldl(F, [], RoleTaskList),
DbList = format_task_bag([],Tasks),
Sql = ?SQL_ROLE_TASK_BAG_BATCH,
batch_save(Sql,DbList),
ok.
format_task_bag(DbList,[])->
DbList;
format_task_bag(DbList,[H|T])->
#role_task{
role_id = Rid,
task_id = Tid,
trigger_time = TriggerTime,
lv = RoleLv,
state=TaskState,
type=Type,
end_state=TaskEndState,
mark = TaskMark,
write_db = IsDb
}=H,
case IsDb >= 1 of
true->
Data0 = [Rid, Tid, TriggerTime, TaskState, TaskEndState, util:term_to_bitstring(TaskMark), Type, RoleLv],
Data1 = io_lib:format("(~p,~p,~p,~p,~p,'~ts',~p,~p)", Data0),
format_task_bag([Data1|DbList],T);
_->
format_task_bag(DbList,T)
end.
batch_save(_Sql,[])->
ok;
batch_save(Sql,DbList)->
ArgsString = string:join(DbList, ","),
SqlN = io_lib:format(Sql, [ArgsString]),
db:execute(SqlN),
ok.
%% 删除触发任务
del_trigger_from_sql(Rid, Tid) ->
db:execute(lists:concat(["delete from `task_bag` where role_id=", Rid, " and task_id=", Tid])).
%% 日常任务清理
daily_clear(Clock, DelaySec)->
spawn(fun() -> util:multiserver_delay(DelaySec, lib_task, daily_clear, [Clock]) end),
ok.
%% 每日清理
daily_clear(Clock) ->
case utime:day_of_week() of
1 -> %% 周一4点重置公会周任务
if
Clock == ?TWELVE -> %% 周一0点清理可清理的任务日志和公会任务
skip;
Clock == ?FOUR -> %% 日常支线任务(悬赏任务)(日清理)
del_log_type(?TASK_TYPE_FOUR),
db:execute("TRUNCATE TABLE `task_log_clear`"),
db:execute( io_lib:format("delete from `task_bag` where `type` = ~p", [?TASK_TYPE_GUILD]) ),
db:execute( io_lib:format("delete from `task_bag` where `type` = ~p", [?TASK_TYPE_DAILY]) ),
db:execute( io_lib:format("delete from `task_bag` where `type` = ~p", [?TASK_TYPE_FOUR]) );
true ->
skip
end;
_ ->
if
Clock =/= ?FOUR -> skip;
true -> %% 日常支线任务(悬赏任务)(日清理)
del_log_type(?TASK_TYPE_FOUR),
db:execute("TRUNCATE TABLE `task_log_clear`"),
db:execute( io_lib:format("delete from `task_bag` where `type` = ~p", [?TASK_TYPE_GUILD]) ),
db:execute( io_lib:format("delete from `task_bag` where `type` = ~p", [?TASK_TYPE_DAILY]) ),
db:execute( io_lib:format("delete from `task_bag` where `type` = ~p", [?TASK_TYPE_FOUR]) )
end
end,
case Clock of
?FOUR->
db:execute("delete from `task_log` where `task_id` = 3070002"),
db:execute("delete from `task_bag` where `task_id` = 3070002");
_->
ignore
end,
%% 每个玩家清理
[gen_server:cast(D#ets_online.pid, {'refresh_and_clear_task', Clock}) || D <- ets:tab2list(?ETS_ONLINE)],
?ERR("task_clear_daily ~n", []),
ok.
%% ================================= 特殊的任务类型触发:悬赏任务和公会任务 =================================
%% return {false, ErrorCode} | {ok, ?SUCCESS}
trigger_type_task(TaskType, TaskArgs)->
%% 是否已经接取了同类型任务
case get_task_bag_id_list_type(TaskType) of
[] ->
%% 过滤出响应等级的任务
case filter_task_type_ids(TaskType, TaskArgs) of
[] ->
{false, ?ERRCODE(err300_lv_no_task)};
TD when TaskType =:= ?TASK_TYPE_DAILY-> %%日常不拼接
TaskMark = [content_to_mark(E, TD#task.content, TaskArgs)||E<-TD#task.content],
add_trigger(TaskArgs#task_args.id, TD#task.id, utime:unixtime(), 0, TD#task.state,
TaskMark, TD#task.type, TD#task.kind, TaskArgs#task_args.figure#figure.lv),
get_my_task_list(TaskType, TaskArgs),
refresh_npc_ico(TaskArgs),
{ok, ?SUCCESS};
TD->
%% npc显示
%% TaskArgs1 = do_dynamic_npc(TaskArgs, TD#task.npc_show),
TaskMark = [content_to_mark(E, TD#task.content, TaskArgs)||E<-TD#task.content]
++ case TD#task.end_talk of
0 -> []; %% end_talk = 0 则直接提交任务
_ -> [content_to_mark([TD#task.state, ?TASK_CONTENT_END_TALK, TD#task.end_npc,
TD#task.end_talk, 0, 0, 0, TD#task.finish_pathfind], TaskArgs)]
end,
add_trigger(TaskArgs#task_args.id, TD#task.id, utime:unixtime(), 0, TD#task.state,
TaskMark, TD#task.type, TD#task.kind, TaskArgs#task_args.figure#figure.lv),
get_my_task_list(TaskType, TaskArgs),
refresh_npc_ico(TaskArgs),
{ok, ?SUCCESS}
end;
_R ->
?ERR("error have task type:~p~n _R:~p~n", [TaskType, _R]),
{false, ?ERRCODE(err300_task_trigger)}
end.
%% 过滤类型
filter_task_type_ids(TaskType, TaskArgs)->
ClsState = case czone_api:zone_enter_check_city() of
true when TaskType =:= ?TASK_TYPE_DAILY->
2;
_->
1
end,
case data_task_lv_dynamic:get_type_task_id(TaskType,ClsState,TaskArgs#task_args.figure#figure.lv) of
#task_lv_dynamic_id{task_ids = TaskIds} when TaskIds /= []->
TaskId = get_next_type_task_id(TaskType, TaskIds, TaskArgs#task_args.figure#figure.lv),
case data_task_lv_dynamic:get_type_task_dynamic(TaskId, TaskArgs#task_args.figure#figure.lv) of
#task_lv_dynamic_content{start_npc = StartNpc, end_npc = EndNpc, scene = SceneId,
x = X, y = Y, content_type = ContentType, id = Id, num = NeedNum} ->
case data_task:get(TaskId) of
#task{kind = LastKind} = TD->
put({'last_task_kind_type', TaskType}, LastKind),
format_task_dynamic_content(TD, StartNpc, EndNpc, SceneId, X, Y, ContentType, Id, NeedNum);
_ ->
?ERR("error dynamic task_id :~p~n", [TaskId]),
[]
end;
_ ->
?ERR("error dynamic content :~p~n", [[TaskIds, TaskArgs#task_args.figure#figure.lv]]),
[]
end;
_ ->
?ERR("error dynamic task content :~p~n", [[TaskType, TaskArgs#task_args.figure#figure.lv]]),
[]
end.
get_next_type_task_id(?TASK_TYPE_DAILY = TaskType, TaskIds, RoleLv) ->
case lists:member(RoleLv, ?DAILY_SPECIAL_LV) of
true -> get_special_task_id(TaskType, TaskIds);
false -> do_get_next_type_task_id(TaskType, TaskIds)
end;
get_next_type_task_id(TaskType, TaskIds, _RoleLv) ->
do_get_next_type_task_id(TaskType, TaskIds).
get_special_task_id(?TASK_TYPE_DAILY = TaskType, TaskIds) ->
Fun = fun({_, TaskId}, TmpList) ->
case is_finish_task_id(TaskId) of
true -> TmpList;
false -> [TaskId | TmpList]
end
end,
FilterList = lists:foldr(Fun, [], TaskIds),
case FilterList == [] of
true -> do_get_next_type_task_id(TaskType, TaskIds);
false -> hd(FilterList)
end;
get_special_task_id(TaskType, TaskIds) ->
do_get_next_type_task_id(TaskType, TaskIds).
%%日常非类型过滤
do_get_next_type_task_id(?TASK_TYPE_DAILY, TaskIds)->
{_, TaskId} = util:find_ratio(TaskIds, 1),
TaskId;
% case get({'last_task_kind_type', TaskType}) of
% undefined ->
% {_, TaskId} = util:find_ratio(TaskIds, 1),
% TaskId;
% LastKindType ->
% LessTaskIds = [{Weight, TId} || {Weight, TId} <- TaskIds, TaskInfo <- [data_task:get(TId)], TaskInfo#task.kind =/= LastKindType],
% {_, TaskId} = util:find_ratio(LessTaskIds, 1),
% TaskId
% end.
do_get_next_type_task_id(TaskType, TaskIds)->
case get({'last_task_kind_type', TaskType}) of
undefined ->
{_, TaskId} = util:find_ratio(TaskIds, 1),
TaskId;
LastKindType ->
LessTaskIds = [{Weight, TId} || {Weight, TId} <- TaskIds, TaskInfo <- [data_task:get(TId)], TaskInfo#task.kind =/= LastKindType],
{_, TaskId} = util:find_ratio(LessTaskIds, 1),
TaskId
end.
%% 组装动态任务内容
format_task_dynamic_content(TD, StartNpcId, EndNpcId, SceneId, X, Y, ContentType, Id, NeedNum)->
Content = if
StartNpcId == 0 -> [];
true ->
[[0, ?TASK_CONTENT_TALK, StartNpcId, TD#task.start_talk, 0, 0, 0, 1]]
end,
NewContent = if
ContentType == 0 orelse Id == 0 ->
[];
ContentType == 5 ->
Content;
Content == [] ->
[[0, ContentType, Id, NeedNum, SceneId, X, Y, 1]];
true ->
Content ++ [[1, ContentType, Id, NeedNum, SceneId, X, Y, 1]]
end,
State = length(NewContent),
if
EndNpcId == 0 -> EndTalk = 0;
true -> EndTalk = TD#task.end_talk
end,
TD#task{start_npc = StartNpcId, content = NewContent, end_npc = EndNpcId, state = State, end_talk = EndTalk}.
%% 获取赏金(日常)和公会周任务
get_special_task_reward(TaskId, Type, TaskArgs) ->
RoleId = TaskArgs#task_args.id,
case get_one_trigger(TaskId) of
false -> Goods = [], ExtraReward = [];
RT ->
Goods0 = calc_task_type_reward(Type, RT#role_task.lv),
Goods = get_award_item(data_task:get(TaskId), TaskArgs)++Goods0,
case data_task_lv_dynamic:get_task_type(Type) of
#task_type{module_id = ModuleId, counter_id = CounterId} ->
FinishCount = lib_daily:get_count(RoleId, ModuleId, CounterId)+1,
ExtraReward = calc_extra_task_type_reward(TaskId, Type, FinishCount, RT#role_task.lv);
_ ->
ExtraReward = []
end
end,
lib_server_send:send_to_uid(RoleId, pt_300, 30011, [TaskId, Goods, ExtraReward]).
%% ================================= 任务秘籍 =================================
%% 强制接取某个任务(秘籍使用)
force_trigger(TaskId, TaskArgs) ->
%% 删除缓存
delete_task_bag_list(TaskId),
delete_task_log_list(TaskId),
%% 删除db
TD = get_data(TaskId),
F = fun() ->
del_trigger_from_sql(TaskArgs#task_args.id, TaskId),
del_log(TaskArgs#task_args.id, TaskId, TD#task.type)
end,
db:transaction(F),
%% 刷新
refresh_active(TaskArgs),
TaskArgs1 = do_dynamic_npc(TaskArgs, TD#task.npc_show),
TaskMark = [content_to_mark(E, TaskArgs1)||E<-TD#task.content]
++ case TD#task.end_talk of
0 -> []; %% end_talk=0则直接提交任务
_ -> [content_to_mark([TD#task.state, ?TASK_CONTENT_END_TALK, TD#task.end_npc, TD#task.end_talk, 0, 0, 0, TD#task.finish_pathfind], TaskArgs1)]
end,
add_trigger(TaskArgs#task_args.id, TaskId, utime:unixtime(), 0, TD#task.state,
TaskMark, TD#task.type, TD#task.kind, TaskArgs#task_args.figure#figure.lv),
%% 转生任务接取了要通知其他模块
if
TD#task.type == ?TASK_TYPE_TURN ->
lib_player:apply_cast(TaskArgs#task_args.id, ?APPLY_CAST_SAVE, transform, trigger_task, [TD#task.id]);
true -> skip
end,
get_my_task_list(0, TaskArgs1),
refresh_npc_ico(TaskArgs1),
ok.
%% 清理自身触发的任务
gm_refresh_task(GmType, TaskArgs) ->
put("lib_task_task_bag_id_list", []),
db:execute(io_lib:format("delete from task_log_clear where role_id=~w", [TaskArgs#task_args.id])),
if
GmType == 0 -> %% 当前已接
db:execute(io_lib:format("delete from task_bag where role_id=~w", [TaskArgs#task_args.id]));
true -> %% 删除所有的任务,从0开始
[delete_task_log_list(Tid) || Tid <- data_task_lv:get_ids(TaskArgs#task_args.figure#figure.lv)],
db:execute(io_lib:format("delete from task_log where role_id=~w", [TaskArgs#task_args.id])),
db:execute(io_lib:format("delete from task_bag where role_id=~w", [TaskArgs#task_args.id]))
end,
flush_role_task(TaskArgs),
get_my_task_list(0, TaskArgs),
refresh_npc_ico(TaskArgs).
%% 直接移除某个任务(秘籍使用)
del_task(TaskId, TaskArgs) ->
%% 删除缓存
delete_task_bag_list(TaskId),
delete_task_log_list(TaskId),
TD = get_data(TaskId),
F = fun() ->
db:execute(io_lib:format("delete from task_bag where role_id=~w and task_id=~p",
[TaskArgs#task_args.id, TaskId])),
del_log(TaskArgs#task_args.id, TaskId, TD#task.type)
end,
db:transaction(F),
%% 刷新
refresh_active(TaskArgs),
get_my_task_list(0, TaskArgs),
refresh_npc_ico(TaskArgs),
ok.
%% 完成当前主线任务
gm_finitask(TaskArgs) ->
% spawn(fun()-> finish_lv_task(TaskArgs) end),
TaskList = get_task_bag_id_list(),
Fun = fun(#role_task{task_id = TaskId, type = TaskType})->
case TaskType == ?TASK_TYPE_MAIN of
true -> finish(TaskId, [], TaskArgs);
false -> ok
end
end,
lists:map(Fun, TaskList),
get_my_task_list(0, TaskArgs),
ok.
gm_finish_lv_task(Status)->
TaskArgs = lib_task_api:ps2task_args(Status),
finish_lv_task(TaskArgs).
%% 完成该等级前的所有任务
finish_lv_task(#task_args{id=RoleId, figure=#figure{lv=Lv}}=TaskArgs) ->
% Sql = io_lib:format(<<"delete from `role_npc_show` where id = ~p ">>, [RoleId]),
% db:execute(Sql),
AllIdList = data_task_lv:get_ids(Lv - 1),
F2 = fun(TaskId, Acc) ->
TD = data_task:get(TaskId),
case TD of
#task{type = 1} -> [TaskId|Acc];
_ -> Acc
end
end,
MainTaskIds = lists:droplast( lists:foldr(F2, [], AllIdList)), %% 过滤后把当前级即最后一个去掉
case db:get_all(io_lib:format(<<"select task_id from task_log WHERE role_id=~p">>, [RoleId])) of
LogIds when is_list(LogIds) -> LogIds2 = lists:usort(LogIds);
_ -> LogIds2 = []
end,
NowTime = utime:unixtime(),
F1 = fun(TaskId, Acc) ->
TD = data_task:get(TaskId),
case TD =/= null andalso TD =/= [] andalso TD#task.type == 1 andalso lists:member(TaskId, LogIds2) == false of
true ->
Sql3 = io_lib:format(<<"REPLACE INTO `task_log` set `role_id`=~p, `task_id`=~p, `type`=~p, `trigger_time`=~p, `finish_time`=~p">>,
[RoleId, TaskId, TD#task.type, NowTime, NowTime]),
db:execute(Sql3),
[TaskId|Acc];
false ->
Acc
end
end,
TIds = lists:foldl(F1, [], MainTaskIds),
Sql2 = io_lib:format(<<"delete from `task_bag` where role_id=~p and task_id in (~s)">>, [RoleId, util:link_list(TIds)]),
db:execute(Sql2),
flush_role_task(TaskArgs),
lv_up(TaskArgs),
List = get_task_log_id_list(),
lib_server_send:send_to_uid(RoleId, pt_300, 30017, [List]),
ok.
%%打包多个taskid
pack_task_id(TaskList)->
Fun = fun(TaskId) -> <<TaskId:32>> end,
ListBin = pt:write_array(Fun, TaskList),
ListBin.
%%解包多个taskid
unpack_task_id(TaskListBin)->
Fun = fun(<<Bin0/binary>>) ->
<<TaskId:32, _Args1/binary>> = Bin0,
{TaskId, _Args1}
end,
{TaskList, _Bin1} = pt:read_array(Fun, TaskListBin),
TaskList.
%%触发长剧情
event_to_story(PS, TaskId, EndTime) ->
#player_status{id = RoleId, sid = Sid, scene = SceneId, scene_pool_id = ScenePoolId, copy_id = CopyId, x = X, y = Y} = PS,
Utime = utime:unixtime(),
%%默认60s
DefaultTime = 60,
Times = ?IF( EndTime - Utime > DefaultTime, DefaultTime, max(1, EndTime - Utime)),
Ref = erlang:send_after(Times * 1000, self(), {mod, ?MODULE, event_to_cancel_story, [TaskId]}),
put({?MODULE, event_story, TaskId}, Ref),
lib_server_send:send_to_sid(Sid, pt_300, 30016, [?SUCCESS]),
{ok, BinData} = pt_300:write(30017, [RoleId, 1]),
lib_server_send:send_to_area_scene(SceneId, ScenePoolId, CopyId, X, Y, BinData),
ok.
%%触发结束长剧情
event_to_cancel_story(PS, TaskId) ->
#player_status{id = RoleId, scene = SceneId, scene_pool_id = ScenePoolId, copy_id = CopyId, x = X, y = Y} = PS,
lib_counter:increment(RoleId, ?MOD_TASK, 1, TaskId),
Ref = get({?MODULE, event_story, TaskId}),
util:cancel_timer(Ref),
erase({?MODULE, event_story, TaskId}),
{ok, BinData} = pt_300:write(30017, [RoleId, 0]),
lib_server_send:send_to_area_scene(SceneId, ScenePoolId, CopyId, X, Y, BinData),
{ok, PS}.
after_finish_round_task(RoleId, TaskType, Num) ->
if
TaskType == ?TASK_TYPE_DAILY -> %% 日常任务
custom_act_mobilize:update_mobilize_task(RoleId, dailytask, Num),
mod_hi_point:success_end(RoleId, ?MOD_TASK, 1, 1),
custom_act_adventure:do_trigger_adventure_task(RoleId, ?MOD_TASK, 1),
lib_activitycalen_api:role_success_end_activity(RoleId, ?MOD_TASK, 1, Num),
lib_role_legion:trigger_task(RoleId, ?MOD_TASK, 1);
TaskType == ?TASK_TYPE_GUILD -> %% 公会任务
lib_activitycalen_api:role_success_end_activity(RoleId, ?MOD_TASK, 2, Num),
mod_hi_point:success_end(RoleId, ?MOD_TASK, 2, 1),
custom_act_adventure:do_trigger_adventure_task(RoleId, ?MOD_TASK, 2),
lib_guild_labor:task_active(RoleId,?GTASK_TYPE_TASK);
true ->
skip
end.
%%过滤对话选项任务的完成TalkId
filter_task_talk([])->
0;
filter_task_talk([H|T])->
case H of
[_, _, ?TASK_CONTENT_CHOOSE_TALK, _NeedId, _NeedNum, _Scene, _X, _Y,Talk, _PathFind]->
Talk;
_->
filter_task_talk(T)
end.
%%npc矫正
fix_task_npc([],NewTriggerList,_TaskArgs)->
NewTriggerList;
fix_task_npc([H|T],NewTriggerList,TaskArgs)->
#role_task{mark=Mark}=H,
NMark = fix_task_mark(Mark,[],TaskArgs),
fix_task_npc(T,[H#role_task{mark=NMark}|NewTriggerList],TaskArgs).
fix_task_mark([],Mark,_TaskArgs)->
lists:reverse(Mark);
fix_task_mark([[State,CurState,?TASK_CONTENT_CHOOSE_TALK,Id,Num,_SceneId,_X,_Y,NeedNum,PathFind]|Mark],NMark,TaskArgs)->
NewId=lib_role_task:exchange_npc(Id),
{RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
fix_task_mark(Mark,[[State,CurState,?TASK_CONTENT_CHOOSE_TALK,NewId,Num,RealSceneId, RealX, RealY,NeedNum,PathFind]|NMark],TaskArgs);
fix_task_mark([[State,CurState,?TASK_CONTENT_TALK,Id,Num,_SceneId,_X,_Y,NeedNum,PathFind]|Mark],NMark,TaskArgs)->
NewId=lib_role_task:exchange_npc(Id),
{RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
fix_task_mark(Mark,[[State,CurState,?TASK_CONTENT_TALK,NewId,Num,RealSceneId, RealX, RealY,NeedNum,PathFind]|NMark],TaskArgs);
fix_task_mark([[State,CurState,?TASK_CONTENT_END_TALK,Id,Num,_SceneId,_X,_Y,NeedNum,PathFind]|Mark],NMark,TaskArgs)->
NewId=lib_role_task:exchange_npc(Id),
{RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
fix_task_mark(Mark,[[State,CurState,?TASK_CONTENT_END_TALK,NewId,Num,RealSceneId, RealX, RealY,NeedNum,PathFind]|NMark],TaskArgs);
fix_task_mark([[State,CurState,?TASK_CONTENT_MAILER_RUN,Id,Num,_SceneId,_X,_Y,NeedNum,PathFind]|Mark],NMark,TaskArgs)->
NewId=lib_role_task:exchange_npc(Id),
{RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
fix_task_mark(Mark,[[State,CurState,?TASK_CONTENT_MAILER_RUN,NewId,Num,RealSceneId, RealX, RealY,NeedNum,PathFind]|NMark],TaskArgs);
fix_task_mark([H|T],NMark,TaskArgs)->
fix_task_mark(T,[H|NMark],TaskArgs).