summaryrefslogtreecommitdiff
path: root/src/game-server
diff options
context:
space:
mode:
authorGuillaume Melquiond <guillaume.melquiond@gmail.com>2007-01-02 13:26:47 +0000
committerGuillaume Melquiond <guillaume.melquiond@gmail.com>2007-01-02 13:26:47 +0000
commit0a47b2fb30c83f8b021c2015891fe8c936ca6bf0 (patch)
tree21525442898ca4e41eb8ab51a16cf5384ffef40c /src/game-server
parent5999cff421b0e0b5cd7a0da4d4b0a492f8cc303b (diff)
downloadmanaserv-0a47b2fb30c83f8b021c2015891fe8c936ca6bf0.tar.gz
manaserv-0a47b2fb30c83f8b021c2015891fe8c936ca6bf0.tar.bz2
manaserv-0a47b2fb30c83f8b021c2015891fe8c936ca6bf0.tar.xz
manaserv-0a47b2fb30c83f8b021c2015891fe8c936ca6bf0.zip
Removed obsolete files. Added a generic trigger system.
Diffstat (limited to 'src/game-server')
-rw-r--r--src/game-server/gamehandler.cpp4
-rw-r--r--src/game-server/mapcomposite.cpp74
-rw-r--r--src/game-server/mapcomposite.hpp26
-rw-r--r--src/game-server/mapmanager.cpp2
-rw-r--r--src/game-server/state.cpp173
-rw-r--r--src/game-server/state.hpp17
-rw-r--r--src/game-server/testing.cpp37
-rw-r--r--src/game-server/trigger.cpp55
-rw-r--r--src/game-server/trigger.hpp62
9 files changed, 304 insertions, 146 deletions
diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp
index c8e22350..56b9533c 100644
--- a/src/game-server/gamehandler.cpp
+++ b/src/game-server/gamehandler.cpp
@@ -78,7 +78,7 @@ static void linkCharacter(GameClient *computer, Player *ch)
computer->character = ch;
computer->status = CLIENT_CONNECTED;
ch->setClient(computer);
- gameState->insertObject(ch);
+ gameState->insert(ch);
MessageOut result;
result.writeShort(GPMSG_CONNECT_RESPONSE);
result.writeByte(ERRMSG_OK);
@@ -130,7 +130,7 @@ void GameHandler::computerDisconnected(NetComputer *computer)
}
if (Player *ch = static_cast< GameClient * >(computer)->character)
{
- gameState->removeObject(ch);
+ gameState->remove(ch);
delete ch;
}
delete computer;
diff --git a/src/game-server/mapcomposite.cpp b/src/game-server/mapcomposite.cpp
index b877a775..8b7ef9d7 100644
--- a/src/game-server/mapcomposite.cpp
+++ b/src/game-server/mapcomposite.cpp
@@ -364,6 +364,21 @@ void MapComposite::fillRegion(MapRegion &r, Point const &p, int radius) const
}
}
+void MapComposite::fillRegion(MapRegion &r, Rectangle const &p) const
+{
+ int ax = p.x / zoneDiam,
+ ay = p.y / zoneDiam,
+ bx = std::max((p.x + p.w) / zoneDiam, mapWidth - 1),
+ by = std::max((p.y + p.h) / zoneDiam, mapHeight - 1);
+ for (int y = ay; y <= by; ++y)
+ {
+ for (int x = ax; x <= bx; ++x)
+ {
+ addZone(r, x + y * mapWidth);
+ }
+ }
+}
+
ZoneIterator MapComposite::getAroundObjectIterator(Object *obj, int radius) const
{
MapRegion r;
@@ -371,6 +386,13 @@ ZoneIterator MapComposite::getAroundObjectIterator(Object *obj, int radius) cons
return ZoneIterator(r, this);
}
+ZoneIterator MapComposite::getInsideRectangleIterator(Rectangle const &p) const
+{
+ MapRegion r;
+ fillRegion(r, p);
+ return ZoneIterator(r, this);
+}
+
ZoneIterator MapComposite::getAroundPlayerIterator(Player *obj, int radius) const
{
MapRegion r1;
@@ -396,42 +418,45 @@ ZoneIterator MapComposite::getAroundPlayerIterator(Player *obj, int radius) cons
return ZoneIterator(r2, this);
}
-bool MapComposite::insert(Object *obj)
+bool MapComposite::insert(Thing *ptr)
{
- Point const &pos = obj->getPosition();
- zones[(pos.x / zoneDiam) + (pos.y / zoneDiam) * mapWidth].insert(obj);
-
- int type = obj->getType();
- if (type == OBJECT_MONSTER || type == OBJECT_PLAYER || type == OBJECT_NPC)
+ if (ptr->isVisible())
{
- if (!allocate(static_cast< MovingObject * >(obj)))
+ if (ptr->canMove() && !allocate(static_cast< MovingObject * >(ptr)))
{
return false;
}
+
+ Object *obj = static_cast< Object * >(ptr);
+ Point const &pos = obj->getPosition();
+ zones[(pos.x / zoneDiam) + (pos.y / zoneDiam) * mapWidth].insert(obj);
}
- objects.push_back(obj);
+ things.push_back(ptr);
return true;
}
-void MapComposite::remove(Object *obj)
+void MapComposite::remove(Thing *ptr)
{
- Point const &pos = obj->getPosition();
- zones[(pos.x / zoneDiam) + (pos.y / zoneDiam) * mapWidth].remove(obj);
-
- int type = obj->getType();
- if (type == OBJECT_MONSTER || type == OBJECT_PLAYER || type == OBJECT_NPC)
+ if (ptr->isVisible())
{
- deallocate(static_cast< MovingObject * >(obj));
+ Object *obj = static_cast< Object * >(ptr);
+ Point const &pos = obj->getPosition();
+ zones[(pos.x / zoneDiam) + (pos.y / zoneDiam) * mapWidth].remove(obj);
+
+ if (ptr->canMove())
+ {
+ deallocate(static_cast< MovingObject * >(ptr));
+ }
}
- for (Objects::iterator o = objects.begin(),
- o_end = objects.end(); o != o_end; ++o)
+ for (std::vector< Thing * >::iterator i = things.begin(),
+ i_end = things.end(); i != i_end; ++i)
{
- if (*o == obj)
+ if (*i == ptr)
{
- *o = *(o_end - 1);
- objects.pop_back();
+ *i = *(i_end - 1);
+ things.pop_back();
return;
}
}
@@ -446,15 +471,14 @@ void MapComposite::update()
}
// Cannot use a WholeMap iterator as objects will change zones under its feet.
- for (Objects::iterator o = objects.begin(),
- o_end = objects.end(); o != o_end; ++o)
+ for (std::vector< Thing * >::iterator i = things.begin(),
+ i_end = things.end(); i != i_end; ++i)
{
- int type = (*o)->getType();
- if (type != OBJECT_PLAYER && type != OBJECT_MONSTER && type != OBJECT_NPC)
+ if (!(*i)->canMove())
{
continue;
}
- MovingObject *obj = static_cast< MovingObject * >(*o);
+ MovingObject *obj = static_cast< MovingObject * >(*i);
Point const &pos1 = obj->getOldPosition(),
&pos2 = obj->getPosition();
diff --git a/src/game-server/mapcomposite.hpp b/src/game-server/mapcomposite.hpp
index 84599d39..0623f602 100644
--- a/src/game-server/mapcomposite.hpp
+++ b/src/game-server/mapcomposite.hpp
@@ -152,14 +152,14 @@ class MapComposite {
{ return map; }
/**
- * Inserts an object on the map and sets its public ID.
+ * Inserts an object on the map. Sets its public ID if relevant.
*/
- bool insert(Object *);
+ bool insert(Thing *);
/**
* Removes an object from the map.
*/
- void remove(Object *);
+ void remove(Thing *);
/**
* Updates zones of every moving beings.
@@ -178,6 +178,11 @@ class MapComposite {
{ return ZoneIterator(MapRegion(), this); }
/**
+ * Gets an iterator on the objects inside a given rectangle.
+ */
+ ZoneIterator getInsideRectangleIterator(Rectangle const &) const;
+
+ /**
* Gets an iterator on the objects around a given object.
*/
ZoneIterator getAroundObjectIterator(Object *, int radius) const;
@@ -189,10 +194,10 @@ class MapComposite {
ZoneIterator getAroundPlayerIterator(Player *, int radius) const;
/**
- * Gets all the objects on the map.
+ * Gets everything related to the map.
*/
- Objects const &getObjects() const
- { return objects; }
+ std::vector< Thing * > const &getEverything() const
+ { return things; }
private:
MapComposite(MapComposite const &);
@@ -212,12 +217,17 @@ class MapComposite {
*/
void fillRegion(MapRegion &, Point const &, int) const;
+ /**
+ * Fills a region of zones inside a rectangle.
+ */
+ void fillRegion(MapRegion &, Rectangle const &) const;
+
Map *map; /**< Actual map. */
/**
- * Objects (items, players, monsters, etc) located on the map.
+ * Things (items, players, monsters, etc) located on the map.
*/
- Objects objects;
+ std::vector< Thing * > things;
/**
* Buckets of MovingObjects located on the map, referenced by ID.
diff --git a/src/game-server/mapmanager.cpp b/src/game-server/mapmanager.cpp
index f4bb33bd..1cef6281 100644
--- a/src/game-server/mapmanager.cpp
+++ b/src/game-server/mapmanager.cpp
@@ -91,7 +91,7 @@ MapManager::~MapManager()
Map *MapManager::getMap(int mapId)
{
Maps::iterator i = maps.find(mapId);
- assert(i != maps.end());
+ assert(i != maps.end() && i->second.isActive);
Map *&map = i->second.map;
if (!map)
{
diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp
index f7c12d98..7e78857e 100644
--- a/src/game-server/state.cpp
+++ b/src/game-server/state.cpp
@@ -35,21 +35,6 @@
#include "net/messageout.hpp"
#include "utils/logger.h"
-State::State()
-{
- // Create 10 maggots for testing purposes
- for (int i = 0; i < 10; i++)
- {
- Being *being = new Controlled(OBJECT_MONSTER);
- being->setSpeed(150);
- being->setMapId(1);
- Point pos = { 720, 900 };
- being->setPosition(pos);
- DelayedEvent e = { EVENT_INSERT };
- enqueueEvent(being, e);
- }
-}
-
State::~State()
{
for (Maps::iterator i = maps.begin(), i_end = maps.end(); i != i_end; ++i)
@@ -61,7 +46,9 @@ State::~State()
void State::updateMap(MapComposite *map)
{
// 1. update object status.
- for (ObjectIterator i(map->getWholeMapIterator()); i; ++i)
+ std::vector< Thing * > const &things = map->getEverything();
+ for (std::vector< Thing * >::const_iterator i = things.begin(),
+ i_end = things.end(); i != i_end; ++i)
{
(*i)->update();
}
@@ -82,32 +69,6 @@ void State::updateMap(MapComposite *map)
(*i)->move();
}
map->update();
-
- // 4. Just for fun. Should be replaced by a real trigger system.
- for (MovingObjectIterator i(map->getWholeMapIterator()); i; ++i)
- {
- Object *o = *i;
- if (o->getType() != OBJECT_PLAYER) continue;
- Point pos = o->getPosition();
- int x = pos.x / 32, y = pos.y / 32;
- int m = 0;
- switch (o->getMapId())
- {
- case 1:
- if (x >= 56 && x <= 60 && y == 12)
- { m = 3; x = 44; y = 80; }
- break;
- case 3:
- if (x >= 42 && x <= 46 && y == 88)
- { m = 1; x = 58; y = 17; }
- break;
- }
- if (m != 0)
- {
- DelayedEvent e = { EVENT_WARP, m, x * 32 + 16, y * 32 + 16 };
- enqueueEvent(o, e);
- }
- }
}
void State::informPlayer(MapComposite *map, Player *p)
@@ -125,33 +86,35 @@ void State::informPlayer(MapComposite *map, Player *p)
int otype = o->getType();
int oid = o->getPublicID(), oflags = o->getUpdateFlags();
int flags = 0;
+ bool willBeInRange = ppos.inRangeOf(opos, AROUND_AREA);
- // Send attack messages.
- if ((oflags & ATTACK) && oid != pid && ppos.inRangeOf(opos))
+ if (willBeInRange)
{
- MessageOut AttackMsg(GPMSG_BEING_ATTACK);
- AttackMsg.writeShort(oid);
- gameHandler->sendTo(p, AttackMsg);
- }
+ // Send attack messages.
+ if ((oflags & ATTACK) && oid != pid)
+ {
+ MessageOut AttackMsg(GPMSG_BEING_ATTACK);
+ AttackMsg.writeShort(oid);
+ gameHandler->sendTo(p, AttackMsg);
+ }
- // Send damage messages.
- if (otype == OBJECT_PLAYER || otype == OBJECT_MONSTER)
- {
- Being *victim = static_cast< Being * >(o);
- Hits const &hits = victim->getHitsTaken();
- for (Hits::const_iterator j = hits.begin(),
- j_end = hits.end(); j != j_end; ++j)
+ // Send damage messages.
+ if (o->canFight())
{
- damageMsg.writeShort(oid);
- damageMsg.writeShort(*j);
+ Being *victim = static_cast< Being * >(o);
+ Hits const &hits = victim->getHitsTaken();
+ for (Hits::const_iterator j = hits.begin(),
+ j_end = hits.end(); j != j_end; ++j)
+ {
+ damageMsg.writeShort(oid);
+ damageMsg.writeShort(*j);
+ }
}
}
- /* Check whether this player and this moving object were around
- the last time and whether they will be around the next time. */
- bool wereInRange = pold.inRangeOf(oold) &&
+ // Check if this player and this moving object were around.
+ bool wereInRange = pold.inRangeOf(oold, AROUND_AREA) &&
!((pflags | oflags) & NEW_ON_MAP);
- bool willBeInRange = ppos.inRangeOf(opos);
// Send enter/leaver messages.
if (!wereInRange)
@@ -256,8 +219,7 @@ void State::update()
{
Object *o = *i;
o->clearUpdateFlags();
- int type = o->getType();
- if (type == OBJECT_PLAYER || type == OBJECT_MONSTER)
+ if (o->canFight())
{
static_cast< Being * >(o)->clearHitsTaken();
}
@@ -274,7 +236,7 @@ void State::update()
{
case EVENT_REMOVE:
{
- removeObject(o);
+ remove(o);
if (o->getType() == OBJECT_PLAYER)
{
gameHandler->kill(static_cast< Player * >(o));
@@ -284,18 +246,18 @@ void State::update()
case EVENT_INSERT:
{
- insertObject(o);
+ insert(o);
} break;
case EVENT_WARP:
{
- removeObject(o);
+ remove(o);
o->setMapId(e.map);
Point pos = { e.x, e.y };
o->setPosition(pos);
if (mapManager->isActive(e.map))
{
- insertObject(o);
+ insert(o);
}
else
{
@@ -313,56 +275,57 @@ void State::update()
delayedEvents.clear();
}
-void State::insertObject(Object *objectPtr)
+void State::insert(Thing *ptr)
{
- int mapId = objectPtr->getMapId();
+ int mapId = ptr->getMapId();
MapComposite *map = loadMap(mapId);
- if (!map || !map->insert(objectPtr))
+ if (!map || !map->insert(ptr))
{
- // TODO: Deal with failure to place Object on the map.
+ // TODO: Deal with failure to place Thing on the map.
return;
}
- objectPtr->raiseUpdateFlags(NEW_ON_MAP);
- if (objectPtr->getType() != OBJECT_PLAYER) return;
- Player *playerPtr = static_cast< Player * >(objectPtr);
-
- /* Since the player doesn't know yet where on the world he is after
- * connecting to the map server, we send him an initial change map message.
- */
- MessageOut mapChangeMessage(GPMSG_PLAYER_MAP_CHANGE);
- mapChangeMessage.writeString(mapManager->getMapName(mapId));
- Point pos = playerPtr->getPosition();
- mapChangeMessage.writeShort(pos.x);
- mapChangeMessage.writeShort(pos.y);
- mapChangeMessage.writeByte(0);
- gameHandler->sendTo(playerPtr, mapChangeMessage);
+
+ if (ptr->isVisible())
+ {
+ Object *obj = static_cast< Object * >(ptr);
+ obj->raiseUpdateFlags(NEW_ON_MAP);
+ if (obj->getType() != OBJECT_PLAYER) return;
+
+ /* Since the player doesn't know yet where on the world he is after
+ connecting to the map server, we send him an initial change map message. */
+ MessageOut mapChangeMessage(GPMSG_PLAYER_MAP_CHANGE);
+ mapChangeMessage.writeString(mapManager->getMapName(mapId));
+ Point pos = obj->getPosition();
+ mapChangeMessage.writeShort(pos.x);
+ mapChangeMessage.writeShort(pos.y);
+ gameHandler->sendTo(static_cast< Player * >(obj), mapChangeMessage);
+ }
}
-void State::removeObject(Object *objectPtr)
+void State::remove(Thing *ptr)
{
- int mapId = objectPtr->getMapId();
+ int mapId = ptr->getMapId();
Maps::iterator m = maps.find(mapId);
- if (m == maps.end()) return;
+ assert(m != maps.end());
MapComposite *map = m->second;
- int type = objectPtr->getType();
- if (type == OBJECT_MONSTER || type == OBJECT_PLAYER || type == OBJECT_NPC)
+ if (ptr->canMove())
{
- MovingObject *obj = static_cast< MovingObject * >(objectPtr);
+ MovingObject *obj = static_cast< MovingObject * >(ptr);
MessageOut msg(GPMSG_BEING_LEAVE);
msg.writeShort(obj->getPublicID());
Point objectPos = obj->getPosition();
for (PlayerIterator p(map->getAroundObjectIterator(obj, AROUND_AREA)); p; ++p)
{
- if (*p != obj && objectPos.inRangeOf((*p)->getPosition()))
+ if (*p != obj && objectPos.inRangeOf((*p)->getPosition(), AROUND_AREA))
{
gameHandler->sendTo(*p, msg);
}
}
}
- map->remove(objectPtr);
+ map->remove(ptr);
}
void State::enqueueEvent(Object *ptr, DelayedEvent const &e)
@@ -376,6 +339,13 @@ void State::enqueueEvent(Object *ptr, DelayedEvent const &e)
}
}
+MapComposite *State::getMap(int map)
+{
+ Maps::iterator m = maps.find(map);
+ assert(m != maps.end());
+ return m->second;
+}
+
MapComposite *State::loadMap(int mapId)
{
Maps::iterator m = maps.find(mapId);
@@ -386,30 +356,25 @@ MapComposite *State::loadMap(int mapId)
maps[mapId] = tmp;
// will need to load extra map related resources here also
+ extern void testingMap(int);
+ testingMap(mapId);
return tmp;
}
void State::sayAround(Object *obj, std::string text)
{
- unsigned short id = 65535;
- int type = obj->getType();
- if (type == OBJECT_PLAYER || type == OBJECT_NPC || type == OBJECT_MONSTER)
- {
- id = static_cast< MovingObject * >(obj)->getPublicID();
- }
MessageOut msg(GPMSG_SAY);
- msg.writeShort(id);
+ msg.writeShort(!obj->canMove() ? 65535 :
+ static_cast< MovingObject * >(obj)->getPublicID());
msg.writeString(text);
- Maps::iterator m = maps.find(obj->getMapId());
- if (m == maps.end()) return;
- MapComposite *map = m->second;
+ MapComposite *map = getMap(obj->getMapId());
Point speakerPosition = obj->getPosition();
for (PlayerIterator i(map->getAroundObjectIterator(obj, AROUND_AREA)); i; ++i)
{
- if (speakerPosition.inRangeOf((*i)->getPosition()))
+ if (speakerPosition.inRangeOf((*i)->getPosition(), AROUND_AREA))
{
gameHandler->sendTo(*i, msg);
}
diff --git a/src/game-server/state.hpp b/src/game-server/state.hpp
index d759da88..44c71600 100644
--- a/src/game-server/state.hpp
+++ b/src/game-server/state.hpp
@@ -28,7 +28,9 @@
#include <string>
class MapComposite;
+class Thing;
class Object;
+class Player;
enum
{
@@ -71,8 +73,12 @@ class State
*/
void informPlayer(MapComposite *, Player *);
+ /**
+ * Loads map into game world.
+ */
+ MapComposite *loadMap(int mapId);
+
public:
- State();
~State();
/**
@@ -81,19 +87,18 @@ class State
void update();
/**
- * Loads map into game world.
+ * Gets a composite map.
*/
- MapComposite *loadMap(int mapId);
-
+ MapComposite *getMap(int map);
/**
* Inserts an object on the map.
*/
- void insertObject(Object *);
+ void insert(Thing *);
/**
* Removes an object from the map.
*/
- void removeObject(Object *);
+ void remove(Thing *);
/**
* Enqueues an event. It will be executed at end of update.
diff --git a/src/game-server/testing.cpp b/src/game-server/testing.cpp
new file mode 100644
index 00000000..e580694d
--- /dev/null
+++ b/src/game-server/testing.cpp
@@ -0,0 +1,37 @@
+/* This file is for testing purpose only. It hardcodes some events related
+ to the game. It should be removed once all the related managers have been
+ implemented. There are no headers for this file on purpose. */
+
+#include "controller.h"
+#include "game-server/state.hpp"
+#include "game-server/trigger.hpp"
+
+static Rectangle rectA = { 56 * 32, 12 * 32, 5 * 32, 32 };
+static WarpAction warpA(3, 44 * 32 + 16, 80 * 32 + 16);
+static Rectangle rectB = { 42 * 32, 88 * 32, 5 * 32, 32 };
+static WarpAction warpB(1, 58 * 32 + 16, 17 * 32 + 16);
+
+void testingMap(int id)
+{
+ switch (id)
+ {
+ case 1:
+ {
+ gameState->insert(new TriggerArea(1, rectA, &warpA));
+ for (int i = 0; i < 10; i++)
+ {
+ Being *being = new Controlled(OBJECT_MONSTER);
+ being->setSpeed(150);
+ being->setMapId(1);
+ Point pos = { 720, 900 };
+ being->setPosition(pos);
+ gameState->insert(being);
+ }
+ } break;
+
+ case 3:
+ {
+ gameState->insert(new TriggerArea(3, rectB, &warpB));
+ } break;
+ }
+}
diff --git a/src/game-server/trigger.cpp b/src/game-server/trigger.cpp
new file mode 100644
index 00000000..22a25697
--- /dev/null
+++ b/src/game-server/trigger.cpp
@@ -0,0 +1,55 @@
+/*
+ * The Mana World Server
+ * Copyright 2006 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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 World 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 World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "player.h"
+#include "game-server/mapcomposite.hpp"
+#include "game-server/state.hpp"
+#include "game-server/trigger.hpp"
+
+void WarpAction::process(Object *obj)
+{
+ if (obj->getType() == OBJECT_PLAYER)
+ {
+ DelayedEvent e = { EVENT_WARP, mMap, mX, mY };
+ gameState->enqueueEvent(obj, e);
+ }
+}
+
+TriggerArea::TriggerArea(int map, Rectangle const &r, TriggerAction *ptr)
+ : Thing(OBJECT_OTHER), mZone(r), mAction(ptr)
+{
+ setMapId(map);
+}
+
+void TriggerArea::update()
+{
+ MapComposite *map = gameState->getMap(getMapId());
+
+ for (MovingObjectIterator i(map->getInsideRectangleIterator(mZone)); i; ++i)
+ {
+ if (mZone.contains((*i)->getPosition()))
+ {
+ mAction->process(*i);
+ }
+ }
+}
diff --git a/src/game-server/trigger.hpp b/src/game-server/trigger.hpp
new file mode 100644
index 00000000..a3149812
--- /dev/null
+++ b/src/game-server/trigger.hpp
@@ -0,0 +1,62 @@
+/*
+ * The Mana World Server
+ * Copyright 2006 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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 World 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 World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMWSERV_TRIGGER
+#define _TMWSERV_TRIGGER
+
+#include "object.h"
+
+class TriggerAction
+{
+ public:
+ virtual ~TriggerAction() {}
+ virtual void process(Object *) = 0;
+};
+
+class WarpAction: public TriggerAction
+{
+ public:
+ WarpAction(int m, int x, int y)
+ : mMap(m), mX(x), mY(y) {}
+
+ virtual void process(Object *);
+
+ private:
+ unsigned short mMap, mX, mY;
+};
+
+class TriggerArea: public Thing
+{
+ public:
+ /**
+ * Creates a rectangular trigger for a given map.
+ */
+ TriggerArea(int, Rectangle const &, TriggerAction *);
+ virtual void update();
+
+ private:
+ Rectangle mZone;
+ TriggerAction *mAction;
+};
+
+#endif