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>
This commit is contained in:
@@ -0,0 +1,898 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Purpose : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> & <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> Ŭ<><C5AC><EFBFBD><EFBFBD>
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <Utility/Registry/RegFunctions.h>
|
||||
#include <Utility/Math/Math.h>
|
||||
#include <Utility/Time/Pulse/Pulse.h>
|
||||
#include <Utility/DelimitedFile.h>
|
||||
#include <Utility/Setup/ServerSetup.h>
|
||||
|
||||
#include <Network/ClientSocket/ClientConstants.h>
|
||||
#include <Network/Dispatch/GameClient/SendCharAttack.h>
|
||||
#include <Network/Dispatch/GameClient/GameClientDispatch.h>
|
||||
#include <Network/Packet/PacketStruct/ServerInfo.h>
|
||||
#include <Network/Packet/WrapPacket.h>
|
||||
#include <Network/Packet/PacketCommand.h>
|
||||
|
||||
#include <Creature/CreatureManager.h>
|
||||
#include <Creature/Monster/PatternMonster.h>
|
||||
#include <Creature/Siege/SiegeObject.h>
|
||||
#include <Creature/EnemyCheck.h>
|
||||
|
||||
#include <Community/Party/Party.h>
|
||||
#include <Community/Party/PartyMgr.h>
|
||||
#include <Community/Guild/Guild.h>
|
||||
#include <Community/Guild/GuildMgr.h>
|
||||
|
||||
#include <Castle/Castle.h>
|
||||
#include <Castle/CastleMgr.h>
|
||||
|
||||
#include <GameTime/GameTimeConstants.h>
|
||||
#include <GameTime/GameTimeMgr.h>
|
||||
|
||||
#include <Map/FieldMap/CellManager.h>
|
||||
#include <Skill/Spell/Spell.h>
|
||||
#include <Log/CharacterLog.h>
|
||||
|
||||
#include "AwardTable.h"
|
||||
#include "Monster.h"
|
||||
#include "MonsterShout.h"
|
||||
|
||||
|
||||
LONG CMonster::ms_NormalBehaviorSendCount = 0;
|
||||
LONG CMonster::ms_AttackBehaviorSendCount = 0;
|
||||
LONG CMonster::ms_ReturnBehaviorSendCount = 0;
|
||||
LONG CMonster::ms_EscapeBehaviorSendCount = 0;
|
||||
LONG CMonster::ms_DeadBehaviorSendCount = 0;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
CMonster::CMonster()
|
||||
: m_lpTarget(NULL), m_dwLastBehaviorTick(0), m_lCurrentFrame(0), m_bAttacking(false), m_nCurrentState(0), m_wSearchRange(0),
|
||||
m_nNormalMovingDelay(0), m_nLeaveMovingNum(0), m_bAvoid(false), m_bLongRangeAttacked(false), m_bAdminCmdSummon(false),
|
||||
m_bScout(false), m_nMovingPattern(0), m_OriginalPosition(), CAggresiveCreature(0), m_dwPID(0), m_wRespawnArea(0)
|
||||
{
|
||||
m_wDefaultSearchRange = MONSTER_SEARCH_RANGE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Function : CMonster::CMonster
|
||||
//
|
||||
// Description : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//
|
||||
// Inputs : MonsterCreate - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
//
|
||||
// Outputs : None.
|
||||
//
|
||||
// Returns : None.
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
CMonster::CMonster(MonsterCreateInfo& MonsterCreate, bool bAdminCmdSummon)
|
||||
: m_lpTarget(NULL), m_dwLastBehaviorTick(0), m_lCurrentFrame(0), m_bAttacking(false), m_nCurrentState(0), m_wSearchRange(0),
|
||||
m_nNormalMovingDelay(0), m_nLeaveMovingNum(0), m_bAvoid(false), m_bLongRangeAttacked(false), m_bAdminCmdSummon(bAdminCmdSummon),
|
||||
m_bScout(MonsterCreate.m_bScout), m_nMovingPattern(MonsterCreate.m_nMovingPattern), m_wRespawnArea(MonsterCreate.m_wRespawnArea),
|
||||
m_OriginalPosition(MonsterCreate.m_Pos), CAggresiveCreature(MonsterCreate.m_dwCID), m_dwPID(MonsterCreate.m_dwPID)
|
||||
{
|
||||
const CMonsterMgr::MonsterProtoType* pProtoType =
|
||||
CMonsterMgr::GetInstance().GetMonsterProtoType(MonsterCreate.m_nKID);
|
||||
|
||||
if (NULL == pProtoType)
|
||||
{
|
||||
ERRLOG1(g_Log, "<EFBFBD>˸<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><C5B8><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>. MonsterProtoType.txt<78><74> Ȯ<><C8AE><EFBFBD><EFBFBD><EFBFBD>ֽʽÿ<CABD>. KID:%d", MonsterCreate.m_nKID);
|
||||
return;
|
||||
}
|
||||
|
||||
m_CreatureStatus = pProtoType->m_CreatureStatus;
|
||||
m_MonsterInfo = pProtoType->m_MonsterInfo;
|
||||
|
||||
m_CreatureStatus.m_StatusInfo.CalculateSubStatus();
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD> æƮ ȿ<><C8BF> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>մϴ<D5B4>.
|
||||
m_EquipStatus = pProtoType->m_CreatureStatus.m_StatusInfo;
|
||||
m_EquipStatus.m_cCalculateState = FightStatus::CS_EQUIP_INFO;
|
||||
|
||||
m_wDefaultSearchRange = MONSTER_SEARCH_RANGE;
|
||||
}
|
||||
|
||||
|
||||
CMonster::~CMonster()
|
||||
{
|
||||
m_SpellMgr.GetAffectedInfo().ClearAll();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Function : CMonster::InitMonster
|
||||
//
|
||||
// Description : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʱ<EFBFBD>ȭ
|
||||
//
|
||||
// Inputs : Pos - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ
|
||||
// bDead - ó<><C3B3> <20>α<EFBFBD> <20><><EFBFBD><EFBFBD> true, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ÿ<EFBFBD> false
|
||||
//
|
||||
// Outputs : None.
|
||||
//
|
||||
// Returns : <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
bool CMonster::InitMonster(Position &Pos, bool bDead)
|
||||
{
|
||||
m_CellPos.MoveTo(Pos);
|
||||
if (NULL == m_CellPos.m_lpCell)
|
||||
{
|
||||
ERRLOG4(g_Log, "CID:0x%08x <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20>α<EFBFBD><CEB1>Ͽ<EFBFBD><CFBF><EFBFBD><EFBFBD>ϴ<EFBFBD>. X:%.1f, Y:%.1f, Z:%.1f",
|
||||
m_dwCID, Pos.m_fPointX, Pos.m_fPointY, Pos.m_fPointZ);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_CurrentPos = Pos;
|
||||
m_wSearchRange = m_wDefaultSearchRange;
|
||||
|
||||
m_lpTarget = NULL;
|
||||
|
||||
m_lCurrentFrame = 0;
|
||||
m_bAttacking = false;
|
||||
m_dwLastBehaviorTick = m_dwLastTime = CPulse::GetInstance().GetLastTick();
|
||||
|
||||
ZeroMemory(&m_MotionInfo, sizeof(m_MotionInfo));
|
||||
|
||||
if (bDead)
|
||||
{
|
||||
m_nCurrentState = STATE_ID_DIE;
|
||||
m_CreatureStatus.m_nNowHP = 0;
|
||||
m_CreatureStatus.m_nNowMP = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_CellPos.m_lpCell->SetCreature(m_dwCID, this);
|
||||
|
||||
m_nCurrentState = STATE_ID_NORMAL;
|
||||
m_CreatureStatus.m_nNowHP = m_CreatureStatus.m_StatusInfo.m_nMaxHP;
|
||||
m_CreatureStatus.m_nNowMP = m_CreatureStatus.m_StatusInfo.m_nMaxMP;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Function : CMonster::GetMotion
|
||||
//
|
||||
// Description : <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
//
|
||||
// Inputs : MotionID - <20><><EFBFBD><EFBFBD> ID
|
||||
//
|
||||
// Outputs : Motion - <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
//
|
||||
// Returns : bool - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ID<49><44> false.
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
bool CMonster::GetMotion(unsigned long MotionID, MotionInfo &Motion)
|
||||
{
|
||||
int nIndex = 0;
|
||||
|
||||
switch (MotionID)
|
||||
{
|
||||
case MonsterInfo::Z3D_CA_WALK: nIndex = 0; break;
|
||||
case MonsterInfo::Z3D_CA_RUN: nIndex = 1; break;
|
||||
case MonsterInfo::Z3D_CA_ATTACK: nIndex = 2; break;
|
||||
case MonsterInfo::Z3D_CA_CASTING: nIndex = 3; break;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> <20><> <20>ȴ<EFBFBD>.
|
||||
Motion.m_wAction = m_MonsterInfo.m_MonsterMotions[nIndex].m_wAction;
|
||||
Motion.m_dwFrame = m_MonsterInfo.m_MonsterMotions[nIndex].m_dwFrame;
|
||||
Motion.m_fVelocity = m_MonsterInfo.m_MonsterMotions[nIndex].m_fVelocity;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Function : CMonster::IsOverlap
|
||||
//
|
||||
// Description : <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ°<D6B4>?
|
||||
//
|
||||
// Inputs : None.
|
||||
//
|
||||
// Outputs : None.
|
||||
//
|
||||
// Returns : bool - <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Yes/No
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
bool CMonster::IsOverlap(void)
|
||||
{
|
||||
for (int nCellCount = 0; nCellCount < CCell::CONNECT_NUM; ++nCellCount)
|
||||
{
|
||||
CCell* pCell = m_CellPos.m_lpCell->GetConnectCell(nCellCount);
|
||||
if (NULL == pCell || false == pCell->IsMonster())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CMonster* lpTempMonster = pCell->GetFirstMonster();
|
||||
|
||||
while (NULL != lpTempMonster)
|
||||
{
|
||||
if (this != lpTempMonster)
|
||||
{
|
||||
const float fDX = lpTempMonster->GetCurrentPos().m_fPointX - GetCurrentPos().m_fPointX;
|
||||
const float fDZ = lpTempMonster->GetCurrentPos().m_fPointZ - GetCurrentPos().m_fPointZ;
|
||||
|
||||
if (fDX * fDX + fDZ * fDZ <= 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
lpTempMonster = pCell->GetNextMonster();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Function : CMonster::UpdateBehavior
|
||||
//
|
||||
// Description : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ൿ <20><><EFBFBD><EFBFBD>
|
||||
//
|
||||
// Inputs : dwTick - <20><><EFBFBD><EFBFBD> ƽī<C6BD><C4AB>Ʈ
|
||||
//
|
||||
// Outputs : None.
|
||||
//
|
||||
// Returns : None.
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
void CMonster::UpdateBehavior(unsigned long dwTick)
|
||||
{
|
||||
// <20><><EFBFBD>ӵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD>/<2F><>ȭ<EFBFBD><C8AD> <20>ɸ<EFBFBD><C9B8><EFBFBD> <20>ʴ´<CAB4>.
|
||||
if (MonsterInfo::PATTERN_NAMED == m_MonsterInfo.m_cSkillPattern)
|
||||
{
|
||||
m_SpellMgr.GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::Stun);
|
||||
m_SpellMgr.GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::StoneForm);
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>/<2F><>ȭ<EFBFBD>ÿ<EFBFBD> <20>ƹ<EFBFBD> <20>ൿ<EFBFBD><E0B5BF> <20><><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
|
||||
if (GetEnchantInfo().GetFlag(Skill::SpellID::Stun) ||
|
||||
GetEnchantInfo().GetFlag(Skill::SpellID::StoneForm))
|
||||
{
|
||||
m_lCurrentFrame = FPS;
|
||||
return;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD>¿<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ൿ ó<><C3B3><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
|
||||
switch (m_nCurrentState)
|
||||
{
|
||||
case STATE_ID_NORMAL: NormalBehavior(dwTick); break; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
case STATE_ID_ATTACK: AttackBehavior(dwTick); break; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (<28>Ÿ<EFBFBD><C5B8><EFBFBD> <20>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD> <20>Ѿư<D1BE><C6B0><EFBFBD>...)
|
||||
case STATE_ID_RETURN: ReturnBehavior(dwTick); break; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (<28><> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD>ư<EFBFBD><C6B0><EFBFBD>...)
|
||||
case STATE_ID_ESCAPE: EscapeBehavior(); break; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
case STATE_ID_DIE: DeadBehavior(dwTick); break; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>~)
|
||||
}
|
||||
|
||||
/*
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>α<EFBFBD>
|
||||
char logString[MAX_PATH];
|
||||
switch (m_nCurrentState)
|
||||
{
|
||||
case STATE_ID_NORMAL: strcpy(logString, "Normal"); break;
|
||||
case STATE_ID_ATTACK: strcpy(logString, "Attack"); break;
|
||||
case STATE_ID_RETURN: strcpy(logString, "Return"); break;
|
||||
case STATE_ID_ESCAPE: strcpy(logString, "Escape"); break;
|
||||
case STATE_ID_DIE: strcpy(logString, "Die"); break;
|
||||
}
|
||||
|
||||
DETLOG3(g_Log, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>α<EFBFBD> - * State : %s\t* fX : %f\t* fZ : %f",
|
||||
logString, GetCurrentPos().m_fPointX, GetCurrentPos().m_fPointZ);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Function : CMonster::Process
|
||||
//
|
||||
// Description : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>μ<EFBFBD><CEBC><EFBFBD>
|
||||
//
|
||||
// Inputs : None.
|
||||
//
|
||||
// Outputs : None.
|
||||
//
|
||||
// Returns : bool - <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>߿<EFBFBD> false
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
bool CMonster::Process()
|
||||
{
|
||||
const unsigned long dwTick = CPulse::GetInstance().GetLastTick();
|
||||
|
||||
if (dwTick - m_dwLastBehaviorTick < FPS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((GetSerialNumber() % 3) != (CPulse::GetInstance().GetCurrentPulse() % 3))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned long dwFrame = ((dwTick - m_dwLastBehaviorTick) / FPS);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD>մϴ<D5B4>. (<28>̵<EFBFBD><CCB5>ϸ鼭 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
|
||||
if (m_lCurrentFrame <= 0 || m_bAttacking == true)
|
||||
{
|
||||
if (m_lCurrentFrame <= 0 && m_bAttacking == true) {
|
||||
m_bAttacking = false;
|
||||
}
|
||||
|
||||
UpdateBehavior(dwTick);
|
||||
}
|
||||
|
||||
// ƽ <20><><EFBFBD><EFBFBD>
|
||||
m_dwLastBehaviorTick = dwTick;
|
||||
|
||||
unsigned long dwSlowlyRate = (true == GetEnchantInfo().GetFlag(Skill::SpellID::Frozen)) ? 2 : 1;
|
||||
|
||||
m_lCurrentFrame -= (dwFrame / dwSlowlyRate);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Function : CMonster::MultiAttack
|
||||
//
|
||||
// Description : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><> Ÿ<><C5B8><EFBFBD><EFBFBD> <20>˻<EFBFBD>
|
||||
//
|
||||
// Inputs : None.
|
||||
//
|
||||
// Outputs : None.
|
||||
//
|
||||
// Returns : None.
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
bool CMonster::MultiAttack(void)
|
||||
{
|
||||
unsigned char cDefenderNum = 1;
|
||||
CAggresiveCreature* ppAggresiveCreature[AtNode::MAX_DEFENDER_NUM];
|
||||
unsigned char nDefenserJudges[AtNode::MAX_DEFENDER_NUM];
|
||||
|
||||
ppAggresiveCreature[0] = m_lpTarget;
|
||||
|
||||
// TODO : <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>սô<D5BD>. (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
|
||||
short nMaxDefenderNum = AtNode::MAX_DEFENDER_NUM;
|
||||
std::fill_n(&nDefenserJudges[0], nMaxDefenderNum, ClientConstants::Judge_Front);
|
||||
|
||||
float fDir = CalcDir2D(GetCurrentPos().m_fPointX, GetCurrentPos().m_fPointZ,
|
||||
m_lpTarget->GetCurrentPos().m_fPointX, m_lpTarget->GetCurrentPos().m_fPointZ);
|
||||
|
||||
AtType attackType;
|
||||
attackType.m_wType = AtType::RIGHT_MELEE;
|
||||
char cTargetType = Skill::Target::ENEMY;
|
||||
|
||||
return CAggresiveCreature::MultiAttack(attackType, cDefenderNum, ppAggresiveCreature, nDefenserJudges,
|
||||
GetCurrentPos(), fDir, m_MonsterInfo.m_wAttackRange / 100.0f, m_MonsterInfo.m_fAttackAngle, cTargetType);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Function : CMonster::CancelTarget
|
||||
//
|
||||
// Description : Ÿ<><C5B8><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
//
|
||||
// Inputs : bool bSaveThreat - <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ°<CFB4>?
|
||||
//
|
||||
// Outputs : None.
|
||||
//
|
||||
// Returns : None.
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
void CMonster::CancelTarget(bool bSaveThreat)
|
||||
{
|
||||
if (NULL != m_lpTarget)
|
||||
{
|
||||
if (!bSaveThreat)
|
||||
{
|
||||
m_lpTarget->GetThreat().DeleteThreatened(this);
|
||||
m_Threat.DeleteThreat(m_lpTarget);
|
||||
}
|
||||
|
||||
// <20><>Ƽ<EFBFBD><C6BC> <20>־<EFBFBD><D6BE>ٸ<EFBFBD>.. <20><>Ƽ<EFBFBD><C6BC> Ÿ<>ٿ<EFBFBD><D9BF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
||||
CMonsterParty* lpParty = reinterpret_cast<CMonsterParty*>(GetParty());
|
||||
if (NULL != lpParty)
|
||||
{
|
||||
CMonsterParty::PartyTargetSet::iterator itr = lpParty->GetPartyTargetSet().find(m_lpTarget->GetCID());
|
||||
if (itr != lpParty->GetPartyTargetSet().end())
|
||||
{
|
||||
lpParty->GetPartyTargetSet().erase(itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_lpTarget = NULL;
|
||||
m_bAttacking = false;
|
||||
m_nCurrentState = CFSM::GetInstance().StateTransition(m_nCurrentState, INPUT_ID_LEAVE_PLAYER);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Function : CMonster::Dead
|
||||
//
|
||||
// Description : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3>
|
||||
//
|
||||
// Inputs : None.
|
||||
//
|
||||
// Outputs : None.
|
||||
//
|
||||
// Returns : <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. (false<73><65> Ÿ<>ٵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
bool CMonster::Dead(CAggresiveCreature* pOffencer)
|
||||
{
|
||||
m_dwLastBehaviorTick = m_dwLastTime = CPulse::GetInstance().GetLastTick();
|
||||
m_lCurrentFrame = FPS;
|
||||
m_bAttacking = false;
|
||||
|
||||
m_nCurrentState = CFSM::GetInstance().StateTransition(m_nCurrentState, INPUT_ID_ZERO_HP);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ó<><C3B3>
|
||||
unsigned long aryItemID[AwardTable::MAX_DROP_ITEM + EliteBonus::MAX_BONUS_DROP_ITEM] = { 0, };
|
||||
|
||||
Item::CItem* aryItem[AwardTable::MAX_DROP_ITEM + EliteBonus::MAX_BONUS_DROP_ITEM] = { 0, };
|
||||
|
||||
unsigned long dwOwnerID = 0;
|
||||
unsigned char cItemNum = m_Threat.GetAward(aryItemID, aryItem, &dwOwnerID);
|
||||
|
||||
Position SetPosition;
|
||||
CCell::ItemInfo itemInfo;
|
||||
|
||||
CCell* lpDropCell = GetCellPos().m_lpCell;
|
||||
|
||||
if (NULL != lpDropCell)
|
||||
{
|
||||
for (unsigned char cDropIndex = 0; cDropIndex < cItemNum; ++cDropIndex)
|
||||
{
|
||||
if (0 != aryItemID[cDropIndex])
|
||||
{
|
||||
SetPosition = GetCurrentPos();
|
||||
SetPosition.m_fPointX += cDropIndex;
|
||||
if (cItemNum / 2 <= cDropIndex)
|
||||
{
|
||||
SetPosition.m_fPointX -= cItemNum / 2;
|
||||
SetPosition.m_fPointZ += 1.0f;
|
||||
}
|
||||
|
||||
unsigned long dwGold = (NULL == aryItem[cDropIndex]) ? (aryItemID[cDropIndex] & ~CCell::TYPE_CHECK_BIT) : 0;
|
||||
|
||||
if(pOffencer->GetStatus().m_nLevel<=GOLD_INC_LEVEL_LIMIT)
|
||||
{
|
||||
dwGold = static_cast<unsigned long>( dwGold * 1.5f );
|
||||
}
|
||||
|
||||
lpDropCell->SetItem(SetPosition, aryItem[cDropIndex], dwGold, dwOwnerID, CCell::PARTY, itemInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1> <20>й<EFBFBD><D0B9>Ѵ<EFBFBD>.
|
||||
const long lMaxThreat = m_Threat.GetMaxThreatAmount();
|
||||
m_Threat.DivisionExp();
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
||||
m_CellPos.m_lpCell->DeleteCreature(m_dwCID);
|
||||
|
||||
CAggresiveCreature *pCreature = m_Threat.GetMaxThreatCreature();
|
||||
if (NULL != pCreature)
|
||||
{
|
||||
if (m_CreatureStatus.m_nLevel - pCreature->GetStatus().m_nLevel >= 3 &&
|
||||
lMaxThreat > m_CreatureStatus.m_StatusInfo.m_nMaxHP * 0.8f)
|
||||
{ // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3 <20>̻<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>α<CEB1> <20><><EFBFBD><EFBFBD>
|
||||
RULLOG5(g_Log, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͳ<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ư<EFBFBD><C6B0>̽<EFBFBD><CCBD>ϴ<EFBFBD>... Monster : 0x%08x (%d), Player : 0x%08x (%d), ȹ<><C8B9> <20><><EFBFBD><EFBFBD>ġ <20><><EFBFBD><EFBFBD> : %.1f%%",
|
||||
m_dwCID, m_CreatureStatus.m_nLevel, m_Threat.GetMaxThreatCreature()->GetCID(),
|
||||
m_Threat.GetMaxThreatCreature()->GetStatus().m_nLevel, lMaxThreat * 100.0f / m_CreatureStatus.m_StatusInfo.m_nMaxHP);
|
||||
}
|
||||
|
||||
CCharacter* lpOffencerCharacter =
|
||||
(Creature::CT_PC == Creature::GetCreatureType(pCreature->GetCID()))
|
||||
? static_cast<CCharacter*>(pCreature) : 0;
|
||||
|
||||
if (0 != lpOffencerCharacter)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD>Ʈ Ʈ<><C6AE><EFBFBD><EFBFBD> <20>ߵ<EFBFBD>
|
||||
lpOffencerCharacter->CheckTrigger(Quest::TRIGGER_KILL, m_MonsterInfo.m_dwKID, m_CurrentPos, 1);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>α<CEB1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><D7B8><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ID <20><> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD>
|
||||
GAMELOG::LogMonsterDead(*lpOffencerCharacter, GetCID(),
|
||||
m_CreatureStatus.m_nLevel, aryItemID, cItemNum);
|
||||
}
|
||||
}
|
||||
|
||||
// <20><>Ƽ<EFBFBD><C6BC><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
CParty* lpParty = GetParty();
|
||||
if (NULL != lpParty)
|
||||
{
|
||||
lpParty->Leave(GetCID(), 0, GetMapIndex());
|
||||
}
|
||||
|
||||
return CAggresiveCreature::Dead(pOffencer);
|
||||
}
|
||||
|
||||
|
||||
EnemyCheck::EnemyType CMonster::IsEnemy(CCreature* lpTarget, unsigned char* cResult)
|
||||
{
|
||||
if (NULL != lpTarget)
|
||||
{
|
||||
switch (Creature::GetCreatureType(lpTarget->GetCID()))
|
||||
{
|
||||
case Creature::CT_PC:
|
||||
case Creature::CT_SUMMON:
|
||||
case Creature::CT_SIEGE_OBJECT:
|
||||
{
|
||||
return lpTarget->IsEnemy(this);
|
||||
}
|
||||
|
||||
case Creature::CT_NPC:
|
||||
case Creature::CT_MONSTER:
|
||||
case Creature::CT_STRUCT:
|
||||
{
|
||||
if (GetNation() == lpTarget->GetNation())
|
||||
{
|
||||
return EnemyCheck::EC_FRIEND;
|
||||
}
|
||||
|
||||
return EnemyCheck::EC_ENEMY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ERRLOG1(g_Log, "CID:0x%08x <20>Ǿƽĺ<C6BD><C4BA><EFBFBD> Ÿ<><C5B8><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>.", m_dwCID);
|
||||
return EnemyCheck::EC_NEUTRAL;
|
||||
}
|
||||
|
||||
|
||||
void CMonster::Respawn(unsigned long dwTick)
|
||||
{
|
||||
Position RespawnPos(m_OriginalPosition.m_fPointX, m_OriginalPosition.m_fPointY, m_OriginalPosition.m_fPointZ);
|
||||
|
||||
if (m_nMovingPattern != FIXED && m_wRespawnArea > 0)
|
||||
{
|
||||
RespawnPos.m_fPointX += static_cast<float>(Math::Random::SimpleRandom(dwTick, m_wRespawnArea*2) - m_wRespawnArea);
|
||||
RespawnPos.m_fPointY += m_OriginalPosition.m_fPointY;
|
||||
RespawnPos.m_fPointZ += static_cast<float>(Math::Random::SimpleRandom(dwTick, m_wRespawnArea*2) - m_wRespawnArea);
|
||||
}
|
||||
|
||||
InitMonster(RespawnPos);
|
||||
m_nCurrentState = STATE_ID_NORMAL;
|
||||
|
||||
// <20><>Ƽ<EFBFBD><C6BC> <20>߰<EFBFBD>
|
||||
CParty* lpParty = CPartyMgr::GetInstance().GetParty(GetPID());
|
||||
if (NULL != lpParty)
|
||||
{
|
||||
SetParty(lpParty);
|
||||
lpParty->Join(GetCID(), 0, NULL, GetMapIndex());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Function : CMonster::SendMove
|
||||
//
|
||||
// Description : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>̵<EFBFBD> <20><>Ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//
|
||||
// Inputs : None.
|
||||
//
|
||||
// Outputs : Send<6E><64> <20><><EFBFBD><EFBFBD> Ƚ<><C8BD>.
|
||||
//
|
||||
// Returns : None.
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
LONG CMonster::SendMove(unsigned short nAniNum)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>¡<EFBFBD><C2A1><EFBFBD><EFBFBD> MonMove <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ´<CAB4>. (<28><><EFBFBD>ݽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD>...)
|
||||
if (Creature::CT_SIEGE_OBJECT == Creature::GetCreatureType(m_dwCID))
|
||||
{
|
||||
CSiegeObject* lpSiegeObject = reinterpret_cast<CSiegeObject* >(this);
|
||||
if (lpSiegeObject && (lpSiegeObject->IsCamp() || lpSiegeObject->IsEmblem()))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
LONG nSendCount = 0;
|
||||
|
||||
if (true == GetEnchantInfo().GetFlag(Skill::SpellID::Hold) ||
|
||||
true == GetEnchantInfo().GetFlag(Skill::SpellID::Stun) ||
|
||||
true == GetEnchantInfo().GetFlag(Skill::SpellID::StoneForm))
|
||||
{
|
||||
m_MotionInfo.m_fVelocity = 0;
|
||||
}
|
||||
|
||||
if (NULL == m_CellPos.m_lpCell)
|
||||
{
|
||||
ERRLOG0(g_Log, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>̵<EFBFBD> <20><>Ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> : <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>.");
|
||||
return nSendCount;
|
||||
}
|
||||
|
||||
PktMM pktMM;
|
||||
memset(&pktMM, 0, sizeof(PktMM));
|
||||
|
||||
pktMM.m_dwMonID = m_dwCID;
|
||||
|
||||
pktMM.m_NetworkPos = CNetworkPos(m_CurrentPos.m_fPointX, m_CurrentPos.m_fPointY, m_CurrentPos.m_fPointZ,
|
||||
m_MotionInfo.m_fDirection, (0 == m_MotionInfo.m_dwFrame) ? 0.0f : m_MotionInfo.m_fVelocity / m_MotionInfo.m_dwFrame);
|
||||
|
||||
pktMM.m_cAct = static_cast<unsigned char>(m_MotionInfo.m_wAction);
|
||||
pktMM.m_cAniNum = static_cast<unsigned char>(nAniNum);
|
||||
|
||||
// BroadCasting <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ī<><C4AB>Ʈ
|
||||
if (0 != m_CellPos.m_lpCell)
|
||||
{
|
||||
++nSendCount;
|
||||
m_CellPos.m_lpCell->SendAllNearCellCharacter(&pktMM, sizeof(PktMM), CmdMonMove);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERRLOG4(g_Log, "CID:0x%08x <20>̻<EFBFBD><CCBB><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>. (%f,%f,%f)", m_dwCID,
|
||||
m_CurrentPos.m_fPointX, m_CurrentPos.m_fPointY, m_CurrentPos.m_fPointZ);
|
||||
}
|
||||
|
||||
m_nLeaveMovingNum = nAniNum;
|
||||
|
||||
return nSendCount;
|
||||
}
|
||||
|
||||
|
||||
const int CMonster::CalculateFixLevelGap(CAggresiveCreature *pDefender)
|
||||
{
|
||||
// << <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><>ġ >>
|
||||
// - ij<><C4B3><EFBFBD>Ϳ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ũ<EFBFBD><C5A9>Ʈ<EFBFBD><C6AE> <20><><EFBFBD>ǵ<EFBFBD> <20><>ġ<EFBFBD><C4A1>ŭ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ɷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
||||
// - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20>̿<EFBFBD><CCBF>Ѵ<EFBFBD>.
|
||||
|
||||
if (true == m_MonsterInfo.m_bFixLevelGap)
|
||||
{
|
||||
const unsigned char cFixLevelGap = m_CreatureStatus.m_nLevel - m_MonsterInfo.m_cFixLevelGap;
|
||||
if (cFixLevelGap < pDefender->GetStatus().m_nLevel)
|
||||
{
|
||||
return m_MonsterInfo.m_cFixLevelGap;
|
||||
}
|
||||
}
|
||||
|
||||
return CAggresiveCreature::CalculateLevelGap(pDefender);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Function : CMonster::Attack
|
||||
//
|
||||
// Description : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>Ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//
|
||||
// Inputs : pDefender - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//
|
||||
// Outputs : None.
|
||||
//
|
||||
// Returns : None.
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
bool CMonster::Attack(AtType attackType, unsigned char cDefenderNum,
|
||||
CAggresiveCreature** ppDefenders, unsigned char* cDefenderJudges, unsigned short* wDefenderMPHeal)
|
||||
{
|
||||
if (m_CreatureStatus.m_nNowHP == 0)
|
||||
{
|
||||
ERRLOG1(g_Log, "CID:0x%08x <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD> <20>Ͽ<EFBFBD><CFBF><EFBFBD><EFBFBD>ϴ<EFBFBD>.", m_dwCID);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cDefenderNum > AtNode::MAX_DEFENDER_NUM)
|
||||
{
|
||||
ERRLOG2(g_Log, "CID:0x%08x <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ڰ<EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ڸ<EFBFBD> <20>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD>ϴ<EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD> : %d",
|
||||
m_dwCID, cDefenderNum);
|
||||
cDefenderNum = AtNode::MAX_DEFENDER_NUM;
|
||||
}
|
||||
|
||||
// MON_TODO : by Vincent - 2004 : 2 : 25
|
||||
DefenserNode Defenser[AtNode::MAX_DEFENDER_NUM] = {0, };
|
||||
int nDefenserCount = 0;
|
||||
// ------------
|
||||
|
||||
for (unsigned char cDefender = 0; cDefender < cDefenderNum; ++cDefender)
|
||||
{
|
||||
if (NULL == ppDefenders[cDefender]) { continue; }
|
||||
|
||||
CCharacter* lpCharacter = NULL;
|
||||
CMonster* lpSummonee = NULL;
|
||||
|
||||
// Ÿ<><C5B8><EFBFBD><EFBFBD> ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
if (Creature::CT_PC == Creature::GetCreatureType(ppDefenders[cDefender]->GetCID()))
|
||||
{
|
||||
lpCharacter = reinterpret_cast<CCharacter *>(ppDefenders[cDefender]);
|
||||
lpSummonee = lpCharacter->GetSummonee();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ÿ<><C5B8><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
if (Creature::IsSummonMonster(ppDefenders[cDefender]->GetCID()))
|
||||
{
|
||||
lpCharacter = reinterpret_cast<CSummonMonster *>(ppDefenders[cDefender])->GetMaster();
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == lpCharacter) { continue; }
|
||||
|
||||
unsigned char cOffencerJudge = 0;
|
||||
unsigned short wOffencerMPHeal = 0;
|
||||
unsigned short wError = PktBase::NO_SERVER_ERR;
|
||||
|
||||
const unsigned short wDamage =
|
||||
ppDefenders[cDefender]->ApplyDamage(attackType, this, cOffencerJudge, cDefenderJudges[cDefender], wOffencerMPHeal, wDefenderMPHeal[cDefender], wError);
|
||||
|
||||
if (NULL != lpSummonee)
|
||||
{
|
||||
lpSummonee->GuardMe(this, wDamage);
|
||||
}
|
||||
|
||||
lpCharacter->CalculateEquipDurability((ClientConstants::Judge_Guard == cDefenderJudges[cDefender]) ?
|
||||
AtType::GUARD : AtType::DEFENCE);
|
||||
|
||||
CGameClientDispatch* lpDispatch = lpCharacter->GetDispatcher();
|
||||
if (NULL != lpDispatch)
|
||||
{
|
||||
GameClientSendPacket::SendCharAttacked(lpDispatch->GetSendStream(), this, ppDefenders[cDefender],
|
||||
attackType, m_MotionInfo.m_fDirection, wDamage, cDefenderJudges[cDefender], wDefenderMPHeal[cDefender], wError);
|
||||
}
|
||||
|
||||
Defenser[nDefenserCount].m_cJudge = cDefenderJudges[nDefenserCount];
|
||||
Defenser[nDefenserCount].m_dwCharID = ppDefenders[nDefenserCount]->GetCID();
|
||||
Defenser[nDefenserCount].m_wMaxHP = ppDefenders[nDefenserCount]->GetStatus().m_StatusInfo.m_nMaxHP;
|
||||
Defenser[nDefenserCount].m_wMaxMP = ppDefenders[nDefenserCount]->GetStatus().m_StatusInfo.m_nMaxMP;
|
||||
Defenser[nDefenserCount].m_sCurrHP = ppDefenders[nDefenserCount]->GetStatus().m_nNowHP;
|
||||
Defenser[nDefenserCount].m_sCurrMP = ppDefenders[nDefenserCount]->GetStatus().m_nNowMP;
|
||||
Defenser[nDefenserCount].m_wMPHeal = wDefenderMPHeal[nDefenserCount];
|
||||
Defenser[nDefenserCount].m_wDamage = wDamage;
|
||||
++nDefenserCount;
|
||||
}
|
||||
|
||||
CCell* lpCell = m_CellPos.m_lpCell;
|
||||
if (NULL != lpCell)
|
||||
{
|
||||
lpCell->SendAttackInfo(GetCID(), attackType, static_cast<unsigned char>(nDefenserCount), &Defenser[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CMonster::HasSkill()
|
||||
{
|
||||
for (int i=0; i<MonsterInfo::MAX_SKILL_PATTERN; ++i)
|
||||
{
|
||||
if (0 != m_MonsterInfo.m_wSkillID[i]) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int CMonster::GetUseSkillNum() // <20><EFBFBD><EEB0A1><EFBFBD><EFBFBD> <20><>ų<EFBFBD><C5B3> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ°<D6B4>?
|
||||
{
|
||||
int count = 0;
|
||||
for (int i=0; i<MonsterInfo::MAX_SKILL_PATTERN; ++i)
|
||||
{
|
||||
if (0 != m_MonsterInfo.m_wSkillID[i]) ++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
unsigned long CMonster::GetDropRate(unsigned char cIndex)
|
||||
{
|
||||
switch (cIndex)
|
||||
{
|
||||
case MonsterInfo::LOTTERY:
|
||||
{
|
||||
if (false == CServerSetup::GetInstance().GetLotteryEvent())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MonsterInfo::F_RING:
|
||||
case MonsterInfo::D_RING:
|
||||
case MonsterInfo::C_RING:
|
||||
case MonsterInfo::B_RING:
|
||||
case MonsterInfo::A_RING:
|
||||
case MonsterInfo::F_NECKLACE:
|
||||
case MonsterInfo::D_NECKLACE:
|
||||
case MonsterInfo::C_NECKLACE:
|
||||
case MonsterInfo::B_NECKLACE:
|
||||
case MonsterInfo::A_NECKLACE:
|
||||
{
|
||||
if (false == CServerSetup::GetInstance().UseContents(GameRYL::ACCESSORY))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MonsterInfo::F_RUNE:
|
||||
case MonsterInfo::D_RUNE:
|
||||
case MonsterInfo::C_RUNE:
|
||||
case MonsterInfo::B_RUNE:
|
||||
case MonsterInfo::A_RUNE:
|
||||
case MonsterInfo::DESTRUCTION_RUNE:
|
||||
{
|
||||
if (false == CServerSetup::GetInstance().UseContents(GameRYL::RUNE))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return m_MonsterInfo.m_aryDropRate[cIndex];
|
||||
}
|
||||
|
||||
|
||||
bool CMonster::IsDeadSummonMonster(void)
|
||||
{
|
||||
if (m_bAdminCmdSummon)
|
||||
{
|
||||
return (STATE_ID_DIE == m_nCurrentState);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CMonster::LogMonsterMoveCount()
|
||||
{
|
||||
SERLOG5(g_Log, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>̵<EFBFBD> <20><><EFBFBD><EFBFBD> ȸ<><C8B8> <20>α<CEB1> <20><><EFBFBD><EFBFBD><EFBFBD>մϴ<D5B4>. "
|
||||
"NormalBehaviorSendCount:%10d, AttackBehaviorSendCount:%10d, ReturnBehaviorSendCount:%10d, "
|
||||
"EscapeBehaviorSendCount:%10d, DeadBehaviorSendCount:%10d ",
|
||||
ms_NormalBehaviorSendCount, ms_AttackBehaviorSendCount, ms_ReturnBehaviorSendCount,
|
||||
ms_EscapeBehaviorSendCount, ms_DeadBehaviorSendCount);
|
||||
|
||||
ms_NormalBehaviorSendCount = ms_AttackBehaviorSendCount = ms_ReturnBehaviorSendCount =
|
||||
ms_EscapeBehaviorSendCount = ms_DeadBehaviorSendCount = 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned short CMonster::ApplyDamage(AtType attackType, CAggresiveCreature* pOffencer, unsigned char &cOffencerJudge,
|
||||
unsigned char &cDefenserJudge, unsigned short& wOffencerMPHeal, unsigned short& wDefenserMPHeal,
|
||||
unsigned short &wError)
|
||||
{
|
||||
unsigned short usDamage = CAggresiveCreature::ApplyDamage(
|
||||
attackType, pOffencer, cOffencerJudge, cDefenserJudge, wOffencerMPHeal, wDefenserMPHeal, wError);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> Ÿ<><C5B8> ã<><C3A3>
|
||||
CMonsterShout::Behavior eBehavior = CMonsterShout::NORMAL_ATTACK;
|
||||
unsigned short usShoutSkill_ID = 0;
|
||||
|
||||
if (0 == (attackType.m_wType & AtType::SKILL_BIT))
|
||||
{
|
||||
// <20><>ų <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƴϴ<C6B4>.
|
||||
if (cDefenserJudge == ClientConstants::Judge_Critical)
|
||||
{
|
||||
eBehavior = CMonsterShout::CRITICAL_ATTACKED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
eBehavior = CMonsterShout::SKILL_ATTACKED;
|
||||
usShoutSkill_ID = attackType.m_wType;
|
||||
}
|
||||
|
||||
const char* szCharacterName = 0;
|
||||
if (0 != pOffencer && Creature::CT_PC == Creature::GetCreatureType(pOffencer->GetCID()))
|
||||
{
|
||||
szCharacterName = static_cast<CCharacter*>(pOffencer)->GetCharacterName();
|
||||
}
|
||||
|
||||
// <20><>ġ<EFBFBD><C4A1> <20>˻<EFBFBD><CBBB>ؼ<EFBFBD> <20><>ħ.
|
||||
CMonsterShout::GetInstance().Shout(m_dwCID, m_MonsterInfo.m_dwKID,
|
||||
static_cast<unsigned short>(m_CurrentPos.m_fPointX),
|
||||
static_cast<unsigned short>(m_CurrentPos.m_fPointZ),
|
||||
eBehavior, szCharacterName, usShoutSkill_ID);
|
||||
|
||||
return usDamage;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user