《永生》生活技能系统
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中,客户端也是如此。