#include "stdafx.h" #include "utils.h" #include "config.h" #include "questmanager.h" #include "sectree_manager.h" #include "char.h" #include "char_manager.h" #include "desc.h" #include "packet.h" #include "target.h" ///////////////////////////////////////////////////////////////////// // Packet ///////////////////////////////////////////////////////////////////// void SendTargetCreatePacket(LPDESC d, TargetInfo * info) { if (!info->bSendToClient) return; TPacketGCTargetCreate pck; pck.bHeader = HEADER_GC_TARGET_CREATE; pck.lID = info->iID; pck.bType = info->iType; pck.dwVID = info->iArg1; strncpy(pck.szName, info->szTargetDesc, sizeof(pck.szName)); d->Packet(&pck, sizeof(TPacketGCTargetCreate)); } void SendTargetUpdatePacket(LPDESC d, int iID, int x, int y) { TPacketGCTargetUpdate pck; pck.bHeader = HEADER_GC_TARGET_UPDATE; pck.lID = iID; pck.lX = x; pck.lY = y; d->Packet(&pck, sizeof(TPacketGCTargetUpdate)); sys_log(0, "SendTargetUpdatePacket %d %dx%d", iID, x, y); } void SendTargetDeletePacket(LPDESC d, int iID) { TPacketGCTargetDelete pck; pck.bHeader = HEADER_GC_TARGET_DELETE; pck.lID = iID; d->Packet(&pck, sizeof(TPacketGCTargetDelete)); } ///////////////////////////////////////////////////////////////////// CTargetManager::CTargetManager() : m_iID(0) { } CTargetManager::~CTargetManager() { } EVENTFUNC(target_event) { TargetInfo * info = dynamic_cast( event->info ); if ( info == NULL ) { sys_err( "target_event> Null pointer" ); return 0; } // Raplaced direct pointer reference with key searching. //LPCHARACTER pkChr = info->pkChr; LPCHARACTER pkChr = CHARACTER_MANAGER::instance().FindByPID(info->dwPID); if (pkChr == NULL) { return 0; // need to be confirmed } LPCHARACTER tch = NULL; int x = 0, y = 0; int iDist = 5000; if (info->iMapIndex != pkChr->GetMapIndex()) return std::clamp(iDist / (1500 / passes_per_sec), passes_per_sec / 2, passes_per_sec * 5); switch (info->iType) { case TARGET_TYPE_POS: x = info->iArg1; y = info->iArg2; iDist = DISTANCE_APPROX(pkChr->GetX() - x, pkChr->GetY() - y); break; case TARGET_TYPE_VID: { tch = CHARACTER_MANAGER::instance().Find(info->iArg1); if (tch && tch->GetMapIndex() == pkChr->GetMapIndex()) { x = tch->GetX(); y = tch->GetY(); iDist = DISTANCE_APPROX(pkChr->GetX() - x, pkChr->GetY() - y); } } break; } bool bRet = true; if (iDist <= 500) bRet = quest::CQuestManager::instance().Target(pkChr->GetPlayerID(), info->dwQuestIndex, info->szTargetName, "arrive"); if (!tch && info->iType == TARGET_TYPE_VID) { quest::CQuestManager::instance().Target(pkChr->GetPlayerID(), info->dwQuestIndex, info->szTargetName, "die"); CTargetManager::instance().DeleteTarget(pkChr->GetPlayerID(), info->dwQuestIndex, info->szTargetName); } if (event->is_force_to_end) { sys_log(0, "target_event: event canceled"); return 0; } if (x != info->iOldX || y != info->iOldY) { if (info->bSendToClient) SendTargetUpdatePacket(pkChr->GetDesc(), info->iID, x, y); info->iOldX = x; info->iOldY = y; } if (!bRet) return passes_per_sec; else return std::clamp(iDist / (1500 / passes_per_sec), passes_per_sec / 2, passes_per_sec * 5); } void CTargetManager::CreateTarget(DWORD dwPID, DWORD dwQuestIndex, const char * c_pszTargetName, int iType, int iArg1, int iArg2, int iMapIndex, const char * c_pszTargetDesc, int iSendFlag) { sys_log(0, "CreateTarget : target pid %u quest %u name %s arg %d %d %d", dwPID, dwQuestIndex, c_pszTargetName, iType, iArg1, iArg2); LPCHARACTER pkChr = CHARACTER_MANAGER::instance().FindByPID(dwPID); if (!pkChr) { sys_err("Cannot find character ptr by PID %u", dwPID); return; } if (pkChr->GetMapIndex() != iMapIndex) return; itertype(m_map_kListEvent) it = m_map_kListEvent.find(dwPID); if (it != m_map_kListEvent.end()) { std::list::const_iterator it2 = it->second.begin(); while (it2 != it->second.end()) { LPEVENT pkEvent = *(it2++); TargetInfo* existInfo = dynamic_cast(pkEvent->info); if (NULL == existInfo) { sys_err("CreateTarget : event already exist, but have no info"); return; } if (existInfo->dwQuestIndex == dwQuestIndex && !strcmp(existInfo->szTargetName, c_pszTargetName)) { sys_log(0, "CreateTarget : same target will be replaced"); if (existInfo->bSendToClient) SendTargetDeletePacket(pkChr->GetDesc(), existInfo->iID); if (c_pszTargetDesc) { strncpy(existInfo->szTargetDesc, c_pszTargetDesc, sizeof(existInfo->szTargetDesc)); } else { *existInfo->szTargetDesc = '\0'; } existInfo->iID = ++m_iID; existInfo->iType = iType; existInfo->iArg1 = iArg1; existInfo->iArg2 = iArg2; existInfo->iOldX = 0; existInfo->iOldY = 0; existInfo->bSendToClient = iSendFlag ? true : false; SendTargetCreatePacket(pkChr->GetDesc(), existInfo); return; } } } TargetInfo* newInfo = AllocEventInfo(); if (c_pszTargetDesc) { strncpy(newInfo->szTargetDesc, c_pszTargetDesc, sizeof(newInfo->szTargetDesc)); } else { *newInfo->szTargetDesc = '\0'; } newInfo->iID = ++m_iID; // Removed pkChr //newInfo->pkChr = pkChr; newInfo->dwPID = dwPID; newInfo->dwQuestIndex = dwQuestIndex; strncpy(newInfo->szTargetName, c_pszTargetName, sizeof(newInfo->szTargetName)); newInfo->iType = iType; newInfo->iArg1 = iArg1; newInfo->iArg2 = iArg2; newInfo->iMapIndex = iMapIndex; newInfo->iOldX = 0; newInfo->iOldY = 0; newInfo->bSendToClient = iSendFlag ? true : false; LPEVENT event = event_create(target_event, newInfo, PASSES_PER_SEC(1)); if (NULL != event) { m_map_kListEvent[dwPID].push_back(event); SendTargetCreatePacket(pkChr->GetDesc(), newInfo); } } void CTargetManager::DeleteTarget(DWORD dwPID, DWORD dwQuestIndex, const char * c_pszTargetName) { itertype(m_map_kListEvent) it = m_map_kListEvent.find(dwPID); if (it == m_map_kListEvent.end()) return; std::list::iterator it2 = it->second.begin(); while (it2 != it->second.end()) { LPEVENT pkEvent = *it2; TargetInfo * info = dynamic_cast(pkEvent->info); if ( info == NULL ) { sys_err( "CTargetManager::DeleteTarget> Null pointer" ); ++it2; continue; } if (dwQuestIndex == info->dwQuestIndex) { if (!c_pszTargetName || !strcmp(info->szTargetName, c_pszTargetName)) { if (info->bSendToClient) { // Removed pkChr //SendTargetDeletePacket(info->pkChr->GetDesc(), info->iID); LPCHARACTER pkChr = CHARACTER_MANAGER::instance().FindByPID(info->dwPID); if (pkChr != NULL) { SendTargetDeletePacket(pkChr->GetDesc(), info->iID); } } event_cancel(&pkEvent); it2 = it->second.erase(it2); continue; } } it2++; } } LPEVENT CTargetManager::GetTargetEvent(DWORD dwPID, DWORD dwQuestIndex, const char * c_pszTargetName) { itertype(m_map_kListEvent) it = m_map_kListEvent.find(dwPID); if (it == m_map_kListEvent.end()) return NULL; std::list::iterator it2 = it->second.begin(); while (it2 != it->second.end()) { LPEVENT pkEvent = *(it2++); TargetInfo * info = dynamic_cast(pkEvent->info); if ( info == NULL ) { sys_err( "CTargetManager::GetTargetEvent> Null pointer" ); continue; } if (info->dwQuestIndex != dwQuestIndex) continue; if (strcmp(info->szTargetName, c_pszTargetName)) continue; return pkEvent; } return NULL; } TargetInfo * CTargetManager::GetTargetInfo(DWORD dwPID, int iType, int iArg1) { itertype(m_map_kListEvent) it = m_map_kListEvent.find(dwPID); if (it == m_map_kListEvent.end()) return NULL; std::list::iterator it2 = it->second.begin(); while (it2 != it->second.end()) { LPEVENT pkEvent = *(it2++); TargetInfo * info = dynamic_cast(pkEvent->info); if ( info == NULL ) { sys_err( "CTargetManager::GetTargetInfo> Null pointer" ); continue; } if (!IS_SET(info->iType, iType)) continue; if (info->iArg1 != iArg1) continue; return info; } return NULL; } void CTargetManager::Logout(DWORD dwPID) { itertype(m_map_kListEvent) it = m_map_kListEvent.find(dwPID); if (it == m_map_kListEvent.end()) return; std::list::iterator it2 = it->second.begin(); while (it2 != it->second.end()) event_cancel(&(*(it2++))); m_map_kListEvent.erase(it); }