HisaoShou 3 Posted March 24, 2019 Share Posted March 24, 2019 Hello everyone. I'm currently facing an issue where I want to make a certain system / icon visible only if a variable (which was declared and changed via quest) has a certain value. I want the client to check the value of the variable for the quest, and the client to update automatically as the variable is set to a certain value. Can this be done? I have looked into an older topic related to this issue: [HowTo|Old]Quest-Client communication(for any version) , but it didn't help really much. I'm still not sure how to check this. Can someone help me please? I'm pretty dumb when comes to client communication Link to comment Share on other sites More sharing options...
HisaoShou 3 Posted March 27, 2019 Author Share Posted March 27, 2019 Bump. Link to comment Share on other sites More sharing options...
HisaoShou 3 Posted March 31, 2019 Author Share Posted March 31, 2019 Bump. Link to comment Share on other sites More sharing options...
OtherChoice 77 Posted March 31, 2019 Share Posted March 31, 2019 each quest function, including questflags and globalflags, its called by the quest itself(lua) but is handled on game server and its declaration its c++ code. What you could do is adding a new function in client binary to pythonnetworkmodule so your py files can call this function which sends a request packet (HEADER_CG) to game server which performs any check you want on said flags and sends the response back to client (HEADER_GC), then you could have a BINARY_CALLBACK (game.py function accessible by client binary) which performs your desired python function. Hope it was clear, if not just tell me which part isn't clear and i'll make some example code as i get back home. 2 Link to comment Share on other sites More sharing options...
HisaoShou 3 Posted March 31, 2019 Author Share Posted March 31, 2019 Acum 5 ore, OtherChoice a spus: each quest function, including questflags and globalflags, its called by the quest itself(lua) but is handled on game server and its declaration its c++ code. What you could do is adding a new function in client binary to pythonnetworkmodule so your py files can call this function which sends a request packet (HEADER_CG) to game server which performs any check you want on said flags and sends the response back to client (HEADER_GC), then you could have a BINARY_CALLBACK (game.py function accessible by client binary) which performs your desired python function. Hope it was clear, if not just tell me which part isn't clear and i'll make some example code as i get back home. Thank you for your answer, it made me understand a little how this works. What I want to do is only quest - client related. For example I want an UI button to be displayed only if the variable declared by quest has a certain value. Do you think this is possible only with python(client) and quest(lua) ? I would really appreciate an example if you have one. Something like, if you could make a present game button (e.g.: Inventory Button from the bottom bar) be displayed only when quest variable is 1 that would be the easiest i think. I'm sorry for asking for this, I'm not good at it. Link to comment Share on other sites More sharing options...
OtherChoice 77 Posted April 1, 2019 Share Posted April 1, 2019 22 hours ago, HisaoShou said: Thank you for your answer, it made me understand a little how this works. What I want to do is only quest - client related. For example I want an UI button to be displayed only if the variable declared by quest has a certain value. Do you think this is possible only with python(client) and quest(lua) ? I would really appreciate an example if you have one. Something like, if you could make a present game button (e.g.: Inventory Button from the bottom bar) be displayed only when quest variable is 1 that would be the easiest i think. I'm sorry for asking for this, I'm not good at it. It's not possible to have only python and quest in this system since python will access game variables only through python modules inside client binary, i'll send you an example in a few minutes Link to comment Share on other sites More sharing options...
Solution OtherChoice 77 Posted April 1, 2019 Solution Share Posted April 1, 2019 Packet.h (both client and server source) add where HEADER(s) are declared HEADER_GC_FLAG_RESPONSE = 156, //any number still not used HEADER_CG_FLAG_REQUEST = 157, // same here add where struct(s) are declared typedef struct packet_flag_response { BYTE header; char* FlagName; } TPacketCGFlagRequest; typedef struct packet_flag_response { BYTE header; DWORD dwFlag; } TPacketGCFlagResponse; PythonNetworkStreamPhaseGame.cpp (client binary) In function GamePhase() add below other cases: case HEADER_GC_FLAG_RESPONSE: ret = RecvFlagResponsePacket(); break; Then add 2 new bools: bool CPythonNetworkStream::SendFlagRequestPacket(char* flag) { TPacketCGFlagRequest pPack; pPack.header = HEADER_CG_FLAG_REQUEST; pPack.FlagName = flag; if (!Send(sizeof(ItemInfoLoadPacket), &ItemInfoLoadPacket)) return false; return SendSequence(); } bool CPythonNetworkStream::RecvFlagResponsePacket(){ TPacketGCFlagResponse pPack; if (!Recv(sizeof(TPacketGCFLagResponse), &pPack)) return false; DWORD flag = pPack.dwFlag; CInstanceBase * pInstPlayer = CPythonCharacterManager::Instance().GetMainInstancePtr(); if (pInstPlayer) { PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "BINARY_AddFlagValue", Py_BuildValue("(i)", flag)); } return true; } In PythonNetworkStream.h add the definition of the previous function (client binary) after bool RecvPartyParameter(); add bool RecvFlagResponsePacket(); In PythonNetworkStreamModule.cpp add: PyObject* netFlagRequest(PyObject* poSelf, PyObject* poArgs) { char* flag; if (!PyTuple_GetString(poArgs, 0, &flag)) { return Py_BuildException(); } CPythonNetworkStream& rns = CPythonNetworkStream::Instance(); rns.SendFlagRequestPacket(flag); return Py_BuildNone(); } then in void initnet() add { "SendFlagRequest", netSendFlagRequest, METH_VARARGS }, that's client binary example now we move on game server Packet.h edited as above input_main.cpp case HEADER_CG_FLAG_REQUEST: { FlagRequest(ch, c_pData); } break; then add a new void (and of course its definition in input_main.h) void CInputMain::FlagRequest(LPCHARACTER ch, const char* c_pData) { TPacketCGFlagRequest pRequest = (TPacketCGFlagRequest*)c_pData; TPacketGCFLagResponse pResponse; pResponse.header = HEADER_GC_FLAG_RESPONSE; pResponse.flag = ch->GetQuestFlag(pRequest.FlagName); ch->GetDesc()->Packet(&pResponse, sizeof(TPacketGCFlagResponse)); } packet_info.cpp in CPacketInfoCG::CPacketInfoCG() add Set(HEADER_CG_ITEM_INFO_LOAD, sizeof(TPacketCGItemInfoLoad), "ItemInfoLoad", true); and we're done server side, now there's only python part left and since i do not know your code i'll make a very simple example: in game.py add def BINARY_AddFlagValue(self, flag): if flag == YOUR_VALUE: #do something like self.YourButton.Show() if self.YourButton is part of game.py else if your element is part of another python file we call uiexample.py which gets initialized in game.py like self.myexample = uiexample.ExampleClass() do self.myexample.YourButton.Show() or self.myexample.MyCustomFunction() which handles visibility of the button #INVENTORY BUTTON EXAMPLE: self.interface.ShowInventoryButton() #then in interfacemodule.py in class interface add def ShowInvetoryButton(self): self.wndTaskBar.GetChild("InventoryButton").Show() Spoiler now to have the whole process start we need to call net.SendFlagRequest("flagname") but with the current example we need to constatly know when the flag changes so the best way to avoid a whole bunch of server traffic is to have the server tell the cilent when to call net.SendFlagRequest("flagname") and we just need to add a check inside CHARACTER::SetQuestFlag(const std::string& flag, int value) (game/char.cpp) and when our check flag == interestedflag is true as we did above we add a new packet struct, header, and client handle (we only need game to client so just HEADER_GC) which gets sent. When Client recives this packet it will call our function SendFlagRequestPacket(char* flag) and the process will start. Notice that with the example of interface button and new packet (game -> to -> client only) there were no need to call net.SendFlagRequest("flagname") from python but directly from binary SendFlagRequestPacket(char* flag), THIS IS NOT ALWAYS TRUE, you might find yourself using both calls upon different situation. MOREOVER the whole example purpose is not to have a quick and clean code but to understand how things work so yeah, we could have skipped a whole part and have it straight handled by game source (eg. in SetQuestFlag instead of calling our new packet that will make the whole process start, we simply have our FLAG == YOUR_VALUE check here and on successful check we send our response packet back to client and it will call game.py BINARY_SetFlagValue which handles the visibility of the button. As I said its way shorter and better but these way you have access to a better code blueprint in my opinion) It should be complete, I could have missed a declaration or something since i coded it without source by hand so if any problem just show your errors. Hope I helped! P.S. As you might have noticed i totally skipped lua part since its function pc.getqf is c++ code and its definition is CHARACTER::GetQuestFlag so no need to change anything on lua, just do your quest, use pc.setqf and you will be able to access just calling in game source ch->GetQuestFlag(flagname) 1 Link to comment Share on other sites More sharing options...
HisaoShou 3 Posted April 8, 2019 Author Share Posted April 8, 2019 Thank you very much about your answer! It was really helpful. Thank you also for your time spent explaining all these to me, thanks! Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now