Postado Abril 11, 2023 2 anos @myllenaszDiz que é a versão 11, digamos que seja TFS 1.3 ou 1.4. Essas versões devem trazer o flag blockable ou ignorespawnblock, da mesma forma verifique a ver. https://github.com/otland/forgottenserver/pull/3601/files
Postado Julho 3, 2023 1 ano Em 01/04/2023 em 22:50, myllenasz disse: static bool findPlayer(const Position& pos); bool spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup = false); void checkSpawn(); void scheduleSpawn(uint32_t spawnId, spawnBlock_t& sb, uint16_t interval); Provavelmente essa linha é responsável por fazer os monstros nascerem na tela do jogador. Eu coloquei como 'false' e os monstros nasceram na tela que eu queria. Então, talvez deva ser colocado como 'true' para que os monstros não nasçam na tela. Não tenho certeza se vai funcionar
Postado Julho 5, 2023 1 ano Diretor Em 01/04/2023 em 22:50, myllenasz disse: Boa noite tudo bem? estou querendo colocar block spawn em uma versão 11.00 quero que os monstros não nasce com player na tela SPAWN.CPP /** * @file spawn.cpp * * The Forgotten Server - a free and open-source MMORPG server emulator * Copyright (C) 2019 Mark Samman <mark.samman@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "otpch.h" #include "spawn.h" #include "game.h" #include "monster.h" #include "configmanager.h" #include "scheduler.h" #include "events.h" #include "pugicast.h" extern Events* g_events; extern ConfigManager g_config; extern Monsters g_monsters; extern Game g_game; extern Events* g_events; static constexpr int32_t MINSPAWN_INTERVAL = 1000; bool Spawns::loadFromXml(const std::string& fromFilename) { if (loaded) { return true; } pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(fromFilename.c_str()); if (!result) { printXMLError("Error - Spawns::loadFromXml", fromFilename, result); return false; } this->filename = fromFilename; loaded = true; for (auto spawnNode : doc.child("spawns").children()) { Position centerPos( pugi::cast<uint16_t>(spawnNode.attribute("centerx").value()), pugi::cast<uint16_t>(spawnNode.attribute("centery").value()), pugi::cast<uint16_t>(spawnNode.attribute("centerz").value()) ); int32_t radius; pugi::xml_attribute radiusAttribute = spawnNode.attribute("radius"); if (radiusAttribute) { radius = pugi::cast<int32_t>(radiusAttribute.value()); } else { radius = -1; } spawnList.emplace_front(centerPos, radius); Spawn& spawn = spawnList.front(); for (auto childNode : spawnNode.children()) { if (strcasecmp(childNode.name(), "monster") == 0) { pugi::xml_attribute nameAttribute = childNode.attribute("name"); if (!nameAttribute) { continue; } Direction dir; pugi::xml_attribute directionAttribute = childNode.attribute("direction"); if (directionAttribute) { dir = static_cast<Direction>(pugi::cast<uint16_t>(directionAttribute.value())); } else { dir = DIRECTION_NORTH; } Position pos( centerPos.x + pugi::cast<uint16_t>(childNode.attribute("x").value()), centerPos.y + pugi::cast<uint16_t>(childNode.attribute("y").value()), centerPos.z ); uint32_t interval = pugi::cast<uint32_t>(childNode.attribute("spawntime").value()) * 1000; if (interval > MINSPAWN_INTERVAL) { spawn.addMonster(nameAttribute.as_string(), pos, dir, interval); } else { std::cout << "[Warning - Spawns::loadFromXml] " << nameAttribute.as_string() << ' ' << pos << " spawntime can not be less than " << MINSPAWN_INTERVAL / 1000 << " seconds." << std::endl; } } else if (strcasecmp(childNode.name(), "npc") == 0) { pugi::xml_attribute nameAttribute = childNode.attribute("name"); if (!nameAttribute) { continue; } Npc* npc = Npc::createNpc(nameAttribute.as_string()); if (!npc) { continue; } pugi::xml_attribute directionAttribute = childNode.attribute("direction"); if (directionAttribute) { npc->setDirection(static_cast<Direction>(pugi::cast<uint16_t>(directionAttribute.value()))); } npc->setMasterPos(Position( centerPos.x + pugi::cast<uint16_t>(childNode.attribute("x").value()), centerPos.y + pugi::cast<uint16_t>(childNode.attribute("y").value()), centerPos.z ), radius); npcList.push_front(npc); } } } return true; } void Spawns::startup() { if (!loaded || isStarted()) { return; } for (Npc* npc : npcList) { g_game.placeCreature(npc, npc->getMasterPos(), false, true); } npcList.clear(); for (Spawn& spawn : spawnList) { spawn.startup(); } started = true; } void Spawns::clear() { for (Spawn& spawn : spawnList) { spawn.stopEvent(); } spawnList.clear(); loaded = false; started = false; filename.clear(); } bool Spawns::isInZone(const Position& centerPos, int32_t radius, const Position& pos) { if (radius == -1) { return true; } return ((pos.getX() >= centerPos.getX() - radius) && (pos.getX() <= centerPos.getX() + radius) && (pos.getY() >= centerPos.getY() - radius) && (pos.getY() <= centerPos.getY() + radius)); } void Spawn::startSpawnCheck() { if (checkSpawnEvent == 0) { checkSpawnEvent = g_scheduler.addEvent(createSchedulerTask(getInterval(), std::bind(&Spawn::checkSpawn, this))); } } Spawn::~Spawn() { for (const auto& it : spawnedMap) { Monster* monster = it.second; monster->setSpawn(nullptr); monster->decrementReferenceCounter(); } } bool Spawn::findPlayer(const Position& pos) { SpectatorHashSet spectators; g_game.map.getSpectators(spectators, pos, false, true); for (Creature* spectator : spectators) { if (!spectator->getPlayer()->hasFlag(PlayerFlag_IgnoredByMonsters)) { return true; } } return false; } bool Spawn::isInSpawnZone(const Position& pos) { return Spawns::isInZone(centerPos, radius, pos); } bool Spawn::spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup /*= false*/) { std::unique_ptr<Monster> monster_ptr(new Monster(mType)); if (startup) { //No need to send out events to the surrounding since there is no one out there to listen! if (!g_game.internalPlaceCreature(monster_ptr.get(), pos, true)) { return false; } } else { if (!g_game.placeCreature(monster_ptr.get(), pos, false, true)) { return false; } } Monster* monster = monster_ptr.release(); monster->setDirection(dir); monster->setSpawn(this); monster->setMasterPos(pos); monster->incrementReferenceCounter(); spawnedMap.insert(spawned_pair(spawnId, monster)); spawnMap[spawnId].lastSpawn = OTSYS_TIME(); g_events->eventMonsterOnSpawn(monster, pos); return true; } void Spawn::startup() { for (const auto& it : spawnMap) { uint32_t spawnId = it.first; const spawnBlock_t& sb = it.second; spawnMonster(spawnId, sb.mType, sb.pos, sb.direction, true); } } void Spawn::checkSpawn() { checkSpawnEvent = 0; cleanup(); uint32_t spawnCount = 0; for (auto& it : spawnMap) { uint32_t spawnId = it.first; if (spawnedMap.find(spawnId) != spawnedMap.end()) { continue; } spawnBlock_t& sb = it.second; if (!sb.mType->canSpawn(sb.pos)) { sb.lastSpawn = OTSYS_TIME(); continue; } if (OTSYS_TIME() >= sb.lastSpawn + sb.interval) { if (sb.mType->info.isBlockable && findPlayer(sb.pos)) { sb.lastSpawn = OTSYS_TIME(); continue; } if (sb.mType->info.isBlockable) { spawnMonster(spawnId, sb.mType, sb.pos, sb.direction); } else { scheduleSpawn(spawnId, sb, 3 * NONBLOCKABLE_SPAWN_INTERVAL); } if (++spawnCount >= static_cast<uint32_t>(g_config.getNumber(ConfigManager::RATE_SPAWN))) { break; } } } if (spawnedMap.size() < spawnMap.size()) { checkSpawnEvent = g_scheduler.addEvent(createSchedulerTask(getInterval(), std::bind(&Spawn::checkSpawn, this))); } } void Spawn::scheduleSpawn(uint32_t spawnId, spawnBlock_t& sb, uint16_t interval) { if (interval <= 0) { spawnMonster(spawnId, sb.mType, sb.pos, sb.direction); } else { g_game.addMagicEffect(sb.pos, CONST_ME_TELEPORT); g_scheduler.addEvent(createSchedulerTask(1400, std::bind(&Spawn::scheduleSpawn, this, spawnId, sb, interval - NONBLOCKABLE_SPAWN_INTERVAL))); } } void Spawn::cleanup() { auto it = spawnedMap.begin(); while (it != spawnedMap.end()) { uint32_t spawnId = it->first; Monster* monster = it->second; if (monster->isRemoved()) { if (spawnId != 0) { spawnMap[spawnId].lastSpawn = OTSYS_TIME(); } monster->decrementReferenceCounter(); it = spawnedMap.erase(it); } else if (!isInSpawnZone(monster->getPosition()) && spawnId != 0) { spawnedMap.insert(spawned_pair(0, monster)); it = spawnedMap.erase(it); } else { ++it; } } } bool Spawn::addMonster(const std::string& name, const Position& pos, Direction dir, uint32_t scheduleInterval) { MonsterType* mType = g_monsters.getMonsterType(name); if (!mType) { std::cout << "[Spawn::addMonster] Can not find " << name << std::endl; return false; } this->interval = std::min(this->interval, scheduleInterval); spawnBlock_t sb; sb.mType = mType; sb.pos = pos; sb.direction = dir; sb.interval = scheduleInterval; sb.lastSpawn = 0; uint32_t spawnId = spawnMap.size() + 1; spawnMap[spawnId] = sb; return true; } void Spawn::removeMonster(Monster* monster) { for (auto it = spawnedMap.begin(), end = spawnedMap.end(); it != end; ++it) { if (it->second == monster) { monster->decrementReferenceCounter(); spawnedMap.erase(it); break; } } } void Spawn::stopEvent() { if (checkSpawnEvent != 0) { g_scheduler.stopEvent(checkSpawnEvent); checkSpawnEvent = 0; } } SPAWN.H /** * @file spawn.h * * The Forgotten Server - a free and open-source MMORPG server emulator * Copyright (C) 2019 Mark Samman <mark.samman@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef OT_SRC_SPAWN_H_ #define OT_SRC_SPAWN_H_ #include "tile.h" #include "position.h" class Monster; class MonsterType; class Npc; struct spawnBlock_t { Position pos; MonsterType* mType; int64_t lastSpawn; uint32_t interval; Direction direction; }; class Spawn { public: Spawn(Position initPos, int32_t initRadius) : centerPos(std::move(initPos)), radius(initRadius) {} ~Spawn(); // non-copyable Spawn(const Spawn&) = delete; Spawn& operator=(const Spawn&) = delete; bool addMonster(const std::string& name, const Position& pos, Direction dir, uint32_t interval); void removeMonster(Monster* monster); uint32_t getInterval() const { return interval; } void startup(); void startSpawnCheck(); void stopEvent(); bool isInSpawnZone(const Position& pos); void cleanup(); private: //map of the spawned creatures using SpawnedMap = std::multimap<uint32_t, Monster*>; using spawned_pair = SpawnedMap::value_type; SpawnedMap spawnedMap; //map of creatures in the spawn std::map<uint32_t, spawnBlock_t> spawnMap; Position centerPos; int32_t radius; uint32_t interval = 60000; uint32_t checkSpawnEvent = 0; static bool findPlayer(const Position& pos); bool spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup = false); void checkSpawn(); void scheduleSpawn(uint32_t spawnId, spawnBlock_t& sb, uint16_t interval); }; class Spawns { public: static bool isInZone(const Position& centerPos, int32_t radius, const Position& pos); bool loadFromXml(const std::string& filename); void startup(); void clear(); bool isStarted() const { return started; } std::forward_list<Spawn>& getSpawnList() { return spawnList; } private: std::forward_list<Npc*> npcList; std::forward_list<Spawn> spawnList; std::string filename; bool loaded = false; bool started = false; }; static constexpr int32_t NONBLOCKABLE_SPAWN_INTERVAL = 1400; #endif por favor alguem consegue me ajudar? Troque e adicione oque não tem em Spawn.cpp bool Spawn::findPlayer(const Position& pos) { SpectatorHashSet spectators; g_game.map.getSpectators(spectators, pos, false, true); for (Creature* spectator : spectators) { if (!spectator->getPlayer()->hasFlag(PlayerFlag_IgnoredByMonsters)) { return true; } } return false; } void Spawn::checkSpawn() { checkSpawnEvent = 0; cleanup(); uint32_t spawnCount = 0; for (auto& it : spawnMap) { uint32_t spawnId = it.first; if (spawnedMap.find(spawnId) != spawnedMap.end()) { continue; } spawnBlock_t& sb = it.second; if (!sb.mType->canSpawn(sb.pos)) { sb.lastSpawn = OTSYS_TIME(); continue; } if (OTSYS_TIME() >= sb.lastSpawn + sb.interval) { if (sb.mType->info.isBlockable && findPlayer(sb.pos)) { sb.lastSpawn = OTSYS_TIME(); continue; } if (sb.mType->info.isBlockable) { spawnMonster(spawnId, sb.mType, sb.pos, sb.direction); } else { scheduleSpawn(spawnId, sb, 3 * NONBLOCKABLE_SPAWN_INTERVAL); } if (++spawnCount >= static_cast<uint32_t>(g_config.getNumber(ConfigManager::RATE_SPAWN))) { break; } } } if (spawnedMap.size() < spawnMap.size()) { checkSpawnEvent = g_scheduler.addEvent(createSchedulerTask(getInterval(), std::bind(&Spawn::checkSpawn, this))); } } Eu sou um entusiasta da programação apaixonado por ajudar a comunidade open source a crescer. Sempre em busca de novos desafios e oportunidades para contribuir com meu código. #OpenSource #Programação #Contribuição
Participe da conversa
Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.