Jump to content

masodikbela

Premium
  • Posts

    235
  • Joined

  • Last visited

  • Days Won

    28
  • Feedback

    100%

Posts posted by masodikbela

  1. 2 minutes ago, ManiacRobert said:

    Error..

     

    
    compile item_manager_read_tables.cpp
    
    	item_manager_read_tables.cpp: In member function 'bool ITEM_MANAGER::ReadMonsterDropItemGroup(const char*, bool)':
    
    	item_manager_read_tables.cpp:699: warning: unused variable 'pkGroup'
    
    	item_manager_read_tables.cpp: In member function 'bool ITEM_MANAGER::ReadDropItemGroup(const char*)':
    
    	item_manager_read_tables.cpp:945: error: 'isReloading' was not declared in this scope
    
    	item_manager_read_tables.cpp:947: error: 'tempDropItemGr' was not declared in this scope
    
    	item_manager_read_tables.cpp:947: error: invalid type in declaration before '=' token
    
    	item_manager_read_tables.cpp:950: error: 'pkGroup' was not declared in this scope
    
    	item_manager_read_tables.cpp:954: error: 'bNew' was not declared in this scope
    
    	item_manager_read_tables.cpp:955: error: base operand of '->' is not a pointer
    
    	item_manager_read_tables.cpp:955: warning: unused variable 'pkGroup'
    
    	item_manager_read_tables.cpp:963: error: 'pkGroup' was not declared in this scope
    
    	item_manager_read_tables.cpp:967: error: 'bNew' was not declared in this scope
    
    	item_manager_read_tables.cpp:968: warning: unused variable 'pkGroup'
    
    	item_manager_read_tables.cpp:989: error: 'it' was not declared in this scope
    
    	item_manager_read_tables.cpp:990: error: 'pkGroup' was not declared in this scope
    
    	item_manager_read_tables.cpp:1008: error: 'it' was not declared in this scope
    
    	item_manager_read_tables.cpp:1009: error: 'pkGroup' was not declared in this scope
    
    	item_manager_read_tables.cpp:1015: error: 'pkGroup' was not declared in this scope
    
    	item_manager_read_tables.cpp:1022: error: 'it' was not declared in this scope
    
    	item_manager_read_tables.cpp:1023: error: 'pkGroup' was not declared in this scope
    
    
    
     

    Could you pastebin the edited item_manager_read_tables.cpp?

    • Love 5
  2. On 2016. 01. 12. at 5:09 PM, alexandru1992 said:

    Hi guys,i promised i will be back with the confirmation if masodikbela's suggestion with game will work,today i finally have time to test the method  and guess what it really works ,it solved my problem,thank you very much masodikblea,but at first i get some connection refused i looked at my syserror  on channels and it seems like only problem was that i have to port forward some p2p_ports on external ip ,more precise channel99 port and core2_channel1 port ,i don't really know why i have to port forward these but that solved the problem with connection refused,so i have one question ,i follow your tutorial and replace both in strlcpy,and memcpy with my external ip and now i have to portforward those p2p_ports, what do i have to do to have more security on those p2p_ports?use pf ?or ipfw? and what rule i have to set to pass all outcoming or incoming packets,because i think i have to pass only out packet?

    Well on BSD you have to wait some minutes after starting the core to establish the local connection (IDK why...) In this time, you probably will see some connection refused "operation timed out" message (about 5-10 pcs), but don't panic! Just wait ~2 minutes, then try to connect. You don't have to portforward the p2p ports.

    Edit:

    Hmm... its quite interesting, for me I didn't have to portforward the p2p_ports, they was closed, and I got only operation timed out, as I mentioned it before.

  3. M2 Download Center

    This is the hidden content, please
    ( Internal )

    Hi there devs,

     

    I made some new reload commands about 2 weeks ago and published a tutorial about it on our Hungarian forum (you may saw them in the samurai core) and today I had some time to make the translation.

    What can I reload now?

    • refine_proto (this is the only one which is not mine, its @xP3NG3Rx's, and already public here, but I added it, because I think this package has to contain it ;)) command: /reload p
    • shop_item table (npc's shops) command: /reload p
    • item_attr && item_attr_rare table; command: /reload p
    • etc_drop_item.txt, mob_drop_item.txt, special_item_group.txt; command: /reload drop
    • group.txt, group_group.txt; command: /reload group
    • regen.txt, npc.txt, boss.txt, stone.txt (only on the current map) command: /reload regen
    • because of the new "reload regen" command, I had to write a new purge command that destroys all mobs, npcs, stones (and so on...) on the current map, so I added a new /p map command to the "/p" commands that are already exists (no, the "/p all" only destroys the mobs on the current sectree (current block))
    • also I had to create a new command that stops all the regens (and ofc. deletes them from the memory) on the current map, so I added a new "/free_regens" command (because why not B)) Its only deletes the loaded regens, and prevents the mobs from respawning (its not necessary to use this before the /reload regen)

    Known bug

    • Well its not a serious problem, but for some unknown reason, when I'm debugging the core on windows server (no, not debug mode, but vs 13's debugger) and I try to do /reload regen, the core starts to consume ~40% cpu, and doesn't want to do anything (so stops working, but doesn't crash). It has no affect on FreeBSD and release or debug mode (without visual studio's debugger) on windows.

     

    Spoiler

    If you get fcked up codes like me, try to remove the pagestyle in your browser.
    mz7XE.jpg

    game/src

    cmd.cpp

    Spoiler

    Add this to the top of the file (where you can find more ACMDs)

    ACMD(do_free_regen);

    Then above this:

    	{ "who",		do_who,			0,			POS_DEAD,	GM_IMPLEMENTOR	},

    Add this:

    	{ "free_regens", do_free_regen,	0,			POS_DEAD,	GM_IMPLEMENTOR	},

     

    cmd_gm.cpp

    Spoiler

    Add this to the end of the file:

    ACMD(do_free_regen)
    {
    	ch->ChatPacket(CHAT_TYPE_INFO, "freeing regens on mapindex %ld", ch->GetMapIndex());
    	regen_free_map(ch->GetMapIndex());
    	ch->ChatPacket(CHAT_TYPE_INFO, "the regens now FREEEE! :)");
    }

    Replace the ACMD(do_purge) with this:

    ACMD(do_purge)
    {
    	char arg1[256];
    	one_argument(argument, arg1, sizeof(arg1));
    
    	FuncPurge func(ch);
    
    	if (*arg1 && !strcmp(arg1, "map"))
    	{
    		CHARACTER_MANAGER::instance().DestroyCharacterInMap(ch->GetMapIndex());
    	}
    	else
    	{
    		if (*arg1 && !strcmp(arg1, "all"))
    			func.m_bAll = true;
    		LPSECTREE sectree = ch->GetSectree();
    		if (sectree) // #431
    			sectree->ForEachAround(func);
    		else
    			sys_err("PURGE_ERROR.NULL_SECTREE(mapIndex=%d, pos=(%d, %d)", ch->GetMapIndex(), ch->GetX(), ch->GetY());
    	}
    }

    In the ACMD(do_reload) function under this:

    			case 'c':	// cube
    				// ·ÎÄĂ ÇÁ·ÎĽĽ˝ş¸¸ °»»ęÇŃ´Ů.
    				Cube_init ();
    				break;

    Insert this:

    			default:
    				const int FILE_NAME_LEN = 256;
    				if (strstr(arg1, "drop"))
    				{
    					char szETCDropItemFileName[FILE_NAME_LEN];
    					char szMOBDropItemFileName[FILE_NAME_LEN];
    					char szSpecialItemGroupFileName[FILE_NAME_LEN];
    
    					snprintf(szETCDropItemFileName, sizeof(szETCDropItemFileName),
    						"%s/etc_drop_item.txt", LocaleService_GetBasePath().c_str());
    					snprintf(szMOBDropItemFileName, sizeof(szMOBDropItemFileName),
    						"%s/mob_drop_item.txt", LocaleService_GetBasePath().c_str());
    					snprintf(szSpecialItemGroupFileName, sizeof(szSpecialItemGroupFileName),
    						"%s/special_item_group.txt", LocaleService_GetBasePath().c_str());
    
    					ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: ETCDropItem: %s", szETCDropItemFileName);
    					if (!ITEM_MANAGER::instance().ReadEtcDropItemFile(szETCDropItemFileName, true))
    						ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload ETCDropItem: %s", szETCDropItemFileName);
    					else
    						ch->ChatPacket(CHAT_TYPE_INFO, "reload success: ETCDropItem: %s", szETCDropItemFileName);
    
    					ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: SpecialItemGroup: %s", szSpecialItemGroupFileName);
    					if (!ITEM_MANAGER::instance().ReadSpecialDropItemFile(szSpecialItemGroupFileName, true))
    						ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload SpecialItemGroup: %s", szSpecialItemGroupFileName);
    					else
    						ch->ChatPacket(CHAT_TYPE_INFO, "reload success: SpecialItemGroup: %s", szSpecialItemGroupFileName);
    
    					ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: MOBDropItemFile: %s", szMOBDropItemFileName);
    					if (!ITEM_MANAGER::instance().ReadMonsterDropItemGroup(szMOBDropItemFileName, true))
    						ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload MOBDropItemFile: %s", szMOBDropItemFileName);
    					else
    						ch->ChatPacket(CHAT_TYPE_INFO, "reload success: MOBDropItemFile: %s", szMOBDropItemFileName);
    				}
    				else if (strstr(arg1, "group"))
    				{
    					char szGroupFileName[FILE_NAME_LEN];
    					char szGroupGroupFileName[FILE_NAME_LEN];
    
    					snprintf(szGroupFileName, sizeof(szGroupGroupFileName),
    						"%s/group.txt", LocaleService_GetBasePath().c_str());
    					snprintf(szGroupGroupFileName, sizeof(szGroupGroupFileName),
    						"%s/group_group.txt", LocaleService_GetBasePath().c_str());
    
    					ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: mob groups: %s", szGroupFileName);
    					if (!CMobManager::instance().LoadGroup(szGroupFileName, true))
    						ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload mob groups: %s", szGroupFileName);
    
    					ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: mob group group: %s", szGroupGroupFileName);
    					if (!CMobManager::instance().LoadGroupGroup(szGroupGroupFileName, true))
    						ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload mob group group: %s", szGroupGroupFileName);
    				}
    				else if (strstr(arg1, "regen"))
    				{
    					SendNoticeMap("Reloading regens!", ch->GetMapIndex(), false);
    					regen_free_map(ch->GetMapIndex());
    					CHARACTER_MANAGER::instance().DestroyCharacterInMap(ch->GetMapIndex());
    					regen_reload(ch->GetMapIndex());
    					SendNoticeMap("Regens reloaded!", ch->GetMapIndex(), false);
    				}
    				break;

     

    input_db.cpp

    Spoiler

    void CInputDB::ReloadProto(const char * c_pData)

    Above this:

    	CMotionManager::instance().Build();

    Add this:

    	/*
    	* SHOP
    	*/
    
    	wSize = decode_2bytes(c_pData);
    	c_pData += sizeof(WORD);
    	sys_log(0, "RELOAD: SHOP: %d", wSize);
    
    
    	if (wSize)
    	{
    		CShopManager::instance().Initialize((TShopTable *)c_pData, wSize);
    		c_pData += wSize * sizeof(TShopTable);
    	}
    
    	/*
    	* REFINE
    	*/
    	wSize = decode_2bytes(c_pData);
    	c_pData += 2;
    	sys_log(0, "RELOAD: REFINE: %d", wSize);
    
    	if (wSize)
    	{
    		CRefineManager::instance().Initialize((TRefineTable *)c_pData, wSize);
    		c_pData += wSize * sizeof(TRefineTable);
    	}
    
    	/*
    	* ATTR
    	*/
    	wSize = decode_2bytes(c_pData);
    	c_pData += 2;
    	sys_log(0, "RELOAD: ItemAtt: %d", wSize);
    
    	if (wSize)
    	{
    		TItemAttrTable * p = (TItemAttrTable *)c_pData;
    		g_map_itemAttr.clear();
    		for (int i = 0; i < wSize; ++i, ++p)
    		{
    			if (p->dwApplyIndex >= MAX_APPLY_NUM)
    				continue;
    
    			g_map_itemAttr[p->dwApplyIndex] = *p;
    			sys_log(0, "ITEM_ATTR[%d]: %s %u", p->dwApplyIndex, p->szApply, p->dwProb);
    		}
    		c_pData += wSize*sizeof(TItemAttrTable);
    	}
    
    	/*
    	* ATTR_RARE
    	*/
    	wSize = decode_2bytes(c_pData);
    	c_pData += 2;
    	sys_log(0, "RELOAD: ItemRareAtt: %d", wSize);
    
    	if (wSize)
    	{
    		TItemAttrTable * p = (TItemAttrTable *)c_pData;
    		g_map_itemRare.clear();
    		for (int i = 0; i < wSize; ++i, ++p)
    		{
    			if (p->dwApplyIndex >= MAX_APPLY_NUM)
    				continue;
    
    			g_map_itemRare[p->dwApplyIndex] = *p;
    			sys_log(0, "ITEM_RARE[%d]: %s %u", p->dwApplyIndex, p->szApply, p->dwProb);
    		}
    		c_pData += wSize*sizeof(TItemAttrTable);
    	}

     

    shop_manager.cpp

    Spoiler

    bool CShopManager::Initialize(TShopTable * table, int size

    Replace this:

    	if (!m_map_pkShop.empty())
    		return false;

    With this:

    	if (!m_map_pkShop.empty())
    	{
    		for (TShopMap::iterator it = m_map_pkShop.begin(); it != m_map_pkShop.end(); it++)
    		{
    			it->second->RemoveAllGuests();
    		}
    	}
    
    	m_map_pkShop.clear();
    	m_map_pkShopByNPCVnum.clear();

     

    refine.cpp

    Spoiler

    Insert this to the top of this function:bool CRefineManager::Initialize(TRefineTable * table, int size)

    	m_map_RefineRecipe.clear();

     

    char_manager.cpp

    Spoiler

    Insert this to the end of the file:

    void CHARACTER_MANAGER::DestroyCharacterInMap(long lMapIndex)
    {
    	std::vector<LPCHARACTER> tempVec;
    	for (itertype(m_map_pkChrByVID) it = m_map_pkChrByVID.begin(); it != m_map_pkChrByVID.end(); it++)
    	{
    		LPCHARACTER pkChr = it->second;
    		if (pkChr && pkChr->GetMapIndex() == lMapIndex && pkChr->IsNPC() && !pkChr->IsPet() && pkChr->GetRider() == NULL)
    		{
    			tempVec.push_back(pkChr);
    		}
    	}
    	for (std::vector<LPCHARACTER>::iterator it = tempVec.begin(); it != tempVec.end(); it++)
    	{
    		DestroyCharacter(*it);
    	}
    }

     

    char_manager.h

    Spoiler

    Above this:

    void			Update(int iPulse);

    Insert this:

    void DestroyCharacterInMap(long lMapIndex);

     

    item_manager.h

    Spoiler

    Replace this:

    		bool			ReadEtcDropItemFile(const char * c_pszFileName);
    		bool			ReadMonsterDropItemGroup(const char * c_pszFileName);
    		bool			ReadSpecialDropItemFile(const char * c_pszFileName);

    With this:

    		bool			ReadEtcDropItemFile(const char * c_pszFileName, bool isReloading = false);
    		bool			ReadMonsterDropItemGroup(const char * c_pszFileName, bool isReloading = false);
    		bool			ReadSpecialDropItemFile(const char * c_pszFileName, bool isReloading = false);

     

    item_manager_read_tables.cpp

    Spoiler

    Firstly replace this:

    bool ITEM_MANAGER::ReadEtcDropItemFile(const char * c_pszFileName)

    With this:

    bool ITEM_MANAGER::ReadEtcDropItemFile(const char * c_pszFileName, bool isReloading)

    Now we will work in this function we just edited. Above this:

    char buf[512]

    Insert this:

    	std::map<DWORD, DWORD> tempLoader;
    	if (isReloading)
    	{
    		sys_log(0, "RELOADING EtcDrop");
    	}

    Then replace this:

    m_map_dwEtcItemDropProb[dwItemVnum] = (DWORD) (fProb * 10000.0f);

    With this:

    		if (isReloading)
    			tempLoader[dwItemVnum] = (DWORD)(fProb * 10000.0f);
    		else
    			m_map_dwEtcItemDropProb[dwItemVnum] = (DWORD) (fProb * 10000.0f);

    Add this above the return true; that we can find at the end of the function:

    	if (isReloading)
    	{
    		m_map_dwEtcItemDropProb.clear();
    		for (std::map<DWORD, DWORD>::iterator it = tempLoader.begin(); it != tempLoader.end(); it++)
    		{
    			m_map_dwEtcItemDropProb[it->first] = it->second;
    		}
    	}

    Okay, now we finished this function. Lets search for this:

    bool ITEM_MANAGER::ReadSpecialDropItemFile(const char * c_pszFileName)

    Then replace with this:

    bool ITEM_MANAGER::ReadSpecialDropItemFile(const char * c_pszFileName, bool isReloading)

    Okay, we will work in this function. Before the first for loop add this:

    	std::map<DWORD, CSpecialAttrGroup*> tempSpecAttr;
    	std::map<DWORD, CSpecialItemGroup*> tempSpecItem;
    	std::map<DWORD, CSpecialItemGroup*> tempSpecItemQuest;
    	if (isReloading)
    		sys_log(0, "RELOADING SpecialDrop");

    Then replace this:

    m_map_pkSpecialAttrGroup.insert(std::make_pair(iVnum, pkGroup));

    With this:

    			if (isReloading)
    				tempSpecAttr.insert(std::make_pair(iVnum, pkGroup));
    			else
    				m_map_pkSpecialAttrGroup.insert(std::make_pair(iVnum, pkGroup));

    Then replace this:

    			if (CSpecialItemGroup::QUEST == type)
    			{
    				m_map_pkQuestItemGroup.insert(std::make_pair(iVnum, pkGroup));
    			}
    			else
    			{
    				m_map_pkSpecialItemGroup.insert(std::make_pair(iVnum, pkGroup));
    			}

    With this:

    			if (CSpecialItemGroup::QUEST == type)
    			{
    				if (isReloading)
    					tempSpecItemQuest.insert(std::make_pair(iVnum, pkGroup));
    				else
    					m_map_pkQuestItemGroup.insert(std::make_pair(iVnum, pkGroup));
    			}
    			else
    			{
    				if (isReloading)
    					tempSpecItem.insert(std::make_pair(iVnum, pkGroup));
    				else
    					m_map_pkSpecialItemGroup.insert(std::make_pair(iVnum, pkGroup));
    			}

    Again, above the return true; (we can find this at the end of the function) add this:

    	if (isReloading)
    	{
    		m_map_pkQuestItemGroup.clear();
    		m_map_pkSpecialItemGroup.clear();
    		m_map_pkSpecialAttrGroup.clear();
    
    		for (std::map<DWORD, CSpecialAttrGroup*>::iterator it = tempSpecAttr.begin(); it != tempSpecAttr.end(); it++)
    		{
    			m_map_pkSpecialAttrGroup[it->first] = it->second;
    		}
    
    		for (std::map<DWORD, CSpecialItemGroup*>::iterator it = tempSpecItem.begin(); it != tempSpecItem.end(); it++)
    		{
    			m_map_pkSpecialItemGroup[it->first] = it->second;
    		}
    
    		for (std::map<DWORD, CSpecialItemGroup*>::iterator it = tempSpecItemQuest.begin(); it != tempSpecItemQuest.end(); it++)
    		{
    			m_map_pkQuestItemGroup[it->first] = it->second;
    		}
    	}

    Lets search for a new function. Replace this:

    bool ITEM_MANAGER::ReadMonsterDropItemGroup(const char * c_pszFileName)

    With this:

    bool ITEM_MANAGER::ReadMonsterDropItemGroup(const char * c_pszFileName, bool isReloading)

    Okay, we will work again in the "just edited" function. Before the first for loop add this:

    	std::map<DWORD, CMobItemGroup*> temMobItemGr;
    	std::map<DWORD, CDropItemGroup*> tempDropItemGr;
    	std::map<DWORD, CLevelItemGroup*> tempLevelItemGr;
    	std::map<DWORD, CBuyerThiefGlovesItemGroup*> tempThiefGlovesGr;
    	if (isReloading)
    	{
    		sys_log(0, "RELOADING MonsterDrop");
    	}

    Replace this:

    m_map_pkMobItemGroup.insert(std::map<DWORD, CMobItemGroup*>::value_type(iMobVnum, pkGroup));

    With this:

    			if (isReloading)
    				temMobItemGr.insert(std::map<DWORD, CMobItemGroup*>::value_type(iMobVnum, pkGroup));
    			else
    				m_map_pkMobItemGroup.insert(std::map<DWORD, CMobItemGroup*>::value_type(iMobVnum, pkGroup));

    Then this:

    				itertype(m_map_pkDropItemGroup) it = m_map_pkDropItemGroup.find(iMobVnum);
    				if (it == m_map_pkDropItemGroup.end())
    				{
    					pkGroup = M2_NEW CDropItemGroup(0, iMobVnum, stName);
    				}
    				else
    				{
    					bNew = false;
    					CDropItemGroup* pkGroup = it->second;
    				}

    With this:

    			if (isReloading)
    			{
    				itertype(tempDropItemGr) it = tempDropItemGr.find(iMobVnum);
    				if (it == tempDropItemGr.end())
    				{
    					pkGroup = M2_NEW CDropItemGroup(0, iMobVnum, stName);
    				}
    				else
    				{
    					bNew = false;
    					CDropItemGroup* pkGroup = it->second;
    				}
    			}
    			else
    			{
    				itertype(m_map_pkDropItemGroup) it = m_map_pkDropItemGroup.find(iMobVnum);
    				if (it == m_map_pkDropItemGroup.end())
    				{
    					pkGroup = M2_NEW CDropItemGroup(0, iMobVnum, stName);
    				}
    				else
    				{
    					bNew = false;
    					CDropItemGroup* pkGroup = it->second;
    				}
    			}

    Replace this:

    			if (bNew)
    				m_map_pkDropItemGroup.insert(std::map<DWORD, CDropItemGroup*>::value_type(iMobVnum, pkGroup));

    With this:

    			if (bNew)
    			{
    				if (isReloading)
    					tempDropItemGr.insert(std::map<DWORD, CDropItemGroup*>::value_type(iMobVnum, pkGroup));
    				else
    					m_map_pkDropItemGroup.insert(std::map<DWORD, CDropItemGroup*>::value_type(iMobVnum, pkGroup));
    			}

    This:

    m_map_pkLevelItemGroup.insert(std::map<DWORD, CLevelItemGroup*>::value_type(iMobVnum, pkLevelItemGroup));

    With this:

    			if (isReloading)
    				tempLevelItemGr.insert(std::map<DWORD, CLevelItemGroup*>::value_type(iMobVnum, pkLevelItemGroup));
    			else
    				m_map_pkLevelItemGroup.insert(std::map<DWORD, CLevelItemGroup*>::value_type(iMobVnum, pkLevelItemGroup));

    This:

    m_map_pkGloveItemGroup.insert(std::map<DWORD, CBuyerThiefGlovesItemGroup*>::value_type(iMobVnum, pkGroup));

    With this:

    			if (isReloading)
    				tempThiefGlovesGr.insert(std::map<DWORD, CBuyerThiefGlovesItemGroup*>::value_type(iMobVnum, pkGroup));
    			else
    				m_map_pkGloveItemGroup.insert(std::map<DWORD, CBuyerThiefGlovesItemGroup*>::value_type(iMobVnum, pkGroup));

    Then add this above the return true; at the end of the function:

    	if (isReloading)
    	{
    		for (std::map<DWORD, CBuyerThiefGlovesItemGroup*>::iterator it = m_map_pkGloveItemGroup.begin(); it != m_map_pkGloveItemGroup.end(); it++)
    			M2_DELETE(it->second);
    		m_map_pkGloveItemGroup.clear();
    		for (std::map<DWORD, CLevelItemGroup*>::iterator it = m_map_pkLevelItemGroup.begin(); it != m_map_pkLevelItemGroup.end(); it++)
    			M2_DELETE(it->second);
    		m_map_pkLevelItemGroup.clear();
    		for (std::map<DWORD, CDropItemGroup*>::iterator it = m_map_pkDropItemGroup.begin(); it != m_map_pkDropItemGroup.end(); it++)
    			M2_DELETE(it->second);
    		m_map_pkDropItemGroup.clear();
    		for (std::map<DWORD, CMobItemGroup*>::iterator it = m_map_pkMobItemGroup.begin(); it != m_map_pkMobItemGroup.end(); it++)
    			M2_DELETE(it->second);
    		m_map_pkMobItemGroup.clear();
    
    		for (std::map<DWORD, CBuyerThiefGlovesItemGroup*>::iterator it = tempThiefGlovesGr.begin(); it != tempThiefGlovesGr.end(); it++)
    		{
    			m_map_pkGloveItemGroup[it->first] = it->second;
    		}
    
    		for (std::map<DWORD, CLevelItemGroup*>::iterator it = tempLevelItemGr.begin(); it != tempLevelItemGr.end(); it++)
    		{
    			m_map_pkLevelItemGroup[it->first] = it->second;
    		}
    
    		for (std::map<DWORD, CDropItemGroup*>::iterator it = tempDropItemGr.begin(); it != tempDropItemGr.end(); it++)
    		{
    			m_map_pkDropItemGroup[it->first] = it->second;
    		}
    
    		for (std::map<DWORD, CMobItemGroup*>::iterator it = temMobItemGr.begin(); it != temMobItemGr.end(); it++)
    		{
    			m_map_pkMobItemGroup[it->first] = it->second;
    		}
    	}

     

    mob_manager.h

    Spoiler

    Replace this:

    		bool		LoadGroup(const char * c_pszFileName);
    		bool		LoadGroupGroup(const char * c_pszFileName);

    With this:

    		bool		LoadGroup(const char * c_pszFileName, bool isReloading = false);
    		bool		LoadGroupGroup(const char * c_pszFileName, bool isReloading = false);

     

    mob_manager.cpp

    Spoiler

    Replace this:

    bool CMobManager::LoadGroupGroup(const char * c_pszFileName)

    With this:

    bool CMobManager::LoadGroupGroup(const char * c_pszFileName, bool isReloading)

    We will work in this function again. Add this above the first for loop:

    	std::map<DWORD, CMobGroupGroup *> tempLoader;
    	if (isReloading)
    		sys_log(0, "RELOADING group group: %s", c_pszFileName);

    Then replace this:

    m_map_pkMobGroupGroup.insert(std::make_pair((DWORD)iVnum, pkGroup));

    With this:

    		if (isReloading)
    			tempLoader.insert(std::make_pair((DWORD)iVnum, pkGroup));
    		else
    			m_map_pkMobGroupGroup.insert(std::make_pair((DWORD)iVnum, pkGroup));

    Then insert this above the return true; at the end of the function:

    	if (isReloading)
    	{
    		for (std::map<DWORD, CMobGroupGroup *>::iterator it = m_map_pkMobGroupGroup.begin(); it != m_map_pkMobGroupGroup.end(); it++)
    			M2_DELETE(it->second);
    		m_map_pkMobGroupGroup.clear();
    		for (std::map<DWORD, CMobGroupGroup *>::iterator it = tempLoader.begin(); it != tempLoader.end(); it++)
    		{
    			m_map_pkMobGroupGroup[it->first] = it->second;
    		}
    	}

    Okay we done with the this function, lets search for this:

    bool CMobManager::LoadGroup(const char * c_pszFileName)

    And replace with this:

    bool CMobManager::LoadGroup(const char * c_pszFileName, bool isReloading)

    Obliviously we will work in this function. Lets add this again before the first for loop:

    	std::map<DWORD, CMobGroup *> tempLoader;
    	if (isReloading)
    		sys_log(0, "RELOADING groups: %s", c_pszFileName);

    Then replace this:

    m_map_pkMobGroup.insert(std::map<DWORD, CMobGroup *>::value_type(iVnum, pkGroup));

    With this:

    		if (isReloading)
    			tempLoader.insert(std::map<DWORD, CMobGroup *>::value_type(iVnum, pkGroup));
    		else
    			m_map_pkMobGroup.insert(std::map<DWORD, CMobGroup *>::value_type(iVnum, pkGroup));

    And last but not least lets add this before the return true; at the end of the function:

    	if (isReloading)
    	{
    		for (std::map<DWORD, CMobGroup *>::iterator it = m_map_pkMobGroup.begin(); it != m_map_pkMobGroup.end(); it++)
    			M2_DELETE(it->second);
    		m_map_pkMobGroup.clear();
    		for (std::map<DWORD, CMobGroup *>::iterator it = tempLoader.begin(); it != tempLoader.end(); it++)
    		{
    			m_map_pkMobGroup[it->first] = it->second;
    		}
    	}

     

    char.cpp

    Spoiler

    void CHARACTER::Destroy()

    Replace this:

    	if (m_pkRegen)
    	{
    		if (m_pkDungeon) {
    			// Dungeon regen may not be valid at this point
    			if (m_pkDungeon->IsValidRegen(m_pkRegen, regen_id_)) {
    				--m_pkRegen->count;
    			}
    		} else {
    			// Is this really safe?
    			--m_pkRegen->count;
    		}
    		m_pkRegen = NULL;
    	}

    With this:

    	if (m_pkRegen)
    	{
    		if (m_pkDungeon) {
    			// Dungeon regen may not be valid at this point
    			if (m_pkDungeon->IsValidRegen(m_pkRegen, regen_id_)) {
    				--m_pkRegen->count;
    			}
    		} else {
    			// Is this really safe? NO IT ISNT! F*CK THAT SH!T!
    			if (is_valid_regen(m_pkRegen))
    				--m_pkRegen->count;
    		}
    		m_pkRegen = NULL;
    	}

     

    sectree_manager.cpp

    Spoiler

    int SECTREE_MANAGER::Build(const char * c_pszListFileName, const char* c_pszMapBasePath)

    Under this:

    			snprintf(szFilename, sizeof(szFilename), "%s/%s/server_attr", c_pszMapBasePath, szMapName);
    			LoadAttribute(pkMapSectree, szFilename, setting);

    Insert this:

    			snprintf(szFilename, sizeof(szFilename), "%s/%s/", c_pszMapBasePath, szMapName);
    			regen_register_map(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY);

     

    regen.h

    Spoiler

    Under this:

    extern bool	regen_load(const char *filename, long lMapIndex, int base_x, int base_y);

    Insert this:

    extern void regen_free_map(long lMapIndex);
    extern void regen_reload(long lMapIndex);
    extern void regen_register_map(const char * szBaseName, long lMapIndex, int base_x, int base_y);
    extern bool is_valid_regen(LPREGEN currRegen);

     

    regen.cpp

    Spoiler

    Under this:

    LPREGEN_EXCEPTION regen_exception_list = NULL;

    Add this:

    typedef struct SMapDataContainer
    {
    	char szBaseName[256];
    	int base_x;
    	int base_y;
    }TMapDataContainer;
    
    #define mbMapDataCType std::map<DWORD, TMapDataContainer*>
    mbMapDataCType mbMapDataContainer;

    At the end of the file add these:

    bool is_valid_regen(LPREGEN currRegen)
    {
    	LPREGEN		regen;
    
    	for (regen = regen_list; regen; regen = regen->next)
    	{
    		if (regen == currRegen)
    			return true;
    	}
    	return false;
    }
    
    void regen_free_map(long lMapIndex)
    {
    	LPREGEN		regen, prev, next, next_regen;
    
    	for (regen = regen_list; regen; regen = next_regen)
    	{
    		next_regen = regen->next;
    		if (regen->lMapIndex != lMapIndex)
    			continue;
    		event_cancel(&regen->event);
    		REMOVE_FROM_TW_LIST(regen, regen_list, prev, next);
    		M2_DELETE(regen);
    	}
    }
    
    void regen_reload(long lMapIndex)
    {
    	if (mbMapDataContainer.find(lMapIndex) == mbMapDataContainer.end())
    		return;
    
    	char szFilename[256];
    	
    	snprintf(szFilename, sizeof(szFilename), "%sregen.txt", mbMapDataContainer[lMapIndex]->szBaseName);
    	regen_load(szFilename, lMapIndex, mbMapDataContainer[lMapIndex]->base_x, mbMapDataContainer[lMapIndex]->base_y);
    
    	snprintf(szFilename, sizeof(szFilename), "%snpc.txt", mbMapDataContainer[lMapIndex]->szBaseName);
    	regen_load(szFilename, lMapIndex, mbMapDataContainer[lMapIndex]->base_x, mbMapDataContainer[lMapIndex]->base_y);
    
    	snprintf(szFilename, sizeof(szFilename), "%sboss.txt", mbMapDataContainer[lMapIndex]->szBaseName);
    	regen_load(szFilename, lMapIndex, mbMapDataContainer[lMapIndex]->base_x, mbMapDataContainer[lMapIndex]->base_y);
    
    	snprintf(szFilename, sizeof(szFilename), "%sstone.txt", mbMapDataContainer[lMapIndex]->szBaseName);
    	regen_load(szFilename, lMapIndex, mbMapDataContainer[lMapIndex]->base_x, mbMapDataContainer[lMapIndex]->base_y);
    }
    
    void regen_register_map(const char * szBaseName, long lMapIndex, int base_x, int base_y)
    {
    	TMapDataContainer* container = new TMapDataContainer;
    	memset(container->szBaseName, 0, sizeof(container->szBaseName));
    #ifdef __FreeBSD__
    	strlcpy(container->szBaseName, szBaseName, sizeof(container->szBaseName) - 1);
    #else
    	strncpy(container->szBaseName, szBaseName, sizeof(container->szBaseName) - 1);
    #endif
    	container->base_x = base_x;
    	container->base_y = base_y;
    	mbMapDataContainer[lMapIndex] = container;
    }

    EVENTFUNC(regen_event)

    Under this:

    	LPREGEN	regen = info->regen;

    Insert this:

    	if (!is_valid_regen(regen))
    		return 0;

     

    shop.h

    Spoiler

    Under this:

    		void	RemoveGuest(LPCHARACTER ch);

    Insert this:

    		void	RemoveAllGuests();

     

    shop.cpp

    Spoiler

    Add this at the end of the file:

    void CShop::RemoveAllGuests()
    {
    	if (m_map_guest.empty())
    		return;
    	for (GuestMapType::iterator it = m_map_guest.begin(); it != m_map_guest.end(); it++)
    	{
    		LPCHARACTER ch = it->first;
    		if (ch)
    		{
    			if (ch->GetDesc() && ch->GetShop() == this)
    			{
    				ch->SetShop(NULL);
    
    				TPacketGCShop pack;
    
    				pack.header = HEADER_GC_SHOP;
    				pack.subheader = SHOP_SUBHEADER_GC_END;
    				pack.size = sizeof(TPacketGCShop);
    
    				ch->GetDesc()->Packet(&pack, sizeof(pack));
    			}
    		}
    	}
    	m_map_guest.clear();
    }

     

    db/src

    ClientManager.cpp

    Spoiler

    void CClientManager::QUERY_RELOAD_PROTO()

    Replace this:

    		tmp->EncodeHeader(HEADER_DG_RELOAD_PROTO, 0, 
    				sizeof(WORD) + sizeof(TSkillTable) * m_vec_skillTable.size() +
    				sizeof(WORD) + sizeof(TBanwordTable) * m_vec_banwordTable.size() +
    				sizeof(WORD) + sizeof(TItemTable) * m_vec_itemTable.size() +
    				sizeof(WORD) + sizeof(TMobTable) * m_vec_mobTable.size());

    With this:

    		tmp->EncodeHeader(HEADER_DG_RELOAD_PROTO, 0, 
    				sizeof(WORD) + sizeof(TSkillTable) * m_vec_skillTable.size() +
    				sizeof(WORD) + sizeof(TBanwordTable) * m_vec_banwordTable.size() +
    				sizeof(WORD) + sizeof(TItemTable) * m_vec_itemTable.size() +
    				sizeof(WORD) + sizeof(TMobTable) * m_vec_mobTable.size() +
    				sizeof(WORD) + sizeof(TShopTable) * m_iShopTableSize +
    				sizeof(WORD) + sizeof(TRefineTable)* m_iRefineTableSize +
    				sizeof(WORD) + sizeof(TItemAttrTable)*m_vec_itemAttrTable.size() +
    				sizeof(WORD) + sizeof(TItemAttrTable)*m_vec_itemRareTable.size());

    Then under this:

    		tmp->EncodeWORD(m_vec_mobTable.size());
    		tmp->Encode(&m_vec_mobTable[0], sizeof(TMobTable) * m_vec_mobTable.size());

    Add this:

    
    		tmp->EncodeWORD(m_iShopTableSize);
    		tmp->Encode(m_pShopTable, sizeof(TShopTable) * m_iShopTableSize);
    
    		tmp->EncodeWORD(m_iRefineTableSize);
    		tmp->Encode(m_pRefineTable, sizeof(TRefineTable) * m_iRefineTableSize);
    
    		tmp->EncodeWORD(m_vec_itemAttrTable.size());
    		tmp->Encode(&m_vec_itemAttrTable[0], sizeof(TItemAttrTable) * m_vec_itemAttrTable.size());
    
    		tmp->EncodeWORD(m_vec_itemRareTable.size());
    		tmp->Encode(&m_vec_itemRareTable[0], sizeof(TItemAttrTable) * m_vec_itemRareTable.size());

     

    And finally let me wish you all good luck for the setup ;) If you have further question(s), remark(s), or anything that you want to ask or suggest, feel free to post it here, or send it in PM.

    If you get error(s) please upload the affected (and edited) file to http://pastebin.com/ and link it in your post, to make my work easier and probably I will be able to help you only in one post, so please spare me from asking basic requests like "Could you upload...". Thank you ;)

    Have a nice day,
    ~masodikbela

    • Metin2 Dev 69
    • Angry 1
    • Smile Tear 1
    • Confused 1
    • Good 16
    • Love 4
    • Love 82
  4. 6 hours ago, Thanatos said:

    this game have a visual bug.in client where it must apear level instead of level apear Szint [Name_of_character].

    How i can rezolv it?

    Lol, its not a visual bug, its just a Hungarian core, so the old Lv. string is translated to Hungarian. If you search it in the client_binary's source (or in the .exe with a hex editor) you can rewrite it easily.

  5. Actually, your second "code" is a solution. I tested it in the following way:

    I wrote this into my questlib.lua:

    Spoiler

    test_shitty_string = "I think you are "..pc.get_name()

    Then I wrote this into my quest:

    Spoiler

            when 9005.chat.test_shitty_string begin
                chat("YOLO")
            end

    Then the result was:

    Spoiler

    ab94999152.jpg

    (The second option is from my other quest :D)

  6. So. Firstly, try to replace the g_szPublicIP variable, to your ip only in this part:

    Spoiler

                        if (!bSentBoot)
                        {
                            bSentBoot = true;
                            TPacketGDBoot p;
                            p.dwItemIDRange[0] = 0;
                            p.dwItemIDRange[1] = 0;
                            memcpy(p.szIP, g_szPublicIP, 16);
                            DBPacket(HEADER_GD_BOOT, 0, &p, sizeof(p));
                        }

    An example:

    Spoiler

                        if (!bSentBoot)
                        {
                            bSentBoot = true;
                            TPacketGDBoot p;
                            p.dwItemIDRange[0] = 0;
                            p.dwItemIDRange[1] = 0;
                            memcpy(p.szIP, "write.your.ip.here", 16);
                            DBPacket(HEADER_GD_BOOT, 0, &p, sizeof(p));
                        }

    IF it doesn't solve the problem, then you should replace the g_szPublicIP variable to your ip in this line too:

    Spoiler

    strlcpy(p.szPublicIP, g_szPublicIP, sizeof(p.szPublicIP));

     

    • Dislove 1
  7. 1 hour ago, alexandru1992 said:

    Hi guys ,i have a big problem with my game or client binary i don't  know really what's the problem , i'm trying to figure it out for about 2 weeks and nothing, i searched on google ,other forums but my searches were in vain so i hope you will help me so let me tell you about my "bug" : so i created a server , i installed unix ,ports all stuffs on a pc portforwarded the ports i need through router all were good until someone tried to login ,he was kick out when he selected his character and i don't f**king know why this stupid thing drives me crayzi, if i login  on my internal network even from external ip it works ,but when my friend tries to connect nothing, it kicks him to the login again and again, i saw that it's already a post related to that on this forum named, if i think well "40250 game problem" , i follow those steps with bind_ip and other stuff but when i bind the ip it says to me that "can't bind that adress " i don't know again why ,i tried all possible things even change the game with other and same ,of course it was same version 40k ,what do you recommend me to do guys?And i mentioned i have static ip .I don't know what to do :( please help me if you know of course ,many people avoid to answer at this question "how to resolve kick login"  please don't avoid me too.

     

    Well, for me this usually works:

    Try to replace this in your desc_client.cpp:
    replace the g_szPublicIP to your ip adress (like memcpy(p.szIP, "69.69.69.69", 16);) in this:
     

                        if (!bSentBoot)
    
    	                    {
    
    	                        bSentBoot = true;
    
    	                        TPacketGDBoot p;
    
    	                        p.dwItemIDRange[0] = 0;
    
    	                        p.dwItemIDRange[1] = 0;
    
    	                        memcpy(p.szIP, g_szPublicIP, 16);
    
    	                        DBPacket(HEADER_GD_BOOT, 0, &p, sizeof(p));
    
    	                    }
    
     

    If it didn't solve the problem, then replace the same variable in this one too:

     

                    strlcpy(p.szPublicIP, g_szPublicIP, sizeof(p.szPublicIP));
    
     

    On windows, doing only the first part solves the problem for me, but on BSD, usually I have to do both. (Don't ask me why...)

    • Love 2
  8. 27 minutes ago, enzi said:

    Very much thanks man ;) 

    but i got 1 more error:

      Hide contents

    1230 12:08:17293 :: 
    uiTaskBar.py(line:480) LoadWindow
    ui.py(line:2828) LoadScriptFile

    TaskBar.LoadWindow.LoadObject - <type 'exceptions.KeyError'>:'window'

    1230 12:08:17293 :: ============================================================================================================
    1230 12:08:17293 :: Abort!!!!

    This is the hidden content, please

    This is the hidden content, please

     

    In your taskbar.py in locale_xx/locale/xx/ui/ something is wrong, maybe wrong tabulators, or missing the window key, or something. It should start like this:

    window = {
    	"name" : "TaskBar",
    
    	"x" : 0,
    	"y" : SCREEN_HEIGHT - 37,
    
    	"width" : SCREEN_WIDTH,
    	"height" : 37,
    
    	"children" :
    	(

     

     

    • Love 1
  9. 9 hours ago, enzi said:

    Hello..

    Anyone know fix for this error?

      Hide contents

    1230 01:04:17179 :: Traceback (most recent call last):

    1230 01:04:17179 ::   File "networkModule.py", line 247, in SetGamePhase

    1230 01:04:17179 ::   File "game.py", line 78, in __init__

    1230 01:04:17180 ::   File "interfaceModule.py", line 286, in MakeInterface

    1230 01:04:17180 ::   File "interfaceModule.py", line 170, in __MakeWindows

    1230 01:04:17180 ::   File "uiInventory.py", line 262, in __init__

    1230 01:04:17180 ::   File "uiInventory.py", line 400, in __LoadWindow

    1230 01:04:17180 ::   File "uiInventory.py", line 468, in SetInventoryPage

    1230 01:04:17180 ::   File "uiInventory.py", line 580, in RefreshBagSlotWindow

    1230 01:04:17180 ::   File "uiInventory.py", line 230, in RefreshSlot

    1230 01:04:17180 :: AttributeError
    1230 01:04:17180 :: : 
    1230 01:04:17180 :: 'GridSlotWindow' object has no attribute 'SetAlwaysRenderCoverButton'
    1230 01:04:17180 :: 

    This is the hidden content, please

    This is the hidden content, please

    This is the hidden content, please

    This is the hidden content, please

    In the ui.py you don't have the function 'SetAlwaysRenderCoverButton' in class 'GridSlotWindow'. Here is mine:

    	def SetAlwaysRenderCoverButton(self, slotIndex, bAlwaysRender = TRUE):
    		wndMgr.SetAlwaysRenderCoverButton(self.hWnd, slotIndex, bAlwaysRender)
    
     
    • Love 2
  10. Maybe if you accept only payment with option "Send money to a family member or a friend" the customers can't refund the money.

    Or if you create a "merchant button" for the customers, they can't refund too (I'm not sure about this, but this refund option in paypal very annoying)

  11. But the problem is remain what I said: The "items" vector doesn't have as much record as much you wish to index. And this came from the bad length of data in the txts.

    Sadly I can't say more than this, because some part of the system is now more than one years old, and the newer parts are old enough to forget what I did before 3+ mounts ago :D

  12. The line that you see in the syserr is not equal to the line in the quest file. To see the line exactly go to: quest/object/state/ and open mb_igshop.


    Btw I think the problem caused by this line: item = split_(items,"#") Because it creates a table from the lines in the txt-s. So you have to change the line writer functions before you can test this one.

  13. 33 minutes ago, Traktorzysta said:

    Can someone explain values in this function:

            function add_items(maxpage, page, items, itemsOnLastPage, group)
                if page <= 0 then page = 1 end
                if page > maxpage then page = maxpage end
                local from = (page - 1)*5 + 1
                local to = 0
                if maxpage > page then
                    to = ((page - 1 )*5) + 5
                else
                    to = ((page - 1)*5) + itemsOnLastPage
                end
                local slot = 1
                local item
                local commandL
                if group == "my_buys" then
                    commandL = "IGShop_BOUGHTITEMS"
                elseif group == "my_sales" then
                    commandL = "IGShop_MYSALES"
                else
                    commandL = "IGShop_ITEMS"
                end

                for i = from, to do
                    item = split_(items,"#")
                    if igshopEnableTrade then
                        if group == "get_trade_items" then
                            cmdchat("trade.GetTradeItems "..slot.." "..item[1].." "..item[2].." "..item[3].." "..item[4].." "..item[5].." "..item[6].." "..item[7].." "..item[8].." "..item[9].." "..item[10].." "..item[11].." "..item[12].." "..item[13].." "..item[14].." "..item[15].." "..item[16].." "..item[17].." "..item[18].." "..item[19].." "..item[20].." "..item[21].." "..item[22].." "..item[23].." "..item[24])
                        else
                            cmdchat(commandL.." "..slot.." "..item[1].." "..item[2].." "..item[3].." "..item[4].." "..item[5].." "..item[6].." "..item[4+3]..' '..item[5+3]..' '..item[6+3]..' '..item[7+3]..' '..item[8+3]..' '..item[9+3]..' '..item[10+3]..' '..item[11+3]..' '..item[12+3]..' '..item[13+3]..' '..item[14+3]..' '..item[15+3]..' '..item[16+3]..' '..item[17+3]..' '..item[18+3]..' '..item[19+3]..' '..item[20+3]..' '..item[21+3]..' '..item[22+3]..' '..item[23+3]..' '..item[28]..' '..mb_igshop.IsTradeItem(item[1]))
                        end
                    else
                        cmdchat(commandL.." "..slot.." "..item[1].." "..item[2].." "..item[3].." "..item[4].." "..item[5].." "..item[6].." "..item[4+3]..' '..item[5+3]..' '..item[6+3]..' '..item[7+3]..' '..item[8+3]..' '..item[9+3]..' '..item[10+3]..' '..item[11+3]..' '..item[12+3]..' '..item[13+3]..' '..item[14+3]..' '..item[15+3]..' '..item[16+3]..' '..item[17+3]..' '..item[18+3]..' '..item[19+3]..' '..item[20+3]..' '..item[21+3]..' '..item[22+3]..' '..item[23+3]..' '..item[28]..' -1')
                    end
                    -- 1. slot, 2. item id, 3. item vnum, 4. item count, 5. owner name, 6. price se, 7. price yang
                    slot = slot + 1
                end
            end

     

     

    Why in else values+3? I need change this function for 4socket and 6 attr+2rare

    If you check the game.py, you can see the value names exactly.

    For the line starts with cmdchat("trade.GetTradeItems see def _IGShopGetTradeItem. For the others see def _IGShopItems.

  14. 14 hours ago, ds_aim said:

    Thanks for share.

    But , you should debug client binary and see where it's the problem.

     

    I sloved this one month ago. But i don't changed in game nothing. :)

    As you can see in the video it crashed the core, and not the client binary. But I already debuged the core, and the problem was there. Its definitely game core problem not client binary problem. Because when you invite somebody to the party, it sets the "dungeon" to the new member. And if we don't set the dungeon to "null" when we destroy the dungeon, it will point to an incorrect memory adress, and when we try to use this incorrect adress, it will lead to core crash,

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