Esempio n. 1
0
///=====================================================
/// 
///=====================================================
void AISystem::DefendStrategy() const{
	static IntVec2 defenceLocation(48, 9);

	for (Actors::const_iterator actorIter = Actor::s_actorsOnMap.cbegin(); actorIter != Actor::s_actorsOnMap.cend(); ++actorIter){
		Actor* actor = actorIter->second;

		if (actor->m_isDead)
			continue;

		if (actor->IsPlayer()){
			break;
		}
		else{
			NPC* npc = (NPC*)actor;
			if (npc->m_plannedBehavior->m_name == "Wander" && CalcDistanceSquared(npc->m_position, defenceLocation) > (10 * 10)){ //if we're far away from the defence location and wandering, move toward the defence location
				DefendLocationBehavior* defendLocationBehavior = (DefendLocationBehavior*)npc->FindBehaviorByName("DefendLocation");
				RECOVERABLE_ASSERT(defendLocationBehavior != nullptr);
				if (defendLocationBehavior != nullptr){
					defendLocationBehavior->m_defenceLocation = defenceLocation;
					npc->m_plannedBehavior = defendLocationBehavior;
				}
			}
		}
	}
}
Esempio n. 2
0
///---------------------------------------------------------------------------------
/// fast
///---------------------------------------------------------------------------------
inline bool Disc2D::IsPointInside( const Vector2& point ) const
{
	float distanceToPointSquared = CalcDistanceSquared( m_center, point );
	float radiusSquared = m_radius * m_radius;
	bool isInside = distanceToPointSquared < radiusSquared;
	return isInside;
}
Esempio n. 3
0
///=====================================================
/// 
///=====================================================
bool TeleportBehavior::Think(){
	if ((m_NPC->m_health / m_NPC->m_maxHealth) > m_healthThreshold){
		m_NPC->m_ignoredBehaviors.push_back(this);
		m_NPC->PlanNextThink(false);
		return m_NPC->Think(false);
	}

	std::vector<Tile*>& airTiles = m_NPC->m_map->GetAllTilesOfType(TileType::Air, true);
	if (airTiles.empty())
		return false;

	std::vector<Tile*>::const_iterator tileIter = airTiles.cbegin() + GetRandomIntLessThan(airTiles.size());
	Tile* tile = *tileIter;

	while (CalcDistanceSquared(tile->m_position, m_NPC->m_position) <= (5 * 5)){
		airTiles.erase(tileIter);

		if (airTiles.empty())
			return false;

		tileIter = airTiles.cbegin() + GetRandomIntLessThan(airTiles.size());
		tile = *tileIter;
	}

	m_NPC->MoveToLocation(tile->m_position);
	m_NPC->TakeDamage(-(int)((float)m_NPC->m_maxHealth * m_healthThreshold), m_NPC);

	if (m_numUses > 0)
		--m_numUses;

	if (m_NPC->CanSeePlayer())
		s_theMessageBar->m_messages.push_back(m_NPC->m_name + " " + m_phrase + " and disappears!");

	return true;
}
Esempio n. 4
0
///---------------------------------------------------------------------------------
///
///---------------------------------------------------------------------------------
inline float CalcDistance( const IntVector2& positionA, const IntVector2& positionB )
{
	return sqrtf( (float) CalcDistanceSquared( positionA, positionB ) );
}
Esempio n. 5
0
///---------------------------------------------------------------------------------
/// very slow
///---------------------------------------------------------------------------------
float CalcDistance( const Vector2& positionA, const Vector2& positionB )
{
	float distSquared = CalcDistanceSquared( positionA, positionB );
	float dist = sqrtf( distSquared );
	return dist;
}
Esempio n. 6
0
///=====================================================
/// //assumes NPC has RetreatToAllyBehavior
///=====================================================
RememberedActor* AISystem::FindAllyToRetreatTo(NPC& retreatingNPC, bool retreatToBuffers, bool findClosest) const{
	RetreatToAllyBehavior* retreatToAllyBehavior = (RetreatToAllyBehavior*)retreatingNPC.FindBehaviorByName("RetreatToAlly");
	retreatToAllyBehavior->m_avoidEnemies = !retreatToBuffers && findClosest;

	if (retreatToAllyBehavior == nullptr){
		RECOVERABLE_ERROR();
		return nullptr;
	}

	RememberedActor* prevTargetAlly = retreatingNPC.m_targetAlly;
	
	RememberedActor* allyToRetreatTo = nullptr;
	int bestDistanceSquared = findClosest ? INT_MAX : -1;
	for (std::vector<Actor*>::const_iterator actorIter = retreatingNPC.m_visibleActors.cbegin(); actorIter != retreatingNPC.m_visibleActors.cend(); ++actorIter){
		Actor* actor = *actorIter;
		FATAL_ASSERT(actor != nullptr);
		RECOVERABLE_ASSERT(actor != &retreatingNPC);

		if (retreatToBuffers){
			if (actor->IsPlayer())
				continue;

			NPC* npc = (NPC*)actor;
			AOEBuffBehavior* buffBehavior = (AOEBuffBehavior*)npc->FindBehaviorByName("AOEBuff");
			if (buffBehavior == nullptr || buffBehavior->m_hasBeenUsed)
				continue;
		}

		if (retreatingNPC.GetFactionStatus(actor->m_faction->m_factionID, actor->m_ID) > 0){ //is ally
			int distanceSquared = CalcDistanceSquared(actor->m_position, retreatingNPC.m_position);
			if ((findClosest && distanceSquared < bestDistanceSquared) || (!findClosest && distanceSquared > bestDistanceSquared)){
				RememberedActor remActor = RememberedActor(*actor);
				retreatingNPC.m_targetAlly = &remActor;

				IntVec2 possibleMoveLocation = retreatToAllyBehavior->CalcNextPathStep();

				if ((possibleMoveLocation.x != -1) && (retreatToBuffers || !findClosest || CalcDistanceSquared(possibleMoveLocation, retreatingNPC.m_targetEnemy->m_position) > CalcDistanceSquared(retreatingNPC.m_position, retreatingNPC.m_targetEnemy->m_position))){
					//only retreat if the first step would take us further away from the enemy in the case of findFurthest
					bestDistanceSquared = distanceSquared;

					if (allyToRetreatTo == nullptr)
						allyToRetreatTo = new RememberedActor(remActor);
					else
						*allyToRetreatTo = remActor;
				}
			}
		}
	}

	if (allyToRetreatTo == nullptr){ //we didn't find anyone to retreat to, so let's see if we remember any nearby allies
		for (std::map<int, RememberedActor>::const_iterator actorIter = retreatingNPC.m_previouslyVisibleActors.cbegin(); actorIter != retreatingNPC.m_previouslyVisibleActors.cend(); ++actorIter){
			const RememberedActor& rememberedActorData = actorIter->second;
			if (Entity::s_turnCount - 5 > rememberedActorData.m_turn)
				continue;

			if (retreatToBuffers && !rememberedActorData.m_canAOEBuff){
				continue;
			}
			
			if (retreatingNPC.GetFactionStatus(rememberedActorData.m_factionID, actorIter->first) > 0){ //is ally
				int distanceSquared = CalcDistanceSquared(rememberedActorData.m_position, retreatingNPC.m_position);
				if ((findClosest && distanceSquared < bestDistanceSquared) || (!findClosest && distanceSquared > bestDistanceSquared)){
					retreatingNPC.m_targetAlly = (RememberedActor*)&rememberedActorData;

					IntVec2 possibleMoveLocation = retreatToAllyBehavior->CalcNextPathStep();

					if ((possibleMoveLocation.x != -1) && (retreatToBuffers || !findClosest || CalcDistanceSquared(possibleMoveLocation, retreatingNPC.m_targetEnemy->m_position) > CalcDistanceSquared(retreatingNPC.m_position, retreatingNPC.m_targetEnemy->m_position))){
						//only retreat if the first step would take us further away from the enemy in the case of findFurthest
						bestDistanceSquared = distanceSquared;

						if (allyToRetreatTo == nullptr)
							allyToRetreatTo = new RememberedActor(rememberedActorData);
						else
							*allyToRetreatTo = rememberedActorData;
					}
				}
			}
		}
	}

	retreatingNPC.m_targetAlly = prevTargetAlly;

	return allyToRetreatTo;
}
Esempio n. 7
0
///=====================================================
/// 
///=====================================================
void AISystem::AttackStrategy(const Player& player) const{
	for (Actors::const_iterator actorIter = Actor::s_actorsOnMap.cbegin(); actorIter != Actor::s_actorsOnMap.cend(); ++actorIter){
		Actor* actor = actorIter->second;

		if (actor->m_isDead || actor->GetFactionStatus(player.m_faction->m_factionID, player.m_ID) > 0)
			continue;

		if (actor->IsPlayer()){
			break;
		}

		NPC* npc = (NPC*)actor;

		//if we are a healer, we are next to an enemy, and there are nearby allies, try to run away
		if (npc->FindBehaviorByName("HealAlly") != nullptr && (npc->m_plannedBehavior->m_behaviorType == BehaviorType::Attack)){
			if (npc->m_targetAlly != nullptr && npc->m_targetAlly->m_turn == Entity::s_turnCount && npc->m_targetEnemy->m_turn == Entity::s_turnCount && CalcDistanceSquared(npc->m_position, npc->m_targetEnemy->m_position) <= 8){
				BaseAIBehavior* retreatToAllyBehavior = npc->FindBehaviorByName("RetreatToAlly");
				if (retreatToAllyBehavior != nullptr){
					RememberedActor* allyToRetreatTo = FindAllyToRetreatTo(*npc, false, true);
					if (allyToRetreatTo != nullptr){
						//smartly retreat toward an ally if we can
						delete npc->m_targetAlly;
						npc->m_targetAlly = allyToRetreatTo;

						npc->m_plannedBehavior = retreatToAllyBehavior;
						continue;
					}
				}

				RetreatBehavior* retreatBehavior = (RetreatBehavior*)npc->FindBehaviorByName("Retreat");
				if (retreatBehavior != nullptr){
					retreatBehavior->m_retreatCount = 0;
					npc->m_plannedBehavior = retreatBehavior; //otherwise, dumbly retreat
					continue;
				}

				continue;
			}
		}

		//if a lot of monsters want to chase/attack, we should too as long as we know where the player is
		if (npc->m_targetEnemy != nullptr && npc->m_targetEnemy->m_isPlayer){
			if (npc->m_plannedBehavior->m_behaviorType != BehaviorType::Attack && npc->m_plannedBehavior->m_behaviorType != BehaviorType::Aide){ //if we're far away and a bunch of monsters want to chase, get a bit closer
				BaseAIBehavior* chaseBehavior = npc->FindBehaviorByName("Chase");
				RECOVERABLE_ASSERT(chaseBehavior != nullptr);
				if (chaseBehavior != nullptr){
					npc->m_plannedBehavior = chaseBehavior;
					continue;
				}
			}
		}

		//try to group up for buffing
		if (npc->m_plannedBehavior->m_name == "AOEBuff" || (npc->m_plannedBehavior->m_behaviorType != BehaviorType::Attack && npc->m_plannedBehavior->m_behaviorType != BehaviorType::Aide && npc->m_plannedBehavior->m_name != "PickUpItem")){
			BaseAIBehavior* retreatToAllyBehavior = npc->FindBehaviorByName("RetreatToAlly");
			if (retreatToAllyBehavior != nullptr){
				AOEBuffBehavior* buffBehavior = (AOEBuffBehavior*)npc->FindBehaviorByName("AOEBuff");
				if (buffBehavior == nullptr){
					RememberedActor* allyToRetreatTo = FindAllyToRetreatTo(*npc, true, true); //try to move to a buff-caster
					if (allyToRetreatTo != nullptr){
						delete npc->m_targetAlly;
						npc->m_targetAlly = allyToRetreatTo;

						npc->m_plannedBehavior = retreatToAllyBehavior;
						continue;
					}
				}
				else if (buffBehavior->m_hasBeenUsed == false && npc->m_plannedBehavior->m_name != "AOEBuff"){
					RememberedActor* allyToRetreatTo = FindAllyToRetreatTo(*npc, false, false); //try to move to someone who we can buff
					if (allyToRetreatTo != nullptr){
						delete npc->m_targetAlly;
						npc->m_targetAlly = allyToRetreatTo;

						npc->m_plannedBehavior = retreatToAllyBehavior;
						continue;
					}
				}
			}
		}
	}
}
Esempio n. 8
0
primitiveType CalcDistance( const Vector4< primitiveType >& positionA, const Vector4< primitiveType >& positionB )
{
    primitiveType distSquared = CalcDistanceSquared( positionA, positionB );
    primitiveType dist = sqrt( distSquared );
    return dist;
}
Esempio n. 9
0
//#define collisions
///==========================================================================================================================================
/// Fireworks
///==========================================================================================================================================
void FireworksEmitter::Update(double deltaSeconds){
	double currentTime = GetCurrentSeconds();

#if defined collisions
	Vec3s initialPositions;
	Vec3s finalPositions;
#endif
	//update existing particles
	for (Particles::iterator particleIter = m_particles.begin(); particleIter != m_particles.end();){
		Particle* particle = *particleIter;

		//delete expired particles
		if (particle->m_expirationTime < currentTime){
			delete particle;
			particleIter = m_particles.erase(particleIter);
			continue;
		}

#if defined collisions
		initialPositions.push_back(particle->m_position);
#endif
		particle->m_velocity.y -= m_acceleration * (float)deltaSeconds;
		particle->Update(deltaSeconds);
#if defined collisions
		finalPositions.push_back(particle->m_position);
#endif
		++particleIter;
	}
#if defined collisions
	int count1 = 0;
	int count2 = 0;
	for (Particles::iterator particleIter = m_particles.begin(); particleIter != m_particles.end();){
		Particle* particle = *particleIter;

		Vec3 p1 = initialPositions.at(count1);
		if (CalcDistanceSquared(p1, m_position) < 0.5f){
			++particleIter;
			++count1;
			continue;
		}
		Vec3 p2 = finalPositions.at(count1);

		count2 = ++count1;
		float R1 = 0.00000001f;
		for (Particles::iterator particleIter2 = ++particleIter; particleIter2 != m_particles.end(); ++particleIter2, ++count2){
			Particle* particle2 = *particleIter2;

			Vec3 q1 = initialPositions.at(count2);
			if (CalcDistanceSquared(q1, m_position) < 0.5f){
				continue;
			}
			Vec3 q2 = finalPositions.at(count2);
			float R2 = 0.00000001f;

			Vec3 x0(q1 - p1);
			Vec3 e(q2 - q1 - (p2 - p1));
			float R = R1 + R2;

			float collisionTest = (DotProduct(e, x0) * DotProduct(e, x0)) - (DotProduct(e, e) * (DotProduct(x0, x0) - (R * R)));
			if (collisionTest >= 0.0f){ //did collide
				float collisionTime = (-DotProduct(e, x0) - sqrt(collisionTest)) / DotProduct(e, e);
				if (collisionTime < 0.0f)
					collisionTime = 0.0f;

				particle2->m_color = RGBAchars::YELLOW;
				particle->m_color = RGBAchars::YELLOW;

				particle->m_position = initialPositions.at(count1 - 1);
				particle2->m_position = initialPositions.at(count2);

				Vec3 collisionNormal = particle->m_position - particle2->m_position;
				float length = collisionNormal.Normalize();
				if (length <= 0.001f)
					continue;

				float v1Parallel = DotProduct(particle->m_velocity, collisionNormal);
				Vec3 v1Perp = particle->m_velocity - v1Parallel * collisionNormal;
				float v2Parallel = DotProduct(particle2->m_velocity, collisionNormal);
				Vec3 v2Perp = particle2->m_velocity - v2Parallel * collisionNormal;

				float e = 0.7f;
				Vec3 v1ParralelFinal = (0.5f * (v1Parallel + v2Parallel + e * (v2Parallel - v1Parallel))) * collisionNormal;
				Vec3 v2ParralelFinal = (0.5f * (v1Parallel + v2Parallel - e * (v2Parallel - v1Parallel))) * collisionNormal;

				particle->m_velocity = v1ParralelFinal + v1Perp;
				particle2->m_velocity = v2ParralelFinal + v2Perp;
			}
		}
	}
#endif	

	//add new particles
	m_timeSinceParticleEmission += deltaSeconds;
	if (m_timeSinceParticleEmission >= m_timeBetweenParticleEmissions){
		AddParticles();
		m_timeSinceParticleEmission -= m_timeBetweenParticleEmissions;
	}
}