Files
Client/Server/RylServerProject/RylGameLibrary/Creature/Monster/AwardTable.cpp
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

677 lines
22 KiB
C++

#include "stdafx.h"
#include <Utility/Math/Math.h>
#include <Utility/Setup/ServerSetup.h>
#include <Item/Item.h>
#include <Item/ItemMgr.h>
#include <Item/ItemFactory.h>
#include <Creature/CreatureManager.h>
#include <Creature/Character/Character.h>
#include <GameEvent/GameEventMgr.h>
#include "Monster.h"
#include "AwardTable.h"
using namespace AwardTable;
CAward CAward::ms_this;
unsigned long CAward::GetAward(unsigned char cItemKind, CMonster* lpDeadMonster, CCharacter* lpAttackCharacter,
Item::CItem** lpItem_Out)
{
if (NULL == lpDeadMonster || NULL == lpAttackCharacter)
{
ERRLOG2(g_Log, "CAward::GetAward 포인터 오류입니다. Monster:0x%p, Character:0x%p", lpDeadMonster, lpAttackCharacter);
return 0;
}
// edith 드랍 아이템의 속성별 확율
// 이벤트 아이템이 드랍될 타이밍인지 체크한다.
unsigned long dwResultItem = CGameEventMgr::GetInstance().PopDropEventItem();
if (0 == dwResultItem)
{
const unsigned char cLevel = lpDeadMonster->GetStatus().m_nLevel;
const unsigned int iPattern = lpDeadMonster->GetPattern();
using namespace Item::EquipType;
OptionType eOptionType = MAX_OPTION_TYPE;
Grade eGrade = MAX_GRADE;
float fAddPer = 1.0f;
switch (cItemKind)
{
case MonsterInfo::ORIGINAL1:
case MonsterInfo::ORIGINAL2:
case MonsterInfo::ORIGINAL3:
case MonsterInfo::ORIGINAL4:
case MonsterInfo::ORIGINAL5:
dwResultItem = lpDeadMonster->GetAwardItem(cItemKind);
break;
case MonsterInfo::COIN:
// 골드에 스틸핸드가 미치는 영향
if(lpAttackCharacter->GetEnchantInfo().GetFlag(Skill::SpellID::StealHand))
{
// 배수로 확정한다. 1이면
int iLevel = lpAttackCharacter->GetEnchantLevel(Skill::SpellID::StealHand);
// 기본 1.0
fAddPer += ((float)iLevel/10.0f);
}
if( lpAttackCharacter->GetAbilityValue(Skill::Type::AB_GETUP_GOLD) )
{
fAddPer += ((float)lpAttackCharacter->GetAbilityValue(Skill::Type::AB_GETUP_GOLD)/100.0f);
}
dwResultItem = GetAwardCoin(cLevel, fAddPer);
break;
case MonsterInfo::GEM: dwResultItem = GetAwardGem(cLevel); break;
case MonsterInfo::METAL: dwResultItem = GetAwardMetal(cLevel); break;
case MonsterInfo::POTION: dwResultItem = GetAwardPotion(cLevel); break;
case MonsterInfo::SKILL:
dwResultItem = GetAwardSkill(cLevel, lpAttackCharacter->GetRace());
break;
case MonsterInfo::CASH_ITEM: dwResultItem = GetAwardCashItem(lpAttackCharacter->GetRace(), cLevel, iPattern); break;
case MonsterInfo::LOTTERY: dwResultItem = GetAwardLottery(); break;
case MonsterInfo::F_STANDARD_EQUIP: eOptionType = STANDARD_OPTION; eGrade = F_GRADE; break;
case MonsterInfo::D_STANDARD_EQUIP: eOptionType = STANDARD_OPTION; eGrade = D_GRADE; break;
case MonsterInfo::C_STANDARD_EQUIP: eOptionType = STANDARD_OPTION; eGrade = C_GRADE; break;
case MonsterInfo::B_STANDARD_EQUIP: eOptionType = STANDARD_OPTION; eGrade = B_GRADE; break;
case MonsterInfo::A_STANDARD_EQUIP: eOptionType = STANDARD_OPTION; eGrade = A_GRADE; break;
case MonsterInfo::F_OVER_EQUIP: eOptionType = OVER_OPTION; eGrade = F_GRADE; break;
case MonsterInfo::D_OVER_EQUIP: eOptionType = OVER_OPTION; eGrade = D_GRADE; break;
case MonsterInfo::C_OVER_EQUIP: eOptionType = OVER_OPTION; eGrade = C_GRADE; break;
case MonsterInfo::B_OVER_EQUIP: eOptionType = OVER_OPTION; eGrade = B_GRADE; break;
case MonsterInfo::A_OVER_EQUIP: eOptionType = OVER_OPTION; eGrade = A_GRADE; break;
case MonsterInfo::NO_EQUIP: eOptionType = NO_OPTION; break;
//--// start..
case MonsterInfo::F_RING: dwResultItem = GetAwardRing(cLevel, F_GRADE); break;
case MonsterInfo::D_RING: dwResultItem = GetAwardRing(cLevel, D_GRADE); break;
case MonsterInfo::C_RING: dwResultItem = GetAwardRing(cLevel, C_GRADE); break;
case MonsterInfo::B_RING: dwResultItem = GetAwardRing(cLevel, B_GRADE); break;
case MonsterInfo::A_RING: dwResultItem = GetAwardRing(cLevel, A_GRADE); break;
case MonsterInfo::F_NECKLACE: dwResultItem = GetAwardNecklace(cLevel, F_GRADE); break;
case MonsterInfo::D_NECKLACE: dwResultItem = GetAwardNecklace(cLevel, D_GRADE); break;
case MonsterInfo::C_NECKLACE: dwResultItem = GetAwardNecklace(cLevel, C_GRADE); break;
case MonsterInfo::B_NECKLACE: dwResultItem = GetAwardNecklace(cLevel, B_GRADE); break;
case MonsterInfo::A_NECKLACE: dwResultItem = GetAwardNecklace(cLevel, A_GRADE); break;
case MonsterInfo::F_RUNE: dwResultItem = GetAwardRune(cLevel, F_GRADE); break;
case MonsterInfo::D_RUNE: dwResultItem = GetAwardRune(cLevel, D_GRADE); break;
case MonsterInfo::C_RUNE: dwResultItem = GetAwardRune(cLevel, C_GRADE); break;
case MonsterInfo::B_RUNE: dwResultItem = GetAwardRune(cLevel, B_GRADE); break;
case MonsterInfo::A_RUNE: dwResultItem = GetAwardRune(cLevel, A_GRADE); break;
case MonsterInfo::DESTRUCTION_RUNE: dwResultItem = GetAwardDestructionRune(); break;
//--// end..
default: return 0;
}
Item::CItemFactory& ItemFactory = Item::CItemFactory::GetInstance();
if (MAX_OPTION_TYPE != eOptionType)
{
// 장비의 경우
dwResultItem = GetAwardEquipment(eOptionType, cLevel, lpAttackCharacter, false);
*lpItem_Out = ItemFactory.CreateItem(static_cast<unsigned short>(dwResultItem));
Item::CEquipment* lpEquip = Item::CEquipment::DowncastToEquipment(*lpItem_Out);
if (NULL != lpEquip)
{
// edith 2008.01.14 장비에 옵션을 랜덤으로 건다.(설명)
if(lpEquip->AddRandomOption(eGrade, lpDeadMonster->GetOptionBaseNum(eOptionType), lpAttackCharacter->GetMagicChancePoint()))
lpEquip->SetNewEquip(2);
else
lpEquip->SetNewEquip();
}
}
else
{
if (!(dwResultItem & CCell::MONEY_BIT))
{
// 돈이 아닌 기타 잡템
*lpItem_Out = ItemFactory.CreateItem(static_cast<unsigned short>(dwResultItem));
if (NULL != *lpItem_Out)
{
(*lpItem_Out)->SetNumOrDurability(1);
}
}
}
}
return dwResultItem;
}
unsigned long CAward::GetAwardCoin(unsigned char cDeadMonsterLevel, float cAddPer)
{
// edith 2009.06.13 골드 드랍양 조절
// const unsigned long dwMinMoney = static_cast<unsigned long>(cDeadMonsterLevel) * 2;
// const unsigned long dwMaxMoney = static_cast<unsigned long>(cDeadMonsterLevel) * 4 + 10;
const unsigned long dwMinMoney = static_cast<unsigned long>(cDeadMonsterLevel) * 3 + 6;
const unsigned long dwMaxMoney = static_cast<unsigned long>(cDeadMonsterLevel) * 6 + 12;
unsigned long dwMoneyAmount =
static_cast<unsigned long>( min(Math::Random::ComplexRandom(dwMaxMoney + 1, dwMinMoney) * (CServerSetup::GetInstance().GetDropDefault() / 100.0f) * cAddPer,
float(CCell::MAX_MONEY_AMOUNT)) );
dwMoneyAmount = min(dwMoneyAmount, ULONG_MAX & ~CCell::TYPE_CHECK_BIT);
return (CCell::MONEY_BIT + dwMoneyAmount);
}
unsigned long CAward::GetAwardGem(unsigned char cDeadMonsterLevel)
{
cDeadMonsterLevel = std::min(cDeadMonsterLevel, unsigned char(MAX_MONSTER_LEVEL));
const int nPoint = Math::Random::ComplexRandom(std::accumulate(&(aryGemDropTable[(cDeadMonsterLevel - 1) / 10][0]),
&(aryGemDropTable[(cDeadMonsterLevel - 1) / 10][GEM_DROP_TABLE_ROW]), 0));
int nSpace = 0;
for (int nAwardTableIndex = 0; nAwardTableIndex < GEM_DROP_TABLE_ROW; ++nAwardTableIndex)
{
nSpace += aryGemDropTable[(cDeadMonsterLevel - 1) / 10][nAwardTableIndex];
if (nSpace > nPoint)
{
return (Item::EtcItemID::GEM_START_ID +
Math::Random::ComplexRandom(Item::MAX_GEM_KIND) + (nAwardTableIndex * Item::MAX_GEM_KIND));
}
}
return 0;
}
//--// start..
unsigned long CAward::GetAwardRing(unsigned char cLevel, unsigned char cGrade)
{
return Item::CItemMgr::GetInstance().GetRingDropItem(cLevel, cGrade);
}
unsigned long CAward::GetAwardNecklace(unsigned char cLevel, unsigned char cGrade)
{
return Item::CItemMgr::GetInstance().GetNecklaceDropItem(cLevel, cGrade);
}
unsigned long CAward::GetAwardRune(unsigned char cLevel, unsigned char cGrade)
{
return Item::CItemMgr::GetInstance().GetRuneDropItem(cLevel, cGrade);
}
unsigned long CAward::GetAwardDestructionRune()
{
return Item::EtcItemID::DESTRUCTION_RUNE;
}
//--// end..
unsigned long CAward::GetAwardMetal(unsigned char cDeadMonsterLevel)
{
cDeadMonsterLevel = std::min(cDeadMonsterLevel, unsigned char(MAX_MONSTER_LEVEL));
const int nPoint = Math::Random::ComplexRandom(std::accumulate(&(aryMetalDropTable[(cDeadMonsterLevel - 1) / 10][0]),
&(aryMetalDropTable[(cDeadMonsterLevel - 1) / 10][METAL_DROP_TABLE_ROW]), 0));
int nSpace = 0;
for (int nAwardTableIndex = 0; nAwardTableIndex < METAL_DROP_TABLE_ROW; ++nAwardTableIndex)
{
nSpace += aryMetalDropTable[(cDeadMonsterLevel - 1) / 10][nAwardTableIndex];
if (nSpace > nPoint)
{
// 코어시스템
if(nAwardTableIndex == 6)
{
// edith 2009.09.17 코어시스템
// 현재로서는 각성의 코어만 있으므로 각성의 코어를 떨군다.
return Item::EtcItemID::AWAKENCORE;
}
else
{
int iMetalID = (Item::EtcItemID::MINERAL_START_ID + nAwardTableIndex);
if(iMetalID > Item::EtcItemID::MINERAL_END_ID)
iMetalID = Item::EtcItemID::MINERAL_END_ID;
return iMetalID;
}
}
}
return 0;
}
unsigned long CAward::GetAwardPotion(unsigned char cDeadMonsterLevel)
{
cDeadMonsterLevel = std::min(cDeadMonsterLevel, unsigned char(MAX_MONSTER_LEVEL));
const int nPoint = Math::Random::ComplexRandom(std::accumulate(&(aryPotionDropTable[(cDeadMonsterLevel - 1) / 10][0]),
&(aryPotionDropTable[(cDeadMonsterLevel - 1) / 10][POTION_DROP_TABLE_ROW]), 0));
int nSpace = 0;
for (int nAwardTableIndex = 0; nAwardTableIndex < POTION_DROP_TABLE_ROW; ++nAwardTableIndex)
{
nSpace += aryPotionDropTable[(cDeadMonsterLevel - 1) / 10][nAwardTableIndex];
if (nSpace > nPoint)
{
if(nAwardTableIndex <= 3)
{
const int iType = Math::Random::ComplexRandom(2);
// 빵들.
if(iType == 0)
{
switch (nAwardTableIndex)
{
case 0: return Item::EtcItemID::BREAD;
case 1: return Item::EtcItemID::RARE_STEAK;
case 2: return Item::EtcItemID::WELLDONE_STEAK;
case 3: return Item::EtcItemID::BACON;
}
}
else if(iType == 1)
{
switch (nAwardTableIndex)
{
case 0: return Item::EtcItemID::MANNA1;
case 1: return Item::EtcItemID::MANNA2;
case 2: return Item::EtcItemID::MANNA3;
case 3: return Item::EtcItemID::MANNA4;
}
}
else if(iType == 2)
{
switch (nAwardTableIndex)
{
case 0: return Item::EtcItemID::SOUP1;
case 1: return Item::EtcItemID::SOUP2;
case 2: return Item::EtcItemID::SOUP3;
case 3: return Item::EtcItemID::SOUP4;
}
}
}
else
{
// 4부터 포션 0랩 포션
// 포션계열,
int iLevel = nAwardTableIndex-4;
const int iType = Math::Random::ComplexRandom(14);
switch(iType)
{
case 0: return Item::EtcItemID::POTION1+iLevel;
case 1: return Item::EtcItemID::POTION2+iLevel;
case 2: return Item::EtcItemID::POTION3+iLevel;
case 3: return Item::EtcItemID::POTION4+iLevel;
case 4: return Item::EtcItemID::POTION5+iLevel;
case 5: return Item::EtcItemID::POTION6+iLevel;
case 6: return Item::EtcItemID::POTION7+iLevel;
case 7: return Item::EtcItemID::POTION8+iLevel;
case 8: return Item::EtcItemID::POTION9+iLevel;
case 9: return Item::EtcItemID::POTION10+iLevel;
case 10: return Item::EtcItemID::POTION11+iLevel;
case 11: return Item::EtcItemID::POTION12+iLevel;
case 12: return Item::EtcItemID::POTION13+iLevel;
case 13: return Item::EtcItemID::POTION14+iLevel;
// case 14: return Item::EtcItemID::POTION15+iLevel;
}
}
}
}
return 0;
}
unsigned long CAward::GetAwardSkill(unsigned char cDeadMonsterLevel, char cAttackCharacterNation)
{
cDeadMonsterLevel = std::min(cDeadMonsterLevel, unsigned char(MAX_MONSTER_LEVEL));
const short nDeadMonsterLevelRange = (cDeadMonsterLevel - 1) / 10;
const short nPoint = static_cast<short>(Math::Random::ComplexRandom(arySkillBookDropTable[nDeadMonsterLevelRange] * 3));
short nSkillLevel = (101 <= cDeadMonsterLevel) ? 4 : nPoint % arySkillBookDropTable[nDeadMonsterLevelRange];
// edith 2008.05.07 스킬북 드랍 설정
if (true == CServerSetup::GetInstance().UseContents(GameRYL::LEVEL_LIMIT_90))
{
// 4단계까지 드랍 가능
nSkillLevel = min(nSkillLevel, short(3));
}
else
{
// 3단계까지 드랍 가능
nSkillLevel = min(nSkillLevel, short(2));
}
/*
else if (true == CServerSetup::GetInstance().UseContents(GameRYL::LEVEL_LIMIT_80))
{
// 4단계까지 드랍 가능
nSkillLevel = min(nSkillLevel, short(3));
}
else
{
// 3단계까지 드랍 가능
nSkillLevel = min(nSkillLevel, short(2));
}
*/
const CClass::JobLevel nSkillType = (nPoint < arySkillBookDropTable[nDeadMonsterLevelRange] || 4 <= nSkillLevel) ?
CClass::JOB_CHANGE_1ST : CClass::DEFAULT_CLASS;
int nSkillKind = (4 <= nSkillLevel) ? FIFTHSKILL_KIND : SKILL_KIND;
unsigned short* arySkillShuffleList = new unsigned short[nSkillKind];
for(int i = 0; i < nSkillKind; i++)
{
arySkillShuffleList[i] = 0;
}
if(4 <= nSkillLevel)
{
std::copy(aryDropableFifthSkillbookList, aryDropableFifthSkillbookList + nSkillKind, arySkillShuffleList);
}
else
{
std::copy(aryDropableSkillbookList, aryDropableSkillbookList + nSkillKind, arySkillShuffleList);
}
std::random_shuffle(arySkillShuffleList, arySkillShuffleList + nSkillKind);
for (int nAwardTableIndex = 0; nAwardTableIndex < nSkillKind; nAwardTableIndex++)
{
const unsigned char cSkillBookClass = (arySkillShuffleList[nAwardTableIndex] & ~Skill::SKILL_MASK) >> 8;
if ((cSkillBookClass >> 4) == cAttackCharacterNation && CClass::GetJobLevel(cSkillBookClass) == nSkillType)
{
return Item::CItemMgr::GetInstance().GetItemIDFromSkillID(arySkillShuffleList[nAwardTableIndex], nSkillLevel);
}
}
delete arySkillShuffleList;
return 0;
}
unsigned short CAward::GetAwardEquipment(Item::EquipType::OptionType eOptionType,
unsigned char cDeadMonsterLevel, CCharacter* lpCharacter, bool bQuestAward)
{
unsigned short wItemID = 0;
// 솔로잉
if (NULL == lpCharacter->GetParty() || true == bQuestAward)
{
// edith 2008.01.14 40프로 확율로 클래스에 알맞는 장비 드랍
// 40%의 확률로 클래스에 알맞은 장비를 드랍한다.
if (Math::Random::ComplexRandom(100) < (unsigned long)(40+lpCharacter->GetAbilityValue(Skill::Type::AB_MYEQUIP_UP)))
{
unsigned char aryShuffleList[PRIMARY_EQUIP_TABLE_ROW] = { 0, };
std::copy(aryPrimaryEquipList[lpCharacter->GetClass()],
aryPrimaryEquipList[lpCharacter->GetClass()] + PRIMARY_EQUIP_TABLE_ROW,
aryShuffleList);
std::random_shuffle(aryShuffleList, aryShuffleList + PRIMARY_EQUIP_TABLE_ROW);
Item::CItemType& itemType = Item::CItemType::GetInstance();
for (unsigned char cIndex = 0; cIndex < PRIMARY_EQUIP_TABLE_ROW; ++cIndex)
{
Item::ItemType::Type eItemType = static_cast<Item::ItemType::Type>(aryShuffleList[cIndex]);
// edith 2008.01.14 옵션타입 알아오기 (스탠다드옵션, 오버옵션, 논옵션)
if (MAX_ITEM_TYPE != aryShuffleList[cIndex] &&
true == itemType.IsCorrectOptionType(eOptionType, eItemType))
{
wItemID = Item::CItemMgr::GetInstance().GetDropItem(eItemType, cDeadMonsterLevel);
if (0 == wItemID) { continue; }
break;
}
}
}
else
{
if (CClass::HUMAN == lpCharacter->GetRace())
{
wItemID = SelectItemByRace(eOptionType, aryHumanEquipTypeList, HUMAN_EQUIP_TYPE_NUM, cDeadMonsterLevel);
}
else if (CClass::AKHAN == lpCharacter->GetRace())
{
wItemID = SelectItemByRace(eOptionType, aryAkhanEquipTypeList, AKHAN_EQUIP_TYPE_NUM, cDeadMonsterLevel);
}
else
{
ERRLOG2(g_Log, "CID:0x%08x 캐릭터의 종족이 이상합니다. 종족:%d",
lpCharacter->GetCID(), lpCharacter->GetRace());
return 0;
}
}
}
// 파티 플레이
else
{
CCharacterParty* lpParty = reinterpret_cast<CCharacterParty *>(lpCharacter->GetParty());
CCharacter* aryNearCharacterList[PARTY::MAX_MEM];
unsigned char cHighestLevel = 0;
const unsigned char cNearPartyMemberNum = lpParty->GetNearMemberList(lpCharacter->GetCellPos().m_lpCell,
true, aryNearCharacterList, cHighestLevel);
if (0 == cNearPartyMemberNum) { return 0; }
unsigned char cHumanNum = 0;
for (unsigned char cMemberIndex = 0; cMemberIndex < cNearPartyMemberNum; ++cMemberIndex)
{
if (CClass::HUMAN == aryNearCharacterList[cMemberIndex]->GetRace())
{
++cHumanNum;
}
}
// 파티원의 종족 비율에 의해 드랍될 장비 타입의 확률이 결정된다.
if (static_cast<unsigned long>(cHumanNum * 100.0f / cNearPartyMemberNum) > Math::Random::ComplexRandom(100))
{
wItemID = SelectItemByRace(eOptionType, aryHumanEquipTypeList, HUMAN_EQUIP_TYPE_NUM, cDeadMonsterLevel);
}
else
{
wItemID = SelectItemByRace(eOptionType, aryAkhanEquipTypeList, AKHAN_EQUIP_TYPE_NUM, cDeadMonsterLevel);
}
}
if (0 == wItemID)
{
ERRLOG0(g_Log, "드랍할 장비를 결정하지 못하였습니다.");
return 0;
}
return wItemID;
}
unsigned short CAward::GetQuestEquipmentClass(Item::EquipType::OptionType eOptionType, unsigned char cClass,
unsigned char cDeadMonsterLevel, CCharacter* lpCharacter)
{
unsigned short wItemID = 0;
unsigned char aryShuffleList[PRIMARY_EQUIP_TABLE_ROW] = { 0, };
std::copy(aryPrimaryEquipList[cClass],
aryPrimaryEquipList[cClass] + PRIMARY_EQUIP_TABLE_ROW,
aryShuffleList);
std::random_shuffle(aryShuffleList, aryShuffleList + PRIMARY_EQUIP_TABLE_ROW);
Item::CItemType& itemType = Item::CItemType::GetInstance();
for (unsigned char cIndex = 0; cIndex < PRIMARY_EQUIP_TABLE_ROW; ++cIndex)
{
Item::ItemType::Type eItemType = static_cast<Item::ItemType::Type>(aryShuffleList[cIndex]);
// edith 2008.01.14 옵션타입 알아오기 (스탠다드옵션, 오버옵션, 논옵션)
if (MAX_ITEM_TYPE != aryShuffleList[cIndex] &&
true == itemType.IsCorrectOptionType(eOptionType, eItemType))
{
wItemID = Item::CItemMgr::GetInstance().GetDropItem(eItemType, cDeadMonsterLevel);
if (0 == wItemID) { continue; }
break;
}
}
if (0 == wItemID)
{
ERRLOG0(g_Log, "드랍할 장비를 결정하지 못하였습니다.");
return 0;
}
return wItemID;
}
unsigned long CAward::GetAwardCashItem(char cAttackCharacterNation, unsigned char cDeadMonsterLevel, unsigned int cDeadMonsterPattern)
{
cDeadMonsterLevel = std::min(cDeadMonsterLevel, unsigned char(MAX_MONSTER_LEVEL));
int iMonLevel = (cDeadMonsterLevel - 1) / 10;
if(cDeadMonsterPattern == MonsterInfo::PATTERN_CHIEF) // 치프면 11
iMonLevel = 11;
else if(cDeadMonsterPattern == MonsterInfo::PATTERN_NAMED) // 네임드면 12 테이블
iMonLevel = 12;
const int nPoint = Math::Random::ComplexRandom(std::accumulate(&(aryCashDropTable[iMonLevel][0]),
&(aryCashDropTable[iMonLevel][CASH_DROP_TABLE_ROW]), 0));
// 캐쉬템의 드랍아이템 리스트는 여기에
int nSpace = 0;
for (int nAwardTableIndex = 0; nAwardTableIndex < CASH_DROP_TABLE_ROW; ++nAwardTableIndex)
{
nSpace += aryCashDropTable[(cDeadMonsterLevel - 1) / 10][nAwardTableIndex];
if (nSpace > nPoint)
{
if(nAwardTableIndex == 0) // 망각의돌
return Item::EtcItemID::OBLIVION_STONE;
else if(nAwardTableIndex == 4) // 내구도석
return Item::EtcItemID::ENDURANCESTONE;
else if(nAwardTableIndex == 5) // 부활의돌
return Item::EtcItemID::REBIRTH_STONE;
else if(nAwardTableIndex == 6) // 탈것
{
const int iType = Math::Random::ComplexRandom(2);
if(cAttackCharacterNation == 0) //휴먼
{
if(iType == 0)
return Item::EtcItemID::RIDEH1;
else
return Item::EtcItemID::RIDEH2;
}
else // 아칸
{
if(iType == 0)
return Item::EtcItemID::RIDEA1;
else
return Item::EtcItemID::RIDEA2;
}
}
else if(nAwardTableIndex == 3) // 오브
{
const int iType = Math::Random::ComplexRandom(2);
if(iType == 0)
return Item::EtcItemID::ORB_EXP;
else
return Item::EtcItemID::ORB_LUCK;
}
else if(nAwardTableIndex == 1 || nAwardTableIndex == 2) // 유료 포션
{
int iLevel = nAwardTableIndex-1;
int iType = 0;
const int iRage = Math::Random::ComplexRandom(100);
if(iRage < 60)
{
iType = Math::Random::ComplexRandom(2);
}
else
{
iType = 2+Math::Random::ComplexRandom(12);
}
switch(iType)
{
case 0: return Item::EtcItemID::CASHPOTION1+iLevel;
case 1: return Item::EtcItemID::CASHPOTION2+iLevel;
case 2: return Item::EtcItemID::CASHPOTION3+iLevel;
case 3: return Item::EtcItemID::CASHPOTION4+iLevel;
case 4: return Item::EtcItemID::CASHPOTION5+iLevel;
case 5: return Item::EtcItemID::CASHPOTION6+iLevel;
case 6: return Item::EtcItemID::CASHPOTION7+iLevel;
case 7: return Item::EtcItemID::CASHPOTION8+iLevel;
case 8: return Item::EtcItemID::CASHPOTION9+iLevel;
case 9: return Item::EtcItemID::CASHPOTION10+iLevel;
case 10: return Item::EtcItemID::CASHPOTION11+iLevel;
case 11: return Item::EtcItemID::CASHPOTION12+iLevel;
case 12: return Item::EtcItemID::CASHPOTION13+iLevel;
case 13: return Item::EtcItemID::CASHPOTION14+iLevel;
// case 14: return Item::EtcItemID::CASHPOTION15+iLevel;
}
}
}
}
ERRLOG0(g_Log, "드랍할 캐쉬아이템을 결정하지 못하였습니다.");
return 0;//Item::EtcItemID::OBLIVION_STONE;
}
unsigned long CAward::GetAwardLottery(void)
{
if (false == CServerSetup::GetInstance().GetLotteryEvent())
{
ERRLOG0(g_Log, "복권 이벤트를 하고 있지 않은데, 복권 드랍을 요청하였습니다.");
return 0;
}
return CGameEventMgr::GetInstance().GetLotteryEvent().GetLottery();
}
unsigned short CAward::SelectItemByRace(Item::EquipType::OptionType eOptionType,
const unsigned char* aryItemType, unsigned char cMaxItemType, unsigned char cLevel)
{
unsigned char aryShuffleList[UCHAR_MAX] = { 0, };
std::copy(aryItemType, aryItemType + cMaxItemType, aryShuffleList);
std::random_shuffle(aryShuffleList, aryShuffleList + cMaxItemType);
unsigned short wItemID = 0;
for (unsigned char cIndex = 0; cIndex < cMaxItemType; ++cIndex)
{
Item::ItemType::Type eItemType = static_cast<Item::ItemType::Type>(aryShuffleList[cIndex]);
if (true == Item::CItemType::GetInstance().IsCorrectOptionType(eOptionType, eItemType))
{
wItemID = Item::CItemMgr::GetInstance().GetDropItem(eItemType, cLevel);
if (0 != wItemID)
{
break;
}
}
}
return wItemID;
}