void ZSurvival::LoadNPCMeshes() { #ifdef _DEBUG // 혼자서 AI 테스트할 경우 if ((ZApplication::GetInstance()->GetLaunchMode() == ZApplication::ZLAUNCH_MODE_STANDALONE_QUEST) || (ZApplication::GetInstance()->GetLaunchMode() == ZApplication::ZLAUNCH_MODE_STANDALONE_AI)) { ZGetNpcMeshMgr()->LoadAll(); ZGetNpcMeshMgr()->ReloadAllAnimation();// 읽지 않은 에니메이션이 있다면 로딩 return; } #endif if (!m_GameInfo.IsInited()) { mlog("not inialized Quest Game Info\n"); _ASSERT(0); return; } for (int i = 0; i < m_GameInfo.GetNPCInfoCount(); i++) { MQUEST_NPC npc = m_GameInfo.GetNPCInfo(i); ZGetNpcMeshMgr()->Load(GetNPCInfo(npc)->szMeshName); } ZGetNpcMeshMgr()->ReloadAllAnimation();// 읽지 않은 에니메이션이 있다면 로딩 }
void ZActor::InitMesh(char* szMeshName, MQUEST_NPC nNPCType) { // for test RMesh* pMesh; pMesh = ZGetNpcMeshMgr()->Get(szMeshName); if(!pMesh) { _ASSERT(0); mlog("ZActor::InitMesh() - 원하는 모델을 찾을수 없음\n"); return; } int nVMID = g_pGame->m_VisualMeshMgr.Add(pMesh); if(nVMID==-1) mlog("ZActor::InitMesh() - 캐릭터 생성 실패\n"); RVisualMesh* pVMesh = g_pGame->m_VisualMeshMgr.GetFast(nVMID); SetVisualMesh(pVMesh); pVMesh->SetScale(rvector(15,15,15)); m_Animation.Set(ZA_ANIM_RUN); pVMesh->m_FrameInfo[0].m_pAniIdEventSet = ZGetAniEventMgr()->GetAniIDEventSet((int)nNPCType); }
void ZSurvival::OnDestroy() { //m_Map.Final(); ZGetNpcMeshMgr()->UnLoadAll(); m_GameInfo.Final(); ZGetScreenEffectManager()->DestroyQuestRes(); }
bool ZSurvival::OnNPCSpawn(MCommand* pCommand) { if (ZGetGame() == NULL) return false; MUID uidChar, uidNPC; unsigned char nNPCType, nPositionIndex; pCommand->GetParameter(&uidChar, 0, MPT_UID); pCommand->GetParameter(&uidNPC, 1, MPT_UID); pCommand->GetParameter(&nNPCType, 2, MPT_UCHAR); pCommand->GetParameter(&nPositionIndex, 3, MPT_UCHAR); MQUEST_NPC NPCType = MQUEST_NPC(nNPCType); ZMapSpawnType nSpawnType = ZMST_NPC_MELEE; ZMapSpawnManager* pMSM = ZGetGame()->GetMapDesc()->GetSpawnManager(); MQuestNPCInfo* pNPCInfo = GetNPCInfo(NPCType); if (pNPCInfo == NULL) return false; switch (pNPCInfo->GetSpawnType()) { case MNST_MELEE: nSpawnType = ZMST_NPC_MELEE; break; case MNST_RANGE: nSpawnType = ZMST_NPC_RANGE; break; case MNST_BOSS: nSpawnType = ZMST_NPC_BOSS; break; default: _ASSERT(0); }; ZMapSpawnData* pSpawnData = pMSM->GetSpawnData(nSpawnType, nPositionIndex); if (pSpawnData == NULL) { // 보스 스폰지점이 없는 맵을 서바이벌맵으로 사용한 경우 그냥 밀리용 지점을 사용하자 if (nSpawnType == ZMST_NPC_BOSS) pSpawnData = pMSM->GetSpawnData(ZMST_NPC_MELEE, nPositionIndex); } rvector NPCPos = rvector(0,0,0); rvector NPCDir = rvector(1,0,0); if (pSpawnData) { NPCPos = pSpawnData->m_Pos; NPCDir = pSpawnData->m_Dir; } // 만약 리소스 로딩을 안했으면 로드 - 이럴일은 테스트빼곤 없어야한다. // if (ZIsLaunchDevelop()) { RMesh* pNPCMesh = ZGetNpcMeshMgr()->Get(pNPCInfo->szMeshName); if (pNPCMesh) { if (!pNPCMesh->m_isMeshLoaded) { ZGetNpcMeshMgr()->Load(pNPCInfo->szMeshName); ZGetNpcMeshMgr()->ReloadAllAnimation(); } } } float fTC = m_GameInfo.GetNPC_TC(); ////////// 하드코딩.. 특정 맵에서 npc 충돌 반지름을 플레이어의 반지름으로 강제한다 ////// bool bForceCollRadius35 = false; if (m_GameInfo.GetMapSectorID(m_GameInfo.GetCurrSectorIndex()) == 207) // Prison_hall2 bForceCollRadius35 = true; ////////////////////////////////////////////////////////////////////////////////////////// ZActor* pNewActor = ZActor::CreateActor(NPCType, fTC, m_GameInfo.GetQuestLevel(), bForceCollRadius35); if (pNewActor) { bool bMyControl = (uidChar == ZGetGameClient()->GetPlayerUID()); pNewActor->SetMyControl(bMyControl); pNewActor->SetUID(uidNPC); pNewActor->SetPosition(NPCPos); pNewActor->SetDirection(NPCDir); ZCharacter *pOwner = ZGetCharacterManager()->Find(uidChar); if(pOwner) pNewActor->SetOwner(pOwner->GetUserName()); if(pNewActor->m_pVMesh) { D3DCOLORVALUE color; color.r = pNPCInfo->vColor.x; color.g = pNPCInfo->vColor.y; color.b = pNPCInfo->vColor.z; color.a = 1.f; pNewActor->m_pVMesh->SetNPCBlendColor(color);//색을 지정한 경우.. } ZGetObjectManager()->Add(pNewActor); ZGetEffectManager()->AddReBirthEffect(NPCPos); if ((pNPCInfo->nGrade == NPC_GRADE_BOSS) || (pNPCInfo->nGrade == NPC_GRADE_LEGENDARY)) { // 만약 보스급 NPC가 스폰하면 자동적으로 boss 등록 m_GameInfo.GetBosses().push_back(uidNPC); // 바운딩볼륨이 큰 보스가 벽 근처에서 스폰될때 바운딩이 벽에 일부 묻힌 채로 스폰될 수가 있다 // 이렇게 되면 간혹 벽 뒤로 이동해버리는 경우가 발생 -> 보이지 않으므로 보스를 죽일 수 없다 -> 게임 진행 막힘 // 보스형 몬스터에 한해서 스폰할때 벽과 충돌체크를 해서 초기위치를 조정한다 if (pNewActor->IsMyControl()) { float radius = bForceCollRadius35 ? 35.f : pNewActor->GetCollRadius(); if (true == ZGetGame()->GetWorld()->GetBsp()->CheckSolid(NPCPos, radius)) { // 맵에 충돌한다면. OutputDebugString("보스몹 스폰지점 충돌검사 실패...\n"); // 가까운 네비게이션 노드의 중앙으로 옮겨버린다 RNavigationMesh* pNavMesh = ZGetGame()->GetWorld()->GetBsp()->GetNavigationMesh(); if (pNavMesh) { RNavigationNode* pNavNode = pNavMesh->FindClosestNode(NPCPos); if (pNavNode) { pNewActor->SetPosition( pNavNode->CenterVertex()); OutputDebugString("스폰위치조정됨!\n"); } } } } } } return true; }