Honorable Member xP3NG3Rx 19679 Posted April 18, 2020 Honorable Member Share Posted April 18, 2020 Yo! Yesterday I have noticed that webzen changed the CPythonMiniMap::__LoadAtlasMarkInfo function whiches basically load all the positions of the npcs, warp portals onto the atlaswindow. I don't know they stopped sending the HEADER_GC_NPC_POSITION packet on every single login or not, but it seems with this code and the files from the official locale all the maps have the complete npc position info. My opinion about this that it's not needed to send this packet after every single login/warp. So I reversed this small modification, which is a bit different then the old one. This is how the old position info looks like: #TokenIndex Type PosX PosY ToolTipText 0 WARP 140900 13900 "ąÚ¶óÇö" And this is the new one: #TokenIndex PosX PosY NPCVnum 0 44100 3300 20081 Here is the modified function: Spoiler void CPythonMiniMap::__LoadAtlasMarkInfo() { ClearAtlasMarkInfo(); ClearGuildArea(); CPythonBackground& rkBG=CPythonBackground::Instance(); if (!rkBG.IsMapOutdoor()) return; CMapOutdoor& rkMap=rkBG.GetMapOutdoorRef(); // LOCALE char szAtlasMarkInfoFileName[64+1]; _snprintf(szAtlasMarkInfoFileName, sizeof(szAtlasMarkInfoFileName), "%s/map/%s_point.txt", LocaleService_GetLocalePath(), rkMap.GetName().c_str()); // END_OF_LOCALE CTokenVectorMap stTokenVectorMap; if (!LoadMultipleTextData(szAtlasMarkInfoFileName, stTokenVectorMap)) { Tracef(" CPythonMiniMap::__LoadAtlasMarkInfo File Load %s ERROR\n", szAtlasMarkInfoFileName); return; } #ifndef ENABLE_GF_ATLAS_MARK_INFO const std::string strType[TYPE_COUNT] = { "OPC", "OPCPVP", "OPCPVPSELF", "NPC", "MONSTER", "WARP", "WAYPOINT" }; #endif for (DWORD i = 0; i < stTokenVectorMap.size(); ++i) { char szMarkInfoName[32+1]; _snprintf(szMarkInfoName, sizeof(szMarkInfoName), "%lu", i); if (stTokenVectorMap.end() == stTokenVectorMap.find(szMarkInfoName)) continue; const CTokenVector & rVector = stTokenVectorMap[szMarkInfoName]; #ifdef ENABLE_GF_ATLAS_MARK_INFO const std::string& c_rstrPositionX = rVector[0].c_str(); const std::string& c_rstrPositionY = rVector[1].c_str(); const std::string& c_rstrVnum = rVector[2].c_str(); const DWORD c_dwVnum = atoi(c_rstrVnum.c_str()); const CPythonNonPlayer::TMobTable* c_pMobTable = CPythonNonPlayer::Instance().GetTable(c_dwVnum); if (c_pMobTable) { TAtlasMarkInfo aAtlasMarkInfo; aAtlasMarkInfo.m_fX = atof(c_rstrPositionX.c_str()); aAtlasMarkInfo.m_fY = atof(c_rstrPositionY.c_str()); aAtlasMarkInfo.m_strText = c_pMobTable->szLocaleName; if (c_pMobTable->bType == CActorInstance::TYPE_NPC) aAtlasMarkInfo.m_byType = TYPE_NPC; else if (c_pMobTable->bType == CActorInstance::TYPE_WARP) { aAtlasMarkInfo.m_byType = TYPE_WARP; int iPos = aAtlasMarkInfo.m_strText.find(" "); if (iPos >= 0) aAtlasMarkInfo.m_strText[iPos] = 0; } else if (c_pMobTable->bType == CActorInstance::TYPE_STONE && c_dwVnum >= 20702 && c_dwVnum <= 20706) aAtlasMarkInfo.m_byType = TYPE_NPC; aAtlasMarkInfo.m_fScreenX = aAtlasMarkInfo.m_fX / m_fAtlasMaxX * m_fAtlasImageSizeX - (float)m_WhiteMark.GetWidth() / 2.0f; aAtlasMarkInfo.m_fScreenY = aAtlasMarkInfo.m_fY / m_fAtlasMaxY * m_fAtlasImageSizeY - (float)m_WhiteMark.GetHeight() / 2.0f; switch (aAtlasMarkInfo.m_byType) { case TYPE_NPC: m_AtlasNPCInfoVector.push_back(aAtlasMarkInfo); break; case TYPE_WARP: m_AtlasWarpInfoVector.push_back(aAtlasMarkInfo); break; } } #else const std::string & c_rstrType = rVector[0].c_str(); const std::string & c_rstrPositionX = rVector[1].c_str(); const std::string & c_rstrPositionY = rVector[2].c_str(); const std::string & c_rstrText = rVector[3].c_str(); TAtlasMarkInfo aAtlasMarkInfo; //memset(&aAtlasMarkInfo, 0, sizeof(aAtlasMarkInfo)); for ( int i = 0; i < TYPE_COUNT; ++i) { if (0 == c_rstrType.compare(strType[i])) aAtlasMarkInfo.m_byType = (BYTE)i; } aAtlasMarkInfo.m_fX = atof(c_rstrPositionX.c_str()); aAtlasMarkInfo.m_fY = atof(c_rstrPositionY.c_str()); aAtlasMarkInfo.m_strText = c_rstrText; aAtlasMarkInfo.m_fScreenX = aAtlasMarkInfo.m_fX / m_fAtlasMaxX * m_fAtlasImageSizeX - (float)m_WhiteMark.GetWidth() / 2.0f; aAtlasMarkInfo.m_fScreenY = aAtlasMarkInfo.m_fY / m_fAtlasMaxY * m_fAtlasImageSizeY - (float)m_WhiteMark.GetHeight() / 2.0f; switch(aAtlasMarkInfo.m_byType) { case TYPE_NPC: m_AtlasNPCInfoVector.push_back(aAtlasMarkInfo); break; case TYPE_WARP: m_AtlasWarpInfoVector.push_back(aAtlasMarkInfo); break; } #endif } } Don't forget to include the PythonNonPlayer.h, if you don't have it. Some facts what good to know about this: This code does nothing until the RecvNPCList runs down, because when the packet arrives into the client, it clears the loaded vectors what was loaded from the txt files. Just in that case do remove the packet, if you know what you are doing, and 101% sure about it... Without the packet the server will not take care about your atlaswindow anymore, so you have to take care about it by yourself, if you place a new NPC/Warp portal on a map, you have to add it into the text file of the map at clientside. (Easy to write a script which iterates all over the map folder and collect these entries.) I don't provide guide/help how to remove the HEADER_GC_NPC_POSITION packet, it's very basic.. 2 15 Link to comment Share on other sites More sharing options...
Honorable Member Owsap 8175 Posted April 18, 2020 Honorable Member Share Posted April 18, 2020 I think this was a move they made for their multi language system since the packet sends the name from the server directly to the binary without any translation, with this method they can get the locale name based on the vnum, just my guess and the best way to handle it. 1 1 https://owsap.dev/ / https://osf.owsap.dev/ Link to comment Share on other sites More sharing options...
Recommended Posts