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:
610
Server/AdminTool/AdminToolLibrary/character/ModifyCharacter.cpp
Normal file
610
Server/AdminTool/AdminToolLibrary/character/ModifyCharacter.cpp
Normal file
@@ -0,0 +1,610 @@
|
||||
#include "stdafx.h"
|
||||
#include "ModifyCharacter.h"
|
||||
|
||||
#include <Network/Dispatch/Dispatch.h>
|
||||
#include <Network/Protocol/Ryl_AdminMgrProtocol.h>
|
||||
#include <Network/Packet/PacketStruct/CharStatusPacket.h>
|
||||
#include <Network/Packet/PacketStruct/CharQuestPacket.h>
|
||||
#include <Skill/SkillMgr.h>
|
||||
#include <Item/ItemStructure.h>
|
||||
#include <Log/ServerLog.h>
|
||||
#include <Quest/QuestMgr.h>
|
||||
#include <Creature/Character/CharacterClass.h>
|
||||
#include <Creature/CreatureStructure.h>
|
||||
|
||||
CModifyCharacter::CModifyCharacter()
|
||||
: CCharacter(0, 0)
|
||||
, m_dwServerGroup(0)
|
||||
, m_byChangedInfo(0)
|
||||
, m_bScheduleClose(false)
|
||||
, m_bSave(false)
|
||||
, m_bIsOwnCopyItem(false)
|
||||
|
||||
{
|
||||
Initialize(NULL);
|
||||
ZeroMemory(&m_ExtraData, sizeof(CHAR_EXTRA_DATA));
|
||||
|
||||
m_ModifyCharItemSerialInfo.clear();
|
||||
m_OverlapSerialInfo.clear();
|
||||
|
||||
m_cOldServerGroupID = UnifiedConst::Part2Selectable;
|
||||
}
|
||||
|
||||
// 이녀석은 사용하지 말자 Initialize <- 이녀석 캐릭터 생성후 딱~~ 1번만 사용하자
|
||||
// 그렇지 않으면 메모리 샌다 ㅡ.ㅡ;
|
||||
void CModifyCharacter::Reset()
|
||||
{
|
||||
SetUID(0);
|
||||
SetCID(0);
|
||||
|
||||
m_dwServerGroup = 0;
|
||||
m_byChangedInfo = 0;
|
||||
m_bScheduleClose = false;
|
||||
|
||||
ZeroMemory(&m_DBData, sizeof(CharacterDBData));
|
||||
Initialize(NULL);
|
||||
}
|
||||
|
||||
unsigned short CModifyCharacter::GetMaxSkillPoint()
|
||||
{
|
||||
// CalculateStatusData가 선행되어야 함.
|
||||
return m_CreatureStatus.m_StatusInfo.m_wSkillPoint;
|
||||
}
|
||||
|
||||
// 스킬 추가 및 스킬 레벨 변경 (이미 습득한 스킬을 추가 요청한다면 레벨 수정으로 인식)
|
||||
unsigned char CModifyCharacter::AppendSkill(unsigned short wSkillID, char cLevel, char cLockCount)
|
||||
{
|
||||
m_DBData.m_Skill.wSkillNum = m_DBData.m_Skill.GetSkillNum(); // 현재 스킬수 재 계산
|
||||
|
||||
const Skill::ProtoType* lpSkillProtoType = CSkillMgr::GetInstance().GetSkillProtoType(wSkillID);
|
||||
|
||||
short sSlotIndex = GetSkillSlotIndex(wSkillID);
|
||||
|
||||
bool bIsNewSkill = false; // 새 스킬 습득 여부
|
||||
if(-1 == sSlotIndex) bIsNewSkill = true;
|
||||
|
||||
if(NULL == lpSkillProtoType)
|
||||
{
|
||||
ERRLOG1(g_Log, "스킬 프로토 타입 얻기 실패. 스킬ID: 0x%04x", wSkillID);
|
||||
return PktAdminMgr::PktSkillEdit::FAILED_TO_GET_SKILLPROTOTYPE;
|
||||
}
|
||||
|
||||
if(CSkillMgr::MAX_SKILL_LOCKCOUNT <= cLockCount)
|
||||
{
|
||||
ERRLOG1(g_Log, "최대 스킬 락 카운트를 초과하였습니다. 락 카운트: %c", cLockCount);
|
||||
return PktAdminMgr::PktSkillEdit::OVERED_MAX_LOCKCOUNT;
|
||||
}
|
||||
|
||||
if(CSkillMgr::MAX_SKILL_LEVEL < cLevel)
|
||||
{
|
||||
ERRLOG1(g_Log, "최대 스킬 레벨을 초과하였습니다. 스킬 레벨: %c", cLevel);
|
||||
return PktAdminMgr::PktSkillEdit::OVERED_MAX_SKILL_LEVEL;
|
||||
}
|
||||
|
||||
if(lpSkillProtoType[0].m_usSkill_ID != lpSkillProtoType[cLockCount].m_usSkill_ID)
|
||||
{
|
||||
ERRLOG2(g_Log, "스킬 ID가 다릅니다. 0x%04x : 0x%04x", lpSkillProtoType[0].m_usSkill_ID,
|
||||
lpSkillProtoType[cLockCount].m_usSkill_ID);
|
||||
|
||||
return PktAdminMgr::PktSkillEdit::FAILED;
|
||||
}
|
||||
|
||||
// 최대 스킬 레벨을 추가할 경우 (다음 단계로 넘어가는 경우)
|
||||
if(cLevel == CSkillMgr::MAX_SKILL_LEVEL)
|
||||
{
|
||||
// 최종 단계 스킬이 아닌경우 다음 단계 0레벨 스킬로 습득
|
||||
if(cLockCount < CSkillMgr::MAX_SKILL_LOCKCOUNT - 1) // 아직 0~3 단계까지만 사용중
|
||||
{
|
||||
cLevel = 0;
|
||||
++cLockCount;
|
||||
}
|
||||
}
|
||||
|
||||
// 새로운 스킬 습득
|
||||
if(bIsNewSkill && (m_DBData.m_Skill.wSlotNum < SKILL::MAX_SLOT_NUM))
|
||||
{
|
||||
sSlotIndex = m_DBData.m_Skill.wSlotNum; // 새 슬롯 얻기
|
||||
}
|
||||
else if(m_DBData.m_Skill.wSlotNum == SKILL::MAX_SLOT_NUM)
|
||||
{
|
||||
ERRLOG0(g_Log, "이미 사용할 수 있는 최대 슬롯을 사용중입니다.");
|
||||
return PktAdminMgr::PktSkillEdit::NOT_ENOUGH_SKILLSLOT;
|
||||
}
|
||||
|
||||
SKILLSLOT TempSkillSlot;
|
||||
TempSkillSlot.SKILLINFO.wSkill = wSkillID;
|
||||
TempSkillSlot.SKILLINFO.cSkillLevel = cLevel;
|
||||
TempSkillSlot.SKILLINFO.cLockCount = cLockCount;
|
||||
|
||||
unsigned short cResult = ReadSkill(TempSkillSlot, wSkillID, cLockCount);
|
||||
|
||||
if(PktBase::NO_SERVER_ERR == cResult) // 사용 가능한 스킬임
|
||||
{
|
||||
SKILL& Skill = m_DBData.m_Skill;
|
||||
SKILLSLOT& SkillSlot = Skill.SSlot[sSlotIndex];
|
||||
|
||||
ChkEmptySlot(Skill); // 빈 슬롯을 가지고 있는지 체크
|
||||
|
||||
unsigned short BeforePoint =
|
||||
(SkillSlot.SKILLINFO.cLockCount * CSkillMgr::MAX_SKILL_LOCKCOUNT) + SkillSlot.SKILLINFO.cSkillLevel;
|
||||
|
||||
unsigned short AfterPoint =
|
||||
(cLockCount * CSkillMgr::MAX_SKILL_LOCKCOUNT) + cLevel;
|
||||
|
||||
// 기존 스킬 레벨 변경
|
||||
if((!bIsNewSkill) && (GetMaxSkillPoint() >= ((GetSkillPoint() - BeforePoint) + AfterPoint)))
|
||||
{
|
||||
SkillSlot.SKILLINFO.wSkill = wSkillID;
|
||||
SkillSlot.SKILLINFO.cSkillLevel = cLevel;
|
||||
SkillSlot.SKILLINFO.cLockCount = cLockCount;
|
||||
}
|
||||
// 새로운 스킬 추가
|
||||
else if(bIsNewSkill && (GetMaxSkillPoint() >= (GetSkillPoint() + AfterPoint)))
|
||||
{
|
||||
SkillSlot.SKILLINFO.wSkill = wSkillID;
|
||||
SkillSlot.SKILLINFO.cSkillLevel = cLevel;
|
||||
SkillSlot.SKILLINFO.cLockCount = cLockCount;
|
||||
|
||||
++m_DBData.m_Skill.wSlotNum; // 사용중인 슬롯수 + 1
|
||||
}
|
||||
|
||||
UpdateQuickSlotSkill(SkillSlot);
|
||||
m_DBData.m_Skill.wSkillNum = m_DBData.m_Skill.GetSkillNum();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(cResult)
|
||||
{
|
||||
case PktSk::FAIL_NOT_CURRENT_CLASS:
|
||||
return PktAdminMgr::PktSkillEdit::NOT_CURRENT_CLASS;
|
||||
case PktSk::FAIL_NOT_ENOUGH_STATUS:
|
||||
return PktAdminMgr::PktSkillEdit::NOT_ENOUGH_STAT;
|
||||
case PktSk::FAIL_MAX_LEVEL:
|
||||
return PktAdminMgr::PktSkillEdit::OVERED_MAX_SKILL_LEVEL;
|
||||
case PktSk::FAIL_NOT_CURRENT_LOCK_COUNT:
|
||||
return PktAdminMgr::PktSkillEdit::FAILED;
|
||||
default:
|
||||
return PktAdminMgr::PktSkillEdit::FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return PktAdminMgr::PktSkillEdit::SUCCESS;
|
||||
}
|
||||
|
||||
// 스킬 삭제 (스킬 포인트 조정 및 해당 스킬 슬롯 정보 초기화)
|
||||
unsigned char CModifyCharacter::DeleteSkill(unsigned short wSkillID, char cLevel, char cLockCount)
|
||||
{
|
||||
m_DBData.m_Skill.wSkillNum = m_DBData.m_Skill.GetSkillNum(); // 현재 스킬수 재 계산
|
||||
|
||||
short sDelSlotIndex = GetSkillSlotIndex(wSkillID);
|
||||
|
||||
if(-1 != sDelSlotIndex)
|
||||
{
|
||||
SKILL& Skill = m_DBData.m_Skill;
|
||||
SKILLSLOT& DelSlot = Skill.SSlot[sDelSlotIndex];
|
||||
|
||||
ChkEmptySlot(Skill); // 빈 슬롯을 가지고 있는지 체크
|
||||
|
||||
const Skill::ProtoType* lpSkillProtoType = CSkillMgr::GetInstance().GetSkillProtoType(wSkillID);
|
||||
if(NULL == lpSkillProtoType)
|
||||
{
|
||||
ERRLOG1(g_Log, "스킬 프로토 타입 얻기 실패. 스킬ID: 0x%04x", wSkillID);
|
||||
return PktAdminMgr::PktSkillEdit::FAILED_TO_GET_SKILLPROTOTYPE;
|
||||
}
|
||||
|
||||
if(DelSlot.SKILLINFO.wSkill != wSkillID)
|
||||
{
|
||||
ERRLOG3(g_Log, "삭제 요청 받은 스킬과 삭제 할 슬롯의 스킬이 일치하지 않습니다."
|
||||
"슬롯번호: %d , 삭제할 슬롯의 스킬ID: 0x%04x, 삭제 요청 한 스킬ID: 0x%04x",
|
||||
sDelSlotIndex, DelSlot.SKILLINFO.wSkill, wSkillID);
|
||||
|
||||
return PktAdminMgr::PktSkillEdit::FAILED;
|
||||
}
|
||||
|
||||
if(true == lpSkillProtoType->m_bIsClassSkill)
|
||||
{
|
||||
ERRLOG0(g_Log, "삭제하려는 스킬이 클래스 스킬입니다.");
|
||||
return PktAdminMgr::PktSkillEdit::FAILED;
|
||||
}
|
||||
|
||||
// 스킬 슬롯 중간이 비면 한칸씩 앞으로 당겨옴 (중간에 비는 슬롯이 없도록!)
|
||||
unsigned short sLastSlotIndex = Skill.wSlotNum - 1;
|
||||
|
||||
for(unsigned short sSlotIndex = sDelSlotIndex; sSlotIndex < sLastSlotIndex; ++sSlotIndex)
|
||||
{
|
||||
Skill.SSlot[sSlotIndex] = Skill.SSlot[sSlotIndex + 1];
|
||||
}
|
||||
|
||||
Skill.SSlot[sLastSlotIndex].SKILLINFO.wSkill = 0;
|
||||
Skill.SSlot[sLastSlotIndex].SKILLINFO.cSkillLevel = 0;
|
||||
Skill.SSlot[sLastSlotIndex].SKILLINFO.cLockCount = 0;
|
||||
|
||||
Skill.wSkillNum -=
|
||||
(DelSlot.SKILLINFO.cLockCount * CSkillMgr::MAX_SKILL_LEVEL) + DelSlot.SKILLINFO.cSkillLevel;
|
||||
|
||||
Skill.wSlotNum -= 1;
|
||||
|
||||
UpdateQuickSlotSkill(DelSlot);
|
||||
|
||||
return PktAdminMgr::PktSkillEdit::SUCCESS;
|
||||
}
|
||||
|
||||
return PktAdminMgr::PktSkillEdit::FAILED;
|
||||
}
|
||||
|
||||
bool CModifyCharacter::ChkEmptySlot(SKILL Skill)
|
||||
{
|
||||
CString strEmptySlotIndex;
|
||||
|
||||
for(unsigned short sSlotIndex = 0; sSlotIndex < Skill.wSlotNum; ++sSlotIndex)
|
||||
{
|
||||
if(0 == Skill.SSlot[sSlotIndex].SKILLINFO.wSkill)
|
||||
{
|
||||
strEmptySlotIndex.AppendFormat("%d ", sSlotIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if(!strEmptySlotIndex.IsEmpty())
|
||||
{
|
||||
ERRLOG3(g_Log, "스킬 슬롯에 빈슬롯이 있습니다. CID: %u, 슬롯수: %d, 빈슬롯: %s",
|
||||
GetCID(), Skill.wSlotNum, strEmptySlotIndex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 걍 날림 스킬레벨가져오기..
|
||||
// Return :
|
||||
// 존재하는 스킬이면 현재 내레벨.. 같은계열의 하위스킬일경우 MaxSkillLevel을...
|
||||
// 같은 계열스킬중 상위계열이면 0을 리턴..
|
||||
short CModifyCharacter::GetSkillLevelEX(unsigned short usSkillType, char cLockCount)
|
||||
{
|
||||
const Skill::ProtoType* lpSkillProtoType = CSkillMgr::GetInstance().GetSkillProtoType(usSkillType);
|
||||
|
||||
if(NULL != lpSkillProtoType)
|
||||
{
|
||||
int nMaxSlotNum = m_DBData.m_Skill.wSlotNum;
|
||||
|
||||
if(SKILL::MAX_SLOT_NUM >= nMaxSlotNum)
|
||||
{
|
||||
for( int nSlot = 0; nSlot < nMaxSlotNum; ++ nSlot )
|
||||
{
|
||||
const SKILLSLOT& SkillSlot = m_DBData.m_Skill.SSlot[ nSlot ];
|
||||
if( SkillSlot.SKILLINFO.wSkill == usSkillType )
|
||||
{
|
||||
if( SkillSlot.SKILLINFO.cLockCount == cLockCount )
|
||||
{
|
||||
return SkillSlot.SKILLINFO.cSkillLevel;
|
||||
}
|
||||
else if( SkillSlot.SKILLINFO.cLockCount > cLockCount )
|
||||
{
|
||||
return SKILL::MAX_SKILL_LEVEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool CModifyCharacter::SetGold(unsigned long dwGold)
|
||||
{
|
||||
if(dwGold > ULONG_MAX)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_DBData.m_Info.Gold = dwGold;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 캐릭터를 잡고 있는 관리자의 Session을 리턴~~
|
||||
CSession* CModifyCharacter::GetCheckSession( unsigned long dwUID )
|
||||
{
|
||||
if( m_dwUID == dwUID )
|
||||
{
|
||||
if( NULL != m_lpPacketDispatch )
|
||||
{
|
||||
CSession& lpSession = m_lpPacketDispatch->GetSession( );
|
||||
//if( NULL != lpSession ) return lpSession;
|
||||
return &lpSession;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 캐릭터 정보가 변경됬음을 기억해놓자..
|
||||
void CModifyCharacter::OnChangedInfo( int iMask )
|
||||
{
|
||||
m_byChangedInfo |= iMask;
|
||||
}
|
||||
|
||||
// 캐릭터 변경정보를 지운다..
|
||||
void CModifyCharacter::OffChangedInfo( int iMask )
|
||||
{
|
||||
m_byChangedInfo &= iMask;
|
||||
}
|
||||
|
||||
// 캐릭터의 Status
|
||||
void CModifyCharacter::GetModifyCharStatus(PktAdminMgr::CHAR_STATUS_ST& StatusST)
|
||||
{
|
||||
StatusST.m_cFace = m_DBData.m_Info.Face;
|
||||
StatusST.m_cHair = m_DBData.m_Info.Hair;
|
||||
StatusST.m_cLevel = m_DBData.m_Info.Level;
|
||||
StatusST.m_cRace = m_DBData.m_Info.Race;
|
||||
StatusST.m_cSex = m_DBData.m_Info.Sex;
|
||||
StatusST.m_dwExp = m_DBData.m_Info.Exp;
|
||||
StatusST.m_dwFame = m_DBData.m_Info.Fame;
|
||||
StatusST.m_dwMileage = m_DBData.m_Info.Mileage;
|
||||
StatusST.m_nClass = m_DBData.m_Info.Class;
|
||||
StatusST.m_nCON = m_DBData.m_Info.CON;
|
||||
StatusST.m_nDEX = m_DBData.m_Info.DEX;
|
||||
StatusST.m_nINT = m_DBData.m_Info.INT;
|
||||
StatusST.m_nIP = m_DBData.m_Info.IP;
|
||||
StatusST.m_nSTR = m_DBData.m_Info.STR;
|
||||
StatusST.m_nWIS = m_DBData.m_Info.WIS;
|
||||
StatusST.m_cChance = m_DBData.m_Info.Chance;
|
||||
}
|
||||
|
||||
// 캐릭터 Status변경..
|
||||
bool CModifyCharacter::UpdataStatus(PktAdminMgr::CHAR_STATUS_ST& StatusST)
|
||||
{
|
||||
CHAR_INFOST OrgCharInfo;
|
||||
|
||||
CopyMemory(&OrgCharInfo, &m_DBData.m_Info, sizeof(CHAR_INFOST));
|
||||
|
||||
m_DBData.m_Info.Sex = StatusST.m_cSex;
|
||||
m_DBData.m_Info.Hair = StatusST.m_cHair;
|
||||
m_DBData.m_Info.Face = StatusST.m_cFace;
|
||||
m_DBData.m_Info.Race = StatusST.m_cRace;
|
||||
m_DBData.m_Info.Class = StatusST.m_nClass;
|
||||
|
||||
m_DBData.m_Info.Fame = StatusST.m_dwFame;
|
||||
m_DBData.m_Info.Mileage = StatusST.m_dwMileage;
|
||||
|
||||
m_DBData.m_Info.Level = StatusST.m_cLevel;
|
||||
m_DBData.m_Info.Exp = StatusST.m_dwExp;
|
||||
|
||||
m_DBData.m_Info.IP = StatusST.m_nIP;
|
||||
|
||||
m_DBData.m_Info.STR = StatusST.m_nSTR;
|
||||
m_DBData.m_Info.CON = StatusST.m_nCON;
|
||||
m_DBData.m_Info.DEX = StatusST.m_nDEX;
|
||||
m_DBData.m_Info.INT = StatusST.m_nINT;
|
||||
m_DBData.m_Info.WIS = StatusST.m_nWIS;
|
||||
m_DBData.m_Info.Chance = StatusST.m_cChance;
|
||||
|
||||
m_CreatureStatus.m_nExp = StatusST.m_dwExp;
|
||||
m_CreatureStatus.m_nLevel = StatusST.m_cLevel;
|
||||
|
||||
// Status 계산식을 넣자
|
||||
if(!CalculateStatusData(false))
|
||||
{
|
||||
// 잘못된 Status값
|
||||
CopyMemory(&m_DBData.m_Info, &OrgCharInfo, sizeof(CHAR_INFOST));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 캐릭터가 소지하고 있는 아이템을 UID로 검색하여 리턴한다..
|
||||
// 해당 아이템이 없으면 NULL
|
||||
Item::CItem* CModifyCharacter::UIDbyItem(unsigned __int64 ItemUID, unsigned char cTakeType)
|
||||
{
|
||||
Item::CItemContainer::iterator Itr;
|
||||
|
||||
if(cTakeType == TakeType::TS_INVEN) // 인벤토리 아이템
|
||||
{
|
||||
Item::CArrayContainer& ArrayContainer = GetInventory();
|
||||
Itr = ArrayContainer.begin();
|
||||
|
||||
for(;Itr != ArrayContainer.end(); ++Itr)
|
||||
{
|
||||
if(NULL != (*Itr))
|
||||
{
|
||||
if((*Itr)->GetUID() == ItemUID) return (*Itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( cTakeType == TakeType::TS_EQUIP ) // 장비창 아이템
|
||||
{
|
||||
Item::CEquipmentsContainer& EquipContainer = GetEquipments( );
|
||||
Itr = EquipContainer.begin( );
|
||||
|
||||
for(;Itr != EquipContainer.end(); ++Itr )
|
||||
{
|
||||
if(NULL != (*Itr))
|
||||
{
|
||||
if((*Itr)->GetUID() == ItemUID) return (*Itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(cTakeType == TakeType::TS_DEPOSIT) // 창고 아이템
|
||||
{
|
||||
Item::CDepositContainer& DepositContainer = GetDeposit();
|
||||
|
||||
for (unsigned char cTab = 0; cTab < DepositContainer.GetMaxTabNum(); ++cTab)
|
||||
{
|
||||
Item::CItemContainer* DepositTabContainer = DepositContainer.GetTab(cTab);
|
||||
Itr = DepositTabContainer->begin();
|
||||
for(; Itr != DepositTabContainer->end( ); ++Itr )
|
||||
{
|
||||
if( NULL != ( *Itr ) )
|
||||
{
|
||||
if( ( *Itr )->GetUID( ) == ItemUID ) return ( *Itr );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CModifyCharacter::ChangeName(char* szName)
|
||||
{
|
||||
strncpy(m_DBData.m_Info.Name, szName, CHAR_INFOST::MAX_NAME_LEN);
|
||||
}
|
||||
|
||||
// 캐릭터를 편집중인 관리자 계정을 저장한다.
|
||||
void CModifyCharacter::SetModifyAdmin(char* Account, int Length)
|
||||
{
|
||||
strncpy(m_szModifyAdmin, Account, Length);
|
||||
}
|
||||
|
||||
void CModifyCharacter::ParseQuestData()
|
||||
{
|
||||
Quest::ExecutingQuest* aryExecutingQuest = GetExecutingQuest();
|
||||
unsigned short* aryHistoryQuest = GetHistoryQuest();
|
||||
|
||||
// 수행중인 퀘스트 목록
|
||||
int nIndex = 0;
|
||||
|
||||
PktQuestDB::ExecutingQuest* lpExecuteQuestPos =
|
||||
reinterpret_cast<PktQuestDB::ExecutingQuest*>(m_ExtraData.m_Quest.Data);
|
||||
|
||||
PktQuestDB::ExecutingQuest* lpExecuteQuestEnd =
|
||||
reinterpret_cast<PktQuestDB::ExecutingQuest*>(m_ExtraData.m_Quest.Data) +
|
||||
(m_ExtraData.m_Quest.dwSize / sizeof(PktQuestDB::ExecutingQuest));
|
||||
|
||||
for(; lpExecuteQuestPos != lpExecuteQuestEnd; ++lpExecuteQuestPos)
|
||||
{
|
||||
Quest::QuestNode* lpQuest = CQuestMgr::GetInstance().GetQuestNode(lpExecuteQuestPos->m_wQuestID);
|
||||
|
||||
if (0 != lpQuest && false == lpQuest->CheckNationDependent(GetUserNation()))
|
||||
{
|
||||
aryExecutingQuest[nIndex] = Quest::ExecutingQuest(lpExecuteQuestPos->m_wQuestID,
|
||||
lpExecuteQuestPos->m_cPhase, lpExecuteQuestPos->m_cTriggerCount);
|
||||
|
||||
++nIndex;
|
||||
}
|
||||
}
|
||||
|
||||
nIndex = 0;
|
||||
|
||||
// 완료 퀘스트 목록
|
||||
unsigned short* lpHistoryQuestPos =
|
||||
reinterpret_cast<unsigned short*>(m_ExtraData.m_History.Data);
|
||||
|
||||
unsigned short* lpHistoryQuestEnd =
|
||||
reinterpret_cast<unsigned short*>(m_ExtraData.m_History.Data) +
|
||||
(m_ExtraData.m_History.dwSize / sizeof(unsigned short));
|
||||
|
||||
for (; lpHistoryQuestPos != lpHistoryQuestEnd; ++lpHistoryQuestPos)
|
||||
{
|
||||
Quest::QuestNode* lpQuest = CQuestMgr::GetInstance().GetQuestNode(*lpHistoryQuestPos);
|
||||
|
||||
if (0 != lpQuest && false == lpQuest->CheckNationDependent(GetUserNation()))
|
||||
{
|
||||
aryHistoryQuest[nIndex] = *lpHistoryQuestPos;
|
||||
++nIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// 퀘스트에 의해 받는 영향을 계산
|
||||
CalculateStatusData(false);
|
||||
}
|
||||
|
||||
void CModifyCharacter::SetQuestData()
|
||||
{
|
||||
const int MAX_BUFFER =
|
||||
sizeof(PktQuestDB) + PktQuestDB::MAX_EXECUTING_QUEST * sizeof(PktQuestDB::ExecutingQuest) +
|
||||
PktQuestDB::MAX_HISTORY_QUEST * sizeof(unsigned short);
|
||||
|
||||
char szBuffer[MAX_BUFFER];
|
||||
|
||||
PktQuestDB* lpPktQuestDB = reinterpret_cast<PktQuestDB*>(szBuffer);
|
||||
|
||||
lpPktQuestDB->m_dwUID = GetUID();
|
||||
lpPktQuestDB->m_dwCID = GetCID();
|
||||
lpPktQuestDB->m_wExecuteQuestSize = 0;
|
||||
lpPktQuestDB->m_wHistoryQuestSize = 0;
|
||||
|
||||
Quest::ExecutingQuest* ExecutingQuest = GetExecutingQuest();
|
||||
unsigned short *wHistoryQuest = GetHistoryQuest();
|
||||
|
||||
int nIndex = 0;
|
||||
for (nIndex = 0; nIndex < PktQuestDB::MAX_EXECUTING_QUEST; ++nIndex)
|
||||
{
|
||||
if (NULL == ExecutingQuest[nIndex].m_QuestNode)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
PktQuestDB::ExecutingQuest* ExecuteQuest =
|
||||
reinterpret_cast<PktQuestDB::ExecutingQuest*>
|
||||
(szBuffer + sizeof(PktQuestDB) + lpPktQuestDB->m_wExecuteQuestSize);
|
||||
|
||||
ExecuteQuest->m_wQuestID = ExecutingQuest[nIndex].m_QuestNode->m_wQuestID;
|
||||
ExecuteQuest->m_cPhase = ExecutingQuest[nIndex].m_cPhase;
|
||||
memcpy(ExecuteQuest->m_cTriggerCount, ExecutingQuest[nIndex].m_cTriggerCount,
|
||||
sizeof(unsigned char) * PktQuestDB::MAX_TRIGGER);
|
||||
|
||||
lpPktQuestDB->m_wExecuteQuestSize += sizeof(PktQuestDB::ExecutingQuest);;
|
||||
}
|
||||
|
||||
for (nIndex = 0; nIndex < PktQuestDB::MAX_HISTORY_QUEST; nIndex++)
|
||||
{
|
||||
if (0 == wHistoryQuest[nIndex])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned short* wHistoryQuestForPkt =
|
||||
reinterpret_cast<unsigned short *>(szBuffer + sizeof(PktQuestDB) +
|
||||
lpPktQuestDB->m_wExecuteQuestSize + lpPktQuestDB->m_wHistoryQuestSize);
|
||||
|
||||
*wHistoryQuestForPkt = wHistoryQuest[nIndex];
|
||||
|
||||
lpPktQuestDB->m_wHistoryQuestSize += sizeof(unsigned short);
|
||||
}
|
||||
|
||||
memset(&m_ExtraData.m_Quest, 0, sizeof(QUEST));
|
||||
m_ExtraData.m_Quest.dwSize = lpPktQuestDB->m_wExecuteQuestSize;
|
||||
memcpy(m_ExtraData.m_Quest.Data, lpPktQuestDB + 1, lpPktQuestDB->m_wExecuteQuestSize);
|
||||
|
||||
memset(&m_ExtraData.m_History, 0, sizeof(HISTORY));
|
||||
m_ExtraData.m_History.dwSize = lpPktQuestDB->m_wHistoryQuestSize;
|
||||
memcpy(m_ExtraData.m_History.Data, reinterpret_cast<char*>(lpPktQuestDB + 1) + lpPktQuestDB->m_wExecuteQuestSize,
|
||||
lpPktQuestDB->m_wHistoryQuestSize);
|
||||
}
|
||||
|
||||
void CModifyCharacter::RevisionQuestNation()
|
||||
{
|
||||
using namespace Creature;
|
||||
|
||||
// 양국체제에선 무조건 휴먼은 카르테란트, 아칸은 메르카디아! (퀘스트 파싱할때 필요)
|
||||
switch(GetRace())
|
||||
{
|
||||
case CClass::RaceType::HUMAN:
|
||||
m_cQuestNation = Creature::KARTERANT;
|
||||
break;
|
||||
case CClass::RaceType::AKHAN:
|
||||
m_cQuestNation = Creature::MERKADIA;
|
||||
break;
|
||||
default:
|
||||
m_cQuestNation = Creature::MAX_NATION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// class CModifyItem Down_Cast ----------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void CModifyItem::SetUID(unsigned __int64 UID)
|
||||
{
|
||||
m_ItemData.m_dwUID = UID;
|
||||
}
|
||||
|
||||
void CModifyItem::SetPrototoypID(unsigned short PrototypeID)
|
||||
{
|
||||
m_ItemData.m_usProtoTypeID = PrototypeID;
|
||||
}
|
||||
291
Server/AdminTool/AdminToolLibrary/character/ModifyCharacter.h
Normal file
291
Server/AdminTool/AdminToolLibrary/character/ModifyCharacter.h
Normal file
@@ -0,0 +1,291 @@
|
||||
#ifndef _MODIFY_CHARACTER_H_
|
||||
#define _MODIFY_CHARACTER_H_
|
||||
|
||||
#include < Creature/Character/Character.h >
|
||||
#include < Network/Protocol/Ryl_AdminMgrProtocol.h >
|
||||
#include < Pattern/Singleton.h >
|
||||
|
||||
// 전처리 ------------------------
|
||||
class CPacketDispatch;
|
||||
class CModifyCharacterMgr;
|
||||
class CBuffer;
|
||||
class CSession;
|
||||
//--------------------------------
|
||||
|
||||
// Ryl_ItemData.cpp
|
||||
namespace ItemData
|
||||
{
|
||||
// 아이템 좌표를 만든다.
|
||||
Item::ItemPos MakeItemPos(unsigned char cPos, unsigned char cX, unsigned char cY, unsigned char cZ);
|
||||
// 어떤위치에 아이템이 존재할까?
|
||||
inline bool IsArrayContainer(unsigned char cTakePos);
|
||||
// 아이템을 복사한다.
|
||||
Item::CItem* CloneItem(Item::CItem* lpSrcItem, PktAdminMgr::CreateItemInfo EquipInfo);
|
||||
|
||||
// 한개의 UID에 3명의 캐릭터가 있고 3명의 캐릭터는 1개의 창고를 사용한다..
|
||||
// 여러 계정의 창고 접근을 막자..
|
||||
// 창고데이터가 갱신됬을경우 해당 UID에 걸려있는 캐릭터를 작업중인 관리자들에게 창고 정보를 갱신시켜 주자.
|
||||
class CDepositLock
|
||||
{
|
||||
public:
|
||||
struct DepositInfo
|
||||
{
|
||||
unsigned long m_dwCID;
|
||||
CPacketDispatch* m_lpPacketDispatch;
|
||||
|
||||
DepositInfo()
|
||||
: m_dwCID(0)
|
||||
, m_lpPacketDispatch(NULL) { ;}
|
||||
|
||||
DepositInfo(unsigned long dwCID, CPacketDispatch* lpPacketDispatch)
|
||||
: m_dwCID(dwCID)
|
||||
, m_lpPacketDispatch(lpPacketDispatch) { ;}
|
||||
};
|
||||
|
||||
typedef std::map< unsigned long, DepositInfo > isMapDeposit;
|
||||
typedef isMapDeposit::iterator isDepositPos;
|
||||
|
||||
public:
|
||||
isDepositPos begin() { return m_DepositUser.begin(); }
|
||||
isDepositPos end() { return m_DepositUser.end(); }
|
||||
|
||||
size_t size() { return m_DepositUser.size(); }
|
||||
|
||||
bool isUse(unsigned long dwUID, unsigned long dwCID, CPacketDispatch* lpPacketDispatch, bool& bisLock);
|
||||
void DepositLock(unsigned long dwUID, unsigned long dwCID, CPacketDispatch* lpPacketDispatch);
|
||||
void DepositUnLock(unsigned long dwUID);
|
||||
|
||||
CPacketDispatch* GetDispatch(unsigned long dwUID);
|
||||
void RemoveAllSelectDispatch(CPacketDispatch* lpPacketDispatch);
|
||||
bool GetLockInfo(unsigned long dwUID, DepositInfo& Info);
|
||||
|
||||
private:
|
||||
isMapDeposit m_DepositUser;
|
||||
};
|
||||
};
|
||||
|
||||
// LearnSkill.cpp
|
||||
// 특정 캐릭터가 습득가능한 스킬을 표시하기 위해 필요한 클래스
|
||||
// 스킬 스크립트를 로드하여 아이템타입을 제외한 모든 스킬의 ID만 보관
|
||||
class CSkillID : public CStaticSingleton<CSkillID>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::list<unsigned short> isListSkillUID;
|
||||
typedef isListSkillUID::iterator isListSkillPos;
|
||||
|
||||
~CSkillID() { m_listSkillUID.clear(); }
|
||||
|
||||
isListSkillPos begin() { return m_listSkillUID.begin(); }
|
||||
isListSkillPos end() { return m_listSkillUID.end(); }
|
||||
|
||||
void insert(unsigned short SkillUID) { m_listSkillUID.push_back(SkillUID); }
|
||||
bool ReadSkillScript(char* szScriptName = "./Script/Game/SkillScript.txt");
|
||||
|
||||
private:
|
||||
|
||||
isListSkillUID m_listSkillUID;
|
||||
};
|
||||
|
||||
|
||||
// Item::CEquipment 다운 캐스트 클래스 (멤버 변수 추가하지 마시오!)
|
||||
class CModifyEquipment : public Item::CEquipment
|
||||
{
|
||||
public:
|
||||
void AdjustData(PktAdminMgr::CreateItemInfo EquipInfo)
|
||||
{
|
||||
m_cMaxNumOrDurability = EquipInfo.m_cMaxDurability;
|
||||
m_cMaxSocket = EquipInfo.m_cMaxSocketNum;
|
||||
m_cUpgradeLevel = EquipInfo.m_cUpgradeLevel;
|
||||
m_cSeasonRecord = EquipInfo.m_cSeasonRecord;
|
||||
m_cCoreLevel = EquipInfo.m_cCoreLevel;
|
||||
|
||||
for(m_cSocketNum = 0; m_cSocketNum < m_cMaxSocket; ++m_cSocketNum)
|
||||
{
|
||||
if (0 == EquipInfo.m_cSocket[m_cSocketNum]) break;
|
||||
}
|
||||
|
||||
CopyMemory(m_cSocket, EquipInfo.m_cSocket,
|
||||
sizeof(unsigned char) * m_cSocketNum);
|
||||
CopyMemory(m_usRuneSocket, EquipInfo.m_usRuneSocket,
|
||||
sizeof(unsigned short) * Item::EquipmentInfo::MAX_RUNE_SOCKET_NUM);
|
||||
CopyMemory(m_wAttribute, EquipInfo.m_usAttribute,
|
||||
sizeof(unsigned short) * Item::Attribute::MAX_ATTRIBUTE_NUM);
|
||||
}
|
||||
|
||||
void AddGemAttribute() { ApplyGemAttribute(APPLY); }
|
||||
void RemoveGemAttribute() { ApplyGemAttribute(REMOVE); }
|
||||
|
||||
void AddUpgradeAttribute() { ApplyUpgradeAttribute(APPLY); }
|
||||
void RemoveUpgradeAttribute() { ApplyUpgradeAttribute(REMOVE); }
|
||||
|
||||
void AddRuneAttribute() { ApplyRuneAttribute(APPLY); }
|
||||
void RemoveRuneAttribute() { ApplyRuneAttribute(REMOVE); }
|
||||
};
|
||||
|
||||
// Item::CItem 다운 캐스트 클래스 (멤버 변수 추가하지 마시오!)
|
||||
class CModifyItem : public Item::CItem
|
||||
{
|
||||
public:
|
||||
void SetUID(unsigned __int64 UID);
|
||||
void SetPrototoypID(unsigned short PrototypeID);
|
||||
};
|
||||
|
||||
|
||||
// 캐릭터 정보 수정을 위한 확장 클래스
|
||||
class CModifyCharacter : public CCharacter
|
||||
{
|
||||
friend CModifyCharacterMgr;
|
||||
|
||||
public:
|
||||
#pragma pack(1)
|
||||
struct CHAR_EXTRA_DATA
|
||||
{
|
||||
CHAR_INFOEX m_CharInfoEX;
|
||||
QUEST m_Quest;
|
||||
HISTORY m_History;
|
||||
CONFIG m_Config;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
enum MASK
|
||||
{
|
||||
ON_BASIC = 1, // ON_BASIC 정보 수정
|
||||
ON_EXTRA = 2, // ON_EXTRA 정보 수정
|
||||
ON_FRIEND = 4, // ON_FRIEND 정보 수정
|
||||
ON_BAN = 8, // ON_BAN 정보 수정
|
||||
ON_STROE12 = 16, // ON_STROE12 정보 수정
|
||||
ON_STORE34 = 32, // ON_STORE34 정보 수정
|
||||
|
||||
OFF_BASIC = 62, // ON_BASIC 정보 없음
|
||||
OFF_EXTRA = 61, // ON_EXTRA 정보 없음
|
||||
OFF_FRIEND = 59, // ON_FRIEND 정보 없음
|
||||
OFF_BAN = 55, // ON_BAN 정보 없음
|
||||
OFF_STORE12 = 47, // ON_STROE12 정보 없음
|
||||
OFF_STORE34 = 31, // ON_STORE34 정보 없음
|
||||
};
|
||||
|
||||
CModifyCharacter();
|
||||
~CModifyCharacter() { }
|
||||
|
||||
BYTE m_byChangedInfo;
|
||||
|
||||
void SetUID(unsigned long dwUID) { m_dwUID = dwUID; } // 캐릭터 UID 변경
|
||||
void SetCID(unsigned long dwCID) { m_dwCID = dwCID; } // 캐릭터 CID 변경
|
||||
void SetUserNation(unsigned char cNation) { m_cQuestNation = cNation; } // 캐릭터 국적 변경
|
||||
void SetServerGroup(unsigned long dwServerGroup) { m_dwServerGroup = dwServerGroup; } // 서버그룹 변경
|
||||
void SetOldServerGroup(unsigned char cGroupID) { m_cOldServerGroupID = cGroupID; } // Old 서버 그룹 변경
|
||||
unsigned long GetServerGroup() { return m_dwServerGroup; } // 현재 서버그룹 얻기
|
||||
|
||||
void SetModifyAdmin(char* Account, int Length); // 에디팅중인 관리자 아이디 변경
|
||||
void SetDispatch(CPacketDispatch* lpPacketDispatch) { m_lpPacketDispatch = lpPacketDispatch; } // 에디팅중인 관리자 Dispatch변경
|
||||
CPacketDispatch* GetDispatch() { return m_lpPacketDispatch; } // 에디팅중인 관리자의 Dispatch를 가져온다
|
||||
|
||||
unsigned short GetMaxHP() { return m_CreatureStatus.m_StatusInfo.m_nMaxHP; } // 캐릭터의 최대 체력
|
||||
unsigned short GetNowHP() { return m_CreatureStatus.m_nNowHP; } // 캐릭터의 현재 체력
|
||||
unsigned short GetMaxMP() { return m_CreatureStatus.m_StatusInfo.m_nMaxMP; } // 캐릭터의 최대 마나
|
||||
unsigned short GetNowMP() { return m_CreatureStatus.m_nNowMP; } // 캐릭터의 현재 마나
|
||||
|
||||
char* GetName() { return m_DBData.m_Info.Name; } // 캐릭명 얻기
|
||||
void ChangeName(char* szName); // 캐릭명 변경
|
||||
void GetModifyCharStatus(PktAdminMgr::CHAR_STATUS_ST& StatusST); // 스테이터스 정보 얻기
|
||||
CHAR_EXTRA_DATA& GetExtraData() { return m_ExtraData; } // 기타 정보 얻기
|
||||
bool UpdataStatus(PktAdminMgr::CHAR_STATUS_ST& StatusST); // 스테이터스 정보 수정
|
||||
bool SetGold(unsigned long dwGold); // 캐릭터 소지금 변경
|
||||
Item::CItem* UIDbyItem(unsigned __int64 ItemUID, unsigned char cTakeType); // 아이템UID로 캐릭터 아이템 검색
|
||||
|
||||
unsigned short GetMaxSkillPoint(); // 캐릭터가 사용할 수 있는 스킬 포인트
|
||||
unsigned short GetSkillPoint() { return m_DBData.m_Skill.GetSkillNum(); } // 현재 스킬 수
|
||||
SKILL& GetSkill() { return m_DBData.m_Skill; } // 캐릭터의 스킬 정보
|
||||
unsigned char AppendSkill(unsigned short wSkillID, char cLevel, char cLockCount); // 스킬 추가
|
||||
unsigned char DeleteSkill(unsigned short wSkillID, char cLevel, char cLockCount); // 스킬 삭제
|
||||
short GetSkillLevelEX(unsigned short usSkillType, char cLockCount); // 스킬 레벨 얻기
|
||||
bool ChkEmptySlot(SKILL Skill); // 빈 슬롯이 있는지 체크
|
||||
|
||||
CHAR_POS& GetLastPos() { return m_DBData.m_Pos; } // 캐릭터의 마지막 위치 얻기
|
||||
Position& GetCurPos() { return m_CurrentPos; } // 캐릭터의 마지막 위치를 얻기(데이터베이스 정보)
|
||||
void SetServerID(unsigned long dwServerID) { m_ExtraData.m_CharInfoEX.ServerID = dwServerID; } // 캐릭터의 마지막 서버 아이디(존) 수정
|
||||
unsigned long GetServerID() { return m_ExtraData.m_CharInfoEX.ServerID; } // 마지막 존 얻기
|
||||
|
||||
void Reset(); // 전부 초기화
|
||||
|
||||
void OnChangedInfo(int iMask); // 정보가 변경된 섹션 저장
|
||||
void OffChangedInfo(int iMask); // 정보 변경 섹션을 해제
|
||||
void SetNextClose() { m_bScheduleClose = true; } // 저장후 캐릭터닫음 설정
|
||||
bool isClose() { return m_bScheduleClose; } // 캐릭터의 닫힌 상태 여부
|
||||
void SetClientKey(unsigned long dwClientKey) { m_dwClientRequestKey = dwClientKey; } // 관리자의 클라이언트 키를 변경 ( 클라이언트가 MDI로 계발되었기때문에 있어야함 )
|
||||
unsigned long GetClientKey() { return m_dwClientRequestKey; } // 관리자의 클라이언트키 가져오기
|
||||
unsigned char GetOldServerGroupID() { return m_cOldServerGroupID; } // 이전 서버군 ID 얻기 (Part2Selectable)
|
||||
|
||||
CSession* GetCheckSession(unsigned long dwUID); // 세션 무결성 체크
|
||||
|
||||
void SetSaveState(bool bSave) { m_bSave = bSave; } // 저장임을 알리자
|
||||
bool GetSaveState() { return m_bSave; } // 저장 중인지 여부
|
||||
|
||||
// 중복 아이템 검사 관련
|
||||
typedef std::set <__int64> ModifyCharItemSerialInfo;
|
||||
typedef std::vector<__int64> OverlapSerialInfo;
|
||||
|
||||
ModifyCharItemSerialInfo m_ModifyCharItemSerialInfo;
|
||||
OverlapSerialInfo m_OverlapSerialInfo;
|
||||
|
||||
void SetOwnCopyItemState(bool IsOwn) { m_bIsOwnCopyItem = IsOwn; } // 복사 아이템 소유여부 셋팅
|
||||
bool IsOwnCopyItem() { return m_bIsOwnCopyItem; } // 복사 아이템 소유여부
|
||||
|
||||
void ParseQuestData();
|
||||
void SetQuestData();
|
||||
|
||||
unsigned char GetUserNation() { return m_cQuestNation; }
|
||||
|
||||
char GetChance() { return m_DBData.m_Info.Chance; }
|
||||
|
||||
unsigned char GetNameChangeChance() { return m_ExtraData.m_CharInfoEX.cNameChangeCount; }
|
||||
void SetNameChangeChance(unsigned char cChance) { m_ExtraData.m_CharInfoEX.cNameChangeCount = cChance; }
|
||||
|
||||
void RevisionQuestNation(); // 퀘스트 종속성 체크용 국적 설정(2005-11-23 추가)
|
||||
|
||||
private:
|
||||
|
||||
CPacketDispatch* m_lpPacketDispatch; // 접근중인 관리자 디스패치
|
||||
|
||||
unsigned long m_dwServerGroup; // 해당 캐릭터가 존재하는 중계서버의 그룹
|
||||
char m_szModifyAdmin[40]; // 에디팅중인 관리자 계정명
|
||||
bool m_bScheduleClose; // 업데이트후 캐릭터 세션을 닫을지 여부
|
||||
unsigned long m_dwClientRequestKey; // 클라이언트 수정창(문서)의 식별번호
|
||||
bool m_bSave; // 저장 중인지 여부
|
||||
bool m_bIsOwnCopyItem; // 복사 아이템 소유 여부
|
||||
|
||||
unsigned char m_cQuestNation; // 국적 퀘스트 종속성 검사용
|
||||
unsigned char m_cOldServerGroupID; // Part2Selectable 타입일때 필요한 정보
|
||||
|
||||
CHAR_EXTRA_DATA m_ExtraData; // 캐릭터 정보 구조체 (기타, 퀘스트, 히스토리, 설정)
|
||||
};
|
||||
|
||||
|
||||
// 정보 열람, 수정 중인 캐릭터 목록 관리
|
||||
// 각 서버 그룹의 Dispatch가 각각 1개씩 소유
|
||||
class CModifyCharacterMgr
|
||||
{
|
||||
public:
|
||||
typedef std::map<unsigned long, CModifyCharacter*> isMapCharList;
|
||||
typedef isMapCharList::iterator iterator;
|
||||
|
||||
iterator begin() { return m_mapModifyChar.begin(); }
|
||||
iterator end() { return m_mapModifyChar.end(); }
|
||||
size_t size() { return m_mapModifyChar.size(); }
|
||||
|
||||
CModifyCharacter* GetCharacter(unsigned long dwCID); // 캐릭터 얻기
|
||||
CModifyCharacter* InsertChar(unsigned long dwCID); // 캐릭터 등록
|
||||
bool EraseChar(unsigned long dwCID); // 캐릭터 삭제
|
||||
|
||||
void AllRemoveChar(CPacketDispatch* lpPacketDispatch); // lpPacketDispatch를 사용하는 캐릭터를 목록에서 모두 삭제
|
||||
|
||||
void isUIDSendAll(unsigned long dwUID, CBuffer* lpBuffer); // UID가 같은 캐릭터 목록의 Dispatch로 패킷 전송
|
||||
|
||||
private:
|
||||
CModifyCharacter* CreateCharacter() { return new CModifyCharacter; }
|
||||
|
||||
isMapCharList m_mapModifyChar;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user