Integrar CustomNpcMove en MUEMU: Guía Completa
Si deseas integrar CustomNpcMove en MUEMU, sigue estos pasos detallados para asegurarte de que todo funcione correctamente.
1. Preparar el Código
Asegúrate de tener los archivos CustomNpcMove.cpp y CustomNpcMove.h listos. Si ya has realizado modificaciones para incluir requisitos de ítems, verifica que todo esté correcto.
2. Agregar Archivos al Proyecto
Ubicación de Archivos
Copia CustomNpcMove.cpp y CustomNpcMove.h en la carpeta de tu proyecto del GameServer. Normalmente, esta se encuentra en src o GameServer/src.
Incluir el Archivo de Cabecera
Abre el archivo donde se maneja la lógica principal del servidor, como GameServer.cpp o Main.cpp, y añade la inclusión del archivo de cabecera:
cpp
3. Instanciar la Clase
En el archivo donde inicializas las clases del servidor, agrega la instancia de CCustomNpcMove:
cpp
CCustomNpcMove gCustomNpcMove;
4. Cargar Datos de Configuración
Asegúrate de que la función Load se llame durante la inicialización del servidor. Esto puede hacerse en la función principal o en la función de inicialización del servidor:
cpp
gCustomNpcMove.Load("Path/To/Your/CustomNpcMove.txt");
Verifica que la ruta sea correcta y que el archivo exista.
5. Modificar el Proceso de Teletransporte
En la función GetNpcMove, asegúrate de que se llame correctamente desde el flujo de movimiento del NPC. Esto puede estar en un archivo relacionado con la lógica de interacción de NPCs.
6. Compilar el Proyecto
- Abre tu entorno de desarrollo (como Visual Studio).
- Asegúrate de que no haya errores en el código.
- Compila el proyecto. Esto generará el ejecutable del servidor actualizado con la nueva funcionalidad.
7. Probar el Servidor
Inicia el servidor y asegúrate de que no haya errores en la consola. Conéctate al juego y prueba interactuar con los NPCs que has configurado para verificar que los requisitos de ítems funcionen correctamente.
8. Ajustes Adicionales
Si encuentras errores o comportamientos inesperados:
- Verifica los mensajes de error.
- Asegúrate de que los ítems requeridos estén correctamente configurados en el juego.
- Revisa los logs para más detalles sobre posibles problemas.
Recursos Adicionales
Para más información sobre el desarrollo de servidores, visita este artículo sobre optimización de servidores de juegos.
Ejemplo de Código
CustomNpcMove.cpp
////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "CustomNpcMove.h" #include "CastleSiegeSync.h" #include "GensSystem.h" #include "Map.h" #include "MapManager.h" #include "MemScript.h" #include "Message.h" #include "Notice.h" #include "NpcTalk.h" #include "Path.h" #include "Util.h" CCustomNpcMove gCustomNpcMove; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CCustomNpcMove::CCustomNpcMove() // OK { this->m_CustomNpcMove.clear(); } CCustomNpcMove::~CCustomNpcMove() // OK { } void CCustomNpcMove::Load(char* path) // OK { CMemScript* lpMemScript = new CMemScript; if(lpMemScript == 0) { ErrorMessageBox(MEM_SCRIPT_ALLOC_ERROR,path); return; } if(lpMemScript->SetBuffer(path) == 0) { ErrorMessageBox(lpMemScript->GetLastError()); delete lpMemScript; return; } this->m_CustomNpcMove.clear(); try { while(true) { if(lpMemScript->GetToken() == TOKEN_END) { break; } if(strcmp("end",lpMemScript->GetString()) == 0) { break; } NPC_MOVE_INFO info; info.Index = lpMemScript->GetNumber(); info.MonsterClass = lpMemScript->GetAsNumber(); info.Map = lpMemScript->GetAsNumber(); info.X = lpMemScript->GetAsNumber(); info.Y = lpMemScript->GetAsNumber(); info.MoveMap = lpMemScript->GetAsNumber(); info.MoveX = lpMemScript->GetAsNumber(); info.MoveY = lpMemScript->GetAsNumber(); info.MinLevel = lpMemScript->GetAsNumber(); info.MaxLevel = lpMemScript->GetAsNumber(); info.MinReset = lpMemScript->GetAsNumber(); info.MaxReset = lpMemScript->GetAsNumber(); info.MinMReset = lpMemScript->GetAsNumber(); info.MaxMReset = lpMemScript->GetAsNumber(); info.AccountLevel = lpMemScript->GetAsNumber(); info.PkMove = lpMemScript->GetAsNumber(); // Req Item Igk info.ReqItem = lpMemScript->GetAsNumber(); info.ReqItemLevel = lpMemScript->GetAsNumber(); info.ReqItemCount = lpMemScript->GetAsNumber(); strcpy_s(info.Question,lpMemScript->GetAsString()); this->m_CustomNpcMove.insert(std::pair<int,NPC_MOVE_INFO>(info.Index,info)); } } catch(...) { ErrorMessageBox(lpMemScript->GetLastError()); } delete lpMemScript; } bool CCustomNpcMove::GetNpcMove(LPOBJ lpObj,int MonsterClass,int Map,int X,int Y) // OK { #if (GAMESERVER_CLIENTE_UPDATE >= 17) for(std::map<int,NPC_MOVE_INFO>::iterator it=this->m_CustomNpcMove.begin();it != this->m_CustomNpcMove.end();it++) { if(it->second.MonsterClass == MonsterClass && it->second.Map == Map && it->second.X == X && it->second.Y == Y) { if(it->second.MinLevel != -1 && lpObj->Level < it->second.MinLevel) { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(224),it->second.MinLevel); return 1; } if(it->second.MaxLevel != -1 && lpObj->Level > it->second.MaxLevel) { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(230),it->second.MaxLevel); return 1; } if(it->second.MinReset != -1 && lpObj->Reset < it->second.MinReset) { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(231),it->second.MinReset); return 1; } if(it->second.MaxReset != -1 && lpObj->Reset > it->second.MaxReset) { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(232),it->second.MaxReset); return 1; } if(it->second.MinReset != -1 && lpObj->MasterReset < it->second.MinMReset) { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(818),it->second.MinMReset); return 1; } if(it->second.MaxReset != -1 && lpObj->MasterReset > it->second.MaxMReset) { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(819),it->second.MaxMReset); return 1; } if(lpObj->AccountLevel < it->second.AccountLevel) { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(226)); return 1; } if(it->second.PkMove == 0 && lpObj->PKLevel >= 5) { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(227)); return 1; } if(lpObj->Interface.use != 0 || lpObj->Teleport != 0 || lpObj->DieRegen != 0 || lpObj->PShopOpen != 0) { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(226)); return 1; } if(it->second.MoveMap == MAP_ATLANS && (lpObj->Inventory[8].IsItem() != 0 && (lpObj->Inventory[8].m_Index == GET_ITEM(13,2) || lpObj->Inventory[8].m_Index == GET_ITEM(13,3)))) // Uniria,Dinorant { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(274)); return 1; } if((it->second.MoveMap == MAP_ICARUS || it->second.MoveMap == MAP_KANTURU3) && (lpObj->Inventory[7].IsItem() == 0 && lpObj->Inventory[8].m_Index != GET_ITEM(13,3) && lpObj->Inventory[8].m_Index != GET_ITEM(13,37))) // Dinorant,Fenrir { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(228)); return 1; } #if(GAMESERVER_UPDATE>=501) if(lpObj->GensFamily == GENS_FAMILY_NONE && gMapManager.GetMapGensBattle(it->second.MoveMap) != 0) { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(229)); return 1; } #endif // Requerimiento de Items if(it->second.ReqItemCount > 0) { int count = gItemManager.GetInventoryItemCount(lpObj,it->second.ReqItem, it->second.ReqItemLevel); if(count >= it->second.ReqItemCount) { gItemManager.DeleteInventoryItemCount(lpObj,it->second.ReqItem,it->second.ReqItemLevel,it->second.ReqItemCount); gObjTeleport(lpObj->Index,it->second.MoveMap,it->second.MoveX,it->second.MoveY); return 1; } else { gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(862),it->second.Question); //gNotice.GCNoticeSend(lpObj->Index,1,0,0,0,0,0,gMessage.GetMessage(862)); return 1; } } //------- gObjTeleport(lpObj->Index,it->second.MoveMap,it->second.MoveX,it->second.MoveY); return 1; } } #endif return 0; }
CustomNpcMove.h
////////////////////////////////////////////////////////////////////// #pragma once #include "User.h" struct NPC_MOVE_INFO { int Index; int MonsterClass; int Map; int X; int Y; int MoveMap; int MoveX; int MoveY; int MinLevel; int MaxLevel; int MinReset; int MaxReset; int MinMReset; int MaxMReset; int AccountLevel; int PkMove; // Req item Igk int ReqItem; int ReqItemLevel; int ReqItemCount; char Question[128]; }; class CCustomNpcMove { public: CCustomNpcMove(); virtual ~CCustomNpcMove(); void Load(char* path); bool GetNpcMove(LPOBJ lpObj,int MonsterClass,int Map,int X,int Y); private: std::map<int,NPC_MOVE_INFO> m_CustomNpcMove; }; extern CCustomNpcMove gCustomNpcMove;
CustomNpcMove.txt
//Index Npc NpcMap NpcX NpcY MoveMap MoveX MoveY MinLevel MaxLevel MinReset MaxReset MinMReset MaxMReset AccountLevel PKMove Index Level Count Comment 0 602 0 126 143 2 222 62 50 * * * * * 0 1 * 0 0 "Move To Devias Teste " 1 603 0 128 143 30 87 213 50 * * * * * 0 1 * 0 0 "Move To Devias Teste " 2 615 3 193 113 83 55 194 400 * * * * * 0 0 7342 0 1 "Necesitas 1 Spirit Map" end
Conclusión
Siguiendo estos pasos, deberías poder integrar CustomNpcMove en MUEMU de Season 6. Recuerda hacer copias de seguridad de tus archivos antes de realizar cambios significativos y prueba siempre en un entorno controlado.