Jump to content

PetePeter

Member
  • Posts

    106
  • Joined

  • Last visited

  • Feedback

    0%

Everything posted by PetePeter

  1. Your problem is about the item_proto part for the item problems. For the page, check the uiscript part for the inventory. Some files use another python file than the default one (Exemple: inventorywindow.py / inventorywindowex.py) Check in the uiinventory.py file from root where the uiscript file is located (The function LoadScriptFile)
  2. This is enough p.bHPPercent = MINMAX(0, static_cast<int64_t>(static_cast<int64_t>(m_pkChrTarget->GetHP()) * 100) / static_cast<int64_t>(m_pkChrTarget->GetMaxHP()), 100);
  3. I'm sure it's work for you because as I see you used a clean base which is not my case so I guess something doing conflict
  4. Thanks @UdvAtt108 your way not work but you give me a good hint to know where to check ! I will update the topic if I find out
  5. This function is only called for GameMaster, so if someone edit your client to activate it I think he can do what ever he want anyway if you follow my logic
  6. Hello everyone, I would like to know if someone know the simpliest way to setting up an effect client side always visible ? To explain a bit I want to display an effect only clientside (Based on the metin detector code) for a player on a map. I'm using a trick to spawn an invisible NPC and spawn the effect at his position but if i'm not looking directly at the "invisible npc" the effect is not displayed. I'm using the GameForge effect: Here is the code: else if (!strcmpi(szCmd, "ShowZone")) { if (4 != TokenVector.size()) { TraceError("CPythonNetworkStream::ServerCommand(c_szCommand=%s) - Strange Parameter Count : %d", c_szCommand, TokenVector.size()); return; } DWORD dwVID = atoi(TokenVector[1].c_str()); BYTE bType = atoi(TokenVector[2].c_str()); float iSize = static_cast<float>(atof(TokenVector[3].c_str())); IAbstractCharacterManager& rkChrMgr = IAbstractCharacterManager::GetSingleton(); CInstanceBase* pInstance = rkChrMgr.GetInstancePtr(dwVID); if (!pInstance) { TraceError("CPythonNetworkStream::ServerCommand(c_szCommand=%s) - Not Exist Instance", c_szCommand); return; } pInstance->SetAlwaysRender(true); TPixelPosition PixelPosition; D3DXVECTOR3 v3Rotation(0.0f, 0.0f, 0.0f); D3DXVECTOR3 v3Scale(iSize, iSize, iSize); pInstance->NEW_GetPixelPosition(&PixelPosition); PixelPosition.y *= -1.0f; //PixelPosition.z -= 30.0f; switch (bType) { case 1: { CEffectManager::Instance().RegisterEffect("d:/ymir work/effect/battleroyale/battley_01.mse", true); CEffectManager::Instance().CreateEffect("d:/ymir work/effect/battleroyale/battley_01.mse", PixelPosition, v3Rotation, iSize); } break; case 2: { CEffectManager::Instance().RegisterEffect("d:/ymir work/effect/battleroyale/battley_01_64.mse", true); CEffectManager::Instance().CreateEffect("d:/ymir work/effect/battleroyale/battley_01_64.mse", PixelPosition, v3Rotation, iSize); } break; case 3: { CEffectManager::Instance().RegisterEffect("d:/ymir work/effect/battleroyale/battley_02_sphere.mse", true); CEffectManager::Instance().CreateEffect("d:/ymir work/effect/battleroyale/battley_02_sphere.mse", PixelPosition, v3Rotation, iSize); } break; } } Or what is the best way to display this effect at a given position and setting it always visible ? Thanks in advance
  7. It's mean the error come from range vnum, maybe the feature is disable or maybe your are using sql instead of txt. But i bet it's a problem with this function
  8. There is no item 110000 on your item_proto that's what the error say
  9. My bad you are right, I took the python part from the 2018 root and this is the "official" function so I admited than there is no existing function who read the skillPower so they created a new one.
  10. That's not correct, "skillPower" use the value of "player.GetSkillCurrentEfficientPercentage". The real fix is to use "skill.GetSkillPowerByLevel" as the server side do. ## uiTooltip.py def AppendPartySkillData(self, skillGrade, skillLevel): # @fixme008 BEGIN def comma_fix(vl): return vl.replace("%,0f", "%.0f") # @fixme008 END if 1 == skillGrade: skillLevel += 19 elif 2 == skillGrade: skillLevel += 29 elif 3 == skillGrade: skillLevel = 40 if skillLevel <= 0: return skillIndex = player.SKILL_INDEX_TONGSOL slotIndex = player.GetSkillSlotIndex(skillIndex) skillPower = player.GetSkillCurrentEfficientPercentage(slotIndex) if localeInfo.IsBRAZIL(): k = skillPower else: # k = player.GetSkillLevel(skillIndex) / 100.0 k = float( skill.GetSkillPowerByLevel(skillLevel) ) /100 self.AppendSpace(5) self.AutoAppendTextLine(localeInfo.TOOLTIP_PARTY_SKILL_LEVEL % skillLevel, self.NORMAL_COLOR) bonusPercent = 0 # @fixme008 BEGIN if skillLevel>=10: self.AutoAppendTextLine(localeInfo.PARTY_SKILL_ATTACKER % int(10 + 60 * k ) ) bonusPercent = 5 if skillLevel>=20: self.AutoAppendTextLine(localeInfo.PARTY_SKILL_BERSERKER % int(1 + 5 * k)) self.AutoAppendTextLine(localeInfo.PARTY_SKILL_TANKER % int(50 + 1450 * k)) bonusPercent = 10 if skillLevel>=25: self.AutoAppendTextLine(localeInfo.PARTY_SKILL_BUFFER % int(5 + 45 * k )) if skillLevel >= 30: bonusPercent = 15 if skillLevel>=35: self.AutoAppendTextLine(localeInfo.PARTY_SKILL_SKILL_MASTER % int(25 + 600 * k )) if skillLevel>=40: self.AutoAppendTextLine(localeInfo.PARTY_SKILL_DEFENDER % int( 5 + 30 * k )) if bonusPercent > 0: self.AppendSpace(5) self.AutoAppendTextLine(localeInfo.PARTY_SKILL_LEADER_REFLECT_BONUS % bonusPercent) # @fixme008 END self.AlignHorizonalCenter() // PythonSkill.cpp PyObject* skillGetSkillPowerByLevel(PyObject* poSelf, PyObject* poArgs) { int dwSkillLevel; if (!PyTuple_GetInteger(poArgs, 0, &dwSkillLevel)) return Py_BadArgument(); return Py_BuildValue("i", LocaleService_GetSkillPower(dwSkillLevel)); } { "GetSkillPowerByLevel", skillGetSkillPowerByLevel, METH_VARARGS },
  11. Why not using Timestamp instead of increase a dungeon quest flag every time ? define TIME_OUT 3600 -- 1 hour define TIME_OUT_STEP 60 -- 1 minute define DUNGEON_MAP_INDEX XXX quest dungeon begin state start begin when --[[]] with InDungeon(DUNGEON_MAP_INDEX) begin -- InDungeon - [Hidden Content] -- if (TIME_OUT and TIME_OUT_STEP) then -- No reason to initialize anything if you don't want a time limit. server_loop_timer("dungeon_time_out_check", TIME_OUT_STEP, d.get_map_index()); d.setf("dungeon_time_out_end", get_global_time() + (TIME_OUT_STEP*60)) d.notice(string.format("<Dungeon> Initialized! Time limit: %s!", get_time_format(TIME_OUT))) -- get_time_format - [Hidden Content] end -- if end -- when when dungeon_time_out_check.server_timer begin -- Only refer to our personal dungeon instance's server timer. if (d.select(get_server_timer_arg())) then if (d.getf("dungeon_time_out_end") < get_global_time()) then -- Clear the timer as there's no more need for it to loop. clear_server_timer("dungeon_time_out_check", get_server_timer_arg()); d.notice("<Dungeon> Time expired.") d.exit_all(); else -- As long as the time hasn't expired, we just notify the dungeon about the Time remaining. d.notice(string.format("<Dungeon> Time remaining: %s.", get_time_format(d.getf("dungeon_time_out_end") - get_global_time()))) -- get_time_format - [Hidden Content] end -- if/else end -- if end -- when end -- state end -- quest
  12. You are the best @Owsap as usual, thanks a lot !. Just a little suggestions, you didn't check the Dragon Flames item server side other than "IsDragonSoulRefineMaterial" but it's can be true with any DS material, so we can imagine a cheat sending other items if bypassing the client check bool IsDragonSoulRefineMaterial(LPITEM pItem) { if (pItem->GetType() != ITEM_MATERIAL) return false; return (pItem->GetSubType() == MATERIAL_DS_REFINE_NORMAL || pItem->GetSubType() == MATERIAL_DS_REFINE_BLESSED || pItem->GetSubType() == MATERIAL_DS_REFINE_HOLLY #if defined(__DS_CHANGE_ATTR__) || pItem->GetSubType() == MATERIAL_DS_CHANGE_ATTR #endif ); } I will suggest to add a little check also // Replace this line in DragonSoul.cpp DSManager::DoChangeAttribute else if (IsDragonSoulRefineMaterial(pItem)) // With subtype check else if (IsDragonSoulRefineMaterial(pItem) && pItem->GetSubType() == MATERIAL_DS_CHANGE_ATTR) // Or with vnum check else if (IsDragonSoulRefineMaterial(pItem) && (pItem->GetVnum() == 100700 || pItem->GetVnum() == 100701))
  13. // questlua_party.cpp ALUA(party_get_min_level) { LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr(); if (ch->GetParty()) lua_pushnumber(L,ch->GetParty()->GetMemberMinLevel()); else lua_pushnumber(L, 1); return 1; } // party.cpp BYTE CParty::GetMemberMinLevel() { BYTE bMin = PLAYER_MAX_LEVEL_CONST; itertype(m_memberMap) it = m_memberMap.begin(); while (it!=m_memberMap.end()) { if (!it->second.bLevel) { ++it; continue; } if (!bMin) bMin = it->second.bLevel; else if (it->second.bLevel) bMin = MIN(bMin, it->second.bLevel); ++it; } return bMin; } // party.h BYTE GetMemberMinLevel();
  14. I think every dev are different any way, and cleaning and optimise the code will come after debug phase. But thanks for your comment
  15. Because packet_info.cpp is used for CG packet (Client to Game) and GG (Game to Game) but my issue is about GC packet (Game to Client) so have nothing in the packet_info.cpp
  16. Thanks a lot for the tip, i never noticed it before. I just did the change, but i have the exactly same bug right now just the packet size is different from log now 0602 16:56:03758 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 22133 0602 16:56:03774 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 22133 I'm gonna be crazy
  17. Hi everyone, I'm not asking for help often as I try to debug everything by myself for my knowledge but I'm struggling with a bug and I don't understand the issue. Let's me explain everything in detail, maybe someone already this that and can at least give me some clues. As the title say I have a problem with a dynamic packet, but I have compare it multiple time with other one and i don't understand what can cause the bug. Let's me first explain what going on. Everytime this packet is sent to the client, the client is like frozen in time (The client still working, but it's like the connexion is lost with the server and no more packet are read) but i can unblock it by sending new packet (For example trying to ride the mount multiple time will make all previous packet to be read as normal) Now let's me show you all the code Serverside: // HEADER_GC_EVENT_MANAGER = 243 // EVENT_MANAGER_LOAD = 0 // tables.h typedef struct event_struct_ { WORD eventID; BYTE eventIndex; int startTime; int endTime; BYTE empireFlag; BYTE channelFlag; DWORD value[4]; bool eventStatus; bool eventTypeOnlyStart; } TEventManagerData; typedef struct event_packet_struct_ { BYTE dayIndex; TEventManagerData dayEventData; } TEventManagerDataPacket; typedef struct event_status_packet_struct_ { WORD eventID; bool eventStatus; int endTime; } TEventManagerDataStatusPacket; // packet.h typedef struct SPacketGCEventManager { BYTE header; BYTE subheader; WORD size; } TPacketGCEventManager; // char_manager.cpp void CHARACTER_MANAGER::CompareEventSendData(TEMP_BUFFER *buf) { for (auto it = m_eventData.begin(); it != m_eventData.end(); ++it) { if (it->second.size()) { TEventManagerDataPacket pDataPacket; pDataPacket.dayIndex = static_cast<BYTE>(it->first); for (DWORD j = 0; j < it->second.size(); ++j) { TEventManagerData pData = it->second[j]; pDataPacket.dayEventData = pData; buf->write(&pDataPacket, sizeof(pDataPacket)); } } } } void CHARACTER_MANAGER::SendDataPlayer(LPCHARACTER ch) { if (!ch->GetDesc()) return; TEMP_BUFFER buf; CompareEventSendData(&buf); TPacketGCEventManager p; p.header = HEADER_GC_EVENT_MANAGER; p.subheader = EVENT_MANAGER_LOAD; p.size = sizeof(p) + buf.size(); if (buf.size()) { ch->GetDesc()->BufferedPacket(&p, sizeof(p)); ch->GetDesc()->Packet(buf.read_peek(), buf.size()); } else { ch->GetDesc()->Packet(&p, sizeof(p)); } sys_log(0, "[EventManager] Send Data to Client. p.header: %d, p.subheader: %d, p.size: %d, buf.size: %d", p.header, p.subheader, p.size, buf.size()); } ClientSide: // Packet.h typedef struct SPacketGCEventManager { BYTE header; BYTE subheader; WORD size; } TPacketGCEventManager; typedef struct event_struct_ { WORD eventID; BYTE eventIndex; int startTime; int endTime; BYTE empireFlag; BYTE channelFlag; DWORD value[4]; bool eventStatus; bool eventTypeOnlyStart; }TEventManagerData; typedef struct event_packet_struct_ { BYTE dayIndex; TEventManagerData dayEventData; } TEventManagerDataPacket; typedef struct event_status_packet_struct_ { WORD eventID; bool eventStatus; int endTime; } TEventManagerDataStatusPacket; // PythonNetworkStream.cpp Set(HEADER_GC_EVENT_MANAGER, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCEventManager), DYNAMIC_SIZE_PACKET)); // PythonNetworkStreamPhaseGame.cpp bool CPythonNetworkStream::RecvEventManager() { Tracef(" RecvEventManager\n"); TPacketGCEventManager packet; if (!Recv(sizeof(TPacketGCEventManager), &packet)) return false; packet.size -= sizeof(packet); if (packet.subheader == EVENT_MANAGER_LOAD) { PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "ClearEventManager", Py_BuildValue("()")); while (packet.size > 0) { TEventManagerDataPacket pDataPacket; if (!Recv(sizeof(pDataPacket), &pDataPacket)) return false; const BYTE dayIndex = pDataPacket.dayIndex; const auto& eventPtr = pDataPacket.dayEventData; const time_t startTime = eventPtr.startTime; const time_t endTime = eventPtr.endTime; const struct tm vEventStartKey = *localtime(&startTime); const struct tm vEventEndKey = *localtime(&endTime); static char startTimeText[24]; static char endTimeText[24]; snprintf(startTimeText, sizeof(startTimeText), "%d-%02d-%02d %02d:%02d:%02d", vEventStartKey.tm_year + 1900, vEventStartKey.tm_mon + 1, vEventStartKey.tm_mday, vEventStartKey.tm_hour, vEventStartKey.tm_min, vEventStartKey.tm_sec); snprintf(endTimeText, sizeof(endTimeText), "%d-%02d-%02d %02d:%02d:%02d", vEventEndKey.tm_year + 1900, vEventEndKey.tm_mon + 1, vEventEndKey.tm_mday, vEventEndKey.tm_hour, vEventEndKey.tm_min, vEventEndKey.tm_sec); PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "AppendEvent", Py_BuildValue("(iiissiiiiiiiii)", dayIndex, eventPtr.eventID, eventPtr.eventIndex, startTimeText, endTimeText, eventPtr.empireFlag, eventPtr.channelFlag, eventPtr.value[0], eventPtr.value[1], eventPtr.value[2], eventPtr.value[3], eventPtr.startTime, eventPtr.endTime, eventPtr.eventStatus)); packet.size -= sizeof(pDataPacket); } PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "RefreshEventManager", Py_BuildValue("()")); } else if (packet.subheader == EVENT_MANAGER_EVENT_STATUS) { TEventManagerDataStatusPacket pDataStatusPacket; if (!Recv(sizeof(pDataStatusPacket), &pDataStatusPacket)) return false; WORD eventID = pDataStatusPacket.eventID; bool eventStatus = pDataStatusPacket.eventStatus; int endTime = pDataStatusPacket.endTime; const time_t endTimeReal = endTime; const struct tm vEventEndKey = *localtime(&endTimeReal); char endTimeText[24]; snprintf(endTimeText, sizeof(endTimeText), "%d-%02d-%02d %02d:%02d:%02d", vEventEndKey.tm_year + 1900, vEventEndKey.tm_mon + 1, vEventEndKey.tm_mday, vEventEndKey.tm_hour, vEventEndKey.tm_min, vEventEndKey.tm_sec); PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "RefreshEventStatus", Py_BuildValue("(iiis)", eventID, eventStatus, endTime, endTimeText)); } return true; } As you can see I added some debug points, here is the result when the function is called: Server: Jun 2 15:41:25 :: [EventManager] Send Data to Client. p.header: 243, p.subheader: 0, p.size: 84, buf.size: 80 Client: 0602 15:41:00437 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 115 packet size: 2381 0602 15:41:00440 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 115 packet size: 2381 0602 15:41:00451 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 115 packet size: 2381 0602 15:41:00468 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 115 packet size: 2381 [...] 0602 15:41:00501 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 4 packet size: 147 0602 15:41:00516 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 4 packet size: 122 [...] 0602 15:41:00615 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:41:00633 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:41:00649 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:41:00666 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:41:00682 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:41:00698 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:41:00715 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:41:00731 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:41:00748 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 [...] 0602 15:42:14872 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:42:14888 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:42:14905 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:42:14922 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:42:14937 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:42:14955 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:42:14971 :: CPythonNetworkStream::CheckPacket - Not enough dynamic packet size: header 243 packet size: 21504 0602 15:42:14987 :: RecvEventManager All the "Not enough dynamic packet size" are spammed until I do the mount ride thing (as on the gif) and the "RecvEventManager" is called only at the end so it's can't be the function itself. I also notice than I got some other header with the error but it's only when this packet is sent, if I don't send this packet everything is normal and no error show. Thanks a lot if you can help me with that, i try to check everything and i really don't understand what can do that as I have a lot of the other dynamic packet who working perfectly.
  18. [Hidden Content] Easy to do, lot of files can be detected as false positive for multiple reasons. If the file try to access to some files (Like this tool do to convert the files) and if the exe is new it's will increase the detection rate. You can just run exe file on sandbox to see if something is legit, i suggest you to use tool like this [Hidden Content]
  19. As I told you every state have a different number. Finish the kon_1 on your test server and look at the state number (You need wait the cache to save the quest on DB) and use this value on the code. From the example you sent from the 3 players, are you sure they all completed it ?
  20. Why are you looking for "lead" quest ? Check the status of the "kon_1"
  21. The number on the database depend of the name of your complete state. If you name it "complete" or "__complete" or "__complete__" it's all different numbers. Normally if you use the same name for your complete state you must have the same number. And so you can do something like that: quest kon_2 begin state start begin when login or levelup or enter with pc.get_level() >= 8 begin local valueComplete = "557528158" questState = get_quest_state("kon_1") questStateFormated = string.format("%d", questState) if questStateFormated == valueComplete then setstate(run) end end end state run begin when login or levelup or enter with pc.get_level() >=8 begin set_state(information) end end [...]
  22. The best way is too add the set_quest_state("kon_3", "run") even if the quest not exist yet. Example at end of your 12th quest you setup set_quest_state("kon_13", "run") And when the quest will exist, it's will read the run state of it The number "557528158" come from database (it's egal to "__complete" state), if you go to quest database you will see than state are saved by number and not by name. So you can check the state number of your already finish quest to know what number is for the "complete" state
  23. Post the 7th quest here, you have to use the "set_quest_state" even if the quest still not exist to save the flag. But you can also add some code on the "complete" state to do that
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.