05-15-2021, 02:53 AM
2Here is all known fixes that i have for dupes. and other additional fixes. If you have any other fixes and chose to share them it would be appreciated.
I do apologize ahead of time for anyone this may upset by releasing these fixes.
I think everyone in lc likes to keep all these fixes private and by doing this anyone who wants to create a server can't really.
credits: rrkbmz,reza (whoever else i missed)
these fixes are from 1 (source i paid for and 2 reza's source leak)
1.mysterious statue dupe (negative gold value)
Server/GameServer/doFuncExpressSystem.cpp
after void process_use_unsearchable_stonestatue(CPC* ch, CNetMsg::SP& msg)
put this :
//change this:
if (sendItem->Count() < packet->itemCount)
//to this:
if (sendItem->Count() < packet->itemCount || packet->itemCount <= 0)
2. drop item dupe (negative value)
Server/GameServer/DoFuncItem.cpp
after void do_ItemThrow(CPC* ch, CNetMsg::SP& msg)
put this:
// you will see somthing like this in your code.
ArtifactManager::instance()->item_drop(item);
}
CItem* dropitem = NULL;
// new code will look like this:
ArtifactManager::instance()->item_drop(item);
}
if (packet->count <= 0) {
CNetMsg::SP rmsg(new CNetMsg);
SysMsg(rmsg, MSG_SYS_FULL_INVENTORY);
SEND_Q(rmsg, ch->m_desc);
return;
}
CItem* dropitem = NULL;
3. guild storage dupe
this is a little to big to write in a couple lines ill just link the fixes:
gameserver/pc.cpp
gameserver/ProcHelperMsg.cpp
gameserver/Character.h
gameserver/DoFuncGuild.cpp
2
2
2
2
here is an example of what you're looking for :
2
2
2
2
4. double login dupe (here their might be more then 1 fix for this method might not full fix it)
Server/GameServer/Descriptor.cpp
in void CDescriptor::operate( rnSocketIOService* service )
put this:
// you'll see this code (just search it)
packet->subType = MSG_RETURN_TO_SELECT_CHANNEL;
rmsg->setSize(sizeof(pTypeBase));
SEND_Q(rmsg, this);
}
break;
default:
//replace that code with this:
packet->subType = MSG_RETURN_TO_SELECT_CHANNEL;
rmsg->setSize(sizeof(pTypeBase));
SEND_Q(rmsg, this);
this->Close("");
return;
}
break;
default:
//next you'll see this
LOG_ERROR("Invalid packet. type[%d] / now is character select screen. user_index",
msg->m_mtype, this->m_index);
this->Close("Invalid packet. now is character select screen");
return;
}
break;
//replace it with this
LOG_ERROR("Invalid packet. type[%d] / now is character select screen. user_index",
msg->m_mtype, this->m_index);
//this->Close("Invalid packet. now is character select screen");
GAMELOG << init("INVALID_PACKET")
<< "user_index" << delim
<< this->m_index << delim
<< end;
return;
}
break;
5. Quest Exploit (dupe)
Server/GameServer/DoFuncQuest.cpp
after void do_Quest(CPC* ch, CNetMsg::SP& msg)
put this:
// you'll see this
case MSG_QUEST_RESTORE_ABANDON:
do_QuestRestoreAbandon(ch, msg); // 포기 퀘스트 복구
break;
case MSG_QUEST_ITEM_REQ:
do_QuestItemReq(ch, msg); // 완료한 퀘스트중 퀘스트 아이템 받기
break;
//change it to this
case MSG_QUEST_RESTORE_ABANDON:
do_QuestRestoreAbandon(ch, msg); // 포기 퀘스트 복구
break;
Next we'll want to disable the function too
after void do_QuestRestoreAbandon(CPC* ch, CNetMsg::SP& msg)|
put this:
//the deefault code
void do_QuestItemReq(CPC* ch, CNetMsg::SP& msg)
//disable this whole function or delete it
// this disables
6. Gold Dupe
Server/GameServer/DoFuncEtc.cpp
put this:
//search for this MSG_MANAGEMENT_STATE_CHANGE
if(ch->m_inventory.getMoney() < needMoney)
{
// ERROR 돈 없음
CNetMsg::SP rmsg(new CNetMsg);
DVDManagementMsg( rmsg, MSG_MANAGEMENT_ENV_CHANGE );
RefMsg(rmsg) << (unsigned char) MSG_DVD_ERROR_MONEY;
SEND_Q( rmsg, ch->m_desc );
return;
}
else
//modify this
if(ch->m_inventory.getMoney() < needMoney)
//to this
if( ch->m_inventory.getMoney() < needMoney || needMoney <= 0)
//next in case MSG_MANAGEMENT_ENV_CHANGE :
//find this
if( ch->m_inventory.getMoney() < needMoney)
{
// ERROR �� ����
CNetMsg::SP rmsg(new CNetMsg);
DVDManagementMsg( rmsg, MSG_MANAGEMENT_ENV_CHANGE );
RefMsg(rmsg) << (unsigned char) MSG_DVD_ERROR_MONEY;
SEND_Q( rmsg, ch->m_desc );
return;
}
else
//change it to this
if( ch->m_inventory.getMoney() < needMoney || needMoney <=0)
Additionally here are some secondary crash fixes:
Area.cpp:
//after this
for (; it != endit; ++it)
{
CNPCRegenInfo* p = *(it);
p->m_lastDieTime = gserver->m_pulse + GetRandom(1, p->m_regenSec / 2);
p->m_bAlive = false;
}
//add this
if (this->m_RaidDifficulty > 2 || this->m_RaidDifficulty <= -1)
{
this->m_RaidDifficulty = 0;
}
Raidata.cpp:
2
DoFuncExpedtion.cpp:
// in this function
void do_ExpedChangeTypeReq(CPC* ch, CNetMsg::SP& msg)
{
//after this value
GAMELOG << init("EXPED DEBUG CHANGETYPE REQ", ch)
<< "EXPEDTYPE" << delim << cExpedType << delim
<< "DIVITYPE" << delim << cDiviType << delim
<< end;
// add this
if (cExpedType > MSG_EXPED_TYPE_OPENBOX || cDiviType > MSG_DIVITYPE_SP)
{
CNetMsg::SP rmsg(new CNetMsg);
ExpedErrorMsg(rmsg, MSG_EXPED_ERROR_NOT_EXPED);
SEND_Q(rmsg, ch->m_desc);
return;
}
//next we add somthing here
void do_ExpedMoveGroupReq(CPC* ch, CNetMsg::SP& msg)
//after this
GAMELOG << init("EXPED DEBUG MOVEGROUP REQ", ch)
<< "SOURCE GROUP" << delim << nMoveCharIndex << delim
<< "MOVE CHAR INDEX" << delim << nMoveCharIndex << delim
<< "TARGET GROUP" << delim << nTargetGroup << delim
<< "TARGET CHAR INDEX" << delim << nTargetListindex
<< end;
//add this
if (nSourceGroup >= MSG_EXPED_GROUP_COUNT || nTargetGroup >= MSG_EXPED_GROUP_COUNT)
{
LOG_INFO("Crash teste ????????");
return;
}
//next we add a fix here
void do_ExpendOffline(CPC* ch, CNetMsg::SP& msg)
{
//add this
if( !ch || ch->m_Exped == NULL || ch->m_bProcDisconnect == 0)
{
return;
}
DoFuncParty.cpp:
//in this function
void do_PartyChangeType(CPC* ch, CNetMsg::SP& msg)
{
//after this
RefMsg(msg) >> cPartyType // ÀϹÝ(±Õµî),ÀÔŒö¿ìŒ±,ÀüÅõÇü,»óÀÚ¿±â ±žºÐ
>> cDiviType // °æÇèÄ¡,ŸÆÀÌÅÛ,œºÆäŒÈ ŸÆÀÌÅÛ ±žºÐ
>> cAllOneSet;
//add this
if (cPartyType > MSG_PARTY_TYPE_OPENBOX ||cDiviType > MSG_DIVITYPE_SPECIAL || cAllOneSet > MSG_PARTY_SETALLONE_ONE)
{
CNetMsg::SP rmsg(new CNetMsg);
PartyErrorMsg(rmsg, MSG_PARTY_ERROR_NOT_PARTY);
SEND_Q(rmsg, ch->m_desc);
return;
}
//next fix in this function
void do_PartyOffline(CPC* ch, CNetMsg::SP& msg)
{
//add this
if ( ( !ch && (ch->m_party != NULL)) || (ch->m_party == NULL) || (ch->m_bProcDisconnect == 0))
{
return;
}
warehouse save: ( DBManager_SaveCharacterInfo.cpp)
//replace this
std:
tring deleteQuery = boost:
tr(boost::format("DELETE FROM t_stash%02d WHERE a_user_idx=%d") % stashIndex % pChar->m_index);
//change to this
std:
tring deleteQuery = boost:
tr(boost::format("DELETE FROM t_stash%02d WHERE a_user_idx=%d") % stashIndex % pChar->m_desc->m_index);
DoFuncEtc.cpp (castle crystal outside area)
//after this
{
CNetMsg::SP rmsg(new CNetMsg);
CastleErrorMsg(rmsg, MSG_EX_CASTLE_ERROR_MEM_5_FAIL);
SEND_Q(rmsg, ch->m_desc);
return;
}
//add this
CNPC* pLordSymbol = pCastle->GetLordSymbol();
if (pLordSymbol && (GetDistance(GET_X(pLordSymbol), GET_Z(pLordSymbol), GET_H(pLordSymbol), ch) > 12
|| GET_YLAYER(ch) != GET_YLAYER(pLordSymbol)))
{
CNetMsg::SP rmsg(new CNetMsg);
CastleErrorMsg(rmsg, MSG_EX_CASTLE_ERROR_POS_FAIL);
SEND_Q(rmsg, ch->m_desc);
ch->m_desc->IncreaseHackCount(3);
return;
}
Engine/Contents/Base/ChattingUI.cpp
//replace this
int nIndexBuf[32];
//with this
int nIndexBuf[256];
Chat input crash fix.
Engine/Interface/UITextBoxEx.cpp
// in function void CUITextBoxEx:
plit(std:
tring str, CItems* item, int countItems)//your code will look like this
else
strText = strSyntax;
switch(m_eSplitType)
{
case SPLIT_NONE:
//change it to this
else
strText = strSyntax;
if (strText.empty()) break;
switch(m_eSplitType)
{
case SPLIT_NONE:
//next function we will modify is void CUITextBoxEx::insertBtn( CUITextEx* pTextEx, vecValcont& val, std:
tring&//you will e looking for this
int nCmd = -1;
int nIndex = -1;
if (nSize >= eTVCMD_INDEX)
{
nCmd = atoi(val[eTVCMD_CMD].c_str());
nIndex = atoi(val[eTVCMD_INDEX].c_str());
//modify the line nSize >= eTVCMD_INDEX
//change it to this
if (nSize > eTVCMD_INDEX)

