|
%%%-----------------------------------
|
|
%%% @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).
|