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:
2025-11-29 20:17:20 +09:00
parent 5d3cd64a25
commit dd97ddec92
11602 changed files with 1446576 additions and 0 deletions

View File

@@ -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;
}