Vector<WorldCoordinates>* PathFinderManager::findPathFromCellToCell(const WorldCoordinates& pointA, const WorldCoordinates& pointB) { CellObject* ourCell = pointA.getCell(); CellObject* targetCell = pointB.getCell(); if (ourCell != targetCell) return findPathFromCellToDifferentCell(pointA, pointB); int ourCellID = ourCell->getCellNumber(); ManagedReference<BuildingObject*> building = cast<BuildingObject*>( ourCell->getParent().get().get()); SharedObjectTemplate* templateObject = building->getObjectTemplate(); if (templateObject == NULL) return NULL; PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) return NULL; FloorMesh* floorMesh1 = portalLayout->getFloorMesh(ourCellID); PathGraph* pathGraph1 = floorMesh1->getPathGraph(); Vector<WorldCoordinates>* path = new Vector<WorldCoordinates>(5, 1); path->add(pointA); // adding source //info("same cell... trying to calculate triangle path", true); Vector<Triangle*>* trianglePath = NULL; //info("searching floorMesh for cellID " + String::valueOf(ourCellID), true); int res = getFloorPath(pointA.getPoint(), pointB.getPoint(), floorMesh1, trianglePath); if (res == -1) { //points in the same triangle path->add(pointB); return path; } if (trianglePath == NULL) { // returning NULL, no path found //error("path NULL"); delete path; return findPathFromCellToDifferentCell(pointA, pointB); } else { //info("path found", true); addTriangleNodeEdges(pointA.getPoint(), pointB.getPoint(), trianglePath, path, ourCell); delete trianglePath; path->add(pointB); //adding destination return path; } return path; }
AABBTree* CollisionManager::getAABBTree(SceneObject* scno, int collisionBlockFlags) { SharedObjectTemplate* templateObject = scno->getObjectTemplate(); if (templateObject == NULL) return NULL; if (!(templateObject->getCollisionActionBlockFlags() & collisionBlockFlags)) return NULL; PortalLayout* portalLayout = templateObject->getPortalLayout(); MeshAppearanceTemplate* mesh = NULL; if (portalLayout != NULL) { mesh = portalLayout->getMeshAppearanceTemplate(0); } else { AppearanceTemplate* appTemplate = templateObject->getAppearanceTemplate(); if (appTemplate == NULL) return NULL; mesh = dynamic_cast<MeshAppearanceTemplate*>(appTemplate->getFirstMesh()); } if (mesh == NULL) return NULL; return mesh->getAABBTree(); }
short PetManagerImplementation::checkMountEligibility(PetControlDevice* petControlDevice, float height) { ManagedReference<TangibleObject*> controlledObject = petControlDevice->getControlledObject(); if (controlledObject == NULL || !controlledObject->isAiAgent()) return PetManager::INVALIDCREATURE; ManagedReference<AiAgent*> pet = cast<AiAgent*>(controlledObject.get()); if( pet == NULL ) return PetManager::INVALIDCREATURE; //Check if the pet's species is able to be trained as a mount if (!pet->hasSlotDescriptor("rider")) return PetManager::INVALIDCREATURE; SharedObjectTemplate* objectTemplate = petControlDevice->getObjectTemplate(); if (objectTemplate == NULL) return PetManager::INVALIDCREATURE; short result; if (height == -1) result = isValidMountScale(objectTemplate->getAppearanceFilename(), 1, pet->getHeight()); else result = isValidMountScale(objectTemplate->getAppearanceFilename(), 1, height); return result; }
bool PlanetManagerImplementation::isInObjectsNoBuildZone(float x, float y, float extraMargin) { SortedVector<ManagedReference<QuadTreeEntry* > > closeObjects; Vector3 targetPos(x, y, zone->getHeight(x, y)); zone->getInRangeObjects(x, y, 512, &closeObjects, true); for (int i = 0; i < closeObjects.size(); ++i) { SceneObject* obj = cast<SceneObject*>(closeObjects.get(i).get()); SharedObjectTemplate* objectTemplate = obj->getObjectTemplate(); if (objectTemplate != NULL) { float radius = objectTemplate->getNoBuildRadius(); // Only check objects with an actual NoBuildRadius if (radius > 0) { // Add margin to check radius += extraMargin; Vector3 objWorldPos = obj->getWorldPosition(); if (objWorldPos.squaredDistanceTo(targetPos) < radius * radius) { return true; } } } } return false; }
bool CollisionManager::checkLineOfSightWorldToCell(const Vector3& rayOrigin, const Vector3& rayEnd, float distance, CellObject* cellObject) { ManagedReference<SceneObject*> building = cellObject->getParent(); if (building == NULL) return true; SharedObjectTemplate* objectTemplate = building->getObjectTemplate(); PortalLayout* portalLayout = objectTemplate->getPortalLayout(); if (portalLayout == NULL) return true; Ray ray = convertToModelSpace(rayOrigin, rayEnd, building); if (cellObject->getCellNumber() >= portalLayout->getAppearanceTemplatesSize()) return true; MeshAppearanceTemplate* app = portalLayout->getMeshAppearanceTemplate(cellObject->getCellNumber()); AABBTree* aabbTree = app->getAABBTree(); if (aabbTree == NULL) return true; float intersectionDistance; Triangle* triangle = NULL; if (aabbTree->intersects(ray, distance, intersectionDistance, triangle, true)) return false; return true; }
bool CollisionManager::checkLineOfSightInParentCell(SceneObject* object, Vector3& endPoint) { ManagedReference<SceneObject*> parent = object->getParent(); if (parent == NULL || !parent->isCellObject()) return true; CellObject* cell = cast<CellObject*>( parent.get()); SharedObjectTemplate* objectTemplate = parent->getRootParent().get()->getObjectTemplate(); PortalLayout* portalLayout = objectTemplate->getPortalLayout(); MeshAppearanceTemplate* appearanceMesh = NULL; if (portalLayout == NULL) return true; try { appearanceMesh = portalLayout->getMeshAppearanceTemplate(cell->getCellNumber()); } catch (Exception& e) { return true; } if (appearanceMesh == NULL) { //info("null appearance mesh "); return true; } AABBTree* aabbTree = appearanceMesh->getAABBTree(); if (aabbTree == NULL) return true; //switching Y<->Z, adding 0.1 to account floor Vector3 startPoint = object->getPosition(); startPoint.set(startPoint.getX(), startPoint.getY(), startPoint.getZ() + 0.1f); endPoint.set(endPoint.getX(), endPoint.getY(), endPoint.getZ() + 0.1f); Vector3 dir = endPoint - startPoint; dir.normalize(); float distance = endPoint.distanceTo(startPoint); float intersectionDistance; Ray ray(startPoint, dir); Triangle* triangle = NULL; //nothing in the middle if (aabbTree->intersects(ray, distance, intersectionDistance, triangle, true)) return false; Ray ray2(endPoint, Vector3(0, -1, 0)); //check if we are in the cell with dir (0, -1, 0) if (!aabbTree->intersects(ray2, 64000.f, intersectionDistance, triangle, true)) return false; return true; }
Vector<float>* CollisionManager::getCellFloorCollision(float x, float y, CellObject* cellObject) { Vector<float>* collisions = NULL; ManagedReference<SceneObject*> rootObject = cellObject->getRootParent(); if (rootObject == NULL) return NULL; SharedObjectTemplate* templateObject = rootObject->getObjectTemplate(); if (templateObject == NULL) return NULL; PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) return NULL; FloorMesh* mesh = portalLayout->getFloorMesh(cellObject->getCellNumber()); if (mesh == NULL) return NULL; AABBTree* tree = mesh->getAABBTree(); if (tree == NULL) return NULL; Vector3 rayStart(x, 16384.f, y); Vector3 rayEnd(x, -16384.f, y); Vector3 norm = rayEnd - rayStart; norm.normalize(); Ray ray(rayStart, norm); SortedVector<IntersectionResult> results(3, 2); tree->intersects(ray, 16384 * 2, results); if (results.size() == 0) return NULL; collisions = new Vector<float>(results.size(), 1); for (int i = 0; i < results.size(); ++i) { float floorHeight = 16384 - results.get(i).getIntersectionDistance(); collisions->add(floorHeight); } return collisions; }
String TemplateManager::getTemplateFile(uint32 key) { SharedObjectTemplate* templateData = templateCRCMap->get(key); if (templateData == NULL) { String ascii = clientTemplateCRCMap->get(key); if (ascii.isEmpty()) throw Exception("TemplateManager::getTemplateFile exception unknown template key 0x" + String::hexvalueOf((int)key)); else return ascii; } return templateData->getFullTemplateString(); }
TEST_F(LuaMobileTest, LuaLootGroupsTest) { // Verify loot group map loaded ASSERT_EQ(LootGroupMap::ERROR_CODE, 0); // Test Loot Items HashTableIterator<String, Reference<LootItemTemplate*> > itemIter = lootGroupMap->itemTemplates.iterator(); while (itemIter.hasNext()) { LootItemTemplate* lootItemTemplate = itemIter.next(); String itemTemplateName( lootItemTemplate->getTemplateName().toCharArray() ); // Make sure that no loot items have the same name as a loot group EXPECT_FALSE( lootGroupMap->lootGroupExists(itemTemplateName) ) << "Loot item " << std::string(itemTemplateName.toCharArray()) << " has the same name as a loot group."; // Verify that directObjectTemplate is valid String directObjectTemplate = lootItemTemplate->getDirectObjectTemplate(); SharedObjectTemplate* templateObject = templateManager->getTemplate(directObjectTemplate.hashCode()); EXPECT_TRUE( templateObject != NULL && templateObject->isSharedTangibleObjectTemplate() ) << "directObjectTemplate is invalid in loot item " << std::string(itemTemplateName.toCharArray()); } // Test Loot Groups HashTableIterator<String, Reference<LootGroupTemplate*> > iter = lootGroupMap->groupTemplates.iterator(); while (iter.hasNext()) { LootGroupTemplate* lootGroupTemplate = iter.next(); String groupTemplateName( lootGroupTemplate->getTemplateName().toCharArray() ); // Verify that group is not empty EXPECT_TRUE( lootGroupTemplate->getLootGroupEntryForRoll(-1).length() > 0 ) << "No entries in loot group: " << std::string(groupTemplateName.toCharArray()); // Check loot group to make sure their chances total correctly EXPECT_GT( lootGroupTemplate->getLootGroupEntryForRoll(10000000).length(), 0 ) << "Item total chance is less than 10000000: " << std::string(groupTemplateName.toCharArray()); EXPECT_EQ( lootGroupTemplate->getLootGroupEntryForRoll(10000001).length(), 0 ) << "Item total chance is greater than 10000000: " << std::string(groupTemplateName.toCharArray()); // Check that all loot group entries are valid for( int i = 0; i < lootGroupTemplate->size(); i++ ){ Vector<String> parentGroups; parentGroups.add(groupTemplateName); String entryName = lootGroupTemplate->getLootGroupEntryAt(i); checkLootGroupEntryRecursive(entryName, &parentGroups); } } }
float PetManagerImplementation::getMountedRunSpeed(CreatureObject* mount) { if (!mount->isMount()) return mount->getRunSpeed(); ManagedReference<PetControlDevice*> pcd = mount->getControlDevice().get().castTo<PetControlDevice*>(); if (pcd != NULL) { SharedObjectTemplate* objectTemplate = pcd->getObjectTemplate(); if (objectTemplate != NULL) { MountSpeedData* mountSpeedData = getMountSpeedData(objectTemplate->getAppearanceFilename()); if (mountSpeedData != NULL) return mountSpeedData->getRunSpeed(); } } return mount->getRunSpeed(); }
FloorMesh* PathFinderManager::getFloorMesh(CellObject* cell) { ManagedReference<BuildingObject*> building1 = (cell->getParent().get().castTo<BuildingObject*>()); SharedObjectTemplate* templateObject = building1->getObjectTemplate(); if (templateObject == NULL) { return NULL; } PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) { return NULL; } FloorMesh* floorMesh1 = portalLayout->getFloorMesh(cell->getCellNumber()); return floorMesh1; }
SceneObject* ObjectManager::loadObjectFromTemplate(uint32 objectCRC) { Locker _locker(this); SceneObject* object = NULL; try { SharedObjectTemplate* templateData = templateManager->getTemplate(objectCRC); if (templateData == NULL) { error("trying to create object with unknown objectcrc 0x" + String::hexvalueOf((int)objectCRC)); return NULL; } uint32 gameObjectType = templateData->getGameObjectType(); object = objectFactory.createObject(gameObjectType); if (object == NULL) { error("creating object unknown gameObjectType " + String::valueOf(gameObjectType)); return NULL; } databaseManager->addTemporaryObject(object); object->setServerObjectCRC(objectCRC); object->loadTemplateData(templateData); } catch (Exception& e) { error("exception caught in SceneObject* ObjectManager::loadObjectFromTemplate(uint32 objectCRC)"); error(e.getMessage()); e.printStackTrace(); } catch (...) { error("unreported exception caught in SceneObject* ObjectManager::loadObjectFromTemplate(uint32 objectCRC)"); throw; } return object; }
bool CollisionManager::checkLineOfSightInBuilding(SceneObject* object1, SceneObject* object2, SceneObject* building) { SharedObjectTemplate* objectTemplate = building->getObjectTemplate(); PortalLayout* portalLayout = objectTemplate->getPortalLayout(); if (portalLayout == NULL) return true; //we are in model space... in cells Vector3 rayOrigin = object1->getPosition(); rayOrigin.set(rayOrigin.getX(), rayOrigin.getY(), rayOrigin.getZ() + 1.f); Vector3 rayEnd = object2->getPosition(); rayEnd.set(rayEnd.getX(), rayEnd.getY(), rayEnd.getZ() + 1.f); Vector3 direction(Vector3(rayEnd - rayOrigin)); direction.normalize(); float distance = rayEnd.distanceTo(rayOrigin); float intersectionDistance; Ray ray(rayOrigin, direction); Triangle* triangle = NULL; // we check interior cells for (int i = 1; i < portalLayout->getAppearanceTemplatesSize(); ++i) { MeshAppearanceTemplate* app = portalLayout->getMeshAppearanceTemplate(i); AABBTree* aabbTree = app->getAABBTree(); if (aabbTree == NULL) continue; if (aabbTree->intersects(ray, distance, intersectionDistance, triangle, true)) return false; } return true; }
bool PlanetManagerImplementation::isInObjectsNoBuildZone(float x, float y, float extraMargin) { SortedVector<QuadTreeEntry*> closeObjects; Vector3 targetPos(x, y, zone->getHeight(x, y)); zone->getInRangeObjects(x, y, 512, &closeObjects, true); for (int i = 0; i < closeObjects.size(); ++i) { SceneObject* obj = static_cast<SceneObject*>(closeObjects.get(i)); SharedObjectTemplate* objectTemplate = obj->getObjectTemplate(); if (objectTemplate != NULL) { float radius = objectTemplate->getNoBuildRadius(); // Only check objects with an actual NoBuildRadius if (radius > 0) { // Add margin to check radius += extraMargin; Vector3 objWorldPos = obj->getWorldPosition(); if (objWorldPos.squaredDistanceTo(targetPos) < radius * radius) { return true; } } // Check if it's within a structure's footprint if (objectTemplate->isSharedStructureObjectTemplate()) { if (StructureManager::instance()->isInStructureFootprint(cast<StructureObject*>(obj), x, y, extraMargin)) { return true; } } } } return false; }
void TemplateManager::addTemplate(uint32 key, const String& fullName, LuaObject* templateData) { uint32 templateType = templateData->getIntField("templateType"); String clientTemplateFile = templateData->getStringField("clientTemplateFileName"); SharedObjectTemplate* templateObject = templateFactory.createObject(templateType); if (templateObject == NULL) { error("error creating template from lua with templateType 0x" + String::hexvalueOf((int)templateType)); return; } //info("loading " + fullName, true); String fileName = fullName.subString(fullName.lastIndexOf('/') + 1, fullName.lastIndexOf('.')); templateObject->setFullTemplateString(fullName); templateObject->setTemplateFileName(fileName); if (!clientTemplateFile.isEmpty()) { IffStream* iffStream = openIffFile(clientTemplateFile); if (iffStream != NULL) { templateObject->readObject(iffStream); delete iffStream; } } templateObject->readObject(templateData); if (!clientTemplateFile.isEmpty()) templateObject->addDerivedFile(clientTemplateFile); info("loaded " + fullName); if (templateCRCMap->put(key, templateObject) != NULL) { //error("duplicate template for " + fullName); } }
Vector<WorldCoordinates>* PathFinderManager::findPathFromWorldToCell(const WorldCoordinates& pointA, const WorldCoordinates& pointB, Zone *zone) { CellObject* targetCell = pointB.getCell(); if (targetCell == NULL) return NULL; ManagedReference<BuildingObject*> building = dynamic_cast<BuildingObject*>(targetCell->getParent().get().get()); if (building == NULL) { error("building == NULL in PathFinderManager::findPathFromWorldToCell"); return NULL; } SharedObjectTemplate* templateObject = building->getObjectTemplate(); if (templateObject == NULL) return NULL; PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) return NULL; //find nearest entrance FloorMesh* exteriorFloorMesh = portalLayout->getFloorMesh(0); // get outside layout if (exteriorFloorMesh == NULL) return NULL; PathGraph* exteriorPathGraph = exteriorFloorMesh->getPathGraph(); FloorMesh* targetFloorMesh = portalLayout->getFloorMesh(targetCell->getCellNumber()); PathGraph* targetPathGraph = targetFloorMesh->getPathGraph(); Vector<WorldCoordinates>* path = new Vector<WorldCoordinates>(5, 1); path->add(pointA); Vector3 transformedPosition = transformToModelSpace(pointA.getPoint(), building); PathNode* nearestEntranceNode = exteriorPathGraph->findNearestNode(transformedPosition); if (nearestEntranceNode == NULL) { error("NULL entrance node for building " + templateObject->getFullTemplateString()); delete path; return NULL; } //PathNode* nearestTargetNode = targetPathGraph->findNearestNode(pointB.getPoint()); TriangleNode* nearestTargetNodeTriangle = CollisionManager::getTriangle(pointB.getPoint(), targetFloorMesh); if (nearestTargetNodeTriangle == NULL) { delete path; return NULL; } PathNode* nearestTargetNode = CollisionManager::findNearestPathNode(nearestTargetNodeTriangle, targetFloorMesh, pointB.getPoint());//targetPathGraph->findNearestNode(pointB.getPoint()); if (nearestTargetNode == NULL) { delete path; return NULL; } /*if (nearestEntranceNode == nearestTargetNode) info("nearestEntranceNode == nearestTargetNode", true);*/ //find graph from outside to appropriate cell Vector<PathNode*>* pathToCell = portalLayout->getPath(nearestEntranceNode, nearestTargetNode); if (pathToCell == NULL) { error("pathToCell = portalLayout->getPath(nearestEntranceNode, nearestTargetNode); == NULL"); delete path; return NULL; } for (int i = 0; i < pathToCell->size(); ++i) { PathNode* pathNode = pathToCell->get(i); PathGraph* pathGraph = pathNode->getPathGraph(); FloorMesh* floorMesh = pathGraph->getFloorMesh(); int cellID = floorMesh->getCellID(); //info("cellID:" + String::valueOf(cellID), true); if (cellID == 0) { // we are still outside WorldCoordinates coord(pathNode->getPosition(), targetCell); path->add(WorldCoordinates(coord.getWorldPosition(), NULL)); } else { // we are inside the building CellObject* pathCell = building->getCell(cellID); path->add(WorldCoordinates(pathNode->getPosition(), pathCell)); if (i == pathToCell->size() - 1) if (pathCell != targetCell) { error("final cell not target cell"); } } } delete pathToCell; pathToCell = NULL; // path from cell path node to destination point Vector<Triangle*>* trianglePath = NULL; int res = getFloorPath(path->get(path->size() - 1).getPoint(), pointB.getPoint(), targetFloorMesh, trianglePath); if (res != -1 && trianglePath != NULL) addTriangleNodeEdges(path->get(path->size() - 1).getPoint(), pointB.getPoint(), trianglePath, path, targetCell); if (trianglePath != NULL) delete trianglePath; path->add(pointB); return path; }
TEST_F(LuaMobileTest, LuaMobileTemplatesTest) { CreatureTemplateManager::DEBUG_MODE = 1; // Verify that all mobiles load ASSERT_EQ(CreatureTemplateManager::instance()->loadTemplates(), 0); // Verify loot group map loaded ASSERT_EQ(LootGroupMap::ERROR_CODE, 0); // Verify factions load FactionManager::instance()->loadData(); ASSERT_FALSE(FactionManager::instance()->getFactionMap()->isEmpty()); // Load Templates ASSERT_TRUE( TemplateManager::instance() != NULL ); if( TemplateManager::instance()->loadedTemplatesCount == 0 ){ TemplateManager::instance()->loadLuaTemplates(); ASSERT_EQ(TemplateManager::ERROR_CODE, 0); } // verify DNA manager loads DnaManager::instance()->loadSampleData(); ASSERT_TRUE( DnaManager::instance() != NULL); // Test Creature Templates HashTableIterator<uint32, Reference<CreatureTemplate*> > creatureIterator = CreatureTemplateManager::instance()->iterator(); while (creatureIterator.hasNext()) { CreatureTemplate* creature = creatureIterator.next(); std::string templateName( creature->getTemplateName().toCharArray() ); //Verify non-empty objectName is a valid string String objName = creature->getObjectName(); if (!objName.isEmpty()) { std::string name = objName.toCharArray(); EXPECT_TRUE( mobNames.contains(objName) ) << "Mobile " << templateName << " has invalid objectName: " << name; } // Check configured templates Vector<String> objTemps = creature->getTemplates(); EXPECT_FALSE( objTemps.isEmpty() ) << "Mobile " << templateName << " does not have any templates configured"; int objectType = 0; for( int j=0; j< objTemps.size(); j++ ){ SharedObjectTemplate* templateData = templateManager->getTemplate(objTemps.get(j).hashCode()); std::string objName = objTemps.get(j).toCharArray(); EXPECT_TRUE( templateData != NULL ) << "Mobile " << templateName << " has invalid template configured: " << objName; // Check Template Genetics math to find invalid mobs if (templateData != NULL) { SharedCreatureObjectTemplate* creoData = dynamic_cast<SharedCreatureObjectTemplate*> (templateData); if (creoData != NULL) { } } if (objectType == 0) { objectType = templateData->getGameObjectType(); } } // Verify that control device template is valid String controlDeviceTemplate = creature->getControlDeviceTemplate(); if (!controlDeviceTemplate.isEmpty()) { SharedObjectTemplate* controlDeviceTemplateData = templateManager->getTemplate(controlDeviceTemplate.hashCode()); EXPECT_TRUE( controlDeviceTemplateData != NULL ) << "Control device template " << controlDeviceTemplate.toCharArray() << " from " << templateName << " does not exist."; EXPECT_TRUE( controlDeviceTemplate.beginsWith("object/intangible/pet/") ) << "Control device template " << controlDeviceTemplate.toCharArray() << " from " << templateName << " is not a pet/droid control device template."; } // Verify that faction is valid String faction = creature->getFaction(); if (!faction.isEmpty()) { EXPECT_TRUE( FactionManager::instance()->isFaction(faction) ) << "Faction, " << faction.toCharArray() << ", from mobile template " << templateName << " does not exist."; } // Verify level int level = creature->getLevel(); EXPECT_TRUE( level > 0 ) << "Level is not a positive value on mobile: " << templateName; // Verify hit chance float hitChance = creature->getChanceHit(); EXPECT_TRUE( hitChance > 0 ) << "ChanceHit is not a positive value on mobile: " << templateName; // Verify xp int xp = creature->getBaseXp(); EXPECT_TRUE( xp >= 0 ) << "Xp has a negative value on mobile: " << templateName; // Verify damage int minDamage = creature->getDamageMin(); int maxDamage = creature->getDamageMax(); EXPECT_TRUE( minDamage > 0 ) << "Min damage is not a positive value on mobile: " << templateName; EXPECT_TRUE( maxDamage >= minDamage ) << "Max damage is lower than min damage on mobile: " << templateName; // Verify HAM int minHam = creature->getBaseHAM(); int maxHam = creature->getBaseHAMmax(); EXPECT_TRUE( minHam > 0 ) << "Base ham is not a positive value on mobile: " << templateName; EXPECT_TRUE( maxHam >= minHam ) << "Base ham max is lower than base ham on mobile: " << templateName; // Verify armor int armor = creature->getArmor(); EXPECT_TRUE( armor >= 0 && armor <= 3 ) << "Armor is not a valid value on mobile: " << templateName; // Verify resists float kinetic = creature->getKinetic(); EXPECT_TRUE( kinetic >= -1 && kinetic <= 200 ) << "Kinetic resist is not a valid value on mobile: " << templateName; float energy = creature->getEnergy(); EXPECT_TRUE( energy >= -1 && energy <= 200 ) << "Energy resist is not a valid value on mobile: " << templateName; float electricity = creature->getElectricity(); EXPECT_TRUE( electricity >= -1 && electricity <= 200 ) << "Electricity resist is not a valid value on mobile: " << templateName; float stun = creature->getStun(); EXPECT_TRUE( stun >= -1 && stun <= 200 ) << "Stun resist is not a valid value on mobile: " << templateName; float blast = creature->getBlast(); EXPECT_TRUE( blast >= -1 && blast <= 200 ) << "Blast resist is not a valid value on mobile: " << templateName; float heat = creature->getHeat(); EXPECT_TRUE( heat >= -1 && heat <= 200 ) << "Heat resist is not a valid value on mobile: " << templateName; float cold = creature->getCold(); EXPECT_TRUE( cold >= -1 && cold <= 200 ) << "Cold resist is not a valid value on mobile: " << templateName; float acid = creature->getAcid(); EXPECT_TRUE( acid >= -1 && acid <= 200 ) << "Acid resist is not a valid value on mobile: " << templateName; float lightSaber = creature->getLightSaber(); EXPECT_TRUE( lightSaber >= -1 && lightSaber <= 200 ) << "LightSaber resist is not a valid value on mobile: " << templateName; // Verify creature resources String meat = creature->getMeatType(); float meatMax = creature->getMeatMax(); if (!meat.isEmpty()) { String meatResources = "meat_domesticated,meat_wild,meat_herbivore,meat_carnivore,meat_reptilian,meat_avian,meat_insect"; StringTokenizer tokenizer(meatResources); tokenizer.setDelimeter(","); bool match = false; String token; while (tokenizer.hasMoreTokens()) { tokenizer.getStringToken(token); if (meat == token) match = true; } EXPECT_TRUE( match ) << "Meat type on mobile " << templateName << " is not a valid meat resource"; EXPECT_TRUE( meatMax > 0 ) << "Meat amount on mobile " << templateName << " is zero."; } else { EXPECT_TRUE( meatMax == 0 ) << "MeatAmount is not zero yet has no type defined on mobile " << templateName; } String hide = creature->getHideType(); float hideMax = creature->getHideMax(); if (!hide.isEmpty()) { String hideResources = "hide_bristley,hide_leathery,hide_scaley,hide_wooly"; StringTokenizer tokenizer(hideResources); tokenizer.setDelimeter(","); bool match = false; String token; while (tokenizer.hasMoreTokens()) { tokenizer.getStringToken(token); if (hide == token) match = true; } EXPECT_TRUE( match ) << "Hide type on mobile " << templateName << " is not a valid hide resource"; EXPECT_TRUE( hideMax > 0 ) << "Hide amount on mobile " << templateName << " is zero."; } else { EXPECT_TRUE( hideMax == 0 ) << "HideAmount is not zero yet has no type defined on mobile " << templateName; } String bone = creature->getBoneType(); float boneMax = creature->getBoneMax(); if (!bone.isEmpty()) { String boneResources = "bone_avian,bone_mammal"; StringTokenizer tokenizer(boneResources); tokenizer.setDelimeter(","); bool match = false; String token; while (tokenizer.hasMoreTokens()) { tokenizer.getStringToken(token); if (bone == token) match = true; } EXPECT_TRUE( match ) << "Bone type on mobile " << templateName << " is not a valid bone resource"; EXPECT_TRUE( boneMax > 0 ) << "Bone amount on mobile " << templateName << " is zero."; } else { EXPECT_TRUE( boneMax == 0 ) << "BoneAmount is not zero yet has no type defined on mobile " << templateName; } String milk = creature->getMilkType(); float milkMax = creature->getMilk(); if (!milk.isEmpty()) { String milkResources = "milk_domesticated,milk_wild"; StringTokenizer tokenizer(milkResources); tokenizer.setDelimeter(","); bool match = false; String token; while (tokenizer.hasMoreTokens()) { tokenizer.getStringToken(token); if (milk == token) match = true; } EXPECT_TRUE( match ) << "Milk type on mobile " << templateName << " is not a valid milk resource"; EXPECT_TRUE( milkMax > 0 ) << "Milk amount on mobile " << templateName << " is zero."; } else { EXPECT_TRUE( milkMax == 0 ) << "Milk is not zero yet has no type defined on mobile " << templateName; } // Verify taming chance float tamingChance = creature->getTame(); EXPECT_TRUE( tamingChance >= 0 && tamingChance <= 1 ) << "Taming chance is not a valid value on mobile: " << templateName; // Verify diet on creatures if (boneMax > 0 || hideMax > 0 || meatMax > 0 || milkMax > 0 || tamingChance > 0) { uint32 diet = creature->getDiet(); EXPECT_TRUE( diet != 0 ) << "Diet is NONE on creature type mobile " << templateName; } // Verify scale float scale = creature->getScale(); EXPECT_TRUE( scale > 0 ) << "Scale is not a positive value on mobile: " << templateName; // Verify PACK mobs have a social group uint32 creatureBitmask = creature->getCreatureBitmask(); String socialGroup = creature->getSocialGroup(); if (creatureBitmask & CreatureFlag::PACK) { EXPECT_FALSE( socialGroup.isEmpty() ) << "Social group is empty on pack mobile: " << templateName; } // Verify loot group percentages LootGroupCollection* groupCollection = creature->getLootGroups(); if( groupCollection->count() > 0 ){ for( int i = 0; i < groupCollection->count(); i++ ){ LootGroupCollectionEntry* collectionEntry = groupCollection->get(i); LootGroups* groups = collectionEntry->getLootGroups(); if( groups->count() > 0){ int totalChance = 0; for( int j = 0; j < groups->count(); j++ ){ LootGroupEntry* lootGroup = groups->get(j); totalChance += lootGroup->getLootChance(); // Verify loot group is configured correctly LootGroupTemplate* foundGroup = lootGroupMap->getLootGroupTemplate( lootGroup->getLootGroupName() ); std::string groupName( lootGroup->getLootGroupName().toCharArray() ); EXPECT_TRUE( foundGroup != NULL ) << "Loot group " << groupName << " from " << templateName << " was not found in LootGroupMap"; } EXPECT_EQ( 10000000, totalChance ) << "Loot groups total chance is incorrect " << templateName; } } } // Verify weapon groups exist Vector<String> weapons = creature->getWeapons(); for (int i = 0; i < weapons.size(); i++) { String weaponGroup = weapons.get(i); std::string groupName( weaponGroup.toCharArray() ); Vector<String> group = CreatureTemplateManager::instance()->getWeapons(weaponGroup); EXPECT_TRUE( group.size() > 0 ) << "Weapon group " << groupName << " from " << templateName << " was not found in weaponMap"; } // Verify conversation template exist, and the mob has converse option bit uint32 convoTemplate = creature->getConversationTemplate(); uint32 optionsBitmask = creature->getOptionsBitmask(); if (convoTemplate != 0) { ConversationTemplate* convoTemp = CreatureTemplateManager::instance()->getConversationTemplate(convoTemplate); EXPECT_TRUE( convoTemp != NULL ) << "Conversation template from " << templateName << " was not found."; EXPECT_TRUE( optionsBitmask & OptionBitmask::CONVERSE ) << templateName << " has a convo template but not the CONVERSE options bit."; } // Verify that mobs with converse option bit have a convo template if (optionsBitmask & OptionBitmask::CONVERSE) { EXPECT_TRUE( convoTemplate != 0 ) << templateName << " has the CONVERSE options bit but not a convo template."; } // Verify that outfits exist String outfit = creature->getOutfit(); if (!outfit.isEmpty()) { MobileOutfitGroup* outfitGroup = CreatureTemplateManager::instance()->getMobileOutfitGroup(outfit); EXPECT_TRUE( outfitGroup != NULL ) << "Outfit group " << outfit.toCharArray() << " from " << templateName << " was not found."; } // Verify attacks are valid commands CreatureAttackMap* cam = creature->getAttacks(); for (int i = 0; i < cam->size(); i++) { String commandName = cam->getCommand(i); EXPECT_TRUE( commandName.isEmpty() || commandConfigManager->contains(commandName) ) << "Attack: " << commandName.toCharArray() << " is not a valid command in mobile template: " << templateName; } // Very attackable npcs uint32 pvpBitmask = creature->getPvpBitmask(); if ((pvpBitmask & CreatureFlag::ATTACKABLE) && objectType == 1025) { // Verify attackable npcs have attacks EXPECT_TRUE( cam->size() > 0 ) << "Attackable npc " << templateName << " does not have attacks."; } } // Test Lair Templates HashTableIterator<uint32, Reference<LairTemplate*> > lairIterator = CreatureTemplateManager::instance()->lairTemplateIterator(); while (lairIterator.hasNext()) { LairTemplate* lair = lairIterator.next(); std::string templateName( lair->getName().toCharArray() ); // Verify that mobiles exist and that their weighting is positive VectorMap<String, int>* mobiles = lair->getMobiles(); for (int i = 0; i < mobiles->size(); i++) { int weighting = mobiles->elementAt(i).getValue(); String mobile = mobiles->elementAt(i).getKey(); std::string mobName = mobile.toCharArray(); EXPECT_TRUE( CreatureTemplateManager::instance()->getTemplate(mobile) != NULL ) << "Mobile " << mobName << " in lair template " << templateName << " does not exist"; EXPECT_TRUE( weighting > 0 ) << "Mobile " << mobName << " in lair template " << templateName << " has a non positive weighting"; } // Verify that boss mobiles exist and that their count is positive VectorMap<String, int>* bossMobiles = lair->getBossMobiles(); for (int i = 0; i < bossMobiles->size(); i++) { int count = bossMobiles->elementAt(i).getValue(); String bossMob = bossMobiles->elementAt(i).getKey(); std::string bossName = bossMob.toCharArray(); EXPECT_TRUE( CreatureTemplateManager::instance()->getTemplate(bossMob) != NULL ) << "Boss mobile " << bossName << " in lair template " << templateName << " does not exist"; EXPECT_TRUE( count > 0 ) << "Boss mobile " << bossName << " in lair template " << templateName << " has a non positive spawn count"; } // Verify spawn limit is positive int limit = lair->getSpawnLimit(); EXPECT_TRUE( limit > 0 ) << "Spawn limit in lair template " << templateName << " is not positive"; // Verify any configured buildings exist int buildingCount = 0; for(int i=0; i<=4; i++){ Vector<String>* buildings = lair->getBuildings( i ); if( buildings == NULL ) continue; buildingCount += buildings->size(); for( int j=0; j < buildings->size(); j++ ){ String buildingTemplate = buildings->get(j); std::string buildingStr = buildingTemplate.toCharArray(); SharedObjectTemplate* templateObject = templateManager->getTemplate(buildingTemplate.hashCode()); EXPECT_TRUE( templateObject != NULL && templateObject->isSharedTangibleObjectTemplate() ) << "Building template " << buildingStr << " in lair template " << templateName << " does not exist"; if( lair->getBuildingType() == LairTemplate::LAIR ){ EXPECT_TRUE( buildingTemplate.beginsWith( "object/tangible/lair/") ) << "Building template " << buildingStr << " in lair template " << templateName << " is not a child of object/tangible/lair/"; } if( lair->getBuildingType() == LairTemplate::THEATER ){ EXPECT_TRUE( buildingTemplate.beginsWith( "object/building/poi/") ) << "Building template " << buildingStr << " in lair template " << templateName << " is not a child of object/building/poi/"; } } } // Verify mission buildings exist and are lairs String missionBuilding = lair->getMissionBuilding(10); if (!missionBuilding.isEmpty()) { std::string buildingStr = missionBuilding.toCharArray(); SharedObjectTemplate* templateObject = templateManager->getTemplate(missionBuilding.hashCode()); EXPECT_TRUE( templateObject != NULL && templateObject->isSharedTangibleObjectTemplate() ) << "Mission building template " << buildingStr << " in lair template " << templateName << " does not exist"; EXPECT_TRUE( missionBuilding.beginsWith( "object/tangible/lair/") ) << "Mission building template " << buildingStr << " in lair template " << templateName << " is not a child of object/tangible/lair/"; } if( lair->getBuildingType() == LairTemplate::THEATER ){ EXPECT_TRUE( buildingCount > 0 ) << "There are no buildings configured in theater type lair template " << templateName; } if( lair->getBuildingType() == LairTemplate::NONE ){ EXPECT_TRUE( buildingCount == 0 ) << "There are buildings configured in 'none' type lair template " << templateName; } if( lair->getBuildingType() == LairTemplate::LAIR ){ EXPECT_TRUE( buildingCount > 0 ) << "There are no buildings configured in lair type lair template " << templateName; } } // Test Spawn Groups HashTableIterator<uint32, Reference<SpawnGroup*> > spawnIterator = CreatureTemplateManager::instance()->spawnGroupIterator(); while (spawnIterator.hasNext()) { SpawnGroup* group = spawnIterator.next(); std::string templateName( group->getTemplateName().toCharArray() ); Vector<String> lairTemplates; // Verify spawn list Vector<Reference<LairSpawn*> >* spawnList = group->getSpawnList(); for (int i = 0; i < spawnList->size(); i++) { LairSpawn* spawn = spawnList->get(i); std::string lairName( spawn->getLairTemplateName().toCharArray() ); // Verify lair template exists and isn't duplicated in the group String lairTemplateName = spawn->getLairTemplateName(); Reference<LairTemplate*> lairTemplate = CreatureTemplateManager::instance()->getLairTemplate(lairTemplateName.hashCode()); EXPECT_TRUE( lairTemplate != NULL ) << "Lair template " << lairName << " in spawn group " << templateName << " does not exist."; EXPECT_FALSE( lairTemplates.contains(lairTemplateName) ) << "Lair template " << lairName << " is duplicated in spawn group " << templateName; lairTemplates.add(lairTemplateName); // Verify spawn limit is at least -1 float spawnLimit = spawn->getSpawnLimit(); EXPECT_TRUE( spawnLimit >= -1 ) << "SpawnLimit for lairTemplate " << lairName << " in spawn group " << templateName << " is less than -1."; // Verify difficulties int minDiff = spawn->getMinDifficulty(); int maxDiff = spawn->getMaxDifficulty(); EXPECT_TRUE( minDiff > 0 ) << "MinDifficulty for lairTemplate " << lairName << " in spawn group " << templateName << " is not positive."; EXPECT_TRUE( maxDiff >= minDiff ) << "MaxDifficulty for lairTemplate " << lairName << " in spawn group " << templateName << " is less than min difficulty."; // Verify number to spawn is not negative int numberToSpawn = spawn->getNumberToSpawn(); EXPECT_TRUE( numberToSpawn >= 0 ) << "NumberToSpawn for lairTemplate " << lairName << " in spawn group " << templateName << " is negative."; // Verify weighting is positive int weighting = spawn->getWeighting(); EXPECT_TRUE( weighting > 0 ) << "Weighting for lairTemplate " << lairName << " in spawn group " << templateName << " is not positive."; // Verify size is at least 1 float size = spawn->getSize(); EXPECT_TRUE( size >= 1 ) << "Size for lairTemplate " << lairName << " in spawn group " << templateName << " is less than 1."; } } // Test Destroy Mission Spawn Groups HashTableIterator<uint32, Reference<SpawnGroup*> > missionIterator = CreatureTemplateManager::instance()->destroyMissionGroupIterator(); while (missionIterator.hasNext()) { SpawnGroup* group = missionIterator.next(); std::string templateName( group->getTemplateName().toCharArray() ); Vector<String> lairTemplates; // Verify spawn list Vector<Reference<LairSpawn*> >* spawnList = group->getSpawnList(); for (int i = 0; i < spawnList->size(); i++) { LairSpawn* spawn = spawnList->get(i); std::string lairName( spawn->getLairTemplateName().toCharArray() ); // Verify lair template exists String lairTemplateName = spawn->getLairTemplateName(); Reference<LairTemplate*> lairTemplate = CreatureTemplateManager::instance()->getLairTemplate(lairTemplateName.hashCode()); EXPECT_TRUE( lairTemplate != NULL ) << "Lair template " << lairName << " in destroy mission spawn group " << templateName << " does not exist."; EXPECT_FALSE( lairTemplates.contains(lairTemplateName) ) << "Lair template " << lairName << " is duplicated in destroy mission spawn group " << templateName; lairTemplates.add(lairTemplateName); if (lairTemplate != NULL) { // Verify that lair template has a valid mission building or is of type LAIR String missionBuilding = lairTemplate->getMissionBuilding(10); if (!missionBuilding.isEmpty()) { std::string buildingStr = missionBuilding.toCharArray(); SharedObjectTemplate* templateObject = templateManager->getTemplate(missionBuilding.hashCode()); EXPECT_TRUE( templateObject != NULL && templateObject->isSharedTangibleObjectTemplate() ) << "Mission building template " << buildingStr << " in lair template " << lairName << ", part of destroy mission group " << templateName << " does not exist"; EXPECT_TRUE( missionBuilding.beginsWith( "object/tangible/lair/") ) << "Mission building template " << buildingStr << " in lair template " << lairName << ", part of destroy mission group " << templateName << " is not a child of object/tangible/lair/"; } else { EXPECT_TRUE( lairTemplate->getBuildingType() == LairTemplate::LAIR ) << "Lair template " << lairName << ", part of destroy mission group " << templateName << " is not of type LAIR"; } } // Verify difficulties int minDiff = spawn->getMinDifficulty(); int maxDiff = spawn->getMaxDifficulty(); EXPECT_TRUE( minDiff > 0 ) << "MinDifficulty for lairTemplate " << lairName << " in destroy mission spawn group " << templateName << " is not positive."; EXPECT_TRUE( maxDiff >= minDiff ) << "MaxDifficulty for lairTemplate " << lairName << " in destroy mission spawn group " << templateName << " is less than min difficulty."; // Verify size is at least 1 float size = spawn->getSize(); EXPECT_TRUE( size >= 1 ) << "Size for lairTemplate " << lairName << " in destroy mission spawn group " << templateName << " is less than 1."; } } }
Vector<WorldCoordinates>* PathFinderManager::findPathFromCellToWorld(const WorldCoordinates& pointA, const WorldCoordinates& pointB, Zone *zone) { Vector<WorldCoordinates>* path = new Vector<WorldCoordinates>(5, 1); if (path == NULL) return NULL; path->add(pointA); CellObject* ourCell = pointA.getCell(); ManagedReference<BuildingObject*> building = cast<BuildingObject*>( ourCell->getParent().get().get()); int ourCellID = ourCell->getCellNumber(); SharedObjectTemplate* templateObject = ourCell->getParent().get()->getObjectTemplate(); if (templateObject == NULL) { delete path; return NULL; } PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) { delete path; return NULL; } FloorMesh* sourceFloorMesh = portalLayout->getFloorMesh(ourCellID); if (sourceFloorMesh == NULL) { delete path; return NULL; } PathGraph* sourcePathGraph = sourceFloorMesh->getPathGraph(); if (sourcePathGraph == NULL) { delete path; return NULL; } FloorMesh* exteriorFloorMesh = portalLayout->getFloorMesh(0); if (exteriorFloorMesh == NULL) { delete path; return NULL; } PathGraph* exteriorPathGraph = exteriorFloorMesh->getPathGraph(); if (exteriorPathGraph == NULL) { delete path; return NULL; } // we need to move world position into model space Vector3 transformedPosition = transformToModelSpace(pointB.getPoint(), building); //find exit node in our cell //PathNode* exitNode = sourcePathGraph->findNearestNode(pointA.getPoint()); TriangleNode* nearestTargetNodeTriangle = CollisionManager::getTriangle(pointA.getPoint(), sourceFloorMesh); if (nearestTargetNodeTriangle == NULL) { delete path; return NULL; } PathNode* exitNode = CollisionManager::findNearestPathNode(nearestTargetNodeTriangle, sourceFloorMesh, transformedPosition);//targetPathGraph->findNearestNode(pointB.getPoint()); if (exitNode == NULL) { delete path; return NULL; } //find exterior node PathNode* exteriorNode = exteriorPathGraph->findNearestGlobalNode(transformedPosition); if (exteriorNode == NULL) { delete path; return NULL; } //find path to the exit Vector<PathNode*>* exitPath = portalLayout->getPath(exitNode, exteriorNode); if (exitPath == NULL) { error("exitPath == NULL"); delete path; return NULL; } //find triangle path to exitNode Vector<Triangle*>* trianglePath = NULL; int res = getFloorPath(pointA.getPoint(), exitNode->getPosition(), sourceFloorMesh, trianglePath); if (res != -1 && trianglePath != NULL) addTriangleNodeEdges(pointA.getPoint(), exitNode->getPosition(), trianglePath, path, ourCell); if (trianglePath != NULL) delete trianglePath; path->add(WorldCoordinates(exitNode->getPosition(), ourCell)); //populate cell traversing for (int i = 0; i < exitPath->size(); ++i) { PathNode* pathNode = exitPath->get(i); PathGraph* pathGraph = pathNode->getPathGraph(); FloorMesh* floorMesh = pathGraph->getFloorMesh(); int cellID = floorMesh->getCellID(); if (cellID == 0) { // we are outside WorldCoordinates coord(pathNode->getPosition(), ourCell); path->add(WorldCoordinates(coord.getWorldPosition(), NULL)); } else { // we are inside the building CellObject* pathCell = building->getCell(cellID); path->add(WorldCoordinates(pathNode->getPosition(), pathCell)); } } delete exitPath; exitPath = NULL; if (path->size()) { Vector<WorldCoordinates>* newPath = findPathFromWorldToWorld(path->get(path->size()-1), pointB, zone); if (newPath) { path->addAll(*newPath); delete newPath; } } else path->add(pointB); return path; }
Vector<WorldCoordinates>* PathFinderManager::findPathFromCellToDifferentCell(const WorldCoordinates& pointA, const WorldCoordinates& pointB) { //info ("findPathFromCellToDifferentCell", true); CellObject* ourCell = pointA.getCell(); CellObject* targetCell = pointB.getCell(); int ourCellID = ourCell->getCellNumber(); int targetCellID = targetCell->getCellNumber(); ManagedReference<BuildingObject*> building1 = cast<BuildingObject*>( ourCell->getParent().get().get()); ManagedReference<BuildingObject*> building2 = cast<BuildingObject*>( targetCell->getParent().get().get()); if (building1 != building2) // TODO: implement path finding between 2 buildings return NULL; SharedObjectTemplate* templateObject = building1->getObjectTemplate(); if (templateObject == NULL) return NULL; PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) return NULL; FloorMesh* floorMesh1 = portalLayout->getFloorMesh(ourCellID); FloorMesh* floorMesh2 = portalLayout->getFloorMesh(targetCellID); if (floorMesh2->getCellID() != targetCellID) error("floorMes2 cellID != targetCellID"); //info("targetCellID:" + String::valueOf(targetCellID), true); PathGraph* pathGraph1 = floorMesh1->getPathGraph(); PathGraph* pathGraph2 = floorMesh2->getPathGraph(); Vector<WorldCoordinates>* path = new Vector<WorldCoordinates>(5, 1); path->add(pointA); // adding source //PathNode* source = pathGraph1->findNearestNode(pointA.getPoint()); TriangleNode* nearestSourceNodeTriangle = CollisionManager::getTriangle(pointA.getPoint(), floorMesh1); if (nearestSourceNodeTriangle == NULL) { delete path; return NULL; } PathNode* source = CollisionManager::findNearestPathNode(nearestSourceNodeTriangle, floorMesh1, pointB.getPoint());//targetPathGraph->findNearestNode(pointB.getPoint()); if (source == NULL) { delete path; return NULL; } //PathNode* target = pathGraph2->findNearestNode(pointB.getPoint()); TriangleNode* nearestTargetNodeTriangle = CollisionManager::getTriangle(pointB.getPoint(), floorMesh2); if (nearestTargetNodeTriangle == NULL) { delete path; return NULL; } PathNode* target = CollisionManager::findNearestPathNode(nearestTargetNodeTriangle, floorMesh2, pointB.getPoint());//targetPathGraph->findNearestNode(pointB.getPoint()); if (target == NULL) { delete path; return NULL; } Vector<PathNode*>* nodes = portalLayout->getPath(source, target); if (nodes == NULL) { StringBuffer str; str << "Could not find path from node: " << source->getID() << " to node: " << target->getID() << " in building: " << templateObject->getFullTemplateString(); log(str.toString()); delete path; return NULL; } // FIXME (dannuic): Sometimes nodes only have one entry.... why? if (nodes->size() == 1) { error("Only one node"); delete path; return NULL; } // path from our position to path node Vector<Triangle*>* trianglePath = NULL; int res = getFloorPath(pointA.getPoint(), nodes->get(1)->getPosition(), floorMesh1, trianglePath); if (res != -1 && trianglePath != NULL) addTriangleNodeEdges(pointA.getPoint(), nodes->get(1)->getPosition(), trianglePath, path, ourCell); if (trianglePath != NULL) { delete trianglePath; trianglePath = NULL; } path->add(WorldCoordinates(source->getPosition(), ourCell)); //traversing cells for (int i = 1; i < nodes->size(); ++i) { PathNode* pathNode = nodes->get(i); PathGraph* pathGraph = pathNode->getPathGraph(); FloorMesh* floorMesh = pathGraph->getFloorMesh(); int cellID = floorMesh->getCellID(); if (cellID == 0) { //info("cellID == 0", true); WorldCoordinates coord(pathNode->getPosition(), ourCell); path->add(WorldCoordinates(coord.getWorldPosition(), NULL)); } else { CellObject* pathCell = building1->getCell(cellID); WorldCoordinates coord(pathNode->getPosition(), pathCell); path->add(coord); //info("cellID:" + String::valueOf(cellID), true); if (i == nodes->size() - 1) { if (pathNode != target) { StringBuffer msg; msg << "pathNode != target pathNode: " << pathNode->getID() << " target:" << target->getID(); error(msg.toString()); } if (pathCell != targetCell) { error("final cell not target cell"); } } } } delete nodes; nodes = NULL; // path from cell entrance to destination point trianglePath = NULL; res = getFloorPath(path->get(path->size() - 1).getPoint(), pointB.getPoint(), floorMesh2, trianglePath); if (res != -1 && trianglePath != NULL) addTriangleNodeEdges(path->get(path->size() - 1).getPoint(), pointB.getPoint(), trianglePath, path, targetCell); if (trianglePath != NULL) delete trianglePath; path->add(pointB); return path; }
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); }
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; }