summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Melquiond <guillaume.melquiond@gmail.com>2007-07-08 13:31:33 +0000
committerGuillaume Melquiond <guillaume.melquiond@gmail.com>2007-07-08 13:31:33 +0000
commitf23ebba72f01fc6fac49211a50ca008c8af4ed84 (patch)
tree65a603d92548643f4b7d197464c2942722bc374c
parenta4c7586b310a8be8ffd5c8acad88b5236695c1da (diff)
downloadmanaserv-f23ebba72f01fc6fac49211a50ca008c8af4ed84.tar.gz
manaserv-f23ebba72f01fc6fac49211a50ca008c8af4ed84.tar.bz2
manaserv-f23ebba72f01fc6fac49211a50ca008c8af4ed84.tar.xz
manaserv-f23ebba72f01fc6fac49211a50ca008c8af4ed84.zip
Added monster drops.
-rw-r--r--ChangeLog15
-rw-r--r--data/monsters.xml7
-rw-r--r--src/Makefile.am2
-rw-r--r--src/game-server/being.cpp4
-rw-r--r--src/game-server/deathlistener.hpp4
-rw-r--r--src/game-server/main-game.cpp7
-rw-r--r--src/game-server/monster.cpp30
-rw-r--r--src/game-server/monster.hpp42
-rw-r--r--src/game-server/monstermanager.cpp128
-rw-r--r--src/game-server/monstermanager.hpp49
-rw-r--r--src/game-server/spawnarea.cpp6
-rw-r--r--src/game-server/spawnarea.hpp9
-rw-r--r--src/game-server/testing.cpp3
13 files changed, 284 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index d34784e9..cf5e98cc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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));