#include "stdafx.h" #include "NpcThread.h" #include "Npc.h" #define DELAY 250 uint32 THREADCALL NpcThreadProc(void * pParam) { try { CNpcThread* pInfo = (CNpcThread *)pParam; if (!pInfo) return 0; CNpc *pNpc= nullptr; CNpc *pNpcList[32768]; time_t dwDiffTime = 0, dwTickTime = 0, fTime2 = 0; int nTempTotalNPC, NpcCount = 0; ThreadReloadNPC: NpcCount = 0; foreach (itr, pInfo->m_pNpcs) { pNpcList[NpcCount] = *itr; if (pNpcList[NpcCount] == nullptr) continue; NpcCount++; } nTempTotalNPC = g_pMain->m_TotalNPC; while (!g_bNpcExit) { fTime2 = getMSTime(); if (g_pMain->m_TotalNPC != nTempTotalNPC) goto ThreadReloadNPC; for (int x = 0; x < NpcCount; x++) { try { pNpc = nullptr; pNpc = pNpcList[x]; if (pNpc == nullptr) continue; if(pNpc->GetID() < 0) continue; dwTickTime = fTime2 - pNpc->m_fDelayTime; if (pNpc->m_Delay > (int)dwTickTime && !pNpc->m_bFirstLive && pNpc->m_Delay != 0) { if (pNpc->m_Delay < 0) pNpc->m_Delay = 0; if (pNpc->m_NpcState == NPC_STANDING && pNpc->CheckFindEnemy() && pNpc->FindEnemy()) { pNpc->m_NpcState = NPC_ATTACKING; pNpc->m_Delay = 0; } if (pNpc->GetName() != "Guard tower") continue; } dwTickTime = fTime2 - pNpc->m_fHPChangeTime; if (10000 < dwTickTime) pNpc->HpChange(); uint8 bState = pNpc->m_NpcState; time_t tDelay = -1; switch (bState) { case NPC_LIVE: tDelay = pNpc->NpcLive(); break; case NPC_STANDING: tDelay = pNpc->NpcStanding(); break; case NPC_MOVING: tDelay = pNpc->NpcMoving(); break; case NPC_ATTACKING: tDelay = pNpc->NpcAttacking(); break; case NPC_TRACING: tDelay = pNpc->NpcTracing(); break; case NPC_FIGHTING: tDelay = pNpc->Attack(); break; case NPC_BACK: tDelay = pNpc->NpcBack(); break; case NPC_STRATEGY: break; case NPC_DEAD: pNpc->m_NpcState = NPC_LIVE; break; case NPC_SLEEPING: tDelay = pNpc->NpcSleeping(); break; case NPC_FAINTING: tDelay = pNpc->NpcFainting(); break; case NPC_HEALING: tDelay = pNpc->NpcHealing(); break; case NPC_CASTING: tDelay = pNpc->NpcCasting(); break; } // This may not be necessary, but it keeps behaviour identical. if (bState != NPC_LIVE && bState != NPC_DEAD && pNpc->m_NpcState != NPC_DEAD) pNpc->m_fDelayTime = getMSTime(); if (tDelay >= 0) pNpc->m_Delay = tDelay; if (pNpc->m_bDelete) { uint16 myId = pNpc->GetID(); Guard lock(g_pMain->m_freeIdsLock); g_pMain->freeIDs.push_back(myId); pInfo->RemoveNPC(pNpc); g_pMain->m_arNpc.DeleteData(myId); --g_pMain->m_TotalNPC; goto ThreadReloadNPC; } } catch (std::system_error & ex) { printf("[ %s ] Warning 1 : %s\n", __FUNCTION__, ex.what()); continue; } } sleep(250); } } catch (std::system_error & ex) { printf("[ %s ] Warning 2 : %s\n", __FUNCTION__, ex.what()); } return 0; } uint32 THREADCALL ZoneEventThreadProc(void * pParam /* = nullptr */) { while (!g_bNpcExit) { foreach_stlmap_nolock (itr, g_pMain->g_arZone) { MAP *pMap = itr->second; if (pMap == nullptr || pMap->m_byRoomEvent == 0 || pMap->IsRoomStatusCheck()) continue; foreach_stlmap_nolock (itr, pMap->m_arRoomEventArray) { CRoomEvent * pRoom = itr->second; if (pRoom == nullptr || !pRoom->isInProgress()) continue; pRoom->MainRoom(); } } sleep(1000); } return 0; } void CNpcThread::AddNPC(CNpc * pNpc) { Guard lock(m_lock); m_pNpcs.insert(pNpc); } void CNpcThread::RemoveNPC(CNpc * pNpc) { Guard lock(m_lock); m_pNpcs.erase(pNpc); } CNpcThread::CNpcThread() { } CNpcThread::~CNpcThread() { Guard lock(m_lock); m_pNpcs.clear(); }