From 8ebd7ef2c200009e6d22b2cfaa3dd0d849155db6 Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Sat, 17 Mar 2012 21:11:41 +0100 Subject: Changed SpawnArea and TriggerArea to components of Entity Well, first visible change is that everything just gets longer to read. Reviewed-by: Yohann Ferreira --- src/game-server/character.h | 1 + src/game-server/component.h | 49 +++++++++++++ src/game-server/entity.cpp | 22 ++++++ src/game-server/entity.h | 51 ++++++++++--- src/game-server/mapcomposite.cpp | 22 ++++-- src/game-server/monster.h | 3 +- src/game-server/spawnarea.cpp | 120 ------------------------------ src/game-server/spawnarea.h | 58 --------------- src/game-server/spawnareacomponent.cpp | 121 +++++++++++++++++++++++++++++++ src/game-server/spawnareacomponent.h | 62 ++++++++++++++++ src/game-server/trigger.cpp | 83 --------------------- src/game-server/trigger.h | 81 --------------------- src/game-server/triggerareacomponent.cpp | 88 ++++++++++++++++++++++ src/game-server/triggerareacomponent.h | 91 +++++++++++++++++++++++ 14 files changed, 492 insertions(+), 360 deletions(-) create mode 100644 src/game-server/component.h delete mode 100644 src/game-server/spawnarea.cpp delete mode 100644 src/game-server/spawnarea.h create mode 100644 src/game-server/spawnareacomponent.cpp create mode 100644 src/game-server/spawnareacomponent.h delete mode 100644 src/game-server/trigger.cpp delete mode 100644 src/game-server/trigger.h create mode 100644 src/game-server/triggerareacomponent.cpp create mode 100644 src/game-server/triggerareacomponent.h (limited to 'src/game-server') diff --git a/src/game-server/character.h b/src/game-server/character.h index 9c9a5459..2b755bdb 100644 --- a/src/game-server/character.h +++ b/src/game-server/character.h @@ -33,6 +33,7 @@ #include "utils/logger.h" #include +#include #include #include diff --git a/src/game-server/component.h b/src/game-server/component.h new file mode 100644 index 00000000..a0f85d2a --- /dev/null +++ b/src/game-server/component.h @@ -0,0 +1,49 @@ +/* + * The Mana Server + * Copyright (C) 2012 The Mana Developers + * + * 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 . + */ + +#ifndef COMPONENT_H +#define COMPONENT_H + +class Entity; + +enum ComponentType +{ + TriggerArea, + SpawnArea, + + ComponentTypeCount +}; + +/** + * A component of an entity. + */ +class Component +{ + public: + virtual ~Component() {} + + /** + * Updates the internal status. The \a entity is the owner of this + * component. + */ + virtual void update(Entity &entity) = 0; +}; + +#endif // COMPONENT_H diff --git a/src/game-server/entity.cpp b/src/game-server/entity.cpp index 6cb61e58..3593d902 100644 --- a/src/game-server/entity.cpp +++ b/src/game-server/entity.cpp @@ -1,6 +1,7 @@ /* * The Mana Server * Copyright (C) 2007-2010 The Mana World Development Team + * Copyright (C) 2012 The Mana Developers * * This file is part of The Mana Server. * @@ -19,3 +20,24 @@ */ #include "game-server/entity.h" + +Entity::Entity(EntityType type, MapComposite *map) : + mMap(map), + mType(type) +{ + for (int i = 0; i < ComponentTypeCount; ++i) + mComponents[i] = 0; +} + +Entity::~Entity() +{ + for (int i = 0; i < ComponentTypeCount; ++i) + delete mComponents[i]; +} + +void Entity::update() +{ + for (int i = 0; i < ComponentTypeCount; ++i) + if (mComponents[i]) + mComponents[i]->update(*this); +} diff --git a/src/game-server/entity.h b/src/game-server/entity.h index 91f13699..7aed29e6 100644 --- a/src/game-server/entity.h +++ b/src/game-server/entity.h @@ -1,6 +1,7 @@ /* * The Mana Server * Copyright (C) 2004-2010 The Mana World Development Team + * Copyright (C) 2012 The Mana Developers * * This file is part of The Mana Server. * @@ -23,28 +24,29 @@ #include "common/manaserv_protocol.h" -#include +#include "game-server/component.h" #include #include +#include + using namespace ManaServ; class MapComposite; /** - * Base class for in-game objects. Knows only its type and the map it resides - * on. Provides listeners. + * Base class for in-game objects. + * + * Knows its type, the map it resides on and is host to a number of optional + * components. */ class Entity : public sigc::trackable { public: - Entity(EntityType type, MapComposite *map = 0) - : mMap(map), - mType(type) - {} + Entity(EntityType type, MapComposite *map = 0); - virtual ~Entity() {} + virtual ~Entity(); /** * Gets type of this entity. @@ -54,6 +56,32 @@ class Entity : public sigc::trackable EntityType getType() const { return mType; } + /** + * Adds a component. Only one component of a given type can be added. + * Entity takes ownership of \a component. + */ + template + void addComponent(T *component) + { + assert(!mComponents[T::type]); + mComponents[T::type] = component; + } + + /** + * Returns the component of the given type, or 0 when no such component + * was set. + */ + Component *getComponent(ComponentType type) const + { return mComponents[type]; } + + /** + * Get a component by its class. Avoids the need for doing a static- + * cast in the calling code. + */ + template + T *getComponent() const + { return static_cast(getComponent(T::type)); } + /** * Returns whether this entity is visible on the map or not. (Actor) */ @@ -74,9 +102,10 @@ class Entity : public sigc::trackable { return mType == OBJECT_CHARACTER || mType == OBJECT_MONSTER; } /** - * Updates the internal status. + * Updates the internal status. By default, calls update on all its + * components. */ - virtual void update() = 0; + virtual void update(); /** * Gets the map this entity is located on. @@ -96,6 +125,8 @@ class Entity : public sigc::trackable private: MapComposite *mMap; /**< Map the entity is on */ EntityType mType; /**< Type of this entity. */ + + Component *mComponents[ComponentTypeCount]; }; #endif // ENTITY_H diff --git a/src/game-server/mapcomposite.cpp b/src/game-server/mapcomposite.cpp index 99d2734f..a1a3f989 100644 --- a/src/game-server/mapcomposite.cpp +++ b/src/game-server/mapcomposite.cpp @@ -1,7 +1,7 @@ /* * The Mana Server * Copyright (C) 2006-2010 The Mana World Development Team - * Copyright (C) 2010-2011 The Mana Development Team + * Copyright (C) 2010-2012 The Mana Development Team * * This file is part of The Mana Server. * @@ -31,8 +31,8 @@ #include "game-server/mapmanager.h" #include "game-server/mapreader.h" #include "game-server/monstermanager.h" -#include "game-server/spawnarea.h" -#include "game-server/trigger.h" +#include "game-server/spawnareacomponent.h" +#include "game-server/triggerareacomponent.h" #include "scripting/script.h" #include "scripting/scriptmanager.h" #include "utils/logger.h" @@ -800,9 +800,12 @@ void MapComposite::initializeContent() if (destMap && destX && destY) { + Entity *entity = new Entity(OBJECT_OTHER, this); WarpAction *action = new WarpAction(destMap, destX, destY); - insert(new TriggerArea(this, object->getBounds(), - action, false)); + entity->addComponent( + new TriggerAreaComponent(object->getBounds(), + action, false)); + insert(entity); } else { @@ -838,8 +841,13 @@ void MapComposite::initializeContent() if (monster && maxBeings && spawnRate) { - insert(new SpawnArea(this, monster, object->getBounds(), - maxBeings, spawnRate)); + Entity *entity = new Entity(OBJECT_OTHER, this); + SpawnAreaComponent *spawnArea = + new SpawnAreaComponent(monster, object->getBounds(), + maxBeings, spawnRate); + + entity->addComponent(spawnArea); + insert(entity); } } else if (utils::compareStrI(type, "NPC") == 0) diff --git a/src/game-server/monster.h b/src/game-server/monster.h index 6bf06d2b..8e927f92 100644 --- a/src/game-server/monster.h +++ b/src/game-server/monster.h @@ -27,8 +27,9 @@ #include "utils/string.h" #include -#include +#include #include +#include #include diff --git a/src/game-server/spawnarea.cpp b/src/game-server/spawnarea.cpp deleted file mode 100644 index 73dca6b2..00000000 --- a/src/game-server/spawnarea.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 . - */ - -#include "game-server/spawnarea.h" - -#include "game-server/mapcomposite.h" -#include "game-server/monster.h" -#include "game-server/state.h" -#include "utils/logger.h" - -SpawnArea::SpawnArea(MapComposite *map, - MonsterClass *specy, - const Rectangle &zone, - int maxBeings, - int spawnRate): - Entity(OBJECT_OTHER, map), - mSpecy(specy), - mZone(zone), - mMaxBeings(maxBeings), - mSpawnRate(spawnRate), - mNumBeings(0), - mNextSpawn(0) -{ -} - -void SpawnArea::update() -{ - if (mNextSpawn > 0) - mNextSpawn--; - - if (mNextSpawn == 0 && mNumBeings < mMaxBeings && mSpawnRate > 0) - { - MapComposite *map = 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 c = 10; - Point position; - const int x = mZone.x; - const int y = mZone.y; - const int width = mZone.w; - const int height = mZone.h; - - Being *being = new Monster(mSpecy); - - if (being->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); - c--; - } - while (!realMap->getWalk(position.x / realMap->getTileWidth(), - position.y / realMap->getTileHeight(), - being->getWalkMask()) && c); - - if (c) - { - being->signal_removed.connect( - sigc::mem_fun(this, &SpawnArea::decrease)); - - being->setMap(map); - being->setPosition(position); - being->clearDestination(); - 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 SpawnArea::decrease(Entity *) -{ - --mNumBeings; -} diff --git a/src/game-server/spawnarea.h b/src/game-server/spawnarea.h deleted file mode 100644 index 628c072e..00000000 --- a/src/game-server/spawnarea.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 . - */ - -#ifndef SPAWNAREA_H -#define SPAWNAREA_H - -#include "game-server/entity.h" -#include "utils/point.h" - -class Being; -class MonsterClass; - -/** - * A spawn area, where monsters spawn. The area is a rectangular field and will - * spawn a certain number of a given monster type. - */ -class SpawnArea : public Entity -{ - public: - SpawnArea(MapComposite *, MonsterClass *, const Rectangle &zone, - int maxBeings, int spawnRate); - - void update(); - - /** - * Keeps track of the number of spawned being. - */ - void decrease(Entity *); - - private: - MonsterClass *mSpecy; /**< Specy of monster that spawns in this area. */ - Rectangle mZone; - int mMaxBeings; /**< Maximum population of this area. */ - int mSpawnRate; /**< Number of beings spawning per minute. */ - int mNumBeings; /**< Current population of this area. */ - int mNextSpawn; /**< The time until next being spawn. */ - - friend struct SpawnAreaEventDispatch; -}; - -#endif diff --git a/src/game-server/spawnareacomponent.cpp b/src/game-server/spawnareacomponent.cpp new file mode 100644 index 00000000..d71c2502 --- /dev/null +++ b/src/game-server/spawnareacomponent.cpp @@ -0,0 +1,121 @@ +/* + * 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 . + */ + +#include "game-server/spawnareacomponent.h" + +#include "game-server/mapcomposite.h" +#include "game-server/monster.h" +#include "game-server/state.h" +#include "utils/logger.h" + +const ComponentType SpawnAreaComponent::type; + +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; + + Being *being = new Monster(mSpecy); + + if (being->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(), + being->getWalkMask()) + && triesLeft); + + if (triesLeft) + { + being->signal_removed.connect( + sigc::mem_fun(this, &SpawnAreaComponent::decrease)); + + being->setMap(map); + being->setPosition(position); + being->clearDestination(); + 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; +} diff --git a/src/game-server/spawnareacomponent.h b/src/game-server/spawnareacomponent.h new file mode 100644 index 00000000..52399a64 --- /dev/null +++ b/src/game-server/spawnareacomponent.h @@ -0,0 +1,62 @@ +/* + * The Mana Server + * Copyright (C) 2006-2010 The Mana World Development Team + * Copyright (C) 2012 The Mana Developers + * + * 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 . + */ + +#ifndef SPAWNAREACOMPONENT_H +#define SPAWNAREACOMPONENT_H + +#include "game-server/component.h" + +#include "utils/point.h" + +class MonsterClass; + +/** + * A spawn area, where monsters spawn. The area is a rectangular field and will + * spawn a certain number of a given monster type. + */ +class SpawnAreaComponent : public Component +{ + public: + static const ComponentType type = SpawnArea; + + SpawnAreaComponent(MonsterClass *, + const Rectangle &zone, + int maxBeings, int spawnRate); + + void update(Entity &entity); + + /** + * Keeps track of the number of spawned being. + */ + void decrease(Entity *); + + private: + MonsterClass *mSpecy; /**< Specy of monster that spawns in this area. */ + Rectangle mZone; + int mMaxBeings; /**< Maximum population of this area. */ + int mSpawnRate; /**< Number of beings spawning per minute. */ + int mNumBeings; /**< Current population of this area. */ + int mNextSpawn; /**< The time until next being spawn. */ + + friend struct SpawnAreaEventDispatch; +}; + +#endif // SPAWNAREACOMPONENT_H diff --git a/src/game-server/trigger.cpp b/src/game-server/trigger.cpp deleted file mode 100644 index 10e50ecb..00000000 --- a/src/game-server/trigger.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 . - */ - -#include "game-server/trigger.h" - -#include "game-server/character.h" -#include "game-server/mapcomposite.h" -#include "game-server/actor.h" -#include "game-server/state.h" - -#include "utils/logger.h" - -#include - -void WarpAction::process(Actor *obj) -{ - if (obj->getType() == OBJECT_CHARACTER) - { - GameState::enqueueWarp(static_cast< Character * >(obj), mMap, mX, mY); - } -} - -ScriptAction::ScriptAction(Script *script, Script::Ref callback, int arg) : - mScript(script), - mCallback(callback), - mArg(arg) -{ - assert(mCallback.isValid()); -} - -void ScriptAction::process(Actor *obj) -{ - LOG_DEBUG("Script trigger area activated: " - << "(" << obj << ", " << mArg << ")"); - - mScript->prepare(mCallback); - mScript->push(obj); - mScript->push(mArg); - mScript->execute(obj->getMap()); -} - -void TriggerArea::update() -{ - std::set insideNow; - for (BeingIterator i(getMap()->getInsideRectangleIterator(mZone)); i; ++i) - { - // Don't deal with unitialized actors. - if (!(*i) || !(*i)->isPublicIdValid()) - continue; - - // The BeingIterator returns the mapZones in touch with the rectangle - // area. On the other hand, the beings contained in the map zones - // may not be within the rectangle area. Hence, this additional - // contains() condition. - if (mZone.contains((*i)->getPosition())) - { - insideNow.insert(*i); - - if (!mOnce || mInside.find(*i) == mInside.end()) - { - mAction->process(*i); - } - } - } - mInside.swap(insideNow); //swapping is faster than assigning -} diff --git a/src/game-server/trigger.h b/src/game-server/trigger.h deleted file mode 100644 index fbd41fa8..00000000 --- a/src/game-server/trigger.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 . - */ - -#ifndef TRIGGER_H -#define TRIGGER_H - -#include "game-server/entity.h" -#include "scripting/script.h" -#include "utils/point.h" - -class Actor; - -class TriggerAction -{ - public: - virtual ~TriggerAction() {} - virtual void process(Actor *obj) = 0; -}; - -class WarpAction : public TriggerAction -{ - public: - WarpAction(MapComposite *m, int x, int y) - : mMap(m), mX(x), mY(y) {} - - virtual void process(Actor *obj); - - private: - MapComposite *mMap; - unsigned short mX, mY; -}; - -class ScriptAction : public TriggerAction -{ - public: - ScriptAction(Script *script, Script::Ref callback, int arg); - - virtual void process(Actor *obj); - - private: - Script *mScript; // Script object to be called - Script::Ref mCallback; // Reference to the function to call - int mArg; // Argument passed to script function (meaning is function-specific) -}; - -class TriggerArea : public Entity -{ - public: - /** - * Creates a rectangular trigger for a given map. - */ - TriggerArea(MapComposite *m, const Rectangle &r, TriggerAction *ptr, bool once) - : Entity(OBJECT_OTHER, m), mZone(r), mAction(ptr), mOnce(once) {} - - virtual void update(); - - private: - Rectangle mZone; - TriggerAction *mAction; - bool mOnce; - std::set mInside; -}; - -#endif diff --git a/src/game-server/triggerareacomponent.cpp b/src/game-server/triggerareacomponent.cpp new file mode 100644 index 00000000..ebfe8580 --- /dev/null +++ b/src/game-server/triggerareacomponent.cpp @@ -0,0 +1,88 @@ +/* + * The Mana Server + * Copyright (C) 2006-2010 The Mana World Development Team + * Copyright (C) 2012 The Mana Developers + * + * 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 . + */ + +#include "game-server/triggerareacomponent.h" + +#include "game-server/character.h" +#include "game-server/mapcomposite.h" +#include "game-server/actor.h" +#include "game-server/state.h" + +#include "utils/logger.h" + +#include + +void WarpAction::process(Actor *obj) +{ + if (obj->getType() == OBJECT_CHARACTER) + { + GameState::enqueueWarp(static_cast< Character * >(obj), mMap, mX, mY); + } +} + +ScriptAction::ScriptAction(Script *script, Script::Ref callback, int arg) : + mScript(script), + mCallback(callback), + mArg(arg) +{ + assert(mCallback.isValid()); +} + +void ScriptAction::process(Actor *obj) +{ + LOG_DEBUG("Script trigger area activated: " + << "(" << obj << ", " << mArg << ")"); + + mScript->prepare(mCallback); + mScript->push(obj); + mScript->push(mArg); + mScript->execute(obj->getMap()); +} + +const ComponentType TriggerAreaComponent::type; + +void TriggerAreaComponent::update(Entity &entity) +{ + MapComposite *map = entity.getMap(); + std::set insideNow; + + for (BeingIterator i(map->getInsideRectangleIterator(mZone)); i; ++i) + { + // Don't deal with uninitialized actors + if (!(*i) || !(*i)->isPublicIdValid()) + continue; + + // The BeingIterator returns the mapZones in touch with the rectangle + // area. On the other hand, the beings contained in the map zones + // may not be within the rectangle area. Hence, this additional + // contains() condition. + if (mZone.contains((*i)->getPosition())) + { + insideNow.insert(*i); + + if (!mOnce || mInside.find(*i) == mInside.end()) + { + mAction->process(*i); + } + } + } + mInside.swap(insideNow); //swapping is faster than assigning +} diff --git a/src/game-server/triggerareacomponent.h b/src/game-server/triggerareacomponent.h new file mode 100644 index 00000000..4fa6e334 --- /dev/null +++ b/src/game-server/triggerareacomponent.h @@ -0,0 +1,91 @@ +/* + * The Mana Server + * Copyright (C) 2006-2010 The Mana World Development Team + * Copyright (C) 2012 The Mana Developers + * + * 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 . + */ + +#ifndef TRIGGERAREACOMPONENT_H +#define TRIGGERAREACOMPONENT_H + +#include "game-server/entity.h" +#include "scripting/script.h" +#include "utils/point.h" + +#include + +class Actor; + +class TriggerAction +{ + public: + virtual ~TriggerAction() {} + virtual void process(Actor *obj) = 0; +}; + +class WarpAction : public TriggerAction +{ + public: + WarpAction(MapComposite *m, int x, int y) + : mMap(m), mX(x), mY(y) {} + + virtual void process(Actor *obj); + + private: + MapComposite *mMap; + unsigned short mX, mY; +}; + +class ScriptAction : public TriggerAction +{ + public: + ScriptAction(Script *script, Script::Ref callback, int arg); + + virtual void process(Actor *obj); + + private: + Script *mScript; // Script object to be called + Script::Ref mCallback; // Reference to the function to call + int mArg; // Argument passed to script function (meaning is function-specific) +}; + +class TriggerAreaComponent : public Component +{ + public: + static const ComponentType type = TriggerArea; + + /** + * Creates a rectangular trigger for a given map. + */ + TriggerAreaComponent(const Rectangle &r, + TriggerAction *ptr, + bool once) : + mZone(r), + mAction(ptr), + mOnce(once) + {} + + virtual void update(Entity &entity); + + private: + Rectangle mZone; + TriggerAction *mAction; + bool mOnce; + std::set mInside; +}; + +#endif // TRIGGERAREACOMPONENT_H -- cgit v1.2.3-60-g2f50