%%-----------------------------------------------------------------------------
%% @Module  :       lib_dungeon_distribute
%% @Author  :       zengzy
%% @Created :       2019-04-30
%% @Description:    副本分发模块
%%

%% ---------------------------------------------------------------------------
%% 常用副本分发函数，列举了常用高频分发函数，其它部分直接调用分发接口或者在功能模块内处理分发
%%-----------------------------------------------------------------------------

-module (lib_dungeon_distribute).
-include ("dungeon.hrl").
-include ("server.hrl").
-include ("common.hrl").
-include ("def_module.hrl").
-include ("dungeon_multi.hrl").
-include ("drop.hrl").
%%通用分发接口
-export([
		mod_dungeon_type_map/1			%% 根据副本类型获取分发mod
		,get_special_api_mod/3			%% 根据Func获取分发mod

		%%分发接口
		,distribute/4					%% 通过副本类型分发操作
		,distribute_normal/1			%% 不存在分发模块, 触发副本通用

		,dispatch_dun_event/2			%% 消息事件分发
	]).

%%高频副本操作分发接口
-export([
		get_start_dun_args/4  			%%副本初始化带参数
		,get_create_mon_args/1
		,get_role_rec/6
		,get_sweep_wave/4

		,handle_wave_state/2
		,handle_kill_mon_do/2

		%%结算相关
		,get_send_reward/2				%%计算玩家奖励
		,calc_score_rewards/3			%%计算评分奖励
		,calc_rating_rewards/3			%%计算通用评级奖励
		,handle_score_reward_rec/4		%%处理评分奖励参数额外逻辑
		,send_dun_rewards/1 			%%发送奖励
		,push_settlement/3 				%%通用结算界面
		,check_quit_state/2				%%人物退出时检测结果状态

		%%副本评分相关
		,make_grade_event/1				%%初始化评分条件
		,dispatch_dungeon_score_event/4 %%副本评分事件触发/检测

		%%副本评级相关
		,make_grade_rating/1
		,dispatch_dungeon_rating/3
		,calc_rating_drop/1				%% 评级掉落

		%% 翻牌
		,start_dun_flop/3

		%%进入，退出副本相关
		,calc_cost/2					%%副本进入所需消耗内容

		,check_extra/2					%%单人本进入的额外检测

		,role_success_end_activity/4	%%完成副本通知日常刷新
		,handle_enter_dungeon/2 		%%玩家进入副本后特殊处理
		,fin_enter_dun/2				%%加载完场景
		,handle_quit_dungeon/2 			%%玩家退出副本后特殊处理

		,handle_disconnect/4  			%% 副本内断线(闪退/掉线/关闭客户端)
		,login_back_to_scene/9 			%% 副本内断线重连操作
		,get_login_args/2				%% 进入副本，断线重连,副本组合相关参数带回玩家进程
		,get_role_dun_born_xy/4				%% 获取出生坐标


		,handle_role_out_offline/2		%% 副本结束,离线玩家的处理（只限可断线重连副本）

		,get_power_crush_calc/2			%% 战力碾压额外比例计算
		,handle_kill_mon/4				%% 怪物死亡处理
		,handle_player_die/2			%% 玩家死亡处理

		,handle_dungeon_result/1		%%副本结束时触发(副本结算奖励计算完)
		,dungeon_end_clear_mon/2		%%副本结束时清怪

		%%玩家的副本数据相关
		,update_dungeon_record/3		%%通关回写玩家进程
		,handle_task_trigger/3			%%副本通关通知任务系统刷新
		,handle_achievement/2			%%副本通关刷新成就

		%%扫荡相关
		,check_sweep_daily_count/5		%%检测是否能扫荡
		,calc_sweep_rewards/5			%%获取扫荡奖励内容
		,handle_sweep_count_plus/4
		,get_sweep_duns/3

		%% 复活
		,get_revive_info/4

		%% 进入下一个副本
		,enter_next_dun/2

		,pack_account_kv_data/2

		,get_dun_dummy_args/2
		,get_drop_arg/2
		,get_dun_result_succ_args/3
	]).

%%其它特殊接口
-export([
		handle_role_out/5				%%退出 玩家信息的处理
		,role_be_hurted/4				%%玩家在副本被攻击时触发
		,get_power_crush_val/4			%%获取特殊计算的战力碾压和属性碾压
	]).

%% 副本事件分发接口
-export([
	init_dun_wave/2						%% 初始化波数
	,create_mon/3						%% 初始化怪物
	,dungeon_result/3					%% 副本结算
	,dungeon_result/2                   %% 副本结算
	,init_friendly_objects/1            %% 生成友方对象
	]).

%% ---------------------------------------------------------------------------
%% @doc 根据副本类型获取mod
%% ---------------------------------------------------------------------------
mod_dungeon_type_map(?DUNGEON_TYPE_MATERIAL) ->
	lib_dungeon_material;
mod_dungeon_type_map(?DUNGEON_TYPE_EXP) ->
	lib_dungeon_exp;
mod_dungeon_type_map(?DUNGEON_TYPE_VIP) ->
	lib_dungeon_vip;
mod_dungeon_type_map(?DUNGEON_TYPE_PER_BOSS) ->
	lib_dungeon_personal_boss;
mod_dungeon_type_map(?DUNGEON_TYPE_TOWER) ->
	lib_dungeon_tower;
mod_dungeon_type_map(?DUNGEON_TYPE_CRUSADE) ->
	lib_dungeon_crusade;
mod_dungeon_type_map(?DUNGEON_TYPE_VISUS) ->
	lib_dungeon_visus;
mod_dungeon_type_map(?DUNGEON_TYPE_PET) ->
	lib_dungeon_pet;
mod_dungeon_type_map(?DUNGEON_TYPE_GUARD) ->
	lib_dungeon_guard;
mod_dungeon_type_map(?DUNGEON_TYPE_GOD) ->
	lib_dungeon_god;
mod_dungeon_type_map(?DUNGEON_TYPE_CHILD) ->
	lib_dungeon_child;
mod_dungeon_type_map(?DUNGEON_TYPE_GALAXY) ->
	lib_dungeon_galaxy;
mod_dungeon_type_map(?DUNGEON_TYPE_POINT) ->
	lib_dungeon_cross_point;
mod_dungeon_type_map(?DUNGEON_TYPE_CONVOY) ->
	lib_dungeon_convoy;
mod_dungeon_type_map(?DUNGEON_TYPE_HELP) ->
	lib_dungeon_help;
mod_dungeon_type_map(?DUNGEON_TYPE_GUIDE_BOSS) ->
	lib_dungeon_guide_boss;
mod_dungeon_type_map(?DUNGEON_TYPE_MAIN_LINE) ->
	lib_dungeon_main_line;
mod_dungeon_type_map(_) ->
	undefined.

%% ---------------------------------------------------------------------------
%% @doc 获取分发函数的模块名
%% ---------------------------------------------------------------------------
-spec get_special_api_mod(DunType, ApiName, ArgsNum) -> ReturnType when
	DunType :: integer(),
	ApiName :: atom(),
	ArgsNum :: [term()],
	ReturnType :: atom() | undefined.
get_special_api_mod(DunType, ApiName, ArgsNum) ->
    Mod = lib_dungeon_distribute:mod_dungeon_type_map(DunType),
    if
        Mod =/= undefined ->
            case lists:member({ApiName, ArgsNum}, Mod:module_info(exports)) of
                true ->
                    Mod;
                _ ->
                    undefined
            end;
        true ->
            undefined
    end.

%% ---------------------------------------------------------------------------
%% @doc 通过副本类型分发模块接口
-spec distribute(DunType, Fun, Args, DefaultReturn) -> ReturnType when
	DunType        	:: integer(),    			%% 副本类型
	Fun        		:: atom(),		            %% 分发函数名
	Args 			:: list(),					%% 分发函数参数
	DefaultReturn 	:: any(),					%% 默认返回值 | 调用函数
	ReturnType 		:: any().
% ---------------------------------------------------------------------------
distribute(DunType, Fun, Args, DefaultReturn) ->
	ArgsNum = length(Args),
    case get_special_api_mod(DunType, Fun, ArgsNum) of
        undefined ->
        	distribute_normal(DefaultReturn);
        Mod ->
            apply(Mod, Fun, Args)
    end.

%%触发副本通用函数
distribute_normal({default_mfa, Mod, Fun, Args}) ->
	apply(Mod, Fun, Args);
distribute_normal({default_mfa, Fun, Args}) ->
	apply(dungeon_default, Fun, Args);
%%触发副本通用返回值
distribute_normal(DefaultReturn) ->
	DefaultReturn.



%% 消息&事件分发
-spec dispatch_dun_event(Msg, State) -> ReturnType when
	Msg :: term(),
	State :: #dungeon_state{},
	ReturnType :: #dungeon_state{}.
dispatch_dun_event(Msg, State = #dungeon_state{}) ->
	#dungeon_state{dun_type = DunType} = State,
	case get_special_api_mod(DunType, dispatch_dun_event, 2) of
		Mod when Mod =/= undefined ->
			Mod:dispatch_dun_event(Msg, State);
		_ ->
			dungeon_default:dispatch_dun_event(Msg, State)
	end.

%% ------------------------------- 通用事件接口 --------------------------------
%% 初始化波数
-spec init_dun_wave(State, Wave) -> ReturnType when
	State :: #dungeon_state{},
	Wave :: integer(),
	ReturnType :: #dungeon_state{}.
init_dun_wave(State, Wave) ->
	Msg = {'init_dun_wave', Wave},
	dispatch_dun_event(Msg, State).

%% 生成友方对象
-spec init_friendly_objects(State) -> ReturnType when
	State :: #dungeon_state{},
	ReturnType :: #dungeon_state{}.
init_friendly_objects(State) ->
	Msg = {'init_friendly_objects'},
	dispatch_dun_event(Msg, State).

%% 创怪
-spec create_mon(State, Wave, MonList) -> ReturnType when
	State :: #dungeon_state{},
	Wave :: integer(),
	MonList :: list(),
	ReturnType :: #dungeon_state{}.
create_mon(State, Wave, MonList) ->
	Msg = {'create_mon', Wave, MonList},
	dispatch_dun_event(Msg, State).

%% 副本结算
dungeon_result(State, [ResultType, ResultSubtype]) ->
	dungeon_result(State, ResultType, ResultSubtype).
-spec dungeon_result(State, ResultType, ResultSubtype) -> ReturnType when
	State :: #dungeon_state{},
	ResultType :: integer(),
	ResultSubtype :: integer(),
	ReturnType :: #dungeon_state{}.
dungeon_result(State, ResultType, ResultSubtype) ->
	Msg = {'dungeon_result', ResultType, ResultSubtype},
	dispatch_dun_event(Msg, State).


%%---------------------------------副本相关操作分发接口------------------------

%% @doc 副本初始化所带参数
-spec get_start_dun_args(Object, DunRole, Dun, OptionType) -> ReturnType when
	Object :: #player_status{} | integer(),
	DunRole :: #dungeon_role{} | integer(),
	Dun :: #dun_cfg{},
	OptionType :: integer(),
	ReturnType :: list().
get_start_dun_args(Object, DunRole, Dun, OptionType) ->
	#dun_cfg{type = DunType} = Dun,
	Args = [Object, DunRole, Dun, OptionType],
	DefaultReturn = [],
	distribute(DunType, get_start_dun_args, Args, DefaultReturn).

-spec get_create_mon_args(State) -> ReturnType when
	State :: #dungeon_state{},
	ReturnType :: [term()].
get_create_mon_args(State) ->
	#dungeon_state{dun_type = DunType} = State,
	DefaultReturn = [],
	distribute(DunType, get_create_mon_args, [State], DefaultReturn).

%% 获取人物副本记录,
%% 存放在#dungeon_role.typical_data字段
-spec get_role_rec(DunType, DunId, RoleId, DungeonRec, DunData, TypicalData) -> ReturnType when
	DunType :: integer(),
	DunId :: integer(),
	RoleId :: integer(),
	DungeonRec :: list(),
	DunData :: term(),
	TypicalData :: map(),
	ReturnType :: map().
get_role_rec(DunType, DunId, RoleId, DungeonRec, DunData, TypicalData) ->
	Args = [DunId, DunType, RoleId, DungeonRec, DunData, TypicalData],
	DefaultReturn = TypicalData,
	distribute(DunType, get_role_rec, Args, DefaultReturn).


%% 获取扫荡结算波数
-spec get_sweep_wave(Player, DunId, SweepNum, CostType) -> ReturnType when
	Player :: #player_status{},
	DunId :: integer(),
	SweepNum :: integer(),
	CostType :: integer(),
	ReturnType :: integer().
get_sweep_wave(Player, DunId, SweepNum, CostType) ->
	DunType = data_dungeon:get_dun_type(DunId),
	Args = [Player, DunId, DunType, SweepNum, CostType],
	DefaultReturn = 1,
	distribute(DunType, get_sweep_wave, Args, DefaultReturn).

%% 波数状态处理
-spec handle_wave_state(State, Args) -> ReturnType when
	Args :: list(), 	%% [[StateSign, Wave]|_]
	% StateSign :: ?WAVE_SAME|?WAVE_CYCLE|?WAVE_NEXT|?DUN_PASS,
	%% Wave :: integer(),
	State :: #dungeon_state{},
	ReturnType :: #dungeon_state{}.
handle_wave_state(State, Args) ->
	% FunArgs = [Wave, StateSign, State],
	FunArgs = [State|Args],
	DefaultFun = {default_mfa, dungeon_default, handle_wave_state_normal, FunArgs},
	distribute(State#dungeon_state.dun_type, handle_wave_state, FunArgs, DefaultFun).

-spec handle_kill_mon_do(State, Args) -> ReturnType when
	State :: #dungeon_state{},
	Args :: list(),
	ReturnType :: #dungeon_state{}.
handle_kill_mon_do(State, Args) ->
	DefaultFun = {default_mfa, dungeon_default, handle_kill_mon_do_normal, [State|Args]},
	distribute(State#dungeon_state.dun_type, handle_kill_mon_do, [State|Args], DefaultFun).

%% ---------------------------------------------------------------------------
%% @doc 副本结算，计算玩家奖励
-spec get_send_reward(State, DungeonRole) -> ReturnType when
	State :: #dungeon_state{},
	DungeonRole :: #dungeon_role{},
	ReturnType :: list().
%% ---------------------------------------------------------------------------
get_send_reward(State, DungeonRole) ->
	Args = [State, DungeonRole],
	FunArgs = Args,
	DefaultFun = {default_mfa, dungeon_default, get_send_reward_normal, FunArgs},
	distribute(State#dungeon_state.dun_type, get_send_reward, Args, DefaultFun).


%% ---------------------------------------------------------------------------
-spec calc_score_rewards(DunType, DunId, DungeonRole) -> ReturnType when
	DunType :: integer(),
	DunId :: integer(),
	DungeonRole :: #dungeon_role{},
	ReturnType :: {list(), list()}.
calc_score_rewards(DunType, DunId, DungeonRole) ->
	Args = [DunType, DunId, DungeonRole],
	DefaultReturn = {[false], []},
	distribute(DunType, calc_score_rewards, Args, DefaultReturn).

-spec calc_rating_rewards(DunType, DunId, DungeonRole) -> ReturnType when
	DunType :: integer(),
	DunId :: integer(),
	DungeonRole :: #dungeon_role{},
	ReturnType :: list().
calc_rating_rewards(DunType, DunId, DungeonRole) ->
	Args = [DunType, DunId, DungeonRole],
	DefaultFun = {default_mfa, calc_rating_rewards_normal, Args},
	distribute(DunType, calc_rating_rewards, Args, DefaultFun).

-spec handle_score_reward_rec(DunType, Role, DunId, ExtraArgs) -> ReturnType when
	DunType :: integer(),
	Role :: #dungeon_role{},
	DunId :: integer(),
	ExtraArgs :: list(),
	ReturnType :: ok | skip.
handle_score_reward_rec(DunType, Role, DunId, ExtraArgs) ->
	Args = [Role, DunId, ExtraArgs],
	DefaultReturn = ok,
	distribute(DunType, handle_score_reward_rec, Args, DefaultReturn).

%% 副本奖励发放
-spec send_dun_rewards(State) -> ReturnType when
	State :: #dungeon_state{},
	ReturnType :: #dungeon_state{}.
send_dun_rewards(State) ->
	Args = FunArgs = [State],
	DefaultFun = {default_mfa, dungeon_default, send_dun_rewards_normal, FunArgs},
	distribute(State#dungeon_state.dun_type, send_dun_rewards, Args, DefaultFun).


%% 进入副本消耗检测
-spec calc_cost(PS, Dun) -> ReturnType when
	PS :: #player_status{},
	Dun :: #dun_cfg{},
	ReturnType :: list().
calc_cost(PS, Dun) ->
	DefaultReturn = [],
	distribute(Dun#dun_cfg.type, calc_cost, [PS], DefaultReturn).


%% ---------------------------------------------------------------------------
%% @doc 单人副本进入的额外检测
-spec check_extra(PS, Dun) -> ReturnType when
	PS :: #player_status{},
	Dun :: #dun_cfg{},
	ReturnType :: true | {false, integer()}.
check_extra(PS, Dun) ->
	Args = [PS, Dun],
	DefaultReturn = true,
	distribute(Dun#dun_cfg.type, check_extra, Args, DefaultReturn).

%% ---------------------------------------------------------------------------
%% @doc 完成副本通知日常刷新
-spec role_success_end_activity(DunType,DunID,RoleId,PlusCount) -> ReturnType when
	DunType :: integer(),
	DunID :: integer(),
	RoleId :: integer(),
	PlusCount :: integer(),
	ReturnType :: ok.
role_success_end_activity(DunType,DunID,RoleId,PlusCount) ->
	Args = [DunType, RoleId],
	FunArgs = [RoleId, ?MOD_DUNGEON, DunType, DunID,PlusCount],
	DefaultFun = {default_mfa, lib_activitycalen_api, finish_dungeon, FunArgs},
	distribute(DunType, role_success_end_activity, Args, DefaultFun).

%% ---------------------------------------------------------------------------
%% @doc 玩家进入副本后特殊处理
-spec handle_enter_dungeon(PS, Dun) -> ReturnType when
	PS :: #player_status{},
	Dun :: #dun_cfg{},
	ReturnType :: #player_status{}.
handle_enter_dungeon(PS, Dun) ->
	#dun_cfg{type = DunType} = Dun,
	Args = [PS, Dun],
	DefaultReturn = PS,
	distribute(DunType, handle_enter_dungeon, Args, DefaultReturn).

%% ---------------------------------------------------------------------------
%% @doc 加载完场景
%% ---------------------------------------------------------------------------
-spec fin_enter_dun(State, RoleId) -> ReturnType when
	State :: #dungeon_state{},
	RoleId :: integer(),
	ReturnType :: list().
fin_enter_dun(State, RoleId) ->
	Args = [State, RoleId],
	DefaultFun = State,
	distribute(State#dungeon_state.dun_type, fin_enter_dun, Args, DefaultFun).

%% ---------------------------------------------------------------------------
%% @doc 玩家退出副本后特殊处理
-spec handle_quit_dungeon(PS, Dun) -> ReturnType when
	PS :: #player_status{},
	Dun :: #dun_cfg{},
	ReturnType :: #player_status{}.
handle_quit_dungeon(PS, Dun) ->
	#dun_cfg{id = DunId, type = DunType} = Dun,
	Args = [PS, Dun],
	FunArgs = [PS, DunId],
	DefaultFun = {default_mfa, lib_dungeon, handle_quit_remove_skill_buff, FunArgs},
	distribute(DunType, handle_quit_dungeon, Args, DefaultFun).

%% ---------------------------------------------------------------------------
%% @doc 副本内断线/闪退/关掉客户端等原因断开
-spec handle_disconnect(RoleId, Hp, HpLim, State) -> ReturnType when
	RoleId :: integer(),
	Hp :: integer(),
	HpLim :: integer(),
	State :: #dungeon_state{},
	ReturnType :: #dungeon_state{}.
handle_disconnect(RoleId, Hp, HpLim, State) ->
	DefaultReturn = State,
	Args = [RoleId, Hp, HpLim, State],
	distribute(State#dungeon_state.dun_type, handle_disconnect, Args, DefaultReturn).

%% ---------------------------------------------------------------------------
%% @doc 副本内断线重连操作
%% DunType		:: integer()					%% 副本类型
%% PS        	:: #player_status{}             %% 玩家PS.
%% SceneId      :: integer()                  	%% 场景id
%% return 		:: #player_status{}             %% 玩家PS.
%% ---------------------------------------------------------------------------
login_back_to_scene(DunType, PS, SceneId, ScenePoolId, CopyId, X, Y, KeyValList, FArgs) ->
	Args = [PS, SceneId, ScenePoolId, CopyId, X, Y, KeyValList, FArgs],
	FunArgs = Args,
	DefaultFun = {default_mfa, lib_dungeon, login_back_to_scene_normal, FunArgs},
	distribute(DunType, login_back_to_scene, Args, DefaultFun).

%% ---------------------------------------------------------------------------
%% @doc 进入副本，断线重连,副本进程组合相关参数带回玩家进程,比如login_back_to_scene
%% 函数所属进程：副本进程
%% return 		:: list()
%% ---------------------------------------------------------------------------
-spec get_login_args(State, RoleId) -> ReturnType when
	State :: #dungeon_state{},
	RoleId :: integer(),
	ReturnType :: list().
get_login_args(State, RoleId) ->
	Args = [State, RoleId],
	FunArgs = Args,
	DefaultFun = {default_mfa, dungeon_default, get_login_args, FunArgs},
	distribute(State#dungeon_state.dun_type, login, Args, DefaultFun).

%% ---------------------------------------------------------------------------
%% @doc 结算界面61003特殊处理
%% DunType		:: integer()					%% 副本类型
%% State        :: #dungeon_state{}             %% 副本State.
%% DungeonRole  :: #dungeon_role{}              %% 副本玩家记录
%% return 		:: any()
%% ---------------------------------------------------------------------------
push_settlement(DunType, State, DungeonRole) ->
	Args = [State, DungeonRole],
	FunArgs = Args,
	DefaultFun = {default_mfa, dungeon_default, push_settlement_normal, FunArgs},
	distribute(DunType, push_settlement, Args, DefaultFun).

-spec check_quit_state(State, RoleId) -> ReturnType when
	State :: #dungeon_state{},
	RoleId :: integer(),
	ReturnType :: {integer(), integer()}.
check_quit_state(State, RoleId) ->
	#dungeon_state{role_list = RoleList} = State,
	%% 前端播放死亡动作,子类型优先选择玩家死亡类型
	ResultSubtype =
	case lists:keyfind(RoleId, #dungeon_role.id, RoleList) of
		#dungeon_role{hp = Hp} ->
			if Hp =< 0 -> ?DUN_RESULT_SUBTYPE_ROLE_DIE;
				true -> ?DUN_RESULT_SUBTYPE_ACTIVE_QUIT
			end;
		_ ->
			?DUN_RESULT_SUBTYPE_ACTIVE_QUIT
	end,
	Args = [State, RoleId],
	DefaultReturn = {?DUN_RESULT_TYPE_FAIL, ResultSubtype},
	distribute(State#dungeon_state.dun_type, check_quit_state, Args, DefaultReturn).

%% ---------------------------------------------------------------------------
%% @doc 副本结束, 不在线玩家处理，只限可断线重连副本
%% DungeonRole  :: #dungeon_role{}              %% 副本玩家记录
%% State        :: #dungeon_state{}             %% 副本State.
%% return 		:: any()
%% ---------------------------------------------------------------------------
handle_role_out_offline(DungeonRole, State) ->
	Args = [DungeonRole, State],
	DefaultReturn = ok,
	distribute(State#dungeon_state.dun_type, handle_role_out_offline, Args, DefaultReturn).

%% ---------------------------------------------------------------------------
%% @doc 副本战力碾压额外系数计算
%% State        :: #dungeon_state{}             %% 副本State.
%% return 		:: #dungeon_state{}             %% 副本State.
%% ---------------------------------------------------------------------------
get_power_crush_calc(DunType, CrushR) ->
	Args = [CrushR],
	DefaultReturn = CrushR,
	distribute(DunType, get_power_crush_calc, Args, DefaultReturn).

%% ---------------------------------------------------------------------------
%% @doc 怪物死亡处理
%% State        :: #dungeon_state{}             %% 副本State.
%% Mid        	:: integer()             		%% 怪物id
%% CreateKey    :: tuple()           			%% 怪物主键.{mon_event, CommonEventId, WaveSubtype, CycleNum, MonAutoId}
%% DieDatas     :: list()                  		%% 怪物进程死亡所带参数.（可加）
%% return 		:: #dungeon_state{}             %% 副本State.
%% ---------------------------------------------------------------------------
handle_kill_mon(State, Mid, CreateKey, DieDatas) ->
	Args = [State, Mid, CreateKey, DieDatas],
	DefaultReturn = State,
	distribute(State#dungeon_state.dun_type, handle_kill_mon, Args, DefaultReturn).


%% 玩家死亡处理
-spec handle_player_die(State, Args) -> ReturnType when
	State :: #dungeon_state{},
	Args  :: list(), %% [RoleId, DeadCount|_]
	ReturnType :: #dungeon_state{}.
handle_player_die(State, Args) ->
	FunArgs = [State|Args],
	DefaultReturn = State,
	distribute(State#dungeon_state.dun_type, handle_player_die, FunArgs, DefaultReturn).


%% ---------------------------------------------------------------------------
%% @doc 副本结束时触发(副本结算奖励后)
%% State        :: #dungeon_state{}             %% 副本State.
%% return 		:: any() |#dungeon_state{}
%% ---------------------------------------------------------------------------
handle_dungeon_result(State) ->
	Args = [State],
	DefaultReturn = State,
	case distribute(State#dungeon_state.dun_type, handle_dungeon_result, Args, DefaultReturn) of
 		NewState = #dungeon_state{} ->
            NewState;
        _ ->
            State
	end.

%% ---------------------------------------------------------------------------
%% @doc 副本结束时清掉场景怪物
%% State        :: #dungeon_state{}             %% 副本State.
%% return 		:: boolean()
%% ---------------------------------------------------------------------------
dungeon_end_clear_mon(State, ResultType) ->
	Args = [State, ResultType],
	DefaultReturn = true,
	distribute(State#dungeon_state.dun_type, dungeon_end_clear_mon, Args, DefaultReturn).

%% ---------------------------------------------------------------------------
%% @doc 副本通关的数据同步到玩家PS进程,（比如副本记录#player_status.dungeon_record）
%% PS        	:: #player_status{}             %% 玩家PS.
%% Data  		:: #callback_dungeon_succ{}    	%% 副本相关信息
%% return 		:: #player_status{}             %% 玩家PS.
%% ---------------------------------------------------------------------------
update_dungeon_record(DunType, PS, Data) ->
	Args = [PS, Data],
	DefaultReturn = PS,
	distribute(DunType, update_dungeon_record, Args, DefaultReturn).

%% ---------------------------------------------------------------------------
%% @doc 副本通关通知任务系统刷新
%% PS        	:: #player_status{}             %% 玩家PS.
%% CallBack     :: #callback_dungeon_succ{}     %% 副本相关信息
%% return 		:: any()
%% ---------------------------------------------------------------------------
handle_task_trigger(DunType, PS, CallBack) ->
	Args = [PS, CallBack],
	FunArgs = Args,
	DefaultFun = {default_mfa, lib_dungeon, handle_task_trigger_normal, FunArgs},
	distribute(DunType, handle_task_trigger, Args, DefaultFun).

%% ---------------------------------------------------------------------------
%% @doc 副本通关刷新成就
%% PS        	:: #player_status{}             %% 玩家PS.
%% return 		:: #player_status{}             %% 玩家PS.
%% ---------------------------------------------------------------------------
handle_achievement(DunType, PS) ->
	Args = [PS],
	DefaultReturn = PS,
	distribute(DunType, handle_achievement, Args, DefaultReturn).

%% ---------------------------------------------------------------------------
%% @doc 副本评分事件初始化
%% ---------------------------------------------------------------------------
-spec make_grade_event(DunState) -> ReturnValue when
	DunState :: #dungeon_state{},
	ReturnValue :: #dungeon_state{}.
make_grade_event(DunState) ->
	Args = DefaultArgs = [DunState],
	DefaultFun = {default_mfa, make_grade_event_normal, DefaultArgs},
	distribute(DunState#dungeon_state.dun_type, make_grade_event, Args, DefaultFun).


%% 触发评分事件
-spec dispatch_dungeon_score_event(DunState, ScoreEventIds, RoleId, EventArgs) -> NewDunState when
	DunState :: #dungeon_state{},
	ScoreEventIds :: list(),
	RoleId :: integer(),
	EventArgs :: list(),
	NewDunState :: #dungeon_state{}.
dispatch_dungeon_score_event(DunState, ScoreEventIds, RoleId, EventArgs) ->
	Args = DefaultArgs = [DunState, ScoreEventIds, RoleId, EventArgs],
	DefaultFun = {default_mfa, dispatch_dungeon_score_event_normal, DefaultArgs},
	distribute(DunState#dungeon_state.dun_type, dispatch_dungeon_score_event, Args, DefaultFun).

%% 触发评级事件
-spec dispatch_dungeon_rating(State, RoleId, EventArgs) -> NewDunState when
	State :: #dungeon_state{},
	RoleId :: integer(),
	EventArgs :: list(),
	NewDunState :: #dungeon_state{}.
dispatch_dungeon_rating(State, RoleId, EventArgs) ->
	Args = DefaultArgs = [State, RoleId, EventArgs],
	DefaultFun = {default_mfa, dispatch_dungeon_rating_normal, DefaultArgs},
	distribute(State#dungeon_state.dun_type, dispatch_dungeon_rating, Args, DefaultFun).

%% 副本通用评级
-spec make_grade_rating(DunState) -> ReturnType when
	DunState :: #dungeon_state{},
	ReturnType :: #dungeon_state{}.
make_grade_rating(DunState) ->
	Args = DefaultArgs = [DunState],
	DefaultFun = {default_mfa, make_grade_rating_normal, DefaultArgs},
	distribute(DunState#dungeon_state.dun_type, make_grade_rating, Args, DefaultFun).

%% ---------------------------------------------------------------------------
%% @doc 检测是否能扫荡
%% ---------------------------------------------------------------------------
-spec check_sweep_daily_count(Player, Dun, Num, CostType, DailyList) -> ReturnType when
	Player :: #player_status{},
	Dun :: #dun_cfg{},
	Num :: integer(),
	CostType :: integer(),
	DailyList :: list(),
	ReturnType :: boolean() | {boolean(),integer()}.
check_sweep_daily_count(Player, Dun, Num, CostType, DailyList) ->
	Args = FunArgs = [Player, Dun, Num, CostType, DailyList],
	DefaultFun = {default_mfa, lib_dungeon_sweep, check_sweep_count, FunArgs},
	distribute(Dun#dun_cfg.type, check_sweep_daily_count, Args, DefaultFun).

%% ---------------------------------------------------------------------------
%% @doc 获取扫荡的奖励内容
-spec calc_sweep_rewards(PS, Dun, AutoNum, Mul, CostType) -> ReturnType when
	PS :: #player_status{},
	Dun :: #dun_cfg{},
	AutoNum :: integer(),
	Mul :: integer(),
	CostType :: integer(),
	ReturnType :: {ok, list()} | {false, integer()}.
calc_sweep_rewards(PS, Dun, AutoNum, Mul, CostType) ->
	Args = [PS, Dun, AutoNum, Mul, CostType],
	FunArgs = [Dun, AutoNum, Mul, CostType],
	DefaultFun = {default_mfa, lib_dungeon_sweep, calc_sweep_rewards_common, FunArgs},
	distribute(Dun#dun_cfg.type, calc_sweep_rewards, Args, DefaultFun).

%%
%%-----------------------------------------其它特殊分发接口-------------------------------------------------
%%
%% ---------------------------------------------------------------------------
%% @doc 玩家在副本被攻击时触发
%% return 		:: #dungeon_state{}             %% 副本State.
%% ---------------------------------------------------------------------------
-spec role_be_hurted(State, RoleId, Hp, HpLim) -> ReturnType when
	State :: #dungeon_state{},
	RoleId :: integer(),
	Hp :: integer(),
	HpLim :: integer(),
	ReturnType :: #dungeon_state{}.
role_be_hurted(State, RoleId, Hp, HpLim) ->
	Args = [State, RoleId, Hp, HpLim],
	DefaultReturn = State,
	distribute(State#dungeon_state.dun_type, role_be_hurted, Args, DefaultReturn).

%% ---------------------------------------------------------------------------
%% @doc 副本未结束退出,副本内玩家信息的处理
%% ---------------------------------------------------------------------------
-spec handle_role_out(RoleId, LogType, ResultType, ResultSubtype, State) -> ReturnType when
	RoleId :: integer(),
	LogType :: integer(),
	ResultType :: integer(),
	ResultSubtype :: integer(),
	State :: #dungeon_state{},
	ReturnType :: #dungeon_state{}.
handle_role_out(RoleId, LogType, ResultType, ResultSubtype, State) ->
	Args = FunArgs = [RoleId, LogType, ResultType, ResultSubtype, State],
	DefaultFun = {default_mfa, dungeon_default, handle_role_out_normal, FunArgs},
	distribute(State#dungeon_state.dun_type, handle_role_out, Args, DefaultFun).

%% ---------------------------------------------------------------------------
%% @doc 获取特殊计算的战力碾压和属性碾压
%% IsUsePowerCrush :: integer()					%% 是否使用战力碾压开关
%% return 		:: tuple()             			%% {战力碾压, 属性碾压}
%% ---------------------------------------------------------------------------
get_power_crush_val(State, IsUsePowerCrush, RecommendPower, RecommendAttr) ->
	Args = [State, IsUsePowerCrush, RecommendPower, RecommendAttr],
	DefaultReturn = {RecommendPower, RecommendAttr},
	distribute(State#dungeon_state.dun_type, get_power_crush_val, Args, DefaultReturn).


%% 翻牌
-spec start_dun_flop(Player, DunType, DunId) -> ReturnType when
	Player :: #player_status{},
	DunType :: integer(),
	DunId :: integer(),
	ReturnType :: #player_status{}.
start_dun_flop(Player, DunType, DunId) ->
	case data_dungeon:get_dun(DunId) of
	    #dun_cfg{type = DunType, flop_pools = [_|_]} -> %% 有翻牌配置即要求翻牌
	        {_, NewPlayer} = lib_dungeon_flop:start_dun_flop(Player, DunType, DunId),
	        NewPlayer;
	    _ -> 
	    	Player
	end.


%% 特殊次数更新
-spec handle_sweep_count_plus(DunType, DunId, RoleId, SweepNum) -> ReturnType when
	DunType :: integer(),
	DunId :: integer(),
	RoleId :: integer(),
	SweepNum :: integer(),
	ReturnType :: ok|skip|ignore.
handle_sweep_count_plus(DunType, DunId, RoleId, SweepNum) ->
	Args = [DunType, DunId, RoleId, SweepNum],
	DefaultReturn = ok,
	distribute(DunType, handle_sweep_count_plus, Args, DefaultReturn).

%%
-spec get_sweep_duns(DunType, DunId, SweepNum) -> ResultType when
	DunType :: integer(),
	DunId :: integer(),
	SweepNum :: integer(),
	ResultType :: list().
get_sweep_duns(DunType, DunId, SweepNum) ->
	Args = [DunType, DunId, SweepNum],
	DefaultReturn = lists:duplicate(SweepNum, DunId),
	distribute(DunType, get_sweep_duns, Args, DefaultReturn).

%% 复活信息
-spec get_revive_info(DunType, SceneId, RoleX, RoleY) -> ReturnType when
	DunType :: integer(),
	SceneId :: integer(),
	RoleX :: integer(),
	RoleY :: integer(),
	ReturnType :: map().
get_revive_info(DunType, SceneId, RoleX, RoleY) ->
	Args = [DunType, SceneId, RoleX, RoleY],
	DefaultReturn = #{SceneId => {RoleX, RoleY}},
	distribute(DunType, get_revive_info, Args, DefaultReturn).

-spec enter_next_dun(List, State) -> ReturnType when
	List :: list(),
	State :: #dungeon_state{},
	ReturnType :: #dungeon_state{}.
enter_next_dun(List, State) ->
	[_, DunType|_] = List,
	FunArgs = [State|List],
	DefaultFun = {default_mfa, dungeon_default, enter_next_dun, FunArgs},
	distribute(DunType, enter_next_dun, FunArgs, DefaultFun).


-spec pack_account_kv_data(DungeonState, RoleId) -> ReturnType when
	DungeonState :: #dungeon_state{},
	RoleId :: integer(),
	ReturnType :: list().
pack_account_kv_data(DungeonState, RoleId) ->
	#dungeon_state{
		dun_type 	 = DunType,
	    start_time   = StartTime,
        result_time  = ResultTime
	} = DungeonState,
	DefaultReturn = [{?DUN_PASS_TIME, round(ResultTime - StartTime)}],
	distribute(DunType, pack_account_kv_data, [DungeonState, RoleId], DefaultReturn).


-spec get_dun_dummy_args(DungeonState, DummyMember) -> ReturnType when
	DungeonState :: #dungeon_state{},
	DummyMember :: #dun_multi_member{},
	ReturnType :: list().
get_dun_dummy_args(DungeonState, DummyMember) ->
	DefaultReturn = [],
	distribute(DungeonState#dungeon_state.dun_type, get_dun_dummy_args, [DungeonState, DummyMember], DefaultReturn).

-spec get_role_dun_born_xy(State, RoleId, X, Y) -> {integer(), integer()} when
	State :: #dungeon_state{},
	RoleId :: integer(),
	X :: integer(),
	Y :: integer().
get_role_dun_born_xy(State, RoleId, X, Y) ->
	DefaultFun = {default_mfa, dungeon_default, get_role_dun_born_xy, [State, RoleId, X, Y]},
	distribute(State#dungeon_state.dun_type, get_role_dun_born_xy, [State, RoleId, X, Y], DefaultFun).

-spec calc_rating_drop(State) -> NewState when
	State :: #dungeon_state{},
	NewState :: #dungeon_state{}.
calc_rating_drop(State) ->
	DefaultFun = {default_mfa, dungeon_default, calc_rating_drop_normal, [State]},
	distribute(State#dungeon_state.dun_type, calc_rating_drop, [State], DefaultFun).

-spec get_drop_arg(Dungeon, MonArgs) -> NewMonArgs when
	Dungeon :: #status_dungeon{},
	MonArgs :: #mon_args{},
	NewMonArgs :: #mon_args{}.
get_drop_arg(Dungeon, MonArgs) ->
	DefaultFun = MonArgs,
	case data_dungeon:get_dun(Dungeon#status_dungeon.dun_id) of
		#dun_cfg{type = DunType} ->
			distribute(DunType, get_drop_arg, [Dungeon, MonArgs], DefaultFun);
		_ ->
			DefaultFun
	end.

-spec get_dun_result_succ_args(DunType, Role, Args) -> Ret when
	DunType :: integer(),
	Role :: #dungeon_role{},
	Args :: list(),
	Ret :: list().
get_dun_result_succ_args(DunType, Role, Args) ->
	distribute(DunType, get_dun_result_succ_args, [Role, Args], []).