Esempio n. 1
0
Creature& MonsterFSM::getTarget(void) const
{
	ASSERT(m_Owner!=0, "Owner was NULL");
	ASSERT(haveTarget(), "This FSM does not have a target creature!");

	ActorSet &s = m_Owner->getZone().getObjects();

	return dynamic_cast<Creature&>(s.get(targetCreatureHANDLE));
}
Esempio n. 2
0
float MonsterFSM::distanceToTarget(void) const
{
	if(haveTarget())
	{
		return distanceToCreature(getTarget());
	}
	else
	{
		return 0.0f;
	}
}
Esempio n. 3
0
//根据传递trackerlet判定当前跟踪目标是否为指定目标,同时对自身信息进行更新
//在跟踪目标与指定目标不一致的情形下(return false),对tracker进行修正
//默认链表第一个节点为跟踪目标
//返回值表示,头结点是否为跟踪节点。是 true,否 false
bool Manager::dicision()
{
	//完成两个操作,判定头结点是否为指定目标;更新目标池

	//判断当前trackerletList头结点是否为跟踪节点
	if(trackerletList == NULL)
		return true;//在链表无内容情形下,自然无法进行修正过程,自然返回true,都不知道有没有错,怎么改?有道理哈
	
	if(front == rear)//当前目标池为空,直接加入链表头结点
	{
		trackerletList->occupied++;
		targetPool[front++] = trackerletList;//将头结点内容入池
		return true;
	}
	else//目标池非空的情形下,需要对头结点进行判定,
	{
		discriminator.clearDistance();
		//首先将头结点blockfeature内容暂时存放于discriminator
		discriminator.setCurrentFeature(trackerletList->featureSet);

		//将头结点内容与目标池中存储内容进行比较
		int traversal = rear;
		while(traversal != front)
		{   
			blockFeature distratorFeature = targetPool[traversal]->featureSet;
			discriminator.computeDistanceHold(distratorFeature);
			traversal = (traversal + 1) % capacity;
		}
		double dissimilarity = discriminator.distinguish();//得到当前target与目标池中所有元素的差异值
		if(dissimilarity > 1.0)//表示头结点不是跟踪目标,需要对list剩余内容进行遍历,寻找是否存在跟踪目标
		{
			correctTarget = haveTarget();//得到修正trackerlet
			if(correctTarget != NULL)
			{
				updatePool(correctTarget);
			}
			return false;
		}
		else
		{
			//认定当前头结点内容为指定跟踪目标,在必要的情形下对目标池进行更新
			updatePool(trackerletList);
			return true;
		}
	}
}
Esempio n. 4
0
bool MonsterFSM::States( StateMachineEvent event, Message_s * msg, int state )
{
	ASSERT(m_Owner!=0, "Owner was NULL");

// Do the state machine:
BeginStateMachine

	///////////////////////////////////////////////////////////////
	State( STATE_Rnd )
		OnEnter
			m_Owner->CancelOrders();

		OnMsg( MSG_ATTACKED )
			// Attacker becomes our target, retaliate
			if(msg->m_Sender != targetCreatureHANDLE)
			{
				targetCreatureHANDLE = msg->m_Sender;
				SetState(STATE_Attack);
			}

		OnUpdate
			targetCreatureHANDLE = getClosestTarget();

			/*
			If a player is close enough to get our attention, then attack.
			Otherwise, wander randomly
			*/
			if(targetCreatureHANDLE != INVALID_ID)
			{
				SetState(STATE_Pause_Before_Attack);
			}
			else if(m_Owner->anyCollisions() || !m_Owner->HasOrders())
			{
				// Go someplace random
				m_Owner->CancelOrders();
				vec3 waypoint = getRandomWalk();
				float speed = FRAND_RANGE(0.5f, 0.7f);
				m_Owner->QueueCommand(CommandMoveToLocation(waypoint, speed, FLT_EPSILON, 2000.f));
			}

	///////////////////////////////////////////////////////////////
	State( STATE_Pause_Before_Attack )
		OnEnter
			// pause for a moment before reacting
			m_Owner->CancelOrders();
			m_Owner->QueueCommand(CommandFreeze(FRAND_RANGE(200.0f, 400.0f), targetCreatureHANDLE));

		OnUpdate
			if(!m_Owner->HasOrders())
			{
				SetState(STATE_Attack);
			}

	///////////////////////////////////////////////////////////////
	State( STATE_Attack )
		OnEnter
			m_Owner->CancelOrders();
			g_SoundSystem.play(m_Owner->getAttnSfx());

		OnMsg( MSG_ATTACKED )
			// Attacker becomes our new target, retaliate
			if(msg->m_Sender != targetCreatureHANDLE)
			{
				targetCreatureHANDLE = msg->m_Sender;
				SetState(STATE_Attack);
			}

		OnUpdate
			/*
			If we don't have a target, resume wandering.
			Else If target is out of range, resume wandering
			Else If we are low on health, flee.
			Else If we don't have anything to do, keep attacking.
			*/
			if(!haveTarget())
			{
				SetState(STATE_Rnd);
			}
			else if(distanceToTarget() > thresholdLoseInterest)
			{
				SetState(STATE_Rnd);
			}
			else if(m_Owner->getHealthPercentage() < fleeThresholdForHealth)
			{
				SetState(STATE_Flee);
			}
			else if(!m_Owner->HasOrders())
			{
				orderTheAttack();
			}

	///////////////////////////////////////////////////////////////
	State( STATE_Flee )
		OnEnter
			m_Owner->CancelOrders();
			g_SoundSystem.play(m_Owner->getAttnSfx());

		OnMsg( MSG_ATTACKED )
			// Attacker becomes our new target, flee
			if(msg->m_Sender != targetCreatureHANDLE)
			{
				targetCreatureHANDLE = msg->m_Sender;
				SetState(STATE_Flee);
			}

		OnUpdate
			/*
			If we don't have a target, resume wandering.
			Else If target is out of range, resume wandering
			Else If we are not low on health anymore, attack again.
			Else If we don't have anything to do, keep fleeing.
			*/
			if(!haveTarget())
			{
				SetState(STATE_Rnd);
			}
			else if(distanceToTarget() > thresholdLoseInterest)
			{
				SetState(STATE_Rnd);
			}
			else if(m_Owner->getHealthPercentage() >= fleeThresholdForHealth)
			{
				SetState(STATE_Attack);
			}
			else if(!m_Owner->HasOrders())
			{
				m_Owner->QueueCommand(CommandFlee(targetCreatureHANDLE, FRAND_RANGE(0.9f, 1.0f), thresholdLoseInterest, 5000.0f));
			}

	///////////////////////////////////////////////////////////////
EndStateMachine
}