void do_GMGoPC(CPC *a1, char *a2)
{
    CPC *v5; // [sp+20h] [bp-8h]@7

    if(a2 && *a2)
    {
        TrimString(a2);
        if(strcmp(a2, a1->Unk8))
        {
            for(int i = 0; i < gserver.Unk24.Unk32768; ++i)
            {
                v5 = gserver.Unk24.Unk0[i]; // gserver.Unk20[i + 1]
                if(v5 && !strcmp(v5->Unk8, a2))
                {
                    if(v5->Unk408 == a1->Unk408)
                    {
                        GoTo(a1, v5->Unk120.Unk16, v5->Unk120.Unk0, v5->Unk120.Unk4, a1->Unk412->GetHeight(v5->Unk120.Unk16, v5->Unk120.Unk0, v5->Unk120.Unk4), a1->Unk120.Unk12);
                    }
                    else
                    {
                        if(v5->Unk408->Unk0 != 2 && v5->Unk408->Unk0 != 5 && v5->Unk408->Unk0 != 6)
                        {
                            GoZone(a1, v5->Unk408->Unk0, v5->Unk120.Unk16, v5->Unk120.Unk0, v5->Unk120.Unk4);
                        }
                    }

                    return;
                }
            }

            CNetMsg v4;

            SayMsg(v4, 6, 0, "", "", "Not Found the PC");

            if(a1->Unk768)
                a1->Unk768->WriteToOutput(v4);
        }
    }
}
// 믈리 어택
void do_pd_Attack(CPC* pc, CNetMsg::SP& msg)
{
	CDratanCastle * pCastle = CDratanCastle::CreateInstance();
	pCastle->CheckRespond(pc);

	RequestClient::doPDAttack* packet = reinterpret_cast<RequestClient::doPDAttack*>(msg->m_buf);

	if (packet->multicount > 20)
	{
		LOG_ERROR("HACKING : invalid multi count[%d]. charIndex[%d]", packet->multicount, pc->m_index);
		pc->m_desc->Close("invalid multi count");
		return;
	}

	// multi target의 중복 검사
	if (packet->multicount > 1)
	{
		std::set<int> tset;
		for (int i = 0; i < packet->multicount; ++i)
		{
			if (tset.insert(packet->list[i].index).second == false)
			{
				LOG_ERROR("HACKING : duplicate multi target[%d]. charIndex[%d]", packet->list[i].index, pc->m_index);
				pc->m_desc->Close("duplicate multi target");
				return;
			}
		}
	}

	// 대상 검색 : 인접 셀에서만
	CArea* area = pc->m_pArea;
	if (area == NULL)
	{
		LOG_ERROR("HACKING : not found area. charIndex[%d]", pc->m_index);
		pc->m_desc->Close("not found area");
		return;
	}

	CCharacter* tch = area->FindCharInCell(pc, packet->tIndex, (MSG_CHAR_TYPE)packet->tCharType);
	if (tch == NULL)
		return;

	int preIndex = -1;
	for (int i = 0; i < packet->multicount; ++i)
	{
		if(preIndex == packet->list[i].index)
		{
			// 가까운 마을로
			int nearZone;
			int nearZonePos;
			CZone* pZone = gserver->FindNearestZone(pc->m_pZone->m_index, GET_X(pc), GET_Z(pc), &nearZone, &nearZonePos);
			if (pZone == NULL)
				return;

			GoZone(pc, nearZone,
				   pZone->m_zonePos[nearZonePos][0],															// ylayer
				   GetRandom(pZone->m_zonePos[nearZonePos][1], pZone->m_zonePos[nearZonePos][3]) / 2.0f,		// x
				   GetRandom(pZone->m_zonePos[nearZonePos][2], pZone->m_zonePos[nearZonePos][4]) / 2.0f);		// z

			return;
		}

		preIndex = packet->list[i].index;

		CCharacter* ch = area->FindCharInCell(pc, packet->list[i].index, (MSG_CHAR_TYPE) MSG_CHAR_NPC);

		if(!ch) continue;

		if( !IS_NPC(ch) )
		{
			CPC* bugPC = NULL;
			if( IS_ELEMENTAL(ch) )
			{
				CElemental *ele = TO_ELEMENTAL(ch);
				bugPC = ele->GetOwner();
			}
			if( IS_PET(ch) )
			{
				CPet* pet = TO_PET(ch);
				bugPC = pet->GetOwner();
			}

			if( IS_PC(ch) )
			{
				bugPC = TO_PC(ch);
			}

			if( !bugPC )
				return;

			// 가까운 마을로
			int nearZone;
			int nearZonePos;
			CZone* pZone = gserver->FindNearestZone(bugPC->m_pZone->m_index, GET_X(bugPC), GET_Z(bugPC), &nearZone, &nearZonePos);
			if (pZone == NULL)
				return;

			GoZone(bugPC, nearZone,
				   pZone->m_zonePos[nearZonePos][0],															// ylayer
				   GetRandom(pZone->m_zonePos[nearZonePos][1], pZone->m_zonePos[nearZonePos][3]) / 2.0f,		// x
				   GetRandom(pZone->m_zonePos[nearZonePos][2], pZone->m_zonePos[nearZonePos][4]) / 2.0f);		// z

			GAMELOG << init("PD_BUG", bugPC)
					<< end;
			return;
		}

		int ret = ProcAttack(ch, tch, ch->GetAttackType(NULL), NULL, 0);
		if (ret == -1)
			return ;
	}
}
void do_PremiumChar_Jump(CPC* ch, CNetMsg::SP& msg)
{
	if (ch->m_premiumChar.isActive() == false)
	{
		CNetMsg::SP rmsg(new CNetMsg);
		ResponseClient::makePremiumCharJumpToChar(rmsg, ERR_PREMIUM_CHAR_NOT_PREMIUM_CHAR);
		SEND_Q(rmsg, ch->m_desc);
		return;
	}

	if (ch->CanWarp() != 0)
	{
		CNetMsg::SP rmsg(new CNetMsg);
		ResponseClient::makePremiumCharJumpToChar(rmsg, ERR_PREMIUM_CHAR_NOT_JUMP_STATUS);
		SEND_Q(rmsg, ch->m_desc);
		return;
	}

	RequestClient::premiumChar_JumpToChar* packet = reinterpret_cast<RequestClient::premiumChar_JumpToChar*>(msg->m_buf);
	packet->toCharName[MAX_CHAR_NAME_LENGTH] = '\0';

	CPC* pToChar = PCManager::instance()->getPlayerByName(packet->toCharName, false);
	if (pToChar == NULL)
	{
		CNetMsg::SP rmsg(new CNetMsg);
		ResponseClient::makePremiumCharJumpToChar(rmsg, ERR_PREMIUM_CHAR_NOT_FOUNC_CHAR);
		SEND_Q(rmsg, ch->m_desc);

		return;
	}

	if (ch->m_premiumChar.getJumpCount() >= PREMIUM_CHAR_JUMP_COUNT_MAX)
	{
		CNetMsg::SP rmsg(new CNetMsg);
		ResponseClient::makePremiumCharJumpToChar(rmsg, ERR_PREMIUM_CHAR_MAX_JUMP_COUNT);
		SEND_Q(rmsg, ch->m_desc);

		return;
	}

	// 점프할 대상이 친구인가?
	CFriendMember* pFriend = ch->m_Friend->FindFriendMember(pToChar->m_index);
	if (pFriend == NULL)
	{
		CNetMsg::SP rmsg(new CNetMsg);
		ResponseClient::makePremiumCharJumpToChar(rmsg, ERR_PREMIUM_CHAR_NOT_FOUNC_CHAR);
		SEND_Q(rmsg, ch->m_desc);

		return;
	}

	// 친구의 상태가 offline인가?
	if (pFriend->GetCondition() == MSG_FRIEND_CONDITION_OFFLINE)
	{
		CNetMsg::SP rmsg(new CNetMsg);
		ResponseClient::makePremiumCharJumpToChar(rmsg, ERR_PREMIUM_CHAR_FRIEND_IS_OFFLINE);
		SEND_Q(rmsg, ch->m_desc);

		return;
	}

	// 친구한테 점프할수 있는가? item 857과 동일한 조건으로 검사 (패킷 MSG_WARP)
	if (isPossibleWarp(ch, pToChar) == false)
	{
		CNetMsg::SP rmsg(new CNetMsg);
		ResponseClient::makePremiumCharJumpToChar(rmsg, ERR_PREMIUM_CHAR_INVALID_JUMPING_POSITION);
		SEND_Q(rmsg, ch->m_desc);

		return;
	}

	// 대상으로 점핑하기
	if(ch->m_pZone->m_index != pToChar->m_pZone->m_index)
		ch->SetPlayerState(PLAYER_STATE_CASH_ZONE_MOVE);

	if(!GoZone(ch, pToChar->m_pZone->m_index, pToChar->m_pos.m_yLayer, pToChar->m_pos.m_x, pToChar->m_pos.m_z))
	{
		if(ch->IsSetPlayerState(PLAYER_STATE_CASH_ZONE_MOVE))
			ch->ResetPlayerState(PLAYER_STATE_CASH_ZONE_MOVE);

		CNetMsg::SP rmsg(new CNetMsg);
		ResponseClient::makePremiumCharJumpToChar(rmsg, ERR_PREMIUM_CHAR_INVALID_JUMPING_POSITION);
		SEND_Q(rmsg, ch->m_desc);

		return;
	}

	ch->m_premiumChar.setJumpCount(ch->m_premiumChar.getJumpCount() + 1);

	{
		CNetMsg::SP rmsg(new CNetMsg);
		ResponseClient::makePremiumCharJumpToChar(rmsg, ERR_PREMIUM_CHAR_NONE);
		SEND_Q(rmsg, ch->m_desc);
	}
}
void do_NPCRegen(CPC *a1, CNetMsg &a2)
{
    int v21; // [sp+28h] [bp-30h]@9
    CNPC *v23; // [sp+30h] [bp-28h]@6
    CZone *v24; // [sp+34h] [bp-24h]@7
    float v25; // [sp+38h] [bp-20h]@1
    float v26; // [sp+3Ch] [bp-1Ch]@1
    float v27; // [sp+40h] [bp-18h]@1
    float dest; // [sp+44h] [bp-14h]@1
    int src; // [sp+48h] [bp-10h]@1
    char v30; // [sp+4Ch] [bp-Ch]@1
    int v31; // [sp+50h] [bp-8h]@1
    int v32; // [sp+54h] [bp-4h]@1

    a2.MoveFirst();

    a2.__rs(v32);
    a2.__rs(v31);
    a2.__rs(dest);
    a2.__rs(v27);
    a2.__rs(v26);
    a2.__rs(v25);
    a2.__rs(v30);
    a2.__rs(src);

    if(v32 == -1)
    {
        if(a1->Unk408->Unk0 == 2 || a1->Unk408->Unk0 == 5 || a1->Unk408->Unk0 == 6)
        {
            ++a1->Unk412->Unk72;
            if(a1->Unk412->Unk32.Unk8 >= a1->Unk412->Unk72)
            {
                v23 = gserver.Unk452200.Create(v31);
                if(v23)
                {
                    v23->Unk120.Unk0  = dest;
                    v23->Unk476       = dest;
                    v23->Unk120.Unk4  = v27;
                    v23->Unk484       = v27;
                    v23->Unk120.Unk16 = v30;
                    v23->Unk480       = v30;
                    v23->Unk120.Unk12 = v25;
                    v23->Unk120.Unk8  = v26;

                    int v24_2;

                    a1->Unk412->AddNPC(v23);
                    a1->Unk412->PointToCellNum(v23->Unk120.Unk0, v23->Unk120.Unk4, &v24_2, &v21);
                    a1->Unk412->CharToCell(v23, v23->Unk120.Unk16, v24_2, v21);

                    CNetMsg v20;

                    NPCRegenMsg(v20, v23, src);

                    a1->Unk412->SendToCell(v20, a1, 1, 4);
                }
            }
            else
            {
                int v23_2 = gserver.FindZone(0);
                if(v23_2 != -1)
                {
                    v24 = &gserver.Unk452196[v23_2];
                    GoZone(a1, 0, v24->Unk52[0]->Unk0, GetRandom(v24->Unk52[0]->Unk4, v24->Unk52[0]->Unk12) / 2.0, GetRandom(v24->Unk52[0]->Unk8, v24->Unk52[0]->Unk16) / 2.0);
                }
            }
        }
    }
}