void Functions::getNearestObjectByTag(Aurora::NWScript::FunctionContext &ctx) {
	ctx.getReturn() = (Object *) 0;

	const Common::UString &tag = ctx.getParams()[0].getString();
	if (tag.empty())
		return;

	Witcher::Object *target = Witcher::ObjectContainer::toObject(getParamObject(ctx, 1));
	if (!target)
		return;

	size_t nth = MAX<int32>(ctx.getParams()[2].getInt() - 1, 0);

	Common::ScopedPtr<Aurora::NWScript::ObjectSearch> search(_game->getModule().findObjectsByTag(tag));
	Aurora::NWScript::Object *object = 0;

	std::list<Object *> objects;
	while ((object = search->next())) {
		// Needs to be a valid object, not the target, but in the target's area
		Witcher::Object *witcherObject = Witcher::ObjectContainer::toObject(object);
		if (!witcherObject || (witcherObject == target) || (witcherObject->getArea() != target->getArea()))
			continue;

		objects.push_back(witcherObject);
	}

	objects.sort(ObjectDistanceSort(*target));

	std::list<Object *>::iterator it = objects.begin();
	for (size_t n = 0; (n < nth) && (it != objects.end()); ++n)
		++it;

	if (it != objects.end())
		ctx.getReturn() = *it;
}
void Functions::getArea(Aurora::NWScript::FunctionContext &ctx) {
	ctx.getReturn() = (Aurora::NWScript::Object *) 0;

	Witcher::Object *object = Witcher::ObjectContainer::toObject(getParamObject(ctx, 0));
	if (object)
		ctx.getReturn() = (Aurora::NWScript::Object *) object->getArea();
}
void Functions::getNearestObject(Aurora::NWScript::FunctionContext &ctx) {
	ctx.getReturn() = (Aurora::NWScript::Object *) 0;

	Witcher::Object *target = Witcher::ObjectContainer::toObject(getParamObject(ctx, 1));
	if (!target)
		return;

	// Bitfield of type(s) to check for
	uint32 type = ctx.getParams()[0].getInt();
	// We want the nth nearest object
	size_t nth  = MAX<int32>(ctx.getParams()[2].getInt() - 1, 0);

	Aurora::NWScript::ObjectSearch *search = _game->getModule().findObjects();
	Aurora::NWScript::Object       *object = 0;

	std::list<Object *> objects;
	while ((object = search->next())) {
		// Needs to be a valid object, not the target, but in the target's area
		Witcher::Object *witcherObject = Witcher::ObjectContainer::toObject(object);
		if (!witcherObject || (witcherObject == target) || (witcherObject->getArea() != target->getArea()))
			continue;

		// Ignore invalid object types
		const uint32 objectType = (uint32) witcherObject->getType();
		if (objectType >= kObjectTypeMAX)
			continue;

		if (type & objectType)
			objects.push_back(witcherObject);
	}

	delete search;

	objects.sort(ObjectDistanceSort(*target));

	std::list<Object *>::iterator it = objects.begin();
	for (size_t n = 0; (n < nth) && (it != objects.end()); ++n)
		++it;

	if (it != objects.end())
		ctx.getReturn() = *it;
}
void Functions::actionMoveToObject(Aurora::NWScript::FunctionContext &ctx) {
	Witcher::Object *object = Witcher::ObjectContainer::toObject(ctx.getCaller());
	Witcher::Object *moveTo = Witcher::ObjectContainer::toObject(getParamObject(ctx, 0));

	if (!object || !moveTo)
		return;

	float x, y, z;
	moveTo->getPosition(x, y, z);

	jumpTo(object, moveTo->getArea(), x, y, z);

	unimplementedFunction(ctx);
}
void Functions::jumpToObject(Aurora::NWScript::FunctionContext &ctx) {
	// TODO: walkStraightLineToPoint
	// bool walkStraightLineToPoint = ctx.getParams()[1].getInt() != 0;

	Witcher::Object *object = Witcher::ObjectContainer::toObject(ctx.getCaller());
	Witcher::Object *moveTo = Witcher::ObjectContainer::toObject(getParamObject(ctx, 0));

	if (!object || !moveTo)
		return;

	float x, y, z;
	moveTo->getPosition(x, y, z);

	jumpTo(object, moveTo->getArea(), x, y, z);
}
void Functions::getNearestCreature(Aurora::NWScript::FunctionContext &ctx) {
	ctx.getReturn() = (Aurora::NWScript::Object *) 0;

	Witcher::Object *target = Witcher::ObjectContainer::toObject(getParamObject(ctx, 2));
	if (!target)
		return;

	size_t nth = MAX<int32>(ctx.getParams()[3].getInt() - 1, 0);

	/* TODO: Criteria:
	 *
	 * int crit1Type  = ctx.getParams()[0].getInt();
	 * int crit1Value = ctx.getParams()[1].getInt();
	 * int crit2Type  = ctx.getParams()[4].getInt();
	 * int crit2Value = ctx.getParams()[5].getInt();
	 * int crit3Type  = ctx.getParams()[6].getInt();
	 * int crit3Value = ctx.getParams()[7].getInt();
	 */

	Aurora::NWScript::ObjectSearch *search = _game->getModule().findObjects();
	Aurora::NWScript::Object       *object = 0;

	std::list<Object *> creatures;
	while ((object = search->next())) {
		Creature *creature = Witcher::ObjectContainer::toCreature(object);

		if (creature && (creature != target) && (creature->getArea() == target->getArea()))
			creatures.push_back(creature);
	}

	delete search;

	creatures.sort(ObjectDistanceSort(*target));

	std::list<Object *>::iterator it = creatures.begin();
	for (size_t n = 0; (n < nth) && (it != creatures.end()); ++n)
		++it;

	if (it != creatures.end())
		ctx.getReturn() = *it;
}