2025-06-04 05:12:01 +08:00

663 lines
18 KiB
Plaintext

DialogView = class("DialogView", ContainerView)
DialogView.ViewType = UIViewType.DialogLayer;
autoImport("Dialog_MenuData");
autoImport("NpcMenuBtnCell");
autoImport("DialogCell");
autoImport("EndLessTowerCountDownInfo");
local tempV3 = LuaVector3();
function DialogView:GetShowHideMode()
return PanelShowHideMode.MoveOutAndMoveIn
end
function DialogView:Init()
self:InitView();
self:MapEvent();
end
function DialogView:InitView()
self.menu = self:FindGO("Menu");
self.menuSprite = self.menu:GetComponent(UISprite);
local bottom = self:FindGO("Anchor_bottom");
local activeH = GameObjectUtil.Instance:GetUIActiveHeight(self.gameObject)
tempV3:Set(0, -activeH/2, 0);
bottom.transform.localPosition = tempV3;
self.top = self:FindGO("Anchor_Top");
tempV3:Set(0, activeH/2, 0);
self.top.transform.localPosition = tempV3;
local obj = self:LoadPreferb("cell/DialogCell", bottom);
obj.transform.localPosition = LuaVector3.zero;
self.dialogCtl = DialogCell.new(obj);
self.dialogCtl:AddEventListener(MouseEvent.MouseClick, self.ClickDialogEvent, self);
-- updateTasks
local grid = self:FindChild("MenuGrid", self.menu):GetComponent(UIGrid);
self.menuCtl = UIGridListCtrl.new(grid, NpcMenuBtnCell, "NpcMenuBtnCell");
self.menuCtl:AddEventListener(MouseEvent.MouseClick, self.ClickMenuEvent, self);
end
function DialogView:ClickDialogEvent()
local preDialog = self.dialogInfo[self.dialogIndex];
-- 如果上一段對話有選項 則必須點選選項才可以進行下一步 否則無法進行
if(preDialog and (not preDialog.Option or preDialog.Option == "") and self.forceClickMenu ~= true)then
self:DialogGoUpdate();
end
end
function DialogView:ResetViewData()
self.defaultDialogId = nil;
self.dialoglist = nil;
self.dialognpcs = nil;
self.tasks = nil;
self.callback = nil;
self.callbackData = nil;
self.camera = nil;
self.wait = nil;
self.questId = nil;
if(self.questParams)then
TableUtility.ArrayClear(self.questParams);
else
self.questParams = {};
end
self.addconfig = nil;
self.addleft = nil;
self.addfunc = nil;
self.custommenudata = nil;
self.npcguid = nil;
self.npcdata = nil;
self.optionid = nil;
self.dialogInfo = nil;
self.dialogIndex = nil;
self.dialogend = false;
self.subViewId = nil;
self.optionWait = 0;
self.midShowFunc = nil;
self.midShowFuncParam = nil;
self.midHideFunc = nil;
self.forceClickMenu = false;
end
function DialogView:OnEnter()
DialogView.super.OnEnter(self);
self:ResetViewData();
self:UpdateViewData();
self:UpdateShow();
self.gameObject:SetActive(true);
local npcinfo = self:GetCurNpc();
if(npcinfo)then
local npcRootTrans = npcinfo.assetRole.completeTransform;
if(npcRootTrans)then
local viewPort = CameraConfig.NPC_Dialog_ViewPort;
if(type(self.camera)=="number")then
viewPort = Vector3(viewPort.x, viewPort.y, self.camera);
end
local duration = CameraConfig.NPC_Dialog_DURATION;
self:CameraFocusOnNpc(npcRootTrans, viewPort, duration);
end
end
local midShowFunc = self.viewdata.midShowFunc;
if(midShowFunc)then
self.midHideFunc = midShowFunc(self.gameObject, self.viewdata.midShowFuncParam);
end
FunctionVisitNpc.Me():AddVisitRef();
end
-- ViewData參數
-- 1. dialoglist(Dialog表中的ids or string(s){Text=string,ViceText=string}(s)這種情況是爲了處理文字文字大小不一樣)
-- 2. dialognpcs(對話里涉及到的NPCIDS)
-- 3. tasks 對話的任務配置(支線任務或者對話任務)
-- 4. callback(對話結束的回撥) function(callbackData, optionid, isSuccess)
-- 5. camera(攝像機的Z軸角度)
-- 6. wait(對話結束 攝像機重置的等待時間)
-- 7. questdata(任務對話的任務數據)
-- 8. addconfig( 自主新增的功能配置(npcfunc表中的功能型別) )
-- 9. addleft( 是否新增離開按鈕 )
-- 10. addfunc( 自主新增的功能(NameZh = string, event, eventParam, closeDialog, waitClose) )
-- 11. npcinfo( 對話的NPC )
-- 12. subViewId( 對話面板id );
-- 13. midShowFunc(gameObject, showEventParam)( 對話界面中間需要建立其他預設時呼叫 );
-- 14. midShowFuncParam( 對話界面建立時呼叫 );
-- 15. forceClickMenu (點選界面不會關閉對話)
function DialogView:UpdateViewData()
self.defaultDialogId = self.viewdata.defaultDialogId;
self.dialoglist = self.viewdata.dialoglist;
self.dialognpcs = self.viewdata.dialognpcs;
self.tasks = self.viewdata.tasks;
self.callback = self.viewdata.callback;
self.callbackData = self.viewdata.callbackData;
self.camera = self.viewdata.camera;
self.wait = self.viewdata.wait;
self.questId = self.viewdata.questId;
self.addconfig = self.viewdata.addconfig;
self.addleft = self.viewdata.addleft;
self.addfunc = self.viewdata.addfunc;
self.subViewId = self.viewdata.subViewId;
self.forceClickMenu = self.viewdata.forceClickMenu;
self.custommenudata = self.viewdata.custommenudata;
local npcinfo = self.viewdata.npcinfo;
if(npcinfo~=nil)then
self.npcguid = npcinfo.data.id;
self.npcdata = npcinfo.data.staticData;
end
self.dialogInfo = {};
self.dialogIndex = 1;
self:UpdateQuestParams();
end
function DialogView:GetCurNpc()
if(self.npcguid)then
return SceneCreatureProxy.FindCreature(self.npcguid);
end
return nil;
end
function DialogView:UpdateQuestParams()
if(self.questId)then
local questdata = QuestProxy.Instance:getQuestDataByIdAndType( self.questId );
if(questdata and questdata.names)then
TableUtility.ArrayShallowCopy(self.questParams, questdata.names);
end
end
end
function DialogView:UpdateShow()
if(self.dialognpcs~=nil and type(self.dialognpcs) == "table")then
for _,id in pairs(self.dialognpcs) do
local npc = NSceneNpcProxy.Instance:FindNearestNpc(Game.Myself:GetPosition(), id);
if(npc~=nil)then
FunctionVisitNpc.Me():NpcTurnToMe(npc)
end
end
end
if(self.dialoglist)then
self:UpdateDialoglst(self.dialoglist);
else
self:UpdateDefaultDialog();
end
end
function DialogView:UpdateDialoglst(dialoglist)
if(#dialoglist>0)then
local dlst = {};
-- 伺服器下發改為讀配置 重新組裝數據結構
for i = 1,#dialoglist do
local dilg, data = dialoglist[i];
if(type(dilg)=="number")then
-- data = Table_Dialog[dilg];
data = DialogUtil.GetDialogData(dilg);
elseif(type(dilg)=="string")then
data = {id = 0, Text = dilg, SubViewId = self.subViewId};
if(self.npcdata)then
data.Speaker = self.npcdata.id;
end
elseif(type(dilg) == "table")then
data = {id = 0, Text = dilg.Text, ViceText = dilg.ViceText};
if(self.npcdata)then
data.Speaker = self.npcdata.id;
end
end
if(data)then
table.insert(dlst, data);
else
errorLog( string.format("%s not config", dialoglist[i]) );
end
end
self.dialogInfo = dlst;
self:UpdateDialog();
else
self:CloseSelf();
end
end
function DialogView:UpdateDefaultDialog()
if(self.npcdata)then
local defaultDialogId = self.defaultDialogId;
if(defaultDialogId == nil)then
defaultDialogId = self.npcdata.DefaultDialog
end
if(defaultDialogId)then
local configs = {};
if(self.npcdata)then
configs = self.npcdata.NpcFunction;
end
-- self.dialogInfo ={ Table_Dialog[defaultDialogId] };
self.dialogInfo ={ DialogUtil.GetDialogData(defaultDialogId) };
self:UpdateDialog(configs, self.tasks);
else
-- 如果npc沒有配置預設對話 並且有任務事件 則新增預設對話
local configs = self.npcdata.NpcFunction;
local tempData = {
id = 1,
Speaker = self.npcdata.id,
Text = '……',
};
self.dialogInfo ={ tempData };
self:UpdateDialog(configs, self.tasks);
end
else
self:CloseSelf();
end
end
-- config 和 tasks 可以不傳
function DialogView:UpdateDialog(config, tasks)
if(#self.dialogInfo>0)then
self.nowDialogData = self.dialogInfo[self.dialogIndex];
if(self.nowDialogData)then
self.dialogCtl:SetData(self.nowDialogData, self.questParams);
if(self.nowDialogData.Option and self.nowDialogData.Option~="")then
local optionConfig = StringUtil.AnalyzeDialogOptionConfig(self.nowDialogData.Option);
if(#optionConfig>0)then
self:UpdateMenu(config,tasks,optionConfig);
end
else
self:UpdateMenu(config,tasks, nil);
end
self:UpdateDialogSubView(self.nowDialogData.SubViewId);
self.menuSprite.enabled = self.nowDialogData.Text ~= "";
else
errorLog("Not Find Dialog");
self:CloseSelf();
end
else
self.nowDialogData = nil;
end
end
function DialogView:UpdateDialogSubView(subId)
if(self.nowSubId)then
self:RemoveSubView(self.nowSubId);
self.nowSubId = nil;
end
if(subId)then
self.nowSubId = subId;
local subPage = SubViewMap.Instance:GetSubView(subId);
local nowSubPage = self:AddSubView(subId, subPage);
nowSubPage:OnEnter(subId, self);
end
end
function DialogView:DialogGoUpdate()
self.dialogend = self.dialogIndex == #self.dialogInfo;
self.dialogIndex = self.dialogIndex+1;
if(self.dialogIndex<=#self.dialogInfo)then
self:UpdateDialog();
else
-- 沒有特定的離開按鈕
if(not self.addleft)then
self:CloseSelf();
end
end
end
local tempArray = {};
function DialogView:UpdateMenu(configs, tasks, option)
if(not self.menuData)then
self.menuData = {};
else
TableUtility.ArrayClear(self.menuData);
end
-- Tasks
if(tasks)then
for i=1,#tasks do
if(tasks[i])then
if(tasks[i].staticData)then
local taskMenuData = Dialog_MenuData.new();
taskMenuData:Set_ByTask(tasks[i]);
table.insert(self.menuData, taskMenuData);
else
errorLog(string.format("Task:%s Not Have StaticData", tasks[i].id));
end
end
end
end
-- Configs
if(configs or self.addconfig)then
TableUtility.ArrayClear(tempArray);
if(configs)then
TableUtility.ArrayShallowCopy(tempArray, configs);
end
if(self.addconfig)then
for i=1,#self.addconfig do
table.insert(tempArray, self.addconfig[i]);
end
end
for i=1,#tempArray do
local typeid, param, name = tempArray[i].type, tempArray[i].param, tempArray[i].name;
local npcfunc_menuData = Dialog_MenuData.new();
npcfunc_menuData:Set_ByNpcFunctionConfig(typeid, param, name, self:GetCurNpc());
table.insert(self.menuData, npcfunc_menuData);
end
end
-- option
if(option)then
for i=1,#option do
local option_menuData = Dialog_MenuData.new();
option_menuData:Set_ByOption(option[i]);
table.insert(self.menuData, option_menuData);
end
end
-- 額外新增的自主功能(func(event, name))
if(self.addfunc)then
for i=1,#self.addfunc do
local addFunc = self.addfunc[i];
if(addFunc.event and addFunc.NameZh)then
local addfunc_menuData = Dialog_MenuData.new();
addfunc_menuData:Set_Name(addFunc.NameZh);
addfunc_menuData:Set_CloseDialogWhenClick(addFunc.closeDialog);
addfunc_menuData:Set_WaitCloseDialogWhenClick(addFunc.waitClose);
addfunc_menuData:Set_CusetomClickCall(addFunc.event, addFunc.eventParam);
table.insert(self.menuData, addfunc_menuData);
end
end
end
if(self.custommenudata)then
for i=1,#self.custommenudata do
table.insert(self.menuData, self.custommenudata[i]);
end
end
if(self.addleft)then
local addleft_menuData = Dialog_MenuData.new();
addleft_menuData:Set_CusetomClickCall();
addleft_menuData:Set_CloseDialogWhenClick(true);
addleft_menuData:Set_Name(ZhString.DialogView_Left);
table.insert(self.menuData, addleft_menuData);
end
self:UpdateMenuCtl();
end
function DialogView:RegisterMenuEvent(btnGO, optionid, needReplace)
if(btnGO == nil or optionid == nil)then
redlog("btnGO or optionid is nil");
return;
end
local menuDataDirty = false;
local optionData;
local m;
for i=#self.menuData,1,-1 do
m = self.menuData[i];
if(m.optionid == optionid)then
optionData = m;
if(needReplace)then
menuDataDirty = true;
table.remove(self.menuData, i)
end
break;
end
end
local func = function ()
if(optionData == nil)then
self:CloseSelf();
else
self:DoMenuEvent(optionData);
end
end
self:AddClickEvent( btnGO, func);
if(menuDataDirty)then
self:UpdateMenuCtl();
end
end
function DialogView:UpdateMenuCtl(menuData)
menuData = menuData or self.menuData;
if(#menuData>0)then
local realCount = #menuData;
for i=#menuData,1,-1 do
local mData = menuData[i];
if(mData and mData.state == NpcFuncState.InActive)then
realCount = realCount - 1;
end
end
realCount = math.max(0, realCount);
if(realCount > 0)then
self.menu:SetActive(true);
self.menuSprite.height = 60 + realCount * 70;
else
self.menu:SetActive(false);
end
self.menuCtl:ResetDatas(menuData);
self.menuCtl.layoutCtrl.repositionNow = true;
else
self.menu:SetActive(false);
end
end
function DialogView:ClickMenuEvent(cellCtl)
local cellData = cellCtl.data;
if(not cellData)then
return;
end
self:DoMenuEvent(cellData);
end
function DialogView:DoMenuEvent(cellData)
local menuType = cellData.menuType;
local npcinfo = self:GetCurNpc();
if(menuType == Dialog_MenuData_Type.NpcFunc)then
self.dialogend = true;
local stay = FunctionNpcFunc.Me():DoNpcFunc( cellData.npcFuncData, npcinfo, cellData.param )
if(not stay)then
DialogView.super.CloseSelf(self);
end
elseif(menuType == Dialog_MenuData_Type.Option)then
self.optionid = cellData.optionid;
if(self.optionid == 0)then
self:DialogGoUpdate();
else
self.dialogend = true;
-- self.optionWait = 0.2;
self:CloseSelf();
end
elseif(menuType == Dialog_MenuData_Type.Task)then
if(cellData.task)then
if(self.callback)then
self.callback(cellData.task.id, self.optionid);
end
FunctionVisitNpc.Me():ExcuteQuestEvent(npcinfo, cellData.task);
end
elseif(menuType == Dialog_MenuData_Type.CustomFunc)then
if(cellData.closeDialog == true)then
if(cellData.waitClose ~= nil)then
self.optionWait = cellData.waitClose;
end
self:CloseSelf();
end
-- custom event excute after close(if need)
if(cellData.clickCall)then
local stay = cellData.clickCall(self:GetCurNpc(), cellData.clickCallParam);
if(cellData.closeDialog ~= true and stay == false)then
self:CloseSelf();
end
end
end
end
function DialogView:MapEvent()
self:AddListenEvt(SceneGlobalEvent.Map2DChanged, self.HandleUpdateMap2d)
self:AddListenEvt(DialogEvent.AddMenuEvent, self.HandleAddMenuEvent);
self:AddListenEvt(ServiceEvent.NUserRequireNpcFuncUserCmd, self.HandleRequireNpcFuncUserCmd);
self:AddListenEvt(SceneUserEvent.SceneRemoveNpcs, self.HandleRemoveNpcs);
self:AddListenEvt(DialogEvent.NpcFuncStateChange, self.HandleNpcFuncStateChange);
self:AddListenEvt(DialogEvent.AddUpdateSetTextCall, self.HandleAddUpdateSetTextCall);
self:AddListenEvt(ServiceUserProxy.RecvLogin, self.HandleRecvLogin);
self:AddListenEvt(CarrierEvent.MyCarrierStart, self.CloseSelf);
end
function DialogView:HandleRecvLogin(note)
self:CloseSelf();
end
function DialogView:HandleAddUpdateSetTextCall(note)
self.dialogCtl:Set_UpdateSetTextCall(note.body[1], note.body[2]);
end
function DialogView:HandleNpcFuncStateChange(note)
local changeFuncs = note.body;
-- self.menuData
for i=1,#changeFuncs do
local cache = changeFuncs[i];
local menuData,index;
for j=#self.menuData,1,-1 do
if(self.menuData[j].key == cache.key)then
menuData = self.menuData[j];
index = j;
break;
end
end
menuData:Set_State(cache.state);
end
self:UpdateMenuCtl();
end
function DialogView:HandleRemoveNpcs(note)
local npcs = note.body
if(npcs and #npcs>0)then
for i=1,#npcs do
if(self.npcguid == npcs[i])then
self:CloseSelf();
end
end
end
end
function DialogView:HandleUpdateMap2d(note)
local npcinfo = self:GetCurNpc();
if(npcinfo)then
local npc = FunctionVisitNpc.Me():GetTarget()
if(npc ~= npcinfo)then
DialogView.super.CloseSelf(self);
end
end
end
function DialogView:HandleAddMenuEvent(note)
local config = note.body;
if(config == nil)then
return;
end
local npcinfo = self:GetCurNpc();
local dialog_menuData = Dialog_MenuData.new();
dialog_menuData:Set_ByNpcFunctionConfig(config.type, config.param, config.name, npcinfo);
table.insert(self.menuData, 1, dialog_menuData);
self:UpdateMenuCtl();
end
function DialogView:HandleRequireNpcFuncUserCmd(note)
local data = note.body;
local npcinfo = self:GetCurNpc();
if(data == nil or npcinfo == nil )then
return;
end
local requireFunctions = npcinfo.data.staticData.RequireNpcFunction;
local functions = data.functions;
if(functions)then
for i=1,#functions do
local config = StringUtil.Json2Lua(functions[i]);
if(type(config) == "table")then
local dialog_menuData = Dialog_MenuData.new();
dialog_menuData:Set_ByNpcFunctionConfig(config.type, config.param, config.name, npcinfo);
table.insert(self.menuData, 1, dialog_menuData);
end
end
self:UpdateMenuCtl();
end
end
function DialogView:RemoveLeanTween()
if(self.lt)then
self.lt:cancel();
end
self.lt = nil;
end
-- 退出是否需要等待
function DialogView:CloseSelf()
if(self.dialogend and self.callback~=nil)then
self.callback(self.callbackData, self.optionid, true);
self.callback = nil;
self.callbackData = nil;
end
self.gameObject:SetActive(false);
local wait = self.wait or self.optionWait or 0;
if(wait > 0)then
self:RemoveLeanTween();
self.lt = LeanTween.delayedCall(wait, function ()
DialogView.super.CloseSelf(self);
end);
else
DialogView.super.CloseSelf(self);
end
end
function DialogView:OnExit()
-- 結束訪問
self.super.OnExit(self);
FunctionVisitNpc.Me():RemoveVisitRef();
FunctionNpcFunc.Me():ClearUpdateCheck();
if(self.callback~=nil)then
self.callback(self.callbackData, nil, false);
self.callback = nil;
self.callbackData = nil;
end
if(type(self.midHideFunc) == "function")then
self.midHideFunc();
self.midHideFunc = nil;
end
self.dialogCtl:OnExit();
self:CameraReset();
self:RemoveLeanTween();
if(self.dialognpcs~=nil and type(self.dialognpcs) == "table")then
for _,id in pairs(self.dialognpcs) do
local npc = NSceneNpcProxy.Instance:FindNearestNpc(Game.Myself:GetPosition(), id);
if(npc~=nil)then
FunctionVisitNpc.Me():NpcTurnBack(npc)
end
end
end
end