PetePeter
-
Posts
106 -
Joined
-
Last visited
-
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by PetePeter
-
-
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);
- 1
-
1 hour ago, UdvAtt108 said:
I tested it, and it is working for me. But okay.
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
-
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
-
Nobody have the answer to that ?
-
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
- 1
-
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 -
1 hour ago, Kafa said:
[PAID] Searching for someone who can generate mob_drop_item/special_drop_item from italian wikipedia.
Please write me a message.
Quote of VegaS
Wikipedia has a API included, you can play with it. http://wiki.metin2.co.uk/api.php MediaWiki docs: https://www.mediawiki.org/wiki/API:Properties#revisions_.2F_rv Some examples: https://stackoverflow.com/questions/7185288/how-to-get-wikipedia-content-using-wikipedias-api
The problem will be the % of each drop, you can't have access to these values
-
24 minutes ago, LethalArms said:
There is
110000~110099 ÃÖÇÏ±Þ ÀÏ¹Ý ¹é·æ¼® ITEM_DS DS_SLOT1 1 ANTI_SAFEBOX | ANTI_SELL NONE NONE NONE 0 0 0 0 0 TIMER_BASED_ON_WEAR 86400 LIMIT_NONE 0 APPLY_NONE 0 APPLY_NONE 0 APPLY_NONE 0 0 0 0 0 0 0 0 0 0
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
-
Quote
SYSERR: Jul 26 00:05:15 :: ReadSpecialDropItemFile: ReadSpecialDropItemFile : there is no item 110000 : node 용혼원석-보상용_기본
SYSERR: Jul 26 00:05:15 :: Boot: cannot load SpecialItemGroup: locale/portugal/special_item_group.txtThere is no item 110000 on your item_proto that's what the error say
-
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.
-
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 },
- 1
-
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 - https://metin2.dev/topic/15905-syreldars-quest-functions/ -- 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 - https://metin2.dev/topic/15905-syreldars-quest-functions/ 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 - https://metin2.dev/topic/15905-syreldars-quest-functions/ end -- if/else end -- if end -- when end -- state end -- quest
- 1
-
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))
- 1
-
10 hours ago, Th1Doose said:
Thanks for your comments, i appreciate!
Sry for pushing the post, isn't it better if it goes like this?
party.get_min_level()
Sry for pushing the post, isn't it better if it goes like this?
party.get_min_level()
// 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();
-
3 hours ago, WeedHex said:
Ohh yep sorry, I looked so fast and just wanted to put fast hints T_T
Btw looking better I dont like how you managed on char_manager.cpp and in general the system, you could made it very smarter.
I think every dev are different any way, and cleaning and optimise the code will come after debug phase. But thanks for your comment
-
1 hour ago, WeedHex said:
I'm gonna get crazy*. Ahahaha
Jks apart, you didn't post the packet_info.cpp part.
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
- 1
-
19 minutes ago, Shang said:
When you declare the struct of a dynamic packet you should follow the primary struct which is this one:
typedef struct packet_header_dynamic_size { BYTE header; WORD size; } TDynamicSizePacketHeader;
The point is that you are declaring this:
typedef struct SPacketGCEventManager { BYTE header; BYTE subheader; WORD size; } TPacketGCEventManager;
and the correct one should be this:
typedef struct SPacketGCEventManager { BYTE header; WORD size; BYTE subheader; } TPacketGCEventManager;
You can corroborate this information in this function: bool CPythonNetworkStream::CheckPacket(TPacketHeader * pRetHeader) from UserInterface/PythonNetworkStream.cpp.
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
-
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. -
3 minutes ago, Jimmermania said:
Lol dude, its not about trust. Its in the rules of this forum, if you upload an .exe to virustotal it.
And for your interest, my norton deleted it immediately after i downloaded it: https://metin2.download/picture/PChqj75ADu4okaXMKmnAWW3HC3dqAQKz/.png
Anyway, thanks for your time.
https://www.virustotal.com/gui/file/bb53da796f1710c49a4eac8f163048015b7c9550a9682988320536c84aa7d4a8?nocache=1
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 https://sandboxie-plus.com/Sandboxie/- 1
- 1
-
37 minutes ago, Mefarious said:
Im giving example because i wont let anyone do kon_1 quest untill i solve this problem, i dont want people to complete it yet
every quest has different ID for every playerOkey tried this, but doesnt work
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 ? -
7 minutes ago, Mefarious said:
When i look into database in quest table i see this
64746 lead __status 1896384362
64696 lead __status -278129975
64691 lead __status 1395287876
3 different player completed the same quest but they got different number, or im looking in bad tableWhy are you looking for "lead" quest ? Check the status of the "kon_1"
-
6 minutes ago, Mefarious said:
But as you can see, i already set this quest flag in all my quests, even if they are not exist, its not working
and one quest completed in mysql have different id for every player that did this quest, one have 1896384362, other have -278129975.
to get it work i have to clear all quest flags and and compile all the quest in chainThe 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 [...]
-
1 hour ago, Mefarious said:
Example of quests
1st:
quest kon_1 begin
state start begin
when login or levelup or enter with pc.get_level() >=4 begin
set_state(information)
end
end
state information begin
when letter begin
local v = find_npc_by_vnum(20349)
if v != 0 then
target.vid("__TARGET__", v, "Stajenny")
end
send_letter("Nauka Jazdy")
end
when button or info begin
say_title("Nauka Jazdy")
say("")
say("Jestes gotowy aby rozpoczac nauke jazdy konnej ")
say("Odwiedz Stajennego po wiecej informacji ")
say("na temat jazdy. ")
end
when 20349.chat."Jezdziectwo 1" begin
target.delete("__TARGET__")
say_title("Stajenny: ")
say("")
say("Witaj")
say("Sadzimy iz jestes juz gotowy aby rozpoczac ")
say("nauke jazdy konnej. ")
say("Dzieki licencji bedziesz mogl poruszac sie po ")
say("swiecie o wiele szybciej. ")
say("W takim razie zaczynajmy od razu! ")
wait()
say_title("Stajenny: ")
say("")
say("Zanim lecz zaczniemy musisz posiadac ")
say("Medal Konny")
say("To wlasnie on uprawnia mlodych adeptow ")
say("do rozpoczecia nauki jazdy konnej. ")
say("Zdobyc go mozesz od czlego ksztaltnych malp ")
say("przebywajacych w jaskiniach lub ze zlotych szkatolek ")
say("ktore mozesz znalezc po calym swiecie. ")
wait()
say_title("Stajenny: ")
say("")
say("Teraz juz lec zdobyc Medal Konny ")
say("Bede tu czekal na Ciebie. ")
set_state(go_to_disciple)
end
end
state go_to_disciple begin
when letter begin
send_letter("Jezdziectwo 1")
end
when button or info begin
say_title("Znajdz Medal Konny")
say("")
say("Stajenny potrzebuje Medalu Konnego ")
say("by rozpoczac twoj trening. ")
say("Znajdziesz go u malp lub w zlotych skrzyniach")
say_item("Medal Konny ",50050,"")
end
when 20349.chat."Mam Medal" with pc.count_item(50050) >0 begin
say_title("Stajenny: ")
say("")
say("Oh!! Znalazles medal!")
say("Teraz mozemy rozpoczac trening. ")
say("Tylko najpierw sprawdze czy aby to nie falszywka")
wait()
pc.remove_item(50050, 1)
say_title("Stajenny: ")
say("")
say("Wyglada na prawdziwy")
say("Zobaczmy co jest na zdobytym Medalu napisane.. ")
set_state(first)
end
end
state first begin
when letter begin
local v = find_npc_by_vnum(20349)
if v != 0 then
target.vid("__TARGET__", v, "Stajenny")
end
send_letter("Dziwna Sprawa")
end
when button or info begin
say_title("Dziwna Sprawa")
say("")
say("Stajenny ma dla Ciebie informacje ")
say("Porozmawiaj z nim ")
say("jak najszybciej. ")
end
when 20349.chat."Ten Medal jest.." begin
say_title("Stajenny: ")
say("")
say("Ciekawe... ")
say("Wedlug informacji zapisanych na medalu.. ")
wait()
say_title("Stajenny: ")
say("")
say("Matko.. chyba twoj trening bedzie musial poczekac ")
say("Wedlug tych informacji gang czleko ksztaltnych ")
say("przygotowuje Wilki do ataku na nasza wioske ")
wait()
say_title("Stajenny: ")
say("")
say("Musimy sie tym szybko zajac ")
say("Najlepiej bedzie dowiedziec sie kto przewodzi ")
say("Wataha. ")
say("Udaj sie do leza wilkow i poszukaj informacji. ")
target.delete("__TARGET__")
set_state(inf)
end
end
state inf begin
when letter begin
send_letter("Nagle Zadanie")
end
when button or info begin
say_title("Stajenny: ")
say("")
say("Poszukaj informacji na temat przywodcy Watahy ")
say("Byc moze Elitarne jednostki Wilkow ")
say("beda posiadac jakies informacje ")
say("")
say_reward("Zabij Cung-Mok ")
say_reward("aby zdobyc informacje")
end
when 151.kill begin
if number( 1, 100 ) <= 25 then
local v = find_npc_by_vnum(20349)
if v != 0 then
target.vid("__TARGET__", v, "Stajenny")
end
say_title("Nagle Zdanie")
say("")
say_reward("Ten Wilk posiada jakies informacje ")
say_reward("Idz zawiadomic stajennego ")
say("")
set_state(second)
else
say_reward("Ten Wilk nie posiadal zadnych informacji")
end
end
end
state second begin
when 20349.chat."Zdobylem Informacje" begin
target.delete("__TARGET__")
say_title("Stajenny: ")
say("")
say("Pokaz mi to!")
wait()
say_title("Stajenny: ")
say("")
say("Nie jest dobrze.. ")
say("Ale mamy chwile czasu na przygotowanie. ")
say("")
say("Dziekuje za zdobycie tych informacji ")
say("Rada na pewno bedzie wdzieczna. ")
say("Daj nam chwile czasu na obmyslenie planu. ")
wait()
say_title("Stajenny: ")
say("")
say("Jedyne co moge Ci zaoferowac za pomoc ")
say("To dac Ci to po co do mnie przyszedles... ")
wait()
pc.change_money(500)
pc.give_exp2(2500)
pc.give_item2(50051, 1)
horse.unride()
horse.advance()
horse.ride()
say_title("Otrzymano: ")
say_reward("Licencje Jazdy Konnej ")
say_reward("500 yang")
say_reward("2500 exp")
set_quest_state("kon_2", "run")
set_state(__COMPLETE__)
end
end
state __COMPLETE__ begin
end
end
2sd:
quest kon_2 begin
state start begin
end
state run begin
when login or levelup or enter with pc.get_level() >=8 begin
set_state(information)
end
end
state information begin
when letter begin
local v = find_npc_by_vnum(20349)
if v != 0 then
target.vid("__TARGET__", v, "Stajenny")
end
send_letter("Plan Gotowy")
end
when button or info begin
say_title("Plan Gotowy")
say("")
say("Stajenny wzywa Cie do siebie ")
say("Pospiesz sie zanim zaczna bez Ciebie! ")
end
when 20349.chat."Jaki jest plan?" begin
target.delete("__TARGET__")
say_title("Stajenny: ")
say("")
say("Jestes juz, nareszcie..")
say("")
say("Razem z rada doszlismy do wniosku ")
say("ze atak ze strony Watahy jest blisko ")
say("skoro Elity wilkow dostaly juz rozkazy ")
say("otoczenia wioski. ")
wait()
say_title("Stajenny: ")
say("")
say("Na informacji ktore nam dostyarczyles ")
say("widnialy wspolrzedne ")
say("Udasz sie tam gdzie prowadza ")
say("i zdasz mi relacje ")
say("ale najpierw... ")
wait()
say_title("Stajenny: ")
say("")
say("nie zapomnij przyniesc 2 Medali Konnych ")
say("aby ukazac checi do wykonania zlecenia przez Rade ")
say("Rada zgodzila sie szkolic twego Konia w zamian ")
say("za wykonywanie misji, lecz chca widziec, ze Ci zalezy. ")
set_state(go_to_disciple)
end
end
state go_to_disciple begin
when letter begin
send_letter("Medal Konny")
end
when button or info begin
say_title("Znajdz Medal Konny")
say("")
say("Rada potrzebuje 2 Medali Konnych ")
say("by wiedziec, ze jestes wart misji ")
say("Znajdziesz go u malp lub w zlotych skrzyniach")
say_item("Medal Konny ",50050,"")
end
when 20349.chat."Mam 2 Medale" with pc.count_item(50050) >1 begin
say_title("Stajenny: ")
say("")
say("Teraz Rada nie bedzie miec watpliwosci")
say("ze chcesz podejmowac sie zadan. ")
say("Im silniejszy twoj kon tym wiecej Medali bedzie potrzebnych ")
say("Pozwol, ze odbiore je od Ciebie..")
pc.remove_item(50050, 2)
wait()
say_title("Stajenny: ")
say("")
say("A wiec tutaj masz wspolrzedne z informacji")
say("ktore dostarczyles wczesniej. ")
say("Udaj sie tam niezwlocznie ")
say("Tylko nie rob nic glupiego...")
set_state(pos)
end
end
state pos begin
when letter begin
send_letter("Miejsce docelowe")
target.pos("__TARGET1__", 87, 880, 41, "Wspolrzedne")
end
when button or info begin
say_title("Miejsce docelowe")
say("")
say("Udaj sie w miejsce")
say("w ktore wkazuja wspolrzedne")
end
when __TARGET1__.target.arrive begin
target.delete("__TARGET1__")
say("Widzisz ogromnego Wilka.. ")
say("Wyglada na porzywodce Watahy..")
set_state(first)
end
end
state first begin
when letter begin
local v = find_npc_by_vnum(20349)
if v != 0 then
target.vid("__TARGET__", v, "Stajenny")
end
send_letter("Zdaj raport")
end
when button or info begin
say_title("Zdaj raport")
say("")
say("Zdaj raport Stajennemu")
say("co widziales ")
say("w miejscu wspolrzednych ")
end
when 20349.chat."Zdaj Raport" begin
say_title("Stajenny: ")
say("")
say("Wielki wilk? Jeszcze powiedz ze byl ")
say("Szary z bujna grzywa.. ")
wait()
say_title("Stajenny: ")
say("")
say("Jesli mnie pamiec nie myli ")
say("Istota ta to elitarna jednosta Tigrisa! ")
say("Lykos... ")
wait()
say_title("Stajenny: ")
say("")
say("Bardzo niebezpieczny ")
say("Jesli to on przewodzi Wataha to mamy niemaly problem.. ")
say("Jeszcze nie jestes gotow aby stawic mu czola ")
say("Na te walke musimy Cie przygotowac ")
wait()
say_title("Stajenny: ")
say("")
say("Musimy pogrzyzowac mu plany ")
say("Odszukaj drugiego Elitarnego Wilka i go zabij ")
say("Moze troche tym wkurzymy Lykosa ")
say("i zyskamy na czasie ")
target.delete("__TARGET__")
set_state(inf)
end
end
state inf begin
when letter begin
send_letter("Elitarny Wilk")
end
when button or info begin
say_title("Dywersja: ")
say("")
say_reward("Zabij Mu-Rang")
say_reward("aby kupic troche czasu")
end
when 152.kill begin
if number( 1, 100 ) <= 100 then
local v = find_npc_by_vnum(20349)
if v != 0 then
target.vid("__TARGET__", v, "Stajenny")
end
say_title("Mu Rang nie zyje")
say("")
say_reward("Donies Stajennemu ")
say_reward("ze Mu Rang nie zyje ")
say("")
set_state(second)
end
end
end
state second begin
when 20349.chat."Zadanie zrobione?" begin
target.delete("__TARGET__")
say_title("Stajenny: ")
say("")
say("Bardzo dobra robota..")
say("Oby kupilo nam to troche czasu..")
wait()
say_title("Stajenny: ")
say("")
say("Dobrze sie spisales, zasluzyles ")
say("na mini awans ")
say("")
say("Wroc do mnie gdy bedziesz silniejszy")
wait()
pc.change_money(1000)
pc.give_exp2(10000)
horse.unride()
horse.advance()
horse.ride()
say_title("Otrzymano: ")
say_reward("Awans Konia ")
say_reward("1000 yang")
say_reward("10000 exp")
set_quest_state("kon_3", "run")
set_state(__COMPLETE__)
end
end
state __COMPLETE__ begin
end
end
i have already wrote 12 quests,
if i upload 1st one, and someone complete it, he wont recieve second quest if its not uploaded already
And i dont understand what is this number == "557528158" then
all of my 30 quests already have set quest state writtenThe 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
-
59 minutes ago, Mefarious said:
Hello, i have problem with continuation chain quests
Problem occurs when
For example:
I have 7 quests in chain on server.
If someone start to do this chain or complete all of 7
and i implement new i8th quest, hes not able to recieve it.
I have to delete all quest flags for player to make him able to get this 8th quest, but he has to start over again all quests.
How to solve this problem?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
Official Inventory Expansion - some problems
in Community Support - Questions & Answers
Posted
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)