00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "game-server/spawnarea.hpp"
00023
00024 #include "game-server/mapcomposite.hpp"
00025 #include "game-server/monster.hpp"
00026 #include "game-server/state.hpp"
00027 #include "utils/logger.h"
00028
00029 struct SpawnAreaEventDispatch : EventDispatch
00030 {
00031 SpawnAreaEventDispatch()
00032 {
00033 typedef EventListenerFactory< SpawnArea, &SpawnArea::mSpawnedListener >
00034 Factory;
00035 removed = &Factory::create< Thing, &SpawnArea::decrease >::function;
00036 }
00037 };
00038
00039 static SpawnAreaEventDispatch spawnAreaEventDispatch;
00040
00041 SpawnArea::SpawnArea(MapComposite *map,
00042 MonsterClass *specy,
00043 const Rectangle &zone,
00044 int maxBeings,
00045 int spawnRate):
00046 Thing(OBJECT_OTHER, map),
00047 mSpecy(specy),
00048 mSpawnedListener(&spawnAreaEventDispatch),
00049 mZone(zone),
00050 mMaxBeings(maxBeings),
00051 mSpawnRate(spawnRate),
00052 mNumBeings(0),
00053 mNextSpawn(0)
00054 {
00055 }
00056
00057 void SpawnArea::update()
00058 {
00059 if (mNextSpawn > 0)
00060 mNextSpawn--;
00061
00062 if (mNextSpawn == 0 && mNumBeings < mMaxBeings && mSpawnRate > 0)
00063 {
00064 MapComposite *map = getMap();
00065 const Map *realMap = map->getMap();
00066
00067
00068 if (mZone.w == 0 || mZone.h == 0)
00069 {
00070 mZone.x = 0;
00071 mZone.y = 0;
00072 mZone.w = realMap->getWidth() * realMap->getTileWidth();
00073 mZone.h = realMap->getHeight() * realMap->getTileHeight();
00074 }
00075
00076
00077 int c = 10;
00078 Point position;
00079 const int x = mZone.x;
00080 const int y = mZone.y;
00081 const int width = mZone.w;
00082 const int height = mZone.h;
00083
00084 Being *being = new Monster(mSpecy);
00085
00086 if (being->getModifiedAttribute(BASE_ATTR_HP) <= 0)
00087 {
00088
00089 delete being;
00090 being = 0;
00091 }
00092
00093 if (being) {
00094 do {
00095 position = Point(x + rand() % width, y + rand() % height);
00096 c--;
00097 } while (!realMap->getWalk(position.x / realMap->getTileWidth(),
00098 position.y / realMap->getTileHeight(),
00099 being->getWalkMask()) && c);
00100
00101 if (c) {
00102 being->addListener(&mSpawnedListener);
00103 being->setMap(map);
00104 being->setPosition(position);
00105 being->clearDestination();
00106 GameState::enqueueInsert(being);
00107
00108 mNumBeings++;
00109 }
00110 else {
00111 LOG_WARN("Unable to find a free spawn location for monster "
00112 << mSpecy->getType() << " on map " << map->getName()
00113 << " (" << x << ',' << y << ','
00114 << width << ',' << height << ')');
00115 delete being;
00116 }
00117 }
00118
00119
00120 mNextSpawn = (10 * 60) / mSpawnRate;
00121 }
00122 }
00123
00124 void SpawnArea::decrease(Thing *t)
00125 {
00126 --mNumBeings;
00127 t->removeListener(&mSpawnedListener);
00128 }