Files
Client/Server/RylServerProject/RylGameLibrary/Network/Dispatch/GameClient/ParseCharAdmin.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

2149 lines
69 KiB
C++

#include "stdafx.h"
#include <Creature/CreatureManager.h>
#include <Creature/Character/Character.h>
#include <Creature/Character/CharacterClass.h>
#include <Creature/Character/CharacterCreate.h>
#include <Creature/Character/ExpTable.h>
#include <Creature/Monster/Monster.h>
#include <Creature/Monster/AwardTable.h>
#include <Creature/Monster/VirtualMonsterMgr.h>
#include <Network/Dispatch/ParseUtils.h>
#include <Network/Dispatch/Chat/ChatDispatch.h>
#include <Network/Dispatch/DBAgent/DBAgentDispatch.h>
#include <Network/Dispatch/DBAgent/DBAgentRequest.h>
#include <Network/Dispatch/GameClient/SendCharItem.h>
#include <Network/Dispatch/GameClient/SendCharAttack.h>
#include <Network/Dispatch/GameClient/SendCharEtc.h>
#include <Network/Dispatch/GameClient/SendCharAdmin.h>
#include <Network/Dispatch/GameClient/SendCharQuest.h>
#include <Network/Dispatch/GameClient/SendCharCommunity.h>
#include <Network/Dispatch/GameClient/SendCharLevelUp.h>
#include <Network/Packet/ChatPacket.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Network/Packet/PacketStruct/CharAdminPacket.h>
#include <Skill/SkillTable.h>
#include <Skill/Spell/SpellTable.h>
#include <Skill/Spell/GlobalSpellMgr.h>
#include <Map/FieldMap/CellManager.h>
#include <Map/FieldMap/VirtualArea/VirtualArea.h>
#include <Map/FieldMap/VirtualArea/VirtualAreaMgr.h>
#include <Map/FieldMap/VirtualArea/BGServer/BGServerMap.h>
#include <Log/LogStruct.h>
#include <Log/ItemLog.h>
#include <Community/Party/Party.h>
#include <Quest/QuestMgr.h>
#include <Item/Item.h>
#include <Item/ItemFactory.h>
#include <Utility/Filter/Filter.h>
#include <Utility/Setup/ServerSetup.h>
#include "GameClientDispatch.h"
#include "ParseCharAdmin.h"
#include <Network/Packet/PacketStruct/CastlePacket.h>
struct Respawn
{
bool operator() (CCharacter* lpCharacter)
{
if (NULL != lpCharacter)
{
lpCharacter->Respawn();
if (0 != lpCharacter->GetPID())
{
// 파티원 리스폰을 알린다.
GameClientSendPacket::SendCharDeadToParty(lpCharacter, 0, PktDeadInfo::RESPAWN);
}
}
return true;
}
};
bool GameClientParsePacket::ParseCharAdminCmd(CGameClientDispatch& GameClientDispatch, PktBase* lpPktBase)
{
CHECK_FIXED_PACKETSIZE(lpPktBase, sizeof(PktAdmin), GameClientDispatch);
PktAdmin* lpPktAdmin = static_cast<PktAdmin*>(lpPktBase);
CCharacter* lpAdmin = GameClientDispatch.GetCharacter();
CHECK_CHARACTER_PTR(lpAdmin, GameClientDispatch, lpPktBase->GetCmd());
if (false == lpAdmin->IsAdmin())
{
ERRLOG1(g_Log, "CID:0x%08x 어드민 명령 오류 : 어드민 캐릭터가 아닙니다.", lpAdmin->GetCID());
return true;
}
BOOL bResult = FALSE;
switch(lpAdmin->GetAdminLevel())
{
/* case 4:
switch(lpPktAdmin->m_usCmd)
{
case PktAdmin::DBAGENT_KILL:
bResult = TRUE;
break;
}
*/
case 5: // 개발자
case 4: // 어드민3
switch(lpPktAdmin->m_usCmd)
{
case PktAdmin::RESPAWN_CHAR: //= 5, // 캐릭터 리스폰
case PktAdmin::DUEL_INIT: //= 9, // 듀얼 초기화
case PktAdmin::KILL_CHAR: //= 7, // 캐릭터 킬
case PktAdmin::CREATE_ITEM: //= 10, // 아이템 드롭
case PktAdmin::CREATE_MON: //= 11, // 몬스터 생성
case PktAdmin::GET_EXP: //= 13, // 경험치 얻기
case PktAdmin::GET_GOLD: //= 14, // 돈 얻기
case PktAdmin::LEVEL_UP: //= 15, // 레벨업
case PktAdmin::GET_FAME: //= 18, // 명성 얻기
case PktAdmin::GET_MILEAGE: //= 19, // 마일리지 얻기
case PktAdmin::APOCALYPSE: //= 26, // 주위 생물체 모두 킬
case PktAdmin::CREATE_EQUIP: //= 27, // 랜덤 옵션이 붙는 장비 드롭
case PktAdmin::ELITE_BONUS: //= 28, // 엘리트 보너스 조절
case PktAdmin::STATUE_INIT: //= 29, // 명예의 석상 초기화
case PktAdmin::RESPAWN_ALL: //= 30, // 모든 캐릭터 리스폰
case PktAdmin::CHANGE_CLASS: //= 31, // 전직 하기
case PktAdmin::LEARN_SKILL: //= 32, // 해당 스킬 배우기
case PktAdmin::ERASE_SKILL: //= 33, // 해당 스킬 지우기
case PktAdmin::LEVEL_DOWN: //= 34, // 레벨 다운
case PktAdmin::GET_QUEST: //= 35, // 퀘스트 받음
case PktAdmin::ADD_QUEST: //= 36, // 완료 퀘스트에 추가
case PktAdmin::DELETE_QUEST: //= 37, // 수행/완료 퀘스트를 삭제
case PktAdmin::SET_ITEM_TEMP_INVEN: //= 45, // 임시 인벤토리에 아이템 넣기
case PktAdmin::ADD_SPELL: //= 46, // 해당 스펠을 부여
case PktAdmin::REALM_POINT: //= 58, // 국가 전쟁 공헌 훈장.
case PktAdmin::LEARN_ABILITY: //= 60, // 해당 스킬 배우기.
case PktAdmin::ERASE_ABILITY: //= 61, // 해당 스킬 지우기
// BG
case PktAdmin::FINISH_GAME: //= 38, // 해당 방의 경기 종료 (승패 결정)
case PktAdmin::DRAW_GAME: //= 39, // 해당 방의 경기 종료 (무승부)
case PktAdmin::IGNORE_GAME: //= 40, // 해당 방의 경기 종료 (승패 무시)
case PktAdmin::SET_MAX: //= 41, // 해당 방의 최대 인원수 설정
case PktAdmin::SET_SCORE: //= 42, // 해당 방의 목표 점수 설정
case PktAdmin::SET_LIMIT_TIME: //= 43, // 해당 방의 시간 제한 설정
case PktAdmin::SET_REST_TIME: //= 44, // 해당 방의 쉬는 시간 설정
bResult = TRUE;
break;
}
case 3: // 어드민2
switch(lpPktAdmin->m_usCmd)
{
case PktAdmin::MOVE_ZONE_CHAR: //= 1, // 캐릭터 존 이동
case PktAdmin::MOVE_ZONE_PARTY: //= 2, // 파티 존 이동
case PktAdmin::MOVE_CHAR: //= 3, // 캐릭터 이동
case PktAdmin::MOVE_PARTY: //= 4, // 파티 이동
case PktAdmin::DELETE_SPELL: //= 47, // 부여된 해당 스펠을 파괴
case PktAdmin::STOP: //= 48, // 해당 캐릭터 묶어두기
case PktAdmin::STOP_OFF: //= 49, // 묶어둔 해당 캐릭터를 풀어주기
bResult = TRUE;
break;
}
case 2: // 어드민1
switch(lpPktAdmin->m_usCmd)
{
case PktAdmin::HIDE_CHAR: //= 21, // 캐릭터 투명
case PktAdmin::SHOW_CHAR: //= 22, // 캐릭터 투명 해제
case PktAdmin::INFO_CHAR: //= 12, // 캐릭터 정보
case PktAdmin::PEACE_MODE: //= 16, // 반전단체 가입
case PktAdmin::WAR_MODE: //= 17, // 반전단체 탈퇴
case PktAdmin::TRACE_CHAR: //= 20, // 캐릭터 추적
case PktAdmin::INVINCIBLE_CHAR: //= 23, // 캐릭터 무적
case PktAdmin::LOGOUT_CHAR: //= 25, // 캐릭터 강제 로그아웃
case PktAdmin::NORMAL_CHAR: //= 24, // 캐릭터 무적 해제
case PktAdmin::CHAT_BAN: //= 50, // 채팅 금지
case PktAdmin::CHAT_OK: //= 51, // 채금 해제
case PktAdmin::NEO: //= 52, // 네오
case PktAdmin::SMITH: //= 53, // 스미스모드
case PktAdmin::RELATION: //= 55, // 적아군 식별.
case PktAdmin::GM_FORM: //= 56, // PC 에서 GM 으로.
case PktAdmin::PC_FORM: //= 57, // GM 에서 PC 로.
bResult = TRUE;
break;
}
}
if(bResult == FALSE)
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %d 레벨 어드민 유저입니다.", lpAdmin->GetCID(), lpAdmin->GetAdminLevel());
return true;
}
/*
// 서포트 이면 리턴
if(lpAdmin->GetAdminLevel() <= 1)
{
ERRLOG1(g_Log, "CID:0x%08x 어드민 명령 오류 : 서포트 유저입니다.", lpAdmin->GetCID());
return true;
}
*/
// 해당 캐릭터가 현재 게임 서버에 없다면.. 중계 서버로 패킷을 보낸다.
CCharacter* lpCharacter = CCreatureManager::GetInstance().GetCharacter(lpPktAdmin->m_stName);
if (NULL == lpCharacter)
{
// edith 이패킷은 무시
switch(lpPktAdmin->m_usCmd)
{
case PktAdmin::INFO_CHAR:
case PktAdmin::DBAGENT_KILL:
return true;
}
ERRLOG2(g_Log, "Admin:0x%08x 현재 서버에 %s 캐릭터가 존재하지 않습니다.\n다른 게임 서버로 패킷을 전송합니다.",
lpAdmin->GetCID(), lpPktAdmin->m_stName);
GET_SINGLE_DISPATCH(lpDBAgentDispatch,
CDBAgentDispatch, CDBAgentDispatch::GetDispatchTable());
if (NULL == lpDBAgentDispatch)
{
ERRLOG0(g_Log, "에이전트 얻기 실패.");
}
else
{
DETLOG3(g_Log, "어드민 명령 요청 - 어드민:0x%08x 캐릭터:%s Cmd:%d",
lpAdmin->GetCID(), lpPktAdmin->m_stName, lpPktAdmin->GetCmd());
// Admin 캐릭터의 CID 를 기억해둔다.
lpPktAdmin->m_dwAdminCID = lpAdmin->GetCID();
// 중계 서버로 전송
GameClientSendPacket::SendCharAdminCmdToDBAgent(lpDBAgentDispatch->GetSendStream(), lpPktBase);
}
return true;
}
return ProcessAdminCmd(lpAdmin, lpCharacter, lpPktAdmin);
}
bool GameClientParsePacket::ProcessAdminCmd(CCharacter* lpAdmin, CCharacter* lpTarget, PktAdmin* lpPktAdmin)
{
// 클라이언트에서 온 패킷 / 중계 서버에서 온 패킷
unsigned long dwAdminCID = (NULL != lpAdmin) ? lpAdmin->GetCID() : lpPktAdmin->m_dwAdminCID;
POS& DestPos = lpPktAdmin->m_Position;
unsigned long dwAmount = lpPktAdmin->m_dwAmount;
char szCommand[PktAdminCommandLog::MAX_COMMAND_SIZE] = {0, };
switch (lpPktAdmin->m_usCmd)
{
case PktAdmin::NEO: //= 52, // 네오
{
lpAdmin->GetSpellMgr().GetAffectedInfo().ClearAll();
lpAdmin->GetSpellMgr().GetCastingInfo().ClearAll();
lpAdmin->GetEnchantInfo().ClearFlag();
lpAdmin->GetEnchantInfo().SetFlag(Skill::SpellID::Hide);
sprintf(szCommand, "/neo");
// 해당 메시지 들은 다시 클라이언트로 되돌려보낸다
CGameClientDispatch* lpDispatch = lpTarget->GetDispatcher();
if (NULL != lpDispatch)
{
GameClientSendPacket::SendCharAdmin(lpDispatch->GetSendStream(), lpPktAdmin, 0);
}
}
break;
case PktAdmin::SMITH: //= 53, // 스미스모드
{
sprintf(szCommand, "/smith");
// 해당 메시지 들은 다시 클라이언트로 되돌려보낸다
CGameClientDispatch* lpDispatch = lpTarget->GetDispatcher();
if (NULL != lpDispatch)
{
GameClientSendPacket::SendCharAdmin(lpDispatch->GetSendStream(), lpPktAdmin, 0);
}
}
break;
case PktAdmin::MOVE_ZONE_CHAR:
{
if (false == lpTarget->MoveZone(DestPos, lpPktAdmin->m_ZoneInfo.m_cZone, lpPktAdmin->m_ZoneInfo.m_cChannel))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %s를 존 이동시키는데 실패하였습니다.",
dwAdminCID, lpPktAdmin->m_stName);
return true;
}
sprintf(szCommand, "/move %s %d %f %f %f", lpTarget->GetCharacterName(), lpPktAdmin->m_ZoneInfo.m_cZone, DestPos.fPointX, DestPos.fPointY, DestPos.fPointZ);
break;
}
case PktAdmin::MOVE_ZONE_PARTY:
{
CParty* lpParty = lpTarget->GetParty();
if (NULL == lpParty)
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %s의 파티 얻기에 실패하였습니다.",
dwAdminCID, lpPktAdmin->m_stName);
return true;
}
lpParty->MoveZone(DestPos, lpPktAdmin->m_ZoneInfo.m_cZone, lpPktAdmin->m_ZoneInfo.m_cChannel);
sprintf(szCommand, "/moveparty %s %d %f %f %f", lpTarget->GetCharacterName(), lpPktAdmin->m_ZoneInfo.m_cZone, DestPos.fPointX, DestPos.fPointY, DestPos.fPointZ);
break;
}
case PktAdmin::MOVE_CHAR:
{
if (false == lpTarget->MovePos(DestPos, lpPktAdmin->m_ZoneInfo.m_cZone, false))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %s를 위치 이동시키는데 실패하였습니다.",
dwAdminCID, lpPktAdmin->m_stName);
return true;
}
sprintf(szCommand, "/moveit %s %f %f %f", lpTarget->GetCharacterName(), DestPos.fPointX, DestPos.fPointY, DestPos.fPointZ);
break;
}
case PktAdmin::MOVE_PARTY:
{
CParty* lpParty = lpTarget->GetParty();
if (NULL == lpParty)
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %s의 파티 얻기에 실패하였습니다.",
dwAdminCID, lpPktAdmin->m_stName);
return true;
}
lpParty->MovePos(DestPos, lpPktAdmin->m_ZoneInfo.m_cZone, false);
sprintf(szCommand, "/moveitparty %s %f %f %f", lpTarget->GetCharacterName(), DestPos.fPointX, DestPos.fPointY, DestPos.fPointZ);
break;
}
case PktAdmin::RESPAWN_CHAR:
{
if (false == lpTarget->Respawn())
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %s를 리스폰시키는데 실패하였습니다.",
dwAdminCID, lpPktAdmin->m_stName);
return true;
}
else
{
if (0 != lpTarget->GetPID())
{
// 파티원 리스폰을 알린다.
GameClientSendPacket::SendCharDeadToParty(lpTarget, 0, PktDeadInfo::RESPAWN);
}
sprintf(szCommand, "/respawn %s", lpTarget->GetCharacterName());
}
break;
}
case PktAdmin::RESPAWN_PARTY: break;
case PktAdmin::KILL_CHAR:
{
if (false == lpTarget->Kill(lpAdmin))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %s를 죽이는데 실패하였습니다.",
dwAdminCID, lpPktAdmin->m_stName);
return true;
}
sprintf(szCommand, "/kick %s", lpTarget->GetCharacterName());
break;
}
case PktAdmin::KILL_PARTY: break;
case PktAdmin::DUEL_INIT:
{
if (false == lpTarget->DuelInit(PktDuC::DUC_CANCEL))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %s의 듀얼 초기화에 실패하였습니다.",
dwAdminCID, lpPktAdmin->m_stName);
return true;
}
sprintf(szCommand, "/duelinit %s", lpTarget->GetCharacterName());
break;
}
case PktAdmin::CREATE_ITEM:
{
if (false == lpTarget->DropItem(lpPktAdmin->m_usProtoTypeID, static_cast<unsigned char>(dwAmount)))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %s 앞에 아이템을 생성하여 떨구는데 실패하였습니다.",
dwAdminCID, lpPktAdmin->m_stName);
return true;
}
sprintf(szCommand, "/dropitem %s %d %d", lpTarget->GetCharacterName(), lpPktAdmin->m_usProtoTypeID, dwAmount);
DETLOG3(g_Log, "CID:0x%08x 어드민이 아이템을 생성하였습니다. 아이템(ID:%d, 갯수:%d)",
lpTarget->GetCID(), lpPktAdmin->m_usProtoTypeID, dwAmount);
break;
}
case PktAdmin::CREATE_MON:
{
// 배틀 그라운드 서버군의 가상존에서는 몬스터를 만들어 낼수 없다!!
if (0 != lpAdmin->GetMapIndex())
{
/* VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(lpAdmin->GetMapIndex());
if (lpVirtualArea)
{
CVirtualMonsterMgr* lpVirtualMonsterMgr = lpVirtualArea->GetMonsterManager();
if (NULL == lpVirtualMonsterMgr ||
false == lpVirtualMonsterMgr->AdminSummonMonster(lpPktAdmin->m_usProtoTypeID, DestPos, lpAdmin->GetMapIndex()))
{
ERRLOG1(g_Log, "CID:0x%08x 어드민 명령 오류 : 몬스터를 생성하는데 실패하였습니다.", dwAdminCID);
return true;
}
}
*/
}
else
{
if (false == CCellManager::GetInstance().AdminSummonMonster(lpPktAdmin->m_usProtoTypeID, DestPos))
{
ERRLOG1(g_Log, "CID:0x%08x 어드민 명령 오류 : 몬스터를 생성하는데 실패하였습니다.", dwAdminCID);
return true;
}
}
sprintf(szCommand, "/createmob %d %f %f %f", lpPktAdmin->m_usProtoTypeID, DestPos.fPointX, DestPos.fPointY, DestPos.fPointZ);
DETLOG5(g_Log, "CID:0x%08x 어드민이 몬스터를 소환하였습니다. 몬스터(ID:%d, (%.1f, %.1f, %.1f))",
dwAdminCID, lpPktAdmin->m_usProtoTypeID, DestPos.fPointX, DestPos.fPointY, DestPos.fPointZ);
break;
}
// PC 에서 GM 으로.
case PktAdmin::GM_FORM:
{
CCharacter* lpCharacter = CCreatureManager::GetInstance().GetCharacter(dwAdminCID);
if(lpCharacter)
{
lpCharacter->SetGMModelFlag(1);
}
sprintf(szCommand, "/gmform");
break;
}
// GM 에서 PC 로.
case PktAdmin::PC_FORM:
{
CCharacter* lpCharacter = CCreatureManager::GetInstance().GetCharacter(dwAdminCID);
if(lpCharacter)
{
lpCharacter->SetGMModelFlag(0);
}
sprintf(szCommand, "/pcform");
break;
}
case PktAdmin::INFO_CHAR:
{
if (false == lpTarget->NotifyInfo(dwAdminCID))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %s의 정보 전달에 실패하였습니다.",
dwAdminCID, lpPktAdmin->m_stName);
return true;
}
sprintf(szCommand, "/hp %s", lpTarget->GetCharacterName());
break;
}
case PktAdmin::RELATION:
{
unsigned char cResult = 0;
unsigned long dwResult = lpAdmin->IsEnemy(lpTarget, &cResult);
char szMessage[PktChat::PktChatMaxSize] = "";
char szType[MAX_PATH] = { 0, };
int nLen = _snprintf(szMessage, PktChat::PktChatMaxSize,
"[Client] Type : %d, Relation : %d, Result : %d, [Server] Type : %d, Relation : %d, Result : %d",
lpPktAdmin->m_usProtoTypeID, lpPktAdmin->m_dwAmount, lpPktAdmin->m_ZoneInfo.m_cZone,
EnemyCheck::CCheckTable::GetInstance().GetEnemyCheckRule(), dwResult, cResult);
if (0 < nLen)
{
szMessage[PktChat::PktChatMaxSize - 1] = 0;
// 채팅 서버로 정보를 보낸다.
GET_SINGLE_DISPATCH(lpChatDispatch, CChatDispatch,
CChatDispatch::GetDispatchTable());
if (0 != lpChatDispatch)
{
const Position& pos = lpTarget->GetCurrentPos();
char strAdminCID[CHAR_INFOST::MAX_NAME_LEN] = "";
strcpy(strAdminCID, "0x");
char* strHexPos = (strAdminCID + 2);
Math::Convert::Hex32ToStr(strHexPos, dwAdminCID);
CChatRequestPacket chatReqPacket(szMessage,
PktChat::ENEMY_CHECK, 0, lpTarget->GetUID(), lpTarget->GetCID(), 0, 0, 0, strAdminCID, 1);
if (chatReqPacket.IsValid())
{
return lpChatDispatch->GetSendStream().PutBuffer(
chatReqPacket.GetCompressedPacket(),
chatReqPacket.GetCompressedSize(), CmdCharChat);
}
}
}
sprintf(szCommand, "/relation %s", lpTarget->GetCharacterName());
break;
}
case PktAdmin::GET_EXP:
{
lpTarget->IncrementExp(dwAmount);
sprintf(szCommand, "/giveexp %s %d", lpTarget->GetCharacterName(), dwAmount);
break;
}
case PktAdmin::GET_GOLD:
{
unsigned long dwSrcGold = lpTarget->GetGold();
lpTarget->AddGold(dwAmount, true);
GAMELOG::LogTakeGold(*lpTarget, dwSrcGold, lpTarget->GetGold(), dwAmount,
TakeType::TS_INVEN, TakeType::TS_INVEN, GAMELOG::sTakeGoldLogV2::ADMIN_GIVEGOLD, 0);
sprintf(szCommand, "/givegold %s %d", lpTarget->GetCharacterName(), dwAmount);
break;
}
case PktAdmin::LEVEL_UP:
{
if (dwAmount < 1 || dwAmount > EXP::GetUsingMaxLevel())
{
break;
}
while (static_cast<unsigned long>(lpTarget->GetStatus().m_nLevel) < dwAmount)
{
if (false == lpTarget->IncrementExp(
static_cast<unsigned long>(EXP::ExpTable[lpTarget->GetStatus().m_nLevel - 1])))
{
break;
}
}
sprintf(szCommand, "/levelup %s %d", lpTarget->GetCharacterName(), dwAmount);
break;
}
// DELETE_ME : 더이상 클라이언트가 반전 모드로의 변경은 불가능하다. 개념만 남아있을 뿐. (2005-05-31 by 로딘)
/*
case PktAdmin::PEACE_MODE:
{
PeaceModeInfo peaceModeInfo = lpTarget->GetPeaceMode();
peaceModeInfo.m_bPeace = true;
lpTarget->SetPeaceMode(peaceModeInfo, false);
CGameClientDispatch* lpDispatch = lpTarget->GetDispatcher();
if (NULL != lpDispatch)
{
GameClientSendPacket::SendCharPeaceMode(lpDispatch->GetSendStream(),
lpTarget->GetCID(), 0, true, 0);
}
break;
}
case PktAdmin::WAR_MODE:
{
PeaceModeInfo peaceModeInfo = lpTarget->GetPeaceMode();
peaceModeInfo.m_bPeace = false;
lpTarget->SetPeaceMode(peaceModeInfo, false);
CGameClientDispatch* lpDispatch = lpTarget->GetDispatcher();
if (NULL != lpDispatch)
{
GameClientSendPacket::SendCharPeaceMode(lpDispatch->GetSendStream(),
lpTarget->GetCID(), 0, false, 0);
}
break;
}
*/
case PktAdmin::GET_FAME:
{
lpTarget->SetFame(dwAmount);
CGameClientDispatch* lpDispatch = lpTarget->GetDispatcher();
if (NULL != lpDispatch)
{
GameClientSendPacket::SendCharFameInfo(lpDispatch->GetSendStream(), lpTarget,
"", "", 0, 0, PktFIAck::FAME_INFO, PktBase::NO_SERVER_ERR);
}
sprintf(szCommand, "/setfame %s %d", lpTarget->GetCharacterName(), dwAmount);
break;
}
case PktAdmin::GET_MILEAGE:
{
lpTarget->SetMileage(dwAmount);
CGameClientDispatch* lpDispatch = lpTarget->GetDispatcher();
if (NULL != lpDispatch)
{
GameClientSendPacket::SendCharFameInfo(lpDispatch->GetSendStream(), lpTarget,
"", "", 0, 0, PktFIAck::FAME_INFO, PktBase::NO_SERVER_ERR);
}
sprintf(szCommand, "/setmileage %s %d", lpTarget->GetCharacterName(), dwAmount);
break;
}
case PktAdmin::TRACE_CHAR:
{
// 목표와 같은 존에 있는 경우
if (NULL != lpAdmin)
{
Position DestPostion = lpTarget->GetCurrentPos();
// 약간 옆으로 이동시켜준다.
DestPostion.m_fPointX += 5;
sprintf(szCommand, "/trace %s", lpTarget->GetCharacterName());
if (false == lpAdmin->MovePos(DestPostion, lpPktAdmin->m_ZoneInfo.m_cZone, false))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %s의 위치로 이동하는데 실패하였습니다.",
dwAdminCID, lpPktAdmin->m_stName);
return true;
}
}
// 목표와 다른 존에 있는 경우
else
{
// Admin 캐릭터를 목표 캐릭터가 있는 존과 위치로 이동 시킨다.
CCharacter* lpAdmin = CCreatureManager::GetInstance().GetCharacter(dwAdminCID);
if (NULL == lpAdmin)
{
ERRLOG1(g_Log, "어드민 명령 오류 : %s 캐릭터를 추적하는데 실패하였습니다. 어드민 캐릭터가 NULL 입니다.",
lpPktAdmin->m_stName);
return true;
}
sprintf(szCommand, "/trace %s", lpAdmin->GetCharacterName());
if (0 == DestPos.fPointX && 0 == DestPos.fPointY && 0 == DestPos.fPointZ)
{
CGameClientDispatch* lpDispatch = lpAdmin->GetDispatcher();
if (NULL != lpDispatch)
{
GameClientSendPacket::SendCharAdmin(lpDispatch->GetSendStream(), lpPktAdmin, PktAdmin::E_LOGOUT_CHAR);
}
return true;
}
else
{
// 약간 옆으로 이동시켜준다.
DestPos.fPointX += 5;
if (false == lpAdmin->MoveZone(DestPos, lpPktAdmin->m_ZoneInfo.m_cZone, lpPktAdmin->m_ZoneInfo.m_cChannel))
{
ERRLOG1(g_Log, "어드민 명령 오류 : %s 캐릭터를 추적하는데 실패하였습니다.", lpPktAdmin->m_stName);
return true;
}
}
}
break;
}
case PktAdmin::REQUEST_TRACE_POS:
{
if (NULL != lpPktAdmin)
{
lpPktAdmin->m_Position.fPointX = lpTarget->GetCurrentPos().m_fPointX;
lpPktAdmin->m_Position.fPointY = lpTarget->GetCurrentPos().m_fPointY;
lpPktAdmin->m_Position.fPointZ = lpTarget->GetCurrentPos().m_fPointZ;
GET_SINGLE_DISPATCH(lpDBAgentDispatch, CDBAgentDispatch, CDBAgentDispatch::GetDispatchTable());
if (NULL != lpDBAgentDispatch)
{
GameClientSendPacket::SendCharAdminCmdToDBAgent(lpDBAgentDispatch->GetSendStream(), lpPktAdmin);
}
}
break;
}
case PktAdmin::HIDE_CHAR:
{
lpAdmin->GetSpellMgr().GetAffectedInfo().ClearAll();
lpAdmin->GetSpellMgr().GetCastingInfo().ClearAll();
lpAdmin->GetEnchantInfo().ClearFlag();
lpAdmin->GetEnchantInfo().SetFlag(Skill::SpellID::Hide);
sprintf(szCommand, "/hide");
break;
}
case PktAdmin::SHOW_CHAR:
{
lpAdmin->GetEnchantInfo().ResetFlag(Skill::SpellID::Hide);
sprintf(szCommand, "/show");
break;
}
case PktAdmin::INVINCIBLE_CHAR:
{
Skill::CAddSpell<CInvincibleSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpAdmin,
Skill::SpellType::MAGICAL_SPELL, Skill::SpellID::Invincible, 1, CSpell::INFINITE_DURATION))(lpAdmin);
sprintf(szCommand, "/god");
break;
}
case PktAdmin::NORMAL_CHAR:
{
lpAdmin->GetSpellMgr().GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::Invincible);
sprintf(szCommand, "/human");
break;
}
case PktAdmin::LOGOUT_CHAR:
{
CGameClientDispatch* lpDispatch = lpTarget->GetDispatcher();
if (NULL != lpDispatch)
{
DETLOG2(g_Log, "CID:0x%08x 어드민이 강제 로그아웃 시켰습니다. 어드민CID:0x%08x",
lpTarget->GetCID(), dwAdminCID);
lpDispatch->Disconnect();
lpDispatch->Disconnected();
}
sprintf(szCommand, "/logout %s", lpTarget->GetCharacterName());
break;
}
case PktAdmin::APOCALYPSE:
{
CCell* lpCell = lpAdmin->GetCellPos().m_lpCell;
if (NULL == lpCell)
{
ERRLOG1(g_Log, "CID:0x%08x 어드민 명령 오류 : 어드민 캐릭터가 있는 셀이 이상합니다.", dwAdminCID);
break;
}
lpCell->KillAll(lpAdmin);
sprintf(szCommand, "/apo");
break;
}
case PktAdmin::CREATE_EQUIP:
{
CCell* lpCell = lpTarget->GetCellPos().m_lpCell;
if (NULL == lpCell)
{
ERRLOG1(g_Log, "CID:0x%08x 어드민 명령 오류 : 캐릭터가 있는 셀이 이상합니다.", lpTarget->GetCID());
break;
}
lpPktAdmin->m_usProtoTypeID = std::max(lpPktAdmin->m_usProtoTypeID, static_cast<unsigned short>(Item::EquipType::AAA_GRADE));
lpPktAdmin->m_usProtoTypeID = std::min(lpPktAdmin->m_usProtoTypeID, static_cast<unsigned short>(Item::EquipType::F_GRADE));
Item::EquipType::Grade eGrade = static_cast<Item::EquipType::Grade>(lpPktAdmin->m_usProtoTypeID);
unsigned char cMonsterLevel =
std::min(static_cast<unsigned char>(Creature::MONSTER_MAX_LEVEL), static_cast<unsigned char>(lpPktAdmin->m_dwAmount));
unsigned short wItemKind = AwardTable::CAward::GetInstance().GetAwardEquipment(
Item::EquipType::STANDARD_OPTION, cMonsterLevel, lpTarget, true);
Item::CItem* lpItem = Item::CItemFactory::GetInstance().CreateItem(wItemKind);
if (NULL != lpItem)
{
Item::CEquipment* lpEquip = Item::CEquipment::DowncastToEquipment(lpItem);
if (NULL != lpEquip)
{
// 매직찬스 50프로 확율 테스트.
if(lpEquip->AddRandomOption(eGrade, (unsigned char)lpPktAdmin->m_dwAmount2, 50))
lpEquip->SetNewEquip(2);
else
lpEquip->SetNewEquip();
}
lpTarget->GiveItem(lpItem);
// GievItem 으로 스택된 경우
if (lpItem->IsSet(Item::DetailData::STACKABLE) && 0 == lpItem->GetNumOrDurability())
{
DELETE_ITEM(lpItem);
}
}
sprintf(szCommand, "/createitem %s %d %d", lpTarget->GetCharacterName(), lpPktAdmin->m_dwAmount, lpPktAdmin->m_usProtoTypeID);
break;
}
case PktAdmin::ELITE_BONUS:
{
CCreatureManager& CreatureManager = CCreatureManager::GetInstance();
EliteBonus::EliteBonusData eliteBonus(lpPktAdmin->m_EliteBonusInfo.m_cNation, lpPktAdmin->m_EliteBonusInfo.m_cLevel);
if ((eliteBonus.m_cNation == CClass::HUMAN || eliteBonus.m_cNation == CClass::AKHAN) &&
(eliteBonus.m_cLevel >= 0 && eliteBonus.m_cLevel <= EliteBonus::MAX_BONUS_LEVEL))
{
CreatureManager.SetAutoBalance(false);
CreatureManager.SetEliteBonus(eliteBonus);
}
else
{
CreatureManager.SetAutoBalance(true);
}
sprintf(szCommand, "/elitebonus %d %d", lpPktAdmin->m_EliteBonusInfo.m_cNation, lpPktAdmin->m_EliteBonusInfo.m_cLevel);
break;
}
case PktAdmin::STATUE_INIT:
{
if (SERVER_ID::ZONE3 == CServerSetup::GetInstance().GetServerZone())
{
CCreatureManager::GetInstance().ProcessAllMonster(
std::bind2nd(std::mem_fun1(&CMonster::Dead), reinterpret_cast<CAggresiveCreature *>(NULL)));
}
sprintf(szCommand, "/resstatue");
break;
}
case PktAdmin::RESPAWN_ALL:
{
CCreatureManager::GetInstance().ProcessAllCharacter(Respawn());
sprintf(szCommand, "/resmen");
break;
}
case PktAdmin::CHANGE_CLASS:
{
if (lpTarget->GetStatus().m_nLevel < 10)
{
ERRLOG1(g_Log, "CID:0x%08x 어드민 명령 오류 : 레벨이 20보다 작습니다.", dwAdminCID);
break;
}
unsigned char cClassType = static_cast<unsigned char>(lpPktAdmin->m_usProtoTypeID);
if (lpTarget->GetClass() == cClassType)
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : 같은 클래스(%d)로 전직할려고 합니다.",
dwAdminCID, cClassType);
break;
}
if (lpTarget->GetRace() != CClass::GetRace(cClassType))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : 체인지 할려는 클래스(%d)와 종족이 다릅니다.",
dwAdminCID, cClassType);
break;
}
// 기본 클래스에서 해당 상위 클래스로 전직하는 경우
if (CClass::GetJobLevel(static_cast<unsigned char>(lpTarget->GetClass())) == CClass::DEFAULT_CLASS &&
CClass::GetPreviousJob(cClassType) == lpTarget->GetClass())
{
if (false == lpTarget->ChangeClass(cClassType))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %d 로 클래스 체인지를 실패하였습니다.",
dwAdminCID, lpPktAdmin->m_usProtoTypeID);
}
}
// 같은 종족의 다른 클래스로 전직하는 경우
else
{
unsigned char cPrevClassType = CClass::GetPreviousJob(cClassType);
int nCurrentLevel = lpTarget->GetStatus().m_nLevel;
// 1 Step
// 레벨 1의 초기 캐릭터로 만들면서, 모든 스킬을 지운다.
if (false == lpTarget->InitLevel1Char(cPrevClassType))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : CID:0x%08x 캐릭터를 1레벨로 만드는데 실패하였습니다.",
dwAdminCID, lpTarget->GetCID());
break;
}
// 2 Step
// 해당 레벨까지 level up
while (lpTarget->GetStatus().m_nLevel < nCurrentLevel)
{
if (false == lpTarget->IncrementExp(
static_cast<unsigned long>(EXP::ExpTable[lpTarget->GetStatus().m_nLevel - 1])))
{
break;
}
}
// 3 Step
// 해당 클래스로 전직
if (lpTarget->GetStatus().m_nLevel >= 10 && cClassType != cPrevClassType)
{
if (false == lpTarget->ChangeClass(cClassType))
{
ERRLOG4(g_Log, "CID:0x%08x 어드민 명령 오류 : CID:0x%08x 캐릭터 클래스 체인지 실패. 현재 캐릭터의 클래스는 %d, 바꾸고자 하는 클래스는 %d입니다.",
dwAdminCID, lpTarget->GetCID(), lpTarget->GetClass(), cClassType);
break;
}
}
}
sprintf(szCommand, "/class %s %d", lpTarget->GetCharacterName(), cClassType);
break;
}
case PktAdmin::LEARN_SKILL:
{
unsigned short nSkillID = lpPktAdmin->m_usProtoTypeID;
unsigned char cLockCount = static_cast<unsigned char>(lpPktAdmin->m_Position.fPointX) - 1; // 1부터 시작으로 입력 받음
unsigned char cSkillLevel = static_cast<unsigned char>(lpPktAdmin->m_Position.fPointY); // 0부터 시작으로 입력 받음
// 이미 배워둔 스킬인지 체크
if (cLockCount < lpTarget->GetSkillLockCount(nSkillID) ||
(cLockCount == lpTarget->GetSkillLockCount(nSkillID) && cSkillLevel <= lpTarget->GetSkillLevel(nSkillID)))
{
ERRLOG4(g_Log, "CID:0x%08x 어드민 명령 오류 : SkillID:0x%08x LockCount:%d SkillLevel:%d 스킬을 배우는데 실패하였습니다.",
dwAdminCID, nSkillID, cLockCount, cSkillLevel);
break;
}
// 스킬 배우기
int count = cLockCount * CSkillMgr::MAX_SKILL_LEVEL + cSkillLevel + 1;
cLockCount = lpTarget->GetSkillLockCount(nSkillID) == -1 ? 0 : lpTarget->GetSkillLockCount(nSkillID);
cSkillLevel = lpTarget->GetSkillLevel(nSkillID) == -1 ? 0 : lpTarget->GetSkillLevel(nSkillID);
count -= cLockCount * CSkillMgr::MAX_SKILL_LEVEL + cSkillLevel + 1;
using namespace Item;
ItemInfo tempItemInfo(nSkillID);
tempItemInfo.m_UseItemInfo.m_usSkill_ID = nSkillID;
tempItemInfo.m_UseItemInfo.m_usSkill_LockCount = cLockCount;
tempItemInfo.m_DetailData.m_dwFlags |= DetailData::USE_ITEM;
// ItemSerial 이 0 인 임시 아이템을 생성한다.
CUseItem* lpUseItem = CUseItem::DowncastToUseItem(
CItemFactory::GetInstance().CreateTempItem(tempItemInfo));
for (int i=0; i<count; ++i)
{
if (!lpTarget->SkillCreate(lpUseItem))
{
ERRLOG4(g_Log, "CID:0x%08x 어드민 명령 오류 : SkillID:0x%08x LockCount:%d SkillLevel:%d 스킬을 배우는데 실패하였습니다.",
dwAdminCID, nSkillID, cLockCount, cSkillLevel);
}
++cSkillLevel;
if (cLockCount != CSkillMgr::MAX_SKILL_LOCKCOUNT-1 && cSkillLevel == CSkillMgr::MAX_SKILL_LEVEL)
{
cSkillLevel = 0;
++cLockCount;
DELETE_ITEM(lpUseItem);
tempItemInfo.m_usProtoTypeID = nSkillID;
tempItemInfo.m_UseItemInfo.m_usSkill_ID = nSkillID;
tempItemInfo.m_UseItemInfo.m_usSkill_LockCount = cLockCount;
lpUseItem = CUseItem::DowncastToUseItem(
CItemFactory::GetInstance().CreateTempItem(tempItemInfo));
}
}
sprintf(szCommand, "/learnskill 0x%08x %d %d", nSkillID, cLockCount+1, cSkillLevel);
DELETE_ITEM(lpUseItem);
break;
}
case PktAdmin::ERASE_SKILL:
{
unsigned short nSkillID = lpPktAdmin->m_usProtoTypeID;
unsigned char cLockCount = static_cast<unsigned char>(lpPktAdmin->m_Position.fPointX) - 1; // 1부터 시작으로 입력 받음
unsigned char cSkillLevel = static_cast<unsigned char>(lpPktAdmin->m_Position.fPointY); // 0부터 시작으로 입력 받음
if (cLockCount > lpTarget->GetSkillLockCount(nSkillID) ||
(cLockCount == lpTarget->GetSkillLockCount(nSkillID) && cSkillLevel >= lpTarget->GetSkillLevel(nSkillID)))
{
ERRLOG4(g_Log, "CID:0x%08x 어드민 명령 오류 : SkillID:0x%08x LockCount:%d SkillLevel:%d 스킬을 지우는데 실패하였습니다.",
dwAdminCID, nSkillID, cLockCount, cSkillLevel);
break;
}
unsigned char cIndex = static_cast<unsigned char>(lpTarget->GetSkillSlotIndex(nSkillID));
int count = lpTarget->GetSkillLockCount(nSkillID) * CSkillMgr::MAX_SKILL_LEVEL + lpTarget->GetSkillLevel(nSkillID) + 1;
count -= cLockCount * CSkillMgr::MAX_SKILL_LEVEL + cSkillLevel + 1;
for (int i=0; i<count; ++i)
{
Item::ItemPos itemPos(TakeType::TS_ADMIN, 0);
if (false == lpTarget->SkillErase(cIndex, itemPos))
{
ERRLOG4(g_Log, "CID:0x%08x 어드민 명령 오류 : SkillID:0x%08x LockCount:%d SkillLevel:%d 스킬을 지우는데 실패하였습니다.",
dwAdminCID, nSkillID, cLockCount, cSkillLevel);
}
--cSkillLevel;
if (cSkillLevel < 0)
{
cSkillLevel = 0;
--cLockCount;
}
}
sprintf(szCommand, "/eraseskill 0x%08x %d %d", nSkillID, cLockCount+1, cSkillLevel);
break;
}
case PktAdmin::LEARN_ABILITY:
{
unsigned short wAbilityID = lpPktAdmin->m_usProtoTypeID;
unsigned short wAbilityLV = static_cast<unsigned char>(lpPktAdmin->m_Position.fPointX) - 1;
// 이미 배워둔 어빌리티인지 체크
if ( wAbilityLV <= lpTarget->GetSkillLockCount(wAbilityID) )
{
ERRLOG3(g_Log, "CID:0x%08x 어드민 명령 오류 : AbilityID:0x%08x wAbilityLV:%d 어빌리티를 배우는데 실패하였습니다.",
dwAdminCID, wAbilityID, wAbilityLV);
break;
}
using namespace Item;
ItemInfo tempItemInfo(wAbilityID);
tempItemInfo.m_UseItemInfo.m_usSkill_ID = wAbilityID;
tempItemInfo.m_UseItemInfo.m_usSkill_LockCount = wAbilityLV;
tempItemInfo.m_DetailData.m_dwFlags |= DetailData::USE_ITEM;
// ItemSerial 이 0 인 임시 아이템을 생성한다.
CUseItem* lpUseItem = CUseItem::DowncastToUseItem(
CItemFactory::GetInstance().CreateTempItem(tempItemInfo));
if (!lpTarget->AbilityCreate(lpUseItem))
{
ERRLOG3(g_Log, "CID:0x%08x 어드민 명령 오류 : AbilityID:0x%08x wAbilityLV:%d 어빌리티를 배우는데 실패하였습니다.",
dwAdminCID, wAbilityID, wAbilityLV);
}
sprintf(szCommand, "/learnability 0x%08x %d", wAbilityID, wAbilityLV+1);
DELETE_ITEM(lpUseItem);
break;
}
case PktAdmin::ERASE_ABILITY:
{
unsigned short wAbilityID = lpPktAdmin->m_usProtoTypeID;
unsigned short wAbilityLV = static_cast<unsigned char>(lpPktAdmin->m_Position.fPointX) - 1;
// 이미 배워둔 어빌리티인지 체크
if ( wAbilityLV > lpTarget->GetSkillLockCount(wAbilityID) )
{
ERRLOG3(g_Log, "CID:0x%08x 어드민 명령 오류 : AbilityID:0x%08x wAbilityLV:%d 어빌리티를 지우는데 실패하였습니다.",
dwAdminCID, wAbilityID, wAbilityLV);
break;
}
unsigned char cIndex = static_cast<unsigned char>(lpTarget->GetSkillSlotIndex(wAbilityID));
int count = lpTarget->GetSkillLockCount(wAbilityID)-wAbilityLV;
for (int i=0; i<count; ++i)
{
Item::ItemPos itemPos(TakeType::TS_ADMIN, 0);
if (false == lpTarget->AbilityErase(cIndex, itemPos))
{
ERRLOG3(g_Log, "CID:0x%08x 어드민 명령 오류 : SkillID:0x%08x LockCount:%d 어빌리티를 지우는데 실패하였습니다.",
dwAdminCID, wAbilityID, wAbilityLV);
}
--wAbilityLV;
}
sprintf(szCommand, "/eraseability 0x%08x %d", wAbilityID, wAbilityLV+1);
break;
}
case PktAdmin::LEVEL_DOWN:
{
if (dwAmount < 1 || dwAmount > EXP::GetUsingMaxLevel())
{
break;
}
unsigned char cClassType = static_cast<unsigned char>(lpTarget->GetClass());
unsigned char cPrevClassType = cClassType;
if (CClass::GetJobLevel(cClassType) == CClass::JOB_CHANGE_1ST)
{
cPrevClassType = CClass::GetPreviousJob(cClassType);
}
/*
// edith 100 렙 이팩트
// 100레벨 컨텐츠를 사용할경우 만랩 인챈트를 제거한다.
if (true == CServerSetup::GetInstance().UseContents(GameRYL::LEVEL_LIMIT_100))
{
lpTarget->GetSpellMgr().GetAffectedInfo().RemoveChantBySpellType(Skill::SpellID::HundredLevel);
lpTarget->GetSpellMgr().GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::HundredLevel);
}
*/
// 1 Step
// 레벨 1의 초기 캐릭터로 만들면서, 모든 스킬을 지운다.
if (false == lpTarget->InitLevel1Char(cPrevClassType))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : CID:0x%08x 캐릭터를 1레벨로 만드는데 실패하였습니다.",
dwAdminCID, lpTarget->GetCID());
break;
}
// 2 Step
// 해당 레벨까지 level up
while (static_cast<unsigned long>(lpTarget->GetStatus().m_nLevel) < dwAmount)
{
if (false == lpTarget->IncrementExp(
static_cast<unsigned long>(EXP::ExpTable[lpTarget->GetStatus().m_nLevel - 1])))
{
break;
}
}
// 3 Step
// 해당 클래스로 전직
if (lpTarget->GetStatus().m_nLevel >= 10 && cClassType != cPrevClassType)
{
if (false == lpTarget->ChangeClass(cClassType))
{
ERRLOG4(g_Log, "CID:0x%08x 어드민 명령 오류 : CID:0x%08x 캐릭터 클래스 체인지 실패. "
"현재 캐릭터의 클래스는 %d, 바꾸고자 하는 클래스는 %d입니다.",
dwAdminCID, lpTarget->GetCID(), lpTarget->GetClass(), cClassType);
break;
}
}
sprintf(szCommand, "/leveldown %s %d", lpTarget->GetCharacterName(), dwAmount);
break;
}
// 퀘스트 관련 어드민 명령
case PktAdmin::GET_QUEST: // 퀘스트 받기
{
// 캐릭터 이름, 퀘스트 ID
unsigned short wQuestID = lpPktAdmin->m_usProtoTypeID;
Quest::QuestNode* lpQuest = CQuestMgr::GetInstance().GetQuestNode(wQuestID);
if (NULL == lpQuest)
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : QuestID:0x%x 퀘스트가 존재하지 않습니다.",
lpTarget->GetCID(), wQuestID);
break;
}
if (true == lpTarget->HasQuest(wQuestID))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : QuestID:0x%x 를 이미 가지고 있습니다.", lpTarget->GetCID(), wQuestID);
break;
}
if (false == lpTarget->GiveQuest(lpQuest))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : QuestID:0x%x 퀘스트를 주는데 실패했습니다.",
lpTarget->GetCID(), wQuestID);
break;
}
CGameClientDispatch* lpGameClientDispatch = lpTarget->GetDispatcher();
if (NULL != lpGameClientDispatch)
{
GameClientSendPacket::SendCharStartQuest(lpGameClientDispatch->GetSendStream(), lpTarget->GetCID(),
0, wQuestID, PktBase::NO_SERVER_ERR);
}
if (false == lpTarget->StartPhase(wQuestID, 1))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : QuestID:0x%x 퀘스트의 첫번째 단계를 실행하는데 실패했습니다.",
lpTarget->GetCID(), wQuestID);
// 해당 퀘스트 제거
lpTarget->CancelQuest(wQuestID);
GameClientSendPacket::SendCharCancelQuest(lpGameClientDispatch->GetSendStream(),
lpTarget->GetCID(), wQuestID, PktAdmin::NO_SERVER_ERR);
break;
}
sprintf(szCommand, "/getquest %s 0x%08x", lpTarget->GetCharacterName(), wQuestID);
break;
}
case PktAdmin::ADD_QUEST: // 완료 퀘스트에 추가
{
unsigned short wQuestID = lpPktAdmin->m_usProtoTypeID;
Quest::QuestNode* lpQuest = CQuestMgr::GetInstance().GetQuestNode(wQuestID);
if (NULL == lpQuest)
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : QuestID:0x%x 퀘스트가 존재하지 않습니다.",
lpTarget->GetCID(), wQuestID);
break;
}
CGameClientDispatch* lpGameClientDispatch = lpTarget->GetDispatcher();
if (NULL == lpGameClientDispatch)
{
ERRLOG1(g_Log, "CID:0x%08x 어드민 명령 오류 : GameClientDispatch 가 NULL 입니다.",
lpTarget->GetCID());
break;
}
// 이미 완료 퀘스트에 존재하는지 체크한다.
if (true == lpTarget->HasHistoryQuest(wQuestID))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : QuestID:0x%x 퀘스트를 이미 완료하였습니다.",
lpTarget->GetCID(), wQuestID);
break;
}
// 현재 수행중인 퀘스트에 존재하는지 체크한다.
if (true == lpTarget->HasExecutingQuest(wQuestID))
{
// 수행중이던 퀘스트를 없앤다.
lpTarget->CancelQuest(wQuestID);
GameClientSendPacket::SendCharCancelQuest(lpGameClientDispatch->GetSendStream(),
lpTarget->GetCID(), wQuestID, PktAdmin::NO_SERVER_ERR);
}
if (false == lpTarget->InsertHistoryQuest(wQuestID))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : QuestID:0x%x 퀘스트를 완료된 퀘스트로 넣는데 실패했습니다.",
lpTarget->GetCID(), wQuestID);
break;
}
// 퀘스트 정보를 보낸다.
GameClientSendPacket::SendCharQuestInfo(lpGameClientDispatch->GetSendStream(), lpTarget);
sprintf(szCommand, "/addquest %s 0x%08x", lpTarget->GetCharacterName(), wQuestID);
break;
}
case PktAdmin::DELETE_QUEST: // 퀘스트 삭제
{
unsigned short wQuestID = lpPktAdmin->m_usProtoTypeID;
Quest::QuestNode* lpQuest = CQuestMgr::GetInstance().GetQuestNode(wQuestID);
if (NULL == lpQuest)
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : QuestID:0x%x 퀘스트가 존재하지 않습니다.", lpTarget->GetCID(), wQuestID);
break;
}
CGameClientDispatch* lpGameClientDispatch = lpTarget->GetDispatcher();
if (NULL == lpGameClientDispatch)
{
ERRLOG1(g_Log, "CID:0x%08x 어드민 명령 오류 : GameClientDispatch 가 NULL 입니다.", lpTarget->GetCID());
break;
}
if (false == lpTarget->HasQuest(wQuestID))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : QuestID:0x%x 퀘스트를 가지고 있지 않습니다.", lpTarget->GetCID(), wQuestID);
break;
}
if (true == lpTarget->HasExecutingQuest(wQuestID))
{
lpTarget->CancelQuest(wQuestID);
GameClientSendPacket::SendCharCancelQuest(lpGameClientDispatch->GetSendStream(),
lpTarget->GetCID(), wQuestID, PktAdmin::NO_SERVER_ERR);
break;
}
if (true == lpTarget->HasHistoryQuest(wQuestID))
{
if (true == lpTarget->DeleteHistoryQuest(wQuestID))
{
// 퀘스트에 의해 받는 영향을 계산
lpTarget->CalculateStatusData(false);
if (true == lpTarget->CalculateMaxSkillSlot())
{
GameClientSendPacket::SendCharStateRedistribution(lpGameClientDispatch->GetSendStream(),
lpTarget->GetCID(), lpTarget->GetState(), lpTarget->GetSkill(), PktBase::NO_SERVER_ERR);
}
}
}
GameClientSendPacket::SendCharQuestInfo(lpGameClientDispatch->GetSendStream(), lpTarget);
sprintf(szCommand, "/deletequest %s 0x%08x", lpTarget->GetCharacterName(), wQuestID);
break;
}
// BATTLEGROUND_SERVER 운영자 명령
case PktAdmin::FINISH_GAME: // 해당 방의 경기 종료 (승패 결정)
{
unsigned short wMapNumber = lpPktAdmin->m_usProtoTypeID;
unsigned short wMapIndex = static_cast<unsigned short>(VirtualArea::BGSERVERMAP | wMapNumber);
VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(wMapIndex);
if (NULL != lpVirtualArea)
{
VirtualArea::CBGServerMap* lpBGServerMap = reinterpret_cast<VirtualArea::CBGServerMap*>(lpVirtualArea);
VirtualArea::MapInfo& mapInfo = lpBGServerMap->GetMapInfo();
VirtualArea::ResultInfo& resultInfo = lpBGServerMap->GetResultInfo();
resultInfo.m_cWinRace = lpBGServerMap->RuleCheck(true);
std::copy(&mapInfo.m_wScore[0], &mapInfo.m_wScore[CClass::MAX_RACE], &resultInfo.m_wScore[0]);
lpBGServerMap->SendResultInfo();
sprintf(szCommand, "/finish %d", wMapNumber);
}
break;
}
case PktAdmin::DRAW_GAME: // 해당 방의 경기 종료 (무승부)
{
unsigned short wMapNumber = lpPktAdmin->m_usProtoTypeID;
unsigned short wMapIndex = static_cast<unsigned short>(VirtualArea::BGSERVERMAP | wMapNumber);
VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(wMapIndex);
if (NULL != lpVirtualArea)
{
VirtualArea::CBGServerMap* lpBGServerMap = reinterpret_cast<VirtualArea::CBGServerMap*>(lpVirtualArea);
VirtualArea::MapInfo& mapInfo = lpBGServerMap->GetMapInfo();
VirtualArea::ResultInfo& resultInfo = lpBGServerMap->GetResultInfo();
resultInfo.m_cWinRace = lpBGServerMap->RuleCheck(true);
resultInfo.m_cWinRace = CClass::MAX_RACE;
std::copy(&mapInfo.m_wScore[0], &mapInfo.m_wScore[CClass::MAX_RACE], &resultInfo.m_wScore[0]);
lpBGServerMap->SendResultInfo();
sprintf(szCommand, "/draw %d", wMapNumber);
}
break;
}
case PktAdmin::IGNORE_GAME: // 해당 방의 경기 종료 (승패 무시)
{
unsigned short wMapNumber = lpPktAdmin->m_usProtoTypeID;
unsigned short wMapIndex = static_cast<unsigned short>(VirtualArea::BGSERVERMAP | wMapNumber);
VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(wMapIndex);
if (NULL != lpVirtualArea)
{
VirtualArea::CBGServerMap* lpBGServerMap = reinterpret_cast<VirtualArea::CBGServerMap*>(lpVirtualArea);
lpBGServerMap->RuleCheck(true);
sprintf(szCommand, "/ignore %d", wMapNumber);
}
break;
}
case PktAdmin::SET_MAX: // 해당 방의 최대 인원수 설정
{
unsigned short wMapNumber = lpPktAdmin->m_usProtoTypeID;
unsigned short wMapIndex = static_cast<unsigned short>(VirtualArea::BGSERVERMAP | wMapNumber);
unsigned char cMaxCharNum = static_cast<unsigned char>(dwAmount);
VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(wMapIndex);
if (NULL != lpVirtualArea)
{
VirtualArea::CBGServerMap* lpBGServerMap = reinterpret_cast<VirtualArea::CBGServerMap*>(lpVirtualArea);
lpBGServerMap->GetMapInfo().m_cMaxCharNumOfNation = cMaxCharNum;
lpBGServerMap->SendMapInfo();
sprintf(szCommand, "/max %d %d", wMapNumber, cMaxCharNum);
}
break;
}
case PktAdmin::SET_SCORE: // 해당 방의 목표 점수 설정
{
unsigned short wMapNumber = lpPktAdmin->m_usProtoTypeID;
unsigned short wMapIndex = static_cast<unsigned short>(VirtualArea::BGSERVERMAP | wMapNumber);
unsigned short wTargetScore = static_cast<unsigned short>(dwAmount);
VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(wMapIndex);
if (NULL != lpVirtualArea)
{
VirtualArea::CBGServerMap* lpBGServerMap = reinterpret_cast<VirtualArea::CBGServerMap*>(lpVirtualArea);
lpBGServerMap->GetMapInfo().m_wTargetScore = wTargetScore;
lpBGServerMap->SendMapInfo();
sprintf(szCommand, "/score %d %d", wMapNumber, wTargetScore);
}
break;
}
case PktAdmin::SET_LIMIT_TIME: // 해당 방의 시간 제한 설정
{
unsigned short wMapNumber = lpPktAdmin->m_usProtoTypeID;
unsigned short wMapIndex = static_cast<unsigned short>(VirtualArea::BGSERVERMAP | wMapNumber);
unsigned char cLimitMin = static_cast<unsigned char>(dwAmount);
VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(wMapIndex);
if (NULL != lpVirtualArea)
{
VirtualArea::CBGServerMap* lpBGServerMap = reinterpret_cast<VirtualArea::CBGServerMap*>(lpVirtualArea);
lpBGServerMap->GetMapInfo().m_cLimitMin = cLimitMin;
lpBGServerMap->GetMapInfo().m_cRemainPlayMin = cLimitMin;
lpBGServerMap->ResetEnteringMin(cLimitMin); // 들어올 시점의 남은 시간을 cLimit 로 전부 리셋
if (lpBGServerMap->IsPlaying())
{
lpBGServerMap->SetRemainTime( timeGetTime() + cLimitMin * VirtualArea::MILLISEC_PER_MINUTE );
}
lpBGServerMap->SendMapInfo();
sprintf(szCommand, "/time %d %d", wMapNumber, cLimitMin);
}
break;
}
case PktAdmin::SET_REST_TIME: // 해당 방의 쉬는 시간 설정
{
unsigned short wMapNumber = lpPktAdmin->m_usProtoTypeID;
unsigned short wMapIndex = static_cast<unsigned short>(VirtualArea::BGSERVERMAP | wMapNumber);
unsigned char cRestMin = static_cast<unsigned char>(dwAmount);
VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea(wMapIndex);
if (NULL != lpVirtualArea)
{
VirtualArea::CBGServerMap* lpBGServerMap = reinterpret_cast<VirtualArea::CBGServerMap*>(lpVirtualArea);
lpBGServerMap->GetMapInfo().m_cRestMin = cRestMin;
lpBGServerMap->GetMapInfo().m_cRemainRestMin = cRestMin;
if (lpBGServerMap->IsResting())
{
lpBGServerMap->SetRemainTime( timeGetTime() + cRestMin * VirtualArea::MILLISEC_PER_MINUTE );
}
lpBGServerMap->SendMapInfo();
sprintf(szCommand, "/rest %d %d", wMapNumber, cRestMin);
}
break;
}
case PktAdmin::SET_ITEM_TEMP_INVEN:
{
Item::CItem* lpItem = Item::CItemFactory::GetInstance().CreateItem(lpPktAdmin->m_usProtoTypeID);
if (NULL != lpItem)
{
if (lpItem->IsSet(Item::DetailData::STACKABLE))
{
lpItem->SetNumOrDurability(static_cast<unsigned char>(dwAmount));
}
if (false == lpTarget->SetItem(Item::ItemPos(TakeType::TS_TEMPINVEN, 0), lpItem))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령 오류 : %s의 임시 인벤토리에 아이템을 넣어주는데 실패하였습니다.",
dwAdminCID, lpPktAdmin->m_stName);
DELETE_ITEM(lpItem);
return true;
}
sprintf(szCommand, "/addtempinven %s %d %d", lpTarget->GetCharacterName(), lpPktAdmin->m_usProtoTypeID, dwAmount);
DETLOG3(g_Log, "CID:0x%08x 어드민이 아이템을 생성하여 임시 인벤토리에 넣어주었습니다. 아이템(ID:%d, 갯수:%d)",
lpTarget->GetCID(), lpPktAdmin->m_usProtoTypeID, dwAmount);
}
break;
}
// 스펠 관련 운영자 명렁
case PktAdmin::ADD_SPELL:
{
unsigned short wSpellID = static_cast<unsigned short>(min(static_cast<long>(lpPktAdmin->m_dwAmount), USHRT_MAX));
unsigned short wSpellLevel = static_cast<unsigned short>(min(static_cast<long>(lpPktAdmin->m_dwAmount2), USHRT_MAX));
unsigned long dwDurationSec = lpPktAdmin->m_dwAmount3;
dwDurationSec = dwDurationSec == 0 ? CSpell::INFINITE_DURATION : dwDurationSec;
if (false == AddSpell(lpAdmin, lpTarget, wSpellID, wSpellLevel, dwDurationSec))
{
ERRLOG2(g_Log, "CID:0x%08x 어드민 명령으로 스펠 부여 실패 (SpellID : %d)", lpTarget->GetCID(), wSpellID);
return true;
}
sprintf(szCommand, "/addspell %s 0x%08x %d %d", lpTarget->GetCharacterName(), wSpellID, wSpellLevel, dwDurationSec);
break;
}
case PktAdmin::DELETE_SPELL:
{
unsigned char cSpellType = static_cast<unsigned char>(lpPktAdmin->m_usProtoTypeID);
lpTarget->GetSpellMgr().GetAffectedInfo().RemoveChantBySpellType(cSpellType);
lpTarget->GetSpellMgr().GetAffectedInfo().RemoveEnchantBySpellType(cSpellType);
sprintf(szCommand, "/deletespell %s %d", lpTarget->GetCharacterName(), cSpellType);
break;
}
// 캐릭터 묶어두기 관련 운영자 명령
case PktAdmin::STOP:
{
if (false == AddSpell(lpAdmin, lpTarget, Skill::SpellID::Hold, 1, Skill::Disenchant::INFINITE_NUM))
{
ERRLOG1(g_Log, "CID:0x%08x 어드민 명령으로 캐릭터 묶어두기 실패", lpTarget->GetCID());
return true;
}
sprintf(szCommand, "/stop %s", lpTarget->GetCharacterName());
break;
}
case PktAdmin::STOP_OFF:
{
lpTarget->GetSpellMgr().GetAffectedInfo().RemoveChantBySpellType(Skill::SpellID::Hold);
lpTarget->GetSpellMgr().GetAffectedInfo().RemoveEnchantBySpellType(Skill::SpellID::Hold);
sprintf(szCommand, "/stopoff %s", lpTarget->GetCharacterName());
break;
}
case PktAdmin::CHAT_BAN:
{
GET_SINGLE_DISPATCH(lpChatDispatch, CChatDispatch, CChatDispatch::GetDispatchTable());
if (NULL != lpChatDispatch)
{
GameClientSendPacket::SendCharChatBan(lpChatDispatch->GetSendStream(), dwAdminCID, lpTarget->GetCID(), dwAmount);
}
break;
}
case PktAdmin::CHAT_OK:
{
GET_SINGLE_DISPATCH(lpChatDispatch, CChatDispatch, CChatDispatch::GetDispatchTable());
if (NULL != lpChatDispatch)
{
GameClientSendPacket::SendCharChatBan(lpChatDispatch->GetSendStream(), dwAdminCID, lpTarget->GetCID(), 0);
}
break;
}
// 공헌훈장 포인트.
case PktAdmin::REALM_POINT:
{
if(dwAmount>=0 && dwAmount<=5)
{
// DB Agent 보낸다.
GET_SINGLE_DISPATCH(lpDBAgentDispatch, CDBAgentDispatch, CDBAgentDispatch::GetDispatchTable());
if(lpDBAgentDispatch)
{
CSendStream& SendStream = lpDBAgentDispatch->GetSendStream();
char* lpBuffer = SendStream.GetBuffer(sizeof(PktRealmPoint));
if (lpBuffer)
{
PktRealmPoint* lpPktRealmPoint = reinterpret_cast<PktRealmPoint*>(lpBuffer);
lpPktRealmPoint->m_dwCID = lpTarget->GetCID();
lpPktRealmPoint->m_cRealmPoint = static_cast<unsigned char>(dwAmount);
lpPktRealmPoint->m_cType = PktRealmPoint::REALM_JOIN;
return SendStream.WrapCrypt(sizeof(PktRealmPoint), CmdRealmPoint, 0, 0);
}
}
sprintf(szCommand, "/realmpoint %s %d", lpTarget->GetCharacterName(), dwAmount);
}
break;
}
default:
break;
}
// Admin 명령어 로그 패킷 //
if(lpAdmin && lpTarget)
{
GET_SINGLE_DISPATCH(lpDBAgentDispatch, CDBAgentDispatch, CDBAgentDispatch::GetDispatchTable());
if(lpDBAgentDispatch)
{
char* lpBuffer = lpDBAgentDispatch->GetSendStream().GetBuffer(sizeof(PktAdminCommandLog));
if(lpBuffer)
{
PktAdminCommandLog* lpPktAdminCommandLog = reinterpret_cast<PktAdminCommandLog*>(lpBuffer);
lpPktAdminCommandLog->m_dwAdminCID = lpAdmin->GetCID();
lpPktAdminCommandLog->m_dwCID = lpTarget->GetCID();
memcpy(lpPktAdminCommandLog->m_szCommand, szCommand, PktAdminCommandLog::MAX_COMMAND_SIZE);
lpDBAgentDispatch->GetSendStream().WrapHeader(sizeof(PktAdminCommandLog), CmdAdminCommandLog, 0, PktBase::NO_SERVER_ERR);
}
}
}
return true;
}
bool GameClientParsePacket::AddSpell(CCharacter* lpCaster, CCharacter* lpVictim,
unsigned short wSpellID, unsigned short wSpellLevel, unsigned long dwDurationSec)
{
if (!lpCaster || !lpVictim)
{
return false;
}
CSpell* pSpell = NULL ;
unsigned short wResult = CSpell::NO_ENCHANT_ERROR ;
switch (wSpellID)
{
// Chant
case Skill::SpellID::BattleSong :
{
pSpell = new CBattleSongSpell(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec), 0);
}
break;
case Skill::SpellID::StealHand :
{
pSpell = new CStealHandSpell(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec), 0);
}
break;
case Skill::SpellID::MaintenanceChant :
{
pSpell = new CMaintenanceChantSpell(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec), 0);
}
break;
case Skill::SpellID::AccelerationChant :
{
pSpell = new CAccelerationChantSpell(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec), 0);
}
break;
case Skill::SpellID::LifeAura :
{
pSpell = new CLifeAuraSpell(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec), 0);
}
break;
case Skill::SpellID::SpeedBuff :
{
pSpell = new CSpeedBuffChantSpell(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec), 0);
}
break;
// Enchant
case Skill::SpellID::ExpOrb :
{
//CExpOrbSpell
wResult = Skill::CAddSpell<CExpOrbSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::PAYBUFF_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::LuckyOrb :
{
//CLuckyOrbSpell
wResult = Skill::CAddSpell<CLuckyOrbSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::PAYBUFF_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::PowerStatue :
{
wResult = Skill::CAddSpell<CPowerStatueSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::STATUE_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::IntStatue :
{
wResult = Skill::CAddSpell<CIntStatueSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::STATUE_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::ExpStatue :
{
wResult = Skill::CAddSpell<CExpStatueSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::STATUE_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::WealthStatue :
{
wResult = Skill::CAddSpell<CWealthStatueSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::STATUE_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::CD_8D12:
case Skill::SpellID::CD_8D14:
case Skill::SpellID::CD_8D16:
case Skill::SpellID::CD_99A1:
case Skill::SpellID::CD_99A2:
case Skill::SpellID::CD_99A3:
case Skill::SpellID::DemagePotion:
case Skill::SpellID::ArmorPotion:
case Skill::SpellID::HitRatePotion:
case Skill::SpellID::EvadePotion:
case Skill::SpellID::MaxHPPotion:
case Skill::SpellID::MaxMPPotion:
case Skill::SpellID::MPRegenPotion:
case Skill::SpellID::HPRegenPotion:
case Skill::SpellID::CriticalPotion:
case Skill::SpellID::BlockPotion:
case Skill::SpellID::SpeedPotion:
case Skill::SpellID::DeCoolDownPotion:
case Skill::SpellID::MagicPowerPotion:
case Skill::SpellID::MagicResistPotion:
{
wResult = Skill::CAddSpell<CBuffPotionSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::BUFF_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Regeneration :
{
wResult = Skill::CAddSpell<CRegenerationSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Slow :
{
wResult = Skill::CAddSpell<CSlowSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::ArmorBroken :
{
wResult = Skill::CAddSpell<CArmorBrokenSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Blaze :
{
wResult = Skill::CAddSpell<CBlazeSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Charging :
{
wResult = Skill::CAddSpell<CChargingSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Stealth :
{
wResult = Skill::CAddSpell<CStealthSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::ManaShell :
{
wResult = Skill::CAddSpell<CManaShellSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Encourage :
{
wResult = Skill::CAddSpell<CEncourageSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::EnchantWeapon :
{
wResult = Skill::CAddSpell<CEnchantWeaponSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::BrightArmor :
{
wResult = Skill::CAddSpell<CBrightArmorSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::HardenSkin :
{
wResult = Skill::CAddSpell<CHardenSkinSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Flexibility :
{
wResult = Skill::CAddSpell<CFlexibilitySpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Guard :
{
wResult = Skill::CAddSpell<CGuardSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Hold :
{
wResult = Skill::CAddSpell<CHoldSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::PHYSICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Stun :
{
wResult = Skill::CAddSpell<CStunSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Frozen :
{
wResult = Skill::CAddSpell<CFrozenSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Poisoned :
{
wResult = Skill::CAddSpell<CPoisonedSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::LowerStrength :
{
wResult = Skill::CAddSpell<CLowerStrengthSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Invincible :
{
wResult = Skill::CAddSpell<CInvincibleSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Hide :
{
return true;
}
break;
case Skill::SpellID::StoneForm :
{
wResult = Skill::CAddSpell<CStoneFormSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::CounterAttack :
{
return true;
}
break;
case Skill::SpellID::Envenom :
{
wResult = Skill::CAddSpell<CEnvenomSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::BombSet :
{
wResult = Skill::CAddSpell<CBombSetSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::Fired :
{
wResult = Skill::CAddSpell<CFiredSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::CurseOfBlind :
{
wResult = Skill::CAddSpell<CCurseOfBlindSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::HundredLevel :
return true;
/*
// edith 100랩달성 이팩트
case Skill::SpellID::HundredLevel :
{
wResult = Skill::CAddSpell<CHundredLevelSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::ETERNAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
*/
case Skill::SpellID::DeCoolDown :
{
wResult = Skill::CAddSpell<CDeCoolDownSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::MAGICAL_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
case Skill::SpellID::MichaelBless :
{
wResult = Skill::CAddSpell<CMichaelBlessSpell>(CSpell::Spell_Info(Skill::CProcessTable::ProcessInfo::m_NullProtoType, lpCaster,
Skill::SpellType::PAYBUFF_SPELL, wSpellID, wSpellLevel, dwDurationSec))(lpVictim);
return (wResult == CSpell::ENCHANT_FAIL_BY_ENEMY_ENCHANT) ? false : true;
}
break;
}
// Chant Spell
if (pSpell)
{
CParty* pParty = lpVictim->GetParty();
if (pParty)
{
pParty->GetPartySpellMgr().AddAffectedToAllMember(pSpell, lpCaster->GetMapIndex());
}
else
{
unsigned short wError = CSpell::NO_ENCHANT_ERROR;
pSpell->AddAffected(lpVictim, wError);
}
CGlobalSpellMgr::GetInstance().Add(pSpell);
return true;
}
return false;
}
bool GameClientParsePacket::ParseCharNameChange(CGameClientDispatch& GameClientDispatch, PktBase* lpPktBase)
{
CHECK_FIXED_PACKETSIZE(lpPktBase, sizeof(PktCharNameChange), GameClientDispatch);
PktCharNameChange* lpPktCharNameChange =
reinterpret_cast<PktCharNameChange*>(lpPktBase);
/*
// 패킷 진행순서
-Game
bool GameClientParsePacket::ParseCharNameChange(CGameClientDispatch& GameClientDispatch, PktBase* lpPktBase)
-DBAgent
bool CGameDispatch::ChangeName(PktBase* lpPktBase)
-Game
bool DBAgentPacketParse::ParseCharNameChangeAck(CDBAgentDispatch& DBAgentDispatch, PktBase* lpPktBase)
*/
const char* szChangeName = lpPktCharNameChange->m_szCharName;
unsigned long dwUID = lpPktCharNameChange->m_dwUID;
unsigned long dwCID = lpPktCharNameChange->m_dwCID;
Item::ItemPos ItemPos = lpPktCharNameChange->m_ItemPos; // 허가서 위치
unsigned short usError = 0;
CCharacter* lpCharacter = GameClientDispatch.GetCharacter();
if (0 == lpCharacter || lpCharacter->GetUID() != dwUID || lpCharacter->GetCID() != dwCID)
{
ERRLOG3(g_Log, "UID:%10u / CID:%10u / CharacterPointer:0x%08X / 캐릭터 이름 변경 실패 : 일치하는 캐릭터 없음",
dwUID, dwCID, lpCharacter);
usError = PktCharNameChange::ERR_CANNOT_FIND_CHARACTER;
}
/*
// 삭제 아이템 기능이 들어감으로서 해당 로직은 제외
else if (0 == lpCharacter->GetNameChangeCount())
{
ERRLOG2(g_Log, "UID:%10u / CID:%10u / 이름 변경 카운트가 0입니다", dwUID, dwCID);
usError = PktCharNameChange::ERR_NAMECHANGE_COUNT;
}
*/
else if (!CharCreate::CheckCharCreateName(szChangeName, CServerSetup::GetInstance().GetHanCheck()))
{
// 생성 캐릭터 이름 검사
ERRLOG3(g_Log, "UID:%10u / CID:%10u / 잘못된 캐릭터 이름 %s", dwUID, dwCID, szChangeName);
usError = PktCharNameChange::ERR_INVALID_NAME;
}
else if (!Filter::NameCheck(szChangeName))
{
// 생성 캐릭터 이름 검사
ERRLOG3(g_Log, "UID:%10u / CID:%10u / 사용할 수 없는 캐릭터 이름 %s", dwUID, dwCID, szChangeName);
usError = PktCharNameChange::ERR_INVALID_NAME;
}
else if(!lpCharacter->CheckRenameWarrant(ItemPos, false))
{
// 생성 캐릭터 이름 검사
ERRLOG2(g_Log, "UID:%10u / CID:%10u / 계명허가서 아이템에 문제가있다.", dwUID, dwCID);
usError = PktCharNameChange::ERR_NAMECHANGE_ITEM;
}
else
{
GET_SINGLE_DISPATCH(lpAgentDispatch, CDBAgentDispatch,
CDBAgentDispatch::GetDispatchTable());
if(0 == lpAgentDispatch || !GameClientSendPacket::SendCharNameChange(
lpAgentDispatch->GetSendStream(), dwUID, dwCID, szChangeName, 0, &ItemPos, 0))
{
usError = PktCharNameChange::ERR_SERVER;
}
}
if(0 != usError)
{
// 클라이언트로 에러코드를 보낸다.
GameClientSendPacket::SendCharNameChange(GameClientDispatch.GetSendStream(),
dwUID, dwCID, szChangeName, 0, &ItemPos, usError);
}
return true;
}