Jump to content

martysama0134

Honorable Member
  • Posts

    613
  • Joined

  • Last visited

  • Days Won

    96
  • Feedback

    100%

Posts posted by martysama0134

  1. I haven't tested the system, but there's something that you should always avoid if possible:

    using UniqueCharacterMap = std::map<UNIQUE_CHAR_POSITION, LPCHARACTER>;
    UniqueCharacterMap m_mapUniqueCharacter;

    You are directly storing the character ptr into the map, and, later on, calling GetUniqueCharacter to get the ptr back. There's a very good possibility of getting a dangling pointer.

    Purged monsters expire immediately, dead monsters in few seconds. One of the common issues of writing dungeons in c++ is actually this one.

    To be sure you're not getting a dangling pointer, you should store the VID of the monster instead of the ptr. This little change slightly affects performance though.

    This function should be enough to check the validity of a vid:

    LPCHARACTER FindValidCharacter(const VID & vid)
    {
    	if (!vid.GetID())
    		return nullptr;
    	const auto ch = CHARACTER_MANAGER::instance().Find(vid.GetID());
    	return (ch && !ch->IsDead()) ? ch : nullptr;
    }

     

    Thanks for sharing.

    • Metin2 Dev 1
    • Eyes 1
    • Good 2
    • Love 1
    • Love 2
  2. The M2 Download Center may not include the last changes I've committed: 

    This is the hidden content, please
     

    In the last commit, I've added a post-build event that "touches" system.c. (in v2.1 it touches _RESERVED)

    If you're asking why I've done this: visual studio has a known bug of not triggering the pre-build events after a "rebuild".

    • Metin2 Dev 25
    • Good 3
    • Love 3
    • Love 8
  3. 23 minutes ago, Jimmermania said:

    Hello guys,i installed mailbox from @ Mali, but when i try to log in i have this error:

    0725 13:30:07144 :: 
    networkmodule.py(line:211) networkmodule.MainStream.SetSelectCharacterPhase (C:\Users\George\Desktop\WoM2\Binary\Client\CRootLib\Workplace\RootLib\cyTemp\networkmodule.c:3901)
    system.py(line:169) system.__hybrid_import (C:\Users\George\Desktop\WoM2\Binary\Client\CRootLib\Workplace\RootLib\cyTemp\system.c:3889)
    introselect.py(line:32) init introselect (C:\Users\George\Desktop\WoM2\Binary\Client\CRootLib\Workplace\RootLib\cyTemp\introselect.c:30467)
    system.py(line:169) system.__hybrid_import (C:\Users\George\Desktop\WoM2\Binary\Client\CRootLib\Workplace\RootLib\cyTemp\system.c:3889)
    interfacemodule.py(line:52) init interfacemodule (C:\Users\George\Desktop\WoM2\Binary\Client\CRootLib\Workplace\RootLib\cyTemp\interfacemodule.c:58471)
    system.py(line:190) system.__hybrid_import (C:\Users\George\Desktop\WoM2\Binary\Client\CRootLib\Workplace\RootLib\cyTemp\system.c:4312)
    
    networkmodule.SetSelectCharacterPhase - <type 'exceptions.ImportError'>:No module named uimailbox
    
    0725 13:30:07144 :: ============================================================================================================
    0725 13:30:07144 :: Abort!!!!

    I added uimailbox at PythonrootlibManager.cpp, but when i compile .exe i have this error:

    Severity	Code	Description	Project	File	Line	Suppression State
    Error	LNK2001	unresolved external symbol _inituimailbox	UserInterface	

    Any ideas?

    1) You should add the uimailbox.c file in the cythonrootlib project.

    2) You should add the {"uimailbox",inituimailbox} import in the pythonrootlibmanager.cpp file.

    3) You have to be sure that the file is called&imported as uimailbox.py, and not differently. It's case sensitive, so uiMailBox may not work if the file isn't called uiMailBox.py

  4. This is what I did some time ago:

    DWORD GetHorseSkillSlotIndex()
    {
    	constexpr auto HorseSkillIndex = 130;
    	static DWORD RequireSkillSlotIndex = 0;
    	if (!RequireSkillSlotIndex)
    		CPythonPlayer::Instance().FindSkillSlotIndexBySkillIndex(HorseSkillIndex, &RequireSkillSlotIndex);
    	return RequireSkillSlotIndex;
    }
    
    bool CPythonPlayer::__CanUseSkill()
    {
    	CInstanceBase* pkInstMain=NEW_GetMainActorPtr();
    	if (!pkInstMain)
    		return false;
    
    	if (IsObserverMode())
    		return false;
    
    	// Terrible skill slot index managament
    	if (pkInstMain->IsMountingHorse() && (GetSkillGrade(GetHorseSkillSlotIndex()) < 1 && GetSkillLevel(GetHorseSkillSlotIndex()) < 20))
    		return false;
    
    	return pkInstMain->CanUseSkill();
    }
    
    bool CPythonPlayer::__CanAttack()
    {
    	if (__IsProcessingEmotion())
    		return false;
    
    	if (IsOpenPrivateShop())
    		return false;
    
    	if (IsObserverMode())
    		return false;
    
    	CInstanceBase* pkInstMain=NEW_GetMainActorPtr();
    	if (!pkInstMain)
    		return false;
    
    	// Terrible skill slot index managament
    	if (pkInstMain->IsMountingHorse() && pkInstMain->IsNewMount() && (GetSkillGrade(GetHorseSkillSlotIndex()) < 1 && GetSkillLevel(GetHorseSkillSlotIndex()) < 11))
    		return false;
    
    	return pkInstMain->CanAttack();
    }

    I haven't tested your solution, but using GetSkillSlotIndex should be better than FindSkillSlotIndexBySkillIndex.

    • Metin2 Dev 2
    • Good 1
  5. 12 minutes ago, ReFresh said:

    it's a global fix for all default sources?

    Yes, every source is affected. For the other registered effects (not fly), you should search for each GetCaseCRC32 call (a dozen) and fix the input with StringPath.

     

    12 minutes ago, ReFresh said:

    Did I do it right?

    Yes

    • Metin2 Dev 1
    • Eyes 1
  6. On 1/29/2020 at 6:10 PM, Karbust said:

    @xP3NG3Rx

    I have a couple of bugs:

    • Normal arrows don't have any effect
    • Skills don't have any effect (only the skill "warmup" before shooting) while shooting, neither normal arrows nor the quiver

    On Debug Target, the fly effects are not registered.

    You also need to check whether the GetCaseCRC32(filename) is getting mismatches due to UpPeRcAse!=lowercase and backslashes \\\ vs slashes /// or not. (most of the new boss effects are not displayed because of this)

    geeyoIs.png

    like this: (GameLib\RaceMotionDataEvent.h)

    			StringPath(strFlyFileName); //@fixme030
    			dwFlyIndex = GetCaseCRC32(strFlyFileName.c_str(), strFlyFileName.length());
    
    			// Register Fly
    			CFlyingManager::Instance().RegisterFlyingData(strFlyFileName.c_str());

    and also this one: (GameLib\FlyingInstance.cpp)

    mFm0kKH.png

    • Metin2 Dev 1
    • Good 2
    • Love 4
  7. 3 hours ago, Syreldar said:

    But based on what I see here, it means the target will also be pushed way farther than intended while usually targets with Immunity to Fall (mental warriors) get pushed way less.

    To solve this, I've tried to reduce the push by 20%:

    rHOdniw.png

            // VICTIM_COLLISION_TEST
            const D3DXVECTOR3& kVictimPos = rVictim.GetPosition();
            auto externalForceRatio = 1.0f;
            if (rVictim.IsResistFallen())
                externalForceRatio = 0.8f; // reduce external force almost like before
            rVictim.m_PhysicsObject.IncreaseExternalForce(kVictimPos, c_rAttackData.fExternalForce * externalForceRatio);
            // VICTIM_COLLISION_TEST_END

    ActorInstanceBattle.cpp CActorInstance::__ProcessDataAttackSuccess

     

    https://metin2.download/video/vMrt47r4elg57lFB6ym3v765UoC6q2MI/.mp4
    0.7f

    • Dislove 1
    • Good 2
    • Love 1
  8. 4 hours ago, WeedHex said:

    Hmmm, it's not properly a bug. It's happening because you are not making any movement in the victim.

    Anyway thanks to this thread, after some check, I figured out that may be this the problem:

     

    File ActorInstanceSync.cpp:

    Replace the function

    void CActorInstance::__Push(int x, int y)
    {
    	const D3DXVECTOR3& c_rv3Src=GetPosition();
    	const D3DXVECTOR3 c_v3Dst=D3DXVECTOR3(x, -y, c_rv3Src.z);
    	const D3DXVECTOR3 c_v3Delta=c_v3Dst-c_rv3Src;
    
    	const auto LoopValue = 100;
    	const D3DXVECTOR3 inc = c_v3Delta / LoopValue;
    
    	D3DXVECTOR3 v3Movement(0.0f, 0.0f, 0.0f);
    
    	IPhysicsWorld* pWorld = IPhysicsWorld::GetPhysicsWorld();
    	if (!pWorld)
    		return;
    
    	for (int i = 0; i < LoopValue; ++i)
    	{
    		if (pWorld->isPhysicalCollision(c_rv3Src + v3Movement))
    		{
    			ResetBlendingPosition();
    			return;
    		}
    		v3Movement += inc;
    	}
    
    	SetBlendingPosition(c_v3Dst);
    
    	if (IsResistFallen())
    		return;
    
    	if (!IsUsingSkill())
    	{
    		const int len = sqrt(c_v3Delta.x*c_v3Delta.x+c_v3Delta.y*c_v3Delta.y);
    		if (len > 150.0f)
    		{
    			InterceptOnceMotion(CRaceMotionData::NAME_DAMAGE_FLYING);
    			PushOnceMotion(CRaceMotionData::NAME_STAND_UP);
    		}
    	}
    }

     

    Yep, as you can see I just moved the order of execution of a statement. I leave the theory to you.

    This solves the issue client-side, but not server-side. When you respawn, you restart from where the one-sided fight started:

    d6gZGxv.png

    I'm gonna check it further more.

    After relogin:

    6fpyQAQ.png

    • Metin2 Dev 1
    • Good 1
    • Love 1
  9. 12 hours ago, VegaS™ said:

    UPDATE

    Alright, after some debugging:

      Reveal hidden contents

    VJr5VHF.png
    DMfpP3W.png

    Here is a fast fix and should work fine, I didn't test it so well.

    • UserInterface\PythonApplicationProcedure.cpp

     

    Hidden Content

     

    LRESULT CPythonApplication::WindowProcedure(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
    {
    	if (wParam == 0xF100)
    		return 1;
      
    	[...]
    }

     

     

    I've tested it and it seems fine. Gonna test it further more.

    I just prefer it like this:

    pMRG2qf.png

    	case WM_SYSCOMMAND:
    		if (wParam == SC_KEYMENU)
    			return 0;
    		break;

     

    Edit: I've changed the return 1L to return 0. Even (TRUE) should be fine (which is 1).

    https://docs.microsoft.com/en-us/windows/win32/menurc/wm-syscommand

    https://stackoverflow.com/a/4650605/7964985

    • Metin2 Dev 1
    • Good 2
    • Love 1
  10. On 5/31/2022 at 4:38 AM, Shizer said:

     

    Hello, I ran into a problem and I don't know how to solve it, namely my 24 inch monitor broke down recently, and I bought a new 28 inch, and part of the side panel is cut off in the world editor, how can I fix it? changing the resolution does not help, in the current one is 150 recommended, everywhere in other programs it works properly, and with world editor I have a problem unfortunately, can someone help me with it?

    https://metin2.download/picture/EbYmB3mGSKV2ddrA2ytVIEYw4K50nsDz/.png

    Try the latest version. If I remember correctly, it should fix it even without the external dpi manifest fix.

    • Metin2 Dev 1
    • Love 1
  11. 1 hour ago, sxvoyz said:
    void CHARACTER::Initialize()
    {
    	memset(&m_pointsInstant, 0, sizeof(m_pointsInstant));
    }

    That's why somebody got crash. Try define map/unordered_map outside this structure then everything will be alright.

    You probably got a warning in that line, but the solution is even simpler:

    	m_pointsInstant = {};

     

    • Good 1
    • Love 1
  12. There are far better solutions than using std::map or std::unordered_map (which still takes a lot of ram for no reason for each mob):

    (I included the most important parts)

    You also forgot the CubeItems, and we could probably fit the quickslot too.

    Spoiler

    u6xpuP5.png

    8l52tEd.png

    QuAep2f.png

    DyiEUfe.png

    ls2VRPX.png

    • Metin2 Dev 2
    • Good 7
    • Love 7
  13. The problem is not related to "some serverfiles", but to the servers' network.

    In theory, after you close the client (via "quit" cmdchat) the connection should be interrupted, but on some occasions they remained stucked, and that's the bug. The stucked character will probably remain online for 300s until the server will kick it.

    
    			case SCMD_QUIT:
    				ch->ChatPacket(CHAT_TYPE_COMMAND, "quit");
    				if (d)
    					d->SetPhase(PHASE_CLOSE);
    				break;

    I would try like this first, otherwise I'll stick with DelayedDisconnect(1) instead of SetPhase like:

    
    			case SCMD_QUIT:
    				ch->ChatPacket(CHAT_TYPE_COMMAND, "quit");
    				if (d)
    					d->DelayedDisconnect(1);
    				break;

     

    2 hours ago, Draveniou1 said:

    Its 100% fix without game.core or another problems

    			case SCMD_QUIT:
    				if (d)
    					d->DelayedDisconnect(2);
    					d->ChatPacket(CHAT_TYPE_COMMAND, "quit");
    				break;

     

    You're missing if (d) { ... } brackets. if you were to get a nullptr d, you'd end up with a core crash there.

    • Metin2 Dev 2
    • Good 3
    • Love 2
  14. 1 hour ago, xifati said:

    kr9BAPO.png

    It not works well with the vs19/22 titlebar, as you see the titlebar's top is slammed down. (It's white here, open the image in new tab)
    Is it possible to fix somehow? or change the titlebar height smaller like it was in vs2013?

    I cut it in order to see the whole client in 1920x1080 res (otherwise the Windows taskbar will eat up some pixels), Set titlebarSize to 0, otherwise set titlebarSize to 0 only if m_pySystem.GetHeight() >= 1000.

    auto titlebarSize = (m_pySystem.GetHeight() >= 1000) ? 10 : 0;

     

    • Metin2 Dev 3
    • Good 1
  15. 7 hours ago, Abel(Tiger) said:

    Those ~5px are for the shadows if I'm not mistaken.

    Also the ideea made by Ymir to open the client in two diferent position is stupid.

    I consider opening the windowed client on the center it's the best solution:

    		if (Windowed)
    		{
    			m_isWindowed = true;
    
    			RECT rc;
    			GetClientRect(&rc);
    		
    			int windowWidth = rc.right - rc.left;
    			int windowHeight = (rc.bottom - rc.top);
    		
    			// 80 is the gap for the taskbar, you can increase it
    			CMSApplication::SetPosition((GetScreenWidth() - windowWidth) / 2, (GetScreenHeight() - windowHeight - 80) / 2);
    		}
    		else
    		{
    			m_isWindowed = false;
    			SetPosition(0, 0);
    		}

     

    I used GetWindowRect to calculate the dropshadow area automatically:

    		AdjustSize(m_pySystem.GetWidth(), m_pySystem.GetHeight());
    
    		if (Windowed)
    		{
    			m_isWindowed = true;
    			RECT rc{};
    			GetClientRect(&rc);
    			auto windowWidth = rc.right - rc.left;
    			auto windowHeight = (rc.bottom - rc.top);
    			//TraceError("windowWidth %d == %d windowHeight %d == %d", windowWidth, m_pySystem.GetWidth(), windowHeight, m_pySystem.GetHeight());
    			RECT rc2{};
    			GetWindowRect(&rc2);
    			auto windowWidth2 = rc2.right - rc2.left;
    			auto windowHeight2 = (rc2.bottom - rc2.top);
    			//TraceError("windowWidth2 %d windowHeight2 %d", windowWidth2, windowHeight2);
    			auto windowWidthDiff = windowWidth2 - windowWidth;
    			auto windowHeightDiff = windowHeight2 - windowHeight;
    			//TraceError("windowWidthDiff %d windowHeightDiff %d", windowWidthDiff, windowHeightDiff);
    			//TraceError("GetLastError %d", ::GetLastError());
    			constexpr auto taskbarSize = 80;
    			auto dropshadowSize = (windowWidthDiff / 2 != 0) ? (windowWidthDiff / 2 - 1) : 0;
    			CMSApplication::SetPosition(((GetScreenWidth() - windowWidth) / 2) - dropshadowSize, (GetScreenHeight() - windowHeight - taskbarSize) / 2);
    		}
    		else
    		{
    			m_isWindowed = false;
    			SetPosition(0, 0);
    		}

    This one is for 1920x1080 res

    https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect

    Old way with second window:

    		AdjustSize(m_pySystem.GetWidth(), m_pySystem.GetHeight());
    
    		if (Windowed)
    		{
    			m_isWindowed = true;
    			RECT rc{};
    			GetClientRect(&rc);
    			auto windowWidth = rc.right - rc.left;
    			auto windowHeight = (rc.bottom - rc.top);
    			//TraceError("windowWidth %d == %d windowHeight %d == %d", windowWidth, m_pySystem.GetWidth(), windowHeight, m_pySystem.GetHeight());
    			RECT rc2{};
    			GetWindowRect(&rc2);
    			auto windowWidth2 = rc2.right - rc2.left;
    			auto windowHeight2 = (rc2.bottom - rc2.top);
    			//TraceError("windowWidth2 %d windowHeight2 %d", windowWidth2, windowHeight2);
    			auto windowWidthDiff = windowWidth2 - windowWidth;
    			auto windowHeightDiff = windowHeight2 - windowHeight;
    			//TraceError("windowWidthDiff %d windowHeightDiff %d", windowWidthDiff, windowHeightDiff);
    			//TraceError("GetLastError %d", ::GetLastError());
    			auto dropshadowSize = (windowWidthDiff / 2 != 0) ? (windowWidthDiff / 2 - 1) : 0;
    #ifdef ENABLE_CENTERED_CLIENT_WINDOW
    			constexpr auto taskbarSize = 80;
    			CMSApplication::SetPosition(((GetScreenWidth() - windowWidth) / 2) - dropshadowSize, (GetScreenHeight() - windowHeight - taskbarSize) / 2);
    #else
    			constexpr auto taskbarSize = 73;
    			constexpr auto titlebarSize = 10;
    			if (bAnotherWindow)
    				CMSApplication::SetPosition(GetScreenWidth() - windowWidth - dropshadowSize, GetScreenHeight() - windowHeight - taskbarSize);
    			else
    				SetPosition(-dropshadowSize, -titlebarSize);
    #endif
    		}
    		else
    		{
    			m_isWindowed = false;
    			SetPosition(0, 0);
    		}

     

    • Metin2 Dev 18
    • Good 6
    • Love 7
  16. On 9/18/2021 at 2:23 AM, Helia01 said:

    I'm not saying that this is an ideal solution. If you have any ideas, please write comments.

    If m_DamageQueue' size() is bigger than 20 elements, you can just pop() the old one. Just 2 lines of code required.

    I suggest you to change its type from std::list to std::queue.

    • Good 4
  17. On 9/16/2021 at 2:34 PM, Distraught said:

    The effects you use on your maps are not managed by EffectManager. They are managed by the Area itself.

    I've checked them, and they don't stack up. The loaded effects will keep being played as a loop until you move outside of the closed 2x2 area.

    pHlKKTH.png

    wjRlKI6.png

    WEf9uNj.png

    In here there was only one element inside m_EffectInstanceMap, and rkEftMgr.DestroyUnsafeEffectInstance has never being called.

    I initially thought to move the CArea::__UpdateEffectList call inside CPythonBackground::Update, but we probably don't even need to do so if there are no temporary effects in the maps.

    • Metin2 Dev 2
    • Good 3
  18. The black screen was mostly caused by two major bugs:

    1. The granny controller freezing the process for n seconds until you get dc'd from the game
      1. You can test it by:
      2. Spawning tons of monsters
      3. Minimize the client for 30 - 40 minutes
      4. Maximizing the window again (it will freeze exactly at this point)
    2. The EffectManager not destroying the expired effects while the window was minimized, which caused all the executed effects to stack up and be run all at once after maximizing the window again
      1. You can test this bug very easily:
      2. Spawn tons Flame Ghosts and minimize the window
        1. /ma "Flame Ghost" 100
        2. /cannot_dead

    I wasn't sure how to solve the 1st one, but for the 2nd one you can fix it in one of these ways:

     

    151605UCH22zd.png

    1st Way) refresh only once every 256 frames = 4-6 seconds depending on the lag

     

    1516050B26Z93.png

    2nd Way) effect manager refresh for every frame

     

    151605kBI2BOi.png

    3rd Way) move the update from RenderGame to UpdateGame (it may not be called if skipFrame=true on ::Process)

    • Metin2 Dev 62
    • Angry 1
    • Think 3
    • Confused 1
    • Scream 1
    • Good 27
    • Love 9
    • Love 28
×
×
  • 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.