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>
1010 lines
28 KiB
C++
1010 lines
28 KiB
C++
|
||
#include "stdafx.h"
|
||
|
||
#include <Utility/Math/Math.h>
|
||
#include <Utility/Setup/ServerSetup.h>
|
||
|
||
#include <Network/Dispatch/GameClient/GameClientDispatch.h>
|
||
#include <Network/Dispatch/GameClient/SendCharEtc.h>
|
||
#include <Network/Dispatch/GameClient/SendCharLevelUp.h>
|
||
#include <Network/Packet/PacketStruct/ServerInfo.h>
|
||
#include <Network/Packet/PacketCommand.h>
|
||
|
||
#include <Community/Party/Party.h>
|
||
#include <Skill/Spell/Spell.h>
|
||
|
||
#include <Creature/Character/CharacterClass.h>
|
||
#include <Creature/Character/Character.h>
|
||
#include <Creature/Character/ExpTable.h>
|
||
#include <Creature/Monster/Monster.h>
|
||
#include <Creature/Monster/PatternMonster.h>
|
||
#include <Creature/Monster/AwardTable.h>
|
||
#include <Creature/Monster/VirtualMonsterMgr.h>
|
||
|
||
#include "AggresiveCreature.h"
|
||
#include "CreatureManager.h"
|
||
#include "Threat.h"
|
||
|
||
#include <Map/FieldMap/VirtualArea/VirtualArea.h>
|
||
#include <Map/FieldMap/VirtualArea/VirtualAreaMgr.h>
|
||
|
||
#include <Creature/Siege/SiegeConstants.h>
|
||
#include <Creature/Siege/SiegeObject.h>
|
||
|
||
|
||
|
||
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 : <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> ũ<><C5A9><EFBFBD><EFBFBD> <20>߰<EFBFBD>
|
||
//
|
||
// Inputs : pAttackCreature - <20>߰<EFBFBD><DFB0><EFBFBD> ũ<><C5A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
// lThreatAmount - <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE>
|
||
//
|
||
// 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;
|
||
}
|
||
|
||
// <20>̹<EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20>ִ<EFBFBD> <20>༮<EFBFBD><E0BCAE> ó<><C3B3>
|
||
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;
|
||
}
|
||
}
|
||
|
||
// ó<><C3B3> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>༮<EFBFBD><E0BCAE> ó<><C3B3>
|
||
if (0 > lThreatAmount)
|
||
{
|
||
return;
|
||
}
|
||
|
||
size_t nThreatListSize = m_ThreatList.size();
|
||
if (nThreatListSize > MAX_THREAT_TARGET)
|
||
{
|
||
ERRLOG2(g_Log, "CID:0x%08x <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD>ġ<EFBFBD><C4A1> <20>Ѿ<D1BE><EEBCB9><EFBFBD>ϴ<EFBFBD>. 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 : <20><>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> ũ<><C5A9><EFBFBD><EFBFBD> <20>߰<EFBFBD>
|
||
//
|
||
// Inputs : pDefendCreature - <20>߰<EFBFBD><DFB0><EFBFBD> ũ<><C5A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
//
|
||
// 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<73><74> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||
m_ThreatenedList.push_back(pDefendCreature);
|
||
}
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
// Function : CThreat::HealThreat
|
||
//
|
||
// Description : 'Heal Threat'<27><> <20><><EFBFBD><EFBFBD>
|
||
//
|
||
// Inputs : pHealCreature - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> ũ<><C5A9><EFBFBD><EFBFBD>
|
||
// lThreatAmount - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
//
|
||
// 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 : <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> Ÿ<><C5B8>Ʈ, <20><>Ÿ<EFBFBD><C5B8>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||
//
|
||
// Inputs : pTauntCreature - Ÿ<><C5B8>Ʈ<EFBFBD><C6AE> ũ<><C5A9><EFBFBD><EFBFBD>
|
||
// lThreatAmount - Ÿ<><C5B8>Ʈ<EFBFBD><C6AE>
|
||
// eType - Ÿ<><C5B8>Ʈ/<2F><>Ÿ<EFBFBD><C5B8>Ʈ <20><><EFBFBD><EFBFBD>
|
||
//
|
||
// Outputs : None.
|
||
//
|
||
// Returns : None.
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
void CThreat::AffectThreat(CAggresiveCreature* pTauntCreature, long lDamage, AffectThreatType eType)
|
||
{
|
||
// <20><><EFBFBD><EFBFBD>Ÿ<EFBFBD><C5B8> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
|
||
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, "Ÿ<EFBFBD><EFBFBD>Ʈ<EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20>̻<EFBFBD><CCBB>մϴ<D5B4>. <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> : %d", wThreatNum);
|
||
}
|
||
|
||
AddToThreatList(pTauntCreature, lThreatAmount * wThreatNum);
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
// Function : CThreat::DeleteThreatened
|
||
//
|
||
// Description : <20><>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD> ũ<><C5A9><EFBFBD>ĸ<EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
//
|
||
// Inputs : pDefendCreature - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<><C5A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
//
|
||
// 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 : <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD> ũ<><C5A9><EFBFBD>ĸ<EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
//
|
||
// Inputs : pAttackCreature - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<><C5A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
//
|
||
// 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 : <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20>˻<EFBFBD><CBBB><EFBFBD> Ÿ<><C5B8><EFBFBD><EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD>.
|
||
//
|
||
// Inputs : None.
|
||
//
|
||
// Outputs : None.
|
||
//
|
||
// Returns : CAggresiveCreature* - Ÿ<><C5B8> ũ<><C5A9><EFBFBD><EFBFBD>
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
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<CMonster *>(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<CSiegeObject*>(m_pOwner);
|
||
|
||
if (!lpSiegeObject)
|
||
{
|
||
ERRLOG1(g_Log, "CID:0x%08x <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ã<><C3A3> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʽ<EFBFBD><CABD>ϴ<EFBFBD>.", m_pOwner->GetCID());
|
||
return NULL;
|
||
}
|
||
|
||
if (!lpSiegeObject->IsGuard() && !lpSiegeObject->IsEmblem() && !lpSiegeObject->IsCamp())
|
||
{
|
||
ERRLOG2(g_Log, "CID:0x%08x wObjectType:%d <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ã<><C3A3> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD>, <20><>¡<EFBFBD><C2A1>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƴմϴ<D5B4>.",
|
||
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 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ȥ<><C8A4> <20><><EFBFBD><EFBFBD>, <20><> <20><>¡<EFBFBD><C2A1>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƴ<EFBFBD> <20>༮<EFBFBD><E0BCAE> <20><><EFBFBD><EFBFBD> Ÿ<><C5B8><EFBFBD><EFBFBD> ã<><C3A3><EFBFBD>ϴ<EFBFBD>.", m_pOwner->GetCID());
|
||
return NULL;
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
// Function : CThreat::GetAggravation
|
||
//
|
||
// Description : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD>ġ <20>й<EFBFBD><D0B9><EFBFBD>)
|
||
//
|
||
// Inputs : pCreature - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<><C5A9><EFBFBD><EFBFBD>
|
||
//
|
||
// Outputs : None.
|
||
//
|
||
// Returns : float - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
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)
|
||
{
|
||
// <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD> ũ<><C5A9><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ũ<><C5A9><EFBFBD>İ<EFBFBD>
|
||
// '<27>÷<EFBFBD><C3B7>̾<EFBFBD>'<27><> '<27><>ȯ<EFBFBD><C8AF>'<27><> <20><><EFBFBD>쿡<EFBFBD><ECBFA1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
||
return 0;
|
||
}
|
||
|
||
int nRandPoint = 0;
|
||
int nGradeSpace = 0;
|
||
int nLevelDifferenceForArray = 0;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ뷹<D6B4><EBB7B9><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD≯<EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD>.
|
||
const int nLevelDifference = m_pOwner->CalculateLevelGap(m_pOwner->GetStatus().m_nLevel, m_cMaxLevel);
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>+20 <20><><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
|
||
nLevelDifferenceForArray = nLevelDifference + CAggresiveCreature::MAX_LEVEL_GAP;
|
||
|
||
ThreatInfo HighestThreatInfo = m_ThreatList.back();
|
||
|
||
if (NULL == HighestThreatInfo.m_pCreature)
|
||
{
|
||
ERRLOG0(g_Log, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> ž<><C5BE> ũ<><C5A9><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>.");
|
||
return 0;
|
||
}
|
||
|
||
CMonster* lpMonster = reinterpret_cast<CMonster *>(m_pOwner);
|
||
CCharacter* lpCharacter = NULL;
|
||
|
||
float fPt = 1.0f;
|
||
|
||
switch (Creature::GetCreatureType(HighestThreatInfo.m_pCreature->GetCID()))
|
||
{
|
||
case Creature::CT_PC: lpCharacter = reinterpret_cast<CCharacter *>(HighestThreatInfo.m_pCreature); break;
|
||
case Creature::CT_SUMMON: lpCharacter = reinterpret_cast<CSummonMonster *>(HighestThreatInfo.m_pCreature)->GetMaster(); break;
|
||
|
||
default: return 0;
|
||
}
|
||
|
||
// <20>ۼ<EFBFBD>Ʈ<EFBFBD><C6AE> 0<≯<EFBFBD> <20>ƹ<EFBFBD><C6B9>͵<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>. <20>׳<EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
fPt = lpCharacter->GetAwardPer();
|
||
if(fPt == 0.0f)
|
||
return 0;
|
||
|
||
bool bPremiumTime = lpCharacter->CheckPremiumTime();
|
||
|
||
*dwOwnerID = lpCharacter->GetCID();
|
||
|
||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>Ƽ<EFBFBD><C6BC> <20>߿<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>߰<EFBFBD> '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>'<27><> <20><><EFBFBD><EFBFBD><EFBFBD>ߴٸ<DFB4> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ش<EFBFBD>.
|
||
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;
|
||
|
||
// '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
if (true == bLuckyOrb)
|
||
{
|
||
fAddDropPt += 0.3f;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD>̾<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
if(bPremiumTime)
|
||
{
|
||
fAddDropPt += lpCharacter->GetPremiumPt();
|
||
}
|
||
|
||
// '<27><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||
if (true == lpCharacter->GetEnchantInfo().GetFlag(Skill::SpellID::WealthStatue))
|
||
{
|
||
unsigned short wLevel = lpCharacter->GetEnchantLevel(Skill::SpellID::WealthStatue);
|
||
fAddDropPt += (wLevel * 0.01f);
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD> Ȯ<><C8AE><EFBFBD><EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD>.
|
||
unsigned char cItemKindIndex = 0;
|
||
int nTotalRate = 0;
|
||
for (cItemKindIndex = 0; cItemKindIndex < MonsterInfo::MAX_AWARD_KIND; ++cItemKindIndex)
|
||
{
|
||
// <20><>ũ<EFBFBD><C5A9>Ʈ<EFBFBD><C6AE> <20><><EFBFBD>ǵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ۺ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD>.
|
||
nTotalRate += lpMonster->GetDropRate(cItemKindIndex);
|
||
}
|
||
|
||
// <20>ҷ<EFBFBD><D2B7><EFBFBD> <20>̺<EFBFBD>Ʈ<EFBFBD><C6AE> <20><> <20>Դ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> (<28>Դ<EFBFBD><D4B4><EFBFBD> <20>ִ<EFBFBD> 3<><33><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||
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; // <20>Դ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ
|
||
|
||
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
|
||
{
|
||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>߰<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
char eliteBonus = lpCharacter->GetEliteBonus();
|
||
if (0 < eliteBonus)
|
||
{
|
||
wDropRate = EliteBonus::usBonusItemDropRate[eliteBonus - 1][nDropItemIndex - AwardTable::MAX_DROP_ITEM];
|
||
}
|
||
}
|
||
|
||
// <20>߰<EFBFBD><DFB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߰<EFBFBD>.
|
||
if(fAddDropPt > 0.0f)
|
||
{
|
||
wDropRate += static_cast<unsigned short>(wDropRate * fAddDropPt);
|
||
}
|
||
|
||
wDropRate = (unsigned short)(wDropRate*(CServerSetup::GetInstance().GetDropDefault() / 100.0f)*fPt);
|
||
|
||
// fPt<50><74> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> fPt <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><DEB6><EFBFBD><EFBFBD><EFBFBD>.
|
||
// CServerSetup::GetInstance().GetDropDefault() = 100 <20><>.
|
||
//
|
||
if (!bAllInOne && Math::Random::ComplexRandom(1000) > wDropRate)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1> 10<31><30><EFBFBD≯<EFBFBD> 10<31><30><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>Ų<EFBFBD><C5B2>.
|
||
nRandPoint = Math::Random::ComplexRandom(nTotalRate);
|
||
|
||
for (cItemKindIndex = 0; cItemKindIndex < MonsterInfo::MAX_AWARD_KIND; ++cItemKindIndex)
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
int nDropRate = lpMonster->GetDropRate(cItemKindIndex);
|
||
if (0 == nDropRate) { continue; }
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
|
||
nGradeSpace += nDropRate;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
|
||
if (nGradeSpace > nRandPoint)
|
||
{
|
||
aryItemID[nDropItemNum] = AwardTable::CAward::GetInstance().GetAward(
|
||
cItemKindIndex, reinterpret_cast<CMonster *>(m_pOwner), lpCharacter, aryItem + nDropItemNum);
|
||
|
||
if (0 == aryItemID[nDropItemNum])
|
||
{
|
||
CMonster* pMon = reinterpret_cast<CMonster *>(m_pOwner);
|
||
|
||
if(pMon)
|
||
ERRLOG2(g_Log, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʾҽ<CABE><D2BD>ϴ<EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>KID : %d, <20><><EFBFBD><EFBFBD> : %d", pMon->GetKID(), cItemKindIndex);
|
||
}
|
||
else
|
||
{
|
||
++nDropItemNum;
|
||
}
|
||
|
||
// <20>ʱ<EFBFBD>ȭ.
|
||
cItemKindIndex = MonsterInfo::MAX_AWARD_KIND;
|
||
nGradeSpace = 0;
|
||
}
|
||
|
||
// <20>ҷ<EFBFBD><D2B7><EFBFBD> <20>̺<EFBFBD>Ʈ. 3000~3005
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>̺<EFBFBD>Ʈ. 3006~3010
|
||
if(3001 <= MonID && MonID <= 3010)
|
||
{
|
||
// 3006 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3009<30><39><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
if(3006 <= MonID && MonID <= 3010 && nDropItemNum >= 1)
|
||
return nDropItemNum;
|
||
|
||
if(MonID == 3003 && nDropItemNum >= 1)
|
||
return nDropItemNum;
|
||
|
||
if(nDropItemNum >= MonDropMax)
|
||
return nDropItemNum;
|
||
}
|
||
|
||
// <20>Դ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ
|
||
if(3101 <= MonID && MonID <= 3500)
|
||
{
|
||
if(nDropItemNum >= MonDropMax)
|
||
return nDropItemNum;
|
||
}
|
||
}
|
||
}
|
||
|
||
// <20>ҷ<EFBFBD><D2B7><EFBFBD> <20>̺<EFBFBD>Ʈ. 3000~3005
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>̺<EFBFBD>Ʈ. 3006~3010
|
||
if(0 == nDropItemNum && 3001 <= MonID && MonID <= 3010)
|
||
{
|
||
// cItemKindIndex <20><> 0<><30><EFBFBD><EFBFBD> <20>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> A<><41> <20>⺻<EFBFBD><E2BABB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ϱ<EFBFBD> <20><><EFBFBD>ؼ<EFBFBD><D8BC>̴<EFBFBD>.
|
||
cItemKindIndex = 0;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ڿ<EFBFBD> <20><><EFBFBD><EFBFBD>A<EFBFBD><41> <20><><EFBFBD><EFBFBD><EFBFBD>߸<EFBFBD><DFB8><EFBFBD> <20>ߴµ<DFB4> <20><> <20><><EFBFBD><EFBFBD>A<EFBFBD><41> 0 <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD≯<EFBFBD>
|
||
// <20>̰<EFBFBD> <20>ƹ<EFBFBD><C6B9>͵<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD><CCB6>¶<EFBFBD>.
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
int nDropRate = lpMonster->GetDropRate(cItemKindIndex);
|
||
if (0 == nDropRate)
|
||
return 0;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>̺<EFBFBD>Ʈ<EFBFBD>ε<EFBFBD> <20>Ѱ<EFBFBD><D1B0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>
|
||
aryItemID[nDropItemNum] = AwardTable::CAward::GetInstance().GetAward(
|
||
cItemKindIndex, reinterpret_cast<CMonster *>(m_pOwner), lpCharacter, aryItem + nDropItemNum);
|
||
|
||
if (0 == aryItemID[nDropItemNum])
|
||
{
|
||
CMonster* pMon = reinterpret_cast<CMonster *>(m_pOwner);
|
||
|
||
if(pMon)
|
||
ERRLOG2(g_Log, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʾҽ<CABE><D2BD>ϴ<EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>KID : %d, <20><><EFBFBD><EFBFBD> : %d", pMon->GetKID(), cItemKindIndex);
|
||
|
||
return 0;
|
||
}
|
||
|
||
++nDropItemNum;
|
||
}
|
||
|
||
|
||
return nDropItemNum;
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
// Function : CThreat::DivisionExp
|
||
//
|
||
// Description : <20><><EFBFBD><EFBFBD>ġ <20>й<EFBFBD>
|
||
//
|
||
// Inputs : None.
|
||
//
|
||
// Outputs : None.
|
||
//
|
||
// Returns : None.
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
void CThreat::DivisionExp(void)
|
||
{
|
||
if (true == m_ThreatList.empty())
|
||
{
|
||
ERRLOG0(g_Log, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>. <20><> <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD><EFBFBD><EFBFBD> Exp<78><70> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>.");
|
||
return;
|
||
}
|
||
|
||
if (NULL == m_pOwner)
|
||
{
|
||
ERRLOG0(g_Log, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڰ<EFBFBD> NULL<4C>Դϴ<D4B4>.");
|
||
return;
|
||
}
|
||
|
||
unsigned long lSumOfThreatAmount = 0;
|
||
|
||
for (ThreatList::iterator it = m_ThreatList.begin(); it != m_ThreatList.end(); ++it)
|
||
{
|
||
lSumOfThreatAmount += it->m_lThreatAmount;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20>ִ<EFBFBD> <20>༮<EFBFBD><E0BCAE><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ġ <20><><EFBFBD><EFBFBD>
|
||
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, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>̻<EFBFBD><CCBB>մϴ<D5B4>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> %d<>Դϴ<D4B4>.", 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<long>(m_pOwner->GetStatus().m_nExp * tempThreatInfo.m_lThreatAmount /
|
||
std::max(static_cast<float>(lSumOfThreatAmount), static_cast<float>(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;
|
||
}
|
||
}
|
||
|
||
// <20><>ȯ<EFBFBD><C8AF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD>Ϳ<EFBFBD><CDBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
|
||
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<CSummonMonster *>(
|
||
aryIndividualAwardInfo[nSummoneeIndex].m_pCreature)->GetMaster();
|
||
bSummonee = true;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (true == CCreatureManager::GetInstance().IsSummonee(dwCID))
|
||
{
|
||
lpMaster = reinterpret_cast<CSummonMonster *>(
|
||
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();
|
||
}
|
||
}
|
||
}
|
||
|
||
// <20><>Ƽ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ġ <20>й<EFBFBD>
|
||
AwardInfo aryPartyAwardInfo[MAX_THREAT_TARGET];
|
||
|
||
nNumber = 0;
|
||
for (int nIndividualIndex = 0; nIndividualIndex < MAX_THREAT_TARGET; ++nIndividualIndex)
|
||
{
|
||
if (NULL == aryIndividualAwardInfo[nIndividualIndex].m_pCreature)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD>ġ <20>й迡<D0B9><E8BFA1> <20><><EFBFBD>ܵȴ<DCB5>.
|
||
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, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>̻<EFBFBD><CCBB>մϴ<D5B4>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> %d<>Դϴ<D4B4>.", nNumber);
|
||
}
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> MAX_THREAT_REWARD <20><>ŭ<EFBFBD><C5AD> <20><><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
|
||
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;
|
||
|
||
// <20><>Ƽ
|
||
if (NULL != aryPartyAwardInfo[nPartyIndex].m_pParty)
|
||
{
|
||
reinterpret_cast<CCharacterParty* >(aryPartyAwardInfo[nPartyIndex].m_pParty)->SendDivisionExp(
|
||
reinterpret_cast<CCharacter *>(aryPartyAwardInfo[nPartyIndex].m_pCreature), m_pOwner, lIndividualExp, cHighestLevel);
|
||
}
|
||
// <20><><EFBFBD><EFBFBD>
|
||
else
|
||
{
|
||
CCharacter *lpCharacter = reinterpret_cast<CCharacter *>(aryPartyAwardInfo[nPartyIndex].m_pCreature);
|
||
lIndividualExp = static_cast<long>(lIndividualExp * GetAggravation(lpCharacter));
|
||
|
||
// Threat List<73><74> 2<><32> <20><><EFBFBD><EFBFBD> ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ݸ<EFBFBD><DDB8><EFBFBD> <20>´<DEB4>.
|
||
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;
|
||
}
|
||
|
||
// <20>̱<EFBFBD><CCB1><EFBFBD> <20><><EFBFBD>ʸ<EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> PvP<76><50><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>¡ <20><><EFBFBD><EFBFBD>å<EFBFBD><C3A5> <20><>ȭ<EFBFBD>ȴ<EFBFBD>.
|
||
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;
|
||
}
|
||
|