Jump to content

Fix SKILL_FLAG_CRUSH | SKILL_FLAG_CRUSH_LONG


Recommended Posts

  • Active+ Member

This is a nasty bug where a boss can throw you inside a wall if he hits you with a skill that has SKILL_FLAG_CRUSH or SKILL_FLAG_CRUSH_LONG.

 

// char_skill.cpp
// Search:
			if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_CRUSH | SKILL_FLAG_CRUSH_LONG) &&
				!IS_SET(pkChrVictim->GetAIFlag(), AIFLAG_NOMOVE))
			{
				...
			}

// Replace the if with:
			if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_CRUSH | SKILL_FLAG_CRUSH_LONG) &&
				!IS_SET(pkChrVictim->GetAIFlag(), AIFLAG_NOMOVE))
			{
				float fCrushSlidingLength = 200;

				if (m_pkChr->IsNPC())
					fCrushSlidingLength = 400;

				if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_CRUSH_LONG))
					fCrushSlidingLength *= 2;

				float fx, fy;
				float degree = GetDegreeFromPositionXY(m_pkChr->GetX(), m_pkChr->GetY(), pkChrVictim->GetX(), pkChrVictim->GetY());

				if (m_pkSk->dwVnum == SKILL_HORSE_WILDATTACK)
				{
					degree -= m_pkChr->GetRotation();
					degree = fmod(degree, 360.0f) - 180.0f;

					if (degree > 0)
						degree = m_pkChr->GetRotation() + 90.0f;
					else
						degree = m_pkChr->GetRotation() - 90.0f;
				}

				GetDeltaByDegree(degree, fCrushSlidingLength, &fx, &fy);
				
				long startX = (long)(pkChrVictim->GetX());
				long startY = (long)(pkChrVictim->GetY());
				
				long endX = (long)(pkChrVictim->GetX() + fx);
				long endY = (long)(pkChrVictim->GetY() + fy);

				// We asume all positions between the start and end point are movable
				bool allPositionsMovable = true;
				
				// Calculate the distance between the start and end points
				double distance = std::sqrt((endX - startX) * (endX - startX) + (endY - startY) * (endY - startY));

				// Calculate the step size for each coordinate
				double stepX = (endX - startX) / distance;
				double stepY = (endY - startY) / distance;

				// Check if all points on the trajectory between startX, startY and endX, endY are movable
				for (double i = 0; i <= distance; ++i) {
					double currentX = startX + i * stepX;
					double currentY = startY + i * stepY;

					long roundedX = static_cast<long>(std::round(currentX));
					long roundedY = static_cast<long>(std::round(currentY));

					if (!SECTREE_MANAGER::instance().IsMovablePosition(pkChrVictim->GetMapIndex(), roundedX, roundedY)) {
						allPositionsMovable = false;
						break;
					}
				}

				if (allPositionsMovable)
				{
					sys_log(0, "CRUSH SUCCESS! %s -> %s (%d %d) -> (%d %d)", m_pkChr->GetName(), pkChrVictim->GetName(), pkChrVictim->GetX(), pkChrVictim->GetY(), (long)(pkChrVictim->GetX()+fx), (long)(pkChrVictim->GetY()+fy));
				
					pkChrVictim->Sync(endX, endY);
					pkChrVictim->Goto(endX, endY);
					pkChrVictim->CalculateMoveDuration();
				}
				else
				{
					sys_log(0, "CRUSH FAIL! %s -> %s (%d %d) -> (%d %d)", m_pkChr->GetName(), pkChrVictim->GetName(), pkChrVictim->GetX(), pkChrVictim->GetY(), (long)(pkChrVictim->GetX()+fx), (long)(pkChrVictim->GetY()+fy));	
				}

				if (m_pkChr->IsPC() && m_pkChr->m_SkillUseInfo[m_pkSk->dwVnum].GetMainTargetVID() == (DWORD) pkChrVictim->GetVID())
				{
					SkillAttackAffect(pkChrVictim, 1000, IMMUNE_STUN, m_pkSk->dwVnum, POINT_NONE, 0, AFF_STUN, 4, m_pkSk->szName);
				}
				else
				{
					if (allPositionsMovable)
						pkChrVictim->SyncPacket();
				}
			}

 

  • Metin2 Dev 5
  • Good 1
  • Love 7
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.