#include "StdAfx.h" #include "gamesrv.h" #include "Protocol.h" #include "DropScript.h" #include "Drop.h" #include "Monster.h" #include "ObjectManager.h" #include "AppTimer.h" #include "Monster.h" #include "Player.h" #include "MonsterScript.h" #include "item.h" #include "TakeDamagePool.h" #include "Gathering.h" #include "logProtocol.h" #include "AIManager.h" #include "Party.h" #include "PartyManager.h" #include "ItemManager.h" #include "GridManager.h" #include "RandomTable.h" #include "SkillManager.h" #include "Twitter_Common.h" #include "TwitterScript.h" cDrop* cDrop::mpDrop = NULL; cDrop::cDrop(void) { /// ½Ì±ÛÅæ if( mpDrop ) { Verbose->WriteLog( "Drop new error"); } else { mpDrop = this; } } cDrop::~cDrop(void) { } bool cDrop::Init() { mLogWriteTime = DROP_LOG_WRITE_NORMAL; mpDropScript = new cDropScript; if( mpDropScript->Init() == false ) { assert(NULL); return false; } /// ¸ó½ºÅÍ µå¶øÁ¤º¸ Åë°è const cPHashMap* pMonsterMap = MONSTERSCRIPT->GetMonsterMap(); if( pMonsterMap != NULL ) { cPHashMap::cConstIterator i = pMonsterMap->Begin(); cPHashMap::cConstIterator e = pMonsterMap->End(); for( ; i != e ; ++i ) { unsigned long monsterIdx = (*i).mFirst; const sMonsterScript* pScript = (sMonsterScript*)(*i).mSecond; if( pScript == NULL ) continue; sDropItemLog* pLog = new sDropItemLog; pLog->mMonIdx = monsterIdx; if( mDropLogMap.Insert( monsterIdx, pLog ) == false ) { SAFE_DELETE( pLog ); } } } mQuestSeed = RANDOMTABLE->GetSeedx100(); return true; } void cDrop::Release() { unsigned long maxSize = MAX_UDP_PACKET_SIZE; if( maxSize > MAX_IO_CONTEXT_BUFFER_LEN ) maxSize = MAX_IO_CONTEXT_BUFFER_LEN ; /// ¸Þ¼¼Áö¿¡ ´ãÀ» ³»¿ëÀ» ¸Þ¼¼Áö »çÀÌÁ´Ù Å©Áö ¾Ê°Ô ¼³Á¤ unsigned long maxCnt = 0; maxCnt = ( maxSize - sizeof( DROPITEM_EVENT ) ) / sizeof(sDropItem); /// Á¾·á½ÃÁ¡À̶ó ¸Þ¸ð¸® ´ÜÆíÈ­ ºÎºÐ ¹«½Ã /// ¡Ø iocontextpoolÀÌ ÀÌ¹Ì Á¦°ÅµÇ poolÀ» ¸ø¾ò¾î¿È sDropItem* pDropItem = new sDropItem[maxCnt]; unsigned long count = 0; cPHashMap::cIterator i = mDropLogMap.Begin(); cPHashMap::cIterator e = mDropLogMap.End(); for( ; i != e ; ++i ) { unsigned long monsterIdx = (*i).mFirst; sDropItemLog* pLog = (sDropItemLog*)(*i).mSecond; if( pLog == NULL ) continue; /// Á×Àº ÀûÀÌ ¾ø´Â ¸ó½ºÅÍ Åë°ú if( pLog->mMonDieCnt == 0 ) { SAFE_DELETE( pLog ); continue; } /// ¾ÆÀÌÅÛ Á¤º¸ ¾øÀÌ ¸ó½ºÅÍ Á×Àº Á¤º¸¸¸ ±â·ÏÇÒÁö üũ bool dropItemMap = true; bool dropItemNoMap = true; /// µå¶øÇß´ø ¾ÆÀÌÅÛ Á¤º¸ ·Î±×ÆÐŶ¿¡ ±â·Ï cHashMap* pMap = &pLog->mItemMap; if( pMap != NULL ) { cHashMap::cIterator mi = pMap->Begin(); cHashMap::cIterator me = pMap->End(); for( ; mi != me ; ++mi ) { unsigned long itemIdx = (*mi).mFirst; unsigned long itemCnt = (*mi).mSecond; if( itemCnt == 0 ) continue; pDropItem[count].mMonsterIdx = monsterIdx; pDropItem[count].mDieCnt = pLog->mMonDieCnt; pDropItem[count].mMoneyCnt = pLog->mMonMoneyCnt; pDropItem[count].mItemIdx = itemIdx; pDropItem[count].mItemCnt = itemCnt; pDropItem[count].mDropType = 0; /// ¼±Á¤ÈÄ µå¶øÇÔ dropItemMap = false; ++count; if( count >= maxCnt ) break; } //SAFE_DELETE( pMap ); } else dropItemMap = false; /// ¼±Á¤Àº µÆÀ¸³ª µå¶øÇÏÁö ¾ÊÀº ¾ÆÀÌÅÛ Á¤º¸ ·Î±×ÆÐŶ¿¡ ±â·Ï cHashMap* pNoMap = &pLog->mItemNoDropMap; if( pNoMap != NULL ) { cHashMap::cIterator mi = pNoMap->Begin(); cHashMap::cIterator me = pNoMap->End(); for( ; mi != me ; ++mi ) { unsigned long itemIdx = (*mi).mFirst; unsigned long itemCnt = (*mi).mSecond; if( itemCnt == 0 ) continue; pDropItem[count].mMonsterIdx = monsterIdx; pDropItem[count].mDieCnt = pLog->mMonDieCnt; pDropItem[count].mMoneyCnt = pLog->mMonMoneyCnt; pDropItem[count].mItemIdx = itemIdx; pDropItem[count].mItemCnt = itemCnt; pDropItem[count].mDropType = 1; /// ¼±Á¤ÈÄ Á¦¾àÁ¶°Ç¿¡ °É·Á µå¶ø¾ÈÇÔ dropItemNoMap = false; ++count; if( count >= maxCnt ) break; } //SAFE_DELETE( pNoMap ); } else dropItemNoMap = false; /// ¾ÆÀÌÅÛ µå¶øÀÌ ¾ø´Â ¸ó½ºÅÍ if( dropItemMap == true && dropItemNoMap == true ) { pDropItem[count].mMonsterIdx = monsterIdx; pDropItem[count].mDieCnt = pLog->mMonDieCnt; pDropItem[count].mMoneyCnt = pLog->mMonMoneyCnt; pDropItem[count].mItemIdx = 0; pDropItem[count].mItemCnt = 0; ++count; } SAFE_DELETE( pLog ); } /// ¹öÆÛ»çÀÌÁî²Ë ä¿î °æ¿ì ·Î±× ±â·Ï if( count >= maxCnt ) { NETWORK2->PostServerEvent("cDrop::Release count[%d] >= maxCnt[%d]", count, maxCnt ); } NETWORK2->PostDropItemEvent( pDropItem, count ); SAFE_DELETE_ARRAY( pDropItem ); SAFE_RELEASE_DELETE( mpDropScript ); } void cDrop::ProcessDrop( unsigned long /*elapsedTime*/, unsigned long accumTime ) { if( mLogWriteTime > accumTime ) return; /// ´ÙÀ½ ±â·Ï ½Ã°£¼³Á¤ mLogWriteTime = accumTime + DROP_LOG_WRITE_NORMAL; PerIoContext* perIoContext = NETWORK2->GetIoContext( IOCP_REQUEST_WRITE ); sDropItem* pDropItem = (sDropItem*)perIoContext->buffer; unsigned long count = 0; cPHashMap::cIterator i = mDropLogMap.Begin(); cPHashMap::cIterator e = mDropLogMap.End(); for( ; i != e ; ++i ) { unsigned long monsterIdx = (*i).mFirst; sDropItemLog* pLog = (sDropItemLog*)(*i).mSecond; if( pLog == NULL ) continue; /// Á×Àº ÀûÀÌ ÀÖ´Â ¸ó½ºÅ͸¸ ±â·Ï if( pLog->mMonDieCnt == 0 ) continue; /// ¾ÆÀÌÅÛ Á¤º¸ ¾øÀÌ ¸ó½ºÅÍ Á×Àº Á¤º¸¸¸ ±â·ÏÇÒÁö üũ bool dropItemMap = true; bool dropItemNoMap = true; /// µå¶øÇß´ø ¾ÆÀÌÅÛ Á¤º¸ ·Î±×ÆÐŶ¿¡ ±â·Ï cHashMap* pMap = &pLog->mItemMap; if( pMap != NULL ) { /// ¾ÆÀÌÅÛ µå¶ø ³»¿ª È®ÀÎ /// ÇѸó½ºÅÍ¿¡ ÇØ´çÇÏ´Â ¾ÆÀÌÅÛ ¸ñ·ÏÀº count°¡ ÃÖ´ëÄ¡¸¦ ³Ñ¾î¼­´õ¶óµµ ´Ù ±â·ÏÇÑ´Ù. /// ¡Ø ÃÖ´ëÄ¡´Â À§Ç׸ñÀ» ¹Ý¿µÇØ ¼³Á¤ÇÑ´Ù. cHashMap::cIterator mi = pMap->Begin(); cHashMap::cIterator me = pMap->End(); for( ; mi != me ; ++ mi ) { unsigned long itemIdx = (*mi).mFirst; unsigned long itemCnt = (*mi).mSecond; if( itemCnt == 0 ) continue; pDropItem[count].mMonsterIdx = monsterIdx; pDropItem[count].mDieCnt = pLog->mMonDieCnt; pDropItem[count].mMoneyCnt = pLog->mMonMoneyCnt; pDropItem[count].mItemIdx = itemIdx; pDropItem[count].mItemCnt = itemCnt; pDropItem[count].mDropType = 0; /// ¼±Á¤ÈÄ µå¶øÇÔ dropItemMap = false; /// ¾ÆÀÌÅÛ °Ù¼ö ÃʱâÈ­ (*mi).mSecond = 0; ++count; } } else dropItemMap = false; /// ¼±Á¤Àº µÆÀ¸³ª µå¶øÇÏÁö ¾ÊÀº ¾ÆÀÌÅÛ Á¤º¸ ·Î±×ÆÐŶ¿¡ ±â·Ï cHashMap* pNoMap = &pLog->mItemNoDropMap; if( pNoMap != NULL ) { cHashMap::cIterator noI = pNoMap->Begin(); cHashMap::cIterator noE = pNoMap->End(); for( ; noI != noE ; ++ noI ) { unsigned long itemIdx = (*noI).mFirst; unsigned long itemCnt = (*noI).mSecond; if( itemCnt == 0 ) continue; pDropItem[count].mMonsterIdx = monsterIdx; pDropItem[count].mDieCnt = pLog->mMonDieCnt; pDropItem[count].mMoneyCnt = pLog->mMonMoneyCnt; pDropItem[count].mItemIdx = itemIdx; pDropItem[count].mItemCnt = itemCnt; pDropItem[count].mDropType = 1; /// ¼±Á¤ÈÄ Á¦¾àÁ¶°Ç¿¡ °É·Á µå¶ø¾ÈÇÔ dropItemNoMap = false; /// ¾ÆÀÌÅÛ °Ù¼ö ÃʱâÈ­ (*noI).mSecond = 0; ++count; } } else dropItemNoMap = false; /// ¾ÆÀÌÅÛ µå¶øÀÌ ¾ø´Â ¸ó½ºÅÍ if( dropItemMap == true && dropItemNoMap == true ) { pDropItem[count].mMonsterIdx = monsterIdx; pDropItem[count].mDieCnt = pLog->mMonDieCnt; pDropItem[count].mMoneyCnt = pLog->mMonMoneyCnt; pDropItem[count].mItemIdx = 0; pDropItem[count].mItemCnt = 0; pDropItem[count].mDropType = 0; ++count; } /// ÃʱâÈ­ pLog->mMonDieCnt = 0; pLog->mMonMoneyCnt = 0; /// if( count >= DROP_LOG_WRITE_PROCESS_CNT ) { mLogWriteTime = accumTime + DROP_LOG_WRITE_CONTINUE; break; } } if( count != 0 ) NETWORK2->PostDropItemEvent( pDropItem, count ); perIoContext->offset = sizeof( sDropItem ) * count; if( perIoContext->offset > 40000 ) { NETWORK2->PostServerEvent( "cDrop::ProcessDrop perIoContext->offset[%d] > 40000", perIoContext->offset ); } NETWORK2->ReleaseIoContext( perIoContext, "cDrop::ProcessDrop(" ); } void cDrop::MonsterDrop( unsigned long monsterIdx, unsigned long playerIdx, unsigned long partyIdx ) { cMonster* pMonster = OBJECTMANAGER->GetMonster( monsterIdx ); if( pMonster == NULL ) { assert(NULL); NETWORK2->PostServerEvent("drop monster idx error[%d]", monsterIdx ); return; } unsigned long monsterClassIdx = pMonster->GetRaceGender(); sMonsterScript* pMonsterScript = MONSTERSCRIPT->GetMonsterListInfo( monsterClassIdx ); if( pMonsterScript == NULL ) { assert(NULL); NETWORK2->PostServerEvent("drop monsterScript idx error[%d]", monsterClassIdx ); return; } sDropItemLog* pDropLog = (sDropItemLog*)mDropLogMap.GetAt( monsterClassIdx ); if( pDropLog != NULL ) { ++pDropLog->mMonDieCnt; } //Verbose->WriteLog("¸ó½ºÅÍÁ×À½"); /// µå¶ø ¸ñ·Ï Àӽðø°£ ÃʱâÈ­ mDropItemCntMap.Clear(); mDropNoItemCntMap.Clear(); cPlayer* pPlayer = OBJECTMANAGER->GetPlayer( playerIdx ); if( pPlayer == NULL ) return; sGameOption* toOption1 =pPlayer->GetOptionData(); if( toOption1->option1.autoSendTwitterMsg == true ) { DropTwitter( pMonster, playerIdx, partyIdx ); } /// Àú·¾ ¸ó½ºÅ͸¦ ÀâÀº °æ¿ì¿¡ ´ëÇÑ ÆÐ³ÎƼ º¯¼ö ¼±¾ð.. int div = 0; unsigned char level = pPlayer->GetLevel(); cParty* pParty = PARTYMAN->GetParty( partyIdx ); if( pParty ) { unsigned long cnt = pParty->GetCount(); unsigned long* userArr = pParty->GetUserArr(); for( unsigned int i=0;i= MAX_PARTYUSER ) { assert(0); break; } cPlayer* p = OBJECTMANAGER->GetPlayer( userArr[i] ); if( p == 0 ) continue; if( DropMonCheck( pMonster, p ) == false ) continue; if( level < p->GetLevel() ) level = p->GetLevel(); } } div = pMonster->GetLevel() - level; /// money, exp, sxp µå¶ø DropMonsterValue( pMonster ); /// ¾ÆÀÌÅÛ µå¶ø float penalty = 1.0f; if( div < 0) { /// script bool isTheme = NETWORK2->GetServerType() == _E_ST_ID_THEME_; penalty = DROPSCRIPT->GetDropIncrease( isTheme, (char)div ); } DropMonsterClass( monsterClassIdx, penalty ); DropMonsterLevelType( pMonster->GetLevel(), 0, penalty ); DropMonsterLevelType( pMonster->GetLevel(), pMonster->GetMonsterInfo()->mType, penalty ); if( mDropNoItemCntMap.GetSize() != 0 ) { cHashMap::cConstIterator begin = mDropNoItemCntMap.Begin(); cHashMap::cConstIterator end = mDropNoItemCntMap.End(); for( ; begin != end ; ++begin ) { sDropItemLog* pDropLog = (sDropItemLog*)mDropLogMap.GetAt( monsterClassIdx ); if( pDropLog != NULL ) { cHashMap* pMap = (cHashMap*)&pDropLog->mItemNoDropMap; if( pMap != NULL ) { unsigned long itemIdx = (*begin).mFirst; unsigned long itemCnt = (*begin).mSecond; cHashMap::cIterator find = pMap->Find( itemIdx ); cHashMap::cIterator end = pMap->End(); if( find != end ) (*find).mSecond += itemCnt; else pMap->Insert( itemIdx, itemCnt ); } } } } if( mDropItemCntMap.GetSize() == 0 ) return; unsigned long playerOwnerIdx = 0; unsigned long partyOwnerIdx[MAX_PARTYUSER] = {0,}; unsigned char partyOwnerCnt = 0; /// ¼±°øÇÑ À¯Àú ÆÄƼ À¯/¹« if( pParty == NULL ) { /// ÆÄƼ°¡ »ç¶óÁ³À¸¸é ¼±°øÀ¯Àú¿¡°Ô ¿ì¼±±ÇÀ» ÁØ´Ù. if( OBJECTMANAGER->GetPlayer( playerIdx ) != NULL ) { playerOwnerIdx = playerIdx; } } else { switch( pParty->GetDivideType() ) { case PARTY_DIVIDE_TURN: /// ¼ø¼­´ë·Î { playerOwnerIdx = pParty->GetTurnUser( pMonster->GetMapNumber(), pMonster->GetXPos(), pMonster->GetYPos() ); } break; case PARTY_DIVIDE_RANDOM: /// ·£´ý { playerOwnerIdx = pParty->GetRandomUser( pMonster->GetMapNumber(), pMonster->GetXPos(), pMonster->GetYPos() ); } break; case PARTY_DIVIDE_DAMAGE: /// µ¥¹ÌÁö { unsigned long* pUser = pParty->GetUserArr(); if( pUser == NULL ) break; unsigned int partyCnt = pParty->GetCount(); unsigned long maxDamagePlayerIdx = playerIdx; unsigned long maxDamage = 0; unsigned long tempDamage = 0; for( unsigned int i = 0; i < partyCnt; ++i ) { cPlayer* pPlayer = OBJECTMANAGER->GetPlayer( pUser[i] ); if( pPlayer ) { /// Á¶°Ç üũ if( DropMonCheck( pMonster, pPlayer ) == false ) continue; tempDamage = pMonster->GetTakeDamage( pUser[i] ); if( tempDamage > maxDamage ) { maxDamagePlayerIdx = pUser[i]; maxDamage = tempDamage; } } } playerOwnerIdx = maxDamagePlayerIdx; } break; case PARTY_DIVIDE_LEADER: playerOwnerIdx = pParty->GetLeader(); break; } unsigned long* pUser = pParty->GetUserArr(); unsigned int partyCnt = pParty->GetCount(); if( pUser != NULL ) { for( unsigned int i = 0; i < partyCnt; ++i ) { cPlayer* pPlayer = OBJECTMANAGER->GetPlayer( pUser[i] ); if( pPlayer ) { /// Á¶°Ç üũ if( DropMonCheck( pMonster, pPlayer ) == false ) continue; partyOwnerIdx[partyOwnerCnt] = pUser[i]; ++partyOwnerCnt; } } } } unsigned short applyCnt; bool isApply = false; unsigned itemIdx = ITEMMANAGER->MakeItemIdx( ); cItem* item = OBJECTMANAGER->AddItem( itemIdx, pMonster ); if ( item != NULL ) { if( playerOwnerIdx != 0 ) item->PushOwner( playerOwnerIdx ); bool partyLeader = false; if ( pParty ) { partyLeader = (pParty->GetDivideType() == PARTY_DIVIDE_LEADER) ? true : false; } for( unsigned char i = 0 ; i < partyOwnerCnt ; ++i ) item->PushParty( partyOwnerIdx[i], partyLeader ); cHashMap::cConstIterator begin = mDropItemCntMap.Begin(); cHashMap::cConstIterator end = mDropItemCntMap.End(); for( ; begin != end ; ++begin ) { applyCnt = 0; if( (*begin).mSecond == 0 ) NETWORK2->PostServerEvent("cDrop::Drop (*begin).mSecond(%d,%d) == 0", (*begin).mFirst, (*begin).mSecond ); //Verbose->WriteLog("¾ÆÀÌÅÛµå¶ø [%d,%d]", (*begin).mFirst, (*begin).mSecond); /// Åë°èÀÚ·á Ãâ·Â¿ë //printf("\n%d\t%d",(*begin).mFirst, (*begin).mSecond); cPlayer* owner = pPlayer; if( playerOwnerIdx != 0 ) { // ¼ÒÀ¯ÀÚ ±âÁØ owner = OBJECTMANAGER->GetPlayer( playerOwnerIdx ); } if( owner ) { unsigned long itemDefineIndex = (unsigned long)(*begin).mFirst; TB_ITEM_DEFINE* itemDefine = ITEMMANAGER->GetItemDefineByIndex( itemDefineIndex ); if( itemDefine && itemDefine->type == ITEM_ETC1 ) { if( itemDefine->subType == ITEM_ETC1_QUEST ) { // Äù½ºÆ® ½ÃÀÛ¾ÆÀÌÅÛ »ý¼º Á¦ÇÑ // °íÀ¯ ¹øÈ£·Î °Ë»ö TB_ITEM_ABILITY* itemAbility = ITEMMANAGER->GetItemAbility( itemDefine->idx ); if( itemAbility && itemAbility->influence_idx > 0 ) { unsigned long questIndex = itemAbility->influence_idx; if( owner->IsKeepGroupQuest( questIndex ) != -1 ) { if( owner == pPlayer ) continue; else { if( pPlayer->IsKeepGroupQuest( questIndex ) != -1) continue; } } if( owner->IsCompleteQuest( questIndex ) == true ) { if( owner == pPlayer ) continue; else { if( pPlayer->IsCompleteQuest( questIndex ) == true ) continue; } } } } else if( itemDefine->subType == ITEM_ETC1_TITLE ) { // ȣĪ »ý¼º Á¦ÇÑ if( owner->IsHaveTitle( itemDefine->titleIndex ) == true ) { if( owner == pPlayer ) continue; else { if( pPlayer->IsHaveTitle( itemDefine->titleIndex ) == true ) continue; } } } } } while( applyCnt < (*begin).mSecond ) { unsigned short cnt = item->PushItem( (*begin).mFirst, (unsigned short)(*begin).mSecond ); if( cnt == 0 ) { NETWORK2->PostServerEvent("cDrop::Drop item(%d,%d)->PushItem cnt == 0", (*begin).mFirst, (*begin).mSecond); break; } applyCnt = applyCnt + cnt; isApply = true; } sDropItemLog* pDropLog = (sDropItemLog*)mDropLogMap.GetAt( monsterClassIdx ); if( pDropLog != NULL ) { cHashMap* pMap = (cHashMap*)&pDropLog->mItemMap; if( pMap != NULL ) { unsigned long itemIdx = (*begin).mFirst; unsigned long itemCnt = (*begin).mSecond; cHashMap::cIterator find = pMap->Find( itemIdx ); cHashMap::cIterator end = pMap->End(); if( find != end ) (*find).mSecond += itemCnt; else pMap->Insert( itemIdx, itemCnt ); } } } } if( isApply == true ) { /// ¸ó½ºÅÍÀÇ ÇöÀç ÁÂÇ¥¿¡ ¶³¾îÆ®¸±¼ö ¾ø´Â °æ¿ì if( AIMANAGER->IsPossible( item->GetMapNumber(), item->GetXPos(), item->GetYPos(), item->GetObject() ) == false ) { /// ù¹øÂ° ¼ÒÀ¯ÀÚÇÑÅ× ¶³¾îÆ®¸² cPlayer* pPlayer = OBJECTMANAGER->GetPlayer( playerOwnerIdx ); if( pPlayer != NULL && AIMANAGER->IsPossible( pPlayer->GetMapNumber(), pPlayer->GetXPos(), pPlayer->GetYPos(), pPlayer->GetObject() ) == true ) { item->SetMapNumber( pPlayer->GetMapNumber() ); item->SetPos( pPlayer->GetXPos(), pPlayer->GetYPos() ); } else { for( unsigned char i = 0 ; i < partyOwnerCnt ; ++i ) { /// ÆÄƼ ¼ÒÀ¯ÀÚÁß °¡´ÉÇÑ À§Ä¡¿¡ ¶³¾îÆ®¸°´Ù. pPlayer = OBJECTMANAGER->GetPlayer( partyOwnerIdx[i] ); if( pPlayer != NULL && AIMANAGER->IsPossible( pPlayer->GetMapNumber(), pPlayer->GetXPos(), pPlayer->GetYPos(), pPlayer->GetObject() ) == true ) { item->SetMapNumber( pPlayer->GetMapNumber() ); item->SetPos( pPlayer->GetXPos(), pPlayer->GetYPos() ); break; } } } } GRIDMANAGER->AddItem( item ); } else OBJECTMANAGER->RemoveItem( itemIdx ); mDropItemCntMap.Clear(); mDropNoItemCntMap.Clear(); /// Åë°èÀÚ·á Ãâ·Â¿ë //printf("\n-----------------------------------"); } void cDrop::MonsterQuestDrop( unsigned long monsterIdx, unsigned long playerIdx, unsigned long partyIdx ) { cMonster* pMonster = OBJECTMANAGER->GetMonster( monsterIdx ); if( pMonster == NULL ) { assert(NULL); NETWORK2->PostServerEvent("QuestDrop monster idx error[%d]", monsterIdx ); return; } unsigned long monsterClassIdx = pMonster->GetRaceGender(); sMonsterScript* pMonsterScript = MONSTERSCRIPT->GetMonsterListInfo( monsterClassIdx ); if( pMonsterScript == NULL ) { assert(NULL); NETWORK2->PostServerEvent("QuestDrop monsterScript idx error[%d]", monsterClassIdx ); return; } /// ÆÄƼ À¯/¹« cParty* pParty = PARTYMAN->GetParty( partyIdx ); if( pParty == NULL ) { /// ÆÄƼ°¡ »ç¶óÁ³À¸¸é ¼±°øÇÑ Ç÷¹À̾°Ô µå¶øÀ» ÇÑ´Ù. cPlayer* pPlayer = OBJECTMANAGER->GetPlayer( playerIdx ); if( pPlayer != NULL ) DropMonQuestType( pMonster, pPlayer ); } else { unsigned long* pUser = pParty->GetUserArr(); unsigned int partyCnt = pParty->GetCount(); if( pUser != NULL ) { /// ÆÄƼ¿øº° Äù½ºÆ® µå¶ø for( unsigned int i = 0; i < partyCnt; ++i ) { cPlayer* pPlayer = OBJECTMANAGER->GetPlayer( pUser[i] ); if( pPlayer != NULL ) { /// Á¶°Ç üũ if( DropMonCheck( pMonster, pPlayer ) == false ) continue; DropMonQuestType( pMonster, pPlayer ); } } } } } void cDrop::DropTwitter( cMonster* pMonster, unsigned long playerIdx, unsigned long partyIdx ) { if( pMonster == NULL ) return; unsigned long monsterClassIdx = pMonster->GetRaceGender(); /// Æ®À§ÅÍ·Î ¹ß¼ÛÇÑ ¸ó½ºÅÍ ¸ñ·ÏÀÎÁö üũ if( TWITTERSCRIPT->IsMonsterEvnet( monsterClassIdx ) == false ) return; /// ¸ó½ºÅÍ ½ºÅ©¸³Æ® Á¤º¸ sMonsterScript* pMonsterScript = MONSTERSCRIPT->GetMonsterListInfo( monsterClassIdx ); if( pMonsterScript == NULL ) { NETWORK2->PostServerEvent("cDrop::DropTwitter pMonsterScript[%d] == NULL", monsterClassIdx ); return; } /// ¸ó½ºÅ͸¦ °ø°ÝÇÑ µ¥¹ÌÁö ¸Ê TakeDamageRoot* pTakeDamageRoot = pMonster->GetTakeDamageRoot(); if( pTakeDamageRoot == NULL ) { assert(NULL); NETWORK2->PostServerEvent("cDrop::DropTwitter pTakeDamageMap == NULL"); return; } /// ¼±°øÇÑ À¯Àú ÆÄƼ À¯/¹« cPlayer* pPlayer = NULL; cParty* pParty = PARTYMAN->GetParty( partyIdx ); if( pParty == NULL ) { /// ÆÄƼ°¡ »ç¶óÁ³À¸¸é ¼±°øÀ¯Àú¿¡°Ô¸¸ ¾Ë¸°´Ù. pPlayer = OBJECTMANAGER->GetPlayer( playerIdx ); if( pPlayer != NULL ) { HANDLE handle = NULL; MSG_SYN_TWITTER_MONSTER_DIE* sendMsg = (MSG_SYN_TWITTER_MONSTER_DIE*)NETWORK2->GetMsgRoot( &handle, pPlayer->GetConnectionIdx(), NM_TWITTER, NM_TWITTER_MONSTER_DIE_SYN ); if ( sendMsg != NULL ) { sendMsg->mMonsterIdx = monsterClassIdx; NETWORK2->SendMsgRoot( handle, sizeof(MSG_SYN_TWITTER_MONSTER_DIE) ); } return; } } else { unsigned long* pUser = pParty->GetUserArr(); if( pUser == NULL ) return; unsigned int partyCnt = pParty->GetCount(); for( unsigned int i = 0; i < partyCnt; ++i ) { cPlayer* pPlayer = OBJECTMANAGER->GetPlayer( pUser[i] ); if( pPlayer ) { /// Á¶°Ç üũ if( DropMonCheck( pMonster, pPlayer ) == false ) continue; HANDLE handle = NULL; MSG_SYN_TWITTER_MONSTER_DIE* sendMsg = (MSG_SYN_TWITTER_MONSTER_DIE*)NETWORK2->GetMsgRoot( &handle, pPlayer->GetConnectionIdx(), NM_TWITTER, NM_TWITTER_MONSTER_DIE_SYN ); if ( sendMsg != NULL ) { sendMsg->mMonsterIdx = monsterClassIdx; NETWORK2->SendMsgRoot( handle, sizeof(MSG_SYN_TWITTER_MONSTER_DIE) ); } } } } } void cDrop::DropMonsterValue( cMonster* pMonster ) { if( pMonster == NULL ) return; unsigned long monsterKind = pMonster->GetRaceGender(); /// ¸ó½ºÅÍ ½ºÅ©¸³Æ® Á¤º¸ sMonsterScript* pMonsterScript = MONSTERSCRIPT->GetMonsterListInfo( monsterKind ); if( pMonsterScript == NULL ) { NETWORK2->PostServerEvent("cDrop::DropValue pMonsterScript[%d] == NULL", monsterKind); return; } unsigned long maxMoney = 0; unsigned long minMoney = 0; int moneyDropPer = 0; /// µå¶ø money Á¤º¸ sDropMoneyScript* pMoney = mpDropScript->GetDropMonMoney( monsterKind ); if( pMoney != NULL ) { maxMoney = pMoney->mMaxMoney; minMoney = pMoney->mMinMoney; moneyDropPer = pMoney->mDropPercent; } /// ÃÖ¼Ò ÃÖ´ë ±Ý¾× ¼öġȮÀÎ long moneyGap = maxMoney - minMoney; if( moneyGap > RANDOM_MAX ) { NETWORK2->PostServerEvent("cDrop::MonsterDropValue[%d] moneyGap > RANDOM_MAX", monsterKind, moneyGap ); moneyGap = RANDOM_MAX; } /// ¸ó½ºÅ͸¦ °ø°ÝÇÑ µ¥¹ÌÁö ¸Ê TakeDamageRoot* pTakeDamageRoot = pMonster->GetTakeDamageRoot(); if( pTakeDamageRoot == NULL ) { assert(NULL); NETWORK2->PostServerEvent("cDrop::DropValue pTakeDamageMap == NULL"); return; } /// ·£´ý°ª ÃßÃâ unsigned long randValue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ); int dropMoney = 0; unsigned long dropExp = pMonsterScript->mExp; unsigned long dropSxp = pMonsterScript->mSxp; /// moneyµå¶ø üũ ¼º°ø½Ã ·£´ý±Ý¾× °áÁ¤ int droprand = ( randValue % 100 ) + 1; if( droprand <= moneyDropPer ) { randValue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ); if( moneyGap > 0 ) dropMoney = minMoney + ( randValue % moneyGap ); else dropMoney = minMoney; /// ·Î±× Á¤º¸ °»½Å sDropItemLog* pDropLog = (sDropItemLog*)mDropLogMap.GetAt( monsterKind ); if( pDropLog != NULL ) ++pDropLog->mMonMoneyCnt; } unsigned long playerIdx; /// °ø°ÝÀÚ Á¤º¸ unsigned long damage; /// °ø°ÝÀÚ°¡ÁØ µ¥¹ÌÁö float partyTotalMoney; /// °³ÀÎ/ÆÄƼ ºÐ¹è ÇÒ Àüü·® float partyTotalExp; float partyTotalSxp; unsigned long partyIdx; /// ÆÄƼ °íÀ¯¹øÈ£ unsigned long calcExp; unsigned long calcSxp; /// °ø°ÝÇÑ Ç÷¹À̾î(µ¥¹ÌÁö)Àüü ÇÕ»ê unsigned long totalDamage = 0; /// ¸ó½ºÅͰ¡ °ø°Ý¹ÞÀº Àüü µ¥¹ÌÁö °ª PerTakeDamage* per = (PerTakeDamage*)pTakeDamageRoot->pool; while( per ) { totalDamage += per->takeDamage; per = (PerTakeDamage*)per->next; } partyIdxSet.Clear(); per = (PerTakeDamage*)pTakeDamageRoot->pool; while( per ) { playerIdx = per->playerIdx; damage = per->takeDamage; /// µ¥¹ÌÁö¸¦ ÁÖÁö¾Ê´Â ÇüÅÂÀÇ µð¹öÇÁ if( damage == 0 ) { per = (PerTakeDamage*)per->next; continue; } /// Ç÷¹ÀÌ¾î °´Ã¼°¡ ¾øÀ¸¸é money¸¦ ÁÖÁö ¾ÊÀ½ cPlayer* pPlayer = OBJECTMANAGER->GetPlayer( playerIdx ); if( pPlayer == NULL ) { per = (PerTakeDamage*)per->next; continue; } /// µ¥¹ÌÁö ºñÀ²·Î °³ÀÎ/ÆÄƼ(Àüü) ¿¡°Ô µ¹¾Æ°¥ money °è»ê partyTotalMoney = (float)(dropMoney * damage / totalDamage); /// Áõ°¨Ä¡ °è»êÀ» ÇϱâÀü ¼ø¼ö °æÇèÄ¡ partyTotalExp = (float)(dropExp * damage / totalDamage); partyTotalSxp = (float)(dropSxp * damage / totalDamage); bool IsParty = false; /// ÆÄƼÁ¤º¸¸¦ Àоî¿È cParty* pParty = NULL; partyIdx = pPlayer->GetPartyIndex(); if( partyIdx != 0 ) { pParty = PARTYMAN->GetParty( partyIdx ); if( pParty != NULL ) IsParty = true; } /// ÆÄƼ°¡ ¾Æ´Ñ °æ¿ì if( IsParty == false ) { if( pPlayer->GetStateDie() == true ) { per = (PerTakeDamage*)per->next; continue; } /// °ø°Ý µ¥¹ÌÁö°¡ 1% ¹Ì¸¸Àΰæ¿ì º¸»ó ¾øÀ½ if( pMonster->GetMaxHP() * (float)0.01 > damage ) { per = (PerTakeDamage*)per->next; continue; } /// µå¶ø Á¶°ÇÀÌ Å¸´çÇÑÁö üũ if( DropMonCheck( pMonster, pPlayer ) == false ) { per = (PerTakeDamage*)per->next; continue; } calcExp = FloatToInt( MonsterDropExpIncrease( partyTotalExp, pPlayer->GetLevel(), pMonsterScript->mLevel ) ); calcSxp = FloatToInt( MonsterDropExpIncrease( partyTotalSxp, pPlayer->GetLevel(), pMonsterScript->mLevel ) ); ///------ µå¶ø Åë°èÀÚ·á Ãâ·Â½Ã ÁÖ¼® pPlayer->AddExp( calcExp, true, false ); pPlayer->AddSxp( calcSxp, true ); if( partyTotalMoney >= 1.0f ) { float addMoneyPer = pPlayer->GetStatusEtc()->mMoneyAddPer; if( addMoneyPer < 0.0f ) { NETWORK2->PostServerEvent("cDrop::DropMonsterValue addMoneyPer < 0.0f[%f]", partyTotalMoney ); pPlayer->AddMoney( pMonster->GetObject(), FloatToInt(partyTotalMoney) ); } else { unsigned long addMoney = (unsigned long)(partyTotalMoney + ( partyTotalMoney * addMoneyPer / 100.0f )); pPlayer->AddMoney( pMonster->GetObject(), addMoney ); } } ///--------------------------------- } else { /// ÆÄƼ Àΰæ¿ì ÆÄƼ󸮿ë Set¿¡ ±â·ÏÇÑ ÈÄ Ã³¸® /// ¡Ø ÇÑÆÄÆ¼ ¿©·¯¸íÀÌ Ä£°æ¿ì insert ½Ãµµ´Â ¿©·¯ ¹ø ÀÖÀ» ¼ö ÀÖÁö¸¸ 1°³¸¸ µé¾î°¨ partyIdxSet.Insert( partyIdx ); /// ÆÄƼ °´Ã¼¿¡ µå¶ø °ª ´©Àû ÀÔ·Â if( pParty != NULL ) pParty->AddDropValue( pMonster->GetMaxHP(), damage, partyTotalMoney, partyTotalExp, partyTotalSxp ); } per = (PerTakeDamage*)per->next; } cHashSet::cIterator setIter = partyIdxSet.Begin(); cHashSet::cIterator setIterEnd = partyIdxSet.End(); /// µû·Î ó¸® ÇÒ ÆÄƼ °æÇèÄ¡ ºÐ¹è ó¸® while( setIter != setIterEnd ) { partyIdx = (*setIter++); cParty* pParty = PARTYMAN->GetParty( partyIdx ); if( pParty != NULL ) pParty->DivideDropValue( pMonster->GetObjectID(), pMonsterScript->mLevel ); /// ÆÄƼ¿ø¿¡°Ô money, exp, sxp¸¦ ºÐ¹è } } void cDrop::DropMonsterClass( unsigned long monsterIdx, float penalty ) { /// µå¶ø ½ºÅ©¸³Æ®¿¡¼­ ¸ó½ºÅÍ Á¾·ù¿¡ ÇØ´çÇÏ´Â µå¶øÁ¤º¸ ÀÐ¾î ¿È cAry* pAry = DROPSCRIPT->GetDropMonClass( monsterIdx ); if( pAry == NULL ) return; for( unsigned long i = 0 ; i < pAry->GetSize() ; ++i ) { sDropClassScript* pClass = (sDropClassScript*)(*pAry)[i]; if( pClass == NULL ) { NETWORK2->PostServerEvent("cDrop::DropMonsterClass pClass[%d] == NULL", monsterIdx ); continue; } unsigned long dropCnt = 1; unsigned long dropAddRate = pClass->mAddDrop1Rate + pClass->mAddDrop2Rate; unsigned long classIdx = pClass->mClassIdx; /// µå¶ø ¹Ýº¹ Ƚ¼ö °áÁ¤ if( dropAddRate != 0 ) { /// ·£´ý°ª ÃßÃâ unsigned long randValue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ) % 1000000 + 1; if( randValue <= pClass->mAddDrop1Rate ) dropCnt += pClass->mAddDrop1Cnt; else if( randValue <= dropAddRate ) dropCnt += pClass->mAddDrop2Cnt; } /// °°Àº ¾ÆÀÌÅÛ¸ñ·Ï ±×·ì¿¡ Áߺ¹À¸·Î ¶³¾îÁö´ÂÁö üũÇÏ´Âset ÃʱâÈ­ mTempSelectItemSet.Clear(); /// ¼±ÅÃµÈ µå¶ø Ƚ¼ö¸¸Å­ ¹Ýº¹ for( unsigned char j = 0 ; j < dropCnt ; ++j ) { /// ·£´ý°ª ÃßÃâ unsigned long randValue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ) % 1000000 + 1; /// ¾ÆÀÌÅÛ ±×·ìÁß Çϳª¸¦ ¼±Åà cAry* pItemAry = (cAry*)&pClass->mItemGroup; if( pItemAry == NULL ) continue; unsigned long rateSum = 0; for( unsigned long i = 0 ; i < pItemAry->GetSize() ; ++i ) { sDropItemGroupScript* pItemGroup = (sDropItemGroupScript*)(*pItemAry)[i]; if( pItemGroup == NULL ) { NETWORK2->PostServerEvent("cDrop::DropMonsterClass pItemGroup[%d] == NULL", classIdx ); continue; } rateSum += pItemGroup->mItemGroupRate; if( rateSum < randValue ) continue; sDropItemListScript* pItemList = DROPSCRIPT->GetDropMonItem( pItemGroup->mItemGroupIdx ); if( pItemList == NULL ) { NETWORK2->PostServerEvent("cDrop::DropMonsterClass pItemList[%d,%d] == NULL", classIdx, pItemGroup->mItemGroupIdx ); continue; } ++mDropCnt; /// ¼±ÅÃµÈ ±×·ìÀÇ ¾ÆÀÌÅÛ¸ñ·ÏÀ» µå¶ø DropMonItemSelect( pItemList, penalty ); break; } } } } void cDrop::DropMonsterLevelType( unsigned char level, unsigned char type, float penalty ) { /// µå¶ø ½ºÅ©¸³Æ®¿¡¼­ ¸ó½ºÅÍ Á¾·ù¿¡ ÇØ´çÇÏ´Â µå¶øÁ¤º¸ ÀÐ¾î ¿È cAry* pAry = DROPSCRIPT->GetDropMonLevelType( level, type ); if( pAry == NULL ) return; for( unsigned long i1 = 0 ; i1 < pAry->GetSize() ; ++i1 ) { sDropLevelTypeScript* pLevelType = (sDropLevelTypeScript*)(*pAry)[i1]; if( pLevelType == NULL ) { NETWORK2->PostServerEvent("cDrop::DropMonsterLevelType pLevelType[%d,%d] == NULL", level, type ); continue; } if( pLevelType->mServerTypeCheck == eDROPSERVERTYPE_FIELD && NETWORK2->GetServerType() != _E_ST_NORMAL_MAP_ ) continue; else if( pLevelType->mServerTypeCheck == eDROPSERVERTYPE_INDUN && NETWORK2->GetServerType() == _E_ST_NORMAL_MAP_ ) continue; unsigned long dropCnt = 1; unsigned long dropAddRate = pLevelType->mAddDrop1Rate + pLevelType->mAddDrop2Rate; /// È®·ü ÅäÅ»°ª ¿À·ù if( dropAddRate > RANDOM_MAX ) { NETWORK2->PostServerEvent("cDrop::DropMonsterLevelType dropAddRate[%d,%d,%d] > RANDOM_MAX", level, type, dropAddRate ); dropAddRate = RANDOM_MAX; } /// µå¶ø ¹Ýº¹ Ƚ¼ö °áÁ¤ if( dropAddRate != 0 ) { /// ·£´ý°ª ÃßÃâ unsigned long randValue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ) % 1000000 + 1; if( randValue <= pLevelType->mAddDrop1Rate ) dropCnt += pLevelType->mAddDrop1Cnt; else if( randValue <= dropAddRate ) dropCnt += pLevelType->mAddDrop2Cnt; } /// °°Àº ¾ÆÀÌÅÛ¸ñ·Ï ±×·ì¿¡ Áߺ¹À¸·Î ¶³¾îÁö´ÂÁö üũÇÏ´Âset ÃʱâÈ­ mTempSelectItemSet.Clear(); /// µå¶ø ¹Ýº¹ for( unsigned char i2 = 0 ; i2 < dropCnt ; ++i2 ) { /// ·£´ý°ª ÃßÃâ unsigned long randValue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ) % 1000000 + 1; cAry* pItemAry = (cAry*)&pLevelType->mItemGroup; if( pItemAry == NULL ) continue; unsigned long rateSum = 0; for( unsigned long i3 = 0 ; i3 < pItemAry->GetSize() ; ++i3 ) { sDropItemGroupScript* pItemGroup = (sDropItemGroupScript*)(*pItemAry)[i3]; if( pItemGroup == NULL ) { NETWORK2->PostServerEvent("cDrop::DropMonsterLevelType pItemGroup[%d,%d] == NULL", level, type ); continue; } rateSum += pItemGroup->mItemGroupRate; if( rateSum < randValue ) continue; sDropItemListScript* pItemList = DROPSCRIPT->GetDropMonItem( pItemGroup->mItemGroupIdx ); if( pItemList == NULL ) { NETWORK2->PostServerEvent("cDrop::DropMonsterLevelType pItemList[%d,%d,%d] == NULL", level, type, pItemGroup->mItemGroupIdx ); continue; } DropMonItemSelect( pItemList, penalty ); break; } } } } void cDrop::DropMonItemSelect( sDropItemListScript* pDropItemList, float penalty ) { if( pDropItemList == NULL ) { NETWORK2->PostServerEvent( "cDrop::DropItemSelect pDropItemList == NULL" ); return; } cAry* pItemAry = (cAry*)&pDropItemList->mItem; if( pItemAry == NULL ) { NETWORK2->PostServerEvent("cDrop::DropMonsterClass pItemAry[%d] == NULL", pDropItemList->mItemGroupIdx ); return; } //unsigned char Data[4]; //Data[0]=(unsigned char)(rand()%256); //Data[1]=(unsigned char)(rand()%256); //Data[2]=(unsigned char)(rand()%256); //Data[3]=(unsigned char)(rand()%256); //unsigned long *dwRandData=(unsigned long*)Data; //randValue = ((*dwRandData)%1000000); /// ·£´ý°ª ÃßÃâ cHashMap::cIterator f = mItemGroupRandSeed.Find( pDropItemList->mItemGroupIdx ); cHashMap::cIterator e = mItemGroupRandSeed.End(); unsigned long randValue = 0; if( f != e ) randValue = (unsigned long)( RANDOMTABLE->Get( (*f).mSecond ) * 1000000 ) + 1; else { NETWORK2->PostServerEvent("cDrop::DropMonItemSelect f == e [%d]", pDropItemList->mItemGroupIdx ); randValue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ) + 1; } unsigned long rateSum = 0; for( unsigned long i = 0 ; i < pItemAry->GetSize() ; ++i ) { sDropItemScript* pItem = (sDropItemScript*)(*pItemAry)[i]; if( pItem == NULL ) { NETWORK2->PostServerEvent("cDrop::DropMonsterClass pItem[%d] == NULL", pDropItemList->mItemGroupIdx ); continue; } rateSum += (unsigned long)(pItem->mItemRate * penalty); if( rateSum < randValue ) continue; if( pItem->mItemIdx == 0 ) { /// ½ºÅ©¸³Æ® ¿À·ù NETWORK2->PostServerEvent("cDrop::DropMonItemSelect pItem->mItemIdx == 0"); continue; } if( pItem->mItemCount == 0 ) { NETWORK2->PostServerEvent("cDrop::DropMonsterClass pItem->mItemCount[%d,%d,%d] == 0", pDropItemList->mItemGroupIdx, pItem->mItemIdx, pItem->mItemCount ); return; } /// ÀÌ¹Ì Çѹø ¼±Åõƴø ¾ÆÀÌÅÛÀÌ´Ù if( mTempSelectItemSet.GetCount( pItem ) != 0 ) { if( mDropNoItemCntMap.Insert( pItem->mItemIdx, pItem->mItemCount ) == false ) { /// ÀÔ·ÂÀ» Çߴµ¥ ÀÌ¹Ì ÀÖ´Â ¾ÆÀÌÅÛÀÌ¸é °ªÀ» + ½ÃŲ´Ù cHashMap::cIterator find = mDropNoItemCntMap.Find( pItem->mItemIdx ); if( find != mDropNoItemCntMap.End() ) (*find).mSecond += pItem->mItemCount; } //Verbose->WriteLog("À̹̼±ÅÃ"); return; } cPHashMap::cIterator find = mDropMonCantTime.Find( pItem->mItemIdx ); if( find != mDropMonCantTime.End() ) { sDropLimit* pDropLimit = (sDropLimit*)(*find).mSecond; if( pDropLimit != NULL ) { /// µå¶ø½Ã°£ ±¸°£ÀÌ ÇöÀç¿Í ¸Â´ÂÁö üũ if( TIMER->DiffRealTime( pDropLimit->mEndTime ) > 0 ) { /// ÇöÀç ½Ã°£°ú ±¸°£ÀÌ ¸Â´Â °æ¿ì µå¶ø À¯¹« ÆÇ´Ü if( pDropLimit->mIsDrop == true ) { /// ÀÌ¹Ì µå¶ø ÇѰæ¿ìÀÓ - µå¶ø ¾ÈÇÔ if( mDropNoItemCntMap.Insert( pItem->mItemIdx, pItem->mItemCount ) == false ) { /// ÀÔ·ÂÀ» Çߴµ¥ ÀÌ¹Ì ÀÖ´Â ¾ÆÀÌÅÛÀÌ¸é °ªÀ» + ½ÃŲ´Ù cHashMap::cIterator find = mDropNoItemCntMap.Find( pItem->mItemIdx ); if( find != mDropNoItemCntMap.End() ) (*find).mSecond += pItem->mItemCount; // Verbose->WriteLog("½Ã°£ Á¦¾à"); } return; } else { /// Á¤»ó±¸°£¿¡ µå¶øµÇÁö ¾ÊÀº °æ¿ìÀ̹ǷΠµå¶ø½ÃŰ°í µå¶øÇßÀ½ Ç÷¡±×¸¸ Ų´Ù pDropLimit->mIsDrop = true; /// ³×Æ®¿öÅ© ¹ß¼Û NETWORK2->PostItemDropLimitUpdate( pDropLimit->mItemIdx, pDropLimit->mEndTime ); /// DB±â·Ï HANDLE handle = NULL; ITEM_DROPLIMIT_UPDATE* pUpdate = (ITEM_DROPLIMIT_UPDATE*)NETWORK2->GetSQL( &handle, SQL_GAME_PROCESS_ITEM_DROPLIMIT_UPDATE ); if( pUpdate != NULL ) { pUpdate->mItemIdx = pDropLimit->mItemIdx; pUpdate->mEndTime = pDropLimit->mEndTime; NETWORK2->SendSQL( handle, sizeof(ITEM_DROPLIMIT_UPDATE) ); } } } else { /// ÇöÀç ½Ã°£±¸°£ÀÌ ¾È¸ÂÀ¸¹Ç·Î ÀÌÀü µå¶ø ½Ã°£±â°£Áö³ª¼­ óÀ½À¸·Î ¶³¾îÁö´Â °æ¿ìÀÓ /// ½Ã°£ ¼³Á¤À» ÇöÀ縦 ±âÁØÀ¸·Î ½Ã°£ ¼³Á¤ÇÏ°í µå¶ø Ç÷¡±×¸¦ Ų´Ù TIMESTAMP_STRUCT nextTime = pDropLimit->mEndTime; unsigned long errorCheck = 0; while( TIMER->DiffRealTime( nextTime ) <= 0 ) { struct tm tmNextTime = TIMER->ConvertTStoTM( nextTime ); time_t result; tmNextTime.tm_sec = tmNextTime.tm_sec + ( pDropLimit->mDropTerm / 1000 ); if( (result = mktime( &tmNextTime )) != (time_t)-1 ) { //datetime = *localtime( &result ); errno_t err = localtime_s( &tmNextTime , &result ); if( err != 0 ) NETWORK2->PostServerEvent("cDrop::DropMonItemSelect errno_t err[%d]", err ); } nextTime.year = (SQLSMALLINT)tmNextTime.tm_year+1900; nextTime.month = (SQLSMALLINT)tmNextTime.tm_mon+1; nextTime.day = (SQLSMALLINT)tmNextTime.tm_mday; nextTime.hour = (SQLSMALLINT)tmNextTime.tm_hour; nextTime.minute = (SQLSMALLINT)tmNextTime.tm_min; nextTime.second = (SQLSMALLINT)tmNextTime.tm_sec; nextTime.fraction = 0; /// ¹Ýº¹¹®ÀÌ ³Ê¹« ¸¹ÀÌ µµ´Â °æ¿ì¿¡ ´ëºñ(¹ö±×üũ) ++errorCheck; if( errorCheck > 500 ) { pDropLimit->mEndTime = nextTime; NETWORK2->PostServerEvent("cDrop::DropMonItemSelect errorCheck > 500" ); return; } } pDropLimit->mIsDrop = true; pDropLimit->mEndTime = nextTime; /// ³×Æ®¿öÅ© ¹ß¼Û NETWORK2->PostItemDropLimitUpdate( pDropLimit->mItemIdx, pDropLimit->mEndTime ); ///db¿¡ ¿äû HANDLE handle = NULL; ITEM_DROPLIMIT_UPDATE* pUpdate = (ITEM_DROPLIMIT_UPDATE*)NETWORK2->GetSQL( &handle, SQL_GAME_PROCESS_ITEM_DROPLIMIT_UPDATE ); if( pUpdate != NULL ) { pUpdate->mItemIdx = pDropLimit->mItemIdx; pUpdate->mEndTime = pDropLimit->mEndTime; NETWORK2->SendSQL( handle, sizeof(ITEM_DROPLIMIT_UPDATE) ); } } } } mTempSelectItemSet.Insert( pItem ); if( pItem->mItemCount == 0 ) NETWORK2->PostServerEvent("cDrop::DropMonItemSelect itemIdx[%d], itemCnt[%d]", pItem->mItemIdx, pItem->mItemCount ); /// µå¶ø ¸ñ·Ï¿¡ µî·Ï if( mDropItemCntMap.Insert( pItem->mItemIdx, pItem->mItemCount ) == false ) { /// ÀÔ·ÂÀ» Çߴµ¥ ÀÌ¹Ì ÀÖ´Â ¾ÆÀÌÅÛÀÌ¸é °ªÀ» + ½ÃŲ´Ù cHashMap::cIterator find = mDropItemCntMap.Find( pItem->mItemIdx ); if( find == mDropItemCntMap.End() ) { NETWORK2->PostServerEvent("cDrop::DropMonsterClass find[%d,%d,%d] == mDropItemCntMap.End()", pDropItemList->mItemGroupIdx, pItem->mItemIdx, pItem->mItemCount ); return; } (*find).mSecond += pItem->mItemCount; if( (*find).mSecond == 0 ) NETWORK2->PostServerEvent("cDrop::DropMonItemSelect itemIdx[%d], itemCnt[%d]", pItem->mItemIdx, (*find).mSecond ); } return; } } void cDrop::DropMonQuestType( cMonster* pMonster, cPlayer* pPlayer ) { if( pMonster == NULL ) return; if( pPlayer == NULL ) return; unsigned long monsterClassIdx = pMonster->GetRaceGender(); /// Äù½ºÆ® Àüü °Ë»ç for( unsigned long i = 0 ; i < MAX_KEEPQUEST ; ++i ) { /// Äù½ºÆ® Á¤º¸ ·Îµå TB_QUEST_PROGRESS* pQuest = pPlayer->GetQuest( i ); if( pQuest == NULL ) break; if( pQuest->idx == 0 ) return; cQuestDefine* questDefine = QUESTMAN->GetQuestDefine( pQuest->questIdx ); if( !questDefine ) { assert(NULL); NETWORK2->PostServerEvent("DropQType questDefine[%d] == NULL", pQuest->questIdx ); return; } /// Äù½ºÆ® ÁøÇà Áß Ã¼Å© if( pQuest->check == questDefine->mComplete ) continue; /// ¸ó½ºÅͰ¡ Ç÷¹À̾îÀÇ Äù½ºÆ®¿¡ ÇØ´çÇÏ´Â µå¶ø¾ÆÀÌÅÛ Á¾·ù¸¦ Àоî¿È cAry* pAry = DROPSCRIPT->GetDropMonQuest( monsterClassIdx, pQuest->questIdx ); if( pAry == NULL ) continue; /// µå¶ø ¾ÆÀÌÅÛ ºñ±³ for( unsigned long itemI = 0 ; itemI < pAry->GetSize() ; ++itemI ) { sDropQType* pDropQ = (sDropQType*)(*pAry)[itemI]; if( pDropQ == NULL ) { assert(NULL); NETWORK2->PostServerEvent("DropQType pDropQ == NULL [%d]", itemI ); continue; } /// µå¶ø È®·ü ºñ±³ //double randvalue = RANDOMTABLE->Get( mQuestSeed ); /*unsigned long selectRand = ( randvalue * 100 ) + 1;*/ //unsigned long selectRand = ( rand() % 100 ) + 1; double randvalue = RANDOMTABLE->Getx100( mQuestSeed ) + 1; double dropPer = (double)pDropQ->mDropPer; if( randvalue > dropPer ) continue; /// µå¶ø ÇÊ¿ä ¼ö·® È®ÀÎ unsigned long dropNeedCnt = pPlayer->GetDropItemCount( i, pDropQ->mItemIdx ); if( dropNeedCnt == 0 ) continue; /// Äù½ºÆ® Á¦ÇÑ °Ë»ç - Âø¿ëÁ¤º¸ °Ë»ç if( pPlayer->IsEquipQuestItem( pQuest->questIdx ) == false ) continue; /// ÁøÇà½Ã ÇÊ¿äÇÑ Á¶°Ç ¸¸Á·ÇÏ´ÂÁö °Ë»ç if( TRIGGERMAN->CheckDuty( pPlayer->GetObjectID(), pPlayer->GetObjectID(), pQuest->questIdx ) == false ) continue; /// Ç÷¹À̾î ÀÚµ¿ ½Àµæ if( pPlayer->ItemGetQuest( pDropQ->mItemIdx, 1 ) == true ) { /// Äù½ºÆ® ¾ÆÀÌÅÛ ¼öÁý °ü·Ã ¾÷µ¥ÀÌÆ® pPlayer->UpdateDutyItem(); } else { assert(NULL); NETWORK2->PostServerEvent("Drop::DropQType ItemGetQuest[%d] ERROR", pDropQ->mItemIdx ); } } } } float cDrop::MonsterDropExpIncrease( float takeExp, unsigned char playerLevel, unsigned char monsterLevel ) { char levelDifferent; float increase; float exp = 0.0f; /// ·¹º§Â÷¿¡ µû¸¥ Áõ°¨Ä¡¸¦ ¾ò¾î¿È levelDifferent = monsterLevel - playerLevel; bool isTheme = NETWORK2->GetServerType() == _E_ST_ID_THEME_; increase = DROPSCRIPT->GetDropExpIncrease( isTheme, levelDifferent ); /// °æÇèÄ¡ * Áõ°¡Ä¡ exp = takeExp * increase; if( exp < 0.0f ) { assert(NULL); NETWORK2->PostServerEvent("cDrop::DropExpIncrease exp < 0.0f"); return 0.0f; } return exp; } bool cDrop::DropMonCheck( cMonster* pMonster, cPlayer* pPlayer ) { if( pMonster == NULL ) return false; if( pPlayer == NULL ) return false; if( pMonster->GetMapNumber() != pPlayer->GetMapNumber() ) return false; NiPoint2 monsterPos = pMonster->GetPos(); NiPoint2 playerPos = pPlayer->GetPos(); cRangeCheck rangeCheck( PARTY_RANGE ); if( rangeCheck.IsRange( monsterPos, playerPos ) == false ) return false; return true; } void cDrop::GatherDrop( cGathering* pGathering, unsigned long playerIdx ) { if( pGathering == NULL ) return; cPlayer* pPlayer = OBJECTMANAGER->GetPlayer( playerIdx ); if( pPlayer == NULL ) return; /// µå¶ø ¸ñ·Ï Àӽðø°£ ÃʱâÈ­ mDropItemCntMap.Clear(); ///// money µå¶ø DropGatherValue( pGathering, playerIdx ); /// Äù½ºÆ®µå¶ø DropGatherQuest( pGathering, playerIdx ); /// Á¾·ùº°(ÀϹÝ) µå¶ø DropGatherClass( pGathering, playerIdx ); /// È¿°ú Ãß°¡ if( pGathering->GetInfluence() !=0 ) SKILLMANAGER->AddInfluence( pPlayer->GetObject(), pPlayer->GetObject(), pGathering->GetInfluence(), 0, true ); if( mDropItemCntMap.GetSize() == 0 ) return; /// µå¶ø ¾ÆÀÌÅÛ Ã³¸® cHashMap::cConstIterator begin = mDropItemCntMap.Begin(); cHashMap::cConstIterator end = mDropItemCntMap.End(); bool apply = false; for( ; begin != end ; ++begin ) { unsigned long itemIdx = (*begin).mFirst; unsigned long itemCnt = (*begin).mSecond; unsigned short applyCnt = 0; while( applyCnt < itemCnt ) { unsigned short cnt = pPlayer->ItemGetAutoPush( itemIdx, (unsigned short)itemCnt ); if( cnt == 0 ) { assert(0); NETWORK2->PostServerEvent("cDrop::GatherDrop item(%d,%d)->ItemGetAutoPush cnt == 0", itemIdx, itemCnt); break; } applyCnt = applyCnt + cnt; apply = true; } } pPlayer->ItemGetAutoEnd( apply ); mDropItemCntMap.Clear(); } void cDrop::InsertItemGroupRandSeed( unsigned long itemGroup, unsigned long randSeed ) { if( mItemGroupRandSeed.Insert( itemGroup, randSeed ) == false ) { NETWORK2->PostServerEvent("cDrop::InsertItemGroupRandSeed Insert Duplicate[%d,%d]", itemGroup, randSeed ); } } void cDrop::DropGatherValue( cGathering* pGathering, unsigned long playerIdx ) { if( pGathering == NULL ) return; /// Ç÷¹ÀÌ¾î °´Ã¼°¡ ¾øÀ¸¸é money¸¦ ÁÖÁö ¾ÊÀ½ cPlayer* pPlayer = OBJECTMANAGER->GetPlayer( playerIdx ); if( pPlayer == NULL || pPlayer->GetStateDie() == true ) return; unsigned long classIdx = pGathering->GetClassIdx(); sDropMoneyScript* pMoney = mpDropScript->GetDropGatherMoney( classIdx ); if( pMoney == NULL ) return; unsigned long maxMoney = pMoney->mMaxMoney; unsigned long minMoney = pMoney->mMinMoney; /// ÃÖ¼Ò ÃÖ´ë ±Ý¾× ¼öġȮÀÎ long moneyGap = maxMoney - minMoney; if( moneyGap > RANDOM_MAX ) { NETWORK2->PostServerEvent("cDrop::GatherDropValue moneyGap[%d,%d] > RANDOM_MAX", classIdx, moneyGap ); moneyGap = RANDOM_MAX; } /// moneyµå¶ø üũ unsigned long randValue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ); unsigned long droprand = ( randValue % 100 ) + 1; if( droprand > pMoney->mDropPercent ) return; /// ·£´ý±Ý¾× °áÁ¤ randValue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ); int dropMoney = 0; if( moneyGap > 0 ) dropMoney = minMoney + ( randValue % moneyGap ); else dropMoney = minMoney; pPlayer->AddMoney( pGathering->GetObject(), dropMoney ); } void cDrop::DropGatherClass( cGathering* pGathering, unsigned long playerIdx ) { if( pGathering == NULL ) return; /// Ç÷¹ÀÌ¾î °´Ã¼°¡ ¾øÀ¸¸é money¸¦ ÁÖÁö ¾ÊÀ½ cPlayer* pPlayer = OBJECTMANAGER->GetPlayer( playerIdx ); if( pPlayer == NULL || pPlayer->GetStateDie() == true ) return; unsigned long classIdx = pGathering->GetClassIdx(); cAry* pAry = DROPSCRIPT->GetDropGatherClass( classIdx ); if( pAry == NULL ) return; for( unsigned long i = 0 ; i < pAry->GetSize() ; ++i ) { sDropClassScript* pClass = (sDropClassScript*)(*pAry)[i]; if( pClass == NULL ) { NETWORK2->PostServerEvent("cDrop::DropGatherClass pClass[%d] == NULL", classIdx ); continue; } unsigned long dropCnt = 1; unsigned long dropAddRate = pClass->mAddDrop1Rate + pClass->mAddDrop2Rate; unsigned long classIdx = pClass->mClassIdx; /// µå¶ø ¹Ýº¹ Ƚ¼ö °áÁ¤ if( dropAddRate != 0 ) { /// ·£´ý°ª ÃßÃâ unsigned long randValue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ); unsigned long selectRand = ( randValue % dropAddRate ) + 1; if( selectRand <= pClass->mAddDrop1Rate ) dropCnt += pClass->mAddDrop1Cnt; else if( selectRand < dropAddRate ) dropCnt += pClass->mAddDrop2Cnt; } /// °°Àº ¾ÆÀÌÅÛ¸ñ·Ï ±×·ì¿¡ Áߺ¹À¸·Î ¶³¾îÁö´ÂÁö üũÇÏ´Âset ÃʱâÈ­ mTempSelectItemSet.Clear(); /// ¼±ÅÃµÈ µå¶ø Ƚ¼ö¸¸Å­ ¹Ýº¹ for( unsigned char j = 0 ; j < dropCnt ; ++j ) { /// ·£´ý°ª ÃßÃâ unsigned long randValue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ) % 1000000 + 1; /// ¾ÆÀÌÅÛ ±×·ìÁß Çϳª¸¦ ¼±Åà cAry* pItemAry = (cAry*)&pClass->mItemGroup; if( pItemAry == NULL ) continue; unsigned long rateSum = 0; for( unsigned long i = 0 ; i < pItemAry->GetSize() ; ++i ) { sDropItemGroupScript* pItemGroup = (sDropItemGroupScript*)(*pItemAry)[i]; if( pItemGroup == NULL ) { NETWORK2->PostServerEvent("cDrop::DropGatherClass pItemGroup[%d] == NULL", classIdx ); continue; } rateSum += pItemGroup->mItemGroupRate; if( rateSum < randValue ) continue; sDropItemListScript* pItemList = DROPSCRIPT->GetDropGatherItem( pItemGroup->mItemGroupIdx ); if( pItemList == NULL ) { NETWORK2->PostServerEvent("cDrop::DropGatherClass pItemList[%d,%d] == NULL", classIdx, pItemGroup->mItemGroupIdx ); continue; } /// ¼±ÅÃµÈ ±×·ìÀÇ ¾ÆÀÌÅÛ¸ñ·ÏÀ» µå¶ø DropGatherItemSelect( pItemList ); break; } } } } void cDrop::DropGatherQuest( cGathering* pGathering, unsigned long playerIdx ) { if( pGathering == NULL ) return; unsigned long gatherClassIdx = pGathering->GetClassIdx(); cPlayer* pPlayer = OBJECTMANAGER->GetPlayer( playerIdx ); if( pPlayer == NULL ) return; /// Äù½ºÆ® Àüü °Ë»ç for( unsigned long i = 0 ; i < MAX_KEEPQUEST ; ++i ) { /// Äù½ºÆ® Á¤º¸ ·Îµå TB_QUEST_PROGRESS* pQuest = pPlayer->GetQuest( i ); if( pQuest == NULL ) break; if( pQuest->idx == 0 ) return; cQuestDefine* questDefine = QUESTMAN->GetQuestDefine( pQuest->questIdx ); if( !questDefine ) { assert(NULL); NETWORK2->PostServerEvent("GatherDropQType questDefine[%d] == NULL", pQuest->questIdx ); return; } /// Äù½ºÆ® ÁøÇà Áß Ã¼Å© if( pQuest->check == questDefine->mComplete ) continue; /// ¸ó½ºÅͰ¡ Ç÷¹À̾îÀÇ Äù½ºÆ®¿¡ ÇØ´çÇÏ´Â µå¶ø¾ÆÀÌÅÛ Á¾·ù¸¦ Àоî¿È cAry* pAry = DROPSCRIPT->GetDropGatherQuest( gatherClassIdx, pQuest->questIdx ); if( pAry == NULL ) continue; /// µå¶ø ¾ÆÀÌÅÛ ºñ±³ for( unsigned long itemI = 0 ; itemI < pAry->GetSize() ; ++itemI ) { sDropQType* pDropQ = (sDropQTypeGather*)(*pAry)[itemI]; if( pDropQ == NULL ) { assert(NULL); NETWORK2->PostServerEvent("GatherDropQType pDropQ == NULL [%d]", itemI ); continue; } /// µå¶ø È®·ü ºñ±³ unsigned long randvalue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ); unsigned long selectRand = ( randvalue % 100 ) + 1; if( selectRand > pDropQ->mDropPer ) continue; /// µå¶ø ÇÊ¿ä ¼ö·® È®ÀÎ unsigned long dropNeedCnt = pPlayer->GetDropItemCount( i, pDropQ->mItemIdx ); if( dropNeedCnt == 0 ) continue; /// Äù½ºÆ® Á¦ÇÑ °Ë»ç - Âø¿ëÁ¤º¸ °Ë»ç if( pPlayer->IsEquipQuestItem( pQuest->questIdx ) == false ) continue; /// ÁøÇà½Ã ÇÊ¿äÇÑ Á¶°Ç ¸¸Á·ÇÏ´ÂÁö °Ë»ç if( TRIGGERMAN->CheckDuty( pPlayer->GetObjectID(), pPlayer->GetObjectID(), pQuest->questIdx ) == false ) continue; /// Ç÷¹À̾î ÀÚµ¿ ½Àµæ if( pPlayer->ItemGetQuest( pDropQ->mItemIdx, 1 ) == true ) { /// Äù½ºÆ® ¾ÆÀÌÅÛ ¼öÁý °ü·Ã ¾÷µ¥ÀÌÆ® pPlayer->UpdateDutyItem(); } else { assert(NULL); NETWORK2->PostServerEvent("Drop::GatherDropQType ItemGetQuest[%d] ERROR", pDropQ->mItemIdx ); } } } } void cDrop::DropGatherItemSelect( sDropItemListScript* pDropItemList ) { if( pDropItemList == NULL ) { NETWORK2->PostServerEvent( "cDrop::DropGatherItemSelect pDropItemList == NULL" ); return; } cAry* pItemAry = (cAry*)&pDropItemList->mItem; if( pItemAry == NULL ) { NETWORK2->PostServerEvent("cDrop::DropGatherItemSelect pItemAry[%d] == NULL", pDropItemList->mItemGroupIdx ); return; } /// ·£´ý°ª ÃßÃâ unsigned long randValue = (unsigned long)( RANDOMTABLE->Get( ) * 1000000 ) % 1000000 + 1; unsigned long rateSum = 0; for( unsigned long i = 0 ; i < pItemAry->GetSize() ; ++i ) { sDropItemScript* pItem = (sDropItemScript*)(*pItemAry)[i]; if( pItem == NULL ) { NETWORK2->PostServerEvent("cDrop::DropGatherItemSelect pItem[%d] == NULL", pDropItemList->mItemGroupIdx ); continue; } rateSum += pItem->mItemRate; if( rateSum < randValue ) continue; /// ¼±Åà ¾ÈµÉÈ®·ü if( pItem->mItemIdx == 0 ) return; if( pItem->mItemCount == 0 ) { NETWORK2->PostServerEvent("cDrop::DropGatherItemSelect pItem->mItemCount[%d,%d,%d] == 0", pDropItemList->mItemGroupIdx, pItem->mItemIdx, pItem->mItemCount ); return; } /// ÀÌ¹Ì Çѹø ¼±Åõƴø ¾ÆÀÌÅÛÀÌ´Ù if( mTempSelectItemSet.GetCount( pItem ) != 0 ) return; unsigned long cantTime = 0; cHashMap::cIterator find = mDropGatherCantTime.Find( pItem->mItemIdx ); if( find != mDropItemCntMap.End() ) { if( (*find).mSecond > NETWORK2->GetAccumTime() ) return; cantTime = DROPSCRIPT->GetDropGatherCantTime( pItem->mItemIdx ); cantTime += NETWORK2->GetAccumTime(); (*find).mSecond = cantTime; } mTempSelectItemSet.Insert( pItem ); /// µå¶ø ¸ñ·Ï¿¡ µî·Ï if( mDropItemCntMap.Insert( pItem->mItemIdx, pItem->mItemCount ) == false ) { /// ÀÔ·ÂÀ» Çߴµ¥ ÀÌ¹Ì ÀÖ´Â ¾ÆÀÌÅÛÀÌ¸é °ªÀ» + ½ÃŲ´Ù cHashMap::cIterator find = mDropItemCntMap.Find( pItem->mItemIdx ); if( find == mDropItemCntMap.End() ) { NETWORK2->PostServerEvent("cDrop::DropGatherItemSelect find[%d,%d,%d] == mDropItemCntMap.End()", pDropItemList->mItemGroupIdx, pItem->mItemIdx, pItem->mItemCount ); return; } (*find).mSecond += pItem->mItemCount; } return; } }