void CAISocket::RecvNpcRegionUpdate(Packet & pkt) { uint16 sNpcID; float fX, fY, fZ; pkt >> sNpcID >> fX >> fY >> fZ; CNpc * pNpc = g_pMain->GetNpcPtr(sNpcID); if (pNpc == nullptr) return; pNpc->SetPosition(fX, fY, fZ); pNpc->RegisterRegion(); }
void CUser::ClientEvent(uint16 sNpcID) { // Ensure AI's loaded if (!g_pMain->m_bPointCheckFlag || isDead()) return; int32 iEventID = 0; CNpc *pNpc = g_pMain->GetNpcPtr(sNpcID); if (pNpc == nullptr || !isInRange(pNpc, MAX_NPC_RANGE)) return; m_sEventNid = sNpcID; m_sEventSid = pNpc->GetProtoID(); // For convenience purposes with Lua scripts. // Aww. if (pNpc->GetType() == NPC_KISS) { KissUser(); return; } FastGuard lock(g_pMain->m_questNpcLock); QuestNpcList::iterator itr = g_pMain->m_QuestNpcList.find(pNpc->GetProtoID()); if (itr == g_pMain->m_QuestNpcList.end()) return; // Copy it. We should really lock the list, but nevermind. QuestHelperList & pList = itr->second; _QUEST_HELPER * pHelper = nullptr; foreach(itr, pList) { if ((*itr) == nullptr || (*itr)->sEventDataIndex || (*itr)->bEventStatus || ((*itr)->bNation != 3 && (*itr)->bNation != GetNation()) || ((*itr)->bClass != 5 && !JobGroupCheck((*itr)->bClass))) continue; pHelper = (*itr); break; } if (pHelper == nullptr) return; QuestV2RunEvent(pHelper, pHelper->nEventTriggerIndex); }
void CFishingManager::Fishing_Ready_Ack(void* pMsg) { MSG_DWORD4* pmsg = (MSG_DWORD4*)pMsg; CObject* pObject = OBJECTMGR->GetObject(pmsg->dwObjectID); if(!pObject) return; if(pObject == HERO) { if(0==pmsg->dwData1 || 0==pmsg->dwData3 || 0==pmsg->dwData4) return; SetFishingStartTime(gCurTime); SetFishingPlace(pmsg->dwData1); m_fGaugeStartPos = (float)pmsg->dwData2/100.0f; m_dwProcessTime = pmsg->dwData3; m_nRepeatCount = pmsg->dwData4; LONG maxValue = 0; cGuageBar* pGaugeBar = GAMEIN->GetFishingGaugeDlg()->GetFishingGB(); if(pGaugeBar) maxValue = pGaugeBar->GetMaxValue(); m_fGaugeBarSpeed = ((float)m_nRepeatCount * maxValue) / (float)m_dwProcessTime; m_dwUpdateTime = (m_dwProcessTime / m_nRepeatCount) / maxValue; m_bActive = TRUE; } else { CNpc* pNpc = (CNpc*)OBJECTMGR->GetObject(pmsg->dwData1); if(pNpc) { // 방향전환 VECTOR3 pos; pNpc->GetPosition(&pos); MOVEMGR->SetLookatPos(pObject,&pos,0,gCurTime); } } OBJECTSTATEMGR->StartObjectState(pObject, eObjectState_Fishing); OBJECTEFFECTDESC desc( FindEffectNum("char_m_fishing_swing_A.beff") ); pObject->RemoveObjectEffect( FISHING_START_EFFECT ); pObject->AddObjectEffect( FISHING_START_EFFECT, &desc, 1 ); }
// TO-DO: Remove this. NPCs don't just randomly die, it would make sense to do this as a result of the cause, not just because. void CAISocket::RecvNpcDead(Packet & pkt) { CNpc * pNpc; Unit * pAttacker; uint16 nid, attackerID; pkt >> nid >> attackerID; pNpc = g_pMain->GetNpcPtr(nid); if (pNpc == nullptr || pNpc->GetMap() == nullptr) return; pAttacker = g_pMain->GetUnitPtr(attackerID); pNpc->OnDeath(pAttacker); }
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; }
CNpc* CRoomEvent::GetNpcPtr( int sid ) { if (m_mapRoomNpcArray.IsEmpty()) { TRACE("### RoomEvent-GetNpcPtr() : monster empty ###\n"); return nullptr; } foreach_stlmap (itr, m_mapRoomNpcArray) { CNpc *pNpc = g_pMain->GetNpcPtr(itr->first); if (pNpc == nullptr || pNpc->GetProtoID() != sid) continue; return pNpc; }
void CAISocket::RecvNpcInOut(char* pBuf) { int index = 0, nid = 0, nType = 0; float fx = 0.0f, fz=0.0f, fy=0.0f; nType = GetByte( pBuf, index ); nid = GetShort(pBuf, index); fx = Getfloat( pBuf, index ); fz = Getfloat( pBuf, index ); fy = Getfloat( pBuf, index ); if(nid >= NPC_BAND) { CNpc* pNpc = m_pMain->m_arNpcArray.GetData(nid); if(!pNpc) return; pNpc->NpcInOut( nType, fx, fz, fy ); } }
void CUser::Attack(int sid, int tid) { CNpc* pNpc = m_pMain->m_arNpc.GetData(tid-NPC_BAND); if(pNpc == NULL) return; if(pNpc->m_NpcState == NPC_DEAD) return; if(pNpc->m_iHP == 0) return; /* if(pNpc->m_tNpcType == NPCTYPE_GUARD) // 경비병이면 타겟을 해당 유저로 { pNpc->m_Target.id = m_iUserId + USER_BAND; pNpc->m_Target.x = m_curx; pNpc->m_Target.y = m_cury; pNpc->m_Target.failCount = 0; pNpc->Attack(m_pIocport); // return; } */ int nDefence = 0, nFinalDamage = 0; // NPC 방어값 nDefence = pNpc->GetDefense(); // 명중이면 //Damage 처리 ----------------------------------------------------------------// nFinalDamage = GetDamage(tid); if( m_pMain->m_byTestMode ) nFinalDamage = 3000; // sungyong test // Calculate Target HP -------------------------------------------------------// short sOldNpcHP = pNpc->m_iHP; if(pNpc->SetDamage(0, nFinalDamage, m_strUserID, m_iUserId + USER_BAND, m_pIocport) == FALSE) { // Npc가 죽은 경우,, pNpc->SendExpToUserList(); // 경험치 분배!! pNpc->SendDead(m_pIocport); SendAttackSuccess(tid, ATTACK_TARGET_DEAD, nFinalDamage, pNpc->m_iHP); // CheckMaxValue(m_dwXP, 1); // 몹이 죽을때만 1 증가! // SendXP(); } else { // 공격 결과 전송 SendAttackSuccess(tid, ATTACK_SUCCESS, nFinalDamage, pNpc->m_iHP); } // m_dwLastAttackTime = GetTickCount(); }
uint8 CMagicProcess::ExecuteType2(int magicid, int tid, int data1, int data2, int data3) { Packet result(AG_MAGIC_ATTACK_RESULT, uint8(MAGIC_EFFECTING)); int damage = m_pSrcUser->GetDamage(tid, magicid);; uint8 bResult = 1; result << magicid << m_pSrcUser->m_iUserId << tid << data1; if (damage > 0){ CNpc* pNpc = nullptr ; // Pointer initialization! pNpc = g_pMain->m_arNpc.GetData(tid-NPC_BAND); if(pNpc == nullptr || pNpc->m_NpcState == NPC_DEAD || pNpc->m_iHP == 0) { bResult = 0; goto packet_send; } if (!pNpc->SetDamage(magicid, damage, m_pSrcUser->m_strUserID, m_pSrcUser->m_iUserId + USER_BAND)) { result << int16(bResult) << data3 << int16(0) << int16(0) << int16(0) << int16(damage == 0 ? -104 : 0); g_pMain->Send(&result); pNpc->SendExpToUserList(); // 경험치 분배!! pNpc->SendDead(); m_pSrcUser->SendAttackSuccess(tid, MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP); //m_pSrcUser->SendAttackSuccess(tid, ATTACK_TARGET_DEAD, damage, pNpc->m_iHP); return bResult; } else { // 공격 결과 전송 m_pSrcUser->SendAttackSuccess(tid, ATTACK_SUCCESS, damage, pNpc->m_iHP); } } // else // result = 0; packet_send: // this is a little redundant but leaving it in just in case order is intended // this should all be removed eventually anyway... result << int16(bResult) << data3 << int16(0) << int16(0) << int16(0) << int16(damage == 0 ? -104 : 0); g_pMain->Send(&result); return bResult; }
uint8 CMagicProcess::ExecuteType1(int magicid, int tid, int data1, int data2, int data3, uint8 sequence) // Applied to an attack skill using a weapon. { int damage = 0; uint8 bResult = 1; // Variable initialization. result == 1 : success, 0 : fail _MAGIC_TABLE* pMagic = g_pMain->m_MagictableArray.GetData( magicid ); // Get main magic table. if( !pMagic ) return 0; damage = m_pSrcUser->GetDamage(tid, magicid); // Get damage points of enemy. // if(damage <= 0) damage = 1; //TRACE("magictype1 ,, magicid=%d, damage=%d\n", magicid, damage); // if (damage > 0) { CNpc* pNpc = nullptr ; // Pointer initialization! pNpc = g_pMain->m_arNpc.GetData(tid-NPC_BAND); if(pNpc == nullptr || pNpc->m_NpcState == NPC_DEAD || pNpc->m_iHP == 0) { bResult = 0; goto packet_send; } if(pNpc->SetDamage(magicid, damage, m_pSrcUser->m_strUserID, m_pSrcUser->m_iUserId + USER_BAND) == false) { // Npc가 죽은 경우,, pNpc->SendExpToUserList(); // 경험치 분배!! pNpc->SendDead(); //m_pSrcUser->SendAttackSuccess(tid, MAGIC_ATTACK_TARGET_DEAD, 0, pNpc->m_iHP); m_pSrcUser->SendAttackSuccess(tid, ATTACK_TARGET_DEAD, damage, pNpc->m_iHP); } else { // 공격 결과 전송 m_pSrcUser->SendAttackSuccess(tid, ATTACK_SUCCESS, damage, pNpc->m_iHP); } packet_send: if (pMagic->bType[1] == 0 || pMagic->bType[1] == 1) { Packet result(AG_MAGIC_ATTACK_RESULT, uint8(MAGIC_EFFECTING)); result << magicid << m_pSrcUser->m_iUserId << int16(tid) << int16(data1) << uint8(bResult) << int16(data3) << int16(0) << int16(0) << int16(0) << int16(damage == 0 ? -104 : 0); g_pMain->Send(&result); } return bResult; }
bool OnGS2C_LookInfoNpc(struct pk::GS2C_LookInfoNpc *value) { if ( !gMap ) { return false; } CNpc* pNPC = CNpc::create(); if ( pNPC ) { pNPC->SetId(value->id); //pNPC->SetDataID(value->npc_data_id); pNPC->SetDataID(1000000); pNPC->EnterMap(gMap,value->x,value->y); } return true; }
BOOL CServerDlg::CreateNpcThread() { m_TotalNPC = m_sMapEventNpc; m_CurrentNPC = 0; m_CurrentNPCError = 0; LOAD_TABLE_ERROR_ONLY(CNpcPosSet, &m_GameDB, NULL, false); int step = 0, nThreadNumber = 0; CNpcThread* pNpcThread = NULL; DWORD id; foreach_stlmap (itr, m_arNpc) { if (step == 0) pNpcThread = new CNpcThread; CNpc *pNpc = pNpcThread->m_pNpc[step] = itr->second; pNpc->m_sThreadNumber = nThreadNumber; pNpc->Init(); ++step; if( step == NPC_NUM ) { pNpcThread->m_sThreadNumber = nThreadNumber++; pNpcThread->m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&NpcThreadProc, &(pNpcThread->m_ThreadInfo), CREATE_SUSPENDED, &id); m_arNpcThread.push_back( pNpcThread ); step = 0; } } if( step != 0 ) { pNpcThread->m_sThreadNumber = nThreadNumber++; pNpcThread->m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&NpcThreadProc, &(pNpcThread->m_ThreadInfo), CREATE_SUSPENDED, &id); m_arNpcThread.push_back( pNpcThread ); } m_hZoneEventThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ZoneEventThreadProc, (LPVOID)(this), CREATE_SUSPENDED, &id); printf("[Monster Init - %d, threads=%d]\n", m_TotalNPC, m_arNpcThread.size()); return TRUE; }
void CAISocket::RecvMagicAttackResult(Packet & pkt) { uint32 magicid; uint16 sid, tid; uint8 byCommand; /* This is all so redundant... When everything's switched over to pass in Packets we can just pass it through directly! As it is now.. we still need a length (which we can hardcode, but meh) */ pkt >> byCommand >> magicid >> sid >> tid; pkt.SetOpcode(WIZ_MAGIC_PROCESS); if (byCommand == MAGIC_CASTING || (byCommand == MAGIC_EFFECTING && sid >= NPC_BAND && tid >= NPC_BAND)) { CNpc *pNpc = g_pMain->m_arNpcArray.GetData(sid); if (!pNpc) return; pNpc->SendToRegion(&pkt); } else if (byCommand == MAGIC_EFFECTING) { if (sid >= USER_BAND && sid < NPC_BAND) { CUser *pUser = g_pMain->GetUserPtr(sid); if (pUser == NULL || pUser->isDead()) return; pUser->SendToRegion(&pkt); return; } // If we're an NPC, casting a skill (rather, it's finished casting) on a player... pkt.rpos(0); m_MagicProcess.MagicPacket(pkt); } }
void CAISocket::RecvNpcMoveResult(Packet & pkt) { uint8 flag; // 01(INFO_MODIFY), 02(INFO_DELETE) uint16 sNid; float fX, fY, fZ, fSecForMetor; pkt >> flag >> sNid >> fX >> fZ >> fY >> fSecForMetor; CNpc * pNpc = g_pMain->GetNpcPtr(sNid); if (pNpc == nullptr) return; if (pNpc->isDead()) { Packet result(AG_NPC_HP_REQ); result << sNid << pNpc->m_iHP; Send(&result); } pNpc->MoveResult(fX, fY, fZ, fSecForMetor); }
void CGameSocket::RecvNpcHpChange(Packet & pkt) { int16 nid, sAttackerID; int32 nHP, nAmount; pkt >> nid >> sAttackerID >> nHP >> nAmount; CNpc * pNpc = g_pMain->m_arNpc.GetData(nid); if (pNpc == nullptr) return; if (nAmount < 0) { pNpc->SetDamage(0, -nAmount, sAttackerID, 1); } else { pNpc->m_iHP += nAmount; if (pNpc->m_iHP > pNpc->m_iMaxHP) pNpc->m_iHP = pNpc->m_iMaxHP; } }
void CGameSocket::RecvBattleEvent(char* pBuf) { int index = 0, i=0; int nType = 0, nEvent = 0; CNpc* pNpc = NULL; nType = GetByte(pBuf,index); nEvent = GetByte(pBuf,index); if( nEvent == BATTLEZONE_OPEN ) { m_pMain->m_sKillKarusNpc = 0; m_pMain->m_sKillElmoNpc = 0; m_pMain->m_byBattleEvent = BATTLEZONE_OPEN; TRACE("----> RecvBattleEvent : Battle zone Open \n"); } else if( nEvent == BATTLEZONE_CLOSE ) { m_pMain->m_sKillKarusNpc = 0; m_pMain->m_sKillElmoNpc = 0; m_pMain->m_byBattleEvent = BATTLEZONE_CLOSE; TRACE("<---- RecvBattleEvent : Battle zone Close \n"); m_pMain->ResetBattleZone(); } int nSize = m_pMain->m_arNpc.GetSize(); for( i = 0; i < nSize; i++) { pNpc = m_pMain->m_arNpc.GetData( i ); if( !pNpc ) continue; if( pNpc->m_tNpcType > 10 && (pNpc->m_byGroup == KARUS_ZONE || pNpc->m_byGroup == ELMORAD_ZONE) ) { // npc에만 적용되고, 국가에 소속된 npc if( nEvent == BATTLEZONE_OPEN ) { // 전쟁 이벤트 시작 (npc의 능력치 다운) pNpc->ChangeAbility( BATTLEZONE_OPEN ); } else if( nEvent == BATTLEZONE_CLOSE ) { // 전쟁 이벤트 끝 (npc의 능력치 회복) pNpc->ChangeAbility( BATTLEZONE_CLOSE ); } } } }
void CUser::Attack(int sid, int tid) { CNpc* pNpc = g_pMain->m_arNpc.GetData(tid-NPC_BAND); if(pNpc == nullptr) return; if(pNpc->m_NpcState == NPC_DEAD) return; if(pNpc->m_iHP == 0) return; /* if(pNpc->m_proto->m_tNpcType == NPCTYPE_GUARD) // 경비병이면 타겟을 해당 유저로 { pNpc->m_Target.id = m_iUserId + USER_BAND; pNpc->m_Target.x = m_curx; pNpc->m_Target.y = m_cury; pNpc->m_Target.failCount = 0; pNpc->Attack(); // return; } */ int nDefence = 0, nFinalDamage = 0; // NPC 방어값 nDefence = pNpc->GetDefense(); // 명중이면 //Damage 처리 ----------------------------------------------------------------// nFinalDamage = GetDamage(tid); // Calculate Target HP -------------------------------------------------------// short sOldNpcHP = pNpc->m_iHP; if(pNpc->SetDamage(0, nFinalDamage, m_strUserID, m_iUserId + USER_BAND) == false) { // Npc가 죽은 경우,, pNpc->SendExpToUserList(); // 경험치 분배!! pNpc->SendDead(); SendAttackSuccess(tid, ATTACK_TARGET_DEAD, nFinalDamage, pNpc->m_iHP); } else { // 공격 결과 전송 SendAttackSuccess(tid, ATTACK_SUCCESS, nFinalDamage, pNpc->m_iHP); } }
void CGameSocket::RecvNpcHpChange(Packet & pkt) { int16 nid, sAttackerID; int32 nHP, nAmount; uint8 attributeType = AttributeNone; pkt >> nid >> sAttackerID >> nHP >> nAmount >> attributeType; CNpc * pNpc = g_pMain->GetNpcPtr(nid); if (pNpc == nullptr) return; if (nAmount < 0) { pNpc->RecvAttackReq(-nAmount, sAttackerID, (AttributeType) attributeType); } else { pNpc->m_iHP += nAmount; if (pNpc->m_iHP > pNpc->m_iMaxHP) pNpc->m_iHP = pNpc->m_iMaxHP; } }
void CAISocket::RecvNpcAttack(Packet & pkt) { CNpc * pAttacker; Unit * pTarget; uint16 sAttackerID, sTargetID; int16 sDamage; uint8 bResult = ATTACK_FAIL; pkt >> sAttackerID >> sTargetID; pAttacker = g_pMain->GetNpcPtr(sAttackerID); pTarget = g_pMain->GetUnitPtr(sTargetID); if (pAttacker == nullptr || pAttacker->isPlayer() || pTarget == nullptr || pAttacker->isDead() || pTarget->isDead()) return; // TO-DO: Wrap this up into its own virtual method sDamage = pAttacker->GetDamage(pTarget); if (sDamage > 0) { pTarget->HpChange(-(sDamage), pAttacker); if (pTarget->isDead()) bResult = ATTACK_TARGET_DEAD; else bResult = ATTACK_SUCCESS; // Every hit takes a little of the defender's armour durability. if (pTarget->isPlayer()) TO_USER(pTarget)->ItemWoreOut(DEFENCE, sDamage); } Packet result(WIZ_ATTACK, uint8(DIRECT_ATTACK)); result << bResult << sAttackerID << sTargetID; pAttacker->SendToRegion(&result); }
bool CServerDlg::CreateNpcThread() { m_TotalNPC = m_sMapEventNpc; m_CurrentNPC = 0; LOAD_TABLE_ERROR_ONLY(CNpcPosSet, &m_GameDB, nullptr, false); foreach_stlmap (itr, g_arZone) { CNpcThread * pNpcThread = new CNpcThread; m_arNpcThread.push_back(pNpcThread); foreach_stlmap (npcItr, m_arNpc) { if (npcItr->second->m_bCurZone != itr->first) continue; CNpc * pNpc = npcItr->second; pNpc->Init(); pNpcThread->m_pNpcs.insert(pNpc); } }
void CAISocket::InitEventMonster(int index) { int count = index; if( count < 0 || count > NPC_BAND ) { TRACE("### InitEventMonster index Fail = %d ###\n", index); return; } int max_eventmop = count+EVENT_MONSTER; for( int i=count; i<max_eventmop; i++ ) { CNpc* pNpc = new CNpc(); pNpc->m_sNid = i+NPC_BAND; //TRACE("InitEventMonster : uid = %d\n", pNpc->m_sNid); if (!g_pMain->m_arNpcArray.PutData(pNpc->GetID(), pNpc)) { TRACE("Npc PutData Fail - %d\n", pNpc->GetID()); pNpc->DecRef(); } } count = g_pMain->m_arNpcArray.GetSize(); TRACE("TotalMonster = %d\n", count); }
/** * @brief Executes the death action. * * @param pKiller The killer. */ void CNpc::OnDeath(Unit *pKiller) { if (m_NpcState == NPC_DEAD) return; ASSERT(GetMap() != nullptr); ASSERT(GetRegion() != nullptr); m_NpcState = NPC_DEAD; if (m_byObjectType == SPECIAL_OBJECT) { _OBJECT_EVENT *pEvent = GetMap()->GetObjectEvent(GetProtoID()); if (pEvent != nullptr) pEvent->byLife = 0; } Unit::OnDeath(pKiller); CNpc * pNpc = TO_NPC(this); CUser * pUser = TO_USER(pKiller); if (pNpc != nullptr && pUser != nullptr) { if (pNpc->isMonster() && pUser->isPlayer()) { if (pNpc->m_sSid == 700 || pNpc->m_sSid == 750) { if (pUser->CheckExistEvent(STARTER_SEED_QUEST, 0) || pUser->CheckExistEvent(STARTER_SEED_QUEST, 1)) pUser->SaveEvent(STARTER_SEED_QUEST, 2); } } } GetRegion()->Remove(TO_NPC(this)); SetRegion(); }
bool CServerDlg::CreateNpcThread() { m_TotalNPC = m_sMapEventNpc; m_CurrentNPC = 0; LOAD_TABLE_ERROR_ONLY(CNpcPosSet, &m_GameDB, nullptr, false); FastGuard lock(m_eventThreadLock); foreach_stlmap (itr, g_arZone) { CNpcThread * pNpcThread = new CNpcThread(); m_arNpcThread.insert(make_pair(itr->first, pNpcThread)); m_arEventNpcThread.insert(make_pair(itr->first, new CNpcThread())); foreach_stlmap (npcItr, m_arNpc) { if (npcItr->second->GetZoneID() != itr->first) continue; CNpc * pNpc = npcItr->second; pNpc->Init(); pNpcThread->m_pNpcs.insert(pNpc); } }
void CAISocket::RecvNpcDead(char* pBuf) { int index = 0, send_index = 0; int nid = 0; char send_buff[256]; _OBJECT_EVENT* pEvent = NULL; nid = GetShort(pBuf,index); if(nid >= NPC_BAND) { CNpc* pNpc = m_pMain->m_arNpcArray.GetData(nid); if(!pNpc) return; C3DMap* pMap = pNpc->GetMap(); if (pMap == NULL) return; if( pNpc->m_byObjectType == SPECIAL_OBJECT ) { pEvent = pMap->GetObjectEvent( pNpc->m_sSid ); if( pEvent ) pEvent->byLife = 0; } //pNpc->NpcInOut( NPC_OUT ); //TRACE("RecvNpcDead - (%d,%s)\n", pNpc->m_sNid, pNpc->m_strName); pMap->RegionNpcRemove(pNpc->m_sRegion_X, pNpc->m_sRegion_Z, nid); //TRACE("--- RecvNpcDead : Npc를 Region에서 삭제처리.. ,, zone=%d, region_x=%d, y=%d\n", pNpc->m_sZoneIndex, pNpc->m_sRegion_X, pNpc->m_sRegion_Z); SetByte( send_buff, WIZ_DEAD, send_index ); SetShort( send_buff, nid, send_index ); m_pMain->Send_Region(send_buff, send_index, pNpc->GetMap(), pNpc->m_sRegion_X, pNpc->m_sRegion_Z, NULL, false); pNpc->m_sRegion_X = 0; pNpc->m_sRegion_Z = 0; } }
bool CLevel::loadNW(CString& pFileName) { CStringList levelData; CString version; char* dataFile = getDataFile(pFileName.text()); if(!strlen(dataFile)) return false; if(!levelData.load(dataFile)) return false; if(levelData.count() < 1) return false; version = levelData[0]; modTime = getFileModTime(dataFile); fileName = pFileName; if(version == "GLEVNW01" || version == "GSERVL01") { for(int i = 1; i < levelData.count(); i ++) { CStringList words; words.load(levelData[i].text(), " "); if(words.count() <= 0) continue; if(words[0] == "BOARD") { if(words.count() <= 5) continue; int x = atoi(words[1].text()); int y = atoi(words[2].text()); int w = atoi(words[3].text()); CString& data = words[5]; if(x >= 0 && x <= 64 && y >= 0 && y <= 64 && w > 0 && x + w <= 64) { if(data.length() >= w*2) { for(int ii = x; ii < x + w; ii++) { char left = data.readChar(); char top = data.readChar(); short tile = base64.find(left) << 6; tile += base64.find(top); tiles[ii + y*64] = tile; } } } } else if(words[0] == "LINK") { if(words.count() <= 7) continue; if(strlen(getDataFile(words[1].text()))) { links.add(new CLink(words[1], atoi(words[2].text()), atoi(words[3].text()), atoi(words[4].text()), atoi(words[5].text()), words[6], words[7])); } } else if(words[0] == "CHEST") { if(words.count() <= 4) continue; for(int ii = 0; ii < itemcount; ii++) { if(words[3] == itemNames[ii]) { chests.add(new CChest(atoi(words[1].text()), atoi(words[2].text()), atoi(words[4].text()), ii)); break; } } } else if(words[0] == "NPC") { if(words.count() <= 3) continue; CString image, code, code2; float x, y; if(words[1] != "-") image = words[1]; x = (float)atof(words[2].text()); y = (float)atof(words[3].text()); for(i++; i < levelData.count() && levelData[i] != "NPCEND"; i++) code << levelData[i] << "\xa7"; // Create the new NPC. Do this before parsing the join commands. // The CNpc constructor will remove all comments. CNpc* jnpc = new CNpc( image, code, x, y, this, true ); // Now filter out the join commands. CStringList npcData; npcData.load( jnpc->clientCode.text(), "\xa7" ); for ( int j = 0; j < npcData.count(); ++j ) code2 << processNpcLine( npcData[j] ) << "\xa7"; jnpc->clientCode = code2; // Now, add all the joined files to the code. if ( joinList.count() > 0 ) { CString* file = 0; while ( (file = (CString*)joinList[0]) != 0 ) { // Load the source file into memory. CString dataFile = getDataFile(file->text()); if(dataFile.length()) { // Append to the end of the script. CString retVal; retVal.load(dataFile.text()); retVal.replaceAll("\r\n", "\xa7"); retVal.replaceAll("\n", "\xa7"); jnpc->clientCode << retVal << "\xa7"; } delete (CString*)joinList[0]; joinList.remove(0); } } joinList.clear(); npcs.add( jnpc ); } else if(words[0] == "BADDY") { if(words.count() <= 3) continue; int x = atoi(words[1].text()); int y = atoi(words[2].text()); int type = atoi(words[3].text()); CBaddy* baddy = new CBaddy(x, y, type); int baddyId = createBaddyId(baddy); baddy->id = baddyId; for(i++; i < levelData.count() && levelData[i] != "BADDYEND"; i++) baddy->verses.add(levelData[i].text()); if(baddies.count() < 50) baddies.add(baddy); else delete baddy; } else if(words[0] == "SIGN") { if(words.count() <= 2) continue; CString sign; int x = atoi(words[1].text()); int y = atoi(words[2].text()); sign.writeChar(x+32); sign.writeChar(y+32); for (i++; i < levelData.count() && levelData[i] != "SIGNEND"; i++) sign << getSignCode(CString() << levelData[i] << "\n"); signs.add(sign); } else if(words[0] == "REPLACENPC") { int npcId = atoi(words[1].text()); CNpc* npc = (CNpc*)npcs[npcId]; if(npc == NULL) continue; for(i++; i < levelData.count() && levelData[i] != "REPLACENPCEND"; i++) npc->setProps((CPacket&)levelData[i]); } } } else return false; return true; }
// Npc Thread 를 만든다. BOOL CServerDlg::CreateNpcThread() { BOOL bMoveNext = TRUE; int nSerial = m_sMapEventNpc; int nPathSerial = 1; int nNpcCount = 0; int i=0, j=0; int nRandom = 0, nServerNum = 0; double dbSpeed = 0; m_TotalNPC = 0; // DB에 있는 수 m_CurrentNPC = 0; m_CurrentNPCError = 0; CNpcTable* pNpcTable = NULL; CRoomEvent* pRoom = NULL; CNpcPosSet NpcPosSet; char szPath[500]; char szX[5]; char szZ[5]; float fRandom_X = 0.0f; float fRandom_Z = 0.0f; int nMonsterNumber = 0; try { if(NpcPosSet.IsOpen()) NpcPosSet.Close(); if(!NpcPosSet.Open()) { AfxMessageBox(_T("MONSTER_POS DB Open Fail!")); return FALSE; } if(NpcPosSet.IsBOF()) { AfxMessageBox(_T("MONSTER_POS DB Empty!")); return FALSE; } NpcPosSet.MoveFirst(); while(!NpcPosSet.IsEOF()) { nMonsterNumber = NpcPosSet.m_NumNPC; //if( NpcPosSet.m_ZoneID == 101 ) { // 테스트를 위해서,, // nMonsterNumber = 1; //if(nMonsterNumber > 4) { // nMonsterNumber = nMonsterNumber / 4; //} //} nServerNum = 0; nServerNum = GetServerNumber( NpcPosSet.m_ZoneID ); if( m_byZone == nServerNum || m_byZone == UNIFY_ZONE) { for(j=0; j<nMonsterNumber; j++) { CNpc* pNpc = new CNpc(); pNpc->m_byMoveType = NpcPosSet.m_ActType; pNpc->m_byInitMoveType = NpcPosSet.m_ActType; bool bMonster = (NpcPosSet.m_ActType < 100); if (bMonster) pNpcTable = m_arMonTable.GetData(NpcPosSet.m_NpcID); else { pNpc->m_byMoveType = NpcPosSet.m_ActType - 100; //pNpc->m_byInitMoveType = NpcPosSet.m_ActType - 100; pNpcTable = m_arNpcTable.GetData(NpcPosSet.m_NpcID); } if (pNpcTable == NULL) { char buff[128] = {0}; sprintf(buff, "NPC %d not found in %s table.", pNpc->m_sNid, bMonster ? "K_MONSTER" : "K_NPC"); AfxMessageBox(buff); delete pNpc; return FALSE; } pNpc->Load(nSerial++, pNpcTable); pNpc->m_byBattlePos = 0; if(pNpc->m_byMoveType >= 2) { pNpc->m_byBattlePos = myrand( 1, 3 ); pNpc->m_byPathCount = nPathSerial++; } pNpc->InitPos(); if( bMoveNext ) { bMoveNext = FALSE; nNpcCount = NpcPosSet.m_NumNPC; } //////// MONSTER POS //////////////////////////////////////// pNpc->m_bCurZone = NpcPosSet.m_ZoneID; // map에 몬스터의 위치를 랜덤하게 위치시킨다.. (테스트 용 : 수정-DB에서 읽어오는데로 몬 위치 결정) nRandom = abs(NpcPosSet.m_LeftX - NpcPosSet.m_RightX); if(nRandom <= 1) fRandom_X = (float)NpcPosSet.m_LeftX; else { if(NpcPosSet.m_LeftX < NpcPosSet.m_RightX) fRandom_X = (float)myrand(NpcPosSet.m_LeftX, NpcPosSet.m_RightX); else fRandom_X = (float)myrand(NpcPosSet.m_RightX, NpcPosSet.m_LeftX); } nRandom = abs(NpcPosSet.m_TopZ - NpcPosSet.m_BottomZ); if(nRandom <= 1) fRandom_Z = (float)NpcPosSet.m_TopZ; else { if(NpcPosSet.m_TopZ < NpcPosSet.m_BottomZ) fRandom_Z = (float)myrand(NpcPosSet.m_TopZ, NpcPosSet.m_BottomZ); else fRandom_Z = (float)myrand(NpcPosSet.m_BottomZ, NpcPosSet.m_TopZ); } pNpc->m_fCurX = fRandom_X; pNpc->m_fCurY = 0; pNpc->m_fCurZ = fRandom_Z; pNpc->m_sRegenTime = NpcPosSet.m_RegTime * 1000; // 초(DB)단위-> 밀리세컨드로 pNpc->m_byDirection = NpcPosSet.m_byDirection; pNpc->m_sMaxPathCount = NpcPosSet.m_DotCnt; if( pNpc->m_byMoveType >= 2 && NpcPosSet.m_DotCnt == 0 ) { pNpc->m_byMoveType = 1; TRACE("##### ServerDlg:CreateNpcThread - Path type Error : nid=%d, sid=%d, name=%s, acttype=%d, path=%d #####\n", pNpc->m_sNid+NPC_BAND, pNpc->m_proto->m_sSid, pNpc->m_proto->m_strName, pNpc->m_byMoveType, pNpc->m_sMaxPathCount); } int index = 0; strcpy_s(szPath, sizeof(szPath), NpcPosSet.m_path); if(NpcPosSet.m_DotCnt != 0) { for(int l = 0; l<NpcPosSet.m_DotCnt; l++) { memset(szX, 0x00, 5); memset(szZ, 0x00, 5); GetString(szX, szPath, 4, index); GetString(szZ, szPath, 4, index); pNpc->m_PathList.pPattenPos[l].x = atoi(szX); pNpc->m_PathList.pPattenPos[l].z = atoi(szZ); // TRACE(" l=%d, x=%d, z=%d\n", l, pNpc->m_PathList.pPattenPos[l].x, pNpc->m_PathList.pPattenPos[l].z); } } //pNpc->m_byType = NpcPosSet.m_byType; pNpc->m_tItemPer = pNpcTable->m_tItemPer; // NPC Type pNpc->m_tDnPer = pNpcTable->m_tDnPer; // NPC Type pNpc->m_nInitMinX = pNpc->m_nLimitMinX = NpcPosSet.m_LeftX; pNpc->m_nInitMinY = pNpc->m_nLimitMinZ = NpcPosSet.m_TopZ; pNpc->m_nInitMaxX = pNpc->m_nLimitMaxX = NpcPosSet.m_RightX; pNpc->m_nInitMaxY = pNpc->m_nLimitMaxZ = NpcPosSet.m_BottomZ; // dungeon work pNpc->m_byDungeonFamily = NpcPosSet.m_DungeonFamily; pNpc->m_bySpecialType = NpcPosSet.m_SpecialType; pNpc->m_byRegenType = NpcPosSet.m_RegenType; pNpc->m_byTrapNumber = NpcPosSet.m_TrapNumber; if( pNpc->m_byDungeonFamily > 0 ) { pNpc->m_nLimitMinX = NpcPosSet.m_LimitMinX; pNpc->m_nLimitMinZ = NpcPosSet.m_LimitMinZ; pNpc->m_nLimitMaxX = NpcPosSet.m_LimitMaxX; pNpc->m_nLimitMaxZ = NpcPosSet.m_LimitMaxZ; } pNpc->m_pZone = GetZoneByID(pNpc->m_bCurZone); if (pNpc->GetMap() == NULL) { AfxMessageBox("Error : CServerDlg,, Invaild zone Index!!"); delete pNpc; return FALSE; } if( !m_arNpc.PutData( pNpc->m_sNid, pNpc) ) { TRACE("Npc PutData Fail - %d\n", pNpc->m_sNid); delete pNpc; pNpc = NULL; continue; } pNpc->SetUid(pNpc->m_fCurX, pNpc->m_fCurZ, pNpc->m_sNid + NPC_BAND); // if (pNpc->GetMap()->m_byRoomEvent > 0 && pNpc->m_byDungeonFamily > 0 ) { pRoom = pNpc->GetMap()->m_arRoomEventArray.GetData( pNpc->m_byDungeonFamily ); if (pRoom == NULL) { TRACE("Error : CServerDlg,, Map Room Npc Fail!! : nid=%d, sid=%d, name=%s, fam=%d, zone=%d\n", pNpc->m_sNid+NPC_BAND, pNpc->m_proto->m_sSid, pNpc->m_proto->m_strName, pNpc->m_byDungeonFamily, pNpc->m_bCurZone); AfxMessageBox("Error : CServerDlg,, Map Room Npc Fail!!"); delete pNpc; return FALSE; } int *pInt = new int; *pInt = pNpc->m_sNid; if( !pRoom->m_mapRoomNpcArray.PutData( pNpc->m_sNid, pInt ) ) { TRACE("### Map - Room Array MonsterNid Fail : nid=%d, sid=%d ###\n", pNpc->m_sNid, pNpc->m_proto->m_sSid); } } m_TotalNPC = nSerial; if(--nNpcCount > 0) continue; bMoveNext = TRUE; nNpcCount = 0; } } nPathSerial = 1; NpcPosSet.MoveNext(); } NpcPosSet.Close(); } catch(CDBException* e) { e->ReportError(); e->Delete(); return FALSE; } int step = 0, nThreadNumber = 0; CNpcThread* pNpcThread = NULL; foreach_stlmap (itr, m_arNpc) { if (step == 0) pNpcThread = new CNpcThread; CNpc *pNpc = pNpcThread->m_pNpc[step] = itr->second; pNpc->m_sThreadNumber = nThreadNumber; pNpc->Init(); ++step; if( step == NPC_NUM ) { pNpcThread->m_sThreadNumber = nThreadNumber++; pNpcThread->m_pThread = AfxBeginThread(NpcThreadProc, &(pNpcThread->m_ThreadInfo), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); m_arNpcThread.push_back( pNpcThread ); step = 0; } } if( step != 0 ) { pNpcThread->m_sThreadNumber = nThreadNumber++; pNpcThread->m_pThread = AfxBeginThread(NpcThreadProc, &(pNpcThread->m_ThreadInfo), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); m_arNpcThread.push_back( pNpcThread ); } m_pZoneEventThread = AfxBeginThread(ZoneEventThreadProc, (LPVOID)(this), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); //TRACE("m_TotalNPC = %d \n", m_TotalNPC); AddToList("[Monster Init - %d, threads=%d]", m_TotalNPC, m_arNpcThread.size()); return TRUE; }
void cCookManager::Cook_Syn(void* pMsg) { WORD wResult = eCookError_None; MSG_COOK_SYN* pmsg = (MSG_COOK_SYN*)pMsg; CPlayer* pPlayer = (CPlayer*)g_pUserTable->FindUser(pmsg->dwObjectID); if(pPlayer) { // 스피드핵 체크 if(0 < pPlayer->GetLastCookTime()) { wResult=eCookError_InvaildState; goto COOK_NACK; } // 요리도구확인 WORD wCookUtilLevel = CheckCookUtil(pPlayer); if(!wCookUtilLevel) { wResult=eCookError_InvaildUtil; goto COOK_NACK; } // 레시피확인 stRecipeInfo* pRecipe = GetRecipeInfo(pmsg->dwRecipeIdx); if(!pRecipe) { wResult=eCookError_InvaildRecipe; goto COOK_NACK; } // 요리도구-레시피 레벨확인 if(wCookUtilLevel<eCOOKLEVEL3 && wCookUtilLevel<COOKMGR->GetCookLevelFromRecipe(pRecipe->dwRecipeIdx)) { wResult=eCookError_LowerUtil; goto COOK_NACK; } // 모닥불확인 CNpc* pFire = (CNpc*)g_pUserTable->FindUser(pmsg->dwFireNpcIdx); if(!pFire || eObjectKind_Npc!=pFire->GetObjectKind()) { wResult=eCookError_InvaildFire; goto COOK_NACK; } // 제작수량확인 if(pmsg->wMakeNum<1 || 99<pmsg->wMakeNum) { wResult=eCookError_InvaildMakeNum; goto COOK_NACK; } // 거리제한 VECTOR3 vHeroPos, vPlacePos; pPlayer->GetPosition(&vHeroPos) ; pFire->GetPosition(&vPlacePos); float fDistance = CalcDistanceXZ(&vHeroPos, &vPlacePos); if(MAX_COOKING_DISTANCE < fDistance) { wResult = eCookError_OverDistance; goto COOK_NACK; } CItemSlot* pInvenSlot = pPlayer->GetSlot(eItemTable_Inventory); if(0 == ITEMMGR->GetTotalEmptySlotNum(pInvenSlot, pPlayer)) { wResult = eCookError_InvenFull; goto COOK_NACK; } // 요리재료확인 및 소모 if(!CheckIngredients(pPlayer, pRecipe, pmsg->wMakeNum)) { wResult = eCookError_NeedIngredient; goto COOK_NACK; } // 숙련도확인 및 증가 WORD wCookCount = pPlayer->GetCookCount(); WORD wAddPoint = 0; if(pPlayer->GetCookLevel() == GetCookLevelFromRecipe(pRecipe->dwRecipeIdx)) { WORD wExpertPointMin = (WORD)pRecipe->dwExpertPointMin; WORD wExpertPointMax = (WORD)pRecipe->dwExpertPointMax; if(pPlayer->GetCookCount() < wExpertPointMin) { wResult = eCookError_LowerExpertPoint; goto COOK_NACK; } if(wExpertPointMax < wCookCount) wAddPoint = 0; else if(wExpertPointMax <= wCookCount+pmsg->wMakeNum) wAddPoint = wExpertPointMax - wCookCount; else wAddPoint = pmsg->wMakeNum; if(wCookCount+wAddPoint < COOKMGR->GetMaxCookCount(pPlayer->GetCookLevel())) pPlayer->SetCookCount(wCookCount + wAddPoint); else pPlayer->SetCookCount(COOKMGR->GetMaxCookCount(pPlayer->GetCookLevel())); } Cooking_Update(pPlayer); Cooking_Log(pPlayer->GetID(), eCookingLog_CookCount, pRecipe->dwRecipeIdx, wCookCount, wAddPoint, pPlayer->GetCookCount()); DWORD* pPlayerIdx = new DWORD; if(pPlayerIdx) { *pPlayerIdx = pPlayer->GetID(); pPlayer->SetLastCookTime(gCurTime); m_CookerList.Add(pPlayerIdx, *pPlayerIdx); } MSG_DWORD2 msgAck; msgAck.Category = MP_COOK; msgAck.Protocol = MP_COOK_ACK; msgAck.dwObjectID = pPlayer->GetID(); msgAck.dwData1 = pRecipe->dwRecipeIdx; msgAck.dwData2 = pmsg->wMakeNum; pPlayer->SendMsg(&msgAck, sizeof(msgAck)); MSG_DWORD4 msg; msg.Category = MP_COOK; msg.Protocol = MP_COOK_STATE; msg.dwObjectID = pPlayer->GetID(); msg.dwData1 = pPlayer->GetCookLevel(); msg.dwData2 = pPlayer->GetCookCount(); msg.dwData3 = pPlayer->GetEatCount(); msg.dwData4 = pPlayer->GetFireCount(); pPlayer->SendMsg(&msg, sizeof(msg)); return; } COOK_NACK: MSG_DWORD msg; msg.Category = MP_COOK; msg.Protocol = MP_COOK_NACK; msg.dwObjectID = pPlayer->GetID(); msg.dwData = wResult; PACKEDDATA_OBJ->QuickSend( pPlayer, &msg, sizeof( msg ) ); }
BOOL CRoomEvent::RunEvent( int event_num ) { CNpc* pNpc = NULL; int nOption_1 = 0, nOption_2 = 0; BOOL bRetValue = FALSE; switch( event_num ) { case 1: // 다른 몬스터의 출현 nOption_1 = m_Exec[ m_byLogicNumber-1 ].sOption_1; pNpc = GetNpcPtr( nOption_1 ); if( pNpc ) { pNpc->m_byChangeType = 3; // 몬스터 출현해주세여... pNpc->SetLive( &m_pMain->m_Iocport ); } else { TRACE("### RunEvent Error : 몬스터 출현 할 수 없당 = %d, logic=%d ###\n", nOption_1, m_byLogicNumber); } if( m_byCheck == m_byLogicNumber ) { // 방이 클리어 return TRUE; } else m_byLogicNumber++; break; case 2: // 문이 열림 nOption_1 = m_Exec[ m_byLogicNumber-1 ].sOption_1; pNpc = GetNpcPtr( nOption_1 ); if( pNpc ) { } else { TRACE("### RunEvent Error : 문 담당 몬스터 출현 할 수 없당 = %d, logic=%d ###\n", nOption_1, m_byLogicNumber); } //wsprintf(notify, "** 알림 : [%d] 문이 열립니다 **", m_sRoomNumber); //m_pMain->SendSystemMsg( notify, PUBLIC_CHAT, SEND_ALL); if( m_byCheck == m_byLogicNumber ) { // 방이 클리어 return TRUE; } else m_byLogicNumber++; break; case 3: // 다른 몬스터로 변환 if( m_byCheck == m_byLogicNumber ) { // 방이 클리어 return TRUE; } break; case 4: // 특정몬스터 옵션2의 마리수만큼 출현 nOption_1 = m_Exec[ m_byLogicNumber-1 ].sOption_1; nOption_2 = m_Exec[ m_byLogicNumber-1 ].sOption_2; bRetValue = CheckMonsterCount( nOption_1, nOption_2, 2 ); //wsprintf(notify, "** 알림 : [%d, %d] 몬스터 출현 **", nOption_1, nOption_2); //m_pMain->SendSystemMsg( notify, PUBLIC_CHAT, SEND_ALL); if( m_byCheck == m_byLogicNumber ) { // 방이 클리어 return TRUE; } else m_byLogicNumber++; break; case 100: // 특정몬스터 옵션2의 마리수만큼 출현 nOption_1 = m_Exec[ m_byLogicNumber-1 ].sOption_1; nOption_2 = m_Exec[ m_byLogicNumber-1 ].sOption_2; TRACE("RunEvent - room=%d, option1=%d, option2=%d\n", m_sRoomNumber, nOption_1, nOption_2); if( nOption_1 != 0 ) { EndEventSay( nOption_1, nOption_2 ); } if( m_byCheck == m_byLogicNumber ) { // 방이 클리어 return TRUE; } else m_byLogicNumber++; break; default: TRACE("### RunEvent Fail :: event number = %d ###\n", event_num); break; } return FALSE; }
void CAISocket::RecvNpcInfoAll(Packet & pkt) { uint8 bCount = pkt.read<uint8>(); // max of 20 pkt.SByte(); for (int i = 0; i < bCount; i++) { uint8 bDirection; std::string strName; CNpc* pNpc = new CNpc(); pNpc->Initialize(); pkt >> pNpc->m_NpcState >> pNpc->m_sNid >> pNpc->m_sSid >> pNpc->m_sPid >> pNpc->m_sSize >> pNpc->m_iWeapon_1 >> pNpc->m_iWeapon_2 >> pNpc->m_bZone >> strName >> pNpc->m_bNation >> pNpc->m_bLevel >> pNpc->m_curx >> pNpc->m_curz >> pNpc->m_cury >> bDirection >> pNpc->m_tNpcType >> pNpc->m_iSellingGroup >> pNpc->m_iMaxHP >> pNpc->m_iHP >> pNpc->m_byGateOpen >> pNpc->m_fTotalHitrate >> pNpc->m_fTotalEvasionrate >> pNpc->m_sTotalAc >> pNpc->m_sTotalHit >> pNpc->m_byObjectType >> pNpc->m_byTrapNumber >> pNpc->m_bMonster >> pNpc->m_sFireR >> pNpc->m_sColdR >> pNpc->m_sLightningR >> pNpc->m_sMagicR >> pNpc->m_sDiseaseR >> pNpc->m_sPoisonR; if (strName.empty()) strName = "<the spawn with no name>"; if (strName.length() > MAX_NPC_SIZE) { pNpc->DecRef(); continue; } pNpc->m_pMap = g_pMain->GetZoneByID(pNpc->GetZoneID()); if (pNpc->GetMap() == nullptr) { pNpc->DecRef(); continue; } //TRACE("Recv --> NpcUserInfo : uid = %d, x=%f, z=%f.. \n", nid, fPosX, fPosZ); pNpc->m_strName = strName; pNpc->m_byDirection = bDirection; pNpc->SetRegion(pNpc->GetNewRegionX(), pNpc->GetNewRegionZ()); if (pNpc->m_byObjectType == SPECIAL_OBJECT) { _OBJECT_EVENT* pEvent = pNpc->GetMap()->GetObjectEvent(pNpc->m_sSid); if (pEvent != nullptr) pEvent->byLife = 1; } // TRACE("Recv --> NpcUserInfoAll : uid=%d, sid=%d, name=%s, x=%f, z=%f. gate=%d, objecttype=%d \n", nid, sPid, szName, fPosX, fPosZ, byGateOpen, byObjectType); if (!g_pMain->m_arNpcArray.PutData(pNpc->GetID(), pNpc)) { TRACE("Npc PutData Fail - %d\n", pNpc->GetID()); pNpc->DecRef(); continue; } if (pNpc->m_NpcState == NPC_DEAD) { TRACE("Recv --> NpcUserInfoAll : nid=%d, sid=%d, name=%s\n", pNpc->GetID(), pNpc->m_sSid, strName.c_str()); continue; } pNpc->SendInOut(INOUT_IN, pNpc->GetX(), pNpc->GetZ(), pNpc->GetY()); } }
void CAISocket::RecvNpcInfo(Packet & pkt) { std::string strName; uint8 Mode, byDirection; uint16 sNid; bool bCreated = false; pkt.SByte(); pkt >> Mode >> sNid; CNpc *pNpc = g_pMain->GetNpcPtr(sNid); if (pNpc == nullptr) { pNpc = new CNpc(); pNpc->m_sNid = sNid; bCreated = true; } pkt >> pNpc->m_sSid >> pNpc->m_sPid >> pNpc->m_sSize >> pNpc->m_iWeapon_1 >> pNpc->m_iWeapon_2 >> pNpc->m_bZone >> strName >> pNpc->m_bNation >> pNpc->m_bLevel >> pNpc->m_curx >> pNpc->m_curz >> pNpc->m_cury >> byDirection >> pNpc->m_tNpcType >> pNpc->m_iSellingGroup >> pNpc->m_iMaxHP >> pNpc->m_iHP >> pNpc->m_byGateOpen >> pNpc->m_fTotalHitrate >> pNpc->m_fTotalEvasionrate >> pNpc->m_sTotalAc >> pNpc->m_sTotalHit >> pNpc->m_byObjectType >> pNpc->m_byTrapNumber >> pNpc->m_bMonster >> pNpc->m_sFireR >> pNpc->m_sColdR >> pNpc->m_sLightningR >> pNpc->m_sMagicR >> pNpc->m_sDiseaseR >> pNpc->m_sPoisonR; if (strName.empty() || strName.length() > MAX_NPC_SIZE) { pNpc->DecRef(); return; } pNpc->m_NpcState = Mode; pNpc->m_byDirection = byDirection; pNpc->m_strName = strName; pNpc->m_pMap = g_pMain->GetZoneByID(pNpc->GetZoneID()); if (pNpc->GetMap() == nullptr) { pNpc->DecRef(); return; } pNpc->RegisterRegion(); if (pNpc->m_byObjectType == SPECIAL_OBJECT) { _OBJECT_EVENT *pEvent = pNpc->GetMap()->GetObjectEvent( pNpc->m_sSid ); if (pEvent != nullptr) pEvent->byLife = 1; } if (bCreated) g_pMain->m_arNpcArray.PutData(pNpc->GetID(), pNpc); if (pNpc->m_NpcState == NPC_DEAD) { TRACE("RecvNpcInfo - dead monster nid=%d, name=%s\n", pNpc->GetID(), pNpc->GetName().c_str()); return; } pNpc->SendInOut(INOUT_IN, pNpc->GetX(), pNpc->GetZ(), pNpc->GetY()); }