⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ai_mgr.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	SetAnimation
//
//	PURPOSE:	Set the current animation
//
// ----------------------------------------------------------------------- //
DBOOL AI_Mgr::SetAnimation(DDWORD nAni)
{
	if(nAni == m_nCurAnimation)
	{
	    m_pServerDE->ResetModelAnimation(m_hObject);
//		pServerDE->SetObjectDims(m_hObject,&m_vDims);
	}
	else
	{
		DVector vDims;
		VEC_COPY(vDims, m_vDims);		//safety

		if(m_pServerDE->GetModelAnimUserDims(m_hObject, &vDims, nAni) == DE_OK)
		{
			vDims.x *= m_vScale.x;
			vDims.y *= m_vScale.y;
			vDims.z *= m_vScale.z;
		}
		
		m_pServerDE->SetObjectDims2(m_hObject,&vDims);
		m_pServerDE->SetModelAnimation(m_hObject,nAni);
		VEC_COPY(m_vDims,vDims);
		m_nCurAnimation = nAni;
	}

    return DTRUE;
}

// ----------------------------------------------------------------------- //
// ROUTINE		: AI_Mgr::HandleTouch
// DESCRIPTION	: Handle MID_TOUCHNOTIFY messages
// RETURN TYPE	: void 
// PARAMS		: HOBJECT hObj
// ----------------------------------------------------------------------- //

void AI_Mgr::HandleTouch(HOBJECT hObj)
{
	if (!m_hObject || !hObj) return;

	HCLASS hClass = m_pServerDE->GetObjectClass(hObj);

	return;
}

// ----------------------------------------------------------------------- //
// ROUTINE		: AI_Mgr::InsertMe
// DESCRIPTION	: Insert to appropriate list
// RETURN TYPE	: void 
// ----------------------------------------------------------------------- //
void AI_Mgr::InsertMe()
{
	// insert it into the list
	if(m_bCabal)
	{
		dl_Insert( &m_CabalHead, &m_Link );
		m_Link.m_pData = ( void * )this;
		m_dwNumCabal++;
	}
	else
	{
		dl_Insert( &m_MonsterHead, &m_Link );
		m_Link.m_pData = ( void * )this;
		m_dwNumMonster++;
	}
}

// ----------------------------------------------------------------------- //
// ROUTINE		: AI_Mgr::AI_Init
// DESCRIPTION	: Initial update
// RETURN TYPE	: void 
// ----------------------------------------------------------------------- //

void AI_Mgr::InitialUpdate(int nData)
{
	//initialize the inventory aggregate
	m_InventoryMgr.Init(m_hObject);
	//initialize the damage aggregate
	m_damage.Init(m_hObject, &m_InventoryMgr, m_pAnim_Sound);

	// Only init stuff needed when restoring a savegame.
	if (nData == INITIALUPDATE_SAVEGAME)
	{
		return;
	}

	m_InventoryMgr.SetStrength(m_nAIStrength);

	for(int i =0; i < 5; i++)
	{
		int nWeap = WeaponStrToInt(m_szAIWeapon[i]);

		if(!m_InventoryMgr.HasWeapon(nWeap))
			m_InventoryMgr.ObtainWeapon(nWeap);
	}

	m_InventoryMgr.ChangeWeapon(WeaponStrToInt(m_szAIWeapon[0]));

	m_InventoryMgr.AddAmmo(AMMO_BULLET, m_fAIBullets);
	m_InventoryMgr.AddAmmo(AMMO_BMG, m_fAIBMG);
	m_InventoryMgr.AddAmmo(AMMO_SHELL, m_fAIShells);
	m_InventoryMgr.AddAmmo(AMMO_DIEBUGDIE, m_fAIGrenades);
	m_InventoryMgr.AddAmmo(AMMO_HOWITZER, m_fAIRockets);
	m_InventoryMgr.AddAmmo(AMMO_FLARE, m_fAIFlares);
	m_InventoryMgr.AddAmmo(AMMO_BATTERY, m_fAICharges);
	m_InventoryMgr.AddAmmo(AMMO_BATTERY, m_fAICells);
	m_InventoryMgr.AddAmmo(AMMO_FUEL, m_fAIFuel);
	m_InventoryMgr.AddAmmo(AMMO_FOCUS, 200.0f);
	m_InventoryMgr.AddInventoryWeapon(INV_PROXIMITY, (int)m_fProxBombs);

	switch(GetGameDifficulty())
	{
		case DIFFICULTY_EASY:		m_InventoryMgr.AddDamageMultiplier(0.25f);	break;
		case DIFFICULTY_MEDIUM:		m_InventoryMgr.AddDamageMultiplier(1.0f);	break;
		case DIFFICULTY_HARD:		m_InventoryMgr.AddDamageMultiplier(1.5f);	break;
	}

	//Set hit points
	DFLOAT fHP = m_fAIHitPoints + m_pServerDE->Random(1,m_fAIRandomHP);

	switch(GetGameDifficulty())
	{
		case DIFFICULTY_EASY:		fHP *= 0.25f;	break;
		case DIFFICULTY_MEDIUM:		fHP *= 1.0f;	break;
		case DIFFICULTY_HARD:		fHP *= 1.5f;	break;
	}

	m_damage.SetHitPoints(fHP);
	m_damage.SetMaxHitPoints(m_damage.GetHitPoints());
	m_damage.SetMaxMegaHitPoints(m_damage.GetHitPoints());

	//Set armor point
	switch(GetGameDifficulty())
	{
		case DIFFICULTY_EASY:		m_fAIArmorPoints *= 0.25f;	break;
		case DIFFICULTY_MEDIUM:		m_fAIArmorPoints *= 1.0f;	break;
		case DIFFICULTY_HARD:		m_fAIArmorPoints *= 1.5f;	break;
	}

	m_damage.SetArmorPoints(m_fAIArmorPoints);
	m_damage.SetMaxArmorPoints(m_fAIArmorPoints);
	m_damage.SetMaxNecroArmorPoints(m_fAIArmorPoints);
	m_damage.SetMass(m_fAIMass);

	// Added by Kevin S. 9/29/98 to better support scripted AIs...
	m_pServerDE->SetBlockingPriority(m_hObject, BLOCKPRIORITY_AI);

	m_MoveObj.Init(m_hObject);

    // Set the State
    m_nState = StateStrToInt(m_szAIState);
	if(m_nState == STATE_GuardLocation)
		m_pServerDE->GetObjectPos(m_hObject, &m_vGuardPos);

	DDWORD dwFlags = m_pServerDE->GetObjectFlags(m_hObject);
	dwFlags |= FLAG_VISIBLE | FLAG_SOLID | FLAG_TOUCH_NOTIFY | FLAG_GRAVITY | FLAG_STAIRSTEP |
			   FLAG_SHADOW | FLAG_MODELKEYS | FLAG_REMOVEIFOUTSIDE;
	m_pServerDE->SetObjectFlags(m_hObject, dwFlags);

	// insert it into the list
	if(m_bCabal)
	{
		dl_Insert( &m_CabalHead, &m_Link );
		m_Link.m_pData = ( void * )this;
		m_dwNumCabal++;
	}
	else
	{
		dl_Insert( &m_MonsterHead, &m_Link );
		m_Link.m_pData = ( void * )this;
		m_dwNumMonster++;
	}

	//randomize the size/weight
	DFLOAT fScale = m_pServerDE->Random(-0.05f, 0.1f);
	VEC_SET(m_vScale,m_vScale.x - fScale, m_vScale.y + fScale, m_vScale.z - fScale);
	m_pServerDE->ScaleObject(m_hObject,&m_vScale);

	SetAnimation(0);

	m_pServerDE->SetNextUpdate(m_hObject, 0.001f);

	//SCHLEGZ 4/27/98 2:51:47 PM: for vis list activation
	m_bSetShutdown = DFALSE;

	// Greg 9/28/98 Move this object to the ground
	if (m_bMoveToGround)
		MoveObjectToGround(m_hObject);

	m_fLastUpdate = m_pServerDE->GetTime();

	return;
}

// ----------------------------------------------------------------------- //
// ROUTINE		: AI_Mgr::AI_Update
// DESCRIPTION	: Main update function
// RETURN TYPE	: DBOOL 
// ----------------------------------------------------------------------- //

DBOOL AI_Mgr::AI_Update()
{
	if (!m_hObject || m_bRemoveMe) return DFALSE;
	
	//this is so we can desync activating AI and lessen tick spikes
	if(m_pServerDE->GetTime() - m_fLastUpdate >= 1.0f && m_bSetShutdown)
	{
		m_fLastUpdate = m_pServerDE->GetTime();
		m_pServerDE->SetNextUpdate(m_hObject, m_pServerDE->Random(0.01f,0.5f));
		return DTRUE;
	}

	//de-sync method for optimizing AI ticks per frame
/*	DFLOAT fFrameTime = m_pServerDE->GetFrameTime();
	if(fFrameTime == m_fLastFrame)
	{	
		m_pServerDE->SetNextUpdate(m_hObject, m_pServerDE->Random(fFrameTime,fFrameTime * 10));
		return DTRUE;
	}

	m_fLastFrame = fFrameTime;
*/	m_fLastUpdate = m_pServerDE->GetTime();
	
	m_pServerDE->SetNextUpdate(m_hObject, 0.001f);

	//scripted scene? disable!!
	if(g_hActiveCamera && m_nState != STATE_Script && m_nState != STATE_Passive && m_nState != STATE_Idle)
	{
		CameraObj* pCameraObj = (CameraObj*)m_pServerDE->HandleToObject(g_hActiveCamera);
		if(!pCameraObj->AllowPlayerMovement())
		{
			StopVelocity();
			return DTRUE;
		}
	}

	//SCHLEGZ 4/27/98 2:51:47 PM: for vis list activation
	if(!m_bSetShutdown)
	{
		m_pServerDE->SetDeactivationTime(m_hObject,3.0f);
		m_pServerDE->SetObjectState(m_hObject, OBJSTATE_AUTODEACTIVATE_NOW);
		m_bSetShutdown = DTRUE;
	}

	if(m_hTarget)
	{
		// This stuff helps the ai keep the target.  It was getting too easy to lose the target.
		m_bHasTargeted = DTRUE;
		if( m_fSeeingDist > m_fSensingDist && m_fSensingDist > 0.0f )
			m_fSensingDist = m_fSeeingDist;

		m_pServerDE->GetObjectPos(m_hTarget,&m_vTargetPos);

		CBaseCharacter* pAI = (CBaseCharacter*)m_pServerDE->HandleToObject(m_hTarget);
		if(pAI->IsDead())
		{
			m_hTarget = DNULL;
			SetNewState(STATE_Idle);
		}
		else
		{
			if (!(m_dwFlags & FLAG_ALWAYSCLEAR))
			{
				if( !CanSee( m_hTarget ))
				{
					m_hTarget = DNULL;
				}
			}
		}
	}

	if(m_hTrackObject)
		m_pServerDE->GetObjectPos(m_hTrackObject,&m_vTrackObjPos);

    // If we are DYING... then start that STATE!
    if(m_damage.GetHitPoints() <= 0.0f && m_nState != STATE_Dying)
		SetNewState(STATE_Dying);

	//see what we are standing on
	CollisionInfo collisionInfo;
	m_pServerDE->GetStandingOn(m_hObject, &collisionInfo);

	if(collisionInfo.m_hObject && (collisionInfo.m_hObject != m_pServerDE->GetWorldObject()))
	{
		HCLASS hCollClass = m_pServerDE->GetObjectClass(collisionInfo.m_hObject);
		HCLASS hBaseChar = m_pServerDE->GetClass("CBaseCharacter");

		DDWORD dwFlags = m_pServerDE->GetObjectFlags(m_hObject);

		if(m_pServerDE->IsKindOf(hCollClass, hBaseChar))
		{
			dwFlags |= FLAG_DONTFOLLOWSTANDING;		
		}
		else
		{
			dwFlags &= ~FLAG_DONTFOLLOWSTANDING;		
		}

		m_pServerDE->SetObjectFlags(m_hObject, dwFlags);
	}

	//sanity check
	if(Metacmd <= 0)
		Metacmd = 1;

	switch(m_nState)
    {
		case STATE_AttackClose:			AI_STATE_AttackClose();		break;
		case STATE_AttackFar:			AI_STATE_AttackFar();		break;
		case STATE_SearchVisualTarget:	AI_STATE_SearchVisualTarget();	break;
		case STATE_Escape_Hide:			AI_STATE_Escape_Hide();		break;
		case STATE_Escape_RunAway:		AI_STATE_Escape_RunAway();	break;
		case STATE_GuardLocation:		AI_STATE_GuardLocation();	break;
		case STATE_Idle:				AI_STATE_Idle();			break;
		case STATE_Dodge:				AI_STATE_Dodge();			break;
		case STATE_Teleport:			AI_STATE_Teleport();		break;
		case STATE_EnemyAttach:			AI_STATE_EnemyAttach();		break;
		case STATE_AssistAlly:			AI_STATE_AssistAlly();		break;
		case STATE_SearchSmellTarget:	AI_STATE_SearchSmellTarget();	break;
		case STATE_FindAmmo:			AI_STATE_FindAmmo();		break;
		case STATE_FindHealth:			AI_STATE_FindHealth();		break;
		case STATE_Special1:			AI_STATE_Special1();		break;
		case STATE_Special2:			AI_STATE_Special2();		break;
		case STATE_Special3:			AI_STATE_Special3();		break;
		case STATE_Special4:			AI_STATE_Special4();		break;
		case STATE_Special5:			AI_STATE_Special5();		break;
		case STATE_Special6:			AI_STATE_Special6();		break;
		case STATE_Special7:			AI_STATE_Special7();		break;
		case STATE_Special8:			AI_STATE_Special8();		break;
		case STATE_Passive:				AI_STATE_Passive();			break;

		case STATE_Dying:				AI_STATE_Dying();			break;
		case STATE_Recoil:				AI_STATE_Recoil();			break;
		case STATE_WalkAroundObj:		AI_STATE_WalkAroundObj();	break;
		case STATE_RunAroundObj:		AI_STATE_RunAroundObj();	break;
		case STATE_JumpOverObj:			AI_STATE_JumpOverObj();		break;
		case STATE_CrawlUnderObj:		AI_STATE_CrawlUnderObj();	break;
		case STATE_WalkToPos:			AI_STATE_WalkToPos();		break;
		case STATE_RunToPos:			AI_STATE_RunToPos();		break;
		case STATE_Script:				AI_STATE_Script();			break;

        case STATE_Inactive:			return DTRUE;				break;
        default:						AI_STATE_Idle();			break;
    
    }

	return DTRUE;
}

// ----------------------------------------------------------------------- //
// ROUTINE		: AI_Mgr::ComputeStimuli 
// DESCRIPTION	: fill in stimuli set
// RETURN TYPE	: DBOOL 
// ----------------------------------------------------------------------- //

int AI_Mgr::ComputeStimuli()
{
	if (!m_hObject) return DFALSE;

	HOBJECT	hSightTarget = DNULL,hSmellTarget = DNULL, hSenseTarget = DNULL;
	DVector vSight, vSmell, vSense;
	HOBJECT hNewTarget = DNULL;
	int nStimType = 0;

	//Check if hit recently
	if(( hNewTarget = m_damage.GetLastDamager()) != DNULL )
	{
		if( !IsBaseCharacter( hNewTarget ))
			m_damage.ClearLastDamager( );

		nStimType = STIM_SIGHT;
	}
	else
	{
		VEC_COPY(vSight, m_MoveObj.GetPos());
		VEC_COPY(vSmell, m_MoveObj.GetPos());
		VEC_COPY(vSense, m_MoveObj.GetPos());

		//Zero out the stimulus set
		memset(&m_fStimuli,0,sizeof(m_fStimuli));

		// Release current target if any
		SetNewTarget(DNULL);

		HCLASS hEnemyTest = DNULL;
		HCLASS hThis = m_pServerDE->GetObjectClass(m_hObject);

		if(m_pServerDE->IsKindOf(hThis, m_pServerDE->GetClass("BoneLeech")) ||
		   m_pServerDE->IsKindOf(hThis, m_pServerDE->GetClass("TheHandAI")) ||
		   m_pServerDE->IsKindOf(hThis, m_pServerDE->GetClass("Thief")))
		{
			hEnemyTest = m_pServerDE->GetClass("CPlayerObj");
		}
		else
		{
			hEnemyTest = m_pServerDE->GetClass("AI_Mgr");
		}

		HOBJECT hSightObj = FindObjectInRadius(hEnemyTest, m_fSeeingDist, FIND_VISIBLE | FIND_FACE_OBJECT);
		HOBJECT hSmellObj = FindObjectInRadius(m_pServerDE->GetClass("SmellHint"), m_fSmellingDist);
		HOBJECT hSenseObj = FindObjectInRadius(hEnemyTest, m_fSensingDist);

		if(hSightObj)
			m_pServerDE->GetObjectPos(hSightObj, &vSight);
		
		if(hSmellObj)
			m_pServerDE->GetObjectPos(hSmellObj, &vSmell);
		
		if(hSenseObj)
			m_pServerDE->GetObjectPos(hSenseObj, &vSense);

		DFLOAT fSight = VEC_DIST(vSight,m_MoveObj.GetPos());
		DFLOAT fSmell = VEC_DIST(vSmell,m_MoveObj.GetPos());
		DFLOAT fSense = VEC_DIST(vSense,m_MoveObj.GetPos());

		//Check smell
		if(hSmellObj && m_fSmellingDist > 0 && fSmell <= m_fSmellingDist)
		{
			m_fStimuli[SMELL]	= 1.0f - (fSmell/m_fSmellingDist);
			hNewTarget = hSmellObj;
			nStimType = STIM_SMELL;

			if(m_fStimuli[SMELL] <= 0.0f)
			{
				m_fStimuli[SMELL] = 0.0f;	
				hNewTarget = DNULL;
			}
		}

		//Check sense
		if(hSenseObj && m_fSensingDist > 0 && fSense <= m_fSensingDist)
		{
			m_fStimuli[SENSE]	= 1.0f - (fSense/m_fSensingDist);
			hNewTarget = hSenseObj;
			nStimType = STIM_SENSE;

			if(m_fStimuli[SENSE] <= 0.0f)
			{
				m_fStimuli[SENSE] = 0.0f;	
				hNewTarget = DNULL;
			}
		}

		//Check sight
		if(hSightObj && m_fSeeingDist > 0 && fSight <= m_fSeeingDist)
		{
			m_fStimuli[SIGHT]	= 1.0f - (fSight/m_fSeeingDist);
			hNewTarget = hSightObj;
			nStimType = STIM_SIGHT;

			if(m_fStimuli[SIGHT] <= 0.0f)
			{
				m_fStimuli[SIGHT] = 0.0f;	
				hNewTarget = DNULL;
			}
		}
	}

	//Health
	m_fStimuli[HEALTH] = (DFLOAT)m_damage.GetHitPoints()/(DFLOAT)m_damage.GetMaxHitPoints();

	if (hNewTarget)
	{
		if(nStimType != STIM_SMELL)
		{
			CBaseCharacter* pB = (CBaseCharacter*)m_pServerDE->HandleToObject(hNewTarget);

			if( pB->IsDead())
			{
				hNewTarget = DNULL;
    			return 0;
			}

			SetNewTarget(hNewTarget);
//			m_fStimuli[THREAT] = ComputeThr

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -