Jump to content
!-->
  • Join-Us

    https://metin2.dev is the 1st international community on Metin2 development. Join us to develop your skills and share your knowledge with the community, respectful and ethical forum.

Bug-Fix for Horses, Pets and Mounts on Observer Mode


Karbust

Recommended Posts

  • Web Developer

Sup guys

 DISCLAIMER: The code on this topic of only useful if have done changes to the Pet System (like putting it on the slot) and/or use the Mount System that follows the character if you have it on a slot. The code for the horse is valid for everyone.

 

This code was done by @ Mali and he asked me to share it.

 

This code is to fix a bug on observer mode, like guild wars.

  • If you have a pet on the slot and it respawns every time you teleport, this affects you.
  • If you have a mount on the slot and it respawns every time you teleport, this affects you.
  • If you only have the mount following you and you unmount while on observer, it will affect you.
  • This last one is also valid of the horse.

The bug consists on having any of the points described above which will make the pet, mount or horse visible to everyone when the player is in observer mode.

Something like this (the player Faisca is the observer on a guild war):

Spoiler

unknown.png

unknown.png

 

Let's start

Open char_horse.cpp, and after:

Spoiler
m_chHorse->SetRider(this);

Add:

Spoiler
m_chHorse->SetObserverMode(IsObserverMode());

Open PetSystem.cpp

Search for:

Spoiler
	if (0 != m_pkChar)
	{
		m_pkChar->Show (m_pkOwner->GetMapIndex(), x, y);
		m_dwVID = m_pkChar->GetVID();

		return m_dwVID;
	}

And make it like this:

Spoiler
	if (0 != m_pkChar)
	{
		m_pkChar->Show (m_pkOwner->GetMapIndex(), x, y);
		m_dwVID = m_pkChar->GetVID();

		m_pkChar->SetObserverMode(m_pkOwner->IsObserverMode());

		return m_dwVID;
	}

Search for:

Spoiler
m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y, z);

Add after: 

Spoiler
m_pkChar->SetObserverMode(m_pkOwner->IsObserverMode());

At the end of the file add this:

Spoiler
void CPetSystem::UpdateObserver()
{
	if (!m_pkOwner)
		return;

	const bool bFlag = m_pkOwner->IsObserverMode();

	for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
	{
		const CPetActor* petActor = iter->second;
		if (petActor == nullptr)
			continue;
		
		const LPCHARACTER petCh = petActor->GetCharacter();
		if (petCh)
			petCh->SetObserverMode(bFlag);
	}
}

Open PetSystem.h, and after:

Spoiler
void		DeletePet(CPetActor* petActor);

Add:

Spoiler
void		UpdateObserver();

Open entity.cpp

Inside this function:

Spoiler
void CEntity::SetObserverMode(bool bFlag)

Change it like this:

Spoiler
	if (IsType(ENTITY_CHARACTER))
	{
		LPCHARACTER ch = (LPCHARACTER) this;

		LPCHARACTER chHorse = ch->GetHorse();
		if (chHorse)
			chHorse->SetObserverMode(bFlag);

		CPetSystem* petSystem = ch->GetPetSystem();
		if (petSystem)
			petSystem->UpdateObserver();

		ch->ChatPacket(CHAT_TYPE_COMMAND, "ObserverMode %d", m_bIsObserver ? 1 : 0);
	}

 

You are finished if you don't use a special mount system.

 

Now, if you have the file MountSystem.cpp, open it, and search for:

Spoiler
	if (0 != m_pkChar)
	{
		m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y);
		m_dwVID = m_pkChar->GetVID();

		return m_dwVID;
	}

 

And edit like this:

Spoiler
	if (0 != m_pkChar)
	{
		m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y);
		m_dwVID = m_pkChar->GetVID();

		m_pkChar->SetObserverMode(m_pkOwner->IsObserverMode());

		return m_dwVID;
	}

Search for:

Spoiler
m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y, z);

Add after:

Spoiler
m_pkChar->SetObserverMode(m_pkOwner->IsObserverMode());

At the end of the file add this:

Spoiler
void CMountSystem::UpdateObserver()
{
    for (TMountActorMap::const_iterator iter = m_mountActorMap.begin(); iter != m_mountActorMap.end(); ++iter)
    {
        const CMountActor* mountActor = iter->second;
        if (mountActor == nullptr)
            continue;

        const LPCHARACTER mountCh = mountActor->GetCharacter();
        if (mountCh)
            mountCh->SetObserverMode(m_pkOwner->IsObserverMode());
    }
}

Open MountSystem.h, and after:

Spoiler
void		DeleteMount(CMountActor* mountActor);

Add:

Spoiler
void		UpdateObserver();

Then edit entity.cpp again like this:

Spoiler
	if (IsType(ENTITY_CHARACTER))
	{
		LPCHARACTER ch = (LPCHARACTER) this;

		LPCHARACTER chHorse = ch->GetHorse();
		if (chHorse)
			chHorse->SetObserverMode(bFlag);

		CPetSystem* petSystem = ch->GetPetSystem();
		if (petSystem)
			petSystem->UpdateObserver();

		CMountSystem* mountSystem = ch->GetMountSystem();
		if (mountSystem)
			mountSystem->UpdateObserver();

		ch->ChatPacket(CHAT_TYPE_COMMAND, "ObserverMode %d", m_bIsObserver ? 1 : 0);
	}

And your are finished.

Thanks again to @ Mali for helping me solve this issue.

Edited by Metin2 Dev
Core X - External 2 Internal
  • Metin2 Dev 20
  • Love 6
  • Love 1
  • Good 3
  • Lmao 1

QJ0orbR.png

Metin2 Icon Database

Link to comment
Share on other sites

First of all, in all of our name, thank you. If u agree me to correct something little.

 

Inside the entity.cpp modification there is a misstaken, (not in all source!!!).

Inside this function:

void CEntity::SetObserverMode(bool bFlag)

This change is problematic, because (in some source) the code calls the Pet character UpdateObserver function earlier then m_bIsObserver variable set to the new flag:

if (IsType(ENTITY_CHARACTER))
{
	LPCHARACTER ch = (LPCHARACTER) this;

	LPCHARACTER chHorse = ch->GetHorse();
	if (chHorse)
		chHorse->SetObserverMode(bFlag);

	CPetSystem* petSystem = ch->GetPetSystem();
	if (petSystem)
		petSystem->UpdateObserver();

	ch->ChatPacket(CHAT_TYPE_COMMAND, "ObserverMode %d", m_bIsObserver ? 1 : 0);
}

Its is not effective, because (in some source) when in the Pet character UpdateObserver function checks for the current  observer mode flag, the following function will returns the last value, not the new value what has been set later:

m_pkOwner->IsObserverMode();

 

So i recommend the following modification for fix this issue:

Open PetSystem.cpp

At the end of the file add this, or replace it with the old one:

void CPetSystem::UpdateObserver(bool bFlag)
{
	if (!m_pkOwner)
		return;
	
	for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
	{
		const CPetActor* petActor = iter->second;
		if (petActor == nullptr)
			continue;
		
		const LPCHARACTER petCh = petActor->GetCharacter();
		if (petCh)
			petCh->SetObserverMode(bFlag);
	}
}

 

Open PetSystem.h

Add or replace it with the old one after:

void		DeletePet(CPetActor* petActor);

This:

void		UpdateObserver(bool bFlag);

 

Open entity.cpp

Inside this function:

void CEntity::SetObserverMode(bool bFlag)

Change it like this:

if (IsType(ENTITY_CHARACTER))
{
	LPCHARACTER ch = (LPCHARACTER) this;

	LPCHARACTER chHorse = ch->GetHorse();
	if (chHorse)
		chHorse->SetObserverMode(bFlag);

	CPetSystem* petSystem = ch->GetPetSystem();
	if (petSystem)
		petSystem->UpdateObserver(bFlag);

	ch->ChatPacket(CHAT_TYPE_COMMAND, "ObserverMode %d", m_bIsObserver ? 1 : 0);
}

 

The problem is there in MountSystem too.

 

Correct me if im wrong. 🙂

Thanks for it again!

Edited by UdvAtt108
  • Metin2 Dev 8
  • Love 1
  • Think 1
Link to comment
Share on other sites



×
×
  • 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.