feat: move all ldf config to be in xml (#1482)

* feat: move all ldf config to be in xml
cleanup dev-tribute.xml
add comments to atm.xml
remove custom script tag in favor of ldfconfig for it

* replace sto* calls with tryParse's

* remove unesessary .has_value() calls and check for null_lot

* remove member variable naming that on on-member vars

* move max's vendor inventory to be configurable via vanity

* Consolidate triplecated vendor code

* don't write name if one is not given

* Updates to vanity xml's and demo for later docs

* rename vars
This commit is contained in:
Aaron Kimbrell 2024-02-28 17:16:47 -06:00 committed by GitHub
parent ef3fdba621
commit 43707952d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 745 additions and 582 deletions

View File

@ -179,7 +179,7 @@ file(ARCHIVE_EXTRACT INPUT ${PROJECT_BINARY_DIR}/navmeshes.zip DESTINATION ${PRO
file(REMOVE ${PROJECT_BINARY_DIR}/navmeshes.zip) file(REMOVE ${PROJECT_BINARY_DIR}/navmeshes.zip)
# Copy vanity files on first build # Copy vanity files on first build
set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "root.xml" "dev-tribute.xml" "atm.xml") set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "root.xml" "dev-tribute.xml" "atm.xml" "demo.xml")
foreach(file ${VANITY_FILES}) foreach(file ${VANITY_FILES})
configure_file("${CMAKE_SOURCE_DIR}/vanity/${file}" "${CMAKE_BINARY_DIR}/vanity/${file}" COPYONLY) configure_file("${CMAKE_SOURCE_DIR}/vanity/${file}" "${CMAKE_BINARY_DIR}/vanity/${file}" COPYONLY)

View File

@ -2191,9 +2191,3 @@ void Entity::SetRespawnRot(const NiQuaternion& rotation) {
auto* characterComponent = GetComponent<CharacterComponent>(); auto* characterComponent = GetComponent<CharacterComponent>();
if (characterComponent) characterComponent->SetRespawnRot(rotation); if (characterComponent) characterComponent->SetRespawnRot(rotation);
} }
void Entity::SetScale(const float scale) {
if (scale == m_Scale) return;
m_Scale = scale;
Game::entityManager->SerializeEntity(this);
}

View File

@ -295,7 +295,8 @@ public:
void ProcessPositionUpdate(PositionUpdate& update); void ProcessPositionUpdate(PositionUpdate& update);
void SetScale(const float scale); // Scale will only be communicated to the client when the construction packet is sent
void SetScale(const float scale) { m_Scale = scale; };
protected: protected:
LWOOBJID m_ObjectID; LWOOBJID m_ObjectID;

View File

@ -40,9 +40,19 @@ void VendorComponent::RefreshInventory(bool isCreation) {
SetHasMultiCostItems(false); SetHasMultiCostItems(false);
m_Inventory.clear(); m_Inventory.clear();
// Custom code for Max vanity NPC and Mr.Ree cameras // Custom code for Vanity Vendor Invetory Override
if(isCreation && m_Parent->GetLOT() == 9749 && Game::server->GetZoneID() == 1201) { if(m_Parent->HasVar(u"vendorInvOverride")) {
SetupMaxCustomVendor(); std::vector<std::string> items = GeneralUtils::SplitString(m_Parent->GetVarAsString(u"vendorInvOverride"), ',');
uint32_t sortPriority = -1;
for (auto& itemString : items) {
itemString.erase(remove_if(itemString.begin(), itemString.end(), isspace), itemString.end());
auto item = GeneralUtils::TryParse<uint32_t>(itemString);
if (!item) continue;
if (SetupItem(item.value())) {
sortPriority++;
m_Inventory.push_back(SoldItem(item.value(), sortPriority));
}
}
return; return;
} }
@ -52,24 +62,12 @@ void VendorComponent::RefreshInventory(bool isCreation) {
if (lootMatrices.empty()) return; if (lootMatrices.empty()) return;
auto* lootTableTable = CDClientManager::GetTable<CDLootTableTable>(); auto* lootTableTable = CDClientManager::GetTable<CDLootTableTable>();
auto* itemComponentTable = CDClientManager::GetTable<CDItemComponentTable>();
auto* compRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
for (const auto& lootMatrix : lootMatrices) { for (const auto& lootMatrix : lootMatrices) {
auto vendorItems = lootTableTable->GetTable(lootMatrix.LootTableIndex); auto vendorItems = lootTableTable->GetTable(lootMatrix.LootTableIndex);
if (lootMatrix.maxToDrop == 0 || lootMatrix.minToDrop == 0) { if (lootMatrix.maxToDrop == 0 || lootMatrix.minToDrop == 0) {
for (const auto& item : vendorItems) { for (const auto& item : vendorItems) {
if (!m_HasStandardCostItems || !m_HasMultiCostItems) { if (SetupItem(item.itemid)) m_Inventory.push_back(SoldItem(item.itemid, item.sortPriority));
auto itemComponentID = compRegistryTable->GetByIDAndType(item.itemid, eReplicaComponentType::ITEM, -1);
if (itemComponentID == -1) {
LOG("Attempted to add item %i with ItemComponent ID -1 to vendor %i inventory. Not adding item!", itemComponentID, m_Parent->GetLOT());
continue;
}
auto itemComponent = itemComponentTable->GetItemComponentByID(itemComponentID);
if (!m_HasStandardCostItems && itemComponent.baseValue != -1) SetHasStandardCostItems(true);
if (!m_HasMultiCostItems && !itemComponent.currencyCosts.empty()) SetHasMultiCostItems(true);
}
m_Inventory.push_back(SoldItem(item.itemid, item.sortPriority));
} }
} else { } else {
auto randomCount = GeneralUtils::GenerateRandomNumber<int32_t>(lootMatrix.minToDrop, lootMatrix.maxToDrop); auto randomCount = GeneralUtils::GenerateRandomNumber<int32_t>(lootMatrix.minToDrop, lootMatrix.maxToDrop);
@ -79,17 +77,7 @@ void VendorComponent::RefreshInventory(bool isCreation) {
auto randomItemIndex = GeneralUtils::GenerateRandomNumber<int32_t>(0, vendorItems.size() - 1); auto randomItemIndex = GeneralUtils::GenerateRandomNumber<int32_t>(0, vendorItems.size() - 1);
const auto& randomItem = vendorItems.at(randomItemIndex); const auto& randomItem = vendorItems.at(randomItemIndex);
vendorItems.erase(vendorItems.begin() + randomItemIndex); vendorItems.erase(vendorItems.begin() + randomItemIndex);
if (!m_HasStandardCostItems || !m_HasMultiCostItems) { if (SetupItem(randomItem.itemid)) m_Inventory.push_back(SoldItem(randomItem.itemid, randomItem.sortPriority));
auto itemComponentID = compRegistryTable->GetByIDAndType(randomItem.itemid, eReplicaComponentType::ITEM, -1);
if (itemComponentID == -1) {
LOG("Attempted to add item %i with ItemComponent ID -1 to vendor %i inventory. Not adding item!", itemComponentID, m_Parent->GetLOT());
continue;
}
auto itemComponent = itemComponentTable->GetItemComponentByID(itemComponentID);
if (!m_HasStandardCostItems && itemComponent.baseValue != -1) SetHasStandardCostItems(true);
if (!m_HasMultiCostItems && !itemComponent.currencyCosts.empty()) SetHasMultiCostItems(true);
}
m_Inventory.push_back(SoldItem(randomItem.itemid, randomItem.sortPriority));
} }
} }
} }
@ -126,15 +114,6 @@ bool VendorComponent::SellsItem(const LOT item) const {
}) > 0; }) > 0;
} }
void VendorComponent::SetupMaxCustomVendor(){
SetHasStandardCostItems(true);
m_Inventory.push_back(SoldItem(11909, 0)); // Top hat w frog
m_Inventory.push_back(SoldItem(7785, 0)); // Flash bulb
m_Inventory.push_back(SoldItem(12764, 0)); // Big fountain soda
m_Inventory.push_back(SoldItem(12241, 0)); // Hot cocoa (from fb)
}
void VendorComponent::HandleMrReeCameras(){ void VendorComponent::HandleMrReeCameras(){
if (m_Parent->GetLOT() == 13569) { if (m_Parent->GetLOT() == 13569) {
SetHasStandardCostItems(true); SetHasStandardCostItems(true);
@ -211,5 +190,25 @@ void VendorComponent::Buy(Entity* buyer, LOT lot, uint32_t count) {
character->SetCoins(character->GetCoins() - (coinCost), eLootSourceType::VENDOR); character->SetCoins(character->GetCoins() - (coinCost), eLootSourceType::VENDOR);
inventoryComponent->AddItem(lot, count, eLootSourceType::VENDOR); inventoryComponent->AddItem(lot, count, eLootSourceType::VENDOR);
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_SUCCESS); GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_SUCCESS);
}
bool VendorComponent::SetupItem(LOT item) {
auto* itemComponentTable = CDClientManager::GetTable<CDItemComponentTable>();
auto* compRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
auto itemComponentID = compRegistryTable->GetByIDAndType(item, eReplicaComponentType::ITEM, -1);
if (itemComponentID == -1) {
LOG("Attempted to add item %i with ItemComponent ID -1 to vendor %i inventory. Not adding item!", itemComponentID, m_Parent->GetLOT());
return false;
}
if (!m_HasStandardCostItems || !m_HasMultiCostItems) {
auto itemComponent = itemComponentTable->GetItemComponentByID(itemComponentID);
if (!m_HasStandardCostItems && itemComponent.baseValue != -1) SetHasStandardCostItems(true);
if (!m_HasMultiCostItems && !itemComponent.currencyCosts.empty()) SetHasMultiCostItems(true);
}
return true;
}
}

View File

@ -50,8 +50,8 @@ public:
void Buy(Entity* buyer, LOT lot, uint32_t count); void Buy(Entity* buyer, LOT lot, uint32_t count);
private: private:
void SetupMaxCustomVendor();
void HandleMrReeCameras(); void HandleMrReeCameras();
bool SetupItem(LOT item);
float m_BuyScalar = 0.0f; float m_BuyScalar = 0.0f;
float m_SellScalar = 0.0f; float m_SellScalar = 0.0f;
float m_RefreshTimeSeconds = 0.0f; float m_RefreshTimeSeconds = 0.0f;

View File

@ -22,9 +22,18 @@
#include <fstream> #include <fstream>
std::vector<VanityObject> VanityUtilities::m_Objects = {};
std::set<std::string> VanityUtilities::m_LoadedFiles = {};
namespace {
std::vector<VanityObject> objects;
std::set<std::string> loadedFiles;
}
void SetupNPCTalk(Entity* npc);
void NPCTalk(Entity* npc);
void ParseXml(const std::string& file);
LWOOBJID SpawnSpawner(const VanityObject& object, const VanityObjectLocation& location);
Entity* SpawnObject(const VanityObject& object, const VanityObjectLocation& location);
VanityObject* GetObject(const std::string& name);
void VanityUtilities::SpawnVanity() { void VanityUtilities::SpawnVanity() {
const uint32_t zoneID = Game::server->GetZoneID(); const uint32_t zoneID = Game::server->GetZoneID();
@ -36,21 +45,19 @@ void VanityUtilities::SpawnVanity() {
info.pos = { 259.5f, 246.4f, -705.2f }; info.pos = { 259.5f, 246.4f, -705.2f };
info.rot = { 0.0f, 0.0f, 1.0f, 0.0f }; info.rot = { 0.0f, 0.0f, 1.0f, 0.0f };
info.spawnerID = Game::entityManager->GetZoneControlEntity()->GetObjectID(); info.spawnerID = Game::entityManager->GetZoneControlEntity()->GetObjectID();
info.settings = {
info.settings = { new LDFData<bool>(u"hasCustomText", true), new LDFData<bool>(u"hasCustomText", true),
new LDFData<std::string>(u"customText", ParseMarkdown((BinaryPathFinder::GetBinaryDir() / "vanity/TESTAMENT.md").string())) }; new LDFData<std::string>(u"customText", ParseMarkdown((BinaryPathFinder::GetBinaryDir() / "vanity/TESTAMENT.md").string()))
};
auto* entity = Game::entityManager->CreateEntity(info); auto* entity = Game::entityManager->CreateEntity(info);
Game::entityManager->ConstructEntity(entity); Game::entityManager->ConstructEntity(entity);
} }
} }
if (Game::config->GetValue("disable_vanity") == "1") { if (Game::config->GetValue("disable_vanity") == "1") return;
return;
}
for (const auto& npc : m_Objects) { for (const auto& npc : objects) {
if (npc.m_ID == LWOOBJID_EMPTY) continue; if (npc.m_ID == LWOOBJID_EMPTY) continue;
if (npc.m_LOT == 176){ if (npc.m_LOT == 176){
Game::zoneManager->RemoveSpawner(npc.m_ID); Game::zoneManager->RemoveSpawner(npc.m_ID);
@ -61,13 +68,13 @@ void VanityUtilities::SpawnVanity() {
} }
} }
m_Objects.clear(); objects.clear();
m_LoadedFiles.clear(); loadedFiles.clear();
ParseXML((BinaryPathFinder::GetBinaryDir() / "vanity/root.xml").string()); ParseXml((BinaryPathFinder::GetBinaryDir() / "vanity/root.xml").string());
// Loop through all objects // Loop through all objects
for (auto& object : m_Objects) { for (auto& object : objects) {
if (object.m_Locations.find(Game::server->GetZoneID()) == object.m_Locations.end()) continue; if (object.m_Locations.find(Game::server->GetZoneID()) == object.m_Locations.end()) continue;
const std::vector<VanityObjectLocation>& locations = object.m_Locations.at(Game::server->GetZoneID()); const std::vector<VanityObjectLocation>& locations = object.m_Locations.at(Game::server->GetZoneID());
@ -79,12 +86,6 @@ void VanityUtilities::SpawnVanity() {
float rate = GeneralUtils::GenerateRandomNumber<float>(0, 1); float rate = GeneralUtils::GenerateRandomNumber<float>(0, 1);
if (location.m_Chance < rate) continue; if (location.m_Chance < rate) continue;
if (object.m_Config.empty()) {
object.m_Config = {
new LDFData<std::vector<std::u16string>>(u"syncLDF", { u"custom_script_client" }),
new LDFData<std::u16string>(u"custom_script_client", u"scripts\\ai\\SPEC\\MISSION_MINIGAME_CLIENT.lua")
};
}
if (object.m_LOT == 176){ if (object.m_LOT == 176){
object.m_ID = SpawnSpawner(object, location); object.m_ID = SpawnSpawner(object, location);
} else { } else {
@ -94,20 +95,13 @@ void VanityUtilities::SpawnVanity() {
object.m_ID = objectEntity->GetObjectID(); object.m_ID = objectEntity->GetObjectID();
if (!object.m_Phrases.empty()){ if (!object.m_Phrases.empty()){
objectEntity->SetVar<std::vector<std::string>>(u"chats", object.m_Phrases); objectEntity->SetVar<std::vector<std::string>>(u"chats", object.m_Phrases);
auto* scriptComponent = objectEntity->GetComponent<ScriptComponent>();
if (scriptComponent && !object.m_Script.empty()) {
scriptComponent->SetScript(object.m_Script);
scriptComponent->SetSerialized(false);
}
SetupNPCTalk(objectEntity); SetupNPCTalk(objectEntity);
} }
} }
} }
} }
LWOOBJID VanityUtilities::SpawnSpawner(const VanityObject& object, const VanityObjectLocation& location) { LWOOBJID SpawnSpawner(const VanityObject& object, const VanityObjectLocation& location) {
SceneObject obj; SceneObject obj;
obj.lot = object.m_LOT; obj.lot = object.m_LOT;
// guratantee we have no collisions // guratantee we have no collisions
@ -121,7 +115,7 @@ LWOOBJID VanityUtilities::SpawnSpawner(const VanityObject& object, const VanityO
return obj.id; return obj.id;
} }
Entity* VanityUtilities::SpawnObject(const VanityObject& object, const VanityObjectLocation& location) { Entity* SpawnObject(const VanityObject& object, const VanityObjectLocation& location) {
EntityInfo info; EntityInfo info;
info.lot = object.m_LOT; info.lot = object.m_LOT;
info.pos = location.m_Position; info.pos = location.m_Position;
@ -131,18 +125,16 @@ Entity* VanityUtilities::SpawnObject(const VanityObject& object, const VanityObj
info.settings = object.m_Config; info.settings = object.m_Config;
auto* entity = Game::entityManager->CreateEntity(info); auto* entity = Game::entityManager->CreateEntity(info);
entity->SetVar(u"npcName", object.m_Name); if (!object.m_Name.empty()) entity->SetVar(u"npcName", object.m_Name);
if (entity->GetVar<bool>(u"noGhosting")) entity->SetIsGhostingCandidate(false); if (entity->GetVar<bool>(u"noGhosting")) entity->SetIsGhostingCandidate(false);
auto* inventoryComponent = entity->GetComponent<InventoryComponent>(); auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
if (inventoryComponent && !object.m_Equipment.empty()) { if (inventoryComponent && !object.m_Equipment.empty()) {
inventoryComponent->SetNPCItems(object.m_Equipment); inventoryComponent->SetNPCItems(object.m_Equipment);
} }
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>(); auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent) {
if (destroyableComponent != nullptr) {
destroyableComponent->SetIsGMImmune(true); destroyableComponent->SetIsGMImmune(true);
destroyableComponent->SetMaxHealth(0); destroyableComponent->SetMaxHealth(0);
destroyableComponent->SetHealth(0); destroyableComponent->SetHealth(0);
@ -153,12 +145,12 @@ Entity* VanityUtilities::SpawnObject(const VanityObject& object, const VanityObj
return entity; return entity;
} }
void VanityUtilities::ParseXML(const std::string& file) { void ParseXml(const std::string& file) {
if (m_LoadedFiles.contains(file)){ if (loadedFiles.contains(file)){
LOG("Trying to load vanity file %s twice!!!", file.c_str()); LOG("Trying to load vanity file %s twice!!!", file.c_str());
return; return;
} }
m_LoadedFiles.insert(file); loadedFiles.insert(file);
// Read the entire file // Read the entire file
std::ifstream xmlFile(file); std::ifstream xmlFile(file);
std::string xml((std::istreambuf_iterator<char>(xmlFile)), std::istreambuf_iterator<char>()); std::string xml((std::istreambuf_iterator<char>(xmlFile)), std::istreambuf_iterator<char>());
@ -176,24 +168,26 @@ void VanityUtilities::ParseXML(const std::string& file) {
if (enabled != "1") { if (enabled != "1") {
continue; continue;
} }
ParseXML((BinaryPathFinder::GetBinaryDir() / "vanity" / filename).string()); ParseXml((BinaryPathFinder::GetBinaryDir() / "vanity" / filename).string());
} }
} }
// Read the objects // Read the objects
auto* objects = doc.FirstChildElement("objects"); auto* objectsElement = doc.FirstChildElement("objects");
const uint32_t currentZoneID = Game::server->GetZoneID();
if (objects) { if (objectsElement) {
for (auto* object = objects->FirstChildElement("object"); object != nullptr; object = object->NextSiblingElement("object")) { for (auto* object = objectsElement->FirstChildElement("object"); object != nullptr; object = object->NextSiblingElement("object")) {
// for use later when adding to the vector of VanityObjects
bool useLocationsAsRandomSpawnPoint = false;
// Get the NPC name // Get the NPC name
auto* name = object->Attribute("name"); auto* name = object->Attribute("name");
if (!name) name = ""; if (!name) name = "";
// Get the NPC lot // Get the NPC lot
auto* lot = object->Attribute("lot"); auto lot = GeneralUtils::TryParse<LOT>(object->Attribute("lot")).value_or(LOT_NULL);
if (lot == nullptr) { if (lot == LOT_NULL) {
LOG("Failed to parse object lot"); LOG("Failed to parse object lot");
continue; continue;
} }
@ -211,17 +205,17 @@ void VanityUtilities::ParseXML(const std::string& file) {
std::vector<std::string> splitEquipment = GeneralUtils::SplitString(equipmentString, ','); std::vector<std::string> splitEquipment = GeneralUtils::SplitString(equipmentString, ',');
for (auto& item : splitEquipment) { for (auto& item : splitEquipment) {
inventory.push_back(std::stoi(item)); // remove spaces for tryParse to work
item.erase(remove_if(item.begin(), item.end(), isspace), item.end());
auto itemInt = GeneralUtils::TryParse<uint32_t>(item);
if (itemInt) inventory.push_back(itemInt.value());
} }
} }
} }
// Get the phrases // Get the phrases
auto* phrases = object->FirstChildElement("phrases"); auto* phrases = object->FirstChildElement("phrases");
std::vector<std::string> phraseList = {}; std::vector<std::string> phraseList = {};
if (phrases) { if (phrases) {
for (auto* phrase = phrases->FirstChildElement("phrase"); phrase != nullptr; for (auto* phrase = phrases->FirstChildElement("phrase"); phrase != nullptr;
phrase = phrase->NextSiblingElement("phrase")) { phrase = phrase->NextSiblingElement("phrase")) {
@ -235,41 +229,34 @@ void VanityUtilities::ParseXML(const std::string& file) {
} }
} }
// Get the script
auto* scriptElement = object->FirstChildElement("script");
std::string scriptName = "";
if (scriptElement != nullptr) {
auto* scriptNameAttribute = scriptElement->Attribute("name");
if (scriptNameAttribute) scriptName = scriptNameAttribute;
}
auto* configElement = object->FirstChildElement("config"); auto* configElement = object->FirstChildElement("config");
std::vector<std::u16string> keys = {}; std::vector<std::u16string> keys = {};
std::vector<LDFBaseData*> config = {}; std::vector<LDFBaseData*> config = {};
if(configElement) { if(configElement) {
for (auto* key = configElement->FirstChildElement("key"); key != nullptr; for (auto* key = configElement->FirstChildElement("key"); key != nullptr;
key = key->NextSiblingElement("key")) { key = key->NextSiblingElement("key")) {
// Get the config data // Get the config data
auto* data = key->Attribute("data"); auto* data = key->GetText();
if (!data) continue; if (!data) continue;
LDFBaseData* configData = LDFBaseData::DataFromString(data); LDFBaseData* configData = LDFBaseData::DataFromString(data);
if (configData->GetKey() == u"useLocationsAsRandomSpawnPoint" && configData->GetValueType() == eLDFType::LDF_TYPE_BOOLEAN){
useLocationsAsRandomSpawnPoint = static_cast<bool>(configData);
continue;
}
keys.push_back(configData->GetKey()); keys.push_back(configData->GetKey());
config.push_back(configData); config.push_back(configData);
} }
} }
if (!keys.empty()) config.push_back(new LDFData<std::vector<std::u16string>>(u"syncLDF", keys)); if (!keys.empty()) config.push_back(new LDFData<std::vector<std::u16string>>(u"syncLDF", keys));
VanityObject objectData; VanityObject objectData {
objectData.m_Name = name; .m_Name = name,
objectData.m_LOT = std::stoi(lot); .m_LOT = lot,
objectData.m_Equipment = inventory; .m_Equipment = inventory,
objectData.m_Phrases = phraseList; .m_Phrases = phraseList,
objectData.m_Script = scriptName; .m_Config = config
objectData.m_Config = config; };
// Get the locations // Get the locations
auto* locations = object->FirstChildElement("locations"); auto* locations = object->FirstChildElement("locations");
@ -283,64 +270,67 @@ void VanityUtilities::ParseXML(const std::string& file) {
location = location->NextSiblingElement("location")) { location = location->NextSiblingElement("location")) {
// Get the location data // Get the location data
auto* zoneID = location->Attribute("zone"); auto zoneID = GeneralUtils::TryParse<uint32_t>(location->Attribute("zone"));
auto* x = location->Attribute("x"); auto x = GeneralUtils::TryParse<float>(location->Attribute("x"));
auto* y = location->Attribute("y"); auto y = GeneralUtils::TryParse<float>(location->Attribute("y"));
auto* z = location->Attribute("z"); auto z = GeneralUtils::TryParse<float>(location->Attribute("z"));
auto* rw = location->Attribute("rw"); auto rw = GeneralUtils::TryParse<float>(location->Attribute("rw"));
auto* rx = location->Attribute("rx"); auto rx = GeneralUtils::TryParse<float>(location->Attribute("rx"));
auto* ry = location->Attribute("ry"); auto ry = GeneralUtils::TryParse<float>(location->Attribute("ry"));
auto* rz = location->Attribute("rz"); auto rz = GeneralUtils::TryParse<float>(location->Attribute("rz"));
if (zoneID == nullptr || x == nullptr || y == nullptr || z == nullptr || rw == nullptr || rx == nullptr || ry == nullptr if (!zoneID || !x || !y || !z || !rw || !rx || !ry || !rz) {
|| rz == nullptr) {
LOG("Failed to parse NPC location data"); LOG("Failed to parse NPC location data");
continue; continue;
} }
VanityObjectLocation locationData; if (zoneID.value() != currentZoneID) {
locationData.m_Position = { std::stof(x), std::stof(y), std::stof(z) }; LOG_DEBUG("Skipping location because it is in %i and not the current zone (%i)", zoneID.value(), currentZoneID);
locationData.m_Rotation = { std::stof(rw), std::stof(rx), std::stof(ry), std::stof(rz) }; continue;
locationData.m_Chance = 1.0f; }
VanityObjectLocation locationData {
.m_Position = { x.value(), y.value(), z.value() },
.m_Rotation = { rw.value(), rx.value(), ry.value(), rz.value() },
};
if (location->Attribute("chance")) { if (location->Attribute("chance")) {
locationData.m_Chance = std::stof(location->Attribute("chance")); locationData.m_Chance = GeneralUtils::TryParse<float>(location->Attribute("chance")).value_or(1.0f);
} }
if (location->Attribute("scale")) { if (location->Attribute("scale")) {
locationData.m_Scale = std::stof(location->Attribute("scale")); locationData.m_Scale = GeneralUtils::TryParse<float>(location->Attribute("scale")).value_or(1.0f);
} }
const auto& it = objectData.m_Locations.find(zoneID.value());
const auto& it = objectData.m_Locations.find(std::stoi(zoneID));
if (it != objectData.m_Locations.end()) { if (it != objectData.m_Locations.end()) {
it->second.push_back(locationData); it->second.push_back(locationData);
} else { } else {
std::vector<VanityObjectLocation> locations; std::vector<VanityObjectLocation> locations;
locations.push_back(locationData); locations.push_back(locationData);
objectData.m_Locations.insert(std::make_pair(std::stoi(zoneID), locations)); objectData.m_Locations.insert(std::make_pair(zoneID.value(), locations));
} }
if (!(std::find(keys.begin(), keys.end(), u"teleport") != keys.end())) { if (!useLocationsAsRandomSpawnPoint) {
m_Objects.push_back(objectData); objects.push_back(objectData);
objectData.m_Locations.clear(); objectData.m_Locations.clear();
} }
} }
if (std::find(keys.begin(), keys.end(), u"teleport") != keys.end()) {
m_Objects.push_back(objectData); if (useLocationsAsRandomSpawnPoint && !objectData.m_Locations.empty()) {
} objects.push_back(objectData);
}
} }
} }
} }
VanityObject* VanityUtilities::GetObject(const std::string& name) { VanityObject* VanityUtilities::GetObject(const std::string& name) {
for (size_t i = 0; i < m_Objects.size(); i++) { for (size_t i = 0; i < objects.size(); i++) {
if (m_Objects[i].m_Name == name) { if (objects[i].m_Name == name) {
return &m_Objects[i]; return &objects[i];
} }
} }
return nullptr; return nullptr;
} }
@ -350,7 +340,7 @@ std::string VanityUtilities::ParseMarkdown(const std::string& file) {
// Read the file into a string // Read the file into a string
std::ifstream t(file); std::ifstream t(file);
std::stringstream output; std::stringstream output;
// If the file does not exist, return an empty string. // If the file does not exist, return a useful error.
if (!t.good()) { if (!t.good()) {
output << "File "; output << "File ";
output << file.substr(file.rfind("/") + 1); output << file.substr(file.rfind("/") + 1);
@ -408,13 +398,13 @@ std::string VanityUtilities::ParseMarkdown(const std::string& file) {
return output.str(); return output.str();
} }
void VanityUtilities::SetupNPCTalk(Entity* npc) { void SetupNPCTalk(Entity* npc) {
npc->AddCallbackTimer(15.0f, [npc]() { NPCTalk(npc); }); npc->AddCallbackTimer(15.0f, [npc]() { NPCTalk(npc); });
npc->SetProximityRadius(20.0f, "talk"); npc->SetProximityRadius(20.0f, "talk");
} }
void VanityUtilities::NPCTalk(Entity* npc) { void NPCTalk(Entity* npc) {
auto* proximityMonitorComponent = npc->GetComponent<ProximityMonitorComponent>(); auto* proximityMonitorComponent = npc->GetComponent<ProximityMonitorComponent>();
if (!proximityMonitorComponent->GetProximityObjects("talk").empty()) { if (!proximityMonitorComponent->GetProximityObjects("talk").empty()) {

View File

@ -5,58 +5,30 @@
#include <map> #include <map>
#include <set> #include <set>
struct VanityObjectLocation struct VanityObjectLocation {
{
float m_Chance = 1.0f; float m_Chance = 1.0f;
NiPoint3 m_Position; NiPoint3 m_Position;
NiQuaternion m_Rotation; NiQuaternion m_Rotation;
float m_Scale = 1.0f; float m_Scale = 1.0f;
}; };
struct VanityObject struct VanityObject {
{
LWOOBJID m_ID = LWOOBJID_EMPTY; LWOOBJID m_ID = LWOOBJID_EMPTY;
std::string m_Name; std::string m_Name;
LOT m_LOT; LOT m_LOT = LOT_NULL;
std::vector<LOT> m_Equipment; std::vector<LOT> m_Equipment;
std::vector<std::string> m_Phrases; std::vector<std::string> m_Phrases;
std::string m_Script;
std::map<uint32_t, std::vector<VanityObjectLocation>> m_Locations; std::map<uint32_t, std::vector<VanityObjectLocation>> m_Locations;
std::vector<LDFBaseData*> m_Config; std::vector<LDFBaseData*> m_Config;
}; };
class VanityUtilities namespace VanityUtilities {
{ void SpawnVanity();
public:
static void SpawnVanity();
static Entity* SpawnObject( VanityObject* GetObject(const std::string& name);
const VanityObject& object,
const VanityObjectLocation& location
);
static LWOOBJID SpawnSpawner( std::string ParseMarkdown(
const VanityObject& object,
const VanityObjectLocation& location
);
static std::string ParseMarkdown(
const std::string& file const std::string& file
); );
static void ParseXML(
const std::string& file
);
static VanityObject* GetObject(const std::string& name);
private:
static void SetupNPCTalk(Entity* npc);
static void NPCTalk(Entity* npc);
static std::vector<VanityObject> m_Objects;
static std::set<std::string> m_LoadedFiles;
}; };

View File

@ -5,20 +5,17 @@
#include "RenderComponent.h" #include "RenderComponent.h"
void DLUVanityTeleportingObject::OnStartup(Entity* self) { void DLUVanityTeleportingObject::OnStartup(Entity* self) {
if (!self->HasVar(u"npcName") || !self->HasVar(u"teleport")) return; if (!self->HasVar(u"npcName")) return;
m_Object = VanityUtilities::GetObject(self->GetVarAsString(u"npcName"));
m_Object = VanityUtilities::GetObject(self->GetVarAsString(u"npcName"));
if (!m_Object) return; if (!m_Object) return;
if (self->HasVar(u"teleportInterval")) m_TeleportInterval = self->GetVar<float>(u"teleportInterval"); if (self->HasVar(u"teleportInterval")) m_TeleportInterval = self->GetVar<float>(u"teleportInterval");
if (self->GetVar<bool>(u"teleport")) { self->AddTimer("setupTeleport", m_TeleportInterval);
self->AddTimer("setupTeleport", m_TeleportInterval);
}
} }
void DLUVanityTeleportingObject::OnTimerDone(Entity* self, std::string timerName) { void DLUVanityTeleportingObject::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "setupTeleport") { if (timerName == "setupTeleport") {
RenderComponent::PlayAnimation(self, u"interact");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportBeam", "teleportBeam"); GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportBeam", "teleportBeam");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportRings", "teleportRings"); GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportRings", "teleportRings");
@ -40,7 +37,6 @@ void DLUVanityTeleportingObject::OnTimerDone(Entity* self, std::string timerName
self->SetPosition(newLocation.m_Position); self->SetPosition(newLocation.m_Position);
self->SetRotation(newLocation.m_Rotation); self->SetRotation(newLocation.m_Rotation);
self->SetScale(newLocation.m_Scale);
GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportBeam", "teleportBeam"); GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportBeam", "teleportBeam");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportRings", "teleportRings"); GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportRings", "teleportRings");
self->AddTimer("stopFX", 2.0f); self->AddTimer("stopFX", 2.0f);

View File

@ -1,23 +1,40 @@
<objects> <objects>
<object lot="13538"> <object lot="13538">
<config> <config>
<key data="CheckPrecondition=0:168"/> <!--Precondition 168 means the player must complete mission 1203 before being able to use an ATM-->
</config> <key>CheckPrecondition=0:168</key>
<locations> </config>
<location zone="1100" x="248.792" y="381.869" z="-181.114" rw="0.782761" rx="0.00" ry="-0.622322" rz="0.00" /> <locations>
<location zone="1100" x="471.545" y="413.979" z="27.176" rw="0.874378" rx="0.00" ry="-0.485246" rz="0.00" /> <!--AG Sentinel Base Camp-->
<location zone="1200" x="51.663" y="291.371" z="-74.650" rw="-0.446235" rx="0.00" ry="0.894916" rz="0.00" /> <location zone="1100" x="248.792" y="381.781" z="-181.114" rw="0.782761" rx="0.00" ry="-0.622322" rz="0.00" />
<location zone="1200" x="203.348" y="259.136" z="-543.400" rw="0.481554" rx="0.00" ry="0.876416" rz="0.00" /> <!--AG Picnic Area-->
<location zone="1201" x="46.537" y="233.137" z="-311.395" rw="0.780747" rx="0.00" ry="-0.624847" rz="0.00" /> <location zone="1100" x="471.545" y="413.719" z="27.176" rw="0.874378" rx="0.00" ry="-0.485246" rz="0.00" />
<location zone="1260" x="-255.991" y="535.731" z="322.299" rw="0.683777" rx="0.00" ry="-0.729691" rz="0.00" /> <!--NS Nimbus Plaza-->
<location zone="1600" x="85.210" y="1526.810" z="314.816" rw="-0.159486" rx="0.00" ry="0.987200" rz="0.00" /> <location zone="1200" x="51.663" y="291.371" z="-74.650" rw="-0.446235" rx="0.00" ry="0.894916" rz="0.00" />
<location zone="1700" x="-256.293" y="1035.092" z="109.761" rw="0.00" rx="0.00" ry="1" rz="0.00" /> <!--NS Red Blocks-->
<location zone="1300" x="-199.258" y="246.874" z="-101.174" rw="-0.219711" rx="0.00" ry="0.975565" rz="0.00" /> <location zone="1200" x="203.348" y="259.0" z="-543.400" rw="0.481554" rx="0.00" ry="0.876416" rz="0.00" />
<location zone="1300" x="51.848" y="329.0" z="561.114" rw="-0.277656" rx="0.00" ry="0.960681" rz="0.00" /> <!--PC by Lighthouse-->
<location zone="1300" x="363.259" y="259.367" z="-210.834" rw="0.961918" rx="0.00" ry="-0.273340" rz="0.00" /> <location zone="1201" x="46.537" y="232.958" z="-311.395" rw="0.780747" rx="0.00" ry="-0.624847" rz="0.00" />
<location zone="1400" x="-194.288" y="381.275" z="-93.292" rw="0.935135" rx="0.00" ry="0.354292" rz="0.00" /> <!--Frostburgh-->
<location zone="1400" x="-696.957" y="-3.206" z="-452.441" rw="0.884105" rx="0.00" ry="0.467288" rz="0.00" /> <location zone="1260" x="-255.991" y="535.731" z="322.299" rw="0.683777" rx="0.00" ry="-0.729691" rz="0.00" />
<location zone="1800" x="-222.634" y="92.693" z="568.392" rw="-0.435024" rx="0.00" ry="0.900419" rz="0.00" /> <!--Starbase 3001-->
</locations> <location zone="1600" x="93.572" y="1526.970" z="311.905" rw="-0.159486" rx="0.00" ry="0.987200" rz="0.00" />
</object> <!--LEGO Club-->
<location zone="1700" x="-256.293" y="1035.092" z="109.761" rw="0.00" rx="0.00" ry="1" rz="0.00" />
<!--GF Ravine-->
<location zone="1300" x="-199.258" y="246.874" z="-101.174" rw="-0.219711" rx="0.00" ry="0.975565" rz="0.00" />
<!--GF Race Place-->
<location zone="1300" x="51.848" y="329.0" z="561.114" rw="-0.277656" rx="0.00" ry="0.960681" rz="0.00" />
<!--GF Pirate Camp-->
<location zone="1300" x="363.259" y="259.367" z="-210.834" rw="0.961918" rx="0.00" ry="-0.273340" rz="0.00" />
<!--FV Great Tree-->
<location zone="1400" x="-194.288" y="381.275" z="-93.292" rw="0.935135" rx="0.00" ry="0.354292" rz="0.00" />
<!--FV Paradox Refinery-->
<location zone="1400" x="-696.957" y="-3.206" z="-452.441" rw="0.884105" rx="0.00" ry="0.467288" rz="0.00" />
<!--CP Sentinel Point Zeta-->
<location zone="1800" x="-222.634" y="92.373" z="568.392" rw="-0.435024" rx="0.00" ry="0.900419" rz="0.00" />
<!--NJ Monastery Courtyard-->
<location zone="2000" x="-63.487" y="208.270" z="379.195" rw="0.00" rx="0.00" ry="1" rz="0.00" />
</locations>
</object>
</objects> </objects>

132
vanity/demo.xml Normal file
View File

@ -0,0 +1,132 @@
<objects>
<!--A tree spawned at two locations with different positions, rotations, and scales-->
<!--Positions and rotations are easily gotten by typing /loc or /pos, and /rot into the in-game chat-->
<object lot="3248">
<locations>
<location zone="1200" x="-15.0" y="288.8" z="-167.0" rw="0.984321" rx="0.00" ry="0.176388" rz="0.00" />
<location zone="1200" x="15.0" y="288.8" z="-158.0" rw="0.724628" rx="0.00" ry="-0.689141" rz="0.00" scale="0.30" />
</locations>
</object>
<!--A vendor who we will give GM-only items-->
<object name="Demo Fella - GM Items Vendor" lot="1867">
<equipment>7630, 1727, 7453, 7521</equipment>
<config>
<key>vendorInvOverride=0:1727,7292,16553,2243,14535,14538,14531,6730</key>
</config>
<locations>
<location zone="1200" x="35.935" y="288.896" z="-128.213" rw="0.882977" rx="0.00" ry="-0.469416" rz="0.00" />
</locations>
</object>
<!--Friendly Felix will choose one of the 3 locations, then have a 50% chance to spawn at one of them on world server startup-->
<object lot="10141">
<config>
<key>useLocationsAsRandomSpawnPoint=7:1</key>
</config>
<locations>
<location zone="1200" x="31.819" y="288.896" z="-117.095" rw="0.630659" rx="0.00" ry="-0.776060" rz="0.00" chance="0.50"/>
<location zone="1200" x="42.755" y="291.897" z="-144.385" rw="0.855306" rx="0.00" ry="-0.518124" rz="0.00" chance="0.50"/>
<location zone="1200" x="3.984" y="288.896" z="-165.947" rw="0.978508" rx="0.00" ry="-0.206210" rz="0.00" chance="0.50"/>
</locations>
</object>
<!--Spawner(s) for enemies, largely copy-pasted from Portabello in this case-->
<object lot="176">
<config>
<key>CheckPrecondition=0:</key>
<key>SmashableDoesNotCutNavmesh=7:0</key>
<key>add_to_navmesh=7:1</key>
<key>aggroRadius=3:15</key>
<key>camGradSnap=7:0</key>
<key>camPrefersToFadeObject=7:1</key>
<key>carver_only=7:0</key>
<key>create_physics=7:1</key>
<key>currency=5:0</key>
<key>custom_config_names=0:</key>
<key>explode_factor=3:1</key>
<key>fxpriority=1:0</key>
<key>gravFactor=3:1</key>
<key>grpNameQBShowBricks=0:</key>
<key>ignoreCameraCollision=7:0</key>
<key>interaction_distance=3:16</key>
<key>is_smashable=7:1</key>
<key>loadOnClientOnly=7:0</key>
<key>loadSrvrOnly=7:0</key>
<key>max_to_spawn=1:-1</key>
<key>navmesh_carver=7:0</key>
<key>no_auto_spawn=7:1</key>
<key>no_timed_spawn=7:1</key>
<key>override_faction=7:0</key>
<key>radius=3:0</key>
<key>renderAnimLODSkew=3:1</key>
<key>renderCullingGroup=5:0</key>
<key>renderOffscreenAnimEnabled=7:0</key>
<key>respawn=3:20</key>
<key>sceneIDOverride=1:255</key>
<key>sceneIDOverrideEnabled=7:0</key>
<key>sceneLayerIDOverride=5:0</key>
<key>set_faction=13:4</key>
<key>smashable_loot_matrix=1:486</key>
<key>smashable_loot_matrix_set=7:0</key>
<key>softtetherRadius=3:15</key>
<key>spawner_active_on_load=7:1</key>
<key>spawntemplate=1:12379</key>
<key>startsQBActivator=7:0</key>
<key>template=1:-1</key>
<key>tetherRadius=3:15</key>
<key>usetetherdb=7:0</key>
<key>usewanderdb=7:0</key>
<key>wanderRadius=3:15</key>
</config>
<locations>
<location zone="1200" x="-16.749" y="291.841" z="-122.349" rw="1.00" rx="0.00" ry="0.00" rz="0.00" />
<location zone="1200" x="-15.696" y="291.608" z="-136.902" rw="1.00" rx="0.00" ry="0.00" rz="0.00" />
</locations>
</object>
<!--Spawner for a crate-->
<object lot="176">
<config>
<key>CheckPrecondition=0:</key>
<key>SmashableDoesNotCutNavmesh=7:0</key>
<key>add_to_navmesh=7:1</key>
<key>bounding_radius_override=3:0</key>
<key>camGradSnap=7:0</key>
<key>camPrefersToFadeObject=7:1</key>
<key>carver_only=7:0</key>
<key>create_physics=7:1</key>
<key>custom_config_names=0:</key>
<key>explode_factor=3:1</key>
<key>friction=3:1.5</key>
<key>fxpriority=1:0</key>
<key>gravFactor=3:1</key>
<key>grpNameQBShowBricks=0:</key>
<key>ignoreCameraCollision=7:0</key>
<key>interaction_distance=3:16</key>
<key>is_smashable=7:1</key>
<key>loadOnClientOnly=7:0</key>
<key>max_to_spawn=1:-1</key>
<key>navmesh_carver=7:0</key>
<key>no_auto_spawn=7:1</key>
<key>no_timed_spawn=7:1</key>
<key>override_faction=7:0</key>
<key>radius=3:0</key>
<key>renderCullingGroup=5:0</key>
<key>respawn=5:20000</key>
<key>sceneIDOverride=1:255</key>
<key>sceneIDOverrideEnabled=7:0</key>
<key>sceneLayerIDOverride=5:0</key>
<key>set_faction=13:6 </key>
<key>smashable_loot_matrix=1:227</key>
<key>smashable_loot_matrix_set=7:0</key>
<key>spawner_active_on_load=7:1</key>
<key>spawntemplate=1:2295</key>
<key>startsQBActivator=7:0</key>
<key>template=1:-1</key>
</config>
<locations>
<location zone="1200" x="4.232" y="288.895" z="-85.846" rw="-0.205988" rx="0.00" ry="0.978555" rz="0.00" />
</locations>
</object>
</objects>

View File

@ -1,378 +1,439 @@
<objects> <objects>
<object name="Wincent - Developer" lot="2279"> <object name="Wincent - Developer" lot="2279">
<equipment>6802, 2519, 2623, 14806</equipment> <equipment>6802, 2519, 2623, 14806</equipment>
<phrases> <phrases>
<phrase>Sorry for the mess.</phrase> <phrase>Sorry for the mess.</phrase>
<phrase>To future endeavours!</phrase> <phrase>To future endeavours!</phrase>
<phrase>What could imagination bring to light?</phrase> <phrase>What could imagination bring to light?</phrase>
<phrase>Vroom vroom...</phrase> <phrase>Vroom vroom...</phrase>
<phrase>Take care to preserve the universe.</phrase> <phrase>Take care to preserve the universe.</phrase>
<phrase>Builders of the world, unite!</phrase> <phrase>Builders of the world, unite!</phrase>
<phrase>Everything is awesome!</phrase> <phrase>Everything is awesome!</phrase>
<phrase>I hope my behaviors are behaving themselves.</phrase> <phrase>I hope my behaviors are behaving themselves.</phrase>
</phrases> </phrases>
<locations> <config>
<location zone="1200" x="-352.5" y="287.6" z="217.7" rw="-0.095" rx="0.0" ry="0.995" rz="0.0" /> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
</locations> </config>
</object> <locations>
<object name="EmosewaMC - Quickbuilder" lot="6738"> <location zone="1200" x="-352.5" y="287.6" z="217.7" rw="-0.095" rx="0.0" ry="0.995" rz="0.0" />
<equipment>12947, 12949, 12962, 12963</equipment> </locations>
<phrases> </object>
<phrase>I hope quickbulds are still working!</phrase> <object name="EmosewaMC - Quickbuilder" lot="6738">
<phrase>Be careful crossing the gap!</phrase> <equipment>12947, 12949, 12962, 12963</equipment>
<phrase>Have The Maelstrom stopped going invisible?</phrase> <phrases>
</phrases> <phrase>I hope quickbulds are still working!</phrase>
<locations> <phrase>Be careful crossing the gap!</phrase>
<location zone="1800" x="745.756" y="75.262" z="-207.989" rw="0.838565" rx="0.0" ry="0.544801" rz="0.0" /> <phrase>Have The Maelstrom stopped going invisible?</phrase>
</locations> </phrases>
</object> <config>
<object name="Neal - Paradox Scout" lot="6738"> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<equipment>9950, 9944, 14102, 14092</equipment> </config>
<phrases> <locations>
<phrase>Hello Explorer! It's great to see you made it!</phrase> <location zone="1800" x="745.756" y="75.262" z="-207.989" rw="0.838565" rx="0.0" ry="0.544801" rz="0.0" />
<phrase>Have you heard about Darkflame?</phrase> </locations>
<phrase>I've traveled across this entire system, but nothing beats the view here.</phrase> </object>
</phrases> <object name="Neal - Paradox Scout" lot="6738">
<locations> <equipment>9950, 9944, 14102, 14092</equipment>
<location zone="1200" x="163.835" y="330.756" z="-141.933" rw="0.774887" rx="0.0" ry="-0.6321" rz="0.0" /> <phrases>
</locations> <phrase>Hello Explorer! It's great to see you made it!</phrase>
</object> <phrase>Have you heard about Darkflame?</phrase>
<object name="averysumner - Destroyer of Worlds" lot="11235"> <phrase>I've traveled across this entire system, but nothing beats the view here.</phrase>
<equipment></equipment> </phrases>
<phrases> <config>
<phrase>cmerw[acowipaejio;fawjioefasdl;kfjm;</phrase> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<phrase>I, for one, welcome our new robot overlords.</phrase> </config>
<phrase>zxnpoasdfiopwemsadf'kawpfo[ekasdf;'s</phrase> <locations>
<phrase>*teleports behind you*</phrase> <location zone="1200" x="163.835" y="330.756" z="-141.933" rw="0.774887" rx="0.0" ry="-0.6321" rz="0.0" />
</phrases> </locations>
<script name="scripts\02_server\DLU\DLUVanityTeleportingObject.lua" /> </object>
<config> <object name="averysumner - Destroyer of Worlds" lot="11235">
<key data="teleport=7:1" /> <phrases>
<key data="teleportInterval=3:3.0" /> <phrase>cmerw[acowipaejio;fawjioefasdl;kfjm;</phrase>
</config> <phrase>I, for one, welcome our new robot overlords.</phrase>
<locations> <phrase>zxnpoasdfiopwemsadf'kawpfo[ekasdf;'s</phrase>
<location zone="1200" x="-361.583" y="285.541" z="64.4695" rw="0.785518" rx="0.0" ry="0.618838" rz="0.0" /> <phrase>*teleports behind you*</phrase>
<location zone="1200" x="178.188" y="354.528" z="-173.932" rw="0.734375" rx="0.0" ry="-0.678744" rz="0.0" /> </phrases>
<location zone="1200" x="389.093" y="295.119" z="-647.583" rw="0.851229" rx="0.0" ry="-0.524795" rz="0.0" /> <config>
</locations> <key>useLocationsAsRandomSpawnPoint=7:1</key>
</object> <key>teleportInterval=3:15.0</key>
<object name="NinjaOfLU - Resident Physicist" lot="12260"> <key>custom_script_server=0:scripts\02_server\DLU\DLUVanityTeleportingObject.lua</key>
<equipment>4360, 2523, 5659, 10067</equipment> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<phrases> </config>
<phrase>Congratulations! I don't see too many people around here!</phrase> <locations>
<phrase>Got any spring shoes?</phrase> <location zone="1200" x="-361.583" y="285.541" z="64.4695" rw="0.785518" rx="0.0" ry="0.618838" rz="0.0" />
<phrase>I miss the quip!</phrase> <location zone="1200" x="178.188" y="354.528" z="-173.932" rw="0.734375" rx="0.0" ry="-0.678744" rz="0.0" />
<phrase>Want to talk about physics?</phrase> <location zone="1200" x="-318.569" y="287.637695" z="226.728" rw="-0.289502" rx="0.0" ry="0.957178" rz="0.0" />
<phrase>Hang on, this isn't the DLU forums!</phrase> <location zone="1200" x="389.093" y="295.119" z="-647.583" rw="0.851229" rx="0.0" ry="-0.524795" rz="0.0" />
<phrase>What if we're all just Boltzmann brains?</phrase> </locations>
<phrase>Hahaha! The universe? A computer program? How unlikely!</phrase> </object>
<phrase>I have been idle for 10 minutes, and will be returned to the login screen in 5 minutes.</phrase> <object name="NinjaOfLU - Resident Physicist" lot="12260">
<phrase>Of what has one to be proud, if dnot one's friends?</phrase> <equipment>4360, 2523, 5659, 10067</equipment>
</phrases> <phrases>
<locations> <phrase>Congratulations! I don't see too many people around here!</phrase>
<location zone="1100" x="287" y="451" z="-98" rw="-0.320221" rx="0" ry="0.947343" rz="0" /> <phrase>Got any spring shoes?</phrase>
</locations> <phrase>I miss the quip!</phrase>
<locations> <phrase>Want to talk about physics?</phrase>
<location zone="1800" x="798" y="93" z="325" rw="-0.095" rx="0.0" ry="0.995" rz="0.0" /> <phrase>Hang on, this isn't the DLU forums!</phrase>
</locations> <phrase>What if we're all just Boltzmann brains?</phrase>
</object> <phrase>Hahaha! The universe? A computer program? How unlikely!</phrase>
<object name="BlasterBuilder - Race Ace" lot="8205"> <phrase>I have been idle for 10 minutes, and will be returned to the login screen in 5 minutes.</phrase>
<equipment>14098, 8539, 14096, 14092</equipment> <phrase>Of what has one to be proud, if dnot one's friends?</phrase>
<phrases> </phrases>
<phrase>LEGO Universe... LEGO Universe... LEGO Universe... LEGO Universe...</phrase> <config>
<phrase>So, they say the Maelstrom is chaos, but isn't Imagination also chaos?</phrase> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<phrase>The Sentinels have always given me cop vibes...</phrase> </config>
<phrase>Where's Bob, you ask? Yeah, I dunno.</phrase> <locations>
<phrase>Bob's supposed to meet me here. I wonder where he is.</phrase> <location zone="1100" x="287" y="451" z="-98" rw="-0.320221" rx="0" ry="0.947343" rz="0" />
<phrase>Hhhh... Fantastic.</phrase> <location zone="1800" x="798" y="93" z="325" rw="-0.095" rx="0.0" ry="0.995" rz="0.0" />
<phrase>Quicksicles are really nice, except for the 5 seconds of withdrawal.</phrase> </locations>
<phrase>Vroom vroom.</phrase> </object>
<phrase>VROOM VROOM!</phrase> <object name="BlasterBuilder - Race Ace" lot="8205">
<phrase>So I've been thinking: shouldn't every game have mood bars and randomized weather?</phrase> <equipment>14098, 8539, 14096, 14092</equipment>
<phrase>If there are two things I hate more than anything else, it's gender and Maelstrom.</phrase> <phrases>
<phrase>Ah, sunny day. Unless you haven't defeated the Spider Queen yet, in which case, wow, it's raining ash.</phrase> <phrase>LEGO Universe... LEGO Universe... LEGO Universe... LEGO Universe...</phrase>
<phrase>I've been given the power to add to the game's canon: gender is over.</phrase> <phrase>So, they say the Maelstrom is chaos, but isn't Imagination also chaos?</phrase>
<phrase>Wisdom is a circle. What you receive, you must give back.</phrase> <phrase>The Sentinels have always given me cop vibes...</phrase>
<phrase>AAAAAAAAAAAGHHH!</phrase> <phrase>Where's Bob, you ask? Yeah, I dunno.</phrase>
<phrase>I kind of liked the atmosphere better when it was raining ash, but this is fine too I guess.</phrase> <phrase>Bob's supposed to meet me here. I wonder where he is.</phrase>
<phrase>The current temperature in Avant Gardens is 112 degrees Fahrenheit!</phrase> <phrase>Hhhh... Fantastic.</phrase>
<phrase>The current temperature in Avant Gardens is 38 degrees Fahrenheit!</phrase> <phrase>Quicksicles are really nice, except for the 5 seconds of withdrawal.</phrase>
<phrase>Gather uh banana</phrase> <phrase>Vroom vroom.</phrase>
<phrase>I've done nothing all day. Why am I here?</phrase> <phrase>VROOM VROOM!</phrase>
</phrases> <phrase>So I've been thinking: shouldn't every game have mood bars and randomized weather?</phrase>
<locations> <phrase>If there are two things I hate more than anything else, it's gender and Maelstrom.</phrase>
<location zone="1100" x="444.318" y="421.154" z="54.4241" rw="0.877539" rx="0.0" ry="0.479506" rz="0.0" /> <phrase>Ah, sunny day. Unless you haven't defeated the Spider Queen yet, in which case, wow, it's raining ash.</phrase>
</locations> <phrase>I've been given the power to add to the game's canon: gender is over.</phrase>
</object> <phrase>Wisdom is a circle. What you receive, you must give back.</phrase>
<!-- Mick - Brick Market Broker --> <phrase>AAAAAAAAAAAGHHH!</phrase>
<object name="Mick - Brick Market Broker" lot="6876"> <phrase>I kind of liked the atmosphere better when it was raining ash, but this is fine too I guess.</phrase>
<equipment>2519, 4091, 5128, 7990</equipment> <phrase>The current temperature in Avant Gardens is 112 degrees Fahrenheit!</phrase>
<phrases> <phrase>The current temperature in Avant Gardens is 38 degrees Fahrenheit!</phrase>
<phrase>Still can't believe we made it through that 2012 recession.</phrase> <phrase>Gather uh banana</phrase>
<phrase>What's your market on Red Parrots?</phrase> <phrase>I've done nothing all day. Why am I here?</phrase>
<phrase>Heard the news? Prices for brick #14451 are going to the moon!</phrase> </phrases>
<phrase>Heard the news? Prices for brick #13191 are going to the moon!</phrase> <config>
<phrase>Heard the news? Prices for brick #4718 are going to the moon!</phrase> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<phrase>Invest in grey kepis while you still can, they're a steal right now!</phrase> </config>
<phrase>I really need to get rid of these Maelstrom Bricks, how about 80 cents on the dollar?</phrase> <locations>
<phrase>Don't buy at Darby's, the prices might seem good but the fees are outrageous.</phrase> <location zone="1100" x="444.318" y="421.154" z="54.4241" rw="0.877539" rx="0.0" ry="0.479506" rz="0.0" />
<phrase>I know a guy that sells jetpacks, it ain't cheap but everything has a price.</phrase> </locations>
<phrase>You know Dr. Overbuild? He keeps ignoring my calls.</phrase> </object>
</phrases> <object name="Mick - Brick Market Broker" lot="6876">
<locations> <equipment>2519, 4091, 5128, 7990</equipment>
<location zone="1100" x="449.725" y="414.926" z="180.539" rw="0.180645" rx="0.0" ry="0.983548" rz="0.0" /> <phrases>
</locations> <phrase>Still can't believe we made it through that 2012 recession.</phrase>
</object> <phrase>What's your market on Red Parrots?</phrase>
<!-- Knightoffaith - Sage of Wanderlust --> <phrase>Heard the news? Prices for brick #14451 are going to the moon!</phrase>
<object name="Knightoffaith - Sage of Wanderlust" lot="12260"> <phrase>Heard the news? Prices for brick #13191 are going to the moon!</phrase>
<equipment>7359, 7368, 7380, 7392, 7403, 8456</equipment> <phrase>Heard the news? Prices for brick #4718 are going to the moon!</phrase>
<phrases> <phrase>Invest in grey kepis while you still can, they're a steal right now!</phrase>
<phrase>Come and join me - take a look at the beauty that still remains even amidst the chaos</phrase> <phrase>I really need to get rid of these Maelstrom Bricks, how about 80 cents on the dollar?</phrase>
<phrase>If it's a bit scuffed, you're doing it right</phrase> <phrase>Don't buy at Darby's, the prices might seem good but the fees are outrageous.</phrase>
<phrase>Always have things - and people - you care about</phrase> <phrase>I know a guy that sells jetpacks, it ain't cheap but everything has a price.</phrase>
<phrase>Careful, you get me talking and you might not be home in time for dinner!</phrase> <phrase>You know Dr. Overbuild? He keeps ignoring my calls.</phrase>
<phrase>If all else fails, try changing the long to a long long</phrase> </phrases>
<phrase>If you do one thing - let it be to always hold respect for everyone</phrase> <config>
<phrase>Never settle for mediocraty - seek excellence in all things</phrase> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<phrase>You ever heard the one about the octapus, the shark, and the - oh, nevermind</phrase> </config>
<phrase>To imagination! May its spark never be extinguished.</phrase> <locations>
<phrase>Don't look at me, it was Sam's turn to look after Burno!</phrase> <location zone="1100" x="449.725" y="414.926" z="180.539" rw="0.180645" rx="0.0" ry="0.983548" rz="0.0" />
<phrase>The Universe is beautiful - take some time to enjoy it</phrase> </locations>
</phrases> </object>
<locations> <object name="Knightoffaith - Sage of Wanderlust" lot="12260">
<location zone="1100" x="-381.053" y="367.787" z="-60.1185" rw="-0.14307" rx="0" ry="0.989713" rz="0" /> <equipment>7359, 7368, 7380, 7392, 7403, 8456</equipment>
</locations> <phrases>
</object> <phrase>Come and join me - take a look at the beauty that still remains even amidst the chaos</phrase>
<object name="Snifflegully - DLU Alpha Tester" lot="2281"> <phrase>If it's a bit scuffed, you're doing it right</phrase>
<equipment>15975, 7492, 12690, 12472</equipment> <phrase>Always have things - and people - you care about</phrase>
<phrases> <phrase>Careful, you get me talking and you might not be home in time for dinner!</phrase>
<phrase>Praise the cube!</phrase> <phrase>If all else fails, try changing the long to a long long</phrase>
<phrase>Congratulations, you have finished the 'Talk to Snifflegully any%' speedrun!</phrase> <phrase>If you do one thing - let it be to always hold respect for everyone</phrase>
<phrase>Fun fact: you can find R2-D2 bricks sold in Nexus Tower.</phrase> <phrase>Never settle for mediocraty - seek excellence in all things</phrase>
<phrase>Have you found my other friends across the Nimbus System?</phrase> <phrase>You ever heard the one about the octapus, the shark, and the - oh, nevermind</phrase>
<phrase>This game is fun.</phrase> <phrase>To imagination! May its spark never be extinguished.</phrase>
<phrase>Embrace the Sentinel meta!</phrase> <phrase>Don't look at me, it was Sam's turn to look after Burno!</phrase>
<phrase>Hope you enjoy DLU as much as I have, explorer!</phrase> <phrase>The Universe is beautiful - take some time to enjoy it</phrase>
<phrase>There are many more memories still to be made.</phrase> </phrases>
</phrases> <config>
<locations> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<location zone="1200" x="-429.296" y="291.058" z="212.918" rw="0.339487" rx="0" ry="0.940611" rz="0" /> </config>
</locations> <locations>
</object> <location zone="1100" x="-381.053" y="367.787" z="-60.1185" rw="-0.14307" rx="0" ry="0.989713" rz="0" />
<object name="Hollis - Master Builder" lot="9893"> </locations>
<equipment>4465, 2517, 6855, 8532, 9615</equipment> </object>
<phrases> <object name="Snifflegully - DLU Alpha Tester" lot="2281">
<phrase>Visit Starbase 3001 and blast off to the awesome worlds built by the World Builder League!</phrase> <equipment>15975, 7492, 12690, 12472</equipment>
<phrase>I single-handedly built everything you see around you. Well, maybe half of it. Ok, none of it. But I once built a pretty cool house on Nimbus Rock!</phrase> <phrases>
<phrase>I once was told there was an elusive wizard living in the outskirts of Nimbus Station who will give you magical wizard powers if you catch him. I never did find that guy.</phrase> <phrase>Praise the cube!</phrase>
<phrase>I checked the forecast for today, and the gravity on Moonbase will be perfect for jumping around! Which is the same as every day, but still.</phrase> <phrase>Congratulations, you have finished the 'Talk to Snifflegully any%' speedrun!</phrase>
<phrase>There are many amazing properties to explore across the universe. You can visit some of them from the launchpads right here in Brick Annex.</phrase> <phrase>Fun fact: you can find R2-D2 bricks sold in Nexus Tower.</phrase>
<phrase>Don't stop believing! Uhh, I mean building. Don't stop building!</phrase> <phrase>Have you found my other friends across the Nimbus System?</phrase>
</phrases> <phrase>This game is fun.</phrase>
<locations> <phrase>Embrace the Sentinel meta!</phrase>
<location zone="1200" x="-317.509" y="287.652" z="191.86" rw="0.57124" rx="0" ry="-0.820783" rz="0" /> <phrase>Hope you enjoy DLU as much as I have, explorer!</phrase>
</locations> <phrase>There are many more memories still to be made.</phrase>
</object> </phrases>
<object name="Xiphoseer - Database Scout" lot="12260"> <config>
<equipment>2632, 12754, 8645, 8468</equipment> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<phrases> </config>
<phrase>Oh no, not that old list again</phrase> <locations>
<phrase>Have you seen this new thing I added?</phrase> <location zone="1200" x="-429.296" y="291.058" z="212.918" rw="0.339487" rx="0" ry="0.940611" rz="0" />
<phrase>This soundtrack is great!</phrase> </locations>
<phrase>lu:explorer</phrase> </object>
<phrase>I've been to the plains of Avant Gardens!</phrase> <object name="Hollis - Master Builder" lot="9893">
<phrase>It's a hash map, duh</phrase> <equipment>4465, 2517, 6855, 8532, 9615</equipment>
<phrase>Look at that view!</phrase> <phrases>
<phrase>Oxidize!</phrase> <phrase>Visit Starbase 3001 and blast off to the awesome worlds built by the World Builder League!</phrase>
</phrases> <phrase>I single-handedly built everything you see around you. Well, maybe half of it. Ok, none of it. But I once built a pretty cool house on Nimbus Rock!</phrase>
<locations> <phrase>I once was told there was an elusive wizard living in the outskirts of Nimbus Station who will give you magical wizard powers if you catch him. I never did find that guy.</phrase>
<location zone="1300" x="283.986" y="261.208" z="-128.466" rw="0.70207" rx="0" ry="0.712108" rz="0" /> <phrase>I checked the forecast for today, and the gravity on Moonbase will be perfect for jumping around! Which is the same as every day, but still.</phrase>
</locations> <phrase>There are many amazing properties to explore across the universe. You can visit some of them from the launchpads right here in Brick Annex.</phrase>
</object> <phrase>Don't stop believing! Uhh, I mean building. Don't stop building!</phrase>
<object name="Simon - External Archeologist" lot="7128"> </phrases>
<equipment>7363, 7371, 7383, 7395, 7405, 8462</equipment> <config>
<phrases> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<phrase>I want to build a castle, but first I need to build the bricks.</phrase> </config>
<phrase>Why make it easy when you can do it complicated</phrase> <locations>
<phrase>When you do extra steps, you can always customize the steps without redoing the whole staircase</phrase> <location zone="1200" x="-317.509" y="287.652" z="191.86" rw="0.57124" rx="0" ry="-0.820783" rz="0" />
<phrase>Who needs lamps, when you have Tiki Torches</phrase> </locations>
</phrases> </object>
<locations> <object name="Xiphoseer - Database Scout" lot="12260">
<location zone="1300" x="204.93" y="294.784" z="471.537" rw="0.85015" rx="0" ry="-0.52654" rz="0" /> <equipment>2632, 12754, 8645, 8468</equipment>
</locations> <phrases>
</object> <phrase>Oh no, not that old list again</phrase>
<object name="Bricknave - Treasure Hunter" lot="2279"> <phrase>Have you seen this new thing I added?</phrase>
<equipment>7486, 7510, 7462, 8539</equipment> <phrase>This soundtrack is great!</phrase>
<phrases> <phrase>lu:explorer</phrase>
<phrase>During my very first expedition, Stromlings were called Darklings, and they dropped entire treasure chests!</phrase> <phrase>I've been to the plains of Avant Gardens!</phrase>
<phrase>Legend has it that building a mysterious idol was the key to Gnarled Forest survival.</phrase> <phrase>It's a hash map, duh</phrase>
<phrase>I was a member of an Inner Circle during the original Alpha Test expedition.</phrase> <phrase>Look at that view!</phrase>
<phrase>Did Johnny Thunder send you? A pal of Thunder is a pal of mine!</phrase> <phrase>Oxidize!</phrase>
<phrase>Did you know that some guy with green pants, a gray jacket, sunglasses, and a laser whip once impersonated Johnny Thunder?</phrase> </phrases>
<phrase>Every time you build, you discover a piece of yourself.</phrase> <config>
<phrase>There's treasure inside of all of us. It's called Imagination.</phrase> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<phrase>Stromlings! Why did it have to be Stromlings?</phrase> </config>
</phrases> <locations>
<locations> <location zone="1300" x="283.986" y="261.208" z="-128.466" rw="0.70207" rx="0" ry="0.712108" rz="0" />
<location zone="1300" x="-47.6296" y="322.527" z="533.5" rw="0.145135" rx="0" ry="0.989412" rz="0" /> </locations>
</locations> </object>
</object> <object name="Simon - External Archeologist" lot="7128">
<object name="Jamie - Shenanigans Enthusiast" lot="9893"> <equipment>7363, 7371, 7383, 7395, 7405, 8462</equipment>
<equipment>12915, 9683, 10476, 13342, 14166</equipment> <phrases>
<phrases> <phrase>I want to build a castle, but first I need to build the bricks.</phrase>
<phrase>sup lol</phrase> <phrase>Why make it easy when you can do it complicated</phrase>
<phrase>How long have I been standing here?</phrase> <phrase>When you do extra steps, you can always customize the steps without redoing the whole staircase</phrase>
<phrase>Wait, did the game close yet?</phrase> <phrase>Who needs lamps, when you have Tiki Torches</phrase>
<phrase>... What year is it?</phrase> </phrases>
</phrases> <config>
<locations> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<location zone="1400" x="-490.608" y="51.9449" z="-347.747" rw="0.594978" rx="0" ry="-0.803742" rz="0" /> </config>
</locations> <locations>
</object> <location zone="1300" x="204.93" y="294.784" z="471.537" rw="0.85015" rx="0" ry="-0.52654" rz="0" />
<object name="Wicked" lot="7412"> </locations>
<equipment>8287, 2957, 7523, 16613</equipment> </object>
<phrases></phrases> <object name="Bricknave - Treasure Hunter" lot="2279">
<locations> <equipment>7486, 7510, 7462, 8539</equipment>
<location zone="1400" x="264.506" y="339.931" z="54.1201" rw="0.715223" rx="0" ry="0.698896" rz="0" /> <phrases>
</locations> <phrase>During my very first expedition, Stromlings were called Darklings, and they dropped entire treasure chests!</phrase>
</object> <phrase>Legend has it that building a mysterious idol was the key to Gnarled Forest survival.</phrase>
<object name="Krysto - Sentinal Veteran" lot="12260"> <phrase>I was a member of an Inner Circle during the original Alpha Test expedition.</phrase>
<equipment>12651, 12648, 10158, 5694, 16619, 9681, 8286</equipment> <phrase>Did Johnny Thunder send you? A pal of Thunder is a pal of mine!</phrase>
<phrases> <phrase>Did you know that some guy with green pants, a gray jacket, sunglasses, and a laser whip once impersonated Johnny Thunder?</phrase>
<phrase>Need a pick me up? Interact with the consoles here to restore your health and armor!</phrase> <phrase>Every time you build, you discover a piece of yourself.</phrase>
<phrase>Did I ever tell you about that one time I broke the mail?</phrase> <phrase>There's treasure inside of all of us. It's called Imagination.</phrase>
<phrase>Can I interest you in a surprise model pack? No? Ok...</phrase> <phrase>Stromlings! Why did it have to be Stromlings?</phrase>
<phrase>Headed to Forbidden Valley? Watch out for flying Ronin!</phrase> </phrases>
<phrase>If you run into Sensei Wu, tell him he still owes me that red kabuto.</phrase> <config>
<phrase>If you see another me running around, please inform Wisp Lee immediately.</phrase> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<phrase>What do you mean my title is misspelled?</phrase> </config>
<phrase>When I was your age, numbers were illegal.</phrase> <locations>
</phrases> <location zone="1300" x="-47.6296" y="322.527" z="533.5" rw="0.145135" rx="0" ry="0.989412" rz="0" />
<locations> </locations>
<location zone="1900" x="-493.724" y="1124.05" z="-76.6355" rw="0.1719" rx="0" ry="0.985114" rz="0" /> </object>
</locations> <object name="Jamie - Shenanigans Enthusiast" lot="9893">
</object> <equipment>12915, 9683, 10476, 13342, 14166</equipment>
12651 <phrases>
<object name="Matthew - ?????" lot="2279"> <phrase>sup lol</phrase>
<equipment>9856, 7793, 6928, 6927</equipment> <phrase>How long have I been standing here?</phrase>
<phrases> <phrase>Wait, did the game close yet?</phrase>
<phrase>I think I have a migraine from staring at this for so long</phrase> <phrase>... What year is it?</phrase>
<phrase>Anything but Portabello</phrase> </phrases>
</phrases> <config>
<locations> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<location zone="1900" x="-227.621" y="1188.28" z="145.734" rw="-0.254353" rx="0" ry="0.967111" rz="0" /> </config>
</locations> <locations>
</object> <location zone="1400" x="-490.608" y="51.9449" z="-347.747" rw="0.594978" rx="0" ry="-0.803742" rz="0" />
<object name="Raine" lot="9893"> </locations>
<equipment>13342, 7370, 7382</equipment> </object>
<phrases> <object name="Wicked" lot="7412">
<phrase>Per Aspera ad Astra</phrase> <equipment>8287, 2957, 7523, 16613</equipment>
</phrases> <locations>
<locations> <location zone="1400" x="264.506" y="339.931" z="54.1201" rw="0.715223" rx="0" ry="0.698896" rz="0" />
<location zone="1900" x="-190.673" y="1218.34" z="221.6" rw="0.972371" rx="0" ry="-0.233441" rz="0" /> </locations>
</locations> </object>
</object> <object name="Krysto - Sentinal Veteran" lot="12260">
<object name="Brickgirl - Explorer" lot="12260"> <equipment>12651, 12648, 10158, 5694, 16619, 9681, 8286</equipment>
<equipment>12781, 12686, 13000, 12802, 12678, 12095</equipment> <phrases>
<phrases> <phrase>Need a pick me up? Interact with the consoles here to restore your health and armor!</phrase>
<phrase>Imagination will often carry us to worlds that never were, but without it we go nowhere.</phrase> <phrase>Did I ever tell you about that one time I broke the mail?</phrase>
<phrase>I love this view over to Butterscorch. Look at it for a while and admire the changing stars in the sky.</phrase> <phrase>Can I interest you in a surprise model pack? No? Ok...</phrase>
<phrase>Have you tried those buttery croissants from “Farnham Spoon” they are delicious! I might just go and have another</phrase> <phrase>Headed to Forbidden Valley? Watch out for flying Ronin!</phrase>
<phrase>Have fun!</phrase> <phrase>If you run into Sensei Wu, tell him he still owes me that red kabuto.</phrase>
</phrases> <phrase>If you see another me running around, please inform Wisp Lee immediately.</phrase>
<locations> <phrase>What do you mean my title is misspelled?</phrase>
<location zone="1800" x="-39.2259" y="96.8605" z="-550.077" rw="0.815145" rx="0" ry="-0.579257" rz="0" /> <phrase>When I was your age, numbers were illegal.</phrase>
</locations> </phrases>
</object> <config>
<object name="Sam - The Avianite" lot="2281"> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<equipment>12563, 12565, 12567, 12949, 12947, 7570</equipment> </config>
<phrases> <locations>
<phrase>Nice finding me! Now take a moment to take a deep breath, in... And out... NOW GET BACK TO YOUR QUEST!</phrase> <location zone="1900" x="-493.724" y="1124.05" z="-76.6355" rw="0.1719" rx="0" ry="0.985114" rz="0" />
<phrase>Wu once told me, "The path we seek is never a straight line"."</phrase> </locations>
<phrase>Stop! I'm from the future to warn you that there will be snakes, ninja robots! More snakes, ghosts, sky pirates, snakes that make snakes! Bikers, dragon hunters... Wait what do you mean it hasn't happened yet?</phrase> </object>
</phrases> <object name="Matthew - ?????" lot="2279">
<locations> <equipment>9856, 7793, 6928, 6927</equipment>
<location zone="2000" x="-119.269" y="230.372" z="226.63" rw="0.381416" rx="0" ry="0.924404" rz="0" /> <phrases>
</locations> <phrase>I think I have a migraine from staring at this for so long</phrase>
</object> <phrase>Anything but Portabello</phrase>
<object name="lcdr - Dab Specialist" lot="8657"> </phrases>
<equipment>15931, 4298, 2526</equipment> <config>
<phrases> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<phrase>Hello there.</phrase> </config>
<phrase>May the Bodge be with you.</phrase> <locations>
<phrase>The Bodge is what gives a programmer his power. It's an energy field created by all sketchy programs. It surrounds us and penetrates us. It binds the program together.</phrase> <location zone="1900" x="-227.621" y="1188.28" z="145.734" rw="-0.254353" rx="0" ry="0.967111" rz="0" />
<phrase>LEGO Universe truly is the Dark Souls of LEGO games.</phrase> </locations>
<phrase>I'm gonna get DLU to compile on my machine one day, I swear.</phrase> </object>
<phrase>Hold on, I need to reconfigure my input bindings - my foot pedals aren't mapped yet.</phrase> <object name="Raine" lot="9893">
<phrase>If you're having trouble playing, make sure your input piano has at least two octaves available.</phrase> <equipment>13342, 7370, 7382</equipment>
<phrase>Finally, unsigned bool.</phrase> <phrases>
<phrase>If you find a stray PC on the side of the road, give it shelter.</phrase> <phrase>Per Aspera ad Astra</phrase>
<phrase>Place Nate on your Property. Do it now.</phrase> </phrases>
<phrase>Playpen balls are legos.</phrase> <config>
<phrase>Gonk.</phrase> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<phrase>There is a theory which states that if ever anyone discovers exactly what the Universe is for and why it is here, it will instantly disappear and be replaced by something even more bizarre and inexplicable. There is another theory, which states that this has already happened.</phrase> </config>
</phrases> <locations>
<locations> <location zone="1900" x="-190.673" y="1218.34" z="221.6" rw="0.972371" rx="0" ry="-0.233441" rz="0" />
<location zone="1200" x="197.549" y="259.137" z="-587.759" rw="0.873694" rx="0" ry="0.486475" rz="0" /> </locations>
</locations> </object>
</object> <object name="Brickgirl - Explorer" lot="12260">
<object name="zaop - Assembly Scientist" lot="2279"> <equipment>12781, 12686, 13000, 12802, 12678, 12095</equipment>
<equipment>12099, 3010, 10067, 7503</equipment> <phrases>
<phrases> <phrase>Imagination will often carry us to worlds that never were, but without it we go nowhere.</phrase>
<phrase>Hi!</phrase> <phrase>I love this view over to Butterscorch. Look at it for a while and admire the changing stars in the sky.</phrase>
<phrase>If you get in trouble, just go back in time.</phrase> <phrase>Have you tried those buttery croissants from “Farnham Spoon” they are delicious! I might just go and have another</phrase>
<phrase>Hello!</phrase> <phrase>Have fun!</phrase>
<phrase>Particles were not supposed to be looked at!</phrase> </phrases>
<phrase>Direction and magnitude!</phrase> <config>
<phrase>Good to see you here!</phrase> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<phrase>Oh, that's not a bug, it's a surprise feature.</phrase> </config>
<phrase>Hello again, it's been a while!</phrase> <locations>
<phrase>What on earth is a Boltzmann brain?</phrase> <location zone="1800" x="-39.2259" y="96.8605" z="-550.077" rw="0.815145" rx="0" ry="-0.579257" rz="0" />
<phrase>Thanks for stopping by!</phrase> </locations>
<phrase>Where have you been? We've been looking for you since 2012!</phrase> </object>
<phrase>Careful now with that shovel!</phrase> <object name="Sam - The Avianite" lot="2281">
<phrase>Go find my friends scattered across the rest of the Universe!</phrase> <equipment>12563, 12565, 12567, 12949, 12947, 7570</equipment>
<phrase>Excuse me, do you know the way to Frostburgh?</phrase> <phrases>
<phrase>What are those Paradox scientists up to these days?</phrase> <phrase>Nice finding me! Now take a moment to take a deep breath, in... And out... NOW GET BACK TO YOUR QUEST!</phrase>
</phrases> <phrase>Wu once told me, "The path we seek is never a straight line"."</phrase>
<locations> <phrase>Stop! I'm from the future to warn you that there will be snakes, ninja robots! More snakes, ghosts, sky pirates, snakes that make snakes! Bikers, dragon hunters... Wait what do you mean it hasn't happened yet?</phrase>
<location zone="1100" x="436.949" y="415.264" z="151.381" rw="0.528425" rx="0" ry="0.84898" rz="0" /> </phrases>
</locations> <config>
</object> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
<object name="Ben" lot="2279"> </config>
<equipment>8664, 4065, 2587</equipment> <locations>
<phrases></phrases> <location zone="2000" x="-119.269" y="230.372" z="226.63" rw="0.381416" rx="0" ry="0.924404" rz="0" />
<locations> </locations>
<location zone="1200" x="284.538" y="260.627" z="-506.692" rw="0.819721" rx="0" ry="0.572763" rz="0" /> </object>
</locations> <object name="lcdr - Dab Specialist" lot="8657">
</object> <equipment>15931, 4298, 2526</equipment>
<object name="HappyAngryCatfish - Explorer" lot="2279"> <phrases>
<equipment>8613, 13000, 7570</equipment> <phrase>Hello there.</phrase>
<phrases> <phrase>May the Bodge be with you.</phrase>
<phrase>The red parrot can be very difficult to find!</phrase> <phrase>The Bodge is what gives a programmer his power. It's an energy field created by all sketchy programs. It surrounds us and penetrates us. It binds the program together.</phrase>
<phrase>Some say there are elephants in this forest.</phrase> <phrase>LEGO Universe truly is the Dark Souls of LEGO games.</phrase>
<phrase>I think I may be lost...</phrase> <phrase>I'm gonna get DLU to compile on my machine one day, I swear.</phrase>
<phrase>I'm feeling a bit emotionally conflicted right now</phrase> <phrase>Hold on, I need to reconfigure my input bindings - my foot pedals aren't mapped yet.</phrase>
</phrases> <phrase>If you're having trouble playing, make sure your input piano has at least two octaves available.</phrase>
<locations> <phrase>Finally, unsigned bool.</phrase>
<location zone="1300" x="-171.217" y="246.482" z="-147.05" rw="-0.203118" rx="0" ry="0.979154" rz="0" /> <phrase>If you find a stray PC on the side of the road, give it shelter.</phrase>
</locations> <phrase>Place Nate on your Property. Do it now.</phrase>
</object> <phrase>Playpen balls are legos.</phrase>
<phrase>Gonk.</phrase>
<phrase>There is a theory which states that if ever anyone discovers exactly what the Universe is for and why it is here, it will instantly disappear and be replaced by something even more bizarre and inexplicable. There is another theory, which states that this has already happened.</phrase>
</phrases>
<config>
<key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
</config>
<locations>
<location zone="1200" x="197.549" y="259.137" z="-587.759" rw="0.873694" rx="0" ry="0.486475" rz="0" />
</locations>
</object>
<object name="zaop - Assembly Scientist" lot="2279">
<equipment>12099, 3010, 10067, 7503</equipment>
<phrases>
<phrase>Hi!</phrase>
<phrase>If you get in trouble, just go back in time.</phrase>
<phrase>Hello!</phrase>
<phrase>Particles were not supposed to be looked at!</phrase>
<phrase>Direction and magnitude!</phrase>
<phrase>Good to see you here!</phrase>
<phrase>Oh, that's not a bug, it's a surprise feature.</phrase>
<phrase>Hello again, it's been a while!</phrase>
<phrase>What on earth is a Boltzmann brain?</phrase>
<phrase>Thanks for stopping by!</phrase>
<phrase>Where have you been? We've been looking for you since 2012!</phrase>
<phrase>Careful now with that shovel!</phrase>
<phrase>Go find my friends scattered across the rest of the Universe!</phrase>
<phrase>Excuse me, do you know the way to Frostburgh?</phrase>
<phrase>What are those Paradox scientists up to these days?</phrase>
</phrases>
<config>
<key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
</config>
<locations>
<location zone="1100" x="436.949" y="415.264" z="151.381" rw="0.528425" rx="0" ry="0.84898" rz="0" />
</locations>
</object>
<object name="Ben" lot="2279">
<equipment>8664, 4065, 2587</equipment>
<locations>
<location zone="1200" x="284.538" y="260.627" z="-506.692" rw="0.819721" rx="0" ry="0.572763" rz="0" />
</locations>
</object>
<object name="HappyAngryCatfish - Explorer" lot="2279">
<equipment>8613, 13000, 7570</equipment>
<phrases>
<phrase>The red parrot can be very difficult to find!</phrase>
<phrase>Some say there are elephants in this forest.</phrase>
<phrase>I think I may be lost...</phrase>
<phrase>I'm feeling a bit emotionally conflicted right now</phrase>
</phrases>
<config>
<key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
</config>
<locations>
<location zone="1300" x="-171.217" y="246.482" z="-147.05" rw="-0.203118" rx="0" ry="0.979154" rz="0" />
</locations>
</object>
<object name="Max - Developer" lot="9749"> <object name="Max - Developer" lot="9749">
<equipment>4523, 2517, 11909</equipment> <equipment>4523, 2517, 11909</equipment>
<phrases> <phrases>
<phrase>Some people know me as "Darwin"; but that's been a while!</phrase> <phrase>Some people know me as "Darwin"; but that's been a while!</phrase>
<phrase>Per aspera ad astra!</phrase> <phrase>Per aspera ad astra!</phrase>
<phrase>Oh, hi there!</phrase> <phrase>Oh, hi there!</phrase>
<phrase>If you see a certain wizard, say hi to him for me!</phrase> <phrase>If you see a certain wizard, say hi to him for me!</phrase>
<phrase>Persue your goals, I believe in you!</phrase> <phrase>Persue your goals, I believe in you!</phrase>
<phrase>Something to think about: "I like red shirts. Some people don't, but that's okay. It's for me, not them."</phrase> <phrase>Something to think about: "I like red shirts. Some people don't, but that's okay. It's for me, not them."</phrase>
<phrase>Working as intended</phrase> <phrase>Working as intended</phrase>
<phrase>I love cats, little meow meows</phrase> <phrase>I love cats, little meow meows</phrase>
<phrase>It's not perfect, but it works!</phrase> <phrase>It's not perfect, but it works!</phrase>
</phrases> </phrases>
<locations> <config>
<location zone="1201" x="197.709" y="179.335" z="-8.05284" rw="0.544424" rx="0" ry="-0.83881" rz="0" /> <key>custom_script_client=0:scripts\ai\SPEC\MISSION_MINIGAME_CLIENT.lua</key>
</locations> <key>vendorInvOverride=0:11909,7785,12764,12241</key>
</object> </config>
<locations>
<location zone="1201" x="197.709" y="179.335" z="-8.05284" rw="0.544424" rx="0" ry="-0.83881" rz="0" />
</locations>
</object>
</objects> </objects>

View File

@ -1,4 +1,5 @@
<files> <files>
<file name="dev-tribute.xml" enabled="1"/> <file name="dev-tribute.xml" enabled="1"/>
<file name="atm.xml" enabled="0"/> <file name="atm.xml" enabled="0"/>
<file name="demo.xml" enabled="0"/>
</files> </files>