Files
Client/Server/RylServerProject/RylGameLibrary/Creature/AggresiveCreature.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

1102 lines
35 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
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 <Utility/Math/Math.h>
#include <Utility/Setup/ServerSetup.h>
#include <Skill/SkillTable.h>
#include <Skill/Spell/Spell.h>
#include <Network/ClientSocket/ClientConstants.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Network/Packet/PacketStruct/CharStatusPacketStruct.h>
#include <Map/FieldMap/CellManager.h>
#include <Map/FieldMap/VirtualArea/VirtualArea.h>
#include <Map/FieldMap//VirtualArea/VirtualAreaMgr.h>
#include <Map/DuelMap/DuelCellManager.h>
#include <Community/Party/PartyMgr.h>
#include <Log/BugPlayLog.h>
#include "./Character/Character.h"
#include "./Monster/Monster.h"
#include "./Siege/SiegeObject.h"
#include "./Siege/Camp.h"
#include "./Siege/CastleGate.h"
#include "./Siege/CastleEmblem.h"
#include "CreatureManager.h"
#include "AggresiveCreature.h"
#include <Network/Dispatch/GameClient/GameClientDispatch.h>
#include <Network/Dispatch/GameClient/SendCharAttack.h>
#include <Network/Packet/PacketCommand.h>
CellPosition::CellPosition()
: m_lpCell(NULL), m_wMapIndex(0), m_cCellX(0), m_cCellZ(0), m_wInX(0), m_wInZ(0)
{
}
CellPosition::CellPosition(const Position& WorldPos)
{
MoveTo(WorldPos);
}
bool CellPosition::MoveTo(const Position& WorldPos)
{
// °ªÀÌ Â©¸®Áö ¾Êµµ·Ï ÁÖÀÇ!
int nCellX = 0;
int nCellZ = 0;
Position pos = WorldPos;
if (0 != m_wMapIndex)
{
VirtualArea::CVirtualArea* lpVirtualArea =
VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(m_wMapIndex);
pos.m_fPointX -= lpVirtualArea->GetStartX();
pos.m_fPointZ -= lpVirtualArea->GetStartZ();
}
nCellX = static_cast<int>(pos.m_fPointX) >> CCell::CELL_RESOLUTION;
nCellZ = static_cast<int>(pos.m_fPointZ) >> CCell::CELL_RESOLUTION;
m_wInX = static_cast<int>((pos.m_fPointX - (nCellX << CCell::CELL_RESOLUTION)) * CCell::CELL_DISTANCE);
m_wInZ = static_cast<int>((pos.m_fPointZ - (nCellZ << CCell::CELL_RESOLUTION)) * CCell::CELL_DISTANCE);
m_cCellX = static_cast<unsigned char>(nCellX);
m_cCellZ = static_cast<unsigned char>(nCellZ);
m_lpCell = CCellManager::GetInstance().GetCell(m_wMapIndex, m_cCellX, m_cCellZ);
return (NULL != m_lpCell) ? true : false;
}
CAggresiveCreature::CAggresiveCreature(unsigned long dwCID)
: m_dwLastTime(0), m_pParty(NULL), CCreature(dwCID), m_bLogout(false), m_bSitDown(false)
{
m_Threat.SetOwner(this);
m_SpellMgr.SetOwner(this);
std::fill_n(m_aryEnchantLevel, int(Skill::SpellID::MAX_SPELL_TYPE), 0);
}
CAggresiveCreature::~CAggresiveCreature()
{
m_Threat.ClearAll();
}
CAggresiveCreature::MoveInfo CAggresiveCreature::MoveTo(const Position& NewPosition, const bool bSitDown)
{
PERFORMANCE_CHECK(FunctionTimingCheck);
if (m_bLogout ||
true == GetEnchantInfo().GetFlag(Skill::SpellID::Hold) ||
true == GetEnchantInfo().GetFlag(Skill::SpellID::Stun) ||
true == GetEnchantInfo().GetFlag(Skill::SpellID::StoneForm))
{
return F_CELL_CANNOTCHANGE;
}
// µà¾ó »óŶó¸é µà¾ó ¼¿·Î ó¸®
if (CServerSetup::GetInstance().GetDuelModeCheck() && NULL != GetDuelOpponent())
{
m_CurrentPos = NewPosition;
m_bSitDown = bSitDown;
return S_CELL_UNCHANGED;
}
else
{
// TODO : À§Ä¡°¡ °©Àڱ⠸¹ÀÌ Æ¢¾úÀ» ¶§ º¸Á¤ÇÏ´Â ÀÛ¾÷ ÇÊ¿ä.
/* À§Ä¡°¡ Æ¢´Â °æ¿ì ·Î±× È®ÀÎ
if (49 < m_CurrentPos.GetSquaredDistance(Position(0, 0, 0)) &&
49 < m_CurrentPos.GetSquaredDistance(NewPosition))
{
const int MAX_BUFFER = 256;
char szBuffer[MAX_BUFFER];
if (0 < _snprintf(szBuffer, MAX_BUFFER - 1,
"MoveTo : CID:0x%08x : ¼ø°£À̵¿Çϳª?.. %d°Å¸®¸¦ ´«¾Õ¿¡¼­ À̵¿Çß´Ù!"
"/CurrentPulse:%d (%f,%f,%f)->(%f,%f,%f)\n",
m_dwCID, m_CurrentPos.GetSquaredDistance(NewPosition),
CPulse::GetInstance().GetCurrentPulse(),
m_CurrentPos.m_fPointX, m_CurrentPos.m_fPointY, m_CurrentPos.m_fPointZ,
NewPosition.m_fPointX, NewPosition.m_fPointY, NewPosition.m_fPointZ))
{
szBuffer[MAX_BUFFER - 1] = 0;
OutputDebugString(szBuffer);
}
}
*/
m_CurrentPos = NewPosition;
m_bSitDown = bSitDown;
CCell* lpLastCell = m_CellPos.m_lpCell;
if (!m_CellPos.MoveTo(m_CurrentPos))
{
ERRLOG4(g_Log, "CID:0x%08x ÀÌ»óÇÑ À§Ä¡¿¡ ¿Í ÀÖ½À´Ï´Ù. (%f, %f, %f)",
m_dwCID, m_CurrentPos.m_fPointX, m_CurrentPos.m_fPointY, m_CurrentPos.m_fPointZ);
}
if (m_CellPos.m_lpCell == lpLastCell)
{
// °°Àº ¼¿ ¾È¿¡ ÀÖ´Â °æ¿ì.
return S_CELL_UNCHANGED;
}
else
{
if (0 != lpLastCell)
{
// ÀÏ´Ü À̵¿À» ÇßÀ¸´Ï, ¼¿ ·Î±×¾Æ¿ôÀ» ÇÑ´Ù.
lpLastCell->DeleteCreature(m_dwCID, m_CellPos.m_lpCell);
}
if (NULL == m_CellPos.m_lpCell)
{
// Àüü ¼¿ ¹ÛÀ¸·Î ³ª°¡´Â °æ¿ì
return F_CELL_CANNOTCHANGE;
}
}
m_CellPos.m_lpCell->SetCreature(m_dwCID, this, lpLastCell);
return S_CELL_CHANGED;
}
}
const int CAggresiveCreature::CalculateLevelGap(CAggresiveCreature *pDefender)
{
return CalculateLevelGap(m_CreatureStatus.m_nLevel, pDefender->GetStatus().m_nLevel);
}
const int CAggresiveCreature::CalculateLevelGap(int nOffencerLevel, int nDefenderLevel)
{
// edith 2008.02.13 ¸ó½ºÅÍ ·¹º§<C2BA>W¿¡ ÀÇÇÑ ¼±°ø°Ë»ö
// ¸ó½ºÅÍ·¹º§ - °Ë»öÀÚ
// ¸ó½ºÅÍ ·¹º§ÀÌ ´õ Å©¸é nLevelGap ÀÌ ¾ç¼ö
// ¸ó½ºÅÍ ·¹º§ÀÌ ´õ ÀÛÀ¸¸é À½¼ö°ªÀ̳ª¿Â´Ù.
int nLevelGap = nOffencerLevel - nDefenderLevel;
// -20°ú ·¹º§°¸ÀÇ ÃÖ´ë°ª
nLevelGap = max(MAX_LEVEL_GAP * (-1), nLevelGap);
// ¸ó½ºÅͰ¡ 20º¸´Ù ´õ ·¦ÀÌ ³ôÀ¸¸é ÃÖ´ë 20À¸·Î Àâ´Â´Ù.
nLevelGap = min(nLevelGap, int(MAX_LEVEL_GAP));
return nLevelGap;
}
const float CAggresiveCreature::CalculateLevelGapAffect(CAggresiveCreature *pDefender)
{
float fFinalAffect = 1.0f;
// ¸ó½ºÅÍ¿ÍÀÇ ÀüÅõ
Creature::CreatureType eCreatureType = Creature::GetCreatureType(m_dwCID);
Creature::CreatureType eDefenderCreatureType = Creature::GetCreatureType(pDefender->GetCID());
if (Creature::CT_MONSTER == eCreatureType ||
Creature::CT_SUMMON == eCreatureType ||
Creature::CT_STRUCT == eCreatureType ||
Creature::CT_MONSTER == eDefenderCreatureType ||
Creature::CT_SUMMON == eDefenderCreatureType ||
Creature::CT_STRUCT == eDefenderCreatureType)
{
/*
// ROW¿ë
static const float fHuntingAffect[AGGRAVATION_NUM] = {
0.1f, 0.105f, 0.11f, 0.12f, 0.13f, 0.14f, 0.15f, 0.17f, 0.18f, 0.2f,
0.22f, 0.25f, 0.27f, 0.40f, 0.52f, 0.63f, 0.73f, 0.82f, 0.89f, 0.95f,
1.0f,
1.01f, 1.02f, 1.03f, 1.04f, 1.05f, 1.06f, 1.07f, 1.08f, 1.09f, 1.1f,
1.11f, 1.12f, 1.13f, 1.14f, 1.15f, 1.16f, 1.17f, 1.18f, 1.19f, 1.2f
};
*/
// ROW + RYL2
static const float fHuntingAffect[AGGRAVATION_NUM] = {
0.1f, 0.105f, 0.11f, 0.12f, 0.13f, 0.14f, 0.15f, 0.17f, 0.18f, 0.2f,
0.22f, 0.25f, 0.27f, 0.40f, 0.52f, 0.63f, 0.73f, 0.82f, 0.89f, 0.95f,
1.0f,
1.015f, 1.03f, 1.045f, 1.06f, 1.075f, 1.09f, 1.105f, 1.12f, 1.135f, 1.15f,
1.165f, 1.18f, 1.195f, 1.21f, 1.225f, 1.24f, 1.255f, 1.27f, 1.285f, 1.3f
// 1.025f, 1.05f, 1.075f, 1.10f, 1.125f, 1.15f, 1.175f, 1.20f, 1.225f, 1.25f,
// 1.275f, 1.30f, 1.325f, 1.35f, 1.375f, 1.40f, 1.425f, 1.45f, 1.475f, 1.5f
// 1.05f, 1.10f, 1.15f, 1.20f, 1.25f, 1.30f, 1.35f, 1.40f, 1.45f, 1.5f,
// 1.55f, 1.60f, 1.65f, 1.70f, 1.75f, 1.80f, 1.85f, 1.90f, 1.95f, 2.0f
};
/*
static const float fHuntingAffect[AGGRAVATION_NUM] = {
0.1f, 0.105f, 0.11f, 0.12f, 0.13f, 0.14f, 0.15f, 0.17f, 0.18f, 0.2f,
0.22f, 0.25f, 0.27f, 0.33f, 0.45f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f,
1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
};
*/
/*
// ÃÖÁ¾
static const float fHuntingAffect[AGGRAVATION_NUM] = {
0.01f, 0.02f, 0.03f, 0.04f, 0.05f, 0.06f, 0.07f, 0.08f, 0.09f, 0.1f,
0.15f, 0.2f, 0.25f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f,
1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
};
*/
fFinalAffect = fHuntingAffect[CalculateFixLevelGap(pDefender) + MAX_LEVEL_GAP];
}
// PvP
else
{
// ----------------------------------------------------------------------------------
// ·¹º§°¸ Àû¿ë ¹öÀü
CCharacter* lpOffencer = reinterpret_cast<CCharacter *>(this);
CCharacter* lpDefender = reinterpret_cast<CCharacter *>(pDefender);
// static const float fPvPAffect[AGGRAVATION_NUM] = {
// 0.6f, 0.6f, 0.6f, 0.6f, 0.6f, 0.6f, 0.6f, 0.6f, 0.6f, 0.6f,
// 0.6f, 0.64f, 0.68f, 0.72f, 0.76f, 0.8f, 0.84f, 0.88f, 0.92f, 0.96f,
// 1.0f,
// 1.08f, 1.16f, 1.24f, 1.32f, 1.4f, 1.48f, 1.56f, 1.64f, 1.72f, 1.8f,
// 1.8f, 1.8f, 1.8f, 1.8f, 1.8f, 1.8f, 1.8f, 1.8f, 1.8f, 1.8f
// };
/*
static const float fPvPAffect[AGGRAVATION_NUM] = {
0.60f, 0.62f, 0.64f, 0.66f, 0.68f, 0.70f, 0.72f, 0.74f, 0.76f, 0.78f,
0.80f, 0.82f, 0.84f, 0.86f, 0.88f, 0.90f, 0.92f, 0.94f, 0.96f, 0.98f,
1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
};
*/
// ±èÀ翬 PVP µ¥¹ÌÁö
/* // µà¾ó ¹× PVPÀ϶§ µ¥¹ÌÁö Àû¿ë °¸¿ë °¨¼Ò. 0.9->0.8·Î .
static const float fPvPAffect[AGGRAVATION_NUM] = {
0.52f, 0.54f, 0.56f, 0.58f, 0.60f, 0.62f, 0.64f, 0.66f, 0.67f, 0.69f,
0.71f, 0.72f, 0.73f, 0.74f, 0.75f, 0.76f, 0.77f, 0.78f, 0.79f, 0.80f,
0.81f,
0.81f, 0.81f, 0.81f, 0.81f, 0.81f, 0.81f, 0.81f, 0.81f, 0.81f, 0.81f,
0.81f, 0.81f, 0.81f, 0.81f, 0.81f, 0.81f, 0.81f, 0.81f, 0.81f, 0.81f
};
*/
// edith 2009.12.26 PVP Á¶Á¤
static const float fPvPAffect[AGGRAVATION_NUM] = {
0.49f, 0.51f, 0.53f, 0.55f, 0.57f, 0.59f, 0.61f, 0.63f, 0.64f, 0.66f,
0.67f, 0.68f, 0.69f, 0.70f, 0.71f, 0.72f, 0.73f, 0.74f, 0.75f, 0.76f,
0.77f,
0.77f, 0.77f, 0.77f, 0.77f, 0.77f, 0.77f, 0.77f, 0.77f, 0.77f, 0.77f,
0.77f, 0.77f, 0.77f, 0.77f, 0.77f, 0.77f, 0.77f, 0.77f, 0.77f, 0.77f
};
/*
// ÃÖÁ¾.
static const float fPvPAffect[AGGRAVATION_NUM] = {
0.30f, 0.32f, 0.34f, 0.36f, 0.38f, 0.30f, 0.32f, 0.34f, 0.36f, 0.38f,
0.40f, 0.41f, 0.42f, 0.43f, 0.44f, 0.45f, 0.46f, 0.47f, 0.48f, 0.49f,
0.50f,
0.50f, 0.50f, 0.50f, 0.50f, 0.50f, 0.50f, 0.50f, 0.50f, 0.50f, 0.50f,
0.50f, 0.50f, 0.50f, 0.50f, 0.50f, 0.50f, 0.50f, 0.50f, 0.50f, 0.50f
};
*/
fFinalAffect = fPvPAffect[CalculateLevelGap(m_CreatureStatus.m_nLevel, pDefender->GetStatus().m_nLevel) + MAX_LEVEL_GAP];
/*
// ----------------------------------------------------------------------------------
// ¿¤¸®Æ®º¸³Ê½º Àû¿ë ¹öÀü
CCharacter* lpCharacter = reinterpret_cast<CCharacter *>(this);
static const float fEliteBonusAffect[EliteBonus::MAX_BONUS_LEVEL * 2 + 1] = {
0.6f, 0.64f, 0.68f, 0.72f, 0.76f, 0.8f, 0.84f, 0.88f, 0.92f, 0.96f,
1.0f,
1.08f, 1.16f, 1.24f, 1.32f, 1.4f, 1.48f, 1.56f, 1.64f, 1.72f, 1.8f
};
fFinalAffect = fEliteBonusAffect[lpCharacter->GetEliteBonus() + EliteBonus::MAX_BONUS_LEVEL];
*/
/*
// ----------------------------------------------------------------------------------
// °è±Þ È¿°ú Àû¿ë ¹öÀü
CCharacter* lpOffencer = reinterpret_cast<CCharacter *>(this);
CCharacter* lpDefender = reinterpret_cast<CCharacter *>(pDefender);
static const float fCasteAffect[MAX_CASTE + 1] = {
1.0f, 0.96f, 0.92f, 0.88f, 0.84f, 0.8f, 0.76f, 0.72f, 0.68f, 0.64f, 0.6f
};
char cCasteGap = lpDefender->GetCaste() - lpOffencer->GetCaste();
cCasteGap = max(cCasteGap, char(0));
cCasteGap = min(cCasteGap, char(MAX_CASTE));
fFinalAffect = fCasteAffect[cCasteGap];
*/
}
return fFinalAffect;
}
bool CAggresiveCreature::MultiAttack(AtType attackType, unsigned char nDefenderNum, CAggresiveCreature** ppDefenders, unsigned char* cDefenserJudges,
Position CenterPos, float fDir, float nRange, float fAngle, char cTargetType)
{
if (NULL == ppDefenders[0])
{
return false;
}
// ÀÚ±â Áß½ÉÀ¸·Î ¾²´Â ¹üÀ§ ¸¶¹ý
if (this == ppDefenders[0])
{
nDefenderNum = 0;
ppDefenders[0] = NULL;
}
CCell* lpCell = NULL;
// µà¾ó »óŶó¸é µà¾ó ¼¿·Î ó¸®
if (CServerSetup::GetInstance().GetDuelModeCheck() && NULL != GetDuelOpponent())
{
lpCell = CDuelCellManager::GetInstance().GetCell(GetCID());
}
else
{
lpCell = CCellManager::GetInstance().GetCell(m_CellPos.m_wMapIndex,
static_cast<unsigned long>(CenterPos.m_fPointX),
static_cast<unsigned long>(CenterPos.m_fPointY),
static_cast<unsigned long>(CenterPos.m_fPointZ));
}
if (NULL == lpCell)
{
ERRLOG0(g_Log, "CID:0x%08x °ø°Ý Áß½É Ä³¸¯ÅͰ¡ ¼¿ÀÌ Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù.");
return false;
}
unsigned short wDefenserMPHeal[AtNode::MAX_DEFENDER_NUM] = {0, };
for (int nDirection = 0; nDirection < CCell::CONNECT_NUM && nDefenderNum < AtNode::MAX_DEFENDER_NUM; ++nDirection)
{
CCell* lpConnectCell = lpCell->GetConnectCell(nDirection);
if (NULL == lpConnectCell)
{
continue;
}
CAggresiveCreature* lpTempTarget = lpConnectCell->GetFirstAggresiveCreature();
// Ÿ°ÙÀÌ ¾ø°Å³ª, ¹æ¾îÀÚ ¼ö°¡ ÃÖ´ë°¡ µÇ¸é, ·çÇÁ¸¦ ºüÁ®³ª°©´Ï´Ù.
while (NULL != lpTempTarget && nDefenderNum < AtNode::MAX_DEFENDER_NUM)
{
// °ø°Ý¿¡ ´ëÇÑ ¿¹¿Ü»óȲ
bool bException = false;
// º´±â¿¡ ž½ÂÇÑ Ä³¸¯ÅÍ´Â °ø°ÝÇÏÁö ¾Ê´Â´Ù. ´ë½Å º´±â¸¦ °ø°ÝÇÑ´Ù.
if (Creature::CT_PC == Creature::GetCreatureType(lpTempTarget->GetCID()))
{
CCharacter* lpRideChar = reinterpret_cast<CCharacter*>(lpTempTarget);
if (true == lpRideChar->IsRideArms())
{
bException = true;
}
}
EnemyCheck::EnemyType eTargetType = IsEnemy(lpTempTarget);
if ((EnemyCheck::EC_NEUTRAL == eTargetType) ||
(Skill::Target::FRIEND == cTargetType && EnemyCheck::EC_ENEMY == eTargetType) ||
(Skill::Target::ENEMY == cTargetType && EnemyCheck::EC_FRIEND == eTargetType))
{
bException = true;
}
// ¾Æ±ºÀ» ´ë»óÀ¸·Î ÇÑ ½ºÅ³À» °ø¼º ¿ÀºêÁ§Æ®, ¼®»ó¿¡°Ô´Â »ç¿ëÇÒ¼ö ¾øµµ·Ï ó¸®
if (Skill::Target::FRIEND == cTargetType)
{
if (Creature::CT_SIEGE_OBJECT == Creature::GetCreatureType(lpTempTarget->GetCID()))
{
bException = true;
}
else if (Creature::CT_STRUCT == Creature::GetCreatureType(lpTempTarget->GetCID()))
{
CStatue* lpStatue = reinterpret_cast<CMonster*>(lpTempTarget)->DowncastToStatue();
if (NULL != lpStatue)
{
bException = true;
}
}
}
// ¹«Àû »óÅÂÀ̸é ó¸®ÇÏÁö ¾Ê´Â´Ù.
if (true == lpTempTarget->GetEnchantInfo().GetFlag(Skill::SpellID::Invincible))
{
bException = true;
}
// °ãÄ¡´Â °Ô ÀÖÀ¸¸é ó¸®ÇÏÁö ¾Ê´Â´Ù.
for (int nIndex = 0; nIndex < nDefenderNum; nIndex++)
{
if (ppDefenders[nIndex] == lpTempTarget)
{
bException = true;
break;
}
}
if (false == bException)
{
const float fDX = lpTempTarget->GetCurrentPos().m_fPointX - CenterPos.m_fPointX;
const float fDZ = lpTempTarget->GetCurrentPos().m_fPointZ - CenterPos.m_fPointZ;
const float fDistance = (fDX * fDX) + (fDZ * fDZ);
const float fSquareAttackRange = nRange * nRange;
if (fDistance <= fSquareAttackRange)
{
const float fTempfDir = CalcDir2D(CenterPos.m_fPointX, CenterPos.m_fPointZ,
lpTempTarget->GetCurrentPos().m_fPointX, lpTempTarget->GetCurrentPos().m_fPointZ);
const float fDifference = (fTempfDir >= fDir) ? (fTempfDir-fDir) : (fDir-fTempfDir);
if (fDifference <= fAngle && 0 < lpTempTarget->GetStatus().m_nNowHP)
{
ppDefenders[nDefenderNum] = lpTempTarget;
cDefenserJudges[nDefenderNum] = ClientConstants::Judge_Front;
wDefenserMPHeal[nDefenderNum] = 0;
++nDefenderNum;
}
}
}
lpTempTarget = lpConnectCell->GetNextAggresiveCreature();
}
}
if (AtNode::MAX_DEFENDER_NUM < nDefenderNum)
{
SERLOG0(g_Log, "½ºÅà ¿À¹ö·± : ¹æ¾îÀÚ¼ö°¡ ÃÖ´ëÄ¡¸¦ ³Ñ¾î¼Ì½À´Ï´Ù.");
}
return Attack(attackType, nDefenderNum, ppDefenders, cDefenserJudges, wDefenserMPHeal);
}
unsigned short CAggresiveCreature::MeleeAttack(CAggresiveCreature* lpTarget, Creature::StatusType eHandType,
const float fLevelGap, unsigned char &cDefenserJudge, unsigned int ExType)
{
FightStatus resultStatus;
// A. ¿Þ¼Õ/¿À¸¥¼Õ ÆÇÁ¤
if (Creature::RIGHT_PASSIVE_TYPE == eHandType)
{
resultStatus = m_CreatureStatus.m_StatusInfo;
}
else
{
unsigned short aryEnchantLevel[Skill::SpellID::MAX_SPELL_TYPE] = { 0, };
GetEnchantLevel(aryEnchantLevel);
GetEtcTypeStatus(eHandType).CalculateEnchantInfo(aryEnchantLevel, resultStatus);
}
// Àκ£³Ñ »ç¿ë½Ã
CSpell* lpSpell = m_SpellMgr.GetAffectedInfo().GetSpell(Skill::SpellID::Envenom);
if (NULL != lpSpell)
{
unsigned short wResult = Skill::CAddSpell<CPoisonedSpell>(
CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, this,
Skill::SpellType::MAGICAL_SPELL, Skill::SpellID::Poisoned,
lpSpell->GetSpellLevel(), static_cast<unsigned long>(20 * CalculateLevelGapAffect(lpTarget))))(lpTarget);
switch (wResult)
{
case CSpell::NO_ENCHANT_ERROR :
case CSpell::ENCHNAT_FAIL_ALREADY_AFFECTED :
case CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT :
break;
case CSpell::ENCHANT_FAIL_BY_RESIST :
cDefenserJudge = ClientConstants::Judge_Resist;
break;
}
}
// ³»±¸µµ °¨¼Ò
if (Creature::LEFT_PASSIVE_TYPE == eHandType ||
Creature::LEFT_NON_PASSIVE_TYPE == eHandType)
{
CalculateEquipDurability(AtType::LEFT_MELEE);
}
else
{
CalculateEquipDurability(AtType::RIGHT_MELEE);
}
// µ¥¹ÌÁö °è»ê
return lpTarget->CalculateDamage(resultStatus, fLevelGap, cDefenserJudge, ExType);
}
unsigned short CAggresiveCreature::ApplyDamage(AtType attackType, CAggresiveCreature* pOffencer,
unsigned char &cOffencerJudge, unsigned char &cDefenserJudge,
unsigned short& wOffencerMPHeal, unsigned short& wDefenserMPHeal,
unsigned short &wError)
{
PERFORMANCE_CHECK(FunctionTimingCheck)
unsigned short nDamage = 0;
const unsigned short nPreviousHP = m_CreatureStatus.m_nNowHP;
const unsigned short nPreviousMP = m_CreatureStatus.m_nNowMP;
bool bCounter = true;
bool bInterrupt = true;
bool bProtection = true;
Creature::CreatureType eCreatureType = Creature::GetCreatureType(m_dwCID);
if (0x4000 < attackType.m_wType && attackType.m_wType < 0x5000)
{
bCounter = false;
bInterrupt = false;
bProtection = false;
}
else if (0 != (attackType.m_wType & AtType::SKILL_BIT))
{
const Skill::ProtoType* lpSkillProtoType = CSkillMgr::GetInstance().GetSkillProtoType(attackType.m_wType);
if (NULL == lpSkillProtoType)
{
ERRLOG2(g_Log, "CID:0x%08x Á¸ÀçÇÏÁö ¾Ê´Â ½ºÅ³ ¾ÆÀ̵ðÀÔ´Ï´Ù. Skill ID:0x%04x",
pOffencer->GetCID(), attackType.m_wType);
return 0;
}
if (false == lpSkillProtoType[attackType.m_cSkillLockCount].m_bCounter) { bCounter = false; }
if (false == lpSkillProtoType[attackType.m_cSkillLockCount].m_bInterrupt) { bInterrupt = false; }
if (false == lpSkillProtoType[attackType.m_cSkillLockCount].m_bProtection) { bProtection = false; }
}
// Ä«¿îÅÍ ¹ßµ¿
if (true == bCounter)
{
if (true == GetEnchantInfo().GetFlag(Skill::SpellID::CounterAttack))
{
// ¸ó½ºÅÍ´Â Ä«¿îÅ͸¦ ¾µ ¼ö ¾ø´Ù. (¾²·¹Æ®°¡ Áõ°¡ÇÏÁö ¾Ê´Â´Ù.)
cDefenserJudge = ClientConstants::Judge_Counter;
return 0;
}
}
// ¸ÂÀ¸¸é ½ºÅÏ ÆÄ±«
if (true == bInterrupt)
{
m_SpellMgr.GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::Stun);
}
// B. ¸¶³ª¼¿, À̺£ÀÌÁ¯ ÆÇÁ¤
if (true == bProtection)
{
CSpell *pSpell = NULL;
// ¸ÂÀ¸¸é ¸¶³ª¼¿ ·¹º§ 5 °¨¼Ò
pSpell = m_SpellMgr.GetAffectedInfo().GetSpell(Skill::SpellID::ManaShell);
if (NULL != pSpell)
{
if (0 == pSpell->DecreaseSkillLevel(5))
{
m_SpellMgr.GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::ManaShell);
}
m_Threat.AddToThreatList(pOffencer, 1);
cDefenserJudge = ClientConstants::Judge_ManaShell;
return 0;
}
// ¸ÂÀ¸¸é Ç÷º¼­ºô·¯Æ¼ ·¹º§ 5 °¨¼Ò
pSpell = m_SpellMgr.GetAffectedInfo().GetSpell(Skill::SpellID::Flexibility);
if (NULL != pSpell)
{
if (0 == pSpell->DecreaseSkillLevel(5))
{
m_SpellMgr.GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::Flexibility);
}
m_Threat.AddToThreatList(pOffencer, 1);
cDefenserJudge = ClientConstants::Judge_Evade;
return 0;
}
}
if (0x4000 < attackType.m_wType && attackType.m_wType < 0x5000)
{
nDamage = Skill::CProcessTable::GetInstance().UseSkill(attackType, pOffencer, this,
cOffencerJudge, cDefenserJudge, wOffencerMPHeal, wDefenserMPHeal, wError);
}
else if (0 != (attackType.m_wType & AtType::SKILL_BIT))
{
if(0x9E00 < attackType.m_wType && attackType.m_wType <= 0x9EFF)
{
; // °Ô´õ¸µ ½ºÅ³Àº °Ë»ç¸¦ ¹«½ÃÇÑ´Ù.
}
// ½ºÅ³ ¾ÆÀÌÅÛ »ç¿ë½Ã ½ºÅ³ÀÇ ¼ÒÁö ¿©ºÎ¸¦ ¹«½Ã
else if (ClientConstants::Judge_SkillItem != cOffencerJudge)
{
// ¿©±â°¡ °°Àº ¼ÒÀ¯ÀÇ ½ºÅ³ÀÌ ÀÖ´ÂÁö °Ë»öÇÏ´Â ºÎºÐ
if (false == pOffencer->HasSkill(attackType.m_wType, attackType.m_cSkillLockCount, attackType.m_cSkillLevel))
{
return 0;
}
}
// ¿©±â¿¡¼­ ÀÌ¹Ì »ç¿ëµÈ ¶È°°Àº ½ºÅ³ÀÌ ÀÖ´ÂÁö °Ë»ö??
// ¿©±â°¡ ¾ÆÀÌÅÛ »ç¿ë½Ã ½ºÅ³·Î »ç¿ëµÇ´Â ºÎºÐ.
nDamage = Skill::CProcessTable::GetInstance().UseSkill(attackType, pOffencer, this,
cOffencerJudge, cDefenserJudge, wOffencerMPHeal, wDefenserMPHeal, wError);
}
else
{
if (false == pOffencer->AttackUsingBow(attackType.m_wType))
{
return 0;
}
// edith 2008.05.20 ºí·ÏÆÇÁ¤ Ãß°¡
// unsigned long dwRate = Math::Random::ComplexRandom(pOffencer->m_CreatureStatus.m_StatusInfo.m_wHitRate + m_CreatureStatus.m_StatusInfo.m_wEvade + m_CreatureStatus.m_StatusInfo.m_wBlock);
float evade = m_CreatureStatus.m_StatusInfo.m_wEvade*1.05f;
float block = m_CreatureStatus.m_StatusInfo.m_wBlock*1.05f;
unsigned long dwRate = Math::Random::ComplexRandom(pOffencer->m_CreatureStatus.m_StatusInfo.m_wHitRate + (int)(evade + block));
// ºí·ÏÆÇÁ¤
if (dwRate >= static_cast<unsigned short>(pOffencer->m_CreatureStatus.m_StatusInfo.m_wHitRate + m_CreatureStatus.m_StatusInfo.m_wEvade))
{
m_Threat.AddToThreatList(pOffencer, 1);
if (Creature::CT_MONSTER == eCreatureType ||
Creature::CT_SUMMON == eCreatureType ||
Creature::CT_STRUCT == eCreatureType)
{
CMonster* lpMonster = reinterpret_cast<CMonster *>(this);
lpMonster->Attacked();
}
cDefenserJudge = ClientConstants::Judge_Guard;
return 0;
}
// ȸÇÇÆÇÁ¤
if (dwRate >= static_cast<unsigned short>(pOffencer->m_CreatureStatus.m_StatusInfo.m_wHitRate))
{
m_Threat.AddToThreatList(pOffencer, 1);
if (Creature::CT_MONSTER == eCreatureType ||
Creature::CT_SUMMON == eCreatureType ||
Creature::CT_STRUCT == eCreatureType)
{
CMonster* lpMonster = reinterpret_cast<CMonster *>(this);
lpMonster->Attacked();
}
cDefenserJudge = ClientConstants::Judge_Miss;
return 0;
}
/*
// edith 2008.05.19 ¸íÁß, ºí·Ï ÆÇÁ¤ ¼öÁ¤.
// D. ¸íÁß ÆÇÁ¤
if (Math::Random::ComplexRandom(pOffencer->m_CreatureStatus.m_StatusInfo.m_wHitRate + m_CreatureStatus.m_StatusInfo.m_wEvade) >=
static_cast<unsigned short>(pOffencer->m_CreatureStatus.m_StatusInfo.m_wHitRate))
{
m_Threat.AddToThreatList(pOffencer, 1);
if (Creature::CT_MONSTER == eCreatureType ||
Creature::CT_SUMMON == eCreatureType ||
Creature::CT_STRUCT == eCreatureType)
{
CMonster* lpMonster = reinterpret_cast<CMonster *>(this);
lpMonster->Attacked();
}
cDefenserJudge = ClientConstants::Judge_Miss;
return 0;
}
// E. ºí·Ï ÆÇÁ¤
if (Math::Random::ComplexRandom(10000) < m_CreatureStatus.m_StatusInfo.m_fBlockRate * 100)
{
m_Threat.AddToThreatList(pOffencer, 1);
if (Creature::CT_MONSTER == eCreatureType ||
Creature::CT_SUMMON == eCreatureType ||
Creature::CT_STRUCT == eCreatureType)
{
CMonster* lpMonster = reinterpret_cast<CMonster *>(this);
lpMonster->Attacked();
}
cDefenserJudge = ClientConstants::Judge_Guard;
return 0;
}
*/
// A. ¿Þ¼Õ/¿À¸¥¼Õ ÆÇÁ¤
Creature::StatusType eHandType = Creature::RIGHT_PASSIVE_TYPE;
if (AtType::LEFT_MELEE == attackType.m_wType)
{
eHandType = Creature::LEFT_PASSIVE_TYPE;
}
nDamage = pOffencer->MeleeAttack(this, eHandType, pOffencer->CalculateLevelGapAffect(this), cDefenserJudge);
}
CSpell* pSpell = m_SpellMgr.GetAffectedInfo().GetSpell(Skill::SpellID::Guard);
if (0 < nDamage && NULL != pSpell)
{
if (4 <= pSpell->GetSkillLockCount())
{
if (0 != (attackType.m_wType & AtType::SKILL_BIT))
{
const Skill::ProtoType* lpSkillProtoType = CSkillMgr::GetInstance().GetSkillProtoType(attackType.m_wType);
if (NULL == lpSkillProtoType)
{
ERRLOG2(g_Log, "CID:0x%08x Á¸ÀçÇÏÁö ¾Ê´Â ½ºÅ³ ¾ÆÀ̵ðÀÔ´Ï´Ù. Skill ID:0x%04x",
pOffencer->GetCID(), attackType.m_wType);
return 0;
}
else if (-5 < CalculateFixLevelGap(pOffencer))
{
// ÇǰÝÀÚ¿¡°Ô °¡µå 5´Ü°è ½ºÅ³ÀÌ»óÀÇ °¡µå ½ºÆçÀÌ ¹ßµ¿µÇ¾î ÀÖÀ» ¶§ ½ºÅ³ ÇÇ°Ý µ¥¹ÌÁö¸¦ ÀÏÁ¤ È®·ü·Î ¹Ý»ç
unsigned char cSuccessRate = 6 + (pSpell->GetSkillLevel() * 4);
if (cSuccessRate > Math::Random::ComplexRandom(100))
{
unsigned short nRefrectionDamage = nDamage;
if (5000 < nRefrectionDamage)
{
nRefrectionDamage = 5000;
}
unsigned short wNowHP = pOffencer->GetStatus().m_nNowHP;
const unsigned short wThreatAmount = (wNowHP < nRefrectionDamage) ? wNowHP : nRefrectionDamage;
pOffencer->GetThreat().AddToThreatList(this, wThreatAmount);
pOffencer->GetStatus().m_nNowHP = (wNowHP > nRefrectionDamage) ? wNowHP - nRefrectionDamage : 1;
DefenserNode node;
node.m_wDamage = nRefrectionDamage;
node.m_dwCharID = pOffencer->GetCID();
node.m_sCurrHP = pOffencer->GetStatus().m_nNowHP;
node.m_sCurrMP = pOffencer->GetStatus().m_nNowMP;
node.m_wMaxHP = pOffencer->GetStatus().m_StatusInfo.m_nMaxHP;
node.m_wMaxMP = pOffencer->GetStatus().m_StatusInfo.m_nMaxMP;
node.m_wMPHeal = 0;
node.m_cJudge = ClientConstants::Judge_Front;
AtType attackType;
attackType.m_wType = AtType::RIGHT_MELEE;
const int MAX_BUFFER = sizeof(PktAtAck) + AtNode::MAX_DEFENDER_NUM * sizeof(DefenserNode);
char szBuffer[MAX_BUFFER];
PktAtAck* lpPktAtAck = reinterpret_cast<PktAtAck*>(szBuffer);
DefenserNode* lpDefenserNode = reinterpret_cast<DefenserNode*>(lpPktAtAck + 1);
lpDefenserNode = &node;
lpPktAtAck->m_dwCharID = m_dwCID;
lpPktAtAck->m_AtType = attackType;
lpPktAtAck->m_wHP = m_CreatureStatus.m_nNowHP;
lpPktAtAck->m_wMP = m_CreatureStatus.m_nNowMP;
lpPktAtAck->m_wMPHeal = 0;
lpPktAtAck->m_cJudge = ClientConstants::Judge_Front;
lpPktAtAck->m_cDefenserNum = 1;
CGameClientDispatch* lpDispatch = NULL;
if (Creature::CT_PC == Creature::GetCreatureType(m_dwCID))
{
CCharacter* pDeffencerCharacter = CCreatureManager::GetInstance().GetCharacter(m_dwCID);
if (NULL != pDeffencerCharacter)
{
lpDispatch = pDeffencerCharacter->GetDispatcher();
}
}
else if (Creature::CT_PC == Creature::GetCreatureType(pOffencer->GetCID()))
{
CCharacter* pOffencerCharacter = CCreatureManager::GetInstance().GetCharacter(pOffencer->GetCID());
if (NULL != pOffencerCharacter)
{
lpDispatch = pOffencerCharacter->GetDispatcher();
}
}
else
{
CCell* lpCell = pOffencer->GetCellPos().m_lpCell;
if (NULL != lpCell)
{
lpCell->SendAttackInfo(m_dwCID, attackType, 1, &node);
}
}
if (NULL != lpDispatch)
{
GameClientSendPacket::SendCharAttacked(lpDispatch->GetSendStream(), this, pOffencer,
attackType, 0, nRefrectionDamage, ClientConstants::Judge_Front, 0, PktBase::NO_SERVER_ERR);
CSendStream& SendStream = lpDispatch->GetSendStream();
if (true == SendStream.WrapCompress(
szBuffer, sizeof(PktAtAck) + sizeof(DefenserNode), CmdCharAttack, 0, wError) &&
PktBase::NO_SERVER_ERR == wError)
{
CCell* lpCell = pOffencer->GetCellPos().m_lpCell;
if (NULL != lpCell)
{
lpCell->SendAttackInfo(m_dwCID, attackType, 1, &node);
}
}
}
this->GetSpellMgr().GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::Guard);
}
}
}
else
{
// ÇǰÝÀÚ¿¡°Ô °¡µå 5´Ü°è ½ºÅ³ÀÌ»óÀÇ °¡µå ½ºÆçÀÌ ¹ßµ¿µÇ¾î ÀÖÀ» ¶§ ÆòŸ ÇÇ°Ý µ¥¹ÌÁö °¨¼Ò
float fDecreaseRate = static_cast<unsigned short>(5 + (pSpell->GetSkillLevel() * 2.5f)) / 100.0f;
nDamage = nDamage - static_cast<unsigned short>(nDamage * fDecreaseRate);
}
}
}
// Threat °ª º¯µ¿ ó¸®
if (nDamage > 0)
{
// ¼º¹®Àº ¼º¹® ¸·±â¸¦ ÅëÇØ¼­ ºí·°·üÀ» ³ôÀ̰í, ¸·°í Àִ ij¸¯ÅÍ¿¡°Ô µ¥¹ÌÁö°¡ ³ª´²Á®°£´Ù.
if (Creature::CT_SIEGE_OBJECT == eCreatureType)
{
CSiegeObject* lpSiegeObject = reinterpret_cast<CSiegeObject *>(this);
if (lpSiegeObject && lpSiegeObject->IsGate())
{
reinterpret_cast<CCastleGate*>( lpSiegeObject )->DivideDamage(pOffencer, nDamage);
reinterpret_cast<CCastleGate*>( lpSiegeObject )->SendProtectGateInfo();
}
}
const unsigned short nThreatAmount = (m_CreatureStatus.m_nNowHP < nDamage) ? m_CreatureStatus.m_nNowHP : nDamage;
m_Threat.AddToThreatList(pOffencer, nThreatAmount);
m_CreatureStatus.m_nNowHP = (m_CreatureStatus.m_nNowHP > nDamage) ? m_CreatureStatus.m_nNowHP - nDamage : 0;
CMonster* pMonsterDefender = NULL;
if (Creature::CT_MONSTER == eCreatureType ||
Creature::CT_SUMMON == eCreatureType ||
Creature::CT_STRUCT == eCreatureType)
{
pMonsterDefender = reinterpret_cast<CMonster *>(this);
pMonsterDefender->Attacked();
// ÄÁÅÙÃ÷ : ´ÙÅ© Ä«³ª¹ø ±¹°¡ ÀüÀï
if (true == CServerSetup::GetInstance().UseContents(GameRYL::STONE_BATTLE))
{
// ´ÙÅ© Ä«³ª¹ø ¼®»óÀÌ °ø°Ý ´çÇϸé HP Á¤º¸¸¦ ¾÷µ¥ÀÌÆ® ÇÑ´Ù.
if (SERVER_ID::STONE_WAR1 <= CServerSetup::GetInstance().GetServerZone() && CServerSetup::GetInstance().GetServerZone() <= SERVER_ID::STONE_WAR3)
{
CStatue* lpStatue = pMonsterDefender->DowncastToStatue();
if (NULL != lpStatue)
{
lpStatue->SendHPUpdate();
lpStatue->SendAttacked();
}
}
}
/*
// ÄÁÅÙÃ÷ : ½Å±ÔÁ¸
if (true == CServerSetup::GetInstance().UseContents(GameRYL::NEWZONE_ZONE9))
{
// »ý¸íÃàÃâ±â°¡ °ø°Ý ´çÇϸé HP Á¤º¸¸¦ ¾÷µ¥ÀÌÆ® ÇÑ´Ù.
if (CServerSetup::GetInstance().GetServerZone() == SERVER_ID::ZONE9)
{
CStatue* lpStatue = pMonsterDefender->DowncastToStatue();
if (NULL != lpStatue)
{
lpStatue->SendHPUpdate();
lpStatue->SendAttacked();
}
}
}
*/
}
// °ø¼º ¿ÀºêÁ§Æ®¶ó¸é HP Á¤º¸¸¦ DBÁß°è ¼­¹ö¿¡ ¾÷µ¥ÀÌÆ®ÇÑ´Ù.
if (Creature::CT_SIEGE_OBJECT == eCreatureType)
{
CSiegeObject* lpSiegeObject = reinterpret_cast<CSiegeObject *>(this);
if (lpSiegeObject)
{
lpSiegeObject->SendHPUpdateToDBAgent();
if (lpSiegeObject->IsCamp())
{
// °ø°Ý ´çÇϰí ÀÖ´Ù´Â ¸Þ¼¼Áö¸¦ º¸³»ÁØ´Ù.
reinterpret_cast<CCamp*>(lpSiegeObject)->SendAttackedMessage();
}
else if (lpSiegeObject->IsEmblem())
{
// °ø°Ý ´çÇϰí ÀÖ´Ù´Â ¸Þ¼¼Áö¸¦ º¸³»ÁØ´Ù.
reinterpret_cast<CCastleEmblem*>(lpSiegeObject)->SendAttackedMessage();
}
}
}
// edith 2008.07.11 µ¥¹ÌÁö ÆßÇÎÀ» °Ë»öÇÏÁö ¾Ê´Â´Ù. ÀÌÀ¯.. ¾ÆÀÌÅÛÀÇ ·¦Á¦°¡ Ç®·È´Ù..
// 1·¦ÀÌ 100·¦ ¾ÆÀÌÅÛÀ» Âø¿ëÈÄ °ø°ÝÀÌ °¡´ÉÇÏ´Ù. µ¥¹ÌÁö ÆßÇÎÀÌ ¹«ÀÇ¹Ì ÇÏ´Ù.
/*
if (0 == (attackType.m_wType & AtType::SKILL_BIT))
{
if (Creature::CT_PC == Creature::GetCreatureType(pOffencer->GetCID()))
{
CCharacter* pCharacter = (CCharacter *)pOffencer;
if (NULL != pMonsterDefender)
{
if (false == GAMELOG::LogDamagePumping(*pCharacter, *pMonsterDefender, nDamage))
{
ERRLOG1(g_Log, "CID:0x%08x µ¥¹ÌÁö ¹üÇÎÀÌ ¹ß»ýÇÏ¿´½À´Ï´Ù.", pOffencer->GetCID());
}
}
}
}
*/
}
// Ư¼ö ÄÉÀ̽ºÀÇ Ã³¸®
switch (cDefenserJudge)
{
case ClientConstants::Judge_Heal: return m_CreatureStatus.m_nNowHP - nPreviousHP;
case ClientConstants::Judge_ManaHeal: return m_CreatureStatus.m_nNowMP - nPreviousMP;
case ClientConstants::Judge_Guard:
m_Threat.AddToThreatList(pOffencer, 1);
break;
}
// Á×¾úÀ» °æ¿ì (ÀÚ»ì ½ºÅ³Àº ¹«È¿)
// ÀÌ¹Ì Á×¾îÀÖ´Â °æ¿ì¿¡ ·¹Á®·º¼Ç ½ºÅ³À» ¹Þ¾ÒÀ»¶§´Â Dead() ÇÔ¼ö¸¦ ´Ù½Ã È£ÃâÇÏÁö ¾Ê´Â´Ù.
if (0 != nPreviousHP && 0 == m_CreatureStatus.m_nNowHP && pOffencer != this)
{
Dead(pOffencer);
m_Threat.ClearAll();
}
return nDamage;
}
unsigned short CAggresiveCreature::CalculateDamage(const FightStatus& OffencerStatusInfo,
const float fLevelGap, unsigned char &cDefenserJudge, unsigned int ExType)
{
// C. µ¥¹ÌÁö »êÃâ
long lDamage = static_cast<long>(Math::Random::ComplexRandom(OffencerStatusInfo.m_lMaxDamage, OffencerStatusInfo.m_lMinDamage) *
(100 - m_CreatureStatus.m_StatusInfo.m_fDefenceRate) / 100.0f);
// G. Å©¸®Æ¼Äà ÆÇÁ¤
float fCriticalRate = OffencerStatusInfo.m_fCriticalRate;
// edith 2009.12.26 PVPÀ϶§ ¿¡Àӵ弦, ºí·¡½ºÆ®ÀÇ °æ¿ì 1/5 Å©¸® È®À²·Î Á¶Á¤
if(ExType != 0)
fCriticalRate = fCriticalRate/ExType;
if (Math::Random::ComplexRandom(10000) < fCriticalRate * 100)
{
lDamage = static_cast<long>(lDamage * OffencerStatusInfo.m_fCriticalMagnification);
cDefenserJudge = ClientConstants::Judge_Critical;
}
// H. ·¹º§°¸, ¿¤¸®Æ® º¸³Ê½º È¿°ú
lDamage = static_cast<long>(lDamage * fLevelGap);
lDamage = max(lDamage, long(0));
lDamage = min(lDamage, USHRT_MAX);
return static_cast<unsigned short>(lDamage);
}
float CAggresiveCreature::CalcDir2D(const float fSrcX, const float fSrcY, const float fDstX, const float fDstY)
{
float fResult;
const float fDX = fDstX - fSrcX;
const float fDY = fDstY - fSrcY;
if (!fDX && !fDY) {
return 0.0f;
}
if (!fDX) {
return (fDY > 0.0f) ? Math::Const::PI * 0.5f : Math::Const::PI * 1.5f;
}
if (!fDY) {
return (fDX > 0.0f) ? 0.0f : Math::Const::PI;
}
const float ufDX = (fDX > 0.0f) ? fDX : fDX * -1.0f;
const float ufDY = (fDY > 0.0f) ? fDY : fDY * -1.0f;
fResult = atanf(ufDY / ufDX);
if (fDX < 0.0f && fDY >= 0.0f) {
fResult = Math::Const::PI - fResult;
}
else if (fDX < 0.0f && fDY < 0.0f) {
fResult += Math::Const::PI;
}
else if (fDX >= 0.0f && fDY < 0.0f) {
fResult = (Math::Const::PI * 2) - fResult;
}
return fResult;
}
bool CAggresiveCreature::RegenHPAndMP(unsigned short usAdditionalHP, unsigned short usAdditionalMP, bool bAddDefaultRegenValue)
{
if (0 == m_CreatureStatus.m_nNowHP) { return false; }
short usHPRegen = usAdditionalHP;
short usMPRegen = usAdditionalMP;
if (true == bAddDefaultRegenValue)
{
usHPRegen += m_CreatureStatus.m_StatusInfo.m_wHPRegen;
usMPRegen += m_CreatureStatus.m_StatusInfo.m_wMPRegen;
if (true == m_bSitDown)
{
// edith 2009.08.07 ¾É¾ÆÀÖÀ»´ë ¸®Á¨°ªÀ» ³ôÀδÙ.
usHPRegen += (m_CreatureStatus.m_StatusInfo.m_wHPRegen*2);
usMPRegen += (m_CreatureStatus.m_StatusInfo.m_wMPRegen*2);
// usHPRegen += m_CreatureStatus.m_StatusInfo.m_nMaxHP / 10;
// usMPRegen += m_CreatureStatus.m_StatusInfo.m_nMaxMP / 10;
}
}
m_CreatureStatus.m_nNowHP = (m_CreatureStatus.m_nNowHP + usHPRegen < m_CreatureStatus.m_StatusInfo.m_nMaxHP) ?
m_CreatureStatus.m_nNowHP + usHPRegen : m_CreatureStatus.m_StatusInfo.m_nMaxHP;
m_CreatureStatus.m_nNowMP = (m_CreatureStatus.m_nNowMP + usMPRegen < m_CreatureStatus.m_StatusInfo.m_nMaxMP) ?
m_CreatureStatus.m_nNowMP + usMPRegen : m_CreatureStatus.m_StatusInfo.m_nMaxMP;
return true;
}