SceneObject* CreatureManagerImplementation::spawnLair(unsigned int lairTemplate, int difficultyLevel, int difficulty, float x, float z, float y, float size) {
	LairTemplate* lairTmpl = creatureTemplateManager->getLairTemplate(lairTemplate);

	if (lairTmpl == NULL || lairTmpl->getBuildingType() != LairTemplate::LAIR)
		return NULL;

 	String buildingToSpawn;

 	Vector<String>* mobiles = lairTmpl->getWeightedMobiles();

 	if (mobiles->size() == 0)
 		return NULL;

 	buildingToSpawn = lairTmpl->getBuilding((uint32)difficulty);

 	if (buildingToSpawn.isEmpty()) {
 		error("error spawning " + buildingToSpawn);
 		return NULL;
 	}

 	ManagedReference<LairObject*> building = zoneServer->createObject(buildingToSpawn.hashCode(), 0).castTo<LairObject*>();

 	if (building == NULL) {
 		error("error spawning " + buildingToSpawn);
 		return NULL;
 	}

 	Locker blocker(building);

 	building->setFaction(lairTmpl->getFaction());
 	building->setPvpStatusBitmask(CreatureFlag::ATTACKABLE);
 	building->setOptionsBitmask(0, false);
 	building->setMaxCondition(difficultyLevel * (900 + System::random(200)));
 	building->setConditionDamage(0, false);
 	building->initializePosition(x, z, y);
 	building->setDespawnOnNoPlayersInRange(true);

 	ManagedReference<LairObserver*> lairObserver = new LairObserver();
 	lairObserver->deploy();
 	lairObserver->setLairTemplate(lairTmpl);
 	lairObserver->setDifficulty(difficulty);
 	lairObserver->setObserverType(ObserverType::LAIR);
 	lairObserver->setSize(size);

 	building->registerObserver(ObserverEventType::OBJECTDESTRUCTION, lairObserver);
 	building->registerObserver(ObserverEventType::DAMAGERECEIVED, lairObserver);
 	building->registerObserver(ObserverEventType::AIMESSAGE, lairObserver);
 	building->registerObserver(ObserverEventType::OBJECTREMOVEDFROMZONE, lairObserver);

 	zone->transferObject(building, -1, false);

	lairObserver->checkForNewSpawns(building, NULL, true);

 	return building;
}
SceneObject* CreatureManagerImplementation::spawnTheater(unsigned int lairTemplate, int difficulty, float x, float z, float y, float size) {
	LairTemplate* lairTmpl = creatureTemplateManager->getLairTemplate(lairTemplate);

	if (lairTmpl == NULL || lairTmpl->getBuildingType() != LairTemplate::THEATER)
		return NULL;

 	Vector<String>* mobiles = lairTmpl->getWeightedMobiles();

 	if (mobiles->size() == 0)
 		return NULL;

 	String buildingToSpawn = lairTmpl->getBuilding((uint32)difficulty);

 	if (buildingToSpawn.isEmpty()) {
 		error("error spawning " + buildingToSpawn);
 		return NULL;
 	}

 	ManagedReference<PoiBuilding*> building = zoneServer->createObject(buildingToSpawn.hashCode(), 0).castTo<PoiBuilding*>();

 	if (building == NULL) {
 		error("error spawning " + buildingToSpawn);
 		return NULL;
 	}

 	Locker blocker(building);

 	building->initializePosition(x, z, y);
 	building->setDespawnOnNoPlayersInRange(true);

 	ManagedReference<DynamicSpawnObserver*> theaterObserver = new DynamicSpawnObserver();
 	theaterObserver->deploy();
 	theaterObserver->setLairTemplate(lairTmpl);
 	theaterObserver->setDifficulty(difficulty);
 	theaterObserver->setObserverType(ObserverType::LAIR);
 	theaterObserver->setSize(size);

 	building->registerObserver(ObserverEventType::CREATUREDESPAWNED, theaterObserver);
 	building->registerObserver(ObserverEventType::OBJECTREMOVEDFROMZONE, theaterObserver);


 	zone->transferObject(building, -1, false);

 	theaterObserver->spawnInitialMobiles(building);

 	return building;
}
SceneObject* CreatureManagerImplementation::spawnDynamicSpawn(unsigned int lairTemplate, int difficulty, float x, float z, float y, float size) {
	LairTemplate* lairTmpl = creatureTemplateManager->getLairTemplate(lairTemplate);

	if (lairTmpl == NULL || lairTmpl->getBuildingType() != LairTemplate::NONE)
		return NULL;

	Vector<String>* mobiles = lairTmpl->getWeightedMobiles();

	if (mobiles->size() == 0)
		return NULL;

	ManagedReference<ActiveArea*> area = zoneServer->createObject(String("object/active_area.iff").hashCode(), 0).castTo<ActiveArea*>();

	if (area == NULL) {
		error("error creating active area");
		return NULL;
	}

	Locker blocker(area);

	area->initializePosition(x, z, y);
	area->setRadius(64);
	area->setNoSpawnArea(true);
	area->setNoBuildArea(true);

	ManagedReference<DynamicSpawnObserver*> dynamicObserver = new DynamicSpawnObserver();
	dynamicObserver->deploy();
	dynamicObserver->setLairTemplate(lairTmpl);
	dynamicObserver->setDifficulty(difficulty);
	dynamicObserver->setObserverType(ObserverType::LAIR);
	dynamicObserver->setSize(size);

	area->registerObserver(ObserverEventType::CREATUREDESPAWNED, dynamicObserver);

	zone->transferObject(area, -1, false);

	dynamicObserver->spawnInitialMobiles(area);

	return area;
}
SceneObject* CreatureManagerImplementation::spawnDynamicSpawn(unsigned int lairTemplate, int difficulty, float x, float z, float y, float size) {
	LairTemplate* lairTmpl = creatureTemplateManager->getLairTemplate(lairTemplate);

	if (lairTmpl == NULL || lairTmpl->getBuildingType() != LairTemplate::NONE)
		return NULL;

	Vector<String>* mobiles = lairTmpl->getWeightedMobiles();

	if (mobiles->size() == 0)
		return NULL;

	ManagedReference<TheaterObject*> theater = zoneServer->createObject(STRING_HASHCODE("object/intangible/theater/base_theater.iff"), 0).castTo<TheaterObject*>();

	if (theater == NULL) {
		error("error creating intangible theater");
		return NULL;
	}

	Locker blocker(theater);

	theater->initializePosition(x, z, y);
	theater->setDespawnOnNoPlayersInRange(true);

	ManagedReference<DynamicSpawnObserver*> dynamicObserver = new DynamicSpawnObserver();
	dynamicObserver->deploy();
	dynamicObserver->setLairTemplate(lairTmpl);
	dynamicObserver->setDifficulty(difficulty);
	dynamicObserver->setObserverType(ObserverType::LAIR);
	dynamicObserver->setSize(size);

	theater->registerObserver(ObserverEventType::CREATUREDESPAWNED, dynamicObserver);
	theater->registerObserver(ObserverEventType::OBJECTREMOVEDFROMZONE, dynamicObserver);

	zone->transferObject(theater, -1, false);

	theater->createChildObjects();
	dynamicObserver->spawnInitialMobiles(theater);

	return theater;
}
void PlanetManagerImplementation::loadClientRegions() {
	TemplateManager* templateManager = TemplateManager::instance();

	IffStream* iffStream = templateManager->openIffFile("datatables/clientregion/" + zone->getZoneName() + ".iff");

	Reference<PlanetMapCategory*> cityCat = TemplateManager::instance()->getPlanetMapCategoryByName("city");

	if (iffStream == NULL) {
		info("No client regions found.");
		return;
	}

	DataTableIff dtiff;
	dtiff.readObject(iffStream);

	for (int i = 0; i < dtiff.getTotalRows(); ++i) {
		String regionName;
		float x, y, radius;

		DataTableRow* row = dtiff.getRow(i);
		row->getValue(0, regionName);
		row->getValue(1, x);
		row->getValue(2, y);
		row->getValue(3, radius);

		ManagedReference<CityRegion*> cityRegion = regionMap.getRegion(regionName);

		if (cityRegion == NULL) {
			cityRegion = new CityRegion();

			Locker locker(cityRegion);

			cityRegion->deploy();
			cityRegion->setRegionName(regionName);
			cityRegion->setZone(zone);
			regionMap.addRegion(cityRegion);
		}

		Locker locker(cityRegion);

		ManagedReference<Region*> region = cityRegion->addRegion(x, y, radius, false);

		locker.release();

		if (region != NULL) {
			Locker rlocker(region);

			if (cityRegion->getRegionsCount() == 1) {//Register the first region only.
				region->setPlanetMapCategory(cityCat);
				zone->registerObjectWithPlanetaryMap(region);
			}

			region->setMunicipalZone(true);

			ManagedReference<SceneObject*> scenery = NULL;

			if (gcwManager != NULL) {
				int strongholdFaction = gcwManager->isStrongholdCity(regionName);

				if (strongholdFaction == GCWManager::IMPERIALHASH || regionName.contains("imperial")) {
					scenery = zone->getZoneServer()->createObject(STRING_HASHCODE("object/static/particle/particle_distant_ships_imperial.iff"), 0);
				} else if (strongholdFaction == GCWManager::REBELHASH || regionName.contains("rebel")) {
					scenery = zone->getZoneServer()->createObject(STRING_HASHCODE("object/static/particle/particle_distant_ships_rebel.iff"), 0);
				} else {
					scenery = zone->getZoneServer()->createObject(STRING_HASHCODE("object/static/particle/particle_distant_ships.iff"), 0);
				}
			} else {
				scenery = zone->getZoneServer()->createObject(STRING_HASHCODE("object/static/particle/particle_distant_ships.iff"), 0);
			}

			Locker slocker(scenery, region);
			scenery->initializePosition(x, zone->getHeight(x, y) + 100, y);
			region->attachScenery(scenery);
		}

		ManagedReference<ActiveArea*> noBuild = zone->getZoneServer()->createObject(STRING_HASHCODE("object/active_area.iff"), 0).castTo<ActiveArea*>();

		Locker areaLocker(noBuild);

		noBuild->initializePosition(x, 0, y);

		ManagedReference<CircularAreaShape*> areaShape = new CircularAreaShape();

		Locker shapeLocker(areaShape);

		areaShape->setRadius(radius * 2);
		areaShape->setAreaCenter(x, y);
		noBuild->setAreaShape(areaShape);
		noBuild->setRadius(radius * 2);
		noBuild->setNoBuildArea(true);
		// Cities already have "Municipal" protection so the structure no-build should not apply to camps
		noBuild->setCampingPermitted(true);

		Locker zoneLocker(zone);

		zone->transferObject(noBuild, -1, true);
	}

	info("Added " + String::valueOf(regionMap.getTotalRegions()) + " client regions.");

	delete iffStream;
}
void PlanetManagerImplementation::loadClientRegions() {
	TemplateManager* templateManager = TemplateManager::instance();

	IffStream* iffStream = templateManager->openIffFile("datatables/clientregion/" + zone->getZoneName() + ".iff");

	Reference<PlanetMapCategory*> cityCat = TemplateManager::instance()->getPlanetMapCategoryByName("city");

	if (iffStream == NULL) {
		info("No client regions found.");
		return;
	}

	DataTableIff dtiff;
	dtiff.readObject(iffStream);

	for (int i = 0; i < dtiff.getTotalRows(); ++i) {
		String regionName;
		float x, y, radius;

		DataTableRow* row = dtiff.getRow(i);
		row->getValue(0, regionName);
		row->getValue(1, x);
		row->getValue(2, y);
		row->getValue(3, radius);

		ManagedReference<CityRegion*> cityRegion = regionMap.getRegion(regionName);

		if (cityRegion == NULL) {
			cityRegion = new CityRegion();
			cityRegion->deploy();
			cityRegion->setRegionName(regionName);
			cityRegion->setZone(zone);
			regionMap.addRegion(cityRegion);
		}

		ManagedReference<Region*> region = cityRegion->addRegion(x, y, radius, false);

		if (region != NULL) {
			if (cityRegion->getRegionsCount() == 1) {//Register the first region only.
				region->setPlanetMapCategory(cityCat);
				zone->registerObjectWithPlanetaryMap(region);
			}

			region->setMunicipalZone(true);
		}

		ManagedReference<ActiveArea*> noBuild = zone->getZoneServer()->createObject(String("object/active_area.iff").hashCode(), 0).castTo<ActiveArea*>();
		noBuild->initializePosition(x, 0, y);
		ManagedReference<CircularAreaShape*> areaShape = new CircularAreaShape();
		areaShape->setRadius(radius * 2);
		areaShape->setAreaCenter(x, y);
		noBuild->setAreaShape(areaShape);
		noBuild->setRadius(radius * 2);
		noBuild->setNoBuildArea(true);
		// Cities already have "Municipal" protection so the structure no-build should not apply to camps
		noBuild->setCampingPermitted(true);
		zone->transferObject(noBuild, -1, true);
	}

	info("Added " + String::valueOf(regionMap.getTotalRegions()) + " client regions.");
}
void DestroyMissionObjectiveImplementation::spawnLair() {
	ManagedReference<MissionObject* > mission = this->mission.get();

	ManagedReference<MissionSpawnActiveArea* > spawnActiveArea = this->spawnActiveArea;

	if (spawnActiveArea == NULL)
		return;

	if (lairObject != NULL && lairObject->getZone() != NULL)
		return;

	Zone* zone = spawnActiveArea->getZone();

	Locker locker(spawnActiveArea);

	spawnActiveArea->destroyObjectFromWorld(true);

	Vector3 pos = findValidSpawnPosition(zone);

	ManagedReference<WaypointObject*> waypoint = mission->getWaypointToMission();

	if (waypoint == NULL) {
		waypoint = mission->createWaypoint();
	}

	waypoint->setPosition(pos.getX(), 0, pos.getY());
	mission->updateMissionLocation();

	mission->setStartPosition(pos.getX(), pos.getY());

	//TODO: find correct string id
	ManagedReference<CreatureObject*> player = getPlayerOwner();

	if (player != NULL) {
		player->sendSystemMessage("Transmission Received: Mission Target has been located.  Mission waypoint has been updated to exact location");
	}

	LairTemplate* lair = CreatureTemplateManager::instance()->getLairTemplate(lairTemplate.hashCode());

	if (lair == NULL) {
		error("incorrect lair template in destroy mission objective " + lairTemplate);
		abort();
		return;
	}

	if (lairObject == NULL) {
		String buildingToSpawn = lair->getMissionBuilding(difficulty);

	 	if (buildingToSpawn.isEmpty()) {
	 		error("error spawning " + buildingToSpawn);
	 		abort();
	 		return;
	 	}

		lairObject = zone->getZoneServer()->createObject(buildingToSpawn.hashCode(), 0).castTo<LairObject*>();

	 	if (lairObject == NULL) {
	 		error("error spawning " + buildingToSpawn);
	 		abort();
	 		return;
	 	}

	 	Locker locker(lairObject);

	 	lairObject->setFaction(lair->getFaction());
	 	lairObject->setPvpStatusBitmask(CreatureFlag::ATTACKABLE);
	 	lairObject->setOptionsBitmask(0, false);
	 	lairObject->setMaxCondition(difficultyLevel * (900 + System::random(200)));
	 	lairObject->setConditionDamage(0, false);
	 	lairObject->initializePosition(pos.getX(), pos.getZ(), pos.getY());
	 	lairObject->setDespawnOnNoPlayersInRange(false);

		ManagedReference<MissionObserver*> observer = new MissionObserver(_this.get());
		addObserver(observer, true);

		lairObject->registerObserver(ObserverEventType::OBJECTDESTRUCTION, observer);

	 	ManagedReference<DestroyMissionLairObserver*> lairObserver = new DestroyMissionLairObserver();
	 	lairObserver->deploy();
	 	lairObserver->setLairTemplate(lair);
	 	lairObserver->setDifficulty(difficulty);
	 	lairObserver->setObserverType(ObserverType::LAIR);
	 	lairObserver->setSize(mission->getSize());

	 	lairObject->registerObserver(ObserverEventType::OBJECTDESTRUCTION, lairObserver);
	 	lairObject->registerObserver(ObserverEventType::DAMAGERECEIVED, lairObserver);
	 	lairObject->registerObserver(ObserverEventType::AIMESSAGE, lairObserver);
	 	lairObject->registerObserver(ObserverEventType::OBJECTREMOVEDFROMZONE, lairObserver);

		zone->transferObject(lairObject, -1, true);

		lairObserver->checkForNewSpawns(lairObject, NULL, true);
	}

	if (lairObject != NULL && lairObject->getZone() == NULL) {
		zone->transferObject(lairObject, -1, true);
	}
}