Exemplo n.º 1
0
void ZActor::CheckDead(float fDelta)
{
	if (!CheckFlag(AF_MY_CONTROL)) return;
		 
	if (!CheckFlag(AF_DEAD))
	{
		if(m_pModule_HPAP->GetHP()<=0) {
			SetDeadTime(ZGetGame()->GetTime());
			m_Animation.Input(ZA_EVENT_DEATH);
			SetFlag(AF_DEAD, true);

			MUID uidKiller = this->GetLastAttacker();
			ZPostQuestPeerNPCDead(uidKiller, GetUID());

			m_TaskManager.Clear();
		}
	}
	else
	{
		if (!CheckFlag(AF_REQUESTED_DEAD))
		{
			if (ZGetGame()->GetTime()-GetDeadTime() > GetNPCInfo()->fDyingTime)
			{
				MUID uidAttacker = GetLastAttacker();
				if (uidAttacker == MUID(0, 0))
				{
					uidAttacker = ZGetGameClient()->GetPlayerUID();
				}

				ZPostQuestRequestNPCDead(uidAttacker, GetUID(), GetPosition());
				SetFlag(AF_REQUESTED_DEAD, true);
			}
		}
	}
}
Exemplo n.º 2
0
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();// 읽지 않은 에니메이션이 있다면 로딩
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
void ZActor::OnDamaged(ZObject* pAttacker, rvector srcPos, ZDAMAGETYPE damageType, MMatchWeaponType weaponType,
	float fDamage, float fPiercingRatio, int nMeleeType)
{
	if (!CheckFlag(AF_SOUND_WOUNDED))
	{
		bool bMyKill = false;
		if (pAttacker)
		{
			bMyKill = (pAttacker == g_pGame->m_pMyCharacter);
		}

		rvector pos_sound = GetPosition();
		pos_sound.z += m_Collision.fHeight - 10.0f;
		ZApplication::GetSoundEngine()->PlayNPCSound(m_pNPCInfo->nID, NPC_SOUND_WOUND, pos_sound, bMyKill);
		SetFlag(AF_SOUND_WOUNDED, true);		
	}

	if ((m_pNPCInfo->nGrade == NPC_GRADE_BOSS) || (m_pNPCInfo->nGrade == NPC_GRADE_LEGENDARY))
	{
		if (ZGetQuest()->GetGameInfo()->GetBoss() == GetUID())
		{
			ZGetScreenEffectManager()->ShockBossGauge(fDamage);
		}
	}

	if ((damageType == ZD_BULLET) || (damageType == ZD_BULLET_HEADSHOT))
	{
		m_nDamageCount++;
	}

	if(CheckFlag(AF_MY_CONTROL))
	{
		bool bSkipDamagedAnimation = false;

		if(m_pNPCInfo->bNeverAttackCancel ) {

			bSkipDamagedAnimation = ZActorAnimation::IsSkippableDamagedAnimation(GetCurrAni());
		}

		if(bSkipDamagedAnimation==false) {
		
			if((damageType==ZD_MELEE) || (damageType==ZD_KATANA_SPLASH)) {

				ZCharacterObject* pCObj = MDynamicCast(ZCharacterObject, pAttacker);

				bool bLightningDamage = false;

				if(pCObj) {
					ZC_ENCHANT etype = pCObj->GetEnchantType();
					if( etype == ZC_ENCHANT_LIGHTNING )
						bLightningDamage = true;	
				}

				if(bLightningDamage && (damageType==ZD_KATANA_SPLASH)) {
					m_Animation.Input(ZA_EVENT_LIGHTNING_DAMAGED);
				}
				else {
					if(nMeleeType%2)
						m_Animation.Input(ZA_EVENT_MELEE_DAMAGED1);
					else
						m_Animation.Input(ZA_EVENT_MELEE_DAMAGED2);

				}
				SetVelocity(0,0,0);
			}
			else {
				if( GetNPCInfo()->bNeverPushed == false)
				{
					if (m_nDamageCount >= 5)
					{
						m_Animation.Input(ZA_EVENT_RANGE_DAMAGED);
						m_nDamageCount = 0;
					}
				}
			}
		}
	}

	ZObject::OnDamaged(pAttacker,srcPos,damageType,weaponType,fDamage,fPiercingRatio,nMeleeType);
}