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; }
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); }