diff options
author | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2007-01-02 13:26:47 +0000 |
---|---|---|
committer | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2007-01-02 13:26:47 +0000 |
commit | 0a47b2fb30c83f8b021c2015891fe8c936ca6bf0 (patch) | |
tree | 21525442898ca4e41eb8ab51a16cf5384ffef40c /src/game-server | |
parent | 5999cff421b0e0b5cd7a0da4d4b0a492f8cc303b (diff) | |
download | manaserv-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.cpp | 4 | ||||
-rw-r--r-- | src/game-server/mapcomposite.cpp | 74 | ||||
-rw-r--r-- | src/game-server/mapcomposite.hpp | 26 | ||||
-rw-r--r-- | src/game-server/mapmanager.cpp | 2 | ||||
-rw-r--r-- | src/game-server/state.cpp | 173 | ||||
-rw-r--r-- | src/game-server/state.hpp | 17 | ||||
-rw-r--r-- | src/game-server/testing.cpp | 37 | ||||
-rw-r--r-- | src/game-server/trigger.cpp | 55 | ||||
-rw-r--r-- | src/game-server/trigger.hpp | 62 |
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 |