diff --git a/src/otclient/creatures.cpp b/src/otclient/creatures.cpp index c9f8476c..9fde671d 100644 --- a/src/otclient/creatures.cpp +++ b/src/otclient/creatures.cpp @@ -30,6 +30,17 @@ CreatureManager g_creatures; +static bool isInZone(const Position& pos/* placePos*/, + const Position& centerPos, + int radius) +{ + if(radius == -1) + return true; + return ((pos.x >= centerPos.x - radius) && (pos.x <= centerPos.x + radius) && + (pos.y >= centerPos.y - radius) && (pos.y <= centerPos.y + radius) + ); +} + void Spawn::load(TiXmlElement* node) { Position centerPos = node->readPos("center"); @@ -58,7 +69,7 @@ void Spawn::load(TiXmlElement* node) centerPos.x += cNode->readType("x"); centerPos.y += cNode->readType("y"); centerPos.z = cNode->readType("z"); - __addCreature(centerPos, cType); + addCreature(centerPos, cType); } } @@ -74,6 +85,7 @@ void Spawn::save(TiXmlElement*& node) node->SetAttribute("radius", getRadius()); TiXmlElement* creatureNode = nullptr; + for(const auto& pair : m_creatures) { if(!(creatureNode = new TiXmlElement("monster"))) stdext::throw_exception("oom?"); @@ -99,33 +111,23 @@ void Spawn::addCreature(const Position& placePos, const CreatureTypePtr& cType) { const Position& centerPos = getCenterPos(); int m_radius = getRadius(); - if(m_radius != -1 && placePos.x < centerPos.x - m_radius && - placePos.x > centerPos.x + m_radius && placePos.y < centerPos.y - m_radius && - placePos.y > centerPos.y + m_radius) - stdext::throw_exception(stdext::format("cannot place creature, out of range %s %s %d - increment radius.", - stdext::to_string(placePos), stdext::to_string(centerPos), m_radius)); - - return __addCreature(placePos, cType); -} - -void Spawn::__addCreature(const Position& centerPos, const CreatureTypePtr& cType) -{ - g_map.addThing(cType->cast(), centerPos, 4); - m_creatures.insert(std::make_pair(centerPos, cType)); + if(!isInZone(placePos, centerPos, m_radius)) + stdext::throw_exception(stdext::format("cannot place creature at %s %s %d (increment radius)", + stdext::to_string(placePos), stdext::to_string(centerPos), + m_radius + )); + g_map.addThing(cType->cast(), placePos, 4); + m_creatures.insert(std::make_pair(placePos, cType)); } void Spawn::removeCreature(const Position& pos) { auto iterator = m_creatures.find(pos); - if(iterator != m_creatures.end()) - __removeCreature(iterator); -} - -void Spawn::__removeCreature(std::unordered_map::iterator iter) -{ - assert(iter->first.isValid()); - assert(g_map.removeThingByPos(iter->first, 4)); - m_creatures.erase(iter); + if(iterator != m_creatures.end()) { + assert(iterator->first.isValid()); + assert(g_map.removeThingByPos(iterator->first, 4)); + m_creatures.erase(iterator); + } } CreaturePtr CreatureType::cast() @@ -148,8 +150,8 @@ CreatureManager::CreatureManager() void CreatureManager::clearSpawns() { - for(auto it : m_spawns) - it->clear(); + for(auto pair : m_spawns) + pair.second->clear(); m_spawns.clear(); } @@ -226,7 +228,7 @@ void CreatureManager::loadSpawns(const std::string& fileName) SpawnPtr spawn(new Spawn); spawn->load(node); - m_spawns.push_back(spawn); + m_spawns.insert(std::make_pair(spawn->getCenterPos(), spawn)); } doc.Clear(); m_spawnLoaded = true; @@ -243,9 +245,9 @@ void CreatureManager::saveSpawns(const std::string& fileName) TiXmlElement* root = new TiXmlElement("spawns"); doc.LinkEndChild(root); - for(auto spawn : m_spawns) { + for(auto pair : m_spawns) { TiXmlElement* elem; - spawn->save(elem); + pair.second->save(elem); root->LinkEndChild(elem); } @@ -326,7 +328,7 @@ const CreatureTypePtr& CreatureManager::getCreatureByLook(int look) auto findFun = [=] (const CreatureTypePtr& c) -> bool { const Outfit& o = c->getOutfit(); - return o.getId() == look; + return o.getId() == look || o.getAuxId() == look; }; auto it = std::find_if(m_creatures.begin(), m_creatures.end(), findFun); if(it != m_creatures.end()) @@ -337,17 +339,25 @@ const CreatureTypePtr& CreatureManager::getCreatureByLook(int look) SpawnPtr CreatureManager::getSpawn(const Position& centerPos) { - // TODO instead of a list, a map could do better... - auto findFun = [=] (const SpawnPtr& sp) -> bool - { - const Position& center = sp->getCenterPos(); - return center == centerPos; - }; - auto it = std::find_if(m_spawns.begin(), m_spawns.end(), findFun); + auto it = m_spawns.find(centerPos); if(it != m_spawns.end()) - return *it; - // Let it be debug so in release versions it shouldn't annoy the user + return it->second; g_logger.debug(stdext::format("failed to find spawn at center %s",stdext::to_string(centerPos))); return nullptr; } +SpawnPtr CreatureManager::addSpawn(const Position& centerPos, int radius) +{ + auto iter = m_spawns.find(centerPos); + if(iter != m_spawns.end()) + return iter->second; + + SpawnPtr ret(new Spawn); + + ret->setRadius(radius); + ret->setCenterPos(centerPos); + + m_spawns.insert(std::make_pair(centerPos, ret)); + return ret; +} + diff --git a/src/otclient/creatures.h b/src/otclient/creatures.h index 56fa5ede..3876e38d 100644 --- a/src/otclient/creatures.h +++ b/src/otclient/creatures.h @@ -46,7 +46,7 @@ enum SpawnAttr : uint8 class Spawn : public LuaObject { public: - Spawn() { } + Spawn() = default; Spawn(int32 radius) { setRadius(radius); } void setRadius(int32 r) { m_attribs.set(SpawnAttrRadius, r) ;} @@ -62,8 +62,6 @@ public: protected: void load(TiXmlElement* node); void save(TiXmlElement*& node); - void __addCreature(const Position& centerPos, const CreatureTypePtr& cType); - void __removeCreature(std::unordered_map::iterator iter); private: stdext::dynamic_storage m_attribs; @@ -74,7 +72,7 @@ private: class CreatureType : public LuaObject { public: - CreatureType() { } + CreatureType() = default; CreatureType(const std::string& name) { setName(name); } void setSpawnTime(int32 spawnTime) { m_attribs.set(CreatureAttrSpawnTime, spawnTime); } @@ -111,20 +109,21 @@ public: const CreatureTypePtr& getCreatureByName(std::string name); const CreatureTypePtr& getCreatureByLook(int look); + SpawnPtr getSpawn(const Position& centerPos); + SpawnPtr addSpawn(const Position& centerPos, int radius); bool isLoaded() { return m_loaded; } bool isSpawnLoaded() { return m_spawnLoaded; } const std::vector& getCreatures() { return m_creatures; } - const std::vector& getSpawns() { return m_spawns; } protected: void m_loadCreatureBuffer(TiXmlElement* elem, const CreatureTypePtr& m); private: std::vector m_creatures; - std::vector m_spawns; + std::unordered_map m_spawns; stdext::boolean m_loaded, m_spawnLoaded; CreatureTypePtr m_nullCreature; }; diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index cd295b2f..1aa64fdd 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -114,10 +114,10 @@ void OTClient::registerLuaFunctions() g_lua.registerSingletonClass("g_creatures"); g_lua.bindSingletonFunction("g_creatures", "getCreatures", &CreatureManager::getCreatures, &g_creatures); - g_lua.bindSingletonFunction("g_creatures", "getSpawns", &CreatureManager::getSpawns, &g_creatures); g_lua.bindSingletonFunction("g_creatures", "getCreatureByName", &CreatureManager::getCreatureByName, &g_creatures); g_lua.bindSingletonFunction("g_creatures", "getCreatureByLook", &CreatureManager::getCreatureByLook, &g_creatures); - g_lua.bindSingletonFunction("g_creatures", "getSpawn", &CreatureManager::getSpawns, &g_creatures); + g_lua.bindSingletonFunction("g_creatures", "getSpawn", &CreatureManager::getSpawn, &g_creatures); + g_lua.bindSingletonFunction("g_creatures", "addSpawn", &CreatureManager::addSpawn, &g_creatures); g_lua.bindSingletonFunction("g_creatures", "loadMonsters", &CreatureManager::loadMonsters, &g_creatures); g_lua.bindSingletonFunction("g_creatures", "loadNpcs", &CreatureManager::loadNpcs, &g_creatures); g_lua.bindSingletonFunction("g_creatures", "loadSingleCreature", &CreatureManager::loadSingleCreature, &g_creatures);