Files
Sun1602/Tools/ItemDropTestTool/DropManager.cpp
T
2022-10-26 12:25:11 +08:00

692 lines
16 KiB
C++

#include "StdAfx.h"
#include ".\dropmanager.h"
CDropManager::CDropManager(void)
{
m_nScriptType = 0;
m_dwCntKillMonster = 0;
}
CDropManager::~CDropManager(void)
{
ItemInfoParser::Instance()->Release();
ItemInfoParser::Instance()->DestroyInstance();
FormulaRatioParser::Instance()->Release();
FormulaRatioParser::Instance()->DestroyInstance();
NPCInfoParser::Instance()->Release();
NPCInfoParser::Instance()->DestroyInstance();
m_DropCore.Unload();
}
vector<CString> CDropManager::GetProcessTitle()
{
vector<CString> vecTitle;
CString strTemp;
strTemp = "종류";
vecTitle.push_back(strTemp);
strTemp = "코드";
vecTitle.push_back(strTemp);
strTemp = "이름 또는 돈액수";
vecTitle.push_back(strTemp);
strTemp = "드랍레벨";
vecTitle.push_back(strTemp);
strTemp = "인첸트급수";
vecTitle.push_back(strTemp);
strTemp = "랭크급수";
vecTitle.push_back(strTemp);
strTemp = "디바인여부";
vecTitle.push_back(strTemp);
return vecTitle;
}
vector<CString> CDropManager::GetResultTitle()
{
vector<CString> vecTitle;
CString strTemp;
strTemp = "종류";
vecTitle.push_back(strTemp);
strTemp = "코드";
vecTitle.push_back(strTemp);
strTemp = "이름 또는 돈액수";
vecTitle.push_back(strTemp);
strTemp = "드랍레벨";
vecTitle.push_back(strTemp);
//strTemp = "인첸트급수";
//vecTitle.push_back(strTemp);
//strTemp = "랭크급수";
//vecTitle.push_back(strTemp);
//strTemp = "디바인여부";
//vecTitle.push_back(strTemp);
strTemp = "개수";
vecTitle.push_back(strTemp);
strTemp = "드랍확률";
vecTitle.push_back(strTemp);
return vecTitle;
}
vector<CString> CDropManager::GetNameScriptType()
{
vector<CString> vecTitle;
CString strTemp;
strTemp = "헌팅";
vecTitle.push_back(strTemp);
strTemp = "미션";
vecTitle.push_back(strTemp);
return vecTitle;
}
vector<CString> CDropManager::GetNameMonsterType()
{
vector<CString> vecTitle;
CString strTemp;
strTemp = "일반";
vecTitle.push_back(strTemp);
strTemp = "정예";
vecTitle.push_back(strTemp);
strTemp = "대장";
vecTitle.push_back(strTemp);
strTemp = "중보스";
vecTitle.push_back(strTemp);
strTemp = "보스";
vecTitle.push_back(strTemp);
return vecTitle;
}
//나중에 이 부분을 초기화 부분에서 실행하도록 하고,
//따로 선택옵션에 따라 데이타를 처리하도록 코딩할것...
BOOL CDropManager::Initialize()
{
BOOL bRet = FALSE;
ItemInfoParser::Instance()->Init(100);
bRet = ItemInfoParser::Instance()->Load( "data\\AccessoryItemInfo.txt" );
if(bRet == FALSE)
{
AfxMessageBox( "AccessroyItemInfo.txt Load Error" );
return FALSE;
}
bRet = ItemInfoParser::Instance()->Load( "data\\ArmorItemInfo.txt" );
if(bRet == FALSE)
{
AfxMessageBox( "ArmorItemInfo.txt Load Error" );
return FALSE;
}
bRet = ItemInfoParser::Instance()->Load( "data\\WeaponItemInfo.txt" );
if(bRet == FALSE)
{
AfxMessageBox( "WeaponItemInfo.txt Load Error" );
return FALSE;
}
bRet = ItemInfoParser::Instance()->Load( "data\\WasteItemInfo.txt" );
if(bRet == FALSE)
{
AfxMessageBox( "WasteItemInfo.txt Load Error" );
return FALSE;
}
NPCInfoParser::Instance()->Init( 300);
NPCInfoParser::Instance()->Load( "data\\NPCInfo.txt" );
if(bRet == FALSE)
{
AfxMessageBox( "NPCInfo.txt Load Error" );
return FALSE;
}
FormulaRatioParser::Instance()->Init(10);
bRet = FormulaRatioParser::Instance()->Load( "data\\FormulaRatio.txt" );
if(bRet == FALSE)
{
AfxMessageBox( "FormulaRatio.txt Load Error" );
return FALSE;
}
m_DropCore.Load( "data\\DropRatioInfo.txt", "data\\ItemTypeDropRatio.txt", "data\\ItemTypeList.txt" );
return TRUE;
}
BOOL CDropManager::DropItem( WORD wLowerLevel, WORD wUpperLevel, BYTE byGrade, DWORD dwNpcCount, BYTE byFieldType )
{
MONSTER_LIST listMonster;
GetMonster( wLowerLevel, wUpperLevel, byGrade, listMonster );
int nMonsterCnt = (int)listMonster.size();
if( nMonsterCnt <= 0 )
{
AfxMessageBox("해당 조건의 몬스터가 없습니다.");
return FALSE;
}
//한몬스터당 죽일 횟수( 전체 죽일 몬스터의 수에 현재 조건의 몬스터수로 나눈다.)
DWORD dwKillCntPerMonster = dwNpcCount / nMonsterCnt;
DWORD dwKillCntLast = dwNpcCount - ( dwKillCntPerMonster * nMonsterCnt );
FLOAT PlusBonusPercent = 1.0f;
// (헌팅:미션) 구분
if( byFieldType == eZONETYPE_HUNTING )
PlusBonusPercent = 1.1f;
MONEY DroppedMoney = 0;
SCItemSlot DroppedItemSlot;
eDROP_TYPE_ DroppedType;
DWORD dwDecidedSeed = 0;
//Initialize
m_mapDropItem.clear();
m_vecItemCode.clear();
// 기본 몬스터를 죽인다.
for( DWORD dwMonster = 0; dwMonster < dwKillCntPerMonster; dwMonster++ )
{
for( MONSTER_ITER iter = listMonster.begin() ; iter != listMonster.end(); iter++ )
{
BASE_NPCINFO* pNPCInfo = *iter;
if( !pNPCInfo ) continue;
for( int i = 0 ; i < BASE_NPCINFO::MAX_DROPRATIO_INDEX_NUM ; ++i )
{
DWORD dwDropIndex = pNPCInfo->m_dwDropIndex[i];
if( 0 == dwDropIndex ) continue;
if( !m_DropCore.Drop( byFieldType, dwDropIndex, (eNPC_GRADE)pNPCInfo->m_byGrade, PlusBonusPercent,
DroppedType, DroppedMoney, DroppedItemSlot, dwDecidedSeed ) )
continue;
CDropItem item;
DWORD dwCode = 0;
if( DroppedType == DROP_TYPE_ITEM )
{
dwCode = (DWORD)DroppedItemSlot.GetCode();
item.SetCode( dwCode );
item.SetName( DroppedItemSlot.GetItemInfo()->m_pszName );
item.SetDropLevel( (BYTE)DroppedItemSlot.GetDropLevel() );
item.SetRank( DroppedItemSlot.GetRank() );
item.SetEnchantLevel( (BYTE)DroppedItemSlot.GetEnchant() );
item.SetDivine( DroppedItemSlot.IsDivine() );
}
else
{
MONEY money;
DropMoney( DroppedMoney, money );
item.SetCode( dwCode );
item.SetName( "" );
item.SetDropLevel( 0 );
item.SetMoney( (DWORD)money );
item.SetRank( 0 );
item.SetEnchantLevel( 0 );
item.SetDivine( FALSE );
}
item.SetDropType_( DroppedType );
m_mapDropItem.insert( make_pair( dwCode, item ) );
vector<DWORD>::iterator iterCode = find( m_vecItemCode.begin(), m_vecItemCode.end(), dwCode );
if( iterCode == m_vecItemCode.end() )
m_vecItemCode.push_back( dwCode );
}
}
}
// 나머지 몬스터를 죽인다.. 무조건 1번 몬스터로 한다.
for( DWORD dwMonster = 0; dwMonster < dwKillCntLast; dwMonster++ )
{
BASE_NPCINFO* pNPCInfo = *listMonster.begin();
if( !pNPCInfo ) continue;
for( int i = 0 ; i < BASE_NPCINFO::MAX_DROPRATIO_INDEX_NUM ; ++i )
{
DWORD dwDropIndex = pNPCInfo->m_dwDropIndex[i];
if( 0 == dwDropIndex ) continue;
if( !m_DropCore.Drop( byFieldType, dwDropIndex, (eNPC_GRADE)pNPCInfo->m_byGrade, PlusBonusPercent, DroppedType, DroppedMoney, DroppedItemSlot, dwDecidedSeed ) )
continue;
CDropItem item;
DWORD dwCode = 0;
if( DroppedType == DROP_TYPE_ITEM )
{
dwCode = (DWORD)DroppedItemSlot.GetCode();
item.SetCode( dwCode );
item.SetName( DroppedItemSlot.GetItemInfo()->m_pszName );
item.SetDropLevel( (BYTE)DroppedItemSlot.GetDropLevel() );
item.SetRank( DroppedItemSlot.GetRank() );
item.SetEnchantLevel( (BYTE)DroppedItemSlot.GetEnchant() );
item.SetDivine( DroppedItemSlot.IsDivine() );
}
else
{
MONEY money;
DropMoney( DroppedMoney, money );
item.SetCode( dwCode );
item.SetName( "" );
item.SetDropLevel( 0 );
item.SetMoney( (DWORD)money );
item.SetRank( 0 );
item.SetEnchantLevel( 0 );
item.SetDivine( FALSE );
}
item.SetDropType_( DroppedType );
m_mapDropItem.insert( make_pair( dwCode, item ) );
vector<DWORD>::iterator iterCode = find( m_vecItemCode.begin(), m_vecItemCode.end(), dwCode );
if( iterCode == m_vecItemCode.end() )
m_vecItemCode.push_back( dwCode );
}
}
return TRUE;
}
BOOL CDropManager::DropItemEx( DWORD dwNpcCode, DWORD dwNpcCount, BYTE byFieldType )
{
BASE_NPCINFO* pNpcInfo = NPCInfoParser::Instance()->GetMonsterInfo( dwNpcCode );
if( !pNpcInfo ) return FALSE;
FLOAT PlusBonusPercent = 1.0f;
// (헌팅:미션) 구분
if( byFieldType == eZONETYPE_HUNTING )
PlusBonusPercent = 1.1f;
MONEY DroppedMoney = 0;
SCItemSlot DroppedItemSlot;
eDROP_TYPE_ DroppedType;
DWORD dwDecidedSeed = 0;
//Initialize
m_mapDropItem.clear();
m_vecItemCode.clear();
// 기본 아이템 드랍
for( DWORD dwMonster = 0; dwMonster < dwNpcCount; dwMonster++ )
{
for( int i = 0 ; i < BASE_NPCINFO::MAX_DROPRATIO_INDEX_NUM ; ++i )
{
DWORD dwDropIndex = pNpcInfo->m_dwDropIndex[i];
if( 0 == dwDropIndex ) continue;
if( !m_DropCore.Drop( dwDropIndex, (eNPC_GRADE)pNpcInfo->m_byGrade, PlusBonusPercent, DroppedType, DroppedMoney, DroppedItemSlot, dwDecidedSeed ) )
continue;
CDropItem item;
DWORD dwCode = 0;
if( DroppedType == DROP_TYPE_ITEM )
{
dwCode = (DWORD)DroppedItemSlot.GetCode();
item.SetCode( dwCode );
item.SetName( DroppedItemSlot.GetItemInfo()->m_pszName );
item.SetDropLevel( (BYTE)DroppedItemSlot.GetDropLevel() );
item.SetRank( DroppedItemSlot.GetRank() );
item.SetEnchantLevel( (BYTE)DroppedItemSlot.GetEnchant() );
item.SetDivine( DroppedItemSlot.IsDivine() );
}
else
{
MONEY money;
DropMoney( DroppedMoney, money );
item.SetCode( dwCode );
item.SetName( "" );
item.SetDropLevel( 0 );
item.SetMoney( (DWORD)money );
item.SetRank( 0 );
item.SetEnchantLevel( 0 );
item.SetDivine( FALSE );
}
item.SetDropType_( DroppedType );
m_mapDropItem.insert( make_pair( dwCode, item ) );
vector<DWORD>::iterator iterCode = find( m_vecItemCode.begin(), m_vecItemCode.end(), dwCode );
if( iterCode == m_vecItemCode.end() )
m_vecItemCode.push_back( dwCode );
}
}
return TRUE;
}
void CDropManager::SetScriptType(int nType)
{
m_nScriptType = nType;
}
int CDropManager::GetScriptType()
{
return m_nScriptType;
}
//아이템 드롭 결과
void CDropManager::CalcItemDropResult()
{
m_mapDropResult.clear();
//1. Drop된 모든 코드를 뽑아낸다.
for( int i = 0; i < (int)m_vecItemCode.size(); i++ )
{
DWORD dwCode = m_vecItemCode[i];
DWORD dwItemCnt = 0;
DWORD dwSumMoney = 0;
CDropItem item;
DROPITEM_ITER iterPos;
for( iterPos = m_mapDropItem.lower_bound( dwCode ) ; iterPos != m_mapDropItem.upper_bound( dwCode ) ; ++iterPos )
{
item = iterPos->second;
dwItemCnt++;
dwSumMoney += item.GetMoney();
}
if( dwItemCnt > 0 )
{
CDropResult resultInfo;
resultInfo.SetItem( item );
resultInfo.SetSumMoney( dwSumMoney );
resultInfo.SetItemCount( dwItemCnt );
if( m_dwCntKillMonster == 0 )
resultInfo.SetDropRate( 0.0f );
else
resultInfo.SetDropRate( (float)( ((float)resultInfo.GetItemCount() / (float)m_dwCntKillMonster)*100 ) );
m_mapDropResult.insert( make_pair( dwCode, resultInfo ) );
}
}
}
CString CDropManager::GetSaveDropInfo(int nViewOption)
{
int nSize = 0;
CString strSave, str;
if( nViewOption == 0 ) // 결과
{
for( DROPRESULT_ITER iter = m_mapDropResult.begin(); iter != m_mapDropResult.end() ; iter++ )
{
CDropResult info = iter->second;
// 아이템 종류
str = GetItemType( info.GetItem().GetDropType() );
strSave += str;
strSave += "\t";
// 아이템 코드
str.Format("%d", (WORD)info.GetItem().GetCode() );
strSave += str;
strSave += "\t";
// 이름
if( info.GetItem().GetDropType() == DROP_MONEY_1 || info.GetItem().GetDropType() == DROP_MONEY_40 ||
info.GetItem().GetDropType() == DROP_MONEY_400 )
str.Format("%d", info.GetItem().GetMoney() );
else
str.Format("%s", info.GetItem().GetName() );
strSave += str;
strSave += "\t";
// 드랍레벨
str.Format("%d", (WORD)info.GetItem().GetDropLevel() );
strSave += str;
strSave += "\t";
//인첸트 급수
str = GetEnchantLevel( (eENCHANTLEVEL)info.GetItem().GetEnchantLevel() );
strSave += str;
strSave += "\t";
//랭크 급수
str = GetRank( (eRANK)info.GetItem().GetRank() );
strSave += str;
strSave += "\t";
//디바인 여부
if( info.GetItem().GetDivine() ) str = "Y";
else str = "N";
strSave += str;
strSave += "\t";
//개수
str.Format("%d", info.GetItemCount() );
strSave += str;
strSave += "\t";
//확률
str.Format("%0.3f%%", info.GetDropRate() );
strSave += str;
strSave += "\r\n";
}
}
else if( nViewOption == 1 ) // 과정
{
for( DROPITEM_ITER iter = m_mapDropItem.begin(); iter != m_mapDropItem.end(); iter++ )
{
CDropItem item = iter->second;
// 아이템 종류
str = GetItemType( item.GetDropType() );
strSave += str;
strSave += "\t";
// 아이템 코드
str.Format("%d", (WORD)item.GetCode() );
strSave += str;
strSave += "\t";
// 이름
if(item.GetDropType() == DROP_MONEY_1 || item.GetDropType() == DROP_MONEY_40 || item.GetDropType() == DROP_MONEY_400 )
str.Format("%d", item.GetMoney() );
else
str.Format("%s", item.GetName().c_str() );
strSave += str;
strSave += "\t";
// 드랍레벨
str.Format("%d", (WORD)item.GetDropLevel() );
strSave += str;
strSave += "\t";
//인첸트 급수
str = GetEnchantLevel( (eENCHANTLEVEL)item.GetEnchantLevel() );
strSave += str;
strSave += "\t";
//랭크 급수
str = GetRank( (eRANK)item.GetRank() );
strSave += str;
strSave += "\t";
//디바인 여부
if( item.GetDivine()) str = "Y";
else str = "N";
strSave += str;
strSave += "\r\n";
}
}
return strSave;
}
CString CDropManager::GetItemType(eDROP_TYPE type)
{
CString str;
if( type == DROP_MONEY_1 || type == DROP_MONEY_40 || type == DROP_MONEY_400 )
return "돈";
else if( type == DROP_ITEM_0 || type == DROP_ITEM_1 || type == DROP_ITEM_2 || type == DROP_ITEM_3
|| type == DROP_ITEM_4 || type == DROP_ITEM_5 || type == DROP_ITEM_6 || type == DROP_ITEM_7
|| type == DROP_ITEM_8 || type == DROP_ITEM_9 || type == DROP_ITEM_10 )
{
return "아이템";
}
else if( type == DROP_RARE_ITEM )
return "레어아이템";
return "NONE";
}
CString CDropManager::GetItemType(eDROP_TYPE_ type)
{
CString str;
if( type == DROP_TYPE_MONEY )
return "돈";
else if( type == DROP_TYPE_ITEM )
return "아이템";
return "NONE";
}
CString CDropManager::GetEnchantLevel(eENCHANTLEVEL level)
{
CString str = "없음";
if( level == ENCHANT_LOW )
str = "하급";
else if( level == ENCHANT_MIDDLE )
str = "중급";
else if( level == ENCHANT_HIGH )
str = "고급";
return str;
}
CString CDropManager::GetRank( eRANK rank )
{
CString str = "NONE";
if( rank == RANK_F ) //레어아이템시..
str = "F";
else if( rank == RANK_E )
str = "E";
else if( rank == RANK_D )
str = "D";
else if( rank == RANK_C )
str = "C";
else if( rank == RANK_B )
str = "B";
else if( rank == RANK_MA )
str = "MA";
else if( rank == RANK_A )
str = "A";
else if( rank == RANK_PA )
str = "PA";
else if( rank == RANK_MS )
str = "MS";
else if( rank == RANK_S )
str = "S";
else if( rank == RANK_PS )
str = "PS";
return str;
}
VOID CDropManager::DropMoney( MONEY DroppedMoney, MONEY & TotalMoney )
{
TotalMoney = 0;
if( DroppedMoney >= 10000 ) //< 1만 이상의 금액일 때 잭팟
{
MONEY RemainMoney = DroppedMoney;
MONEY CurMoney = 0;
MONEY LastMoney = (MONEY)(DroppedMoney*0.06f);
// 딜레이 줘서 떨어 뜨림
INT i = 0;
while(1)
{
if( RemainMoney <= LastMoney)
break;
CurMoney = (MONEY)(DroppedMoney*random(3,5)/100);
if( RemainMoney < CurMoney )
break;
RemainMoney -= CurMoney;
if( CurMoney != 0 )
TotalMoney += CurMoney;
++i;
}
if( RemainMoney != 0 )
TotalMoney += RemainMoney;
}
else
TotalMoney = DroppedMoney;
}
void CDropManager::GetMonster( WORD wLowerLevel, WORD wUperLevel, BYTE byGrade, MONSTER_LIST& listMonster )
{
NPCINFO_ITERATOR iterBegin = NPCInfoParser::Instance()->Begin();
NPCINFO_ITERATOR iterEnd = NPCInfoParser::Instance()->End();
NPCINFO_ITERATOR iter;
for( iter = iterBegin; iter != iterEnd; ++iter )
{
BASE_NPCINFO* pInfo = *iter;
if( !pInfo || pInfo->m_byGrade >= eNPC_MERCHANT_NPC ) //데이터가 없거나, 상인 이상이면.. 무시.
continue;
if( pInfo->m_DisplayLevel >= wLowerLevel && pInfo->m_DisplayLevel <= wUperLevel && pInfo->m_byGrade == byGrade )
listMonster.push_back( pInfo );
}
}