Files
Sun1602/Server/GameServer/SummonManager.cpp
T
2022-10-26 12:25:11 +08:00

340 lines
9.8 KiB
C++

#include "StdAfx.h"
#include "SummonManager.h"
#include "SummonedNPCs.h"
#include "SkillInfoParser.h"
#include "Summoned.h"
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SummonManager::SummonManager()
{
m_pSummonNPCsPool = new util::CMemoryPoolFactory<SummonedNPCs>;
}
SummonManager::~SummonManager()
{
SAFE_DELETE( m_pSummonNPCsPool );
}
VOID SummonManager::Release()
{
m_SummonNPCsList.clear();
if( m_pSummonNPCsPool )
{
m_pSummonNPCsPool->Release();
}
}
VOID SummonManager::Init( DWORD dwMaxPoolSize )
{
// (WAVERIX)(REMARK)(수치 조정)
// - SummonedNPCs는 그리 부담가는 자료 구조는 아니다 <-( 물론 다른 것에 비해서... )
// - SUMMON_NPC_LIST의 형식을 풀로부터 받을 필요가 없을 듯 한데, 외부 모듈에서 포인터를
// 사용하고 있는 관계로 정확히 확인후 수정하자.
m_pSummonNPCsPool->Initialize( 100, 100, "SummonedNPCs", AssertionLogger4Pool_Server );
}
#ifdef _NA_007667_20141001_WITCHBLADE_SKILL
SummonedNPCs* SummonManager::AllocSummonNPCs( Character* pSummoner, BOOL bPlayerSkill, WORD ability_id /*= 0*/ )
#else
SummonedNPCs* SummonManager::AllocSummonNPCs( Character* pSummoner, BOOL bPlayerSkill )
#endif //_NA_007667_20141001_WITCHBLADE_SKILL
{
SummonedNPCs* pSummonedNPCs = FindSummonNPCs( pSummoner->GetObjectKey() );
#ifdef _NA_007667_20141001_WITCHBLADE_SKILL
if( pSummonedNPCs )
{
// 플레이어 소환의 경우
if( bPlayerSkill )
{
if (ability_id == eABILITY_SUMMON) {
// 일반소환일 경우 일반소환된 소환수만 지운다
DeleteSummonedUsingType(pSummoner, eSUMMON_NORMAL);
}
else if (ability_id == eABILITY_SUMMON_IMMOVABLE) {
// 고정형소환수일경우 고정형 소환수만 지운다
DeleteSummonedUsingType(pSummoner, eSUMMON_IMMOVABLE);
}
else
{
FreeSummonNPCs(pSummonedNPCs); //xiaomi 늪뇹뫘맣梁뻥膠饋쁑
// 해당하는 그룹이 없으면 새로생성
pSummonedNPCs = (SummonedNPCs*)m_pSummonNPCsPool->Alloc();
}
}
else
{
// NPC의 경우 이전 소환정보를 그대로 이용한다.
return pSummonedNPCs;
}
}
else {
pSummonedNPCs = (SummonedNPCs*)m_pSummonNPCsPool->Alloc();
}
#else
if( pSummonedNPCs )
{
// 플레이어 소환의 경우
if( bPlayerSkill )
{
// 이미 소환을 했으면 이전 소환체를 삭제한다.
FreeSummonNPCs( pSummonedNPCs );
}
else
{
// NPC의 경우 이전 소환정보를 그대로 이용한다.
return pSummonedNPCs;
}
}
// 해당하는 그룹이 없으면 새로생성
pSummonedNPCs = (SummonedNPCs*)m_pSummonNPCsPool->Alloc();
#endif //_NA_007667_20141001_WITCHBLADE_SKILL
if( !pSummonedNPCs )
{
SUNLOG( eCRITICAL_LOG, "[SummonManager::AllocSummonNPCs] Can't Allocate SummonedNPCs " );
return NULL;
}
// SummonedNPCs 초기화
if(pSummoner->IsEqualObjectKind(PLAYER_OBJECT))
{
pSummonedNPCs->Init( pSummoner, eSUMMON_COMMAND_DELEGATE_ATTACK_IGNORE_PLAYER );
}
else
{
pSummonedNPCs->Init( pSummoner, eSUMMON_COMMAND_DELEGATE_ATTACK );
}
// SummonManager에 등록
m_SummonNPCsList.insert( std::make_pair( pSummoner->GetObjectKey(), pSummonedNPCs ) );
#ifdef WAVERIX_CODE_DELETE_RESERVED
m_SummonHash.insert( pSummonedNPCs );
#endif
return pSummonedNPCs;
}
BOOL SummonManager::FreeSummonNPCs( SummonedNPCs *pSummonNPCs, BOOL bFollowerDestroy )
{
if( NULL == FindSummonNPCs( pSummonNPCs->GetSummonerKey() ) )
{
SUNLOG( eCRITICAL_LOG, "[SummonManager::FreeSummonNPCs] Can't Remove SummonNPCs " );
return FALSE;
}
m_SummonNPCsList.erase( pSummonNPCs->GetSummonerKey() );
#ifdef WAVERIX_CODE_DELETE_RESERVED
SUMMON_HASH::iterator it = m_SummonHash.find(pSummonNPCs);
if( it == m_SummonHash.end() )
{
SUNLOG( eCRITICAL_LOG, "[SusunLove] FreeSummonNPCs Free Same Memory Pool! SummonerKey[%d]", pSummonNPCs->GetSummonerKey() );
return FALSE;
}
else
{
m_SummonHash.erase(it);
}
#endif
pSummonNPCs->Release( bFollowerDestroy );
m_pSummonNPCsPool->Free( pSummonNPCs );
return TRUE;
}
VOID SummonManager::LoopNode::_AddSummonedSkill( SUMMONED_MAP_PAIR rPair )
{
NPC* pNPC = rPair.second;
if(pNPC->IsEqualObjectKind(SUMMON_OBJECT) == 0)
return;
Summoned* pSummoned = (Summoned*)pNPC;
pSummoned->AddSkill( SKILL_CODE.Get() );
}
VOID SummonManager::AddSummonedSkill( DWORD dwSummonKey, SLOTCODE scSkillCode )
{
SummonedNPCs* pSummonedNPCs = FindSummonNPCs( dwSummonKey );
if( !pSummonedNPCs )
return;
SkillScriptInfo* pBaseCurSkillInfo = SkillInfoParser::Instance()->GetSkillInfo( scSkillCode );
if( pBaseCurSkillInfo->m_bySkillUserType != eSKILL_USER_SUMMONED )
return;
LoopNode loopNode;
loopNode.SKILL_CODE.Set( scSkillCode );
pSummonedNPCs->ForeachSummonedList( &SummonManager::LoopNode::_AddSummonedSkill, &loopNode );
}
VOID SummonManager::LoopNode::_DelSummonedSkill( SUMMONED_MAP_PAIR rPair )
{
NPC* pNPC = rPair.second;
if(pNPC->IsEqualObjectKind(SUMMON_OBJECT) == 0)
return;
Summoned *pSummoned = (Summoned*)pNPC;
pSummoned->DelSkill( SKILL_CODE.Get() );
}
VOID SummonManager::DelSummonedSkill( DWORD dwSummonKey, SLOTCODE scSkillCode )
{
SummonedNPCs *pSummonedNPCs = FindSummonNPCs( dwSummonKey );
if( !pSummonedNPCs )
return;
SkillScriptInfo *pBaseCurSkillInfo = SkillInfoParser::Instance()->GetSkillInfo( scSkillCode );
if( pBaseCurSkillInfo->m_bySkillUserType != eSKILL_USER_SUMMONED )
return;
LoopNode loopNode;
loopNode.SKILL_CODE.Set( scSkillCode );
pSummonedNPCs->ForeachSummonedList( &SummonManager::LoopNode::_DelSummonedSkill, &loopNode );
}
// 현재는 소환체가 1마리라서 오브젝트키로 구분이 필요없지만
// 나중을 위해 클라로부터 명령을 내릴 소환체 오브젝트키를 받아야 한다!
RC::eSUMMON_RESULT SummonManager::SetCommandState( DWORD dwSummonKey, eSUMMON_COMMAND eCommand, DWORD dwObjectKey, DWORD dwTargetKey )
{
SummonedNPCs *pSummonedNPCs = FindSummonNPCs( dwSummonKey );
if( !pSummonedNPCs )
return RC::RC_SUMMON_SUMMONED_NPC_NOTEXIST;
switch(eCommand)
{
case eSUMMON_COMMAND_DESTROY:
{
//!~ _NA_007113_20140324_SHADOW_SKILL_BALLANCE_RENEWAL
if (dwTargetKey)
pSummonedNPCs->Destroy( dwTargetKey );
else
pSummonedNPCs->Destroy( dwObjectKey );
//~! _NA_007113_20140324_SHADOW_SKILL_BALLANCE_RENEWAL
} break;
default:
return pSummonedNPCs->SetCommandState( eCommand, dwObjectKey, dwTargetKey ); // 상태를 바꾸어준다.
}
return RC::RC_SUMMON_SUCCESS;
}
VOID SummonManager::LoopNode::_LeaveSummonNPCs( SUMMONED_MAP_PAIR rPair )
{
NPC* pNPC = rPair.second;
pNPC->SetSummonerKey( 0 );
}
VOID SummonManager::LeaveSummonNPCs( Character *pLeaveChar )
{
#ifdef _NA_000000_20140224_SUMMONER_REFACTORING
SummonedNPCs *pSummonedNPCs = FindSummonNPCs( pLeaveChar->GetObjectKey() );
if (pSummonedNPCs)
{
if(pLeaveChar->IsEqualObjectKind(PLAYER_OBJECT))
{
// 플레이어가 떠날경우 소환정보를 무조건 해제한다.
FreeSummonNPCs( pSummonedNPCs );
}
else
{
// 소환을 시킨 주체인 경우 소환NPC들의 공유소환키(m_dwSummonerKey)를 NULL로 초기화한다.
// NPC가 소환한 부하(소환체)들은 삭제하지 않아야한다.
LoopNode loopNode;
pSummonedNPCs->ForeachSummonedList( &SummonManager::LoopNode::_LeaveSummonNPCs, &loopNode );
FreeSummonNPCs( pSummonedNPCs, FALSE );
}
}
else
{
// 소환을 당한 NPC인 경우 소환정보에서 제거한다.
pSummonedNPCs = FindSummonNPCs( pLeaveChar->GetSummonerKey() );
if (pSummonedNPCs)
{
DWORD dwObjectKey = pLeaveChar->GetObjectKey();
NPC* pLeaveNPC = static_cast<NPC*>(pLeaveChar);
pSummonedNPCs->DecreaseSummoned( pLeaveNPC->GetBaseInfo()->m_MonsterCode, dwObjectKey );
// 소환리스트의 멤버수가 0이면 풀에 반환한다.
if (pSummonedNPCs->GetNumberOfNPCs() == 0) {
FreeSummonNPCs( pSummonedNPCs );
}
}
pLeaveChar->SetSummonerKey(0);
}
#else
SummonedNPCs *pSummonedNPCs = FindSummonNPCs( pLeaveChar->GetObjectKey() );
if( !pSummonedNPCs )
return;
// 플레이어가 떠날경우 소환정보를 무조건 해제한다.
if(pLeaveChar->IsEqualObjectKind(PLAYER_OBJECT))
{
FreeSummonNPCs( pSummonedNPCs );
}
else
{
DWORD dwObjectKey = pLeaveChar->GetObjectKey();
NPC* pLeaveNPC = (NPC*)pLeaveChar;
// 소환을 시킨 주체인 경우 소환NPC들의 공유소환키(m_dwSummonerKey)를 NULL로 초기화한다.
// NPC가 소환한 부하(소환체)들은 삭제하지 않아야한다.
if( pSummonedNPCs->IsSummoner( dwObjectKey ) )
{
LoopNode loopNode;
pSummonedNPCs->ForeachSummonedList( &SummonManager::LoopNode::_LeaveSummonNPCs, &loopNode );
FreeSummonNPCs( pSummonedNPCs, FALSE );
}
// 소환을 당한 NPC인 경우 소환정보에서 제거한다.
else
{
pSummonedNPCs->DecreaseSummoned( pLeaveNPC->GetBaseInfo()->m_MonsterCode, dwObjectKey );
// 소환리스트의 멤버수가 0이면 풀에 반환한다.
if( !pSummonedNPCs->GetNumberOfNPCs() )
{
FreeSummonNPCs( pSummonedNPCs );
}
}
}
pLeaveChar->SetSummonerKey(0);
#endif //_NA_000000_20140224_SUMMONER_REFACTORING
}
#ifdef _NA_007667_20141001_WITCHBLADE_SKILL
bool SummonManager::DeleteSummonedUsingType( Character* pSummoner, eSUMMON_TYPE type )
{
SummonedNPCs* pSummonedNPCs = FindSummonNPCs( pSummoner->GetObjectKey() );
if (pSummonedNPCs == NULL) {
return false;
}
Summoned* summoned = pSummonedNPCs->FindSummonedUsingType(type);
if (summoned == NULL) {
//어찌되었든 없는상태로 만들어야 하니..
return true;
}
pSummonedNPCs->Destroy(summoned->GetObjectKey());
}
#endif //_NA_007667_20141001_WITCHBLADE_SKILL