1
0
forked from metin2/server
server/game/src/item_manager.cpp

1778 lines
43 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stdafx.h"
#include "utils.h"
#include "config.h"
#include "char.h"
#include "char_manager.h"
#include "desc_client.h"
#include "db.h"
#include "log.h"
#include "skill.h"
#include "text_file_loader.h"
#include "priv_manager.h"
#include "questmanager.h"
#include "unique_item.h"
#include "safebox.h"
#include "blend_item.h"
#include "dev_log.h"
#include "locale_service.h"
#include "item.h"
#include "item_manager.h"
#include <common/VnumHelper.h>
#include "DragonSoul.h"
#include "cube.h"
ITEM_MANAGER::ITEM_MANAGER()
: m_iTopOfTable(0), m_dwVIDCount(0), m_dwCurrentID(0)
{
m_ItemIDRange.dwMin = m_ItemIDRange.dwMax = m_ItemIDRange.dwUsableItemIDMin = 0;
m_ItemIDSpareRange.dwMin = m_ItemIDSpareRange.dwMax = m_ItemIDSpareRange.dwUsableItemIDMin = 0;
}
ITEM_MANAGER::~ITEM_MANAGER()
{
Destroy();
}
void ITEM_MANAGER::Destroy()
{
itertype(m_VIDMap) it = m_VIDMap.begin();
for ( ; it != m_VIDMap.end(); ++it) {
#ifdef M2_USE_POOL
pool_.Destroy(it->second);
#else
M2_DELETE(it->second);
#endif
}
m_VIDMap.clear();
}
void ITEM_MANAGER::GracefulShutdown()
{
std::unordered_set<LPITEM>::iterator it = m_set_pkItemForDelayedSave.begin();
while (it != m_set_pkItemForDelayedSave.end())
SaveSingleItem(*(it++));
m_set_pkItemForDelayedSave.clear();
}
bool ITEM_MANAGER::Initialize(TItemTable * table, int size)
{
if (!m_vec_prototype.empty())
m_vec_prototype.clear();
int i;
m_vec_prototype.resize(size);
memcpy(&m_vec_prototype[0], table, sizeof(TItemTable) * size);
for (int i = 0; i < size; i++)
{
if (0 != m_vec_prototype[i].dwVnumRange)
{
m_vec_item_vnum_range_info.push_back( &m_vec_prototype[i]);
}
}
m_map_ItemRefineFrom.clear();
for (i = 0; i < size; ++i)
{
if (m_vec_prototype[i].dwRefinedVnum)
m_map_ItemRefineFrom.insert(std::make_pair(m_vec_prototype[i].dwRefinedVnum, m_vec_prototype[i].dwVnum));
// NOTE : QUEST_GIVE Ç÷¡±×´Â npc À̺¥Æ®·Î ¹ß»ý.
if (m_vec_prototype[i].bType == ITEM_QUEST || IS_SET(m_vec_prototype[i].dwFlags, ITEM_FLAG_QUEST_USE | ITEM_FLAG_QUEST_USE_MULTIPLE))
quest::CQuestManager::instance().RegisterNPCVnum(m_vec_prototype[i].dwVnum);
m_map_vid.insert( std::map<DWORD,TItemTable>::value_type( m_vec_prototype[i].dwVnum, m_vec_prototype[i] ) );
if ( test_server )
sys_log( 0, "ITEM_INFO %d %s ", m_vec_prototype[i].dwVnum, m_vec_prototype[i].szName );
}
int len = 0, len2;
char buf[512];
for (i = 0; i < size; ++i)
{
len2 = snprintf(buf + len, sizeof(buf) - len, "%5u %-16s", m_vec_prototype[i].dwVnum, m_vec_prototype[i].szLocaleName);
if (len2 < 0 || len2 >= (int) sizeof(buf) - len)
len += (sizeof(buf) - len) - 1;
else
len += len2;
if (!((i + 1) % 4))
{
if ( !test_server )
sys_log(0, "%s", buf);
len = 0;
}
else
{
buf[len++] = '\t';
buf[len] = '\0';
}
}
if ((i + 1) % 4)
{
if ( !test_server )
sys_log(0, "%s", buf);
}
ITEM_VID_MAP::iterator it = m_VIDMap.begin();
sys_log (1, "ITEM_VID_MAP %d", m_VIDMap.size() );
while (it != m_VIDMap.end())
{
LPITEM item = it->second;
++it;
const TItemTable* tableInfo = GetTable(item->GetOriginalVnum());
if (NULL == tableInfo)
{
sys_err("cannot reset item table");
item->SetProto(NULL);
}
item->SetProto(tableInfo);
}
return true;
}
LPITEM ITEM_MANAGER::CreateItem(DWORD vnum, DWORD count, DWORD id, bool bTryMagic, int iRarePct, bool bSkipSave)
{
if (0 == vnum)
return NULL;
DWORD dwMaskVnum = 0;
if (GetMaskVnum(vnum))
{
dwMaskVnum = GetMaskVnum(vnum);
}
if (LC_IsKorea() || LC_IsYMIR())
{
if (vnum == 50300 && bTryMagic)
{
// ¼ö·Ã¼­¸¦ ¾ÆÀÌÅÛ ¹øÈ£¸¦ ´Ù¸£°Ô ¸¸µé¾î ÁØ´Ù.
DWORD dwSkillVnum;
do
{
dwSkillVnum = number(1, 111);
CSkillProto * pkSk = CSkillManager::instance().Get(dwSkillVnum);
if (!pkSk)
continue;
break;
} while (1);
vnum = 50400 + dwSkillVnum;
}
}
const TItemTable* table = GetTable(vnum);
if (NULL == table)
return NULL;
LPITEM item = NULL;
//id·Î °Ë»çÇؼ­ Á¸ÀçÇÑ´Ù¸é -- ¸®ÅÏ!
if (m_map_pkItemByID.find(id) != m_map_pkItemByID.end())
{
item = m_map_pkItemByID[id];
LPCHARACTER owner = item->GetOwner();
sys_err("ITEM_ID_DUP: %u %s owner %p", id, item->GetName(), get_pointer(owner));
return NULL;
}
//¾ÆÀÌÅÛ Çϳª ÇÒ´çÇÏ°í
#ifdef M2_USE_POOL
item = pool_.Construct();
#else
item = M2_NEW CItem(vnum);
#endif
bool bIsNewItem = (0 == id);
//ÃʱâÈ­ ÇÏ°í. Å×ÀÌºí ¼ÂÇÏ°í
item->Initialize();
item->SetProto(table);
item->SetMaskVnum(dwMaskVnum);
if (item->GetType() == ITEM_ELK) // µ·Àº ID°¡ ÇÊ¿ä¾ø°í ÀúÀåµµ ÇÊ¿ä¾ø´Ù.
item->SetSkipSave(true);
// Unique ID¸¦ ¼¼ÆÃÇÏÀÚ
else if (!bIsNewItem)
{
item->SetID(id);
item->SetSkipSave(true);
}
else
{
item->SetID(GetNewID());
if (item->GetType() == ITEM_UNIQUE) // À¯´ÏÅ© ¾ÆÀÌÅÛÀº »ý¼º½Ã¿¡ ¼ÒÄÏ¿¡ ³²Àº½Ã°£À» ±â·ÏÇÑ´Ù.
{
if (item->GetValue(2) == 0)
item->SetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME, item->GetValue(0)); // °ÔÀÓ ½Ã°£ À¯´ÏÅ©
else
{
//int globalTime = get_global_time();
//int lastTime = item->GetValue(0);
//int endTime = get_global_time() + item->GetValue(0);
item->SetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME, get_global_time() + item->GetValue(0)); // ½Ç½Ã°£ À¯´ÏÅ©
}
}
}
switch (item->GetVnum())
{
case ITEM_AUTO_HP_RECOVERY_S:
case ITEM_AUTO_HP_RECOVERY_M:
case ITEM_AUTO_HP_RECOVERY_L:
case ITEM_AUTO_HP_RECOVERY_X:
case ITEM_AUTO_SP_RECOVERY_S:
case ITEM_AUTO_SP_RECOVERY_M:
case ITEM_AUTO_SP_RECOVERY_L:
case ITEM_AUTO_SP_RECOVERY_X:
case REWARD_BOX_ITEM_AUTO_SP_RECOVERY_XS:
case REWARD_BOX_ITEM_AUTO_SP_RECOVERY_S:
case REWARD_BOX_ITEM_AUTO_HP_RECOVERY_XS:
case REWARD_BOX_ITEM_AUTO_HP_RECOVERY_S:
case FUCKING_BRAZIL_ITEM_AUTO_SP_RECOVERY_S:
case FUCKING_BRAZIL_ITEM_AUTO_HP_RECOVERY_S:
if (bIsNewItem)
item->SetSocket(2, item->GetValue(0), true);
else
item->SetSocket(2, item->GetValue(0), false);
break;
}
if (item->GetType() == ITEM_ELK) // µ·Àº ¾Æ¹« 󸮰¡ ÇÊ¿äÇÏÁö ¾ÊÀ½
;
else if (item->IsStackable()) // ÇÕÄ¥ ¼ö ÀÖ´Â ¾ÆÀÌÅÛÀÇ °æ¿ì
{
count = MINMAX(1, count, ITEM_MAX_COUNT);
if (bTryMagic && count <= 1 && IS_SET(item->GetFlag(), ITEM_FLAG_MAKECOUNT))
count = item->GetValue(1);
}
else
count = 1;
item->SetVID(++m_dwVIDCount);
if (bSkipSave == false)
m_VIDMap.insert(ITEM_VID_MAP::value_type(item->GetVID(), item));
if (item->GetID() != 0 && bSkipSave == false)
m_map_pkItemByID.insert(std::map<DWORD, LPITEM>::value_type(item->GetID(), item));
if (!item->SetCount(count))
return NULL;
item->SetSkipSave(false);
if (item->GetType() == ITEM_UNIQUE && item->GetValue(2) != 0)
item->StartUniqueExpireEvent();
for (int i=0 ; i < ITEM_LIMIT_MAX_NUM ; i++)
{
// ¾ÆÀÌÅÛ »ý¼º ½ÃÁ¡ºÎÅÍ »ç¿ëÇÏÁö ¾Ê¾Æµµ ½Ã°£ÀÌ Â÷°¨µÇ´Â ¹æ½Ä
if (LIMIT_REAL_TIME == item->GetLimitType(i))
{
if (item->GetLimitValue(i))
{
item->SetSocket(0, time(0) + item->GetLimitValue(i));
}
else
{
item->SetSocket(0, time(0) + 60*60*24*7);
}
item->StartRealTimeExpireEvent();
}
// ±âÁ¸ À¯´ÏÅ© ¾ÆÀÌÅÛó·³ Âø¿ë½Ã¿¡¸¸ »ç¿ë°¡´É ½Ã°£ÀÌ Â÷°¨µÇ´Â ¹æ½Ä
else if (LIMIT_TIMER_BASED_ON_WEAR == item->GetLimitType(i))
{
// ÀÌ¹Ì Âø¿ëÁßÀÎ ¾ÆÀÌÅÛÀ̸é ŸÀ̸Ӹ¦ ½ÃÀÛÇÏ°í, »õ·Î ¸¸µå´Â ¾ÆÀÌÅÛÀº »ç¿ë °¡´É ½Ã°£À» ¼¼ÆÃÇØÁØ´Ù. (
// ¾ÆÀÌÅÛ¸ô·Î Áö±ÞÇÏ´Â °æ¿ì¿¡´Â ÀÌ ·ÎÁ÷¿¡ µé¾î¿À±â Àü¿¡ Socket0 °ªÀÌ ¼¼ÆÃÀÌ µÇ¾î ÀÖ¾î¾ß ÇÑ´Ù.
if (true == item->IsEquipped())
{
item->StartTimerBasedOnWearExpireEvent();
}
else if(0 == id)
{
int duration = item->GetSocket(0);
if (0 == duration)
duration = item->GetLimitValue(i);
if (0 == duration)
duration = 60 * 60 * 10; // Á¤º¸°¡ ¾Æ¹«°Íµµ ¾øÀ¸¸é µðÆúÆ®·Î 10½Ã°£ ¼¼ÆÃ
item->SetSocket(0, duration);
}
}
}
if (id == 0) // »õ·Î ¸¸µå´Â ¾ÆÀÌÅÛÀÏ ¶§¸¸ ó¸®
{
// »õ·ÎÃß°¡µÇ´Â ¾àÃʵéÀÏ°æ¿ì ¼º´ÉÀ» ´Ù¸£°Ôó¸®
if (ITEM_BLEND==item->GetType())
{
if (Blend_Item_find(item->GetVnum()))
{
Blend_Item_set_value(item);
return item;
}
}
if (table->sAddonType)
{
item->ApplyAddon(table->sAddonType);
}
if (bTryMagic)
{
if (iRarePct == -1)
iRarePct = table->bAlterToMagicItemPct;
if (number(1, 100) <= iRarePct)
item->AlterToMagicItem();
}
if (table->bGainSocketPct)
item->AlterToSocketItem(table->bGainSocketPct);
// 50300 == ±â¼ú ¼ö·Ã¼­
if (vnum == 50300 || vnum == ITEM_SKILLFORGET_VNUM)
{
DWORD dwSkillVnum;
do
{
dwSkillVnum = number(1, 111);
if (NULL != CSkillManager::instance().Get(dwSkillVnum))
break;
} while (true);
item->SetSocket(0, dwSkillVnum);
}
else if (ITEM_SKILLFORGET2_VNUM == vnum)
{
DWORD dwSkillVnum;
do
{
dwSkillVnum = number(112, 119);
if (NULL != CSkillManager::instance().Get(dwSkillVnum))
break;
} while (true);
item->SetSocket(0, dwSkillVnum);
}
}
if (item->GetType() == ITEM_QUEST)
{
for (itertype (m_map_pkQuestItemGroup) it = m_map_pkQuestItemGroup.begin(); it != m_map_pkQuestItemGroup.end(); it++)
{
if (it->second->m_bType == CSpecialItemGroup::QUEST && it->second->Contains(vnum))
{
item->SetSIGVnum(it->first);
}
}
}
else if (item->GetType() == ITEM_UNIQUE)
{
for (itertype (m_map_pkSpecialItemGroup) it = m_map_pkSpecialItemGroup.begin(); it != m_map_pkSpecialItemGroup.end(); it++)
{
if (it->second->m_bType == CSpecialItemGroup::SPECIAL && it->second->Contains(vnum))
{
item->SetSIGVnum(it->first);
}
}
}
// »õ·Î »ý¼ºµÇ´Â ¿ëÈ¥¼® ó¸®.
if (item->IsDragonSoul() && 0 == id)
{
DSManager::instance().DragonSoulItemInitialize(item);
}
return item;
}
void ITEM_MANAGER::DelayedSave(LPITEM item)
{
if (item->GetID() != 0)
m_set_pkItemForDelayedSave.insert(item);
}
void ITEM_MANAGER::FlushDelayedSave(LPITEM item)
{
std::unordered_set<LPITEM>::iterator it = m_set_pkItemForDelayedSave.find(item);
if (it == m_set_pkItemForDelayedSave.end())
{
return;
}
m_set_pkItemForDelayedSave.erase(it);
SaveSingleItem(item);
}
void ITEM_MANAGER::SaveSingleItem(LPITEM item)
{
if (!item->GetOwner())
{
DWORD dwID = item->GetID();
DWORD dwOwnerID = item->GetLastOwnerPID();
db_clientdesc->DBPacketHeader(HEADER_GD_ITEM_DESTROY, 0, sizeof(DWORD) + sizeof(DWORD));
db_clientdesc->Packet(&dwID, sizeof(DWORD));
db_clientdesc->Packet(&dwOwnerID, sizeof(DWORD));
sys_log(1, "ITEM_DELETE %s:%u", item->GetName(), dwID);
return;
}
sys_log(1, "ITEM_SAVE %s:%d in %s window %d", item->GetName(), item->GetID(), item->GetOwner()->GetName(), item->GetWindow());
TPlayerItem t;
t.id = item->GetID();
t.window = item->GetWindow();
t.pos = t.window == EQUIPMENT ? item->GetCell() - INVENTORY_MAX_NUM : item->GetCell();
t.count = item->GetCount();
t.vnum = item->GetOriginalVnum();
t.owner = (t.window == SAFEBOX || t.window == MALL) ? item->GetOwner()->GetDesc()->GetAccountTable().id : item->GetOwner()->GetPlayerID();
memcpy(t.alSockets, item->GetSockets(), sizeof(t.alSockets));
memcpy(t.aAttr, item->GetAttributes(), sizeof(t.aAttr));
db_clientdesc->DBPacketHeader(HEADER_GD_ITEM_SAVE, 0, sizeof(TPlayerItem));
db_clientdesc->Packet(&t, sizeof(TPlayerItem));
}
void ITEM_MANAGER::Update()
{
std::unordered_set<LPITEM>::iterator it = m_set_pkItemForDelayedSave.begin();
std::unordered_set<LPITEM>::iterator this_it;
while (it != m_set_pkItemForDelayedSave.end())
{
this_it = it++;
LPITEM item = *this_it;
// SLOW_QUERY Ç÷¡±×°¡ ÀÖ´Â °ÍÀº Á¾·á½Ã¿¡¸¸ ÀúÀåÇÑ´Ù.
if (item->GetOwner() && IS_SET(item->GetFlag(), ITEM_FLAG_SLOW_QUERY))
continue;
SaveSingleItem(item);
m_set_pkItemForDelayedSave.erase(this_it);
}
}
void ITEM_MANAGER::RemoveItem(LPITEM item, const char * c_pszReason)
{
LPCHARACTER o;
if ((o = item->GetOwner()))
{
char szHint[64];
snprintf(szHint, sizeof(szHint), "%s %u ", item->GetName(), item->GetCount());
LogManager::instance().ItemLog(o, item, c_pszReason ? c_pszReason : "REMOVE", szHint);
// SAFEBOX_TIME_LIMIT_ITEM_BUG_FIX
if (item->GetWindow() == MALL || item->GetWindow() == SAFEBOX)
{
// 20050613.ipkn.½Ã°£Á¦ ¾ÆÀÌÅÛÀÌ »óÁ¡¿¡ ÀÖÀ» °æ¿ì ½Ã°£¸¸·á½Ã ¼­¹ö°¡ ´Ù¿îµÈ´Ù.
CSafebox* pSafebox = item->GetWindow() == MALL ? o->GetMall() : o->GetSafebox();
if (pSafebox)
{
pSafebox->Remove(item->GetCell());
}
}
// END_OF_SAFEBOX_TIME_LIMIT_ITEM_BUG_FIX
else
{
o->SyncQuickslot(QUICKSLOT_TYPE_ITEM, item->GetCell(), 255);
item->RemoveFromCharacter();
}
}
M2_DESTROY_ITEM(item);
}
#ifndef DEBUG_ALLOC
void ITEM_MANAGER::DestroyItem(LPITEM item)
#else
void ITEM_MANAGER::DestroyItem(LPITEM item, const char* file, size_t line)
#endif
{
if (item->GetSectree())
item->RemoveFromGround();
if (item->GetOwner())
{
if (CHARACTER_MANAGER::instance().Find(item->GetOwner()->GetPlayerID()) != NULL)
{
sys_err("DestroyItem: GetOwner %s %s!!", item->GetName(), item->GetOwner()->GetName());
item->RemoveFromCharacter();
}
else
{
sys_err ("WTH! Invalid item owner. owner pointer : %p", item->GetOwner());
}
}
std::unordered_set<LPITEM>::iterator it = m_set_pkItemForDelayedSave.find(item);
if (it != m_set_pkItemForDelayedSave.end())
m_set_pkItemForDelayedSave.erase(it);
DWORD dwID = item->GetID();
sys_log(2, "ITEM_DESTROY %s:%u", item->GetName(), dwID);
if (!item->GetSkipSave() && dwID)
{
DWORD dwOwnerID = item->GetLastOwnerPID();
db_clientdesc->DBPacketHeader(HEADER_GD_ITEM_DESTROY, 0, sizeof(DWORD) + sizeof(DWORD));
db_clientdesc->Packet(&dwID, sizeof(DWORD));
db_clientdesc->Packet(&dwOwnerID, sizeof(DWORD));
}
else
{
sys_log(2, "ITEM_DESTROY_SKIP %s:%u (skip=%d)", item->GetName(), dwID, item->GetSkipSave());
}
if (dwID)
m_map_pkItemByID.erase(dwID);
m_VIDMap.erase(item->GetVID());
#ifdef M2_USE_POOL
pool_.Destroy(item);
#else
#ifndef DEBUG_ALLOC
M2_DELETE(item);
#else
M2_DELETE_EX(item, file, line);
#endif
#endif
}
LPITEM ITEM_MANAGER::Find(DWORD id)
{
itertype(m_map_pkItemByID) it = m_map_pkItemByID.find(id);
if (it == m_map_pkItemByID.end())
return NULL;
return it->second;
}
LPITEM ITEM_MANAGER::FindByVID(DWORD vid)
{
ITEM_VID_MAP::iterator it = m_VIDMap.find(vid);
if (it == m_VIDMap.end())
return NULL;
return (it->second);
}
TItemTable * ITEM_MANAGER::GetTable(DWORD vnum)
{
int rnum = RealNumber(vnum);
if (rnum < 0)
{
for (int i = 0; i < m_vec_item_vnum_range_info.size(); i++)
{
TItemTable* p = m_vec_item_vnum_range_info[i];
if ((p->dwVnum < vnum) &&
vnum < (p->dwVnum + p->dwVnumRange))
{
return p;
}
}
return NULL;
}
return &m_vec_prototype[rnum];
}
int ITEM_MANAGER::RealNumber(DWORD vnum)
{
int bot, top, mid;
bot = 0;
top = m_vec_prototype.size();
TItemTable * pTable = &m_vec_prototype[0];
while (1)
{
mid = (bot + top) >> 1;
if ((pTable + mid)->dwVnum == vnum)
return (mid);
if (bot >= top)
return (-1);
if ((pTable + mid)->dwVnum > vnum)
top = mid - 1;
else
bot = mid + 1;
}
}
bool ITEM_MANAGER::GetVnum(const char * c_pszName, DWORD & r_dwVnum)
{
int len = strlen(c_pszName);
TItemTable * pTable = &m_vec_prototype[0];
for (DWORD i = 0; i < m_vec_prototype.size(); ++i, ++pTable)
{
if (!strncasecmp(c_pszName, pTable->szLocaleName, len))
{
r_dwVnum = pTable->dwVnum;
return true;
}
}
return false;
}
bool ITEM_MANAGER::GetVnumByOriginalName(const char * c_pszName, DWORD & r_dwVnum)
{
int len = strlen(c_pszName);
TItemTable * pTable = &m_vec_prototype[0];
for (DWORD i = 0; i < m_vec_prototype.size(); ++i, ++pTable)
{
if (!strncasecmp(c_pszName, pTable->szName, len))
{
r_dwVnum = pTable->dwVnum;
return true;
}
}
return false;
}
std::set<DWORD> g_set_lotto;
void load_lotto()
{
static int bLoaded = false;
if (bLoaded)
return;
bLoaded = true;
FILE * fp = fopen("lotto.txt", "r");
if (!fp)
return;
char buf[256];
while (fgets(buf, 256, fp))
{
char * psz = strchr(buf, '\n');
if (NULL != psz)
*psz = '\0';
DWORD dw = 0;
str_to_number(dw, buf);
g_set_lotto.insert(dw);
}
fclose(fp);
}
DWORD lotto()
{
load_lotto();
char szBuf[6 + 1];
do
{
for (int i = 0; i < 6; ++i)
szBuf[i] = 48 + number(1, 9);
szBuf[6] = '\0';
DWORD dw = 0;
str_to_number(dw, szBuf);
if (g_set_lotto.end() == g_set_lotto.find(dw))
{
FILE * fp = fopen("lotto.txt", "a+");
if (fp)
{
fprintf(fp, "%u\n", dw);
fclose(fp);
}
return dw;
}
}
while (1);
}
class CItemDropInfo
{
public:
CItemDropInfo(int iLevelStart, int iLevelEnd, int iPercent, DWORD dwVnum) :
m_iLevelStart(iLevelStart), m_iLevelEnd(iLevelEnd), m_iPercent(iPercent), m_dwVnum(dwVnum)
{
}
int m_iLevelStart;
int m_iLevelEnd;
int m_iPercent; // 1 ~ 1000
DWORD m_dwVnum;
friend bool operator < (const CItemDropInfo & l, const CItemDropInfo & r)
{
return l.m_iLevelEnd < r.m_iLevelEnd;
}
};
extern std::vector<CItemDropInfo> g_vec_pkCommonDropItem[MOB_RANK_MAX_NUM];
// 20050503.ipkn.
// iMinimum º¸´Ù ÀÛÀ¸¸é iDefault ¼¼Æà (´Ü, iMinimumÀº 0º¸´Ù Ä¿¾ßÇÔ)
// 1, 0 ½ÄÀ¸·Î ON/OFF µÇ´Â ¹æ½ÄÀ» Áö¿øÇϱâ À§ÇØ Á¸Àç
int GetDropPerKillPct(int iMinimum, int iDefault, int iDeltaPercent, const char * c_pszFlag)
{
int iVal = 0;
if ((iVal = quest::CQuestManager::instance().GetEventFlag(c_pszFlag)))
{
if (!test_server && !LC_IsJapan())
{
if (iVal < iMinimum)
iVal = iDefault;
if (iVal < 0)
iVal = iDefault;
}
}
if (iVal == 0)
return 0;
// ±âº» ¼¼ÆÃÀ϶§ (iDeltaPercent=100)
// 40000 iVal ¸¶¸®´ç Çϳª ´À³¦À» ÁÖ±â À§ÇÑ »ó¼öÀÓ
return (40000 * iDeltaPercent / iVal);
}
bool ITEM_MANAGER::GetDropPct(LPCHARACTER pkChr, LPCHARACTER pkKiller, OUT int& iDeltaPercent, OUT int& iRandRange)
{
if (NULL == pkChr || NULL == pkKiller)
return false;
int iLevel = pkKiller->GetLevel();
iDeltaPercent = 100;
if (!pkChr->IsStone() && pkChr->GetMobRank() >= MOB_RANK_BOSS)
iDeltaPercent = PERCENT_LVDELTA_BOSS(pkKiller->GetLevel(), pkChr->GetLevel());
else
iDeltaPercent = PERCENT_LVDELTA(pkKiller->GetLevel(), pkChr->GetLevel());
BYTE bRank = pkChr->GetMobRank();
if (1 == number(1, 50000))
iDeltaPercent += 1000;
else if (1 == number(1, 10000))
iDeltaPercent += 500;
sys_log(3, "CreateDropItem for level: %d rank: %u pct: %d", iLevel, bRank, iDeltaPercent);
iDeltaPercent = iDeltaPercent * CHARACTER_MANAGER::instance().GetMobItemRate(pkKiller) / 100;
//if (pkKiller->GetPoint(POINT_MALL_ITEMBONUS) > 0)
//iDeltaPercent += iDeltaPercent * pkKiller->GetPoint(POINT_MALL_ITEMBONUS) / 100;
// ADD_PREMIUM
if (pkKiller->GetPremiumRemainSeconds(PREMIUM_ITEM) > 0 ||
pkKiller->IsEquipUniqueGroup(UNIQUE_GROUP_DOUBLE_ITEM))
iDeltaPercent += iDeltaPercent;
// END_OF_ADD_PREMIUM
// PC_BANG_ITEM_ADD
if (pkKiller->GetPoint(POINT_PC_BANG_DROP_BONUS) > 0)
{
if (pkKiller->IsPCBang() == true)
iDeltaPercent += iDeltaPercent * pkKiller->GetPoint(POINT_PC_BANG_DROP_BONUS)/100;
}
// END_PC_BANG_ITEM_ADD
iRandRange = 4000000;
iRandRange = iRandRange * 100 /
(100 +
CPrivManager::instance().GetPriv(pkKiller, PRIV_ITEM_DROP) +
pkKiller->IsEquipUniqueItem(UNIQUE_ITEM_DOUBLE_ITEM)?100:0);
if (distribution_test_server) iRandRange /= 3;
return true;
}
bool ITEM_MANAGER::CreateDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::vector<LPITEM> & vec_item)
{
int iLevel = pkKiller->GetLevel();
int iDeltaPercent, iRandRange;
if (!GetDropPct(pkChr, pkKiller, iDeltaPercent, iRandRange))
return false;
BYTE bRank = pkChr->GetMobRank();
LPITEM item = NULL;
// Common Drop Items
std::vector<CItemDropInfo>::iterator it = g_vec_pkCommonDropItem[bRank].begin();
while (it != g_vec_pkCommonDropItem[bRank].end())
{
const CItemDropInfo & c_rInfo = *(it++);
if (iLevel < c_rInfo.m_iLevelStart || iLevel > c_rInfo.m_iLevelEnd)
continue;
int iPercent = (c_rInfo.m_iPercent * iDeltaPercent) / 100;
sys_log(3, "CreateDropItem %d ~ %d %d(%d)", c_rInfo.m_iLevelStart, c_rInfo.m_iLevelEnd, c_rInfo.m_dwVnum, iPercent, c_rInfo.m_iPercent);
if (iPercent >= number(1, iRandRange))
{
TItemTable * table = GetTable(c_rInfo.m_dwVnum);
if (!table)
continue;
item = NULL;
if (table->bType == ITEM_POLYMORPH)
{
if (c_rInfo.m_dwVnum == pkChr->GetPolymorphItemVnum())
{
item = CreateItem(c_rInfo.m_dwVnum, 1, 0, true);
if (item)
item->SetSocket(0, pkChr->GetRaceNum());
}
}
else
item = CreateItem(c_rInfo.m_dwVnum, 1, 0, true);
if (item) vec_item.push_back(item);
}
}
// Drop Item Group
{
itertype(m_map_pkDropItemGroup) it;
it = m_map_pkDropItemGroup.find(pkChr->GetRaceNum());
if (it != m_map_pkDropItemGroup.end())
{
typeof(it->second->GetVector()) v = it->second->GetVector();
for (DWORD i = 0; i < v.size(); ++i)
{
int iPercent = (v[i].dwPct * iDeltaPercent) / 100;
if (iPercent >= number(1, iRandRange))
{
item = CreateItem(v[i].dwVnum, v[i].iCount, 0, true);
if (item)
{
if (item->GetType() == ITEM_POLYMORPH)
{
if (item->GetVnum() == pkChr->GetPolymorphItemVnum())
{
item->SetSocket(0, pkChr->GetRaceNum());
}
}
vec_item.push_back(item);
}
}
}
}
}
// MobDropItem Group
{
itertype(m_map_pkMobItemGroup) it;
it = m_map_pkMobItemGroup.find(pkChr->GetRaceNum());
if ( it != m_map_pkMobItemGroup.end() )
{
CMobItemGroup* pGroup = it->second;
// MOB_DROP_ITEM_BUG_FIX
// 20050805.myevan.MobDropItem ¿¡ ¾ÆÀÌÅÛÀÌ ¾øÀ» °æ¿ì CMobItemGroup::GetOne() Á¢±Ù½Ã ¹®Á¦ ¹ß»ý ¼öÁ¤
if (pGroup && !pGroup->IsEmpty())
{
int iPercent = 40000 * iDeltaPercent / pGroup->GetKillPerDrop();
if (iPercent >= number(1, iRandRange))
{
const CMobItemGroup::SMobItemGroupInfo& info = pGroup->GetOne();
item = CreateItem(info.dwItemVnum, info.iCount, 0, true, info.iRarePct);
if (item) vec_item.push_back(item);
}
}
// END_OF_MOB_DROP_ITEM_BUG_FIX
}
}
// Level Item Group
{
itertype(m_map_pkLevelItemGroup) it;
it = m_map_pkLevelItemGroup.find(pkChr->GetRaceNum());
if ( it != m_map_pkLevelItemGroup.end() )
{
if ( it->second->GetLevelLimit() <= (DWORD)iLevel )
{
typeof(it->second->GetVector()) v = it->second->GetVector();
for ( DWORD i=0; i < v.size(); i++ )
{
if ( v[i].dwPct >= (DWORD)number(1, 1000000/*iRandRange*/) )
{
DWORD dwVnum = v[i].dwVNum;
item = CreateItem(dwVnum, v[i].iCount, 0, true);
if ( item ) vec_item.push_back(item);
}
}
}
}
}
// BuyerTheitGloves Item Group
{
if (pkKiller->GetPremiumRemainSeconds(PREMIUM_ITEM) > 0 ||
pkKiller->IsEquipUniqueGroup(UNIQUE_GROUP_DOUBLE_ITEM))
{
itertype(m_map_pkGloveItemGroup) it;
it = m_map_pkGloveItemGroup.find(pkChr->GetRaceNum());
if (it != m_map_pkGloveItemGroup.end())
{
typeof(it->second->GetVector()) v = it->second->GetVector();
for (DWORD i = 0; i < v.size(); ++i)
{
int iPercent = (v[i].dwPct * iDeltaPercent) / 100;
if (iPercent >= number(1, iRandRange))
{
DWORD dwVnum = v[i].dwVnum;
item = CreateItem(dwVnum, v[i].iCount, 0, true);
if (item) vec_item.push_back(item);
}
}
}
}
}
// ÀâÅÛ
if (pkChr->GetMobDropItemVnum())
{
itertype(m_map_dwEtcItemDropProb) it = m_map_dwEtcItemDropProb.find(pkChr->GetMobDropItemVnum());
if (it != m_map_dwEtcItemDropProb.end())
{
int iPercent = (it->second * iDeltaPercent) / 100;
if (iPercent >= number(1, iRandRange))
{
item = CreateItem(pkChr->GetMobDropItemVnum(), 1, 0, true);
if (item) vec_item.push_back(item);
}
}
}
if (pkChr->IsStone())
{
if (pkChr->GetDropMetinStoneVnum())
{
int iPercent = (pkChr->GetDropMetinStonePct() * iDeltaPercent) * 400;
if (iPercent >= number(1, iRandRange))
{
item = CreateItem(pkChr->GetDropMetinStoneVnum(), 1, 0, true);
if (item) vec_item.push_back(item);
}
}
}
if (pkKiller->IsHorseRiding() &&
GetDropPerKillPct(1000, 1000000, iDeltaPercent, "horse_skill_book_drop") >= number(1, iRandRange))
{
sys_log(0, "EVENT HORSE_SKILL_BOOK_DROP");
if ((item = CreateItem(ITEM_HORSE_SKILL_TRAIN_BOOK, 1, 0, true)))
vec_item.push_back(item);
}
if (GetDropPerKillPct(100, 1000, iDeltaPercent, "lotto_drop") >= number(1, iRandRange))
{
DWORD * pdw = M2_NEW DWORD[3];
pdw[0] = 50001;
pdw[1] = 1;
pdw[2] = quest::CQuestManager::instance().GetEventFlag("lotto_round");
// Çà¿îÀÇ ¼­´Â ¼ÒÄÏÀ» ¼³Á¤ÇÑ´Ù
DBManager::instance().ReturnQuery(QID_LOTTO, pkKiller->GetPlayerID(), pdw,
"INSERT INTO lotto_list VALUES(0, 'server%s', %u, NOW())",
get_table_postfix(), pkKiller->GetPlayerID());
}
//
// ½ºÆä¼È µå·Ó ¾ÆÀÌÅÛ
//
CreateQuestDropItem(pkChr, pkKiller, vec_item, iDeltaPercent, iRandRange);
for (itertype(vec_item) it = vec_item.begin(); it != vec_item.end(); ++it)
{
LPITEM item = *it;
DBManager::instance().SendMoneyLog(MONEY_LOG_DROP, item->GetVnum(), item->GetCount());
}
//
// ½Â·æ°î õÀǵ¿±¼ 2Ãþ¿¡¼­¸¸ ¼ö·æ¹æ ÀÔÀå±Ç
//
if (LC_IsYMIR() || LC_IsKorea())
{
if (73 == pkKiller->GetMapIndex())
{
int per = 25; // 0.25%
if (number(1, 10000) <= per)
{
LPITEM item = 0;
if ((item = CreateItem(71122, 1, 0, true)))
vec_item.push_back(item);
}
}
}
//
// ½Â·æ°î 1Ãþ, 2Ãþ¿¡¼­¸¸ 7,8 ½ºÅ³ÀÔ¹®¼­ µå·Ó
//
if (LC_IsYMIR() || LC_IsKorea())
{
switch (pkKiller->GetMapIndex())
{
case 72: // õÀǵ¿±¼ 1Ãþ
case 73: // õÀǵ¿±¼ 2Ãþ
{
int vnum = 0;
if (2403 == pkChr->GetRaceNum()) // õÀǹý»ç
vnum = 69200; // 7½ºÅ³ ÀÔ¹®¼­
else if (2411 == pkChr->GetRaceNum()) // ÁøõÀǺ´»ç
vnum = 69201; // 8½ºÅ³ ÀÔ¹®¼­
else
break;
int per = 5; // 0.05%
if (number(1, 10000) <= per)
{
LPITEM item = 0;
item = CreateItem(vnum, 1, 0, true);
if (item)
vec_item.push_back(item);
}
}
break;
}
}
return vec_item.size();
}
// ADD_GRANDMASTER_SKILL
int GetThreeSkillLevelAdjust(int level)
{
if (level < 40)
return 32;
if (level < 45)
return 16;
if (level < 50)
return 8;
if (level < 55)
return 4;
if (level < 60)
return 2;
return 1;
}
// END_OF_ADD_GRANDMASTER_SKILL
// DROPEVENT_CHARSTONE
// drop_char_stone 1
// drop_char_stone.percent_lv01_10 5
// drop_char_stone.percent_lv11_30 10
// drop_char_stone.percent_lv31_MX 15
// drop_char_stone.level_range 10
static struct DropEvent_CharStone
{
int percent_lv01_10;
int percent_lv11_30;
int percent_lv31_MX;
int level_range;
bool alive;
DropEvent_CharStone()
{
percent_lv01_10 = 100;
percent_lv11_30 = 200;
percent_lv31_MX = 300;
level_range = 10;
alive = false;
}
} gs_dropEvent_charStone;
static int __DropEvent_CharStone_GetDropPercent(int killer_level)
{
int killer_levelStep = (killer_level-1)/10;
switch (killer_levelStep)
{
case 0:
return gs_dropEvent_charStone.percent_lv01_10;
case 1:
case 2:
return gs_dropEvent_charStone.percent_lv11_30;
}
return gs_dropEvent_charStone.percent_lv31_MX;
}
static void __DropEvent_CharStone_DropItem(CHARACTER & killer, CHARACTER & victim, ITEM_MANAGER& itemMgr, std::vector<LPITEM>& vec_item)
{
if (!gs_dropEvent_charStone.alive)
return;
int killer_level = killer.GetLevel();
int dropPercent = __DropEvent_CharStone_GetDropPercent(killer_level);
int MaxRange = 10000;
if (LC_IsCanada() == true)
MaxRange = 20000;
if (number(1, MaxRange) <= dropPercent)
{
int log_level = (test_server || killer.GetGMLevel() >= GM_LOW_WIZARD) ? 0 : 1;
int victim_level = victim.GetLevel();
int level_diff = victim_level - killer_level;
if (level_diff >= +gs_dropEvent_charStone.level_range || level_diff <= -gs_dropEvent_charStone.level_range)
{
sys_log(log_level,
"dropevent.drop_char_stone.level_range_over: killer(%s: lv%d), victim(%s: lv:%d), level_diff(%d)",
killer.GetName(), killer.GetLevel(), victim.GetName(), victim.GetLevel(), level_diff);
return;
}
static const int Stones[] = { 30210, 30211, 30212, 30213, 30214, 30215, 30216, 30217, 30218, 30219, 30258, 30259, 30260, 30261, 30262, 30263 };
int item_vnum = Stones[number(0, _countof(Stones))];
LPITEM p_item = NULL;
if ((p_item = itemMgr.CreateItem(item_vnum, 1, 0, true)))
{
vec_item.push_back(p_item);
sys_log(log_level,
"dropevent.drop_char_stone.item_drop: killer(%s: lv%d), victim(%s: lv:%d), item_name(%s)",
killer.GetName(), killer.GetLevel(), victim.GetName(), victim.GetLevel(), p_item->GetName());
}
}
}
bool DropEvent_CharStone_SetValue(const std::string& name, int value)
{
if (name == "drop_char_stone")
{
gs_dropEvent_charStone.alive = value;
if (value)
sys_log(0, "dropevent.drop_char_stone = on");
else
sys_log(0, "dropevent.drop_char_stone = off");
}
else if (name == "drop_char_stone.percent_lv01_10")
gs_dropEvent_charStone.percent_lv01_10 = value;
else if (name == "drop_char_stone.percent_lv11_30")
gs_dropEvent_charStone.percent_lv11_30 = value;
else if (name == "drop_char_stone.percent_lv31_MX")
gs_dropEvent_charStone.percent_lv31_MX = value;
else if (name == "drop_char_stone.level_range")
gs_dropEvent_charStone.level_range = value;
else
return false;
sys_log(0, "dropevent.drop_char_stone: %d", gs_dropEvent_charStone.alive ? true : false);
sys_log(0, "dropevent.drop_char_stone.percent_lv01_10: %f", gs_dropEvent_charStone.percent_lv01_10/100.0f);
sys_log(0, "dropevent.drop_char_stone.percent_lv11_30: %f", gs_dropEvent_charStone.percent_lv11_30/100.0f);
sys_log(0, "dropevent.drop_char_stone.percent_lv31_MX: %f", gs_dropEvent_charStone.percent_lv31_MX/100.0f);
sys_log(0, "dropevent.drop_char_stone.level_range: %d", gs_dropEvent_charStone.level_range);
return true;
}
// END_OF_DROPEVENT_CHARSTONE
// fixme
// À§ÀÇ °Í°ú ÇÔ²² quest·Î »¬°Í »©º¸ÀÚ.
// ÀÌ°Å ³Ê¹« ´õ·´ÀݾÆ...
// ??.. ÇϵåÄÚµù ½È´Ù ¤Ì¤Ð
// °è·® ¾ÆÀÌÅÛ º¸»ó ½ÃÀÛ.
// by rtsummit °íÄ¡ÀÚ ÁøÂ¥
static struct DropEvent_RefineBox
{
int percent_low;
int low;
int percent_mid;
int mid;
int percent_high;
//int level_range;
bool alive;
DropEvent_RefineBox()
{
percent_low = 100;
low = 20;
percent_mid = 100;
mid = 45;
percent_high = 100;
//level_range = 10;
alive = false;
}
} gs_dropEvent_refineBox;
static LPITEM __DropEvent_RefineBox_GetDropItem(CHARACTER & killer, CHARACTER & victim, ITEM_MANAGER& itemMgr)
{
static const int lowerBox[] = { 50197, 50198, 50199 };
static const int lowerBox_range = 3;
static const int midderBox[] = { 50203, 50204, 50205, 50206 };
static const int midderBox_range = 4;
static const int higherBox[] = { 50207, 50208, 50209, 50210, 50211 };
static const int higherBox_range = 5;
if (victim.GetMobRank() < MOB_RANK_KNIGHT)
return NULL;
int killer_level = killer.GetLevel();
//int level_diff = victim_level - killer_level;
//if (level_diff >= +gs_dropEvent_refineBox.level_range || level_diff <= -gs_dropEvent_refineBox.level_range)
//{
// sys_log(log_level,
// "dropevent.drop_refine_box.level_range_over: killer(%s: lv%d), victim(%s: lv:%d), level_diff(%d)",
// killer.GetName(), killer.GetLevel(), victim.GetName(), victim.GetLevel(), level_diff);
// return NULL;
//}
if (killer_level <= gs_dropEvent_refineBox.low)
{
if (number (1, gs_dropEvent_refineBox.percent_low) == 1)
{
return itemMgr.CreateItem(lowerBox [number (1,lowerBox_range) - 1], 1, 0, true);
}
}
else if (killer_level <= gs_dropEvent_refineBox.mid)
{
if (number (1, gs_dropEvent_refineBox.percent_mid) == 1)
{
return itemMgr.CreateItem(midderBox [number (1,midderBox_range) - 1], 1, 0, true);
}
}
else
{
if (number (1, gs_dropEvent_refineBox.percent_high) == 1)
{
return itemMgr.CreateItem(higherBox [number (1,higherBox_range) - 1], 1, 0, true);
}
}
return NULL;
}
static void __DropEvent_RefineBox_DropItem(CHARACTER & killer, CHARACTER & victim, ITEM_MANAGER& itemMgr, std::vector<LPITEM>& vec_item)
{
if (!gs_dropEvent_refineBox.alive)
return;
int log_level = (test_server || killer.GetGMLevel() >= GM_LOW_WIZARD) ? 0 : 1;
LPITEM p_item = __DropEvent_RefineBox_GetDropItem(killer, victim, itemMgr);
if (p_item)
{
vec_item.push_back(p_item);
sys_log(log_level,
"dropevent.drop_refine_box.item_drop: killer(%s: lv%d), victim(%s: lv:%d), item_name(%s)",
killer.GetName(), killer.GetLevel(), victim.GetName(), victim.GetLevel(), p_item->GetName());
}
}
bool DropEvent_RefineBox_SetValue(const std::string& name, int value)
{
if (name == "refine_box_drop")
{
gs_dropEvent_refineBox.alive = value;
if (value)
sys_log(0, "refine_box_drop = on");
else
sys_log(0, "refine_box_drop = off");
}
else if (name == "refine_box_low")
gs_dropEvent_refineBox.percent_low = value < 100 ? 100 : value;
else if (name == "refine_box_mid")
gs_dropEvent_refineBox.percent_mid = value < 100 ? 100 : value;
else if (name == "refine_box_high")
gs_dropEvent_refineBox.percent_high = value < 100 ? 100 : value;
//else if (name == "refine_box_level_range")
// gs_dropEvent_refineBox.level_range = value;
else
return false;
sys_log(0, "refine_box_drop: %d", gs_dropEvent_refineBox.alive ? true : false);
sys_log(0, "refine_box_low: %d", gs_dropEvent_refineBox.percent_low);
sys_log(0, "refine_box_mid: %d", gs_dropEvent_refineBox.percent_mid);
sys_log(0, "refine_box_high: %d", gs_dropEvent_refineBox.percent_high);
//sys_log(0, "refine_box_low_level_range: %d", gs_dropEvent_refineBox.level_range);
return true;
}
// °³·® ¾ÆÀÌÅÛ º¸»ó ³¡.
void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::vector<LPITEM> & vec_item, int iDeltaPercent, int iRandRange)
{
LPITEM item = NULL;
if (!pkChr)
return;
if (!pkKiller)
return;
sys_log(1, "CreateQuestDropItem victim(%s), killer(%s)", pkChr->GetName(), pkKiller->GetName() );
// DROPEVENT_CHARSTONE
__DropEvent_CharStone_DropItem(*pkKiller, *pkChr, *this, vec_item);
// END_OF_DROPEVENT_CHARSTONE
__DropEvent_RefineBox_DropItem(*pkKiller, *pkChr, *this, vec_item);
// Å©¸®½º¸¶½º ¾ç¸»
if (quest::CQuestManager::instance().GetEventFlag("xmas_sock"))
{
//const DWORD SOCK_ITEM_VNUM = 50010;
DWORD SOCK_ITEM_VNUM = 0;
if (LC_IsKorea() || LC_IsYMIR())
{
SOCK_ITEM_VNUM = (number(1,100)<=50) ? 50010 : 71111;
}
else
{
SOCK_ITEM_VNUM = 50010;
}
int iDropPerKill[MOB_RANK_MAX_NUM] =
{
2000,
1000,
300,
50,
0,
0,
};
if ( iDropPerKill[pkChr->GetMobRank()] != 0 )
{
int iPercent = 40000 * iDeltaPercent / iDropPerKill[pkChr->GetMobRank()];
if ( LC_IsHongKong() )
{
iPercent *= 10;
}
sys_log(0, "SOCK DROP %d %d", iPercent, iRandRange);
if (iPercent >= number(1, iRandRange))
{
if ((item = CreateItem(SOCK_ITEM_VNUM, 1, 0, true)))
vec_item.push_back(item);
}
}
}
// ¿ù±¤ º¸ÇÕ
if (quest::CQuestManager::instance().GetEventFlag("drop_moon"))
{
const DWORD ITEM_VNUM = 50011;
int iDropPerKill[MOB_RANK_MAX_NUM] =
{
2000,
1000,
300,
50,
0,
0,
};
if (iDropPerKill[pkChr->GetMobRank()])
{
int iPercent = 40000 * iDeltaPercent / iDropPerKill[pkChr->GetMobRank()];
if (iPercent >= number(1, iRandRange))
{
if ((item = CreateItem(ITEM_VNUM, 1, 0, true)))
vec_item.push_back(item);
}
}
}
if (LC_IsEurope())
{
if (pkKiller->GetLevel() >= 15 && abs(pkKiller->GetLevel() - pkChr->GetLevel()) <= 5)
{
int pct = quest::CQuestManager::instance().GetEventFlag("hc_drop");
if (pct > 0)
{
const DWORD ITEM_VNUM = 30178;
if (number(1,100) <= pct)
{
if ((item = CreateItem(ITEM_VNUM, 1, 0, true)))
vec_item.push_back(item);
}
}
}
}
//À°°¢º¸ÇÕ
if (GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "2006_drop") >= number(1, iRandRange))
{
sys_log(0, "À°°¢º¸ÇÕ DROP EVENT ");
const static DWORD dwVnum = 50037;
if ((item = CreateItem(dwVnum, 1, 0, true)))
vec_item.push_back(item);
}
//À°°¢º¸ÇÕ+
if (GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "2007_drop") >= number(1, iRandRange))
{
sys_log(0, "À°°¢º¸ÇÕ DROP EVENT ");
const static DWORD dwVnum = 50043;
if ((item = CreateItem(dwVnum, 1, 0, true)))
vec_item.push_back(item);
}
// »õÇØ ÆøÁ× À̺¥Æ®
if (GetDropPerKillPct(/* minimum */ 100, /* default */ 1000, iDeltaPercent, "newyear_fire") >= number(1, iRandRange))
{
// Áß±¹Àº ÆøÁ×, Çѱ¹ ÆØÀÌ
const DWORD ITEM_VNUM_FIRE = g_iUseLocale ? 50107 : 50108;
if ((item = CreateItem(ITEM_VNUM_FIRE, 1, 0, true)))
vec_item.push_back(item);
}
// »õÇØ ´ëº¸¸§ ¿ø¼Ò À̺¥Æ®
if (GetDropPerKillPct(100, 500, iDeltaPercent, "newyear_moon") >= number(1, iRandRange))
{
sys_log(0, "EVENT NEWYEAR_MOON DROP");
const static DWORD wonso_items[6] = { 50016, 50017, 50018, 50019, 50019, 50019, };
DWORD dwVnum = wonso_items[number(0,5)];
if ((item = CreateItem(dwVnum, 1, 0, true)))
vec_item.push_back(item);
}
// ¹ß·»Å¸ÀÎ µ¥ÀÌ À̺¥Æ®. OGEÀÇ ¿ä±¸¿¡ µû¶ó event ÃÖ¼Ò°ªÀ» 1·Î º¯°æ.(´Ù¸¥ À̺¥Æ®´Â ÀÏ´Ü ±×´ë·Î µÒ.)
if (GetDropPerKillPct(1, g_iUseLocale ? 2000 : 800, iDeltaPercent, "valentine_drop") >= number(1, iRandRange))
{
sys_log(0, "EVENT VALENTINE_DROP");
const static DWORD valentine_items[2] = { 50024, 50025 };
DWORD dwVnum = valentine_items[number(0, 1)];
if ((item = CreateItem(dwVnum, 1, 0, true)))
vec_item.push_back(item);
}
// ¾ÆÀ̽ºÅ©¸² À̺¥Æ®
if (GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "icecream_drop") >= number(1, iRandRange))
{
const static DWORD icecream = 50123;
if ((item = CreateItem(icecream, 1, 0, true)))
vec_item.push_back(item);
}
// new Å©¸®½º¸¶½º À̺¥Æ®
// 53002 : ¾Æ±â ¼ø·Ï ¼Òȯ±Ç
if ((pkKiller->CountSpecifyItem(53002) > 0) && (GetDropPerKillPct(50, 100, iDeltaPercent, "new_xmas_event") >= number(1, iRandRange)))
{
const static DWORD xmas_sock = 50010;
pkKiller->AutoGiveItem (xmas_sock, 1);
}
if ((pkKiller->CountSpecifyItem(53007) > 0) && (GetDropPerKillPct(50, 100, iDeltaPercent, "new_xmas_event") >= number(1, iRandRange)))
{
const static DWORD xmas_sock = 50010;
pkKiller->AutoGiveItem (xmas_sock, 1);
}
//if (pkChr->GetLevel() >= 30 && (GetDropPerKillPct(50, 100, iDeltaPercent, "ds_drop") >= number(1, iRandRange)))
//{
// const static DWORD dragon_soul_gemstone = 30270;
// if ((item = CreateItem(dragon_soul_gemstone, 1, 0, true)))
// vec_item.push_back(item);
//}
if ( GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "halloween_drop") >= number(1, iRandRange) )
{
const static DWORD halloween_item = 30321;
if ( (item=CreateItem(halloween_item, 1, 0, true)) )
vec_item.push_back(item);
}
if ( GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "ramadan_drop") >= number(1, iRandRange) )
{
const static DWORD ramadan_item = 30315;
if ( (item=CreateItem(ramadan_item, 1, 0, true)) )
vec_item.push_back(item);
}
if ( GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "easter_drop") >= number(1, iRandRange) )
{
const static DWORD easter_item_base = 50160;
if ( (item=CreateItem(easter_item_base+number(0,19), 1, 0, true)) )
vec_item.push_back(item);
}
// ¿ùµåÄÅ À̺¥Æ®
if ( GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "football_drop") >= number(1, iRandRange) )
{
const static DWORD football_item = 50096;
if ( (item=CreateItem(football_item, 1, 0, true)) )
vec_item.push_back(item);
}
// È­ÀÌÆ® µ¥ÀÌ À̺¥Æ®
if (GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "whiteday_drop") >= number(1, iRandRange))
{
sys_log(0, "EVENT WHITEDAY_DROP");
const static DWORD whiteday_items[2] = { ITEM_WHITEDAY_ROSE, ITEM_WHITEDAY_CANDY };
DWORD dwVnum = whiteday_items[number(0,1)];
if ((item = CreateItem(dwVnum, 1, 0, true)))
vec_item.push_back(item);
}
// ¾î¸°À̳¯ ¼ö¼ö²²³¢ »óÀÚ À̺¥Æ®
if (pkKiller->GetLevel()>=50)
{
if (GetDropPerKillPct(100, 1000, iDeltaPercent, "kids_day_drop_high") >= number(1, iRandRange))
{
DWORD ITEM_QUIZ_BOX = 50034;
if ((item = CreateItem(ITEM_QUIZ_BOX, 1, 0, true)))
vec_item.push_back(item);
}
}
else
{
if (GetDropPerKillPct(100, 1000, iDeltaPercent, "kids_day_drop") >= number(1, iRandRange))
{
DWORD ITEM_QUIZ_BOX = 50034;
if ((item = CreateItem(ITEM_QUIZ_BOX, 1, 0, true)))
vec_item.push_back(item);
}
}
// ¿Ã¸²ÇÈ µå·Ó À̺¥Æ®
if (pkChr->GetLevel() >= 30 && GetDropPerKillPct(50, 100, iDeltaPercent, "medal_part_drop") >= number(1, iRandRange))
{
const static DWORD drop_items[] = { 30265, 30266, 30267, 30268, 30269 };
int i = number (0, 4);
item = CreateItem(drop_items[i]);
if (item != NULL)
vec_item.push_back(item);
}
// ADD_GRANDMASTER_SKILL
// È¥¼® ¾ÆÀÌÅÛ µå·Ó
if (pkChr->GetLevel() >= 40 && pkChr->GetMobRank() >= MOB_RANK_BOSS && GetDropPerKillPct(/* minimum */ 1, /* default */ 1000, iDeltaPercent, "three_skill_item") / GetThreeSkillLevelAdjust(pkChr->GetLevel()) >= number(1, iRandRange))
{
const DWORD ITEM_VNUM = 50513;
if ((item = CreateItem(ITEM_VNUM, 1, 0, true)))
vec_item.push_back(item);
}
// END_OF_ADD_GRANDMASTER_SKILL
//
// Á¾ÀÚ ¾ÆÀÌÅÛ drop
//
if (GetDropPerKillPct(100, 1000, iDeltaPercent, "dragon_boat_festival_drop") >= number(1, iRandRange))
{
const DWORD ITEM_SEED = 50085;
if ((item = CreateItem(ITEM_SEED, 1, 0, true)))
vec_item.push_back(item);
}
// ¹«½ÅÀÇ Ãູ¼­¿ë ¸¸³âÇÑö drop
if (pkKiller->GetLevel() >= 15 && quest::CQuestManager::instance().GetEventFlag("mars_drop"))
{
const DWORD ITEM_HANIRON = 70035;
int iDropMultiply[MOB_RANK_MAX_NUM] =
{
50,
30,
5,
1,
0,
0,
};
if (iDropMultiply[pkChr->GetMobRank()] &&
GetDropPerKillPct(1000, 1500, iDeltaPercent, "mars_drop") >= number(1, iRandRange) * iDropMultiply[pkChr->GetMobRank()])
{
if ((item = CreateItem(ITEM_HANIRON, 1, 0, true)))
vec_item.push_back(item);
}
}
}
DWORD ITEM_MANAGER::GetRefineFromVnum(DWORD dwVnum)
{
itertype(m_map_ItemRefineFrom) it = m_map_ItemRefineFrom.find(dwVnum);
if (it != m_map_ItemRefineFrom.end())
return it->second;
return 0;
}
const CSpecialItemGroup* ITEM_MANAGER::GetSpecialItemGroup(DWORD dwVnum)
{
itertype(m_map_pkSpecialItemGroup) it = m_map_pkSpecialItemGroup.find(dwVnum);
if (it != m_map_pkSpecialItemGroup.end())
{
return it->second;
}
return NULL;
}
const CSpecialAttrGroup* ITEM_MANAGER::GetSpecialAttrGroup(DWORD dwVnum)
{
itertype(m_map_pkSpecialAttrGroup) it = m_map_pkSpecialAttrGroup.find(dwVnum);
if (it != m_map_pkSpecialAttrGroup.end())
{
return it->second;
}
return NULL;
}
DWORD ITEM_MANAGER::GetMaskVnum(DWORD dwVnum)
{
TMapDW2DW::iterator it = m_map_new_to_ori.find (dwVnum);
if (it != m_map_new_to_ori.end())
{
return it->second;
}
else
return 0;
}
// pkNewItemÀ¸·Î ¸ðµç ¼Ó¼º°ú ¼ÒÄÏ °ªµéÀ» ¸ñ»çÇÏ´Â ÇÔ¼ö.
// ±âÁ¸¿¡ char_item.cpp ÆÄÀÏ¿¡ ÀÖ´ø ·ÎÄÃÇÔ¼öÀÎ TransformRefineItem ±×´ë·Î º¹»çÇÔ
void ITEM_MANAGER::CopyAllAttrTo(LPITEM pkOldItem, LPITEM pkNewItem)
{
// ACCESSORY_REFINE
if (pkOldItem->IsAccessoryForSocket())
{
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
{
pkNewItem->SetSocket(i, pkOldItem->GetSocket(i));
}
//pkNewItem->StartAccessorySocketExpireEvent();
}
// END_OF_ACCESSORY_REFINE
else
{
// ¿©±â¼­ ±úÁø¼®ÀÌ ÀÚµ¿ÀûÀ¸·Î û¼Ò µÊ
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
{
if (!pkOldItem->GetSocket(i))
break;
else
pkNewItem->SetSocket(i, 1);
}
// ¼ÒÄÏ ¼³Á¤
int slot = 0;
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
{
int socket = pkOldItem->GetSocket(i);
const int ITEM_BROKEN_METIN_VNUM = 28960; // ÀÌ°Ç ¹¹ ¶È°°Àº »ó¼ö°¡ 3±ºµ¥³ª ÀÖ³Ä... Çϳª·Î ÇسõÁö¤Ð¤Ð¤Ð ³ª´Â Æнº È«ÀÌ ÇÒ²¨ÀÓ
if (socket > 2 && socket != ITEM_BROKEN_METIN_VNUM)
pkNewItem->SetSocket(slot++, socket);
}
}
// ¸ÅÁ÷ ¾ÆÀÌÅÛ ¼³Á¤
pkOldItem->CopyAttributeTo(pkNewItem);
}