#include "stdafx.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "AggresiveCreature.h" #include "CreatureManager.h" #include "Threat.h" #include #include #include #include struct CompareAmount { int operator() (const CThreat::ThreatInfo& ThreatInfo1, const CThreat::ThreatInfo& ThreatInfo2) { return ThreatInfo1.m_lThreatAmount < ThreatInfo2.m_lThreatAmount; } }; struct CompareLevel { int operator() (const CThreat::ThreatInfo& ThreatInfo1, const CThreat::ThreatInfo& ThreatInfo2) { return ThreatInfo1.m_pCreature->GetStatus().m_nLevel < ThreatInfo2.m_pCreature->GetStatus().m_nLevel; } }; struct CompareFame { int operator() (const CThreat::ThreatInfo& ThreatInfo1, const CThreat::ThreatInfo& ThreatInfo2) { return ThreatInfo1.m_pCreature->GetFame() < ThreatInfo2.m_pCreature->GetFame(); } }; CThreat::CThreat(void) : m_pOwner(NULL) { ClearAll(); } CThreat::~CThreat(void) { } void CThreat::ClearAll(void) { m_cMaxLevel = 0; m_eMaxLevelCreatureType = Creature::CT_NONE_TYPE; ClearThreatList(); ClearThreatenedList(); } void CThreat::ClearThreatList(void) { for (ThreatList::iterator ThreatIt = m_ThreatList.begin(), ThreatEnd = m_ThreatList.end(); ThreatIt != ThreatEnd; ++ThreatIt) { ThreatIt->m_pCreature->GetThreat().DeleteThreatened(m_pOwner); } m_ThreatList.clear(); } void CThreat::ClearThreatenedList(void) { for (ThreatenedList::iterator ThreatenedIt = m_ThreatenedList.begin(), ThreatenedEnd = m_ThreatenedList.end(); ThreatenedIt != ThreatenedEnd; ++ThreatenedIt) { (*ThreatenedIt)->GetThreat().DeleteThreat(m_pOwner); } m_ThreatenedList.clear(); } /////////////////////////////////////////////////////////////////////////////////// // Function : CThreat::AddToThreatList // // Description : ¾²·¹Æ® ¸®½ºÆ®¿¡ Å©¸®ÃÄ Ãß°¡ // // Inputs : pAttackCreature - Ãß°¡ÇÒ Å©¸®ÃÄÀÇ Æ÷ÀÎÅÍ // lThreatAmount - ¾²·¹Æ®·® // // Outputs : None. // // Returns : None. /////////////////////////////////////////////////////////////////////////////////// void CThreat::AddToThreatList(CAggresiveCreature* pAttackCreature, long lThreatAmount) { if (NULL == pAttackCreature || 0 == lThreatAmount) { return; } if (EnemyCheck::EC_ENEMY != m_pOwner->IsEnemy(pAttackCreature)) { return; } // ÀÌ¹Ì ¸®½ºÆ®¿¡ ÀÖ´Â ³à¼®ÀÇ Ã³¸® for (ThreatList::iterator it = m_ThreatList.begin(); it != m_ThreatList.end(); ++it) { if (pAttackCreature == it->m_pCreature) { it->m_lThreatAmount += lThreatAmount; if (0 >= it->m_lThreatAmount) { pAttackCreature->GetThreat().DeleteThreatened(m_pOwner); DeleteThreat(pAttackCreature); } m_ThreatList.sort(CompareAmount()); return; } } // óÀ½ ¸®½ºÆ®¿¡ µé¾î¿Â ³à¼®ÀÇ Ã³¸® if (0 > lThreatAmount) { return; } size_t nThreatListSize = m_ThreatList.size(); if (nThreatListSize > MAX_THREAT_TARGET) { ERRLOG2(g_Log, "CID:0x%08x ¾²·¹Æ® ¸®½ºÆ® »çÀÌÁî°¡ ÃÖ´ëÄ¡¸¦ ³Ñ¾î¼¹½À´Ï´Ù. Size:%d", m_pOwner->GetCID(), nThreatListSize); return; } else if (nThreatListSize == MAX_THREAT_TARGET) { ThreatInfo& MinThreatInfo = m_ThreatList.front(); if (lThreatAmount < MinThreatInfo.m_lThreatAmount) { return; } MinThreatInfo.m_pCreature->GetThreat().DeleteThreatened(m_pOwner); m_ThreatList.pop_front(); } if (pAttackCreature->GetStatus().m_nLevel > m_cMaxLevel) { m_cMaxLevel = pAttackCreature->GetStatus().m_nLevel; m_eMaxLevelCreatureType = Creature::GetCreatureType(pAttackCreature->GetCID()); } pAttackCreature->GetThreat().AddToThreatenedList(m_pOwner); m_ThreatList.push_front(ThreatInfo(pAttackCreature, lThreatAmount)); m_ThreatList.sort(CompareAmount()); } /////////////////////////////////////////////////////////////////////////////////// // Function : CThreat::AddToThreatenedList // // Description : »óÈ£ÂüÁ¶¸¦ À§ÇÑ ¸®½ºÆ®¿¡ Å©¸®ÃÄ Ãß°¡ // // Inputs : pDefendCreature - Ãß°¡ÇÒ Å©¸®ÃÄÀÇ Æ÷ÀÎÅÍ // // Outputs : None. // // Returns : None. /////////////////////////////////////////////////////////////////////////////////// void CThreat::AddToThreatenedList(CAggresiveCreature* pDefendCreature) { ThreatenedList::iterator FindIt = std::find(m_ThreatenedList.begin(), m_ThreatenedList.end(), pDefendCreature); if (FindIt == m_ThreatenedList.end()) { // ThreatenedList¿¡ ¾øÀ» ¶§¸¸ »ðÀÔ. m_ThreatenedList.push_back(pDefendCreature); } } /////////////////////////////////////////////////////////////////////////////////// // Function : CThreat::HealThreat // // Description : 'Heal Threat'ÀÇ Àû¿ë // // Inputs : pHealCreature - µµ¿òÀ» ÁØ Å©¸®ÃÄ // lThreatAmount - µµ¿ò·® // // Outputs : None. // // Returns : None. /////////////////////////////////////////////////////////////////////////////////// class CAddToThreatList { public: CAddToThreatList(CAggresiveCreature* lpAggresiveCreature, long lThreatAmount) : m_lpAdd(lpAggresiveCreature), m_nAmount(lThreatAmount) { } void operator () (CAggresiveCreature* lpAdded) { if (NULL != lpAdded) { lpAdded->GetThreat().AddToThreatList(m_lpAdd, m_nAmount); } } private: CAggresiveCreature* m_lpAdd; int m_nAmount; }; void CThreat::HealThreat(CAggresiveCreature* pHealCreature, long lThreatAmount) { const int MAX_HEAL_THREATEN_NUM = 30; CAggresiveCreature* lpHealThreaten[MAX_HEAL_THREATEN_NUM]; CAggresiveCreature** lpDestination = lpHealThreaten; unsigned long nCount = 0; for (ThreatenedList::iterator first = m_ThreatenedList.begin(), last = m_ThreatenedList.end(); first != last && nCount < MAX_HEAL_THREATEN_NUM; ++lpDestination, ++nCount, ++first) { *lpDestination = *first; } std::for_each(lpHealThreaten, lpDestination, CAddToThreatList(pHealCreature, lThreatAmount)); } /////////////////////////////////////////////////////////////////////////////////// // Function : CThreat::AffectThreat // // Description : ¾²·¹Æ®°ª¿¡ ¿µÇâÀ» Áִ Ÿ¿îÆ®, µðŸ¿îÆ®¿¡ °üÇÑ °è»ê. // // Inputs : pTauntCreature - Ÿ¿îÆ®ÇÑ Å©¸®ÃÄ // lThreatAmount - Ÿ¿îÆ®·® // eType - Ÿ¿îÆ®/µðŸ¿îÆ® ±¸ºÐ // // Outputs : None. // // Returns : None. /////////////////////////////////////////////////////////////////////////////////// void CThreat::AffectThreat(CAggresiveCreature* pTauntCreature, long lDamage, AffectThreatType eType) { // °áÁ¤Å¸´Â ¾²·¹Æ®¿¡ ¿µÇâÀ» ÁÖÁö ¾Ê´Â´Ù. if (m_pOwner->GetStatus().m_nNowHP <= lDamage) { return; } const long lThreatAmount = lDamage * ((eType == TAUNT) ? 1 : (-1)); unsigned short wThreatNum = 0; for (ThreatList::iterator it = m_ThreatList.begin(); it != m_ThreatList.end(); ++it) { ThreatInfo& threatInfo = *it; threatInfo.m_lThreatAmount = (threatInfo.m_lThreatAmount > lThreatAmount) ? (threatInfo.m_lThreatAmount - lThreatAmount) : 0; ++wThreatNum; } if (wThreatNum > MAX_THREAT_TARGET || wThreatNum < 0) { ERRLOG1(g_Log, "Ÿ¿îÆ®ÇÏ´Â ¸ó½ºÅÍÀÇ ¾²·¹Æ® ¸®½ºÆ®°¡ ÀÌ»óÇÕ´Ï´Ù. ¸®½ºÆ® »çÀÌÁî : %d", wThreatNum); } AddToThreatList(pTauntCreature, lThreatAmount * wThreatNum); } /////////////////////////////////////////////////////////////////////////////////// // Function : CThreat::DeleteThreatened // // Description : »óÈ£ÂüÁ¶¸¦ À§ÇÑ ¸®½ºÆ®¿¡¼­ Å©¸®Ãĸ¦ »èÁ¦ // // Inputs : pDefendCreature - »èÁ¦ÇÒ Å©¸®ÃÄÀÇ Æ÷ÀÎÅÍ // // Outputs : None. // // Returns : None. /////////////////////////////////////////////////////////////////////////////////// bool CThreat::DeleteThreatened(CAggresiveCreature* pDefendCreature) { ThreatenedList::iterator FindIt = std::find(m_ThreatenedList.begin(), m_ThreatenedList.end(), pDefendCreature); if (FindIt == m_ThreatenedList.end()) { return false; } m_ThreatenedList.erase(FindIt); return true; } /////////////////////////////////////////////////////////////////////////////////// // Function : CThreat::DeleteThreat // // Description : ¾²·¹Æ® ¸®½ºÆ®¿¡¼­ Å©¸®Ãĸ¦ »èÁ¦ // // Inputs : pAttackCreature - »èÁ¦ÇÒ Å©¸®ÃÄÀÇ Æ÷ÀÎÅÍ // // Outputs : None. // // Returns : None. /////////////////////////////////////////////////////////////////////////////////// bool CThreat::DeleteThreat(CAggresiveCreature* pAttackCreature) { for (ThreatList::iterator it = m_ThreatList.begin(); it != m_ThreatList.end(); ++it) { if (pAttackCreature == it->m_pCreature) { m_ThreatList.erase(it); return true; } } return false; } /////////////////////////////////////////////////////////////////////////////////// // Function : CThreat::GetTarget // // Description : ¾²·¹Æ® ¸®½ºÆ®¸¦ °Ë»öÇØ Ÿ°ÙÀ» ±¸ÇÑ´Ù. // // Inputs : None. // // Outputs : None. // // Returns : CAggresiveCreature* - Ÿ°Ù Å©¸®ÃÄ /////////////////////////////////////////////////////////////////////////////////// CAggresiveCreature* CThreat::GetTarget(void) { if (true == m_ThreatList.empty()) { return NULL; } Creature::CreatureType eCreatureType = Creature::GetCreatureType(m_pOwner->GetCID()); if (Creature::CT_MONSTER == eCreatureType || Creature::CT_SUMMON == eCreatureType || Creature::CT_STRUCT == eCreatureType) { CMonster* lpMonster = reinterpret_cast(m_pOwner); ThreatList TargetThreatList; ThreatInfo TempTargetInfo; for (ThreatList::iterator it = m_ThreatList.begin(); it != m_ThreatList.end(); ++it) { TempTargetInfo = *it; if (NULL == TempTargetInfo.m_pCreature) { continue; } if (true == TempTargetInfo.m_pCreature->GetEnchantInfo().GetFlag(Skill::SpellID::Stealth)) { continue; } if (EnemyCheck::EC_ENEMY != m_pOwner->IsEnemy(TempTargetInfo.m_pCreature)) { continue; } const float fAttackRange = lpMonster->GetAttackRange() / 100.0f; MotionInfo Motion; lpMonster->GetMotion(MonsterInfo::Z3D_CA_WALK, Motion); const float fMovingAttackRange = fAttackRange + Motion.m_fVelocity; const float fDX = TempTargetInfo.m_pCreature->GetCurrentPos().m_fPointX - m_pOwner->GetCurrentPos().m_fPointX; const float fDZ = TempTargetInfo.m_pCreature->GetCurrentPos().m_fPointZ - m_pOwner->GetCurrentPos().m_fPointZ; const float fDistance = sqrtf((fDX * fDX) + (fDZ * fDZ)); if (fDistance < fAttackRange) { TempTargetInfo.m_lThreatAmount *= ATTACK_TAUNT_RATE; } else if (fDistance < fMovingAttackRange) { TempTargetInfo.m_lThreatAmount *= MOVING_ATTACK_TAUNT_RATE; } TargetThreatList.push_back(TempTargetInfo); } if (true == TargetThreatList.empty()) { return NULL; } TargetThreatList.sort(CompareAmount()); return TargetThreatList.back().m_pCreature; } else if (Creature::CT_SIEGE_OBJECT == eCreatureType) { CSiegeObject* lpSiegeObject = reinterpret_cast(m_pOwner); if (!lpSiegeObject) { ERRLOG1(g_Log, "CID:0x%08x °ø°Ý ´ë»óÀ» ã´Â °ø¼º ¿ÀºêÁ§Æ®°¡ Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù.", m_pOwner->GetCID()); return NULL; } if (!lpSiegeObject->IsGuard() && !lpSiegeObject->IsEmblem() && !lpSiegeObject->IsCamp()) { ERRLOG2(g_Log, "CID:0x%08x wObjectType:%d °ø°Ý ´ë»óÀ» ã´Â °ø¼º ¿ÀºêÁ§Æ®°¡ °¡µå, »ó¡¹°, ¿ä»õ°¡ ¾Æ´Õ´Ï´Ù.", m_pOwner->GetCID(), lpSiegeObject->GetObjectType()); return NULL; } ThreatList TargetThreatList; ThreatInfo TempTargetInfo; for (ThreatList::iterator it = m_ThreatList.begin(); it != m_ThreatList.end(); ++it) { TempTargetInfo = *it; if (NULL == TempTargetInfo.m_pCreature) { continue; } if (true == TempTargetInfo.m_pCreature->GetEnchantInfo().GetFlag(Skill::SpellID::Stealth)) { continue; } if (EnemyCheck::EC_ENEMY != m_pOwner->IsEnemy(TempTargetInfo.m_pCreature)) { continue; } TargetThreatList.push_back(TempTargetInfo); } if (true == TargetThreatList.empty()) { return NULL; } TargetThreatList.sort(CompareAmount()); return TargetThreatList.back().m_pCreature; } ERRLOG1(g_Log, "CID:0x%08x ¸ó½ºÅÍ È¤Àº °¡µå, ¼º »ó¡¹°, ¿ä»õ°¡ ¾Æ´Ñ ³à¼®ÀÌ °ø°Ý Ÿ°ÙÀ» ã½À´Ï´Ù.", m_pOwner->GetCID()); return NULL; } /////////////////////////////////////////////////////////////////////////////////// // Function : CThreat::GetAggravation // // Description : ·¹º§°¸ ¾ò±â (°æÇèÄ¡ ºÐ¹è¿ë) // // Inputs : pCreature - ºñ±³ÇÒ Å©¸®ÃÄ // // Outputs : None. // // Returns : float - ·¹º§°¸ /////////////////////////////////////////////////////////////////////////////////// float CThreat::GetAggravation(CAggresiveCreature* pCreature) { static const float aryAggravation[CAggresiveCreature::AGGRAVATION_NUM] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.05f, 1.1f, 1.15f, 1.2f, 1.25f, 1.3f, 1.35f, 1.4f, 1.45f, 1.5f, 1.55f, 1.6f, 1.65f, 1.7f, 1.75f, 1.8f, 1.85f, 1.9f, 1.95f, 2.0f, }; const int nLevelDifference = m_pOwner->CalculateLevelGap(pCreature); return aryAggravation[nLevelDifference + CAggresiveCreature::MAX_LEVEL_GAP]; } unsigned char CThreat::GetAward(unsigned long* aryItemID, Item::CItem** aryItem, unsigned long* dwOwnerID) { if (true == m_ThreatList.empty()) { return 0; } if (Creature::CT_MONSTER != Creature::GetCreatureType(m_pOwner->GetCID())) { return 0; } if (Creature::CT_PC != m_eMaxLevelCreatureType && Creature::CT_SUMMON != m_eMaxLevelCreatureType) { // ¾²·¹Æ® ¸®½ºÆ®¿¡ µé¾îÀÖ´Â Å©¸®ÃÄ Áß °¡Àå ·¹º§ÀÌ ³ôÀº Å©¸®Ãİ¡ // 'Ç÷¹À̾î'³ª '¼Òȯ¼ö'ÀÎ °æ¿ì¿¡¸¸ ¾ÆÀÌÅÛÀ» µå¶øÇÑ´Ù. return 0; } int nRandPoint = 0; int nGradeSpace = 0; int nLevelDifferenceForArray = 0; // ¸ó½ºÅÍÀÇ ·¹º§°ú À¯ÀúÀÇ ÃÖ´ë·¹º§À» ºñ±³ÇØ ±×Â÷À̸¦ ±¸ÇÑ´Ù. const int nLevelDifference = m_pOwner->CalculateLevelGap(m_pOwner->GetStatus().m_nLevel, m_cMaxLevel); // ·¹º§°¸+20 À»ÇØÁØ´Ù. nLevelDifferenceForArray = nLevelDifference + CAggresiveCreature::MAX_LEVEL_GAP; ThreatInfo HighestThreatInfo = m_ThreatList.back(); if (NULL == HighestThreatInfo.m_pCreature) { ERRLOG0(g_Log, "¾²·¹Æ® ¸®½ºÆ®ÀÇ Å¾¿¡ Å©¸®ÃÄ Æ÷ÀÎÅͰ¡ ¾ø½À´Ï´Ù."); return 0; } CMonster* lpMonster = reinterpret_cast(m_pOwner); CCharacter* lpCharacter = NULL; float fPt = 1.0f; switch (Creature::GetCreatureType(HighestThreatInfo.m_pCreature->GetCID())) { case Creature::CT_PC: lpCharacter = reinterpret_cast(HighestThreatInfo.m_pCreature); break; case Creature::CT_SUMMON: lpCharacter = reinterpret_cast(HighestThreatInfo.m_pCreature)->GetMaster(); break; default: return 0; } // ÆÛ¼¾Æ®°¡ 0ÀÌ¸é ¾Æ¹«°Íµµ ¸ø±¸ÇÑ´Ù. ±×³É ¸®ÅÏ fPt = lpCharacter->GetAwardPer(); if(fPt == 0.0f) return 0; bool bPremiumTime = lpCharacter->CheckPremiumTime(); *dwOwnerID = lpCharacter->GetCID(); // ·çÆÃ ±ÇÇÑÀ» °¡Áø ij¸¯ÅÍÀÇ ÆÄƼ¿ø Áß¿¡, ÀüÅõ¿¡ Âü¿©Çß°í 'Çà¿îÀÇ ¿Àºê'¸¦ »ç¿ëÇß´Ù¸é µå¶ø·ü¿¡ ¿µÇâÀ» ÁØ´Ù. bool bLuckyOrb = false; if (NULL != lpCharacter->GetParty()) { for (ThreatList::iterator it = m_ThreatList.begin(); it != m_ThreatList.end(); ++it) { if (it->m_pCreature->GetParty() == lpCharacter->GetParty()) { if (true == it->m_pCreature->GetEnchantInfo().GetFlag(Skill::SpellID::LuckyOrb)) { bLuckyOrb = true; break; } } } } float fAddDropPt = 0.0f; // 'Çà¿îÀÇ ¿Àºê' »ç¿ë½Ã if (true == bLuckyOrb) { fAddDropPt += 0.3f; } // ÇÁ¸®¹Ì¾ö ¼­ºñ½º if(bPremiumTime) { fAddDropPt += lpCharacter->GetPremiumPt(); } // 'ºÎÀÇ ¼®»ó' »ç¿ë½Ã. if (true == lpCharacter->GetEnchantInfo().GetFlag(Skill::SpellID::WealthStatue)) { unsigned short wLevel = lpCharacter->GetEnchantLevel(Skill::SpellID::WealthStatue); fAddDropPt += (wLevel * 0.01f); } // ¸ó½ºÅÍÀÇµå¶ø È®À²À» ´õÇÑ´Ù. unsigned char cItemKindIndex = 0; int nTotalRate = 0; for (cItemKindIndex = 0; cItemKindIndex < MonsterInfo::MAX_AWARD_KIND; ++cItemKindIndex) { // ½ºÅ©¸³Æ®¿¡ Á¤ÀÇµÈ ¾ÆÀÌÅÛº° µå¶ø¼öÄ¡¸¦ ¸ðµÎ ÇÕÇÑ´Ù. nTotalRate += lpMonster->GetDropRate(cItemKindIndex); } // ÇÒ·ÎÀ© À̺¥Æ®¿ë ¹× °Ô´õ ¿ÀºêÁ§Æ®¿ë (°Ô´õµµ ÃÖ´ë 3°³±îÁö ¶³±º´Ù) int MonID = lpMonster->GetKID(); int MonDropMax = 1+Math::Random::ComplexRandom(2); bool bAllInOne = false; if(3006 <= MonID && MonID <= 3009) bAllInOne = true; else if(3101 <= MonID && MonID <= 3500) bAllInOne = true; // °Ô´õ ¿ÀºêÁ§Æ® int nDropItemIndex = 0, nDropItemNum = 0; for (; nDropItemIndex < AwardTable::MAX_DROP_ITEM + EliteBonus::MAX_BONUS_DROP_ITEM; ++nDropItemIndex) { aryItemID[nDropItemNum] = 0; unsigned short wDropRate = 0; if (nDropItemIndex < AwardTable::MAX_DROP_ITEM) { wDropRate = AwardTable::aryItemDropRate[nLevelDifferenceForArray][nDropItemIndex]; } else { // ¼­¹ö ¿¤¸®Æ® º¸³Ê½º¿¡ ÀÇÇÑ Ãß°¡ µå¶ø·ü char eliteBonus = lpCharacter->GetEliteBonus(); if (0 < eliteBonus) { wDropRate = EliteBonus::usBonusItemDropRate[eliteBonus - 1][nDropItemIndex - AwardTable::MAX_DROP_ITEM]; } } // Ãß°¡µå¶øÀ² Ãß°¡. if(fAddDropPt > 0.0f) { wDropRate += static_cast(wDropRate * fAddDropPt); } wDropRate = (unsigned short)(wDropRate*(CServerSetup::GetInstance().GetDropDefault() / 100.0f)*fPt); // fPt¸¦ °öÇØÁØ ÀÌÀ¯´Â fPt °ª¿¡ µû¶ó µå¶øÀ²ÀÌ ´Þ¶óÁø´Ù. // CServerSetup::GetInstance().GetDropDefault() = 100 ÀÓ. // if (!bAllInOne && Math::Random::ComplexRandom(1000) > wDropRate) { continue; } // ¸¸¾à ÃÑ µå¶ø¼öÄ¡°¡ 10¸¸À̸é 10¸¸À» °¡Áö°í µå¶øÀ» ½ÃŲ´Ù. nRandPoint = Math::Random::ComplexRandom(nTotalRate); for (cItemKindIndex = 0; cItemKindIndex < MonsterInfo::MAX_AWARD_KIND; ++cItemKindIndex) { // µå¶øÇÏÁö ¾Ê´Â ¾ÆÀÌÅÛÁ¾·ù¸é ¸®ÅÏ int nDropRate = lpMonster->GetDropRate(cItemKindIndex); if (0 == nDropRate) { continue; } // ¾ÆÀÌÅÛÀ» ¸ðµÎ µ·´Ù. // °¢ ¾ÆÀÌÅÛÀÇ µå¶øÀ²À» ´õÇØÁØ´Ù. nGradeSpace += nDropRate; // ·£´ýÀ¸·Î ³ª¿Â °ªº¸´Ù. ´õÇØÁØ ¾ÆÀÌÅÛÀÇ µå¶ø¼öÄ¡°¡ ´õ ³ôÀ¸¸é // µå¶øÀ» ÇÑ´Ù. if (nGradeSpace > nRandPoint) { aryItemID[nDropItemNum] = AwardTable::CAward::GetInstance().GetAward( cItemKindIndex, reinterpret_cast(m_pOwner), lpCharacter, aryItem + nDropItemNum); if (0 == aryItemID[nDropItemNum]) { CMonster* pMon = reinterpret_cast(m_pOwner); if(pMon) ERRLOG2(g_Log, "¶³¾îÁú ¾ÆÀÌÅÛÀÌ °áÁ¤µÇÁö ¾Ê¾Ò½À´Ï´Ù. ¸ó½ºÅÍKID : %d, Á¾·ù : %d", pMon->GetKID(), cItemKindIndex); } else { ++nDropItemNum; } // ÃʱâÈ­. cItemKindIndex = MonsterInfo::MAX_AWARD_KIND; nGradeSpace = 0; } // ÇÒ·ÎÀ© À̺¥Æ®. 3000~3005 // º¸¼®»óÀÚ À̺¥Æ®. 3006~3010 if(3001 <= MonID && MonID <= 3010) { // 3006 ¹øºÎÅÍ 3009¹ø±îÁö´Â º¸¼®»óÀÚ // ¹«Á¶°Ç 1°³¸¸ ¶³±¸°Ô ¼öÁ¤ if(3006 <= MonID && MonID <= 3010 && nDropItemNum >= 1) return nDropItemNum; if(MonID == 3003 && nDropItemNum >= 1) return nDropItemNum; if(nDropItemNum >= MonDropMax) return nDropItemNum; } // °Ô´õ ¿ÀºêÁ§Æ® if(3101 <= MonID && MonID <= 3500) { if(nDropItemNum >= MonDropMax) return nDropItemNum; } } } // ÇÒ·ÎÀ© À̺¥Æ®. 3000~3005 // º¸¼®»óÀÚ À̺¥Æ®. 3006~3010 if(0 == nDropItemNum && 3001 <= MonID && MonID <= 3010) { // cItemKindIndex ¸¦ 0À¸·Î ÇÏ´Â ÀÌÀ¯´Â ÀâÅÆ A¸¦ ±âº»ÀûÀ¸·Î ¶³±¸°Ô Çϱâ À§Çؼ­ÀÌ´Ù. cItemKindIndex = 0; // ½ÇÆÐÇÑ µÚ¿¡ ÀâÅÆA¸¦ ¶³¾î¶ß¸®°Ô Çߴµ¥ ÀÌ ÀâÅÛA°¡ 0 Áï ¾ø´Â ¾ÆÀÌÅÛÀ̸é // ÀÌ°Ç ¾Æ¹«°Íµµ ¶³±¸Áö ¾Ê´Â Àâ¸÷À̶ó´Â¶æ. // µå¶øÇÏÁö ¾Ê´Â ¾ÆÀÌÅÛÁ¾·ù¸é ¸®ÅÏ int nDropRate = lpMonster->GetDropRate(cItemKindIndex); if (0 == nDropRate) return 0; // ¹«Á¶°Ç µå¶øÇÏ´Â À̺¥Æ®Àε¥ ÇѰ³µµ ¶³±¸Áö ¾Ê¾ÒÀ¸¸é aryItemID[nDropItemNum] = AwardTable::CAward::GetInstance().GetAward( cItemKindIndex, reinterpret_cast(m_pOwner), lpCharacter, aryItem + nDropItemNum); if (0 == aryItemID[nDropItemNum]) { CMonster* pMon = reinterpret_cast(m_pOwner); if(pMon) ERRLOG2(g_Log, "¶³¾îÁú ¾ÆÀÌÅÛÀÌ °áÁ¤µÇÁö ¾Ê¾Ò½À´Ï´Ù. ¸ó½ºÅÍKID : %d, Á¾·ù : %d", pMon->GetKID(), cItemKindIndex); return 0; } ++nDropItemNum; } return nDropItemNum; } /////////////////////////////////////////////////////////////////////////////////// // Function : CThreat::DivisionExp // // Description : °æÇèÄ¡ ºÐ¹è // // Inputs : None. // // Outputs : None. // // Returns : None. /////////////////////////////////////////////////////////////////////////////////// void CThreat::DivisionExp(void) { if (true == m_ThreatList.empty()) { ERRLOG0(g_Log, "½º·¹Æ® ¸®½ºÆ®°¡ ºñ¾î ÀÖ½À´Ï´Ù. ÀÌ »óÅ¿¡¼­´Â Exp¸¦ ³ª´­ ¼ö ¾ø½À´Ï´Ù."); return; } if (NULL == m_pOwner) { ERRLOG0(g_Log, "¼ÒÀ¯ÀÚ°¡ NULLÀÔ´Ï´Ù."); return; } unsigned long lSumOfThreatAmount = 0; for (ThreatList::iterator it = m_ThreatList.begin(); it != m_ThreatList.end(); ++it) { lSumOfThreatAmount += it->m_lThreatAmount; } // ¾²·¹Æ® ¸®½ºÆ®¿¡ ÀÖ´Â ³à¼®µéÀÇ °³º°ÀûÀÎ °æÇèÄ¡ °è»ê AwardInfo aryIndividualAwardInfo[MAX_THREAT_TARGET]; CAggresiveCreature* pHighestThreatCreature = m_ThreatList.back().m_pCreature; const unsigned char cHighestLevel = pHighestThreatCreature->GetStatus().m_nLevel; int nNumber = 0; for (ThreatList::iterator it = m_ThreatList.begin(); it != m_ThreatList.end() && nNumber < MAX_THREAT_TARGET; ++it, ++nNumber) { if (nNumber >= MAX_THREAT_TARGET) { ERRLOG1(g_Log, "½º·¹Æ® ¸®½ºÆ®¿¡¼­, µé¾î ÀÖ´Â ¸â¹öÀÇ ¼ö°¡ ÀÌ»óÇÕ´Ï´Ù. ¸â¹öÀÇ ¼ö´Â %dÀÔ´Ï´Ù.", nNumber); break; } const ThreatInfo& tempThreatInfo = *it; aryIndividualAwardInfo[nNumber].m_pCreature = tempThreatInfo.m_pCreature; aryIndividualAwardInfo[nNumber].m_pParty = tempThreatInfo.m_pCreature->GetParty(); aryIndividualAwardInfo[nNumber].m_lAward = static_cast(m_pOwner->GetStatus().m_nExp * tempThreatInfo.m_lThreatAmount / std::max(static_cast(lSumOfThreatAmount), static_cast(m_pOwner->GetStatus().m_StatusInfo.m_nMaxHP))); const int nIndividualLevel = aryIndividualAwardInfo[nNumber].m_pCreature->GetStatus().m_nLevel; if (::abs(cHighestLevel - nIndividualLevel) > EXP_CONSENT_GAP) { aryIndividualAwardInfo[nNumber].m_lAward = 1; } } // ¼Òȯ¼öÀÇ °æÇèÄ¡´Â ¸¶½ºÅÍ¿¡°Ô ÇÕÃÄÁØ´Ù. for (int nSummoneeIndex = 0; nSummoneeIndex < nNumber; ++nSummoneeIndex) { unsigned long dwCID = aryIndividualAwardInfo[nSummoneeIndex].m_pCreature->GetCID(); CAggresiveCreature* lpMaster = NULL; bool bSummonee = false; if (0 != aryIndividualAwardInfo[nSummoneeIndex].m_pCreature->GetMapIndex()) { VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea( aryIndividualAwardInfo[nSummoneeIndex].m_pCreature->GetMapIndex()); if (NULL != lpVirtualArea) { CVirtualMonsterMgr* lpVirtualMonsterMgr = lpVirtualArea->GetMonsterManager(); if (NULL != lpVirtualMonsterMgr && true == lpVirtualMonsterMgr->IsSummonee(dwCID)) { lpMaster = reinterpret_cast( aryIndividualAwardInfo[nSummoneeIndex].m_pCreature)->GetMaster(); bSummonee = true; } } } else { if (true == CCreatureManager::GetInstance().IsSummonee(dwCID)) { lpMaster = reinterpret_cast( aryIndividualAwardInfo[nSummoneeIndex].m_pCreature)->GetMaster(); bSummonee = true; } } if (true == bSummonee) { if (NULL != lpMaster) { if (pHighestThreatCreature == aryIndividualAwardInfo[nSummoneeIndex].m_pCreature) { pHighestThreatCreature = lpMaster; } int nMasterIndex = 0; for (; nMasterIndex < nNumber; ++nMasterIndex) { if (aryIndividualAwardInfo[nMasterIndex].m_pCreature == lpMaster) { aryIndividualAwardInfo[nMasterIndex].m_lAward += aryIndividualAwardInfo[nSummoneeIndex].m_lAward; aryIndividualAwardInfo[nSummoneeIndex] = AwardInfo(); break; } } if (nMasterIndex == nNumber) { aryIndividualAwardInfo[nSummoneeIndex].m_pCreature = lpMaster; aryIndividualAwardInfo[nSummoneeIndex].m_pParty = lpMaster->GetParty(); } } else { aryIndividualAwardInfo[nSummoneeIndex] = AwardInfo(); } } } // ÆÄƼ Á¤º¸¿¡ µû¶ó °æÇèÄ¡ ºÐ¹è AwardInfo aryPartyAwardInfo[MAX_THREAT_TARGET]; nNumber = 0; for (int nIndividualIndex = 0; nIndividualIndex < MAX_THREAT_TARGET; ++nIndividualIndex) { if (NULL == aryIndividualAwardInfo[nIndividualIndex].m_pCreature) { continue; } // ¸ó½ºÅÍ´Â °æÇèÄ¡ ºÐ¹è¿¡¼­ Á¦¿ÜµÈ´Ù. Creature::CreatureType eCreatureType = Creature::GetCreatureType(aryIndividualAwardInfo[nIndividualIndex].m_pCreature->GetCID()); if (Creature::CT_MONSTER == eCreatureType || Creature::CT_STRUCT == eCreatureType) { continue; } bool newParty = true; for (int nPartyIndex = 0; nPartyIndex < nNumber; ++nPartyIndex) { if (NULL != aryPartyAwardInfo[nPartyIndex].m_pParty) { if (aryPartyAwardInfo[nPartyIndex].m_pParty == aryIndividualAwardInfo[nIndividualIndex].m_pParty) { aryPartyAwardInfo[nPartyIndex].m_lAward += aryIndividualAwardInfo[nIndividualIndex].m_lAward; newParty = false; break; } } } if (true == newParty) { aryPartyAwardInfo[nNumber] = aryIndividualAwardInfo[nIndividualIndex]; if (++nNumber > MAX_THREAT_TARGET) { ERRLOG1(g_Log, "½º·¹Æ® ¸®½ºÆ®¿¡¼­, µé¾î ÀÖ´Â ¸â¹öÀÇ ¼ö°¡ ÀÌ»óÇÕ´Ï´Ù. ¸â¹öÀÇ ¼ö´Â %dÀÔ´Ï´Ù.", nNumber); } } } // °æÇèÄ¡·®¿¡ µû¶ó Á¤·ÄÇØ¼­ MAX_THREAT_REWARD ¸¸Å­¸¸ ³ª´²ÁØ´Ù. for (int nPartyIndex = 0; nPartyIndex < MAX_THREAT_REWARD; ++nPartyIndex) { for (int nCompareIndex = nPartyIndex + 1; nCompareIndex < nNumber; ++nCompareIndex) { if (aryPartyAwardInfo[nPartyIndex].m_lAward < aryPartyAwardInfo[nCompareIndex].m_lAward) { std::swap(aryPartyAwardInfo[nPartyIndex], aryPartyAwardInfo[nCompareIndex]); } } if (NULL == aryPartyAwardInfo[nPartyIndex].m_pCreature) { break; } long lIndividualExp = aryPartyAwardInfo[nPartyIndex].m_lAward; // ÆÄƼ if (NULL != aryPartyAwardInfo[nPartyIndex].m_pParty) { reinterpret_cast(aryPartyAwardInfo[nPartyIndex].m_pParty)->SendDivisionExp( reinterpret_cast(aryPartyAwardInfo[nPartyIndex].m_pCreature), m_pOwner, lIndividualExp, cHighestLevel); } // °³ÀÎ else { CCharacter *lpCharacter = reinterpret_cast(aryPartyAwardInfo[nPartyIndex].m_pCreature); lIndividualExp = static_cast(lIndividualExp * GetAggravation(lpCharacter)); // Threat ListÀÇ 2À§ ÀÌÇÏ Ä³¸¯ÅÍÀÇ °æ¿ì Àý¹Ý¸¸À» ¹Þ´Â´Ù. if (pHighestThreatCreature != lpCharacter) { lIndividualExp /= 2; } lpCharacter->GetHuntingExp(m_pOwner, lIndividualExp, 1); } } } bool CThreat::SaveEnemy(unsigned long dwCID) { int nOldestIndex = 0; int nLoopIndex = 0; const unsigned long dwLastTickCount = ::GetTickCount(); for (nLoopIndex = 0; nLoopIndex < SaveEnemyInfo::MAX_SAVING_ENEMY; ++nLoopIndex) { if (0 == m_LatestEnemy[nLoopIndex].m_dwCID) { continue; } // ¹Ì±¹ÀÇ Åä³Ê¸ÕÆ® ¼­¹ö±º¿¡¼­´Â PvP½ÃÀÇ ¸í¼º ¾îºä¡ ¹æÁöÃ¥ÀÌ °­È­µÈ´Ù. const unsigned long dwSavingTicCount = SaveEnemyInfo::MAX_SAVING_TICKCOUNT; if (dwLastTickCount - m_LatestEnemy[nLoopIndex].m_dwTickCount >= dwSavingTicCount) { m_LatestEnemy[nLoopIndex] = SaveEnemyInfo(); continue; } if (dwCID == m_LatestEnemy[nLoopIndex].m_dwCID) { m_LatestEnemy[nLoopIndex].m_dwTickCount = dwLastTickCount; return true; } if (m_LatestEnemy[nLoopIndex].m_dwTickCount < m_LatestEnemy[nOldestIndex].m_dwTickCount) { nOldestIndex = nLoopIndex; } } for (nLoopIndex = 0; nLoopIndex < SaveEnemyInfo::MAX_SAVING_ENEMY; ++nLoopIndex) { if (0 == m_LatestEnemy[nLoopIndex].m_dwCID) { m_LatestEnemy[nLoopIndex].m_dwCID = dwCID; m_LatestEnemy[nLoopIndex].m_dwTickCount = dwLastTickCount; return false; } } m_LatestEnemy[nOldestIndex].m_dwCID = dwCID; m_LatestEnemy[nOldestIndex].m_dwTickCount = dwLastTickCount; return false; }