//----------------------------------------------------------------------- void EditorOperation::execute() { if ( getScene() ) { TerrainManager* terrain = getScene()->getTerrainManager(); if ( terrain ) { Ogre::Rect rect = BrushSystem::getInstance().getActiveRect(); UInt chunkCount = terrain->getTerrainChunkCount(); for (UInt i=0;i<chunkCount; i++) { TerrainChunk* chunk = terrain->getTerrainChunkByIndex(i); if ( chunk ) { Ogre::Rect chunkRect = rect.intersect( chunk->getBoundingRect() ); if ( chunkRect.isNull() == false ) { execute( chunk, chunkRect ); } } } } } }
void RenderManager::AddTerrainToRenderer(TerrainManager &t) { terrain = SetupVAO(t.GetTerrainMesh()); terrainSize = t.GetTerrainMesh().GetSize(); terrainManager = &t; water = SetupVAO(t.GetWaterMesh()); }
float ZoneImplementation::getHeight(float x, float y) { if (planetManager != NULL) { TerrainManager* manager = planetManager->getTerrainManager(); if (manager != NULL) return manager->getHeight(x, y); } return 0; }
Vector3 MissionObjectiveImplementation::getEndPosition() { ManagedReference<MissionObject* > mission = this->mission.get(); Vector3 missionEndPoint; missionEndPoint.setX(mission->getEndPositionX()); missionEndPoint.setY(mission->getEndPositionY()); TerrainManager* terrain = getPlayerOwner().get()->getZone()->getPlanetManager()->getTerrainManager(); missionEndPoint.setZ(terrain->getHeight(missionEndPoint.getX(), missionEndPoint.getY())); return missionEndPoint; }
Vector3 ReconMissionObjectiveImplementation::getEndPosition() { ManagedReference<MissionObject* > mission = this->mission.get(); Vector3 missionEndPoint; missionEndPoint.setX(mission->getStartPositionX()); missionEndPoint.setY(mission->getStartPositionY()); Zone* zone = getPlayerOwner().get()->getZone(); if (zone != NULL) { TerrainManager* terrain = zone->getPlanetManager()->getTerrainManager(); missionEndPoint.setZ(terrain->getHeight(missionEndPoint.getX(), missionEndPoint.getY())); } return missionEndPoint; }
StructureObject* StructureManager::placeStructure(CreatureObject* creature, const String& structureTemplatePath, float x, float y, int angle, int persistenceLevel) { ManagedReference<Zone*> zone = creature->getZone(); if (zone == NULL) return NULL; TerrainManager* terrainManager = zone->getPlanetManager()->getTerrainManager(); SharedStructureObjectTemplate* serverTemplate = dynamic_cast<SharedStructureObjectTemplate*>(templateManager->getTemplate( structureTemplatePath.hashCode())); if (serverTemplate == NULL) { info("server template is null"); return NULL; } float z = zone->getHeight(x, y); float floraRadius = serverTemplate->getClearFloraRadius(); bool snapToTerrain = serverTemplate->getSnapToTerrain(); Reference<StructureFootprint*> structureFootprint = serverTemplate->getStructureFootprint(); float w0 = -5; //Along the x axis. float l0 = -5; //Along the y axis. float l1 = 5; float w1 = 5; float zIncreaseWhenNoAvailableFootprint = 0.f; //TODO: remove this when it has been verified that all buildings have astructure footprint. if (structureFootprint != NULL) { //If the angle is odd, then swap them. getStructureFootprint(serverTemplate, angle, l0, w0, l1, w1); } else { if (!serverTemplate->isCampStructureTemplate()) warning( "Structure with template '" + structureTemplatePath + "' has no structure footprint."); zIncreaseWhenNoAvailableFootprint = 5.f; } if (floraRadius > 0 && !snapToTerrain) z = terrainManager->getHighestHeight(x + w0, y + l0, x + w1, y + l1, 1) + zIncreaseWhenNoAvailableFootprint; String strDatabase = "playerstructures"; bool bIsFactionBuilding = (serverTemplate->getGameObjectType() == SceneObjectType::FACTIONBUILDING); if (bIsFactionBuilding || serverTemplate->getGameObjectType() == SceneObjectType::TURRET) { strDatabase = "playerstructures"; } ManagedReference<SceneObject*> obj = ObjectManager::instance()->createObject( structureTemplatePath.hashCode(), persistenceLevel, strDatabase); if (obj == NULL || !obj->isStructureObject()) { if (obj != NULL) obj->destroyObjectFromDatabase(true); error( "Failed to create structure with template: " + structureTemplatePath); return NULL; } StructureObject* structureObject = cast<StructureObject*>(obj.get()); structureObject->setOwnerObjectID(creature->getObjectID()); structureObject->grantPermission("ADMIN", creature->getFirstName()); structureObject->setOwnerName(creature->getFirstName()); if(structureObject->isTurret() || structureObject->isMinefield()){ structureObject->setFaction(creature->getFaction()); } BuildingObject* buildingObject = NULL; if (structureObject->isBuildingObject()) { buildingObject = cast<BuildingObject*>(structureObject); if (buildingObject != NULL) buildingObject->createCellObjects(); } structureObject->setPublicStructure(serverTemplate->isPublicStructure()); structureObject->initializePosition(x, z, y); structureObject->rotate(angle); //structureObject->insertToZone(zone); zone->transferObject(structureObject, -1, true); structureObject->createChildObjects(); structureObject->notifyStructurePlaced(creature); return structureObject; }
int main(int argc, char** argv) { if (argc == 3 && strncmp(argv[1], "--convert", 9) == 0) { Configuration* config = new IniConfig(argv[2]); Heightmap* map = new Heightmap(config->getFloatValue("terrain","spacing")); if (map->loadFromImage(config->getValue("terrain","heightmap").c_str())) { std::cout << "Generating Terrain.." << std::endl; TerrainGenerator(map, config->getIntValue("terrain","chunksize"), config->getValue("out","filename").c_str()); std::cout << "..done" << std::endl; std::cout.flush(); } else std::cout << "Generation failed." << std::endl; return 0; } if (argc == 4 && strncmp(argv[1], "--load", 6) == 0) { int id = atoi(argv[3]); TerrainFileReader* reader = new TerrainFileReader(); reader->openFile(argv[2]); TerrainChunk* tc = reader->readId(id); if (tc == NULL || tc->getInfo()->getQuadId() != id) { std::cout << "Got ID" << tc->getInfo()->getQuadId() << " instead of " << id << std::endl; return 1; } else { std::cout << "Successfully got Terrainchunk " << id << std::endl; std::cout << "Spacing of Heightmap is " << tc->getHeightmap()->getSpacing() << " where origin is " << tc->getOrigin().x << "," << tc->getOrigin().y << " and center at " << tc->getCenter().x << "," << tc->getCenter().y << std::endl; } reader->closeFile(); delete tc; delete reader; } if (argc != 2 || strncmp(argv[1], "--run", 5) != 0) { std::cout << "Usage of '" << argv[0] << "'" <<std::endl; std::cout << "\nAvailable Parameter:" << "\n\t--convert terrain.desc" << "\n\t--load terrain.terr chunkid(=0)" << "\n\t--run" << std::endl; return 1; } int width, height; Configuration * win_config = new IniConfig("config.ini"); WindowHints* hints = new WindowHints(); hints->Fullscreen = win_config->getBooleanValue("Window","fullscreen"); hints->Width = win_config->getIntValue("Window","width"); hints->Height = win_config->getIntValue("Window","height"); GraphicsSystem* GSystem = new GraphicsSystem(GraphicsSystem::PROFILE_GL3, hints); if (GSystem->isError()) return -1; GraphicsContext* grctx = GSystem->getGraphicsContext(); Window* win = GSystem->getWindow(); TextureManager* tmgr = new TextureManager(grctx); ModelLoader* mmgr = new ModelLoader(grctx, tmgr); TerrainManager* terrmgr = new TerrainManager(grctx); Model* mdl, *mdl2; Camera* cam = new Camera(); win->getSize(&width, &height); cam->setScreen(width,height); cam->setupLens(65.0f, 1.0f, 1000.0f); if ((mdl = mmgr->loadAsset("Resources/Models/ant01.ms3d")) == NULL) std::cerr << "Could not load Model" << std::endl; if ((mdl2 = mmgr->loadAsset("Resources/Models/dwarf1.ms3d")) == NULL) std::cerr << "Could not load Model" << std::endl; ModelAnimationController mdlanictrl(mdl), mdlanictrl2(mdl2); mdlanictrl.addAnimation("idle", 52, 67, 0.25f, true); mdlanictrl.addAnimation("die", 30, 49, 0.25f, false); mdlanictrl2.addAnimation("begin_walk", 1, 2, 0.25f, false, "walk"); mdlanictrl2.addAnimation("walk", 2, 14, 0.25f, true); mdlanictrl2.addAnimation("jump", 28, 40, 0.5f, false, "begin_walk"); mdlanictrl2.addAnimation("idle", 292, 325, 0.25f, false, "idle2"); mdlanictrl2.addAnimation("idle2", 327, 360, 0.25f, true); mdlanictrl2.addAnimation("die", 230, 251, 0.25f, false); std::cout << "Using DesktopMode: " << width << "x" << height << std::endl; win->setTitle("Xng?! -> Yeah!"); Shader* sh = grctx->createShader(); if (!sh->loadFromFile("Shader/Animation.vs", "Shader/Animation.fs")) return 1; Shader* tsh = grctx->createShader(); if (!tsh->loadFromFile("Shader/Terrain.vs", "Shader/Terrain.fs")) return 1; Timer* t = new Timer(); double frames = 0; grctx->setClearColor(glm::vec4(1.0f, 0.5f, 0.25f, 1.0f)); t->start(); Terrain* terr = terrmgr->loadAsset("Resources/terrain/terrain.terr"); terr->setDetail(0.05f,cam); glm::mat4 mdlm = glm::scale( glm::translate(glm::mat4(1.0f), glm::vec3(5.0f, -5.0f, -20.0f)), glm::vec3(0.5f)); glm::mat4 mdlm2 = glm::scale( glm::translate(glm::mat4(1.0f), glm::vec3(-5.0f, -5.0f, -20.0f)), glm::vec3(0.18f)); mdlm = glm::rotate(mdlm, 180.0f, glm::vec3(0.0f, 1.0f, 0.0f)); mdlm2 = glm::rotate(mdlm2, 180.0f, glm::vec3(0.0f, 1.0f, 0.0f)); glm::vec3 cam_pos = glm::vec3(0.0f,0.0f,0.0f); glm::quat cam_orient = glm::quat(); float speed = 0.0f; float deltaTime = 0; float second = t->getMilli(); float lastTime = second; while (win->isOpen()) { second = t->getMilli(); deltaTime = second - lastTime; lastTime = second; if (glfwGetKey(GLFW_KEY_ESC)) break; if (glfwGetKey(GLFW_KEY_SPACE)) mdlanictrl2.setActiveAnimation("jump"); if (glfwGetKey('W')) mdlanictrl2.setActiveAnimation("begin_walk"); if (glfwGetKey('S')) mdlanictrl2.setActiveAnimation("idle"); if (glfwGetKey('F')) mdlanictrl.setActiveAnimation("die"); if (glfwGetKey('G')) mdlanictrl2.setActiveAnimation("die"); if (glfwGetKey('A')) mdlm2 = glm::rotate(mdlm2, -0.3f, glm::vec3(0.0f, 1.0f, 0.0f)); if (glfwGetKey('D')) mdlm2 = glm::rotate(mdlm2, 0.3f, glm::vec3(0.0f, 1.0f, 0.0f)); if( glfwGetKey(GLFW_KEY_LSHIFT) || glfwGetKey(GLFW_KEY_RSHIFT)) speed = 1.0f; else speed = 0.1f; if (glfwGetKey('I')) cam_pos += glm::cross(cam->getUpVector(),cam->getRightVector()) * speed * deltaTime; if (glfwGetKey('K')) cam_pos -= glm::cross(cam->getUpVector(),cam->getRightVector()) * speed * deltaTime; if (glfwGetKey('J')) cam_pos -= cam->getRightVector() * speed * deltaTime; if (glfwGetKey('L')) cam_pos += cam->getRightVector() * speed * deltaTime; if (glfwGetKey('O')) cam_pos += cam->getUpVector() * speed * deltaTime; if (glfwGetKey('P')) cam_pos -= cam->getUpVector() * speed * deltaTime; if(glfwGetKey(GLFW_KEY_LEFT)) cam_orient = glm::rotate(cam_orient,speed * deltaTime,glm::vec3(0.0f,1.0f,0.0f)); if(glfwGetKey(GLFW_KEY_RIGHT)) cam_orient =glm::rotate(cam_orient,-speed * deltaTime,glm::vec3(0.0f,1.0f,0.0f)); if(glfwGetKey(GLFW_KEY_UP)) cam_orient = glm::rotate(cam_orient,speed * deltaTime,glm::vec3(1.0f,0.0f,0.0f)); if(glfwGetKey(GLFW_KEY_DOWN)) cam_orient = glm::rotate(cam_orient,-speed * deltaTime,glm::vec3(1.0f,0.0f,0.0f)); cam_pos.y = terr->getHeightAt(cam_pos.x,cam_pos.z) + 5; cam->setPosition(cam_pos); cam->setOrientation(cam_orient); mdlanictrl.update(deltaTime); mdlanictrl2.update(deltaTime); grctx->clearDisplay(); grctx->setShader(sh); grctx->setProjectionMatrix(cam->getLens()); grctx->setViewMatrix(cam->getView()); grctx->setModelMatrix(&mdlm); for (int i = 0; i < mdl->getNumMeshes(); i++) { grctx->setMesh(mdl->getMesh(i)); grctx->setMaterial(mdl->getMaterial(mdl->getMesh(i)->getMaterialId())); grctx->setBoneTransformation(mdlanictrl.getBoneTransformation(), mdlanictrl.getNumBones()); grctx->draw(); } grctx->setModelMatrix(&mdlm2); for (int i = 0; i < mdl2->getNumMeshes(); i++) { grctx->setMesh(mdl2->getMesh(i)); grctx->setMaterial(mdl2->getMaterial(mdl2->getMesh(i)->getMaterialId())); grctx->setBoneTransformation(mdlanictrl2.getBoneTransformation(), mdlanictrl2.getNumBones()); grctx->draw(); } grctx->setShader(tsh); grctx->setProjectionMatrix(cam->getLens()); grctx->setViewMatrix(cam->getView()); terr->selectNodes(cam); grctx->swapBuffers(); frames++; } t->end(); delete sh; mmgr->removeAsset("Resources/Models/dwarf1.ms3d"); mmgr->removeAsset("Resources/Models/ant01.ms3d"); std::cout << "TpF: " << t->getLastMilli() / frames << " mspf was " << frames << " Frames in " << t->getLastMilli() << "ms or " << frames / t->getLastSecond() << "fps" << std::endl; delete mmgr; delete tmgr; delete t; delete GSystem; return 0; }
bool CollisionManager::checkShipCollision(ShipObject* ship, const Vector3& targetPosition, Vector3& collisionPoint) { Zone* zone = ship->getZone(); if (zone == NULL) return false; TerrainManager* terrainManager = zone->getPlanetManager()->getTerrainManager(); if (terrainManager->getProceduralTerrainAppearance() != NULL) { float height = terrainManager->getHeight(targetPosition.getX(), targetPosition.getY()); float waterHeight = -16368.f; if (terrainManager->getWaterHeight(targetPosition.getY(), targetPosition.getY(), waterHeight)) height = MAX(waterHeight, height); if (height > targetPosition.getZ()) { collisionPoint = targetPosition; collisionPoint.setZ(height); //ship->info("colliding with terrain", true); return true; } } Vector3 rayOrigin = ship->getWorldPosition(); rayOrigin.set(rayOrigin.getX(), rayOrigin.getY(), rayOrigin.getZ()); Vector3 rayEnd; rayEnd.set(targetPosition.getX(), targetPosition.getY(), targetPosition.getZ()); float dist = rayEnd.distanceTo(rayOrigin); float intersectionDistance; Triangle* triangle = NULL; SortedVector<ManagedReference<QuadTreeEntry*> > objects(512, 512); zone->getInRangeObjects(targetPosition.getX(), targetPosition.getY(), 512, &objects, true); for (int i = 0; i < objects.size(); ++i) { AABBTree* aabbTree = NULL; SceneObject* scno = cast<SceneObject*>(objects.get(i).get()); try { aabbTree = getAABBTree(scno, -1); if (aabbTree == NULL) continue; } catch (Exception& e) { aabbTree = NULL; } catch (...) { throw; } if (aabbTree != NULL) { //moving ray to model space try { Ray ray = convertToModelSpace(rayOrigin, rayEnd, scno); //structure->info("checking ray with building dir" + String::valueOf(structure->getDirectionAngle()), true); if (aabbTree->intersects(ray, dist, intersectionDistance, triangle, true)) { //rayOrigin.set(rayOrigin.getX(), rayOrigin.getY(), rayOrigin.getZ()); Vector3 direction = rayEnd - rayOrigin; direction.normalize(); //intersectionDistance -= 0.5f; collisionPoint.set(rayOrigin.getX() + (direction.getX() * intersectionDistance), rayOrigin.getY() + (direction.getY() * intersectionDistance), rayOrigin.getZ() + (direction.getZ() * intersectionDistance)); //ship->info("colliding with building", true); return true; } } catch (Exception& e) { ship->error(e.getMessage()); } catch (...) { throw; } } } return false; }
float CollisionManager::getWorldFloorCollision(float x, float y, Zone* zone, bool testWater) { SortedVector<ManagedReference<QuadTreeEntry*> > closeObjects; zone->getInRangeObjects(x, y, 128, &closeObjects, true); PlanetManager* planetManager = zone->getPlanetManager(); if (planetManager == NULL) return 0.f; float height = 0; TerrainManager* terrainManager = planetManager->getTerrainManager(); //need to include exclude affectors in the terrain calcs height = terrainManager->getHeight(x, y); Vector3 rayStart(x, 16384.f, y); Vector3 rayEnd(x, -16384.f, y); Triangle* triangle = NULL; if (testWater) { float waterHeight; if (terrainManager->getWaterHeight(x, y, waterHeight)) if (waterHeight > height) height = waterHeight; } float intersectionDistance; for (int i = 0; i < closeObjects.size(); ++i) { BuildingObject* building = dynamic_cast<BuildingObject*>(closeObjects.get(i).get()); if (building == NULL) continue; //building->getObjectTemplate()->get SharedObjectTemplate* templateObject = building->getObjectTemplate(); if (templateObject == NULL) continue; PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) continue; if (portalLayout->getFloorMeshNumber() == 0) continue; //find nearest entrance FloorMesh* exteriorFloorMesh = portalLayout->getFloorMesh(0); // get outside layout AABBTree* aabbTree = exteriorFloorMesh->getAABBTree(); if (aabbTree == NULL) continue; Ray ray = convertToModelSpace(rayStart, rayEnd, building); if (aabbTree->intersects(ray, 16384 * 2, intersectionDistance, triangle, true)) { float floorHeight = 16384 - intersectionDistance; if (floorHeight > height) height = floorHeight; } } return height; }
TerrainCache::lru_value_t run(const float& k, const float& k2) { float height = terrainData->getUnCachedHeight(k , k2); return std::make_pair(new HeightQuadTreeEntry(k, k2), height); }
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); }