Files
Client/Server/RylServerProject/RylGameLibrary/Map/FieldMap/Cell.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

1273 lines
32 KiB
C++
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
///////////////////////////////////////////////////////////////////////////////////
//
// Purpose : CellÀ» °ü¸®Çϴ Ŭ·¡½º
//
///////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Cell.h"
#include <Item/Item.h>
#include <Item/ItemFactory.h>
#include <Item/ItemMgr.h>
#include <Creature/Creature.h>
#include <Creature/AggresiveCreature.h>
#include <Creature/Character/Character.h>
#include <Creature/Monster/Monster.h>
#include <Creature/Monster/VirtualMonsterMgr.h>
#include <Creature/CreatureManager.h>
#include <Creature/Siege/SiegeObject.h>
#include <Creature/Siege/SiegeObjectMgr.h>
#include <Network/Packet/ChatPacket.h>
#include <Network/Stream/SendStream.h>
#include <Network/Dispatch/GameClient/GameClientDispatch.h>
#include <Network/Dispatch/GameClient/SendCharCastle.h>
#include <Network/Dispatch/GameClient/SendCharAttack.h>
#include <Network/ClientSocket/ClientConstants.h>
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/CharItemPacket.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Community/Party/Party.h>
#include <Community/Guild/Guild.h>
#include <Community/Guild/GuildMgr.h>
#include <Stream/Buffer/Buffer.h>
#include <Stream/Buffer/BufferFactory.h>
#include <Map/FieldMap/CellManager.h>
#include <Map/FieldMap/VirtualArea/VirtualArea.h>
#include <Map/FieldMap/VirtualArea/VirtualAreaMgr.h>
unsigned char CCell::ms_CellSize = CCell::CELL_SIZE_DEFAULT;
class CCellObjectUIDMgr
{
public:
static CCellObjectUIDMgr& GetInstance();
unsigned long GetNewObjectUID() { return m_dwCellObjectUID++; }
private:
CCellObjectUIDMgr() : m_dwCellObjectUID(1) { }
unsigned long m_dwCellObjectUID;
};
CCellObjectUIDMgr& CCellObjectUIDMgr::GetInstance()
{
static CCellObjectUIDMgr cellObjectUIDMgr;
return cellObjectUIDMgr;
}
class CFindCreatureFromCID : public std::unary_function<CCreature, bool>
{
public:
explicit CFindCreatureFromCID(unsigned long dwCID)
: m_dwCID(dwCID)
{ }
bool operator() (CCreature* pCreature)
{
return (m_dwCID == pCreature->GetCID()) ? true : false;
}
private:
const unsigned long m_dwCID;
};
CCell::ItemInfo::ItemInfo()
: m_lpItem(NULL), m_dwGold(0), m_dwOwnerID(0), m_wPulse(0), m_cAutoRouting(0)
{
UID.m_nUniqueID = 0;
}
void CCell::ItemInfo::MakeFieldObject(FieldObject& fieldObject)
{
fieldObject.m_nOID = UID.m_nUniqueID;
// ¼Ò¼öÁ¡ ÇÑÀÚ¸®¼ö±îÁö Á¤º¸¸¦ ³²±â±âÀ§Çؼ­ 10À» °öÇØÁØ´Ù.
fieldObject.m_usXPos = static_cast<unsigned short>(m_Pos.m_fPointX * 10.0f);
fieldObject.m_usYPos = static_cast<unsigned short>(m_Pos.m_fPointY * 10.0f);
fieldObject.m_usZPos = static_cast<unsigned short>(m_Pos.m_fPointZ * 10.0f);
if (CServerSetup::GetInstance().GetServerZone() == SERVER_ID::BATTLE_SERVER && 0 != fieldObject.m_usYPos)
{
// Y ÁÂÇ¥°¡ 0ÀÌ ¾Æ´Ñ°æ¿ì(¸ó½ºÅͰ¡ ¶³¾î¶ß¸°°Ô ¾Æ´Ñ°æ¿ì), ¹èƲ·ÎÇÑÀº 1m ¸¦ ³ô¿©ÁØ´Ù.
fieldObject.m_usYPos += 10;
}
if (0 != m_lpItem)
{
fieldObject.m_cNum = m_lpItem->GetNumOrDurability();
fieldObject.m_dwTypeID = m_lpItem->GetPrototypeID();
}
else
{
fieldObject.m_cNum = 1;
fieldObject.m_dwTypeID = (CCell::MONEY_BIT + m_dwGold);
}
}
CCell::CCell()
: m_lpBroadcast2ndBuffer(0),
m_wMapIndex(0),
m_cIndexX(0),
m_cIndexZ(0),
m_cTurnOfGetAggresiveCreature(TURN_OF_CHARACTER),
m_dwCastleEmblemCID(0),
m_eWeather(CCell::WEATHER_FINE)
{
m_MonsterIt = m_lstMonster.end();
m_CharacterIt = m_lstCharacter.end();
m_SiegeObjectIt = m_lstSiegeObject.end();
std::fill_n(m_lpConnectCell, int(CONNECT_NUM), reinterpret_cast<CCell*>(0));
std::fill_n(m_lpSortedConnectedCell, int(CONNECT_NUM), reinterpret_cast<CCell*>(0));
m_lpConnectCell[NO] = this;
}
CCell::~CCell(void)
{
for (ItemList::iterator itr = m_lstItem.begin(); itr != m_lstItem.end(); ++itr)
{
ItemInfo& itemInfo = *itr;
if (NULL != itemInfo.m_lpItem)
{
DELETE_ITEM(itemInfo.m_lpItem);
}
}
ReleaseAllBuffer(m_lpBroadcast2ndBuffer);
}
void CCell::Initialize(unsigned char cIndexX, unsigned char cIndexZ)
{
m_cIndexX = cIndexX;
m_cIndexZ = cIndexZ;
std::partial_sort_copy(m_lpConnectCell, m_lpConnectCell + CCell::CONNECT_NUM,
m_lpSortedConnectedCell, m_lpSortedConnectedCell + CCell::CONNECT_NUM);
}
CMonster* CCell::GetFirstMonster(void)
{
if (false == m_lstMonster.empty())
{
m_MonsterIt = m_lstMonster.begin();
return *m_MonsterIt;
}
return NULL;
}
CSiegeObject* CCell::GetFirstAirShip(void)
{
m_SiegeObjectIt = m_lstSiegeObject.begin();
while (m_SiegeObjectIt != m_lstSiegeObject.end())
{
CSiegeObject* lpSiegeObject = *m_SiegeObjectIt;
if (lpSiegeObject && Siege::AIRSHIP == lpSiegeObject->GetObjectType())
{
return lpSiegeObject;
}
++m_SiegeObjectIt;
}
return NULL;
}
CSiegeObject* CCell::GetNextAirShip(void)
{
while (++m_SiegeObjectIt != m_lstSiegeObject.end())
{
CSiegeObject* lpSiegeObject = *m_SiegeObjectIt;
if (lpSiegeObject && Siege::AIRSHIP == lpSiegeObject->GetObjectType())
{
return lpSiegeObject;
}
}
return NULL;
}
CSiegeObject* CCell::GetFirstSiegeObject()
{
m_SiegeObjectIt = m_lstSiegeObject.begin();
while (m_SiegeObjectIt != m_lstSiegeObject.end())
{
CSiegeObject* lpSiegeObject = *m_SiegeObjectIt;
if (lpSiegeObject)
{
return lpSiegeObject;
}
++m_SiegeObjectIt;
}
return NULL;
}
CSiegeObject* CCell::GetNextSiegeObject()
{
while (++m_SiegeObjectIt != m_lstSiegeObject.end())
{
CSiegeObject* lpSiegeObject = *m_SiegeObjectIt;
if (lpSiegeObject)
{
return lpSiegeObject;
}
}
return NULL;
}
CCharacter* CCell::GetFirstCharacter(void)
{
if (false == m_lstCharacter.empty())
{
m_CharacterIt = m_lstCharacter.begin();
return *m_CharacterIt;
}
return 0;
}
CAggresiveCreature* CCell::GetFirstAggresiveCreature(void)
{
m_cTurnOfGetAggresiveCreature = TURN_OF_CHARACTER;
CAggresiveCreature* pCreature = reinterpret_cast<CAggresiveCreature *>(GetFirstCharacter());
if (NULL == pCreature)
{
m_cTurnOfGetAggresiveCreature = TURN_OF_SIEGE_OBJECT;
pCreature = reinterpret_cast<CAggresiveCreature*>(GetFirstSiegeObject());
if (NULL == pCreature)
{
m_cTurnOfGetAggresiveCreature = TURN_OF_MONSTER;
return reinterpret_cast<CAggresiveCreature *>(GetFirstMonster());
}
}
return pCreature;
}
CAggresiveCreature* CCell::GetNextAggresiveCreature(void)
{
CAggresiveCreature* pCreature = NULL;
switch (m_cTurnOfGetAggresiveCreature)
{
case TURN_OF_CHARACTER:
{
pCreature = reinterpret_cast<CAggresiveCreature *>(GetNextCharacter());
if (NULL == pCreature)
{
m_cTurnOfGetAggresiveCreature = TURN_OF_SIEGE_OBJECT;
pCreature = reinterpret_cast<CAggresiveCreature *>(GetFirstSiegeObject());
if (NULL == pCreature)
{
m_cTurnOfGetAggresiveCreature = TURN_OF_MONSTER;
pCreature = reinterpret_cast<CAggresiveCreature *>(GetFirstMonster());
}
}
return pCreature;
}
break;
case TURN_OF_SIEGE_OBJECT:
{
pCreature = reinterpret_cast<CAggresiveCreature *>(GetNextSiegeObject());
if (NULL == pCreature)
{
m_cTurnOfGetAggresiveCreature = TURN_OF_MONSTER;
pCreature = reinterpret_cast<CAggresiveCreature *>(GetFirstMonster());
}
return pCreature;
}
break;
case TURN_OF_MONSTER:
{
pCreature = reinterpret_cast<CAggresiveCreature *>(GetNextMonster());
return pCreature;
}
break;
}
return NULL;
}
void CCell::KillAll(CCharacter* lpAttacker)
{
if (true == m_lstMonster.empty())
{
return;
}
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);
CMonster* lpDeadMonster[AtNode::MAX_DEFENDER_NUM] = { NULL, };
MonsterList::iterator it = m_lstMonster.begin();
unsigned char cDefenderNum = 0;
for (; it != m_lstMonster.end() && cDefenderNum < AtNode::MAX_DEFENDER_NUM; ++it, ++cDefenderNum)
{
lpDeadMonster[cDefenderNum] = *it;
unsigned short usNowHP = lpDeadMonster[cDefenderNum]->GetStatus().m_nNowHP;
lpDeadMonster[cDefenderNum]->GetStatus().m_nNowHP = 0;
lpDefenserNode[cDefenderNum].m_wDamage = usNowHP;
lpDefenserNode[cDefenderNum].m_dwCharID = lpDeadMonster[cDefenderNum]->GetCID();
lpDefenserNode[cDefenderNum].m_sCurrHP = lpDeadMonster[cDefenderNum]->GetStatus().m_nNowHP;
lpDefenserNode[cDefenderNum].m_sCurrMP = lpDeadMonster[cDefenderNum]->GetStatus().m_nNowMP;
lpDefenserNode[cDefenderNum].m_wMaxHP = lpDeadMonster[cDefenderNum]->GetStatus().m_StatusInfo.m_nMaxHP;
lpDefenserNode[cDefenderNum].m_wMaxMP = lpDeadMonster[cDefenderNum]->GetStatus().m_StatusInfo.m_nMaxMP;
lpDefenserNode[cDefenderNum].m_wMPHeal = 0;
lpDefenserNode[cDefenderNum].m_cJudge = ClientConstants::Judge_Front;
}
for (int nIndex = 0; nIndex < cDefenderNum; ++nIndex)
{
if (NULL == lpDeadMonster[nIndex]) { break; }
lpDeadMonster[nIndex]->GetThreat().AddToThreatList(lpAttacker, 1L);
lpDeadMonster[nIndex]->Dead(lpAttacker);
lpDeadMonster[nIndex]->GetThreat().ClearAll();
}
lpPktAtAck->m_dwCharID = lpAttacker->GetCID();
AtType attackType;
attackType.m_wType = AtType::RIGHT_MELEE;
lpPktAtAck->m_AtType = attackType;
lpPktAtAck->m_wHP = lpAttacker->GetStatus().m_nNowHP;
lpPktAtAck->m_wMP = lpAttacker->GetStatus().m_nNowMP;
lpPktAtAck->m_wMPHeal = 0;
lpPktAtAck->m_cJudge = ClientConstants::Judge_Front;
lpPktAtAck->m_cDefenserNum = cDefenderNum;
CCell* lpCell = lpAttacker->GetCellPos().m_lpCell;
CGameClientDispatch* lpDispatch = lpAttacker->GetDispatcher();
if (0 != lpDispatch &&
lpDispatch->GetSendStream().WrapCompress(szBuffer,
sizeof(PktAtAck) + cDefenderNum * sizeof(DefenserNode), CmdCharAttack, 0, 0) &&
0 != lpCell)
{
lpCell->SendAttackInfo(lpAttacker->GetCID(),
attackType, cDefenderNum, lpDefenserNode);
}
}
void CCell::UpgradeByEmblem(unsigned long dwCID)
{
m_dwCastleEmblemCID = dwCID;
CSiegeObject* lpEmblem = CSiegeObjectMgr::GetInstance().GetSiegeObject(m_dwCastleEmblemCID);
if (lpEmblem)
{
CCharacter* lpCharacter = GetFirstCharacter();
while (lpCharacter)
{
if (EnemyCheck::EC_ENEMY == lpEmblem->IsEnemy(lpCharacter))
{
// ÇØ´ç ij¸¯ÅÍ¿¡°Ô ½ºÅÚ½º¸¦ »ç¿ëÇÒ¼ö ¾ø´Ù´Â Á¤º¸¸¦ º¸³½´Ù.
SendStealthInfo(*lpCharacter, false);
if (true == lpCharacter->GetEnchantInfo().GetFlag(Skill::SpellID::Stealth))
{
DetectionAttack(lpEmblem, lpCharacter);
}
}
lpCharacter = GetNextCharacter();
}
}
}
void CCell::DegradeByEmblem()
{
CSiegeObject* lpEmblem = CSiegeObjectMgr::GetInstance().GetSiegeObject(m_dwCastleEmblemCID);
if (lpEmblem)
{
CCharacter* lpCharacter = GetFirstCharacter();
while (lpCharacter)
{
if (EnemyCheck::EC_ENEMY == lpEmblem->IsEnemy(lpCharacter))
{
// ÇØ´ç ij¸¯ÅÍ¿¡°Ô ½ºÅÚ½º¸¦ »ç¿ë °¡´É Á¤º¸¸¦ º¸³½´Ù.
SendStealthInfo(*lpCharacter, true);
}
lpCharacter = GetNextCharacter();
}
}
m_dwCastleEmblemCID = 0;
}
void CCell::DetectionAttack(CSiegeObject* lpEmblem, CAggresiveCreature* lpTargetCreature)
{
if (NULL == lpEmblem || NULL == lpTargetCreature) return;
AtType attackType;
attackType.m_cSkillLockCount = 0;
attackType.m_cSkillLevel = 1;
attackType.m_cAtCount = 0;
attackType.m_cCasting = 0;
attackType.m_wType = 0x8201; // Detection
CAggresiveCreature* lpAggresiveCreature[AtNode::MAX_DEFENDER_NUM] = {0, };
unsigned char cDefenserJudge[AtNode::MAX_DEFENDER_NUM] = {0, };
unsigned short wDefenserMPHeal[AtNode::MAX_DEFENDER_NUM] = {0, };
lpAggresiveCreature[0] = lpTargetCreature;
lpEmblem->SetFullMP();
lpEmblem->Attack(attackType, 1, lpAggresiveCreature, cDefenserJudge, wDefenserMPHeal);
}
bool CCell::SendStealthInfo(CCharacter& character, bool bUseStealth)
{
CGameClientDispatch* lpDispatch = 0;
if (0 != (lpDispatch = character.GetDispatcher()) &&
GameClientSendPacket::SendStealthInfo(lpDispatch->GetSendStream(), bUseStealth))
{
return true;
}
ERRLOG1(g_Log, "CID:0x%08x ij¸¯ÅÍ¿¡°Ô ½ºÅÚ½º »ç¿ë À¯¹« Á¤º¸ Àü¼Û ½ÇÆÐ", character.GetCID());
return false;
}
///////////////////////////////////////////////////////////////////////////////////
// Function : CCell::SetCreature
//
// Description : Creature(¸ó½ºÅͳª À¯Àú)¸¦ Cell¿¡ ³ÖÀ½
//
// Inputs : dwCID - CreatureÀÇ ID
// pObject - CreatureÀÇ Æ÷ÀÎÅÍ
// eCellMoveType - À̵¿ ŸÀÔ(CCell::SendCellLogin Âü°í)
//
// Outputs : None.
//
// Returns : None.
///////////////////////////////////////////////////////////////////////////////////
void CCell::SetCreature(unsigned long dwCID, CCreature* lpCreature, CCell* lpLastLogoutCell)
{
if (0 == lpCreature)
{
ERRLOG1(g_Log, "Creature Æ÷ÀÎÅͰ¡ NULLÀÔ´Ï´Ù. CID: 0x%08x", dwCID);
return;
}
if (NULL != GetCreature(dwCID))
{
ERRLOG1(g_Log, "ÀÌ ¼¿¿¡´Â ÀÌ¹Ì ÀÌ Å©¸®Ãİ¡ Á¸ÀçÇÕ´Ï´Ù. CID: 0x%08x", dwCID);
return;
}
CAggresiveCreature* lpAggresiveCreature =
static_cast<CAggresiveCreature*>(lpCreature);
switch (Creature::GetCreatureType(dwCID))
{
case Creature::CT_PC:
{
CCharacter* lpCharacter = static_cast<CCharacter*>(lpCreature);
m_lstCharacter.push_back(lpCharacter);
// ¼º ¼ÒÀ¯ »ó¡¹°ÀÇ µðÅØ¼Ç ¿µ¿ª¾È¿¡ ÀÖ´Â ¼¿À̶ó¸é
if (0 != m_dwCastleEmblemCID)
{
CSiegeObject* lpEmblem = CSiegeObjectMgr::GetInstance().GetSiegeObject(m_dwCastleEmblemCID);
if (lpEmblem && EnemyCheck::EC_ENEMY == lpEmblem->IsEnemy(lpCharacter))
{
// ÇØ´ç ij¸¯ÅÍ¿¡°Ô ½ºÅÚ½º¸¦ »ç¿ëÇÏÁö ¸øÇÑ´Ù´Â Á¤º¸¸¦ º¸³½´Ù.
SendStealthInfo(*lpCharacter, false);
if (lpCharacter->GetEnchantInfo().GetFlag(Skill::SpellID::Stealth))
{
DetectionAttack(lpEmblem, lpCharacter);
}
}
}
else
{
// ÇØ´ç ij¸¯ÅÍ¿¡°Ô ½ºÅÚ½º »ç¿ë °¡´É Á¤º¸¸¦ º¸³½´Ù.
SendStealthInfo(*lpCharacter, true);
}
}
break;
case Creature::CT_MONSTER:
case Creature::CT_SUMMON:
case Creature::CT_STRUCT:
m_lstMonster.push_back(static_cast<CMonster*>(lpCreature));
break;
case Creature::CT_SIEGE_OBJECT:
m_lstSiegeObject.push_back(static_cast<CSiegeObject*>(lpCreature));
break;
}
SendCellLogin(lpAggresiveCreature, lpLastLogoutCell);
}
///////////////////////////////////////////////////////////////////////////////////
// Function : CCell::GetCreature
//
// Description : ¼¿¿¡ ¼ÓÇÑ CreatureÀÇ Æ÷ÀÎÅ͸¦ ¾òÀ½
//
// Inputs : dwCID - ¾ò°íÀÚÇÏ´Â ³à¼®ÀÇ CID
//
// Outputs : None.
//
// Returns : LPCCreature - ¾ò´Â ³à¼®ÀÇ Æ÷ÀÎÅÍ
///////////////////////////////////////////////////////////////////////////////////
CCreature* CCell::GetCreature(unsigned long dwCID)
{
CFindCreatureFromCID findCID(dwCID);
switch (Creature::GetCreatureType(dwCID))
{
case Creature::CT_PC:
{
CharacterList::iterator itr = std::find_if(m_lstCharacter.begin(), m_lstCharacter.end(), findCID);
if (itr != m_lstCharacter.end())
{
return (CCreature *)*itr;
}
}
break;
case Creature::CT_MONSTER:
case Creature::CT_SUMMON:
case Creature::CT_STRUCT:
{
MonsterList::iterator itr = std::find_if(m_lstMonster.begin(), m_lstMonster.end(), findCID);
if (itr != m_lstMonster.end())
{
return (CCreature *)*itr;
}
}
break;
case Creature::CT_SIEGE_OBJECT:
{
SiegeObjectList::iterator itr = std::find_if(m_lstSiegeObject.begin(), m_lstSiegeObject.end(), findCID);
if (itr != m_lstSiegeObject.end())
{
return (CCreature *)*itr;
}
}
break;
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////////
// Function : CCell::DeleteCreature
//
// Description : ¼¿¿¡¼­ ¿øÇÏ´Â CreatureÀ» Áö¿ò
//
// Inputs : dwCID - Áö¿ì°íÀÚ ÇÏ´Â CreatureÀÇ CID
// eCellMoveType - À̵¿ ŸÀÔ(CCell::SendCellLogout Âü°í)
//
// Outputs : None.
//
// Returns : None.
///////////////////////////////////////////////////////////////////////////////////
void CCell::DeleteCreature(unsigned long dwCID, CCell* lpPrepareLoginCell)
{
CFindCreatureFromCID findCID(dwCID);
switch (Creature::GetCreatureType(dwCID))
{
case Creature::CT_PC:
{
CharacterList::iterator itr =
std::find_if(m_lstCharacter.begin(), m_lstCharacter.end(), findCID);
if (itr != m_lstCharacter.end())
{
SendCellLogout(*itr, lpPrepareLoginCell);;
m_lstCharacter.erase(itr);
}
else
{
ERRLOG1(g_Log, "ÀÌ ¼¿¿¡´Â ÀÌ Ä³¸¯ÅͰ¡ Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù. CID: 0x%08x", dwCID);
}
}
break;
case Creature::CT_MONSTER:
case Creature::CT_SUMMON:
case Creature::CT_STRUCT:
{
MonsterList::iterator itr =
std::find_if(m_lstMonster.begin(), m_lstMonster.end(), findCID);
if (itr != m_lstMonster.end())
{
SendCellLogout(*itr, lpPrepareLoginCell);;
m_lstMonster.erase(itr);
}
else
{
ERRLOG1(g_Log, "ÀÌ ¼¿¿¡´Â ÀÌ ¸ó½ºÅͰ¡ Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù. CID: 0x%08x", dwCID);
}
}
break;
case Creature::CT_SIEGE_OBJECT:
{
SiegeObjectList::iterator itr =
std::find_if(m_lstSiegeObject.begin(), m_lstSiegeObject.end(), findCID);
if (itr != m_lstSiegeObject.end())
{
m_lstSiegeObject.erase(itr);
}
else
{
ERRLOG1(g_Log, "ÀÌ ¼¿¿¡´Â ÀÌ ÇØ´ç °ø¼º°ü·Ã ¿ÀºêÁ§Æ®°¡ Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù. CID: 0x%08x", dwCID);
}
}
break;
}
}
void CCell::SetItem(const Position& Pos, Item::CItem* lpItem, unsigned long dwGold,
unsigned long dwOwnerID, unsigned char cAutoRouting, CCell::ItemInfo& cellItemInfo)
{
cellItemInfo.m_Pos = Pos;
cellItemInfo.UID.m_Field.dwUID = CCellObjectUIDMgr::GetInstance().GetNewObjectUID();
cellItemInfo.UID.m_Field.wMapIndex = m_wMapIndex;
cellItemInfo.UID.m_Field.cCellX = m_cIndexX;
cellItemInfo.UID.m_Field.cCellZ = m_cIndexZ;
cellItemInfo.m_lpItem = lpItem;
cellItemInfo.m_dwGold = dwGold;
cellItemInfo.m_dwOwnerID = dwOwnerID;
cellItemInfo.m_cAutoRouting = cAutoRouting;
cellItemInfo.m_wPulse = (NONE == cAutoRouting) ? ITEM_RIGHT_TIME : ITEM_LIFE_TIME;
m_lstItem.push_front(cellItemInfo);
SendPullDownInfo(dwOwnerID, cellItemInfo);
}
///////////////////////////////////////////////////////////////////////////////////
// Function : CCell::GetItem
//
// Description : ¼¿¿¡ ¶³¾îÁ® ÀÖ´Â ¾ÆÀÌÅÛÀ» ¾òÀ½
//
// Inputs : dwCreatureID - ¾ÆÀÌÅÛÀ» ¾òÀ¸·Á´Â Å©¸®ÃÄÀÇ ID
// nItemInfoID - ¾ÆÀÌÅÛÀÇ À¯´ÏÅ© ID
//
// Outputs : lppItem - ¾ÆÀÌÅÛÀÇ Æ÷ÀÎÅÍ. ¾ø´Â ¾ÆÀÌÅÛÀ̰ųª ¼ÒÀ¯±ÇÀÌ ¾ø´Â Å©¸®Ãİ¡ ¿äûÇϸé NULL.
// dwMoney_Out - ±Ý¾×
//
// Returns : CCell::ErrorCode - ¿¡·¯ ÄÚµå
///////////////////////////////////////////////////////////////////////////////////
CCell::ErrorCode CCell::GetItem(unsigned long dwCreatureID, unsigned __int64 nItemInfoID,
Item::CItem** lppItem, unsigned long& dwMoney_Out)
{
*lppItem = NULL;
dwMoney_Out = 0;
CAggresiveCreature* lpPickkingCreature = CCreatureManager::GetInstance().GetAggresiveCreature(dwCreatureID);
if (NULL == lpPickkingCreature)
{
return E_NOT_OWNER_OF_ITEM;
}
if (0 == m_lstItem.size())
{
return E_NOT_ITEM;
}
ItemList::iterator pos = m_lstItem.begin();
ItemList::iterator end = m_lstItem.end();
for (; pos != end; ++pos)
{
if (pos->UID.m_nUniqueID == nItemInfoID)
{
break;
}
}
if (pos == end)
{
return E_NOT_ITEM;
}
ItemInfo& itemInfo = *pos;
// ¼ÒÀ¯±Ç üũ
if (itemInfo.m_dwOwnerID != 0)
{
if (GUILD == itemInfo.m_cAutoRouting)
{
Guild::CGuild* lpGuild = Guild::CGuildMgr::GetInstance().GetGuild(itemInfo.m_dwOwnerID);
if (!lpGuild)
{
return E_NOT_EXIST_GUILD;
}
if (lpPickkingCreature->GetGID() != lpGuild->GetGID())
{
return E_NOT_OWNER_OF_ITEM;
}
}
else if (dwCreatureID != itemInfo.m_dwOwnerID)
{
// À¯Àú°¡ ¶³¾î¶ß·È°Å³ª ÇØ¼­ ¼ÒÀ¯±ÇÀÌ ³²¿¡°Ô ÀÖ´Â °æ¿ì
if (NONE == itemInfo.m_cAutoRouting)
{
return E_NOT_OWNER_OF_ITEM;
}
// ¸ó½ºÅͰ¡ ¶³¾î¶ß¸° ¾ÆÀÌÅÛ (¿ÀÅä·çÆÃ Àü)
CAggresiveCreature* lpOwnerCreature =
CCreatureManager::GetInstance().GetAggresiveCreature(itemInfo.m_dwOwnerID);
if (NULL != lpOwnerCreature && NULL != lpPickkingCreature)
{
CParty* lpOwnerParty = lpOwnerCreature->GetParty();
if (NULL == lpOwnerParty || lpOwnerParty != lpPickkingCreature->GetParty())
{
return E_NOT_OWNER_OF_ITEM;
}
}
}
}
Item::CItem* lpItem = NULL;
if (0 != itemInfo.m_dwGold)
{
dwMoney_Out = itemInfo.m_dwGold;
if (Creature::CT_PC == Creature::GetCreatureType(dwCreatureID) &&
reinterpret_cast<CCharacter*>(lpPickkingCreature)->GetGold() > ULONG_MAX - dwMoney_Out)
{
return E_GOLD_OVERFLOW;
}
}
else
{
lpItem = itemInfo.m_lpItem;
if(lpItem == NULL)
{
return E_NOT_ITEM;
}
if (lpItem->IsSet(Item::DetailData::STACKABLE) && 0 == lpItem->GetNumOrDurability())
{
return E_NOT_ITEM;
}
}
ErrorCode eErrorCode = S_SUCCESS;
if (PARTY == itemInfo.m_cAutoRouting)
{
// ¿ÀÅä ·çÆÃ
CParty* lpParty = lpPickkingCreature->GetParty();
if (NULL != lpParty)
{
if (true == lpParty->AutoRouting(lpPickkingCreature, lpItem, dwMoney_Out))
{
eErrorCode = S_AUTO_ROUTING;
}
}
}
else if (GUILD == itemInfo.m_cAutoRouting)
{
// ¿ÀÅä ·çÆÃ
Guild::CGuild* lpGuild = Guild::CGuildMgr::GetInstance().GetGuild(itemInfo.m_dwOwnerID);
if (NULL != lpGuild)
{
if (true == lpGuild->AutoRouting(lpPickkingCreature, lpItem, dwMoney_Out))
{
eErrorCode = S_AUTO_ROUTING;
}
}
}
// TODO : ÃßÈÄ¿¡ ¾²ÀÌ°Ô µÇ¸é ¼öÁ¤ÀÌ ÇÊ¿äÇÕ´Ï´Ù. (¿ÀÅä·çÆÃ±îÁö °í·ÁÇØ¼­...)
/*
if (NULL != lpItem && Creature::CT_PC == Creature::GetCreatureType(lpPickkingCreature->GetCID()))
{
if (Item::ItemType::EVENT_DROP == lpItem->GetItemInfo().m_DetailData.m_cItemType)
{
char szChatMessage[PktChat::PktChatMaxSize];
CCharacter* lpCharacter = static_cast<CCharacter*>(lpPickkingCreature);
int nSize = _snprintf(szChatMessage, PktChat::PktChatMaxSize - 1,
"[¾Ë¸²] ÃàÇÏÇÕ´Ï´Ù~! %s´Ô²²¼­ %sÀ»(¸¦) ¾òÀ¸¼Ì½À´Ï´Ù~!",
lpCharacter->GetCharacterName(), lpItem->GetItemInfo().m_SpriteData.m_szName);
szChatMessage[PktChat::PktChatMaxSize - 1] = 0;
CChatPacket chatPacket(szChatMessage, 0, PktChat::NOTICE);
if (chatPacket.IsValid())
{
CCreatureManager::GetInstance().SendAllCharacter(
chatPacket.GetCompressedPacket(), chatPacket.GetCompressedSize(), CmdCharChat);
}
DETLOG3(g_Log, "CID:0x%08x À̺¥Æ® ·Î±× : %s(ÀÌ)°¡ %sÀ»(¸¦) ¾ò¾ú½À´Ï´Ù.",
lpCharacter->GetCID(), lpCharacter->GetCharacterName(), lpItem->GetItemInfo().m_SpriteData.m_szName);
}
}
*/
*lppItem = lpItem;
m_lstItem.erase(pos);
SendPickUpInfo(dwCreatureID, nItemInfoID);
return eErrorCode;
}
///////////////////////////////////////////////////////////////////////////////////
// Function : CCell::CheckDeleteItem
//
// Description : ¸Ê À§¿¡¼­ÀÇ ¾ÆÀÌÅÛ Áö¼Ó ½Ã°£À» üũÇÑ´Ù.
//
// Inputs : None.
//
// Outputs : None.
//
// Returns : None.
///////////////////////////////////////////////////////////////////////////////////
void CCell::CheckDeleteItem(void)
{
if (true == m_lstItem.empty())
{
return;
}
for (ItemList::iterator itr = m_lstItem.begin(); itr != m_lstItem.end();)
{
ItemInfo& itemInfo = *itr;
itemInfo.m_wPulse -= CHECK_TIME;
if (itemInfo.m_wPulse <= NO_OWNER_TIME)
{
itemInfo.m_dwOwnerID = 0;
}
if (itemInfo.m_wPulse <= 0)
{
// '¶¥ÀÌ ¾ÆÀÌÅÛÀÌ Áݴ´Ù'¶ó´Â »ý°¢...
SendPickUpInfo(0, itemInfo.UID.m_nUniqueID);
if (itemInfo.m_lpItem != NULL)
{
DELETE_ITEM(itemInfo.m_lpItem);
}
m_lstItem.erase(itr++);
continue;
}
++itr;
}
}
///////////////////////////////////////////////////////////////////////////////////
// Function : CCell::DeleteAllItem
//
// Description : ¸Ê À§ÀÇ ¾ÆÀÌÅÛÀ» ¸ðµÎ Áö¿î´Ù.
//
// Inputs : None.
//
// Outputs : None.
//
// Returns : None.
///////////////////////////////////////////////////////////////////////////////////
void CCell::DeleteAllItem(void)
{
if (true == m_lstItem.empty())
{
return;
}
for (ItemList::iterator itr = m_lstItem.begin(); itr != m_lstItem.end();)
{
ItemInfo& itemInfo = *itr;
itemInfo.m_dwOwnerID = 0;
// '¶¥ÀÌ ¾ÆÀÌÅÛÀÌ Áݴ´Ù'¶ó´Â »ý°¢...
SendPickUpInfo(0, itemInfo.UID.m_nUniqueID);
if (itemInfo.m_lpItem != NULL)
{
DELETE_ITEM(itemInfo.m_lpItem);
}
m_lstItem.erase(itr++);
}
}
void CCell::SendPullDownInfo(unsigned long dwOwnerID, ItemInfo& itemInfo)
{
PktPDInfo pktPDInfo;
memset(&pktPDInfo, 0, sizeof(PktPDInfo));
pktPDInfo.m_dwCharID = dwOwnerID;
itemInfo.MakeFieldObject(pktPDInfo.m_FieldObject);
// ³»ºÎ¿¡¼­ WrapÀ» ¾Ë¾Æ¼­ ÇÔ.
SendAllNearCellCharacter(&pktPDInfo, sizeof(PktPDInfo), CmdCharPullDownInfo);
}
///////////////////////////////////////////////////////////////////////////////////
// Function : CCell::SendPickUpInfo
//
// Description : ¾ÆÀÌÅÛÀ» ´©±º°¡ ÁÖ¿ü´Ù´Â Á¤º¸¸¦ ÁÖÀ§ ij¸¯Å͵鿡°Ô º¸³¿
//
// Inputs : dwCreatureID - ÁÖ¿î ³à¼®ÀÇ ¾ÆÀ̵ð
// nItemInfoID - ¾ø¾îÁø ¾ÆÀÌÅÛÀÇ ¾ÆÀ̵ð
//
// Outputs : None.
//
// Returns : None.
///////////////////////////////////////////////////////////////////////////////////
void CCell::SendPickUpInfo(unsigned long dwCreatureID, unsigned __int64 nItemInfoID)
{
PktPUInfo pktPUInfo;
memset(&pktPUInfo, 0, sizeof(PktPUInfo));
pktPUInfo.m_dwCharID = dwCreatureID;
pktPUInfo.m_nObjectID = nItemInfoID;
// ³»ºÎ¿¡¼­ WrapÀ» ¾Ë¾Æ¼­ ÇÔ.
SendAllNearCellCharacter(&pktPUInfo, sizeof(PktPUInfo), CmdCharPickUpInfo);
}
//Interface/////////////////////////////////////////////////////////////////////////////////////
//
// °ø°Ý Á¤º¸
//
// Parameter :
// 1st :
// 2st :
//
// Do :
// °ø°ÝÇÑ °æ¿ì ÁÖº¯ ¼¿ÀÇ Ä³¸¯Å͵鿡°Ô AttackInfo ¸¦ º¸³½´Ù. (UDP -> TCP : 2004-04-20)
//
// Return :
//
///////////////////////////////////////////////////////////////////////////////////////////////
void CCell::SendAttackInfo(unsigned long AttackerID_In, const AtType &AtType_In,
unsigned char DefenserNum_In, DefenserNode* lpNode_In)
{
const int MAX_BUFFER = sizeof(PktAtAck) + AtNode::MAX_DEFENDER_NUM * sizeof(DefenserNode);
char szBuffer[MAX_BUFFER];
memset(szBuffer, 0, MAX_BUFFER);
// ¹æ¾îÀÚ °³¼ö ÀçÁ¶Á¤(ÃÖ´ë °³¼ö ³ÑÀ» ¼ö ¾ø°Ô)
DefenserNum_In = std::min(DefenserNum_In, unsigned char(AtNode::MAX_DEFENDER_NUM));
unsigned short wPacketSize =
sizeof(PktAtInfo) + sizeof(DefenserNode) * DefenserNum_In;
PktAtInfo* lpPktAtInfo = reinterpret_cast<PktAtInfo*>(szBuffer);
DefenserNode* lpDefenserNode = reinterpret_cast<DefenserNode*>(lpPktAtInfo + 1);
lpPktAtInfo->m_dwCharID = AttackerID_In;
lpPktAtInfo->m_AtType = AtType_In;
lpPktAtInfo->m_cDefenserNum = DefenserNum_In;
CopyMemory(lpDefenserNode, lpNode_In, sizeof(DefenserNode) * DefenserNum_In);
// ³»ºÎ¿¡¼­ WrapÀ» ¾Ë¾Æ¼­ ÇÑ´Ù.
SendAllNearCellCharacter(lpPktAtInfo, wPacketSize, CmdCharAttackInfo);
}
// MON_TODO : by Vincent - 2004 : 3 : 3
//Interface/////////////////////////////////////////////////////////////////////////////////////
//
// ¸ó½ºÅÍ ½ºÅ³ ij½ºÆ® Á¤º¸
//
// Parameter :
// 1st :
// 2st :
//
// Do :
// ¸ó½ºÅͰ¡ ½ºÅ³À» »ç¿ëÇÑ °æ¿ì ÁÖº¯ ¼¿ÀÇ Ä³¸¯Å͵鿡°Ô CastObjectInfo ¸¦ º¸³½´Ù.
//
// Return :
//
///////////////////////////////////////////////////////////////////////////////////////////////
void CCell::SendCastObjectInfo(unsigned long SenderID, unsigned long ReceiverID, CastObject& CastObject_In)
{
PktCOInfo pktCOInfo;
memset(&pktCOInfo, 0, sizeof(PktCOInfo));
pktCOInfo.m_dwSenderID = SenderID;
pktCOInfo.m_dwReceiverID = ReceiverID;
pktCOInfo.m_sCastObject = CastObject_In;
SendAllNearCellCharacter(&pktCOInfo, sizeof(PktCOInfo), CmdCharCastObjectInfo);
}
//------------------------------------------------------------------------------------------------
void CCell::SendAllNearCellCharacter(const PktBase* lpPktBase, unsigned short usLength, unsigned char cCMD)
{
__declspec(thread) static char szPacket[PktMaxLen];
unsigned long dwPacket = PktMaxLen;
if (PacketWrap::WrapCompress(szPacket, dwPacket,
reinterpret_cast<const char*>(lpPktBase), usLength, cCMD, 0, 0))
{
CCell** lppConnectCellBound = m_lpConnectCell + CCell::CONNECT_NUM;
for (CCell** lppCell = m_lpConnectCell;
lppCell != lppConnectCellBound; ++lppCell)
{
CCell* lpCell = *lppCell;
if (NULL != lpCell)
{
lpCell->SendNowAllCharacter(
reinterpret_cast<const char*>(szPacket),
static_cast<unsigned short>(dwPacket), cCMD);
}
}
}
}
void CCell::SendAllCharacter(const PktBase* lpPktBase, unsigned short usLength, unsigned char cCMD)
{
__declspec(thread) static char szPacket[PktMaxLen];
unsigned long dwPacket = PktMaxLen;
if (PacketWrap::WrapCompress(szPacket, dwPacket,
reinterpret_cast<const char*>(lpPktBase), usLength, cCMD, 0, 0))
{
SendNowAllCharacter(
reinterpret_cast<const char*>(szPacket),
static_cast<unsigned short>(dwPacket), cCMD);
}
/*
if (sizeof(PktBase) <= usLength)
{
if (0 == m_lpSendAllBuffer ||
m_lpSendAllBuffer->remain() < usLength)
{
// ¹öÆÛ°¡ ¾ø°Å³ª, ¹öÆÛ ±æÀ̰¡ ºÎÁ·Çϰųª, ÆÐŶ Ä«¿îÆ®°¡ ¸¹ÀÌ ½×¿´À¸¸é ÆÐŶÀ» Àü¼ÛÇÑ´Ù.
FlushSendAllBuffer();
// ¹öÆÛ¸¦ »õ·Î »ý¼ºÇÑ´Ù.
m_lpSendAllBuffer = CREATE_BUFFER(
CCellManager::GetInstance().GetBufferFactory(), PktMaxLen - 1024);
if (0 != m_lpSendAllBuffer)
{
// ¹öÆÛ »ý¼ºÈÄ, Çì´õ ºÎºÐÀ» ºñ¿öµÐ´Ù.
m_lpSendAllBuffer->wr_ptr(sizeof(PktBase));
}
}
if (0 != m_lpSendAllBuffer)
{
// ¾ÐÃà Çì´õ¸¦ ºÙÀδÙ. ¾ÐÃà Çì´õ Æ÷¸ËÀº ±æÀÌ 2byte, Ä¿¸Çµå 1byteÀÌ´Ù.
// ±æÀÌ´Â Çì´õ Æ÷ÇÔ ÆÐŶ ±æÀÌÀÌ´Ù.
unsigned short usDataLength = usLength - sizeof(PktBase);
unsigned short usPacketLength = usDataLength + sizeof(usPacketLength) + sizeof(cCMD);
m_lpSendAllBuffer->push(&usPacketLength, sizeof(usPacketLength));
m_lpSendAllBuffer->push(&cCMD, sizeof(cCMD));
// µ¥ÀÌÅÍ¿¡¼­ Çì´õ¸¦ Á¦°ÅÇÏ°í º¹»çÇÑ´Ù.
m_lpSendAllBuffer->push(lpPktBase + 1, usDataLength);
}
}
*/
}
void CCell::SendNowAllNearCellCharacter(const char* szData, unsigned short usLength, unsigned char cCMD)
{
CCell** lppConnectCellBound = m_lpConnectCell + CCell::CONNECT_NUM;
for (CCell** lppCell = m_lpConnectCell;
lppCell != lppConnectCellBound; ++lppCell)
{
CCell* lpCell = *lppCell;
if (NULL != lpCell)
{
lpCell->SendNowAllCharacter(szData, usLength, cCMD);
}
}
}
void CCell::SendNowAllCharacter(const char* szData, unsigned short usLength, unsigned char cCMD)
{
CharacterList::iterator pos = m_lstCharacter.begin();
CharacterList::iterator end = m_lstCharacter.end();
CCharacter* lpCharacter = 0;
CGameClientDispatch* lpDispatch = 0;
for (; pos != end; ++pos)
{
lpCharacter = *pos;
if (0 != lpCharacter &&
0 != (lpDispatch = lpCharacter->GetDispatcher()))
{
lpDispatch->GetSendStream().PutBuffer(szData, usLength, cCMD);
}
}
}
CCell* CCell::GetConnectCell(unsigned int nDir)
{
if (nDir <= CONNECT_NUM)
{
return m_lpConnectCell[nDir];
}
ERRLOG1(g_Log, "Cannot get incorrect direction cell : %d", nDir);
return NULL;
}
void CCell::SetConnectCell(unsigned int nDir, CCell* lpConnectedCell)
{
if (nDir <= CONNECT_NUM)
{
m_lpConnectCell[nDir] = lpConnectedCell;
}
else
{
ERRLOG1(g_Log, "Cannot set incorrect direction cell : %d", nDir);
}
}
bool CCell::IsNearCell(CCell* lpNearCell)
{
CCell** lppConnectedCellPastEnd = m_lpConnectCell + CONNECT_NUM;
for (CCell** lppCell = m_lpConnectCell;
lppCell != lppConnectedCellPastEnd; ++lppCell)
{
if (*lppCell == lpNearCell)
{
return true;
}
}
return false;
}
size_t CCell::GetNearCellCharacterNum() const
{
size_t nCharacterNum = 0;
CCell* const* lppConnectCellBound = m_lpConnectCell + CCell::CONNECT_NUM;
for (CCell* const* lppCell = m_lpConnectCell; lppCell != lppConnectCellBound; ++lppCell)
{
CCell* lpCell = *lppCell;
if (NULL != lpCell)
{
nCharacterNum += lpCell->GetCharacterNum();
}
}
return nCharacterNum;
};
void CCell::RespawnAllCharacter(unsigned char cExceptNation)
{
if (0 == m_lstCharacter.size()) return;
CharacterList::iterator itr = m_lstCharacter.begin();
CCharacter* lpCharacter = NULL;
while (itr != m_lstCharacter.end())
{
lpCharacter = (*itr);
if (lpCharacter && cExceptNation != lpCharacter->GetNation())
{
lpCharacter->Respawn();
if (0 != lpCharacter->GetPID())
{
// ÆÄƼ¿ø ¸®½ºÆùÀ» ¾Ë¸°´Ù.
GameClientSendPacket::SendCharDeadToParty(lpCharacter, 0, PktDeadInfo::RESPAWN);
}
}
++itr;
}
}