diff options
author | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2007-07-08 13:31:33 +0000 |
---|---|---|
committer | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2007-07-08 13:31:33 +0000 |
commit | f23ebba72f01fc6fac49211a50ca008c8af4ed84 (patch) | |
tree | 65a603d92548643f4b7d197464c2942722bc374c | |
parent | a4c7586b310a8be8ffd5c8acad88b5236695c1da (diff) | |
download | manaserv-f23ebba72f01fc6fac49211a50ca008c8af4ed84.tar.gz manaserv-f23ebba72f01fc6fac49211a50ca008c8af4ed84.tar.bz2 manaserv-f23ebba72f01fc6fac49211a50ca008c8af4ed84.tar.xz manaserv-f23ebba72f01fc6fac49211a50ca008c8af4ed84.zip |
Added monster drops.
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | data/monsters.xml | 7 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/game-server/being.cpp | 4 | ||||
-rw-r--r-- | src/game-server/deathlistener.hpp | 4 | ||||
-rw-r--r-- | src/game-server/main-game.cpp | 7 | ||||
-rw-r--r-- | src/game-server/monster.cpp | 30 | ||||
-rw-r--r-- | src/game-server/monster.hpp | 42 | ||||
-rw-r--r-- | src/game-server/monstermanager.cpp | 128 | ||||
-rw-r--r-- | src/game-server/monstermanager.hpp | 49 | ||||
-rw-r--r-- | src/game-server/spawnarea.cpp | 6 | ||||
-rw-r--r-- | src/game-server/spawnarea.hpp | 9 | ||||
-rw-r--r-- | src/game-server/testing.cpp | 3 |
13 files changed, 284 insertions, 22 deletions
@@ -1,4 +1,17 @@ -2007-07-07 Guillaume Melquiond <guillaume.melquiond@gmail.com> +2007-07-08 Guillaume Melquiond <guillaume.melquiond@gmail.com> + + * src/game-server/being.cpp: Lowered messages to debug level. + * src/game-server/deathlistener.hpp: Made members non-abstract, so that + inheritors do not have to define them when they do not use them. + * data/monsters.xml: Added sample monster database. + * src/game-server/monstermanager.cpp, src/game-server/main-game.cpp, + src/game-server/monstermanager.hpp: Added manager for monster species. + * src/game-server/spawnarea.cpp, src/game-server/spawnarea.hpp, + src/game-server/testing.cpp: Specified the monster specy being spawned. + * src/game-server/monster.cpp, src/game-server/monster.hpp: Added + monster drops. + +2007-07-07 Guillaume Melquiond <guillaume.melquiond@gmail.com> * src/common/inventorydata.hpp: Fixed missing include. * src/game-server/mapcomposite.cpp, src/game-server/mapcomposite.hpp: diff --git a/data/monsters.xml b/data/monsters.xml new file mode 100644 index 00000000..d08483b0 --- /dev/null +++ b/data/monsters.xml @@ -0,0 +1,7 @@ +<?xml version="1.0"?> +<monsters> + <monster id="1002"> + <drop item="505" percent="8"/> + <drop item="518" percent="4"/> + </monster> +</monsters> diff --git a/src/Makefile.am b/src/Makefile.am index 213ba2a3..9df78783 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -106,6 +106,8 @@ tmwserv_game_SOURCES = \ game-server/mapreader.cpp \ game-server/monster.hpp \ game-server/monster.cpp \ + game-server/monstermanager.hpp \ + game-server/monstermanager.cpp \ game-server/movingobject.hpp \ game-server/movingobject.cpp \ game-server/object.hpp \ diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp index 59f37a88..45b6b8aa 100644 --- a/src/game-server/being.cpp +++ b/src/game-server/being.cpp @@ -79,7 +79,7 @@ int Being::damage(Damage damage) mHitpoints -= HPloss; mHitsTaken.push_back(HPloss); - LOG_INFO("Being " << getPublicID() << " got hit"); + LOG_DEBUG("Being " << getPublicID() << " got hit."); if (mHitpoints == 0) die(); @@ -88,7 +88,7 @@ int Being::damage(Damage damage) void Being::die() { - LOG_INFO("Being " << getPublicID() << " died"); + LOG_DEBUG("Being " << getPublicID() << " died."); setAction(DEAD); // dead beings stay where they are clearDestination(); diff --git a/src/game-server/deathlistener.hpp b/src/game-server/deathlistener.hpp index 462f36da..06bb760f 100644 --- a/src/game-server/deathlistener.hpp +++ b/src/game-server/deathlistener.hpp @@ -41,12 +41,12 @@ class DeathListener /** * Called when a being died. */ - virtual void died(Being *being) = 0; + virtual void died(Being *) {} /** * Called when a being is deleted. */ - virtual void deleted(Being *being) = 0; + virtual void deleted(Being *) {} }; typedef std::list<DeathListener*> DeathListeners; diff --git a/src/game-server/main-game.cpp b/src/game-server/main-game.cpp index 72aaef56..e7f334fa 100644 --- a/src/game-server/main-game.cpp +++ b/src/game-server/main-game.cpp @@ -38,6 +38,7 @@ #include "game-server/gamehandler.hpp" #include "game-server/itemmanager.hpp" #include "game-server/mapmanager.hpp" +#include "game-server/monstermanager.hpp" #include "game-server/state.hpp" #include "net/connectionhandler.hpp" #include "net/messageout.hpp" @@ -73,6 +74,7 @@ std::string scriptLanugage = "none"; #define DEFAULT_CONFIG_FILE "tmwserv.xml" #define DEFAULT_ITEMSDB_FILE "items.xml" #define DEFAULT_MAPSDB_FILE "maps.xml" +#define DEFAULT_MONSTERSDB_FILE "monsters.xml" utils::Timer worldTimer(100, false); /**< Timer for world tics set to 100 ms */ int worldTime = 0; /**< Current world time in 100ms ticks */ @@ -161,10 +163,10 @@ void initialize() // --- Initialize the managers // Initialize the slang's and double quotes filter. stringFilter = new StringFilter(&config); - // Initialize the map manager + MapManager::initialize(DEFAULT_MAPSDB_FILE); - // Initialize the item manager ItemManager::initialize(DEFAULT_ITEMSDB_FILE); + MonsterManager::initialize(DEFAULT_MONSTERSDB_FILE); // --- Initialize the global handlers // FIXME: Make the global handlers global vars or part of a bigger @@ -234,6 +236,7 @@ void deinitialize() // Destroy Managers delete stringFilter; + MonsterManager::deinitialize(); ItemManager::deinitialize(); MapManager::deinitialize(); diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp index be9d6fa1..30f3a909 100644 --- a/src/game-server/monster.cpp +++ b/src/game-server/monster.cpp @@ -22,13 +22,29 @@ #include "game-server/monster.hpp" -#include "game-server/collisiondetection.hpp" +#include "game-server/item.hpp" #include "game-server/mapcomposite.hpp" - +#include "game-server/state.hpp" #include "utils/logger.h" -Monster::Monster(): +ItemClass *MonsterClass::getRandomDrop() const +{ + int p = rand() / (RAND_MAX / 10000); + for (MonsterDrops::const_iterator i = mDrops.begin(), + i_end = mDrops.end(); i != i_end; ++i) + { + p -= i->probability; + if (p < 0) + { + return i->item; + } + } + return NULL; +} + +Monster::Monster(MonsterClass *specy): Being(OBJECT_MONSTER, 65535), + mSpecy(specy), mCountDown(0), mAttackTime(0), mAttackPreDelay(5), @@ -230,6 +246,14 @@ void Monster::die() { mCountDown = 50; // sets remove time to 5 seconds Being::die(); + if (ItemClass *drop = mSpecy->getRandomDrop()) + { + Item *item = new Item(drop, 1); + item->setMap(getMap()); + item->setPosition(getPosition()); + DelayedEvent e = { EVENT_INSERT }; + GameState::enqueueEvent(item, e); + } } WeaponStats Monster::getWeaponStats() diff --git a/src/game-server/monster.hpp b/src/game-server/monster.hpp index 616aa9d4..f9614ecd 100644 --- a/src/game-server/monster.hpp +++ b/src/game-server/monster.hpp @@ -24,12 +24,49 @@ #define _TMWSERV_MONSTER_H_ #include <map> +#include <vector> #include "game-server/being.hpp" #include "game-server/deathlistener.hpp" +class ItemClass; class MapComposite; -class MovingObject; + +/** + * Structure containing an item class and its probability to be dropped (unit: 1/10000). + */ +struct MonsterDrop +{ + ItemClass *item; + int probability; +}; + +typedef std::vector< MonsterDrop > MonsterDrops; + +/** + * Class describing the characteristics of a generic monster. + */ +class MonsterClass +{ + public: + MonsterClass(int id): mID(id) {} + + /** + * Sets monster drops. + */ + void setDrops(MonsterDrops const &v) + { mDrops = v; } + + /** + * Randomly selects a monster drop (may return NULL). + * TODO: pass some luck modifier as an argument. + */ + ItemClass *getRandomDrop() const; + + private: + unsigned short mID; /**< ID of the monster class. */ + MonsterDrops mDrops; /**< Items the monster drops when dying. */ +}; /** * Structure holding possible positions relative to the target from which @@ -57,7 +94,7 @@ class Monster : public Being, public DeathListener /** * Constructor. */ - Monster(); + Monster(MonsterClass *); /** * Destructor. @@ -108,6 +145,7 @@ class Monster : public Being, public DeathListener private: int calculatePositionPriority(Point position, int targetPriority); + MonsterClass *mSpecy; /**< Monster specy. */ int mCountDown; /**< Count down till next random movement (temporary). */ std::map<Being *, int> mAnger; /**< Aggression towards other beings */ int mAttackTime; /**< Delay until monster can attack */ diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp new file mode 100644 index 00000000..36ee1eef --- /dev/null +++ b/src/game-server/monstermanager.cpp @@ -0,0 +1,128 @@ +/* + * The Mana World + * Copyright 2007 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 <map> + +#include "defines.h" +#include "resourcemanager.h" +#include "game-server/itemmanager.hpp" +#include "game-server/monster.hpp" +#include "game-server/monstermanager.hpp" +#include "utils/logger.h" +#include "utils/xml.hpp" + +typedef std::map< int, MonsterClass * > MonsterClasses; +static MonsterClasses monsterClasses; /**< Monster reference */ + +void MonsterManager::initialize(std::string const &file) +{ + ResourceManager *resman = ResourceManager::getInstance(); + int size; + char *data = (char *)resman->loadFile(file, size); + + if (!data) { + LOG_ERROR("Monster Manager: Could not find " << file << "!"); + free(data); + return; + } + + xmlDocPtr doc = xmlParseMemory(data, size); + free(data); + + if (!doc) + { + LOG_ERROR("Monster Manager: Error while parsing item database (" + << file << ")!"); + return; + } + + xmlNodePtr node = xmlDocGetRootElement(doc); + if (!node || !xmlStrEqual(node->name, BAD_CAST "monsters")) + { + LOG_ERROR("Monster Manager: " << file + << " is not a valid database file!"); + xmlFreeDoc(doc); + return; + } + + LOG_INFO("Loading monster reference..."); + int nbMonsters = 0; + for (node = node->xmlChildrenNode; node != NULL; node = node->next) + { + if (!xmlStrEqual(node->name, BAD_CAST "monster")) + { + continue; + } + + int id = XML::getProperty(node, "id", 0); + + if (id == 0) + { + LOG_WARN("Monster Manager: There is a monster without ID in " + << file << "! It has been ignored."); + continue; + } + + MonsterDrops drops; + + for (xmlNodePtr subnode = node->xmlChildrenNode; subnode != NULL; + subnode = subnode->next) + { + if (xmlStrEqual(subnode->name, BAD_CAST "drop")) + { + MonsterDrop drop; + drop.item = ItemManager::getItem(XML::getProperty(subnode, "item", 0)); + drop.probability = XML::getProperty(subnode, "percent", 0) * 100; + if (drop.item && drop.probability) + { + drops.push_back(drop); + } + } + } + + MonsterClass *monster = new MonsterClass(id); + monster->setDrops(drops); + monsterClasses[id] = monster; + ++nbMonsters; + } + + LOG_INFO("Loaded " << nbMonsters << " monsters from " << file << '.'); + + xmlFreeDoc(doc); +} + +void MonsterManager::deinitialize() +{ + for (MonsterClasses::iterator i = monsterClasses.begin(), + i_end = monsterClasses.end(); i != i_end; ++i) + { + delete i->second; + } + monsterClasses.clear(); +} + +MonsterClass *MonsterManager::getMonster(int id) +{ + MonsterClasses::const_iterator i = monsterClasses.find(id); + return i != monsterClasses.end() ? i->second : NULL; +} diff --git a/src/game-server/monstermanager.hpp b/src/game-server/monstermanager.hpp new file mode 100644 index 00000000..adfaf5e8 --- /dev/null +++ b/src/game-server/monstermanager.hpp @@ -0,0 +1,49 @@ +/* + * The Mana World + * Copyright 2007 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_MONSTERMANAGER_HPP_ +#define _TMWSERV_MONSTERMANAGER_HPP_ + +#include <string> + +class MonsterClass; + +namespace MonsterManager +{ + /** + * Loads monster reference file. + */ + void initialize(std::string const &); + + /** + * Destroy monster classes. + */ + void deinitialize(); + + /** + * Gets the MonsterClass having the given ID. + */ + MonsterClass *getMonster(int); +} + +#endif diff --git a/src/game-server/spawnarea.cpp b/src/game-server/spawnarea.cpp index 951b2085..3a6e9a17 100644 --- a/src/game-server/spawnarea.cpp +++ b/src/game-server/spawnarea.cpp @@ -33,11 +33,11 @@ * TODO: Allow specifying being type and use it. */ -SpawnArea::SpawnArea(MapComposite *map, const Rectangle &zone): +SpawnArea::SpawnArea(MapComposite *map, MonsterClass *specy, const Rectangle &zone): Thing(OBJECT_OTHER, map), + mSpecy(specy), mZone(zone), mMaxBeings(10), - mBeingType(1), mSpawnRate(10), mNumBeings(0), mNextSpawn(0) @@ -67,7 +67,7 @@ SpawnArea::update() if (c) { - Being *being = new Monster(); + Being *being = new Monster(mSpecy); being->addDeathListener(this); // some bogus stats for testing diff --git a/src/game-server/spawnarea.hpp b/src/game-server/spawnarea.hpp index 91aec141..cd682647 100644 --- a/src/game-server/spawnarea.hpp +++ b/src/game-server/spawnarea.hpp @@ -29,6 +29,7 @@ #include "game-server/thing.hpp" class Being; +class MonsterClass; /** * A spawn area, where monsters spawn. The area is a rectangular field and will @@ -37,20 +38,16 @@ class Being; class SpawnArea : public Thing, public DeathListener { public: - SpawnArea(MapComposite *, const Rectangle &zone); - - virtual ~SpawnArea() {} + SpawnArea(MapComposite *, MonsterClass *, Rectangle const &zone); virtual void update(); virtual void died(Being *being); - virtual void deleted(Being *being) {}; - protected: + MonsterClass *mSpecy; /**< Specy of monster that spawns in this area. */ Rectangle mZone; int mMaxBeings; /**< Maximum population of this area. */ - int mBeingType; /**< Type of being that spawns in 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. */ diff --git a/src/game-server/testing.cpp b/src/game-server/testing.cpp index 8bde8e61..31f26d6a 100644 --- a/src/game-server/testing.cpp +++ b/src/game-server/testing.cpp @@ -9,6 +9,7 @@ #include "game-server/itemmanager.hpp" #include "game-server/mapcomposite.hpp" #include "game-server/mapmanager.hpp" +#include "game-server/monstermanager.hpp" #include "game-server/spawnarea.hpp" #include "game-server/state.hpp" #include "game-server/trigger.hpp" @@ -37,7 +38,7 @@ void testingMap(MapComposite *map) { // Create maggot spawn area Rectangle maggotSpawnRect = { 720, 900, 320, 320 }; - GameState::insert(new SpawnArea(map, maggotSpawnRect)); + GameState::insert(new SpawnArea(map, MonsterManager::getMonster(1002), maggotSpawnRect)); // Portal to map 3 GameState::insert(new TriggerArea(map, rectA, &warpA)); |