《永生》生活技能系統
1 生活功能掛接
MonsterAttribute.tab中 :生活技能學習配置:1|2 啦,即:
54 葵月 1 -1 1|14|15|16|17 1|14|15|16|17 0|1|10 1|2
2 客戶端點擊NPC
à Client:
UBI_CCSDefaultDialogPacket
à Server:
CSDefaultDialogHandler -> 調用腳本
--sceneId表示場景號, selfid玩家,targetId爲NPC
function x000001_OnDefaultEvent( sceneId, selfHighId, selfLowId,targeHighId, targeLowId)
BeginAddEvent(sceneId)
AddEvent( sceneId, -1, 2, string4)
AddEvent( sceneId, -1, 13, string5)
EndAddEvent(sceneId)
DispatchEventList(sceneId, selfHighId, selfLowId, targeHighId, targeLowId )
return1
end
通過讀MonsterAttribute.tab中配置的生活技能學習配置(1|2),
之後檢索表:DTT_LIFE_SKILL_LEARN, //生活技能學習表LifeSkillLearn.tab
生活技能商店ID 生活技能商店名稱
INT STRING
1 學習採礦
2 學習鍛造
NPC_EVENT npcEvent;
npcEvent.m_NpcEventType = NPC_EVENT_LIFE_SKILL;
npcEvent.m_nID = 1 | 2;
npcEvent.m_Name = 學習採礦 | 學習鍛造;
其中DispatchEventList中又會發包:SCNPCEventListPacket
à Client:
顯示對話框上的列表選項:
//NPC一級對話事件列表
UBI_VOID WINAPIUBI_CPacketExecute::SCNPCEventListExecute(UBI_CPacket* pPacket)
{
pNPCDialogData->SetNPCGuid(pSCNPCEventListPacket->GetNPCGUID().m_ullValue);
pNPCDialogData->SetDialogTipID(pSCNPCEventListPacket->GetDialogTipID());
for(UBI_INTi=0; i<pSCNPCEventListPacket->GetEventListCount(); i++)
{
pNPCDialogData->SetEventList(pSCNPCEventListPacket->GetNPCEvent(i),i);
}
}
這樣就保存在了NPC_EVENT NpcDialogData::m_EventList[MAX_NPCEVENTLIST_ COUNT]事件列表中,之後顯示界面:pNPCDialogData->OpenNPCDialogInterface();
函數裏面做:
local nEventCount =NPCDialogData:GetDialogEventCount();
if(nEventCount > 0) then
NPCDialog_Event_Count = nEventCount
for i = 0, nEventCount-1 do
local strname, eventtype, nStatus = NPCDialogData:GetDialogEvent(i);
if(strname ~=nil) then NPCDialog_ComplexWindow_Main:AddOptionElement(strname,"1",tostring(i), tostring(nStatus));
end
end
end
這裏的:UBI_ComplexWindow::L_AddOptionElement中調用:
CEGUI::CEGUIComplexWindow* pWindow =static_cast<CEGUI::CEGUIComplexWindow*> (m_pWindow);
pWindow->AddChildElement_Option(strOut0,strOut1,strOut2,strOut3);
CEGUIComplexWindow::AddChildElement_Option中又調用:
_snprintf(szTempName, 32,"__option__%02d#%d,%d", nIndex, atoi(strExtra1.c_str()), atoi(strExtra2.c_str()));
%2d位置上對應:option按鈕的編號
%d,%d位置上分別對應:"1", tostring(i) //i是DialogEvent序號(0,1....17)
//第一步:註冊事件
pNewChild->d_Button->subscribeEvent(PushButton::EventClicked,Event::Subscriber(&CEGUIComplexWindow::handleOptionClicked, this));
//第二步:事件的觸發與響應
boolCEGUIComplexWindow::handleOptionClicked(const EventArgs& e)
{
WindowEventArgs arg( ((const WindowEventArgs&) e).window);
fireEvent(EventOptionClicked,arg, EventNamespace); //觸發
//這裏CEGUIComplexWindow::EventOptionClicked就是:((utf8*)"OptionClicked" );
}
而在XML配置如下:
<WindowType="SH_ComplexWindow" Name="NPCDialog_ComplexWindow_Main">
<PropertyName="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
<PropertyName="UnifiedAreaRect" Value="{{0.0783644,0},{0.157161,0}, {0.920033,0}, {0.891289,0}}" />
<Event Name="OptionClicked"Function="NPCDialogOptionClicked()"/>
而fireEvent內部會執行:
bool ScriptFunctor::operator()(constEventArgs& e) const
{
ScriptModule*scriptModule = System::getSingleton().getScriptingModule();
if (scriptModule)
{return scriptModule->executeScriptedEventHandler(scriptFunctionName, e); }
}
就會執行:UBI_UI_ScriptModule::executeScriptedEventHandler(),
其內部會調用:UBI_LayoutWnd::DoUIEvent,即執行:
UBI_ScriptSystem::GetSingleton().GetLuaState()->GetGlobals().SetString
("param0",pWindow->getName().c_str());
m_pScriptEnv->DoString(szEventHandle);
即:先設置全局變量“param0”的值,之後執行響應函數,即執行NPCDialogOptionClicked()。
3 客戶端點擊按鈕選項
àClient:
這樣,點擊對話框上的按鈕,就會執行NPCDialogOptionClicked()。
此函數中要判斷點擊的是列表中的哪個按鈕,解析param0即可
local clickedname = param0;
local pos1, pos2 =string.find(clickedname, "#");
local pos3, pos4 =string.find(clickedname, ",");
strType =tonumber(string.sub(clickedname, pos2+1, pos3-1 ));
strIndex =tonumber(string.sub(clickedname, pos4+1));
得到的strIndex即是npcEvent序號,注意不是npcEvent.m_nID。
NPCDialogData:ClickEventButton(strIndex,0);
函數內部執行:
UBI_CNPCDialogData::ClickEventButton()
{
//得到腳本參數
UBI_INT nPosition = args[2].GetInteger();
UBI_SHORT nNPCDialogType =args[3].GetInteger();
客戶端如果點擊的按鈕是:關於“生活技能”的,那麼執行:
switch(m_EventList[nPosition].m_NpcEventType)
{
//生活技能
case NPC_EVENT_LIFE_SKILL:
{
UBI_CCSAskNpcEventInfoPacketpacket;
packet.SetTargetGUID(UBI_GUID(pNPCObject->GetGuid()));
packet.SetNpcEventType((UBI_CHAR)m_EventList[nPosition].m_NpcEventType);
packet.SetNpcEventID(m_EventList[nPosition].m_nID);
SendPacket(&packet);
}
break;
}
à Server:
//感覺沒啥用,因爲這些信息都是Client發過來的,怎麼又發了回去?
服務器會判斷客戶端點擊的是哪個NPC的身上的哪個event。
UBI_CPacketHandler::CSAskNpcEventInfoHandler()
{
switch(pAskNpcEventInfoPacket->GetNpcEventType())
{
caseNPC_EVENT_LIFE_SKILL: //生活技能
{
UBI_CSCNpcEventInfoPacketNpcEventInfoPacket;
NpcEventInfoPacket.SetNPCGUID(npcGuid);
NpcEventInfoPacket.SetEventType(pAskNpcEventInfoPacket ->GetNpcEventType());
//UBI_CSCNpcEventInfoPacket內沒有ID,所以通過AddEvent來傳遞技能學習ID
NPCEVENT_INFOnpcEvent;
npcEvent.m_nID= pAskNpcEventInfoPacket->GetNpcEventID();
NpcEventInfoPacket.AddEvent(npcEvent);
pObjectHuman->SendStackPacket(&NpcEventInfoPacket);
break;
}
}
}
4 顯示二級對話框、點擊“學習”
à Client:
//接下來就顯示NPC二級對話事件列表
UBI_CPacketExecute::SCNpcEventInfoExecute(UBI_CPacket*pPacket)
{
switch((NPC_EVENT_TYPE)pSCNpcEventInfoPacket->GetEventType())
{
// 生活技能學習
caseNPC_EVENT_LIFE_SKILL:
{
//獲取技能學習數據
UBI_CLearnLifeSkillData*pLearnLifeSkillData = pDataPoolManager->GetLearnLifeSkillData();
if (UBI_NULL ==pLearnLifeSkillData)
{
return;
}
NPCEVENT_INFO* pInfo= pSCNpcEventInfoPacket->GetEvent(0);
if (UBI_NULL == pInfo)
{
return;
}
讀取表格LifeSkillLearn.tab中的第pInfo->m_nID號對應行的生活技能學習數據,然後
pLearnLifeSkillData->Update(pInfo->m_nID);
(1) 讀取第1頁對應的生活技能,放到:vector<UBI_INT>m_SkillIDs中,
(2) 讀取第1頁對應的配方,放到:vector<UBI_INT> m_PatternIDs中。
界面顯示,
pLearnLifeSkillData->Show();
之後根據m_SkillIDs中的技能ID,去表LifeSkill.tab中查找技能名稱,加載ListBox某行上(對應技能數組索引);
根據m_PatternIDs中的配方ID,去表LifeSkillPattern.tab中查找配方名稱,加載ListBox+5000行上(對應配方數組索引+5000);
這樣,當選擇列表框時候,選擇“習得”,就能根據別選擇列表的索引,進而得到ID。【LearnLifeSkillData:GetPatternID(patternIndex);】
之後給服務器發學習包:
(1) UBI_CCSLearnLifeSkillPacketpacket;
packet.SetSkillID(skillID);
packet.SetPatternID(-1);
(2) UBI_CCSLearnLifeSkillPacketpacket;
packet.SetSkillID(-1);
packet.SetPatternID(patternID);
}
}
}
à Server:
學習配方LearnLifeSkillPattern時候,先得到對應的需求技能ID及其等級,
判斷HasLearnedLifeSkill(requireSkillID)技能以及GetLifeSkillLevel(requireSkillID)技能等級。
學會的生活技能、配方等保存在m_LifeSkills中,客戶端也是如此。