/**
 * Check state changes related to movement
 */
void BehaviorStandard::checkMove() {

	// dying enemies can't move
	if (e->stats.cur_state == ENEMY_DEAD || e->stats.cur_state == ENEMY_CRITDEAD) return;

	// stunned enemies can't act
	if (e->stats.effects.stun) return;

	// handle not being in combat and (not patrolling waypoints or waiting at waypoint)
	if (!e->stats.hero_ally && !e->stats.in_combat && (e->stats.waypoints.empty() || e->stats.waypoint_pause_ticks > 0)) {

		if (e->stats.cur_state == ENEMY_MOVE) {
			e->newState(ENEMY_STANCE);
		}

		// currently enemies only move while in combat or patrolling
		return;
	}

	// clear current space to allow correct movement
	mapr->collider.unblock(e->stats.pos.x, e->stats.pos.y);

	// update direction
	if (e->stats.facing) {
		if (++e->stats.turn_ticks > e->stats.turn_delay) {

			// if blocked, face in pathfinder direction instead
			if (!mapr->collider.line_of_movement(e->stats.pos.x, e->stats.pos.y, pursue_pos.x, pursue_pos.y, e->stats.movement_type)) {

				// if a path is returned, target first waypoint

				bool recalculate_path = false;

				//if theres no path, it needs to be calculated
				if(path.empty())
					recalculate_path = true;

				//if the target moved more than 1 tile away, recalculate
				if(calcDist(map_to_collision(prev_target), map_to_collision(pursue_pos)) > 1.f)
					recalculate_path = true;

				//if a collision ocurred then recalculate
				if(collided)
					recalculate_path = true;

				//add a 5% chance to recalculate on every frame. This prevents reclaulating lots of entities in the same frame
				chance_calc_path += 5;

				if(percentChance(chance_calc_path))
					recalculate_path = true;

				//dont recalculate if we were blocked and no path was found last time
				//this makes sure that pathfinding calculation is not spammed when the target is unreachable and the entity is as close as its going to get
				if(!path_found && collided && !percentChance(chance_calc_path))
					recalculate_path = false;
				else//reset the collision flag only if we dont want the cooldown in place
					collided = false;

				prev_target = pursue_pos;

				// target first waypoint
				if(recalculate_path) {
					chance_calc_path = -100;
					path.clear();
					path_found = mapr->collider.compute_path(e->stats.pos, pursue_pos, path, e->stats.movement_type);
				}

				if(!path.empty()) {
					pursue_pos = path.back();

					//if distance to node is lower than a tile size, the node is going to be passed and can be removed
					if(calcDist(e->stats.pos, pursue_pos) <= 1.f)
						path.pop_back();
				}
			}
			else {
				path.clear();
			}

			if(fleeing)
				e->stats.direction = calcDirection(pursue_pos, e->stats.pos);
			else
				e->stats.direction = calcDirection(e->stats.pos, pursue_pos);
			e->stats.turn_ticks = 0;
		}
	}

	// try to start moving
	if (e->stats.cur_state == ENEMY_STANCE) {
		checkMoveStateStance();
	}

	// already moving
	else if (e->stats.cur_state == ENEMY_MOVE) {
		checkMoveStateMove();
	}

	// if patrolling waypoints and has reached a waypoint, cycle to the next one
	if (!e->stats.waypoints.empty()) {
		FPoint waypoint = e->stats.waypoints.front();
		FPoint pos = e->stats.pos;
		// if the patroller is close to the waypoint
		if (fabs(waypoint.x - pos.x) <= 0.5f && fabs(waypoint.y - pos.y) <= 0.5f) {
			e->stats.waypoints.pop();
			// pick a new random point if we're wandering
			if (e->stats.wander) {
				waypoint = getWanderPoint();
			}
			e->stats.waypoints.push(waypoint);
			e->stats.waypoint_pause_ticks = e->stats.waypoint_pause;
		}
	}

	// re-block current space to allow correct movement
	mapr->collider.block(e->stats.pos.x, e->stats.pos.y, e->stats.hero_ally);

}
/**
 * Check state changes related to movement
 */
void BehaviorStandard::checkMove() {

	// dying enemies can't move
	if (e->stats.cur_state == ENEMY_DEAD || e->stats.cur_state == ENEMY_CRITDEAD) return;

	// stunned enemies can't act
	if (e->stats.effects.stun) return;

	// handle not being in combat and (not patrolling waypoints or waiting at waypoint)
	if (!e->stats.hero_ally && !e->stats.in_combat && (e->stats.waypoints.empty() || e->stats.waypoint_pause_ticks > 0) && (!e->stats.wander || e->stats.wander_pause_ticks > 0)) {

		if (e->stats.cur_state == ENEMY_MOVE) {
			e->newState(ENEMY_STANCE);
		}

		// currently enemies only move while in combat or patrolling
		return;
	}

	// clear current space to allow correct movement
	e->map->collider.unblock(e->stats.pos.x, e->stats.pos.y);

	// update direction
	if (e->stats.facing) {
		if (++e->stats.turn_ticks > e->stats.turn_delay) {

			// if blocked, face in pathfinder direction instead
			if (!e->map->collider.line_of_movement(e->stats.pos.x, e->stats.pos.y, e->stats.hero_pos.x, e->stats.hero_pos.y, e->stats.movement_type)) {

				// if a path is returned, target first waypoint
				std::vector<Point> path;

				e->map->collider.compute_path(e->stats.pos, pursue_pos, path, e->stats.movement_type);
				if(!path.empty())
					pursue_pos = path.back();
			}

			if(fleeing)
				e->stats.direction = calcDirection(pursue_pos, e->stats.pos);
			else
				e->stats.direction = calcDirection(e->stats.pos, pursue_pos);
			e->stats.turn_ticks = 0;
		}
	}

	// try to start moving
	if (e->stats.cur_state == ENEMY_STANCE) {
		checkMoveStateStance();
	}

	// already moving
	else if (e->stats.cur_state == ENEMY_MOVE) {
		checkMoveStateMove();
	}

	// if patrolling waypoints and has reached a waypoint, cycle to the next one
	if (!e->stats.waypoints.empty()) {
		Point waypoint = e->stats.waypoints.front();
		Point pos = e->stats.pos;
		// if the patroller is close to the waypoint
		if (abs(waypoint.x - pos.x) < UNITS_PER_TILE/2 && abs(waypoint.y - pos.y) < UNITS_PER_TILE/2) {
			e->stats.waypoints.pop();
			e->stats.waypoints.push(waypoint);
			e->stats.waypoint_pause_ticks = e->stats.waypoint_pause;
		}
	}

	// if a wandering enemy reaches its destination early, reset wander_ticks
	if (e->stats.wander) {
		Point pos = e->stats.pos;
		if (abs(pursue_pos.x - pos.x) < UNITS_PER_TILE/2 && abs(pursue_pos.y - pos.y) < UNITS_PER_TILE/2) {
			e->stats.wander_ticks = 0;
		}
		if (e->stats.wander_ticks == 0 && e->stats.wander_pause_ticks == 0) {
			e->stats.wander_pause_ticks = rand() % 60;
		}
	}

	// re-block current space to allow correct movement
	e->map->collider.block(e->stats.pos.x, e->stats.pos.y, e->stats.hero_ally);

}