bool PlanetManagerImplementation::isBuildingPermittedAt(float x, float y, SceneObject* object, float margin) {
	SortedVector<ActiveArea*> activeAreas;

	Vector3 targetPos(x, y, 0);

	if (!zone->isWithinBoundaries(targetPos))
		return false;

	//targetPos.setZ(zone->getHeight(x, y)); not needed

	zone->getInRangeActiveAreas(x, y, &activeAreas, true);

	for (int i = 0; i < activeAreas.size(); ++i) {
		ActiveArea* area = activeAreas.get(i);

		if (area->isNoBuildArea()) {
			return false;
		}
	}

	if (isInObjectsNoBuildZone(x, y, margin)) {
		return false;
	}

	if (isInWater(x, y)) {
		return false;
	}

	if (isInRangeWithPoi(x, y, 150))
		return false;

	return true;
}
bool PlanetManagerImplementation::isCampingPermittedAt(float x, float y, float margin) {
	SortedVector<ManagedReference<ActiveArea* > > activeAreas;

	Vector3 targetPos(x, y, zone->getHeight(x, y));

	zone->getInRangeActiveAreas(x, y, &activeAreas, true);

	for (int i = 0; i < activeAreas.size(); ++i) {
		ActiveArea* area = activeAreas.get(i);

		// Skip areas explicitly marked as camping allowed
		if (area->isCampingPermitted()) {
			continue;
		}

		// Honor no-build after checking for areas that camping is explicitly allowed
		if (area->isNoBuildArea()) {
				return false;
		}
	}

	if (isInWater(x, y)) {
		return false;
	}

	if (isInRangeWithPoi(x, y, 150))
		return false;

	return true;
}
bool PlanetManagerImplementation::isSpawningPermittedAt(float x, float y, float margin) {
	SortedVector<ActiveArea*> activeAreas;

	Vector3 targetPos(x, y, zone->getHeight(x, y));

	if (!zone->isWithinBoundaries(targetPos))
		return false;

	zone->getInRangeActiveAreas(x, y, &activeAreas, true);
	zone->getInRangeActiveAreas(x, y, margin + 64.f, &activeAreas, true);

	for (int i = 0; i < activeAreas.size(); ++i) {
		ActiveArea* area = activeAreas.get(i);

		if (area->isRegion() || area->isMunicipalZone() || area->isNoSpawnArea()) {
			return false;
		}
	}

	if (isInObjectsNoBuildZone(x, y, margin)) {
		return false;
	}

	if (isInWater(x, y)) {
		return false;
	}

	if (isInRangeWithPoi(x, y, 150))
		return false;

	if (terrainManager->getHighestHeightDifference(x - 10, y - 10, x + 10, y + 10) > 15.0)
		return false;

	return true;
}
bool PlanetManagerImplementation::isBuildingPermittedAt(float x, float y, SceneObject* object, float margin) {
	SortedVector<ManagedReference<ActiveArea* > > activeAreas;

	Vector3 targetPos(x, y, zone->getHeight(x, y));

	zone->getInRangeActiveAreas(x, y, &activeAreas, true);

	for (int i = 0; i < activeAreas.size(); ++i) {
		ActiveArea* area = activeAreas.get(i);

		if (area->isNoBuildArea()) {
			return false;
		}
	}

	if (isInObjectsNoBuildZone(x, y, margin)) {
		return false;
	}

	if (isInWater(targetPos.getX(), targetPos.getY())) {
		return false;
	}

	if (isInRangeWithPoi(targetPos.getX(), targetPos.getY(), 150))
		return false;

	return true;
}
Пример #5
0
int StructureManager::placeStructureFromDeed(CreatureObject* creature,
		StructureDeed* deed, float x, float y, int angle) {
	ManagedReference<Zone*> zone = creature->getZone();

	//Already placing a structure?
	if (zone == NULL
			|| creature->containsActiveSession(
					SessionFacadeType::PLACESTRUCTURE))
		return 1;

	ManagedReference<PlanetManager*> planetManager = zone->getPlanetManager();

	String serverTemplatePath = deed->getGeneratedObjectTemplate();

	if (deed->getFaction() != 0 && creature->getFaction() != deed->getFaction()) {
		creature->sendSystemMessage("You are not the correct faction");
		return 1;
	}
	Reference<SharedStructureObjectTemplate*> serverTemplate =
			dynamic_cast<SharedStructureObjectTemplate*>(templateManager->getTemplate(
					serverTemplatePath.hashCode()));

	//Check to see if this zone allows this structure.
	if (serverTemplate == NULL
			|| !serverTemplate->isAllowedZone(zone->getZoneName())) {
		creature->sendSystemMessage("@player_structure:wrong_planet"); //That deed cannot be used on this planet.
		return 1;
	}

	if (!planetManager->isBuildingPermittedAt(x, y, creature)) {
		creature->sendSystemMessage("@player_structure:not_permitted"); //Building is not permitted here.
		return 1;
	}

	SortedVector<ManagedReference<ActiveArea*> > objects;
	zone->getInRangeActiveAreas(x, y, &objects, true);

	ManagedReference<CityRegion*> city;

	for (int i = 0; i < objects.size(); ++i) {
		ActiveArea* area = objects.get(i).get();

		if (!area->isRegion())
			continue;

		city = dynamic_cast<Region*>(area)->getCityRegion();

		if (city != NULL)
			break;
	}


	SortedVector<ManagedReference<QuadTreeEntry*> > inRangeObjects;
	zone->getInRangeObjects(x, y, 128, &inRangeObjects, true);

	float placingFootprintLength0, placingFootprintWidth0, placingFootprintLength1, placingFootprintWidth1;

	if (!getStructureFootprint(serverTemplate, angle, placingFootprintLength0, placingFootprintWidth0, placingFootprintLength1, placingFootprintWidth1)) {
		float x0 = x + placingFootprintWidth0;
		float y0 = y + placingFootprintLength0;
		float x1 = x + placingFootprintWidth1;
		float y1 = y + placingFootprintLength1;

		BoundaryRectangle placingFootprint(x0, y0, x1, y1);

		//info("placing center x:" + String::valueOf(x) + " y:" + String::valueOf(y), true);
		//info("placingFootprint x0:" + String::valueOf(x0) + " y0:" + String::valueOf(y0) + " x1:" + String::valueOf(x1) + " y1:" + String::valueOf(y1), true);

		for (int i = 0; i < inRangeObjects.size(); ++i) {
			SceneObject* scene = inRangeObjects.get(i).castTo<SceneObject*>();

			if (scene == NULL)
				continue;

			float l0 = -5; //Along the x axis.
			float w0 = -5; //Along the y axis.
			float l1 = 5;
			float w1 = 5;

			if (getStructureFootprint(scene->getObjectTemplate(), scene->getDirectionAngle(), l0, w0, l1, w1))
				continue;

			float xx0 = scene->getPositionX() + (w0 + 0.1);
			float yy0 = scene->getPositionY() + (l0 + 0.1);
			float xx1 = scene->getPositionX() + (w1 - 0.1);
			float yy1 = scene->getPositionY() + (l1 - 0.1);

			BoundaryRectangle rect(xx0, yy0, xx1, yy1);

			//info("existing footprint xx0:" + String::valueOf(xx0) + " yy0:" + String::valueOf(yy0) + " xx1:" + String::valueOf(xx1) + " yy1:" + String::valueOf(yy1), true);

			// check 4 points of the current rect
			if (rect.containsPoint(x0, y0)
					|| rect.containsPoint(x0, y1)
					|| rect.containsPoint(x1, y0)
					|| rect.containsPoint(x1, y1) ) {

				//info("existing footprint contains placing point", true);

				creature->sendSystemMessage("@player_structure:no_room"); //there is no room to place the structure here..

				return 1;
			}

			if (placingFootprint.containsPoint(xx0, yy0)
					|| placingFootprint.containsPoint(xx0, yy1)
					|| placingFootprint.containsPoint(xx1, yy0)
					|| placingFootprint.containsPoint(xx1, yy1)
					|| (xx0 == x0 && yy0 == y0 && xx1 == x1 && yy1 == y1)) {
				//info("placing footprint contains existing point", true);

				creature->sendSystemMessage("@player_structure:no_room"); //there is no room to place the structure here.

				return 1;
			}
		}
	}

	int rankRequired = serverTemplate->getCityRankRequired();

	if (city == NULL && rankRequired > 0) {
		creature->sendSystemMessage("@city/city:build_no_city");
		return 1;
	}

	if (city != NULL) {
		if (city->isZoningEnabled()
				&& !city->hasZoningRights(creature->getObjectID())) {
			creature->sendSystemMessage("@player_structure:no_rights"); //You don't have the right to place that structure in this city. The mayor or one of the city milita must grant you zoning rights first.
			return 1;
		}

		if (rankRequired != 0 && city->getCityRank() < rankRequired) {
			StringIdChatParameter param("city/city", "rank_req");
			param.setDI(rankRequired);
			param.setTO("city/city", "rank" + String::valueOf(rankRequired));

			creature->sendSystemMessage(param);
			return 1;
		}

		if (serverTemplate->isCivicStructure() && !city->isMayor(creature->getObjectID()) ) {
				creature->sendSystemMessage("@player_structure:cant_place_civic");//"This structure must be placed within the borders of the city in which you are mayor."
				return 1;
		}

		if (serverTemplate->isUniqueStructure()
				&& city->hasUniqueStructure(
						serverTemplate->getServerObjectCRC())) {
			creature->sendSystemMessage("@player_structure:cant_place_unique"); //This city can only support a single structure of this type.
			return 1;
		}

	}

	Locker _lock(deed, creature);


	if(serverTemplate->isDerivedFrom("object/building/faction_perk/base/shared_factional_building_base.iff")){
		Zone* zone = creature->getZone();
		if(zone == NULL)
			return 1;

		GCWManager* gcwMan = zone->getGCWManager();
		if(gcwMan == NULL)
			return 1;

		if(!gcwMan->canPlaceMoreBases(creature))
			return 1;
	}

	//Ensure that it is the correct deed, and that it is in a container in the creature's inventory.
	if (deed == NULL || !deed->isASubChildOf(creature)) {
		creature->sendSystemMessage("@player_structure:no_possession"); //You no longer are in possession of the deed for this structure. Aborting construction.
		return 1;
	}

	TemplateManager* templateManager = TemplateManager::instance();

	ManagedReference<PlayerObject*> ghost = creature->getPlayerObject();

	if (ghost != NULL) {
		String abilityRequired = serverTemplate->getAbilityRequired();

		if (!abilityRequired.isEmpty() && !ghost->hasAbility(abilityRequired)) {
			creature->sendSystemMessage("@player_structure:" + abilityRequired);
			return 1;
		}

		int lots = serverTemplate->getLotSize();

		if (!ghost->hasLotsRemaining(lots)) {
			StringIdChatParameter param("@player_structure:not_enough_lots");
			param.setDI(lots);
			creature->sendSystemMessage(param);
			return 1;
		}
	}

	//Validate that the structure can be placed at the given coordinates:
	//Ensure that no other objects impede on this structures footprint, or overlap any city regions or no build areas.
	//Make sure that the player has zoning rights in the area.

	ManagedReference<PlaceStructureSession*> session =
			new PlaceStructureSession(creature, deed);
	creature->addActiveSession(SessionFacadeType::PLACESTRUCTURE, session);

	//Construct the structure.
	session->constructStructure(x, y, angle);

	//Remove the deed from it's container.
	deed->destroyObjectFromWorld(true);

	return 0;
}
void ZoneImplementation::updateActiveAreas(TangibleObject* tano) {
	//Locker locker(_this.getReferenceUnsafeStaticCast());

	Locker _alocker(tano->getContainerLock());

	SortedVector<ManagedReference<ActiveArea* > > areas = *dynamic_cast<SortedVector<ManagedReference<ActiveArea* > >* >(tano->getActiveAreas());

	_alocker.release();

	Vector3 worldPos = tano->getWorldPosition();

	SortedVector<ManagedReference<QuadTreeEntry*> > entryObjects;

	Zone* managedRef = _this.getReferenceUnsafeStaticCast();

	bool readlock = !managedRef->isLockedByCurrentThread();

	managedRef->rlock(readlock);

	try {
		regionTree->inRange(worldPos.getX(), worldPos.getY(), entryObjects);
	} catch (...) {
		error("unexpeted error caught in void ZoneImplementation::updateActiveAreas(SceneObject* object) {");
	}

	managedRef->runlock(readlock);

	//locker.release();


	managedRef->unlock(!readlock);

	try {

		// update old ones
		for (int i = 0; i < areas.size(); ++i) {
			ManagedReference<ActiveArea*> area = areas.get(i);
//			Locker lockerO(object);

//			Locker locker(area, object);

			if (!area->containsPoint(worldPos.getX(), worldPos.getY(), tano->getParentID())) {
				tano->dropActiveArea(area);
				area->enqueueExitEvent(tano);
//				area->notifyExit(object);
			} else {
				area->notifyPositionUpdate(tano);
			}
		}

		// we update the ones in quadtree.
		for (int i = 0; i < entryObjects.size(); ++i) {
			//update in new ones
			ActiveArea* activeArea = dynamic_cast<ActiveArea*>(entryObjects.get(i).get());

			if (!tano->hasActiveArea(activeArea) && activeArea->containsPoint(worldPos.getX(), worldPos.getY(), tano->getParentID())) {
				//Locker lockerO(object);

				//Locker locker(activeArea, object);

				tano->addActiveArea(activeArea);
				activeArea->enqueueEnterEvent(tano);
				//activeArea->notifyEnter(object);
			}
		}

		// update world areas
		if (creatureManager != NULL) {
			Vector<ManagedReference<SpawnArea*> >* worldAreas = creatureManager->getWorldSpawnAreas();

			if (worldAreas != NULL) {
				for (int i = 0; i < worldAreas->size(); ++i) {
					ActiveArea* activeArea = worldAreas->get(i);
					Locker lockerO(tano);

					//			Locker locker(activeArea, object);

					if (!tano->hasActiveArea(activeArea)) {
						tano->addActiveArea(activeArea);
						//activeArea->enqueueEnterEvent(object);
						activeArea->notifyEnter(tano);
					} else {
						activeArea->notifyPositionUpdate(tano);
					}
				}
			}
		}
	} catch (...) {
		error("unexpected exception caught in void ZoneImplementation::updateActiveAreas(SceneObject* object) {");
		managedRef->wlock(!readlock);
		throw;
	}

	managedRef->wlock(!readlock);
}
int EventPerkDeedImplementation::handleObjectMenuSelect(CreatureObject* player, byte selectedID) {

	if (selectedID == 20) {
		if (generated) {
			return 1;
		}

		Zone* zone = player->getZone();

		if (zone == NULL) {
			return 1;
		}

		PlanetManager* planetManager = zone->getPlanetManager();
		if (planetManager == NULL) {
			return 1;
		}

		EventPerkDeedTemplate* deedTemplate = cast<EventPerkDeedTemplate*>(getObjectTemplate());
		if (deedTemplate == NULL) {
			return 1;
		}

		if (zone->getZoneName().contains("space_")) {
			player->sendSystemMessage("@event_perk:not_in_space"); // You may not deploy a Rental in space. Return to the ground first.
			return 1;
		}

		if (!deedTemplate->isAllowedZone(zone->getZoneName())) {
			player->sendSystemMessage("@event_perk:not_on_this_planet"); // You cannot deploy this rental on this planet. Examine the deed to determine the intended planet for this rental.
			return 1;
		}

		if (!isASubChildOf(player)) {
			player->sendSystemMessage("@event_perk:from_inventory_only"); // This rental must be in your inventory in order to be deployed.
			return 1;
		}

		if (player->getParent() != NULL) {
			player->sendSystemMessage("@event_perk:not_inside"); // You cannot deploy a Rental indoors. You must move outside.
			return 1;
		}

		if (player->isInCombat()) {
			player->sendSystemMessage("@event_perk:not_in_combat"); // You cannot deploy a Rental while in combat.
			return 1;
		}

		if (player->isSwimming()) {
			player->sendSystemMessage("@event_perk:not_while_swimming"); // You cannot deploy a Rental while swimming.
			return 1;
		}

		ManagedReference<CityRegion*> city = player->getCityRegion().get();

		if (city != NULL) {
			if (city->isClientRegion()) {
				player->sendSystemMessage("@event_perk:not_in_municipal_zone"); // You may not place a Rental in a municipal zone.
				return 1;
			}

			if (city->isZoningEnabled() && !city->hasZoningRights(player->getObjectID())) {
				player->sendSystemMessage("@event_perk:no_zoning_rights"); // You must have zoning rights to place a Rental in this city.
				return 1;
			}
		}

		int x = player->getWorldPositionX();
		int y = player->getWorldPositionY();
		int nearbyPerks = 0;

		TerrainManager* terrainManager = planetManager->getTerrainManager();
		if ( terrainManager == NULL || terrainManager->getHighestHeightDifference(x - 10, y - 10, x + 10, y + 10) > 15.0) {
			player->sendSystemMessage("@event_perk:bad_area"); // This rental could not be deployed due to the surrounding terrain. Please move to another area and try again.
			return 1;
		}

		SortedVector<ManagedReference<QuadTreeEntry* > >* closeObjects = player->getCloseObjects();

		if (closeObjects == NULL) {
			error("Player has NULL closeObjectsVector in EventPerkDeedImplementation::handleObjectMenuSelect");
			return 1;
		}

		for (int i = 0; i < closeObjects->size(); ++i) {
			SceneObject* obj = cast<SceneObject*>(closeObjects->get(i).get());

			if (obj == NULL) {
				continue;
			}

			SharedObjectTemplate* objectTemplate = obj->getObjectTemplate();
			if (objectTemplate == NULL) {
				continue;
			}

			float radius = objectTemplate->getNoBuildRadius();

			if (obj->isLairObject() && player->isInRange(obj, radius)) {
				player->sendSystemMessage("@event_perk:too_close_lair"); // You cannot place a Rental this close to a lair.
				return 1;
			}

			if (obj->isCampStructure() && player->isInRange(obj, radius)) {
				player->sendSystemMessage("@event_perk:too_close_camp"); // You cannot place a Rental this close to a camp.
				return 1;
			}

			if (radius > 0 && player->isInRange(obj, radius)) {
				player->sendSystemMessage("@event_perk:too_close_something"); // You are too close to an object to deploy your Rental here. Move away from it.
				return 1;
			}

			if (objectTemplate->isSharedStructureObjectTemplate()) {
				if (StructureManager::instance()->isInStructureFootprint(cast<StructureObject*>(obj), x, y, 0)) {
					player->sendSystemMessage("@event_perk:too_close_building"); // You may not place a Rental this close to a building.
					return 1;
				}
			}

			if (obj->isEventPerk() && player->isInRange(obj, 32) && ++nearbyPerks > 2) {
				player->sendSystemMessage("@event_perk:too_many_perks"); // There are too many Rentals already deployed in this area. Please move to another location.
				return 1;
			}
		}

		SortedVector<ManagedReference<ActiveArea* > > activeAreas;
		zone->getInRangeActiveAreas(x, y, &activeAreas, true);

		for (int i = 0; i < activeAreas.size(); ++i) {
			ActiveArea* area = activeAreas.get(i);

			if (area->isNoBuildArea()) {
				player->sendSystemMessage("@event_perk:too_close_something"); // You are too close to an object to deploy your Rental here. Move away from it.
				return 1;
			}
		}

		if (planetManager->isInRangeWithPoi(x, y, 150)) {
			player->sendSystemMessage("@event_perk:too_close_something"); // You are too close to an object to deploy your Rental here. Move away from it.
			return 1;
		}

		if (perkType != EventPerkDeedTemplate::STATIC) {
			player->sendSystemMessage("This type of event perk deed is not functional yet.");
			return 1;
		}

		ManagedReference<TangibleObject*> object = generatedObject.get();

		if (object == NULL) {
			object = (server->getZoneServer()->createObject(generatedObjectTemplate.hashCode(), "playerstructures", 1)).castTo<TangibleObject*>();

			if (object == NULL) {
				player->sendSystemMessage("Error generating object. Wrong generatedObjectTemplate or is not a tangible object.");
				return 1;
			}

			generatedObject = object;
		}

		EventPerkDataComponent* data = cast<EventPerkDataComponent*>(object->getDataObjectComponent()->get());

		if (data == NULL) {
			player->sendSystemMessage("Error: no dataObjectComponent.");
			object->destroyObjectFromDatabase();
			return 1;
		}

		data->setDeed(_this.get());

		object->initializePosition(player->getPositionX(), player->getPositionZ(), player->getPositionY());
		object->setDirection(Math::deg2rad(player->getDirectionAngle()));
		zone->transferObject(object, -1, true);

		generated = true;
		destroyObjectFromWorld(true);

		return 0;
	}

	return DeedImplementation::handleObjectMenuSelect(player, selectedID);
}