diff options
author | Thorbjørn Lindeijer <thorbjorn@lindeijer.nl> | 2013-04-15 22:15:31 +0200 |
---|---|---|
committer | Thorbjørn Lindeijer <thorbjorn@lindeijer.nl> | 2013-04-15 22:15:31 +0200 |
commit | c53bc90dbaa876a86f762a3d864b1f920e2b8071 (patch) | |
tree | 1a8174f4d1745a4799210db970aa2230df622d34 /src/game-server/spawnareacomponent.cpp | |
parent | b89e404f85358f2e3ff87d7731376dbeacdf9778 (diff) | |
parent | 81be8dc99ba7558c8915310eed095df43e3bdbf7 (diff) | |
download | manaserv-c53bc90dbaa876a86f762a3d864b1f920e2b8071.tar.gz manaserv-c53bc90dbaa876a86f762a3d864b1f920e2b8071.tar.bz2 manaserv-c53bc90dbaa876a86f762a3d864b1f920e2b8071.tar.xz manaserv-c53bc90dbaa876a86f762a3d864b1f920e2b8071.zip |
Merge branch 'master' into lpc2012
Conflicts:
src/account-server/accounthandler.cpp
src/game-server/character.cpp
Diffstat (limited to 'src/game-server/spawnareacomponent.cpp')
-rw-r--r-- | src/game-server/spawnareacomponent.cpp | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/game-server/spawnareacomponent.cpp b/src/game-server/spawnareacomponent.cpp new file mode 100644 index 00000000..54cb017f --- /dev/null +++ b/src/game-server/spawnareacomponent.cpp @@ -0,0 +1,124 @@ +/* + * The Mana Server + * Copyright (C) 2006-2010 The Mana World Development Team + * + * This file is part of The Mana Server. + * + * The Mana Server 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 + * any later version. + * + * The Mana Server 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 The Mana Server. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "game-server/spawnareacomponent.h" + +#include "game-server/mapcomposite.h" +#include "game-server/monster.h" +#include "game-server/state.h" +#include "utils/logger.h" + +SpawnAreaComponent::SpawnAreaComponent(MonsterClass *specy, + const Rectangle &zone, + int maxBeings, + int spawnRate): + mSpecy(specy), + mZone(zone), + mMaxBeings(maxBeings), + mSpawnRate(spawnRate), + mNumBeings(0), + mNextSpawn(0) +{ +} + +void SpawnAreaComponent::update(Entity &entity) +{ + if (mNextSpawn > 0) + mNextSpawn--; + + if (mNextSpawn == 0 && mNumBeings < mMaxBeings && mSpawnRate > 0) + { + MapComposite *map = entity.getMap(); + const Map *realMap = map->getMap(); + + // Reset the spawn area to the whole map in case of dimensionless zone + if (mZone.w == 0 || mZone.h == 0) + { + mZone.x = 0; + mZone.y = 0; + mZone.w = realMap->getWidth() * realMap->getTileWidth(); + mZone.h = realMap->getHeight() * realMap->getTileHeight(); + } + + // Find a free spawn location. Give up after 10 tries + int triesLeft = 10; + Point position; + const int x = mZone.x; + const int y = mZone.y; + const int width = mZone.w; + const int height = mZone.h; + + Entity *being = new Entity(OBJECT_MONSTER); + auto *actorComponent = new ActorComponent(*being); + being->addComponent(actorComponent); + auto *beingComponent = new BeingComponent(*being); + being->addComponent(beingComponent); + being->addComponent(new MonsterComponent(*being, mSpecy)); + + if (beingComponent->getModifiedAttribute(ATTR_MAX_HP) <= 0) + { + LOG_WARN("Refusing to spawn dead monster " << mSpecy->getId()); + delete being; + being = 0; + } + + if (being) + { + do + { + position = Point(x + rand() % width, y + rand() % height); + triesLeft--; + } + while (!realMap->getWalk(position.x / realMap->getTileWidth(), + position.y / realMap->getTileHeight(), + actorComponent->getWalkMask()) + && triesLeft); + + if (triesLeft) + { + being->signal_removed.connect( + sigc::mem_fun(this, &SpawnAreaComponent::decrease)); + + being->setMap(map); + actorComponent->setPosition(*being, position); + beingComponent->clearDestination(*being); + GameState::enqueueInsert(being); + + mNumBeings++; + } + else + { + LOG_WARN("Unable to find a free spawn location for monster " + << mSpecy->getId() << " on map " << map->getName() + << " (" << x << ',' << y << ',' + << width << ',' << height << ')'); + delete being; + } + } + + // Predictable respawn intervals (can be randomized later) + mNextSpawn = (10 * 60) / mSpawnRate; + } +} + +void SpawnAreaComponent::decrease(Entity *) +{ + --mNumBeings; +} |