-
Posts
63 -
Joined
-
Last visited
-
Days Won
3 -
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by Trial
-
-
1 hour ago, WeedHex said:
I think the problem is related to the sectree because your map coord are not multiple of 25600, when you unride from the mount, may happen this issue due to an incorrect calculation in the axis.
Get more info with mapindex
sys_err("cannot find tree by %d %d (map index %d)", x, y, lMapIndex);
i don't think it's related, the bug is present on any map/location, it only depends on the call to CHARACTER::CalculateMoveDuration which sets the m_dwMoveDuration to 0 if CHARACTER::m_posStart equals CHARACTER::m_posDest
it's easy to trigger : login, click somewhere to move (do not release mouse button) + CTRL+G to mount -> undefined behavior, it might be "fine" if the result of (float)dwElapsedTime / (float)m_dwMoveDuration is positive (inf) but if the result is negative (-nan / -inf) it results in -INTMAX coordinates.
Anyway it's undefined behavior in all cases
- 1
-
20 hours ago, Gurgarath said:
To be fair, I had the exact same bug and I postponed the fix for months because it was a low importance bug so far, but your post interested me. In hindsight I decided to work on it because this didn't fix it for me (I also had no syserr, but I was experiencing the same bug with mounts).
This kind of bug is easy to track, just do /state while running with a mount, if the mount has the bug, the coordinates won't be refreshed, which will postpone the loading of the chunks until the server finally catch up and decides to sent the move packet and the refreshing of the chunks.
Usually, it can happen when the server cannot process something, for players, monsters and NPC it is the data folder that is responsible for dealing with that. It will use the duration and the accumulation of an animation to try to replicate as much as it can where a mob should be and when it should be there. If there is no data or if the data is incorrect, you will have many issues (including but not limited to):
- False flagged as a cheater / speedhacker
- Monsters will load with a slight delay (instead of loading in front of you they will load behind you) or won't load at all
- You will receive damages from monsters far behind because the server thinks you are immobile
- The server will think a monster has caught up with you while it hasn't and vice-versa
To fix it, you just have to add the "folder" in the mob_proto of every mount having the issue. Long story short, some mounts won't have a "folder" field in your mob_proto.txt, which will result in them not having a data folder and triggering the aforementioned scenario. In my case, the Manny (20246/20247) was having the issue, so I just added "christmas_2016_mammoth" to the "folder" field in mob_proto.txt, made sure I had it in "share/data/monster" and voilà. It fixed the issue completely.
To easily know the folder, just check in NPClist and make sure it is a folder and not a "subfolder". A subfolder in npc_list.txt is working like this:
#0 #SUBFOLDER #FOLDER <- (This one should be added into mob_proto.txt) 0 christmas_2016_mammoth_01 christmas_2016_mammoth
I still recommend you to apply this fix, I have folders configured as they should be but the problem persisted because of the undefined behavior I quoted above.
SYSERR: Dec 26 17:40:03 :: CHARACTER::Sync: cannot find tree at -2147483648 -2147483648 (name: sync)
Edit: Not same bug I think, the one caused by this undefined behavior is not directly related to motion files.
-
On 7/31/2015 at 12:07 AM, TyWin said:
Open char.cpp
Search:
LPSECTREE new_tree = SECTREE_MANAGER::instance().Get(GetMapIndex(), x, y); if (!new_tree) { if (GetDesc()) { sys_err("cannot find tree at %d %d (name: %s)", x, y, GetName()); GetDesc()->SetPhase(PHASE_CLOSE); } else { sys_err("no tree: %s %d %d %d", GetName(), x, y, GetMapIndex()); Dead(); } return false; }
Replace it with:
LPSECTREE new_tree = SECTREE_MANAGER::instance().Get(GetMapIndex(), x, y); if (!new_tree) { if (GetDesc()) { sys_err("cannot find tree at %d %d (name: %s)", x, y, GetName()); //GetDesc()->SetPhase(PHASE_CLOSE); new_tree = GetSectree(); x = GetX(); y = GetY(); } else { sys_err("no tree: %s %d %d %d", GetName(), x, y, GetMapIndex()); Dead(); } return false; }
And that's it.
I'm digging up this old topic because I'm doing some tests on new server files and I just encountered this problem.
This solutions does work but it doesn't fix the issue at it's origin/source. The origin lies in "CHARACTER::StateMove", here:
float fRate = (float)dwElapsedTime / (float)m_dwMoveDuration;
it sometimes happens that "m_dwMoveDuration" equals 0 thus resulting in undefined behavior (see "CHARACTER::CalculateMoveDuration" for more info)
in "CHARACTER::StateMove" replace this
DWORD dwElapsedTime = get_dword_time() - m_dwMoveStartTime; float fRate = (float)dwElapsedTime / (float)m_dwMoveDuration; if (fRate > 1.0f) fRate = 1.0f; int x = (int)((float)(m_posDest.x - m_posStart.x) * fRate + m_posStart.x); int y = (int)((float)(m_posDest.y - m_posStart.y) * fRate + m_posStart.y);
with this
const DWORD dwElapsedTime = get_dword_time() - m_dwMoveStartTime; int x; int y; bool bMovementFinished = false; //indicates if character moved and has reached destination if (!dwElapsedTime || !m_dwMoveDuration) { x = GetX(); y = GetY(); } else { float fRate = (float)dwElapsedTime / (float)m_dwMoveDuration; if (fRate >= 1.0f) { bMovementFinished = true; fRate = 1.0f; } x = (int)((float)(m_posDest.x - m_posStart.x) * fRate + m_posStart.x); y = (int)((float)(m_posDest.y - m_posStart.y) * fRate + m_posStart.y); }
still in same function replace this
if (1.0f == fRate)
with this
if (bMovementFinished)
- 3
-
Quote
1. Textures blurring out when prompting any UAC check.
This happens because the "Anisotropic Texture Filtering" is only applied when instancing "CStateManager" (CStateManager::SetDevice) it must be applied again after losing/resetting the D3D device.
This could be done by moving this code below from "CStateManager::SetDevice" to "CStateManager::SetDefaultState"
D3DCAPS8 d3dCaps; m_lpD3DDev->GetDeviceCaps(&d3dCaps); if (d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) m_dwBestMagFilter = D3DTEXF_ANISOTROPIC; else m_dwBestMagFilter = D3DTEXF_LINEAR; if (d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) m_dwBestMinFilter = D3DTEXF_ANISOTROPIC; else m_dwBestMinFilter = D3DTEXF_LINEAR; DWORD dwMax = d3dCaps.MaxAnisotropy; dwMax = dwMax < 4 ? dwMax : 4; for (int i = 0; i < 8; ++i) m_lpD3DDev->SetTextureStageState(i, D3DTSS_MAXANISOTROPY, dwMax);
so that "CStateManager::SetDevice" looks like this
void CStateManager::SetDevice(LPDIRECT3DDEVICE8 lpDevice) { StateManager_Assert(lpDevice); lpDevice->AddRef(); if (m_lpD3DDev) { m_lpD3DDev->Release(); m_lpD3DDev = NULL; } m_lpD3DDev = lpDevice; SetDefaultState(); }
(I know the "m_dwBestMagFilter" and "m_dwBestMinFilter" setting part does not need to be called every time device is reset, you are free to edit the code at your will, I kept things simple for the post)
alternatively these lines could be moved to a new method that will be called in "CStateManager::SetDevice" and wherever there is D3D device reset. Although I recommend first solution.
- 4
- 1
- 1
- 4
-
Did this a while ago after noticing freak memory usage, I recommend you add these checks as well for more optimization:
else if (m_me->IsType(ENTITY_ITEM) && ent->IsType(ENTITY_ITEM)) { //NOTE: no item to item insert return; } else if (m_me->IsType(ENTITY_ITEM) && ent->IsType(ENTITY_CHARACTER) && !ent->GetDesc()) { //NOTE: no item to NPC insert return; } else if (m_me->IsType(ENTITY_CHARACTER) && !m_me->GetDesc() && ent->IsType(ENTITY_ITEM)) { //NOTE: no NPC to item insert return; }
- 3
- 1
- 1
-
Since I can't edit the original post (?) here are some explanations for those who are interested in the details:
SpoilerSending "HEADER_GD_FLUSH_CACHE" packet to db flushes db cache for the player. This updates database "player.item" table with current item cache (from db process) at the time of changing name.
You may have already guessed it, if for example you give items in exchange to other players and then change your name then teleport to any map that is on different game core you will still have these items!
Why? The cache! You just flushed cache in db process but did not let the db know about the change of owner for exchanged items before doing so and your next login will load these items from database for you. You need to warp to other game core for this to work because same ID items cannot be loaded twice, there is a check in "ITEM_MANAGER::CreateItem"(Obviously only works for items loaded from database into db process cache then sent to game in "HEADER_DG_ITEM_LOAD" packet as this cache is needed to update database when changing name)
DB Cache should never be flushed manually, better let the normal cache handling process do it's work. -
-
2 hours ago, martysama0134 said:
Sorry if there was any confusion, I was just mentioning the fact that it was posted on your blog.
And yes this is the same game admin I gave this fix to, don't know why he asked you about this as it was fixed, anyway.
I suggest you remove the "how to" part from your screenshots as it may still be too early, I will edit my initial post about details soon.
-
Hello,
So I have shared this fix with someone a few days ago and saw this morning that martysama has published it on it's blog.
I let you know before kids with "private" access to this start playing with it. (I do not have acces to martysama's blog member posts and do not know who does)The "pc_change_name" function has an exploitable item duplication bug.
The fix is simple, in "pc_change_name" replace this code:
db_clientdesc->DBPacketHeader(HEADER_GD_FLUSH_CACHE, 0, sizeof(DWORD)); db_clientdesc->Packet(&pid, sizeof(DWORD));
with this:
if (!CHARACTER_MANAGER::instance().FlushDelayedSave(ch)) { ch->SaveReal(); }
I will edit this post to add details on how and why later on to avoid kids playing with it before it's patched on majority of servers.
Regards,
- 5
- 2
-
On 8/11/2020 at 6:51 PM, Distraught said:
I type the same for the third time now. Packet around will not send anything to the peers because other cores just really don't give a shit what happened real-time with your character. Who sees you (and this is why it sends to them) is connected to the same core as you are.
WHAT YOU THINK HOW THE FUCK SENDS ONE CORE THE DATA TO ALL ANOTHER? THE SAME WAY AS IF THEY WERE NOT ON THE SAME MACHINE
Man you gotta understand that what OP is asking about is impossible to achieve and does not even make any sense.
You keep talking about cores but here it's not relevant, OP wants 2 players to interact in real-time with them being on totally different servers.
To be able to interact with other players in real-time you MUST be on same core, you can spread cores on multiple servers but this has nothing to do with OP's request.
This could be achieved by the exchange of all data concerning the entities between cores but again refer to the quote below :
On 8/11/2020 at 6:39 PM, tierrilopes said:Using the example above, player A has delay to communicate to the server his connected to, same does player B. But then theres also the delay between both servers.
Considering the server-server delay, couldnt it do more harm then good in some ocasions?
Think 5 sec. about the request and what you are suggesting @Distraught and if you still don't understand I can't make it any simpler, have a nice day gameloft c++ programmer!
- 1
-
-
Nice tutorial, thanks for sharing!
- 1
-
Hi metin2dev community,
I'm looking for a complete ItemShop script with official like user interface OR a fully qualified php developer familiar with laravel and/or symfony framework to develop it from scratch.
You must have worked at least on one project using one of the following frameworks : Laravel 5.8+ / Symfony 4.X+
I'm in need of complete web ItemShop, it should include main features of a common game shop, something like this:
Starting salary for coding the project from scratch: 500€ (to be discussed)
Obviously I will not pay such a high price if you simply sell a ready-made project that you can resell to several other people.
You can PM me or ask here for more details.
Best regards,
- 1
-
Il y a 2 heures, avertuss a dit :
Fast teleport doesn't work for me. Syserr is clean.
I tried to edit def GoToLocalPosition(self):
like
def GoToLocalPosition(self): net.SendChatPacket("test")
to check if mouse click works, but it doesn't.
Can you show us your uiminimap.py ? (pastebin it)
-
Il y a 2 heures, Kori a dit :
Only this code works? Or I need the other too?
This is a fix for this method, other code is the "fast teleport" system
-
il y a 15 minutes, ReFresh a dit :
@Trial Thanks for the tutorial, but I got an error:
0719 21:07:23384 :: Traceback (most recent call last): 0719 21:07:23384 :: File "networkModule.py", line 248, in SetGamePhase 0719 21:07:23384 :: File "game.py", line 108, in __init__ 0719 21:07:23384 :: File "interfaceModule.py", line 296, in MakeInterface 0719 21:07:23384 :: File "interfaceModule.py", line 184, in __MakeWindows 0719 21:07:23384 :: File "uiMiniMap.py", line 234, in __init__ 0719 21:07:23384 :: File "uiMiniMap.py", line 110, in LoadWindow 0719 21:07:23384 :: AttributeError 0719 21:07:23384 :: : 0719 21:07:23384 :: 'BoardWithTitleBar' object has no attribute 'SetMouseLeftButtonUpEvent' 0719 21:07:23384 ::
What should I add to _init_ func or it's the problem of uiscript file?
It seems that your "Window" class in ui.py differs a bit from mine, you don't have the method "SetMouseLeftButtonUpEvent", edit the "Window" class as following :
class Window(object): [...] def __init__(self, layer = "UI"): [...] self.mouseLeftButtonDownEvent = None self.mouseLeftButtonDownArgs = None self.mouseLeftButtonUpEvent = None self.mouseLeftButtonUpArgs = None [...] def SetMouseLeftButtonDownEvent(self, event, *args): self.mouseLeftButtonDownEvent = event self.mouseLeftButtonDownArgs = args def OnMouseLeftButtonDown(self): if self.mouseLeftButtonDownEvent: apply(self.mouseLeftButtonDownEvent, self.mouseLeftButtonDownArgs) def SetMouseLeftButtonUpEvent(self, event, *args): self.mouseLeftButtonUpEvent = event self.mouseLeftButtonUpArgs = args def OnMouseLeftButtonUp(self): if self.mouseLeftButtonUpEvent: apply(self.mouseLeftButtonUpEvent, self.mouseLeftButtonUpArgs)
- 1
-
@Exygo Could you try to replace
bool CNetworkActorManager::__IsVisiblePos(LONG lPosX, LONG lPosY)
in NetworkActorManager.cpp with this code and try again to see if this makes a difference
bool CNetworkActorManager::__IsVisiblePos(LONG lPosX, LONG lPosY) { LONG dx = lPosX-m_lMainPosX; LONG dy = lPosY-m_lMainPosY; LONG len = (LONG)sqrtf((float(dx) * float(dx) + float(dy) * float(dy))); extern int CHAR_STAGE_VIEW_BOUND; if (len < CHAR_STAGE_VIEW_BOUND && len > -CHAR_STAGE_VIEW_BOUND) return true; return false; }
- 1
-
Le 17/07/2019 à 16:58, avertuss a dit :
Do you have link to the teleport by click system? Can't find ;/
@avertuss I just made this to test it on my client
PythonMiniMapModule.cpp
PyObject* minimapMousePosToAtlasPos(PyObject* poSelf, PyObject* poArgs) { float fMouseX; if (!PyTuple_GetFloat(poArgs, 0, &fMouseX)) return Py_BuildException(); float fMouseY; if (!PyTuple_GetFloat(poArgs, 1, &fMouseY)) return Py_BuildException(); float fAtlasX, fAtlasY; CPythonMiniMap::Instance().MousePosToAtlasPos(fMouseX, fMouseY, &fAtlasX, &fAtlasY); int iAtlasX, iAtlasY; PR_FLOAT_TO_INT(fAtlasX, iAtlasX); PR_FLOAT_TO_INT(fAtlasY, iAtlasY); iAtlasX /= 100; iAtlasY /= 100; return Py_BuildValue("ii", iAtlasX, iAtlasY); }
add this to "s_methods" array
{ "MousePosToAtlasPos", minimapMousePosToAtlasPos, METH_VARARGS },
PythonMiniMap.h (somewhere as public method of "CPythonMiniMap" class
void MousePosToAtlasPos(long lmx, long lmy, float* pfx, float* pfy);
PythonMiniMap.cpp
void CPythonMiniMap::MousePosToAtlasPos(long lmx, long lmy, float* pfx, float* pfy) { *pfx = (lmx - m_fAtlasScreenX) * (m_fAtlasMaxX / m_fAtlasImageSizeX); *pfy = (lmy - m_fAtlasScreenY) * (m_fAtlasMaxY / m_fAtlasImageSizeY); }
Python (uiminimap.py)
Git diff, you can use https://diffy.org/ to get visual overview of edits, just paste this git diff content and click "Diff me" button. Example: https://diffy.org/diff/b6186f0jn3maex74m1wbnvcxr (link will de destroyed after 24hrs)
diff --git a/root/uiminimap.py b/root/uiminimap.py index 02393c7..d7cfac3 100644 --- a/root/uiminimap.py +++ b/root/uiminimap.py @@ -9,6 +9,7 @@ import app import colorInfo import constInfo import background +import chr class MapTextToolTip(ui.Window): def __init__(self): @@ -106,6 +107,7 @@ class AtlasWindow(ui.ScriptWindow): self.tooltipInfo.SetParent(self.board) self.infoGuildMark.SetParent(self.board) self.SetPosition(wndMgr.GetScreenWidth() - 136 - 256 - 10, 0) + self.board.SetMouseLeftButtonUpEvent(ui.__mem_func__(self.GoToLocalPosition)) self.Hide() miniMap.RegisterAtlasWindow(self) @@ -137,12 +139,18 @@ class AtlasWindow(ui.ScriptWindow): (bFind, sName, iPosX, iPosY, dwTextColor, dwGuildID) = miniMap.GetAtlasInfo(mouseX, mouseY) if False == bFind: - return + if chr.IsGameMaster(player.GetMainCharacterIndex()): + (iPosX, iPosY) = miniMap.MousePosToAtlasPos(mouseX, mouseY) + dwTextColor = 0xffffffff + else: + return if "empty_guild_area" == sName: sName = localeInfo.GUILD_EMPTY_AREA - if localeInfo.IsARABIC() and sName[-1].isalnum(): + if bFind == False: + self.tooltipInfo.SetText("(%d, %d)" % (iPosX, iPosY)) + elif localeInfo.IsARABIC() and sName[-1].isalnum(): self.tooltipInfo.SetText("(%s)%d, %d" % (sName, iPosX, iPosY)) else: self.tooltipInfo.SetText("%s(%d, %d)" % (sName, iPosX, iPosY)) @@ -159,6 +167,14 @@ class AtlasWindow(ui.ScriptWindow): self.infoGuildMark.SetPosition(mouseX - x - textWidth - 18 - 5, mouseY - y) self.infoGuildMark.Show() + def GoToLocalPosition(self): + if False == self.board.IsIn() or False == chr.IsGameMaster(player.GetMainCharacterIndex()): + return + + (mouseX, mouseY) = wndMgr.GetMousePosition() + (iPosX, iPosY) = miniMap.MousePosToAtlasPos(mouseX, mouseY) + net.SendChatPacket("/goto %d %d" % (iPosX, iPosY)) + def Hide(self): if self.AtlasMainWindow: self.AtlasMainWindow.HideAtlas()
- 1
-
Le 09/03/2019 à 17:45, flatik a dit :
Thank you for your public!
I found an error!
Here's the picture of it
https://metin2.download/picture/x8DbNtV3Hh4K9d65ZyR3sVa7GPNrjZ8d/.png
m_pThread
Should be initialized in constructor to avoid undefined behavior, the constructor should look like this
CAsyncSQL::CAsyncSQL() : m_stHost(""), m_stUser(""), m_stPassword(""), m_stDB(""), m_stLocale(""), m_iMsgCount(0), m_iPort(0), m_bEnd(false), m_mtxQuery(), m_mtxResult(), m_iQueryFinished(0), m_ulThreadID(0), m_bConnected(false), m_iCopiedQuery(0), m_pThread(nullptr) { memset(&m_hDB, 0, sizeof(m_hDB)); m_aiPipe[0] = 0; m_aiPipe[1] = 0; }
- 1
-
It's related to network actor management, if I remember it well, the client removes all dynamic actors on main actor "show" but re-inserts them afterwards because they are still stored in a vector or map of network actors because there is aproblem with a function that tests if a given actor is "visible" to main actor.
I can try to take a look at my source edits if you want
- 3
-
.mse files are used for effects, your mse need to be linked to an effect that will be attached to your character like ano other effect
-
*= -1 makes no sense because there is no "overkill" the bug happens because you hit already dead (by hp) character, here's how it should be fixed
//HP and SP recovery bug fix if (iCurHP > 0) { // Ä¥ ¶§¸¶´Ù HPȸº¹ if (pAttacker->GetPoint(POINT_HIT_HP_RECOVERY) && number(0, 4) > 0) // 80% È®·ü { int i = MIN(dam, iCurHP) * pAttacker->GetPoint(POINT_HIT_HP_RECOVERY) / 100; if (i) { CreateFly(FLY_HP_SMALL, pAttacker); pAttacker->PointChange(POINT_HP, i); } } }
-
you can't "fix" this it depends on your hardware
- 1
-
Fix MoveItem Dupe Bug
in Bug Fixes
Posted