Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

C++ Blokada wizualnych itemów


Rekomendowane odpowiedzi

Opublikowano

Od dawna wiadomo ze można pokazać na chat item jaki się tylko chce używając kodu tego samego co wykorzystuje Szkło intuicji czyli np:

|cfff1e6c0|Hitem:13:0:6fe1:0:0:1:11111|h[Miecz+9]|h|r

Miecz +9 z kd Witalności +5 i 11111 hp

 

Wielu ludzi dzięki temu robi plotki ze ma EQ z "navi" i robią rożne ss potem są na MPC i zaczyna się gównoburza jednak da się to zablokować, sam stosuje to od półtora roku i działa dlatego podzielę się z wami tym. 

 

Blokada jest po stronie serwera więc nie jest możliwa do obejścia ponieważ jeśli wysyłasz przedmiot na chat by pokazać jest on sprawdzany przez funkcje czy masz taki w EQ jak nie to wiadomość nie zostanie wysłana, zapewne znajdą się tu miszcze c++ i metina którzy stwierdza że to będzie lagować serwer i ma dziury ale do rzeczy.

 

 

Instalacja w source

 

Otwieramy game/src/char.h i szukamy w tym pliku

		LPITEM			FindSpecifyItem(DWORD vnum) const;

Dodajemy pod tą linia (tworząc nową enterem):

		bool 			CheckSpecifyItem(DWORD vnum, const char * name, std::vector<long> kd, std::vector<TPlayerItemAttribute> attr);

Ma wyglądać tak

 

VrHN52G.png

 

 

 

Zapisujemy i zamykamy.

 

Teraz otwieramy plik game/src/char_item.cpp i na końcu pliku dodajemy

 

bool CHARACTER::CheckSpecifyItem(DWORD vnum, const char * name, std::vector<long> kd, std::vector<TPlayerItemAttribute> attr)
{
	bool isOk = false;
	for (int i = 0; i < (INVENTORY_MAX_NUM + WEAR_MAX_NUM); ++i)
	{
		LPITEM item = GetInventoryItem(i);
		if (!item)
			continue;
		if (item->GetVnum() == vnum){
			bool stones = false;
			for (int s = 0; s < item->GetSocketCount(); ++s)
				if (kd.size() > s && item->GetSocket(s) == kd[s])
					stones = true;			
			bool attrs = false;
			for (int a = 0; a < item->GetAttributeCount(); a++)
				if (attr.size()>a && item->GetAttributeType(a) == attr[a].bType && item->GetAttributeValue(a) == attr[a].sValue)
					attrs = true;
			if (item->GetAttributeCount() == 0 && attr.size() == 0)
				attrs = true;
			if (!stones || !attrs)
				continue;
			return true;
		}
	}
	
	return false;
} 

 

 

Po wklejeniu ma wyglądać tak

HzGwauw.png

 

Ważne jest by czasem nie usunąć klamry } z funkcji wyżej.

 

Zapisujemy i zamykamy.

 

Teraz otwieramy plik game/src/input_main.cpp i szukamy

int GetTextTag(const char * src, int maxLen, int & tagLen, std::string & extraInfo)

I dodajemy pod ta funkcja nowa funkcje

 

#include <stdlib.h>
#include <boost/algorithm/string.hpp> 
int CheckItem(std::string itemChat,LPCHARACTER ch)
{
	std::vector<std::string> results2;
	int  hyperlinks = 0;

	int len;
	std::string extraInfo;
	const char * src = itemChat.c_str();
	size_t src_len=itemChat.length();
	for (int i = 0; i < src_len;)
	{
		int tag = GetTextTag(&src[i], src_len - i, len, extraInfo);

		if (tag == TEXT_TAG_HYPERLINK_START)
			++hyperlinks;

		i += len;
	}
	if(hyperlinks <=0) 
		return 1;
	boost::split(results2, itemChat, boost::is_any_of("|H"));
	for(int i=0;i<results2.size();i++){
		if(results2[i].find("cFF")!=std::string::npos || results2[i].find("cff")!=std::string::npos){
			if (results2[i].find("cfff1e6c0")==std::string::npos && results2[i].find("cffffc700")==std::string::npos)
				return 2;
		}	
		if (results2[i].find("item")!=std::string::npos)
		{
			std::vector<std::string> item_info;
			boost::split(item_info, results2[i], boost::is_any_of(":"));
			if (item_info.size() <ITEM_SOCKET_MAX_NUM+2 || results2.size())
				return 4;

			int col = 1;
			std::string name = results2[i+1];
			boost::replace_all(name, "[", "");
			boost::replace_all(name, "]", "");

			DWORD  vnum = std::strtoul(item_info[col++].c_str(), 0, 16);
			col++;//flag
			std::vector<long> kd;
			for (int i = 0; i<ITEM_SOCKET_MAX_NUM; i++){
				kd.push_back(std::strtoul(item_info[col++].c_str(), 0, 16));
			}
			std::vector<TPlayerItemAttribute> attr;
			for (int i = 0; i<ITEM_ATTRIBUTE_MAX_NUM; i++){
				if (col>=item_info.size())
					break;
				TPlayerItemAttribute t;
				t.bType = std::strtoul(item_info[col++].c_str(), 0, 16);
				t.sValue = std::strtoul(item_info[col++].c_str(), 0, 16);
				attr.push_back(t);
			}
				
			
				
			if(!ch->CheckSpecifyItem(vnum,name.c_str(),kd,attr))
			{	
				return 4;
			}		
			
			
			
			
		}
	}
	return 1;
} 

 

 

 

Ma wyglądać tak

0DCcs81.gif

 

 

Teraz szukamy w tym samym pliku

const size_t buflen = strlen(buf);

Występuje ta linia w 2 funkcjach my zaczynamy od CInputMain::Whisper

I dodajemy pod ta linia

                int err = CheckItem(buf, ch);
		if(err==4){
			ch->ChatPacket(CHAT_TYPE_INFO, "Wystąpił podczas parsowania informacji o przedmiocie,wiadomość nie została wysłana!");
			return iExtraLen;
		}
		if(err==2){
			ch->ChatPacket(CHAT_TYPE_INFO, "Wystąpił podczas parsowania wiadomości,wiadomość nie została wysłana!");
			return iExtraLen;
		}

Ma wyglądać tak

KSiPkhx.png

 

 

 

Teraz szukamy ponownie lini 

const size_t buflen = strlen(buf);

Tylko tym razem w funkcji CInputMain::Chat i postępujemy tak samo jak funkcji opisanej wyżej.

 

Zapisujemy, zamykamy i możemy kompilować game, ważne jest by kompilować je od nowa czyli wpisując komendę:

gmake clean

Następnie

gmake

Dla tych co mają mocniejsze komputery bądź source maja na dedyku/vps mogą przyśpieszyć ten proces dopisując do komendy -j20

 

 

Bonus

Domyślnie na chat pokazuje się przedmiot maksymalnie z 3 slotami KD, by to odblokować by pokazywało prawdziwą ilość wystarczy edytować 2 funkcje w source klienta i root.

 

Otwieramy plik Userinterface/PythonPlayerModule.cpp i szukamy funkcji

PyObject * playerGetItemLink(PyObject * poSelf, PyObject * poArgs)

I zamieniamy cały kod funkcji na

 

PyObject * playerGetItemLink(PyObject * poSelf, PyObject * poArgs)
{
	TItemPos Cell;

	switch (PyTuple_Size(poArgs))
	{
	case 1:	
		if (!PyTuple_GetInteger(poArgs, 0, &Cell.cell))
			return Py_BuildException();
		break;
	case 2:
		if (!PyTuple_GetByte(poArgs, 0, &Cell.window_type))
			return Py_BuildException();
		if (!PyTuple_GetInteger(poArgs, 1, &Cell.cell))
			return Py_BuildException();
		break;
	default:
		return Py_BuildException();
	}
	const TItemData * pPlayerItem = CPythonPlayer::Instance().GetItemData(Cell);
	CItemData * pItemData = NULL;
	char buf[1024];

	if (pPlayerItem && CItemManager::Instance().GetItemDataPointer(pPlayerItem->vnum, &pItemData))
	{
		char itemlink[256];
		int len;
		bool isAttr = false;

		len = snprintf(itemlink, sizeof(itemlink), "item:%x:%x",pPlayerItem->vnum, pPlayerItem->flags);

		for (int i = 0; i < ITEM_SOCKET_SLOT_MAX_NUM; ++i)
			len += snprintf(itemlink+len, sizeof(itemlink), ":%x",pPlayerItem->alSockets[i]);
		for (int i = 0; i < ITEM_ATTRIBUTE_SLOT_MAX_NUM; ++i)
			if (pPlayerItem->aAttr[i].bType != 0)
			{
				len += snprintf(itemlink + len, sizeof(itemlink) - len, ":%x:%d", 
						pPlayerItem->aAttr[i].bType, pPlayerItem->aAttr[i].sValue);
				isAttr = true;
			}

			if (isAttr)
				//"item:ąřČŁ:ÇĂ·ˇ±×:ĽŇÄĎ0:ĽŇÄĎ1:ĽŇÄĎ2"
				snprintf(buf, sizeof(buf), "|cffffc700|H%s|h[%s]|h|r", itemlink, pItemData->GetName());
			else
				snprintf(buf, sizeof(buf), "|cfff1e6c0|H%s|h[%s]|h|r", itemlink, pItemData->GetName());
		
	}
	else
		buf[0] = '\0';

	return Py_BuildValue("s", buf);
}

 

 

 

Ma wyglądać tak

CvIGgMg.gif

 

 

Zapisujemy, zamykamy.

 

Teraz w pliku Userinterface/PythonChatModule.cpp szukamy funkcji

PyObject * chatGetLinkFromHyperlink(PyObject * poSelf, PyObject * poArgs)

I zamieniamy cały kod funkcji na

 

PyObject * chatGetLinkFromHyperlink(PyObject * poSelf, PyObject * poArgs)
{
	char * szHyperlink;
	
	if (!PyTuple_GetString(poArgs, 0, &szHyperlink))
		return Py_BuildException();

	std::string stHyperlink(szHyperlink);
	std::vector<std::string> results;

	split_string(stHyperlink, ":", results, false);

	// item:vnum:flag:socket0:socket1:socket2
	if (0 == results[0].compare("item"))
	{
		if (results.size() < 9)
			return Py_BuildValue("s", "");

		CItemData * pItemData = NULL;

		if (CItemManager::Instance().GetItemDataPointer(htoi(results[1].c_str()), &pItemData))
		{
			char buf[1024] = { 0 };
			char itemlink[256];
			int len;
			bool isAttr = false;
			int col = 1;
			len = snprintf(itemlink, sizeof(itemlink), "item:%x:%x", htoi(results[col++].c_str()), htoi(results[col++].c_str()));
			int i = 0;
			for (; i < ITEM_SOCKET_SLOT_MAX_NUM; ++i)
				len += snprintf(itemlink + len, sizeof(itemlink), ":%x", htoi(results[col++].c_str()));
			if (results.size() >= ITEM_SOCKET_SLOT_MAX_NUM + 4)
			{
				for (; i < results.size(); i += 2)
				{
					len += snprintf(itemlink + len, sizeof(itemlink) - len, ":%x:%d", 
							htoi(results[i].c_str()),
							atoi(results[i+1].c_str()));
					isAttr = true;
				}
			}

			if (isAttr)
				//"item:ąřČŁ:ÇĂ·ˇ±×:ĽŇÄĎ0:ĽŇÄĎ1:ĽŇÄĎ2"
				snprintf(buf, sizeof(buf), "|cffffc700|H%s|h[%s]|h|r", itemlink, pItemData->GetName());
			else
				snprintf(buf, sizeof(buf), "|cfff1e6c0|H%s|h[%s]|h|r", itemlink, pItemData->GetName());

			return Py_BuildValue("s", buf);
		}
	}

	return Py_BuildValue("s", "");
} 

 

 

 

 

Ma wyglądać tak

3XmCxSa.gif

 

 

 

 

Zapisujemy i kompilujemy całe source

 

 

 

Teraz otwieramy w root uiToolTip.py i szukamy funkcji

	def SetHyperlinkItem(self, tokens):

I zamieniamy cała na 

 

	def SetHyperlinkItem(self, tokens):
		minTokenCount = 3 + player.METIN_SOCKET_MAX_NUM
		maxTokenCount = minTokenCount + 2 * player.ATTRIBUTE_SLOT_MAX_NUM

		if tokens and len(tokens) >= minTokenCount and len(tokens) <= maxTokenCount:
			head, vnum, flag = tokens[:3]
			itemVnum = int(vnum, 16)
			metinSlot = [int(metin, 16) for metin in tokens[3:minTokenCount]]

			rests = tokens[minTokenCount:]
			if rests:
				attrSlot = []

				rests.reverse()

				while rests:
					key = int(rests.pop(), 16)
					if rests:
						val = int(rests.pop())
						attrSlot.append((key, val))

				attrSlot += [(0, 0)] * (player.ATTRIBUTE_SLOT_MAX_NUM - len(attrSlot))
			else:
				attrSlot = [(0, 0)] * player.ATTRIBUTE_SLOT_MAX_NUM

			self.ClearToolTip()
			self.AddItemData(itemVnum, metinSlot, attrSlot)

			ItemToolTip.OnUpdate(self) 

 

 

 

 

Ma wyglądać tak

vDj4pMp.png

 

Uwaga! Ważne są taby w tym pliku

 

 

Zapisujemy,pakujemy i gotowe

ban.gif

 

Opublikowano
bool CHARACTER::CheckSpecifyItem(LPCHARACTER ch, DWORD vnum, const char * name, std::vector<long> kd, std::vector<TPlayerItemAttribute> attr)
{
	for (int i = 0; i < (INVENTORY_MAX_NUM + WEAR_MAX_NUM); ++i)
	{
		LPITEM item = GetInventoryItem(i);
		if (!item)
			continue;
		if (item->GetVnum() == vnum){
			for (int i = 0; i < kd.size(); i++)
				if (GetInventoryItem(i)->GetSocket(i) != kd[i])
					return false;
			for (int i = 0; i < attr.size(); i++)
				if (item->GetAttributeType(i) != attr[i].bType || item->GetAttributeValue(i) != attr[i].sValue)
					return false;
			if (item->GetName() != name)
				return false;
		}
	}
	
	return true;
}

Propsuje.

Co się stanie jak będę miał w eq dwa takie same przedmioty, pokaże na szkle ten który jest na dalszym slocie i on będzie miał w sobie inne kd niż ten przedmiot na slocie wcześniejszym?

Opublikowano
bool CHARACTER::CheckSpecifyItem(LPCHARACTER ch, DWORD vnum, const char * name, std::vector<long> kd, std::vector<TPlayerItemAttribute> attr)
{
	for (int i = 0; i < (INVENTORY_MAX_NUM + WEAR_MAX_NUM); ++i)
	{
		LPITEM item = GetInventoryItem(i);
		if (!item)
			continue;
		if (item->GetVnum() == vnum){
			for (int i = 0; i < kd.size(); i++)
				if (GetInventoryItem(i)->GetSocket(i) != kd[i])
					return false;
			for (int i = 0; i < attr.size(); i++)
				if (item->GetAttributeType(i) != attr[i].bType || item->GetAttributeValue(i) != attr[i].sValue)
					return false;
			if (item->GetName() != name)
				return false;
		}
	}
	
	return true;
}

Propsuje.

Co się stanie jak będę miał w eq dwa takie same przedmioty, pokaże na szkle ten który jest na dalszym slocie i on będzie miał w sobie inne kd niż ten przedmiot na slocie wcześniejszym?

 

 

Mi się wydaje że jak mam dwa przedmioty w eq o tym samym vnum, będę chciał wystawić ten który jest na dalszym slocie to funkcja mi na to nie pozwoli bo pobierze dane (KD, Bony) z tego itemu króry jest wcześniej.

 

Ale jest na to sposób, przed zwróceniem true czy false w tej funkcji należy sprawdzić wszystkie itemy w eq i dopiero potem zwrócić rezultat.

8910814572903361049127.png

Opublikowano

Dzięki Ci, jest to bardzo przydatne, bo w tych czasach trafiają się ludzie, którzy takimi rzeczami chcą rozwalić serwer, masz ode mnie lajka :)

Opublikowano

 

bool CHARACTER::CheckSpecifyItem(LPCHARACTER ch, DWORD vnum, const char * name, std::vector<long> kd, std::vector<TPlayerItemAttribute> attr)
{
	for (int i = 0; i < (INVENTORY_MAX_NUM + WEAR_MAX_NUM); ++i)
	{
		LPITEM item = GetInventoryItem(i);
		if (!item)
			continue;
		if (item->GetVnum() == vnum){
			for (int i = 0; i < kd.size(); i++)
				if (GetInventoryItem(i)->GetSocket(i) != kd[i])
					return false;
			for (int i = 0; i < attr.size(); i++)
				if (item->GetAttributeType(i) != attr[i].bType || item->GetAttributeValue(i) != attr[i].sValue)
					return false;
			if (item->GetName() != name)
				return false;
		}
	}
	
	return true;
}
Propsuje.

Co się stanie jak będę miał w eq dwa takie same przedmioty, pokaże na szkle ten który jest na dalszym slocie i on będzie miał w sobie inne kd niż ten przedmiot na slocie wcześniejszym?

Mi się wydaje że jak mam dwa przedmioty w eq o tym samym vnum, będę chciał wystawić ten który jest na dalszym slocie to funkcja mi na to nie pozwoli bo pobierze dane (KD, Bony) z tego itemu króry jest wcześniej.

 

Ale jest na to sposób, przed zwróceniem true czy false w tej funkcji należy sprawdzić wszystkie itemy w eq i dopiero potem zwrócić rezultat.

Zabezpieczenie nie generuje przedmiotu tylko sprawdza czy taki istnieje w eq

ban.gif

 

Opublikowano

Zabezpieczenie nie generuje przedmiotu tylko sprawdza czy taki istnieje w eq

 

Nie zrozumiałeś, napisałem że jest to zrobione źle, bo zamiast sprawdzać kolejny przedmiot zatrzymujesz się i przyjmujesz że na dalszych slotach tego przedmiotu nie znajdzie.

 

Program dla pokazania błędu:

 

 

int GetInventoryItemVnum(int slot)
{
	// jezeli sprawdzany slot jest 8 lub 10 to poda dobrego vnuma, reszta 1
	// czyli na slocie 8 i na slocie 10 jest przedmiot o tym samym id
	switch (slot)
	{
		case 8:
			return 12;
		case 10:
			return 12;
		default:
			return 1;
	}
}

int GetInventoryItemKd(int slot)
{
	// jezeli sprawdza kd z slotu 8 to poda zle id, jezeli z 10 to dobre, reszta 1
	switch (slot)
	{
		case 8:
			return 5;
		case 10:
			return 6;
		default:
			return 1;
	}
}

bool CheckSpecifyItem(int vnum, int kd)
{
	// sprawdza pierwsze 15 slotow
	for (int i = 0; i < 15; ++i)
	{
		int item_vnum = GetInventoryItemVnum(i);
		int kd_item = GetInventoryItemKd(i);
		if (item_vnum == vnum)
		{
			for (int a = 0; a < 3; a++)
			{
				if (kd_item != kd)
				{
					cout << i << ": vnum sie zgadza ale kd sie nie zgadza..." << endl;
					return false;
				}
				else
				{
					cout << i << ": wszystko okej." << endl;
					return true;
				}
			}
		}
		cout << i << " sie nie zgadza. Szukam dalej..." << endl;
	}

	return true;
}

int main()
{
	CheckSpecifyItem(12, 6);	// szuka przedmiotu o vnumie = 12 i id kd = 6, taki przedmiot jest na 10 slocie
	
	system("pause");
	return 0;
}

 

Efekt wykonania programu:

164031454256840483446.png

 

Miał skanować 15 slotów, prawidłowy przedmiot znajduje się na slocie 10, przestał działać na slocie 8 (bo znalazł podane id ale kd się nie zgadzały).

Nie wiem na jakim serwerze używałeś tego półtora roku, że nikt się nie skarżył na brak możliwości pokazania przedmiotu.

Opublikowano

 

Nie zrozumiałeś, napisałem że jest to zrobione źle, bo zamiast sprawdzać kolejny przedmiot zatrzymujesz się i przyjmujesz że na dalszych slotach tego przedmiotu nie znajdzie.

 

Program dla pokazania błędu:

 

 

int GetInventoryItemVnum(int slot)
{
	// jezeli sprawdzany slot jest 8 lub 10 to poda dobrego vnuma, reszta 1
	// czyli na slocie 8 i na slocie 10 jest przedmiot o tym samym id
	switch (slot)
	{
		case 8:
			return 12;
		case 10:
			return 12;
		default:
			return 1;
	}
}

int GetInventoryItemKd(int slot)
{
	// jezeli sprawdza kd z slotu 8 to poda zle id, jezeli z 10 to dobre, reszta 1
	switch (slot)
	{
		case 8:
			return 5;
		case 10:
			return 6;
		default:
			return 1;
	}
}

bool CheckSpecifyItem(int vnum, int kd)
{
	// sprawdza pierwsze 15 slotow
	for (int i = 0; i < 15; ++i)
	{
		int item_vnum = GetInventoryItemVnum(i);
		int kd_item = GetInventoryItemKd(i);
		if (item_vnum == vnum)
		{
			for (int a = 0; a < 3; a++)
			{
				if (kd_item != kd)
				{
					cout << i << ": vnum sie zgadza ale kd sie nie zgadza..." << endl;
					return false;
				}
				else
				{
					cout << i << ": wszystko okej." << endl;
					return true;
				}
			}
		}
		cout << i << " sie nie zgadza. Szukam dalej..." << endl;
	}

	return true;
}

int main()
{
	CheckSpecifyItem(12, 6);	// szuka przedmiotu o vnumie = 12 i id kd = 6, taki przedmiot jest na 10 slocie
	
	system("pause");
	return 0;
}

 

Efekt wykonania programu:

164031454256840483446.png

 

Miał skanować 15 slotów, prawidłowy przedmiot znajduje się na slocie 10, przestał działać na slocie 8 (bo znalazł podane id ale kd się nie zgadzały).

Nie wiem na jakim serwerze używałeś tego półtora roku, że nikt się nie skarżył na brak możliwości pokazania przedmiotu.

 

Hm, w sumie jest tu pewien blad, funkcja byla przepisywana 2 dni temu na odchudzona wiec dlatego, zaraz ja poprawie. 

ban.gif

 

  • 1 rok później...
Opublikowano

Po dodaniu tego na serwer pojawia się błąd: 

"Wystąpił podczas parsowania informacji o przedmiocie,wiadomość nie została wysłana!"

Normalnie działa tylko pokazywanie broni i zbroji na szkle. Gdy chcemy pokazać biżu to wyskakuje ten komunikat.

  • 9 miesięcy temu...
Opublikowano
Dnia 2.09.2018 o 23:19, muchomor321 napisał:

Nie działa, po dodaniu tego nie można nic pokazywać bo cały czas wyskakuje ten komunikat dodany w kodzie.

Przydałby się warunek, by sprawdzał bonusy i kamienie dusz wtedy gdy item->GetType() == ITEM_ARMOR ||  item->GetType() == ITEM_WEAPON

Opublikowano

potwierdzam nie działa ni huhu błąd nie można nic pokazywać bo cały czas wyskakuje ten komunikat dodany w kodzie.

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...