CNpc* CRoomEvent::GetNpcPtr( int sid ) { int count = 0; int nMonster = m_mapRoomNpcArray.GetSize(); if( nMonster == 0 ) { TRACE("### RoomEvent-GetNpcPtr() : monster empty ###\n"); return nullptr; } FastGuard lock(m_mapRoomNpcArray.m_lock); int *pIDList = new int[nMonster]; foreach_stlmap (itr, m_mapRoomNpcArray) pIDList[count++] = *itr->second; for(int i=0 ; i<nMonster; i++ ) { int nMonsterid = pIDList[i]; if( nMonsterid < 0 ) continue; CNpc *pNpc = g_pMain->m_arNpc.GetData( nMonsterid ); if( !pNpc ) continue; if( pNpc->m_proto->m_sSid == sid ) { if(pIDList) { delete [] pIDList; pIDList = nullptr; } return pNpc; } } if (pIDList) delete [] pIDList; return nullptr; }
BOOL CRoomEvent::CheckMonsterCount( int sid, int count, int type ) { int nMonsterCount = 0, nTotalMonster = 0; BOOL bRetValue = FALSE; EnterCriticalSection( &g_region_critical ); int nMonster = m_mapRoomNpcArray.GetSize(); if( nMonster == 0 ) { TRACE("### RoomEvent-GetNpcPtr() : monster empty ###\n"); LeaveCriticalSection( &g_region_critical ); return NULL; } int *pIDList = new int[nMonster]; foreach_stlmap (itr, m_mapRoomNpcArray) pIDList[nTotalMonster++] = *itr->second; LeaveCriticalSection( &g_region_critical ); for(int i=0 ; i<nMonster; i++ ) { CNpc *pNpc = m_pMain->m_arNpc.GetData(pIDList[i]); if( !pNpc ) continue; if( type == 4 ) { if( pNpc->m_byRegenType == 2 ) pNpc->m_byRegenType = 0; pNpc->m_byChangeType = 0; } else if( type == 3 ) { // 모든 몬스터를 죽었는지를 판단 if( pNpc->m_byDeadType == 100 ) nMonsterCount++; if( nMonsterCount == nMonster ) bRetValue = TRUE; } else if( pNpc->m_sSid == sid ) { if( type == 1 ) { // 특정 몬스터가 마리수 만큼 죽었는지를 판단 if( pNpc->m_byChangeType == 100 ) nMonsterCount++; if( nMonsterCount == count ) bRetValue = TRUE; } else if( type == 2 ) { // 특정 몬스터를 마리수 만큼 출현 시켜라,, pNpc->m_byChangeType = 3; nMonsterCount++; if( nMonsterCount == count ) bRetValue = TRUE; } } } if (pIDList) delete [] pIDList; return bRetValue; }
void CUser::HealAreaCheck(int rx, int rz) { MAP* pMap = GetMap(); if (pMap == NULL) return; // 자신의 region에 있는 NpcArray을 먼저 검색하여,, 가까운 거리에 Monster가 있는지를 판단.. if(rx < 0 || rz < 0 || rx > pMap->GetXRegionMax() || rz > pMap->GetZRegionMax()) { TRACE("#### CUser-HealAreaCheck() Fail : [nid=%d, name=%s], nRX=%d, nRZ=%d #####\n", m_iUserId, m_strUserID, rx, rz); return; } float fRadius = 10.0f; // 30m __Vector3 vStart, vEnd; CNpc* pNpc = NULL ; // Pointer initialization! float fDis = 0.0f; vStart.Set(m_curx, (float)0, m_curz); int send_index=0, result = 1, count = 0; EnterCriticalSection( &g_region_critical ); CRegion *pRegion = &pMap->m_ppRegion[rx][rz]; int total_mon = pRegion->m_RegionNpcArray.GetSize(); int *pNpcIDList = new int[total_mon]; foreach_stlmap (itr, pRegion->m_RegionNpcArray) pNpcIDList[count++] = *itr->second; LeaveCriticalSection( &g_region_critical ); for(int i = 0 ; i < total_mon; i++ ) { int nid = pNpcIDList[i]; if( nid < NPC_BAND ) continue; pNpc = (CNpc*)g_pMain->m_arNpc.GetData(nid - NPC_BAND); if( pNpc != NULL && pNpc->m_NpcState != NPC_DEAD) { if( m_bNation == pNpc->m_byGroup ) continue; vEnd.Set(pNpc->m_fCurX, pNpc->m_fCurY, pNpc->m_fCurZ); fDis = pNpc->GetDistance(vStart, vEnd); if(fDis <= fRadius) { // NPC가 반경안에 있을 경우... pNpc->ChangeTarget(1004, this); } } } if (pNpcIDList) delete [] pNpcIDList; }
bool CRoomEvent::CheckMonsterCount( int sid, int count, int type ) { int nMonsterCount = 0, nTotalMonster = 0; bool bRetValue = false; int nMonster = m_mapRoomNpcArray.GetSize(); if( nMonster == 0 ) { TRACE("### RoomEvent-GetNpcPtr() : monster empty ###\n"); return nullptr; } m_mapRoomNpcArray.m_lock.Acquire(); int *pIDList = new int[nMonster]; foreach_stlmap (itr, m_mapRoomNpcArray) pIDList[nTotalMonster++] = *itr->second; m_mapRoomNpcArray.m_lock.Release(); for(int i=0 ; i<nMonster; i++ ) { CNpc *pNpc = g_pMain->m_arNpc.GetData(pIDList[i]); if( !pNpc ) continue; if( type == 4 ) { if( pNpc->m_byRegenType == 2 ) pNpc->m_byRegenType = 0; pNpc->m_byChangeType = 0; } else if( type == 3 ) { // 모든 몬스터를 죽었는지를 판단 if( pNpc->m_byDeadType == 100 ) nMonsterCount++; if( nMonsterCount == nMonster ) bRetValue = true; } else if( pNpc->m_proto->m_sSid == sid ) { if( type == 1 ) { // 특정 몬스터가 마리수 만큼 죽었는지를 판단 if( pNpc->m_byChangeType == 100 ) nMonsterCount++; if( nMonsterCount == count ) bRetValue = true; } else if( type == 2 ) { // 특정 몬스터를 마리수 만큼 출현 시켜라,, pNpc->m_byChangeType = 3; nMonsterCount++; if( nMonsterCount == count ) bRetValue = true; } } } if (pIDList) delete [] pIDList; return bRetValue; }
CNpc* CRoomEvent::GetNpcPtr( int sid ) { int count = 0; EnterCriticalSection( &g_region_critical ); int nMonster = m_mapRoomNpcArray.GetSize(); if( nMonster == 0 ) { TRACE("### RoomEvent-GetNpcPtr() : monster empty ###\n"); LeaveCriticalSection( &g_region_critical ); return NULL; } int *pIDList = new int[nMonster]; foreach_stlmap (itr, m_mapRoomNpcArray) pIDList[count++] = *itr->second; LeaveCriticalSection( &g_region_critical ); for(int i=0 ; i<nMonster; i++ ) { int nMonsterid = pIDList[i]; if( nMonsterid < 0 ) continue; CNpc *pNpc = m_pMain->m_arNpc.GetData( nMonsterid ); if( !pNpc ) continue; if( pNpc->m_sSid == sid ) { if(pIDList) { delete [] pIDList; pIDList = NULL; } return pNpc; } } if (pIDList) delete [] pIDList; return NULL; }
void CMagicProcess::AreaAttackDamage(int magictype, int rx, int rz, int magicid, int moral, int data1, int data2, int data3, int dexpoint, int righthand_damage) { MAP* pMap = m_pSrcUser->GetMap(); if (pMap == NULL) return; // 자신의 region에 있는 UserArray을 먼저 검색하여,, 가까운 거리에 유저가 있는지를 판단.. if(rx < 0 || rz < 0 || rx > pMap->GetXRegionMax() || rz > pMap->GetZRegionMax()) { TRACE("#### CMagicProcess-AreaAttackDamage() Fail : [nid=%d, name=%s], nRX=%d, nRZ=%d #####\n", m_pSrcUser->m_iUserId, m_pSrcUser->m_strUserID, rx, rz); return; } _MAGIC_TYPE3* pType3 = NULL; _MAGIC_TYPE4* pType4 = NULL; _MAGIC_TABLE* pMagic = NULL; int damage = 0, tid = 0, target_damage = 0, attribute = 0; float fRadius = 0; pMagic = g_pMain->m_MagictableArray.GetData( magicid ); // Get main magic table. if( !pMagic ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magic maintable error ,, magicid=%d\n", magicid); return; } if(magictype == 3) { pType3 = g_pMain->m_Magictype3Array.GetData( magicid ); // Get magic skill table type 3. if( !pType3 ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magic table3 error ,, magicid=%d\n", magicid); return; } target_damage = pType3->sFirstDamage; attribute = pType3->bAttribute; fRadius = (float)pType3->bRadius; } else if(magictype == 4) { pType4 = g_pMain->m_Magictype4Array.GetData( magicid ); // Get magic skill table type 3. if( !pType4 ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magic table4 error ,, magicid=%d\n", magicid); return; } fRadius = (float)pType4->bRadius; } if( fRadius <= 0 ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magicid=%d, radius = %d\n", magicid, fRadius); return; } __Vector3 vStart, vEnd; CNpc* pNpc = NULL ; // Pointer initialization! float fDis = 0.0f; vStart.Set((float)data1, (float)0, (float)data3); char send_buff[256]; int send_index=0, result = 1, count = 0, total_mon = 0, attack_type=0;; int* pNpcIDList = NULL; EnterCriticalSection( &g_region_critical ); CRegion *pRegion = &pMap->m_ppRegion[rx][rz]; total_mon = pRegion->m_RegionNpcArray.GetSize(); pNpcIDList = new int[total_mon]; foreach_stlmap (itr, pRegion->m_RegionNpcArray) pNpcIDList[count++] = *itr->second; LeaveCriticalSection(&g_region_critical); for(int i = 0 ; i < total_mon; i++ ) { int nid = pNpcIDList[i]; if( nid < NPC_BAND ) continue; pNpc = (CNpc*)g_pMain->m_arNpc.GetData(nid - NPC_BAND); if( pNpc != NULL && pNpc->m_NpcState != NPC_DEAD) { if( m_pSrcUser->m_bNation == pNpc->m_byGroup ) continue; vEnd.Set(pNpc->m_fCurX, pNpc->m_fCurY, pNpc->m_fCurZ); fDis = pNpc->GetDistance(vStart, vEnd); if(fDis <= fRadius) { // NPC가 반경안에 있을 경우... if(magictype == 3) { // 타잎 3일 경우... damage = GetMagicDamage(pNpc->m_sNid+NPC_BAND, target_damage, attribute, dexpoint, righthand_damage); TRACE("Area magictype3 ,, magicid=%d, damage=%d\n", magicid, damage); if(damage >= 0) { result = pNpc->SetHMagicDamage(damage); } else { damage = abs(damage); if(pType3->bAttribute == 3) attack_type = 3; // 기절시키는 마법이라면..... else attack_type = magicid; if(pNpc->SetDamage(attack_type, damage, m_pSrcUser->m_strUserID, m_pSrcUser->m_iUserId + USER_BAND) == FALSE) { // Npc가 죽은 경우,, pNpc->SendExpToUserList(); // 경험치 분배!! pNpc->SendDead(); m_pSrcUser->SendAttackSuccess(pNpc->m_sNid+NPC_BAND, MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP); } else { m_pSrcUser->SendAttackSuccess(pNpc->m_sNid+NPC_BAND, ATTACK_SUCCESS, damage, pNpc->m_iHP); } } send_index = 0; // 패킷 전송..... //if ( pMagic->bType[1] == 0 || pMagic->bType[1] == 3 ) { SetByte( send_buff, AG_MAGIC_ATTACK_RESULT, send_index ); SetByte( send_buff, MAGIC_EFFECTING, send_index ); SetDWORD( send_buff, magicid, send_index ); SetShort( send_buff, m_pSrcUser->m_iUserId, send_index ); SetShort( send_buff, pNpc->m_sNid+NPC_BAND, send_index ); SetShort( send_buff, data1, send_index ); SetShort( send_buff, result, send_index ); SetShort( send_buff, data3, send_index ); SetShort( send_buff, moral, send_index ); SetShort( send_buff, 0, send_index ); SetShort( send_buff, 0, send_index ); g_pMain->Send( send_buff, send_index ); } } else if(magictype == 4) { // 타잎 4일 경우... send_index = 0; result = 1; switch (pType4->bBuffType) { // Depending on which buff-type it is..... case 1 : // HP 올리기.. break; case 2 : // 방어력 올리기.. break; case 4 : // 공격력 올리기.. break; case 5 : // 공격 속도 올리기.. break; case 6 : // 이동 속도 올리기.. //if (pNpc->m_MagicType4[pType4->bBuffType-1].sDurationTime > 0) { // result = 0 ; //} //else { pNpc->m_MagicType4[pType4->bBuffType-1].byAmount = pType4->bSpeed; pNpc->m_MagicType4[pType4->bBuffType-1].sDurationTime = pType4->sDuration; pNpc->m_MagicType4[pType4->bBuffType-1].fStartTime = TimeGet(); pNpc->m_fSpeed_1 = (float)(pNpc->m_fOldSpeed_1 * ((double)pType4->bSpeed / 100)); pNpc->m_fSpeed_2 = (float)(pNpc->m_fOldSpeed_2 * ((double)pType4->bSpeed / 100)); //} break; case 7 : // 능력치 올리기... break; case 8 : // 저항력 올리기... break; case 9 : // 공격 성공율 및 회피 성공율 올리기.. break; default : result = 0 ; break; } TRACE("Area magictype4 ,, magicid=%d\n", magicid); SetByte( send_buff, AG_MAGIC_ATTACK_RESULT, send_index ); SetByte( send_buff, MAGIC_EFFECTING, send_index ); SetDWORD( send_buff, magicid, send_index ); SetShort( send_buff, m_pSrcUser->m_iUserId, send_index ); SetShort( send_buff, pNpc->m_sNid+NPC_BAND, send_index ); SetShort( send_buff, data1, send_index ); SetShort( send_buff, result, send_index ); SetShort( send_buff, data3, send_index ); SetShort( send_buff, 0, send_index ); SetShort( send_buff, 0, send_index ); SetShort( send_buff, 0, send_index ); g_pMain->Send( send_buff, send_index ); } } } } if(pNpcIDList) { delete [] pNpcIDList; pNpcIDList = NULL; } }
void CMagicProcess::AreaAttackDamage(int magictype, int rx, int rz, int magicid, int moral, int data1, int data2, int data3, int dexpoint, int righthand_damage) { MAP* pMap = m_pSrcUser->GetMap(); if (pMap == nullptr) return; // 자신의 region에 있는 UserArray을 먼저 검색하여,, 가까운 거리에 유저가 있는지를 판단.. if(rx < 0 || rz < 0 || rx > pMap->GetXRegionMax() || rz > pMap->GetZRegionMax()) { TRACE("#### CMagicProcess-AreaAttackDamage() Fail : [nid=%d, name=%s], nRX=%d, nRZ=%d #####\n", m_pSrcUser->m_iUserId, m_pSrcUser->m_strUserID, rx, rz); return; } _MAGIC_TYPE3* pType3 = nullptr; _MAGIC_TYPE4* pType4 = nullptr; _MAGIC_TABLE* pMagic = nullptr; int damage = 0, tid = 0, target_damage = 0, attribute = 0; float fRadius = 0; pMagic = g_pMain->m_MagictableArray.GetData( magicid ); // Get main magic table. if( !pMagic ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magic maintable error ,, magicid=%d\n", magicid); return; } if(magictype == 3) { pType3 = g_pMain->m_Magictype3Array.GetData( magicid ); // Get magic skill table type 3. if( !pType3 ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magic table3 error ,, magicid=%d\n", magicid); return; } target_damage = pType3->sFirstDamage; attribute = pType3->bAttribute; fRadius = (float)pType3->bRadius; } else if(magictype == 4) { pType4 = g_pMain->m_Magictype4Array.GetData( magicid ); // Get magic skill table type 3. if( !pType4 ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magic table4 error ,, magicid=%d\n", magicid); return; } fRadius = (float)pType4->bRadius; } if( fRadius <= 0 ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magicid=%d, radius = %d\n", magicid, fRadius); return; } __Vector3 vStart, vEnd; CNpc* pNpc = nullptr ; // Pointer initialization! float fDis = 0.0f; vStart.Set((float)data1, (float)0, (float)data3); int count = 0, total_mon = 0, attack_type=0; int* pNpcIDList = nullptr; bool bResult = true; pMap->m_lock.Acquire(); CRegion *pRegion = &pMap->m_ppRegion[rx][rz]; total_mon = pRegion->m_RegionNpcArray.GetSize(); pNpcIDList = new int[total_mon]; foreach_stlmap (itr, pRegion->m_RegionNpcArray) pNpcIDList[count++] = *itr->second; pMap->m_lock.Release(); for(int i = 0; i < total_mon; i++) { int nid = pNpcIDList[i]; if( nid < NPC_BAND ) continue; pNpc = g_pMain->m_arNpc.GetData(nid); if (pNpc == nullptr || pNpc->m_NpcState == NPC_DEAD) continue; if( m_pSrcUser->m_bNation == pNpc->m_byGroup ) continue; vEnd.Set(pNpc->GetX(), pNpc->GetY(), pNpc->GetZ()); fDis = pNpc->GetDistance(vStart, vEnd); if(fDis > fRadius) continue; if (magictype == 3) { damage = GetMagicDamage(pNpc->GetID(), target_damage, attribute, dexpoint, righthand_damage); TRACE("Area magictype3 ,, magicid=%d, damage=%d\n", magicid, damage); if(damage >= 0) { bResult = pNpc->SetHMagicDamage(damage); } else { damage = abs(damage); if(pType3->bAttribute == 3) attack_type = 3; // 기절시키는 마법이라면..... else attack_type = magicid; if(pNpc->SetDamage(attack_type, damage, m_pSrcUser->m_iUserId + USER_BAND) == false) { m_pSrcUser->SendAttackSuccess(pNpc->GetID(), MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP); } else { m_pSrcUser->SendAttackSuccess(pNpc->GetID(), ATTACK_SUCCESS, damage, pNpc->m_iHP); } } // 패킷 전송..... //if ( pMagic->bType[1] == 0 || pMagic->bType[1] == 3 ) { Packet result(AG_MAGIC_ATTACK_RESULT, uint8(MAGIC_EFFECTING)); result << magicid << m_pSrcUser->m_iUserId << pNpc->GetID() << uint16(data1) << uint16(bResult) << uint16(data3) << uint16(moral) << uint16(0) << uint16(0); g_pMain->Send(&result); } } else if(magictype == 4) { // 타잎 4일 경우... bResult = true; switch (pType4->bBuffType) { // Depending on which buff-type it is..... case 1 : // HP 올리기.. break; case 2 : // 방어력 올리기.. break; case 4 : // 공격력 올리기.. break; case 5 : // 공격 속도 올리기.. break; case 6 : // 이동 속도 올리기.. //if (pNpc->m_MagicType4[pType4->bBuffType-1].sDurationTime > 0) { // result = 0 ; //} //else { pNpc->m_MagicType4[pType4->bBuffType-1].byAmount = pType4->bSpeed; pNpc->m_MagicType4[pType4->bBuffType-1].sDurationTime = pType4->sDuration; pNpc->m_MagicType4[pType4->bBuffType-1].tStartTime = UNIXTIME; pNpc->m_fSpeed_1 = (float)(pNpc->m_fOldSpeed_1 * ((double)pType4->bSpeed / 100)); pNpc->m_fSpeed_2 = (float)(pNpc->m_fOldSpeed_2 * ((double)pType4->bSpeed / 100)); //} break; case 7 : // 능력치 올리기... break; case 8 : // 저항력 올리기... break; case 9 : // 공격 성공율 및 회피 성공율 올리기.. break; default : bResult = false; break; } TRACE("Area magictype4 ,, magicid=%d\n", magicid); Packet result(AG_MAGIC_ATTACK_RESULT, uint8(MAGIC_EFFECTING)); result << magicid << m_pSrcUser->m_iUserId << pNpc->GetID() << uint16(data1) << uint16(bResult) << uint16(data3) << uint16(0) << uint16(0) << uint16(0); g_pMain->Send(&result); } } if(pNpcIDList) { delete [] pNpcIDList; pNpcIDList = nullptr; } }