summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Schilling <ablu.erikschilling@googlemail.com>2011-10-08 11:19:44 +0200
committerThorbjørn Lindeijer <thorbjorn@lindeijer.nl>2011-10-15 00:10:22 +0200
commit1e6b7a30b7232dce7b8240441bed04912e06f666 (patch)
treeb5aa2d893c2bee4268a3cfc8172dc6ae7ea6ce09
parent9cd09f012ff7c01fbd51b972f9b716cfc8246b2c (diff)
downloadmanaserv-1e6b7a30b7232dce7b8240441bed04912e06f666.tar.gz
manaserv-1e6b7a30b7232dce7b8240441bed04912e06f666.tar.bz2
manaserv-1e6b7a30b7232dce7b8240441bed04912e06f666.tar.xz
manaserv-1e6b7a30b7232dce7b8240441bed04912e06f666.zip
Added script bindings for reading map objects
map_get_objects([string filter]): returns all object of the current map optionally filtered by type. map_get_object_property(handle object, string key): returns the value of the property of the object. map_get_object_bounds(handle object): returns x, y, width, height of an object. map_get_object_name(handle object): returns name of an object. map_get_object_type(handle object): returns type of an object. Mantis-issue: 397 Reviewed-by: Thorbjørn Lindeijer
-rw-r--r--src/game-server/map.cpp10
-rw-r--r--src/game-server/map.h60
-rw-r--r--src/game-server/mapreader.cpp208
-rw-r--r--src/scripting/lua.cpp131
-rw-r--r--src/scripting/luautil.cpp5
-rw-r--r--src/scripting/luautil.h5
6 files changed, 264 insertions, 155 deletions
diff --git a/src/game-server/map.cpp b/src/game-server/map.cpp
index b824aaac..e372f03d 100644
--- a/src/game-server/map.cpp
+++ b/src/game-server/map.cpp
@@ -96,7 +96,6 @@ class Location
int Fcost; /**< Estimation of total path cost */
};
-
Map::Map(int width, int height, int tileWidth, int tileHeight):
mWidth(width), mHeight(height),
mTileWidth(tileWidth), mTileHeight(tileHeight),
@@ -104,6 +103,15 @@ Map::Map(int width, int height, int tileWidth, int tileHeight):
{
}
+Map::~Map()
+{
+ for (std::vector<MapObject*>::iterator it = mMapObjects.begin();
+ it != mMapObjects.end(); ++it)
+ {
+ delete *it;
+ }
+}
+
void Map::setSize(int width, int height)
{
mWidth = width;
diff --git a/src/game-server/map.h b/src/game-server/map.h
index 7c58d005..f1180a77 100644
--- a/src/game-server/map.h
+++ b/src/game-server/map.h
@@ -26,11 +26,12 @@
#include <string>
#include <vector>
+#include "utils/logger.h"
#include "utils/point.h"
+#include "utils/string.h"
typedef std::list<Point> Path;
typedef Path::iterator PathIterator;
-
enum BlockType
{
BLOCKTYPE_NONE = -1,
@@ -59,6 +60,46 @@ class MetaTile
char blockmask; /**< walkability bitfield */
};
+class MapObject
+{
+ public:
+ MapObject(const Rectangle &bounds,
+ const std::string &name,
+ const std::string &type)
+ : mBounds(bounds),
+ mName(name),
+ mType(type)
+ { }
+
+ void addProperty(const std::string &key, const std::string &value)
+ {
+ if (mProperties.contains(key))
+ LOG_WARN("Duplicate property " << key <<
+ " of object " << mName);
+ else
+ mProperties.insert(key, value);
+ }
+
+ std::string getProperty(const std::string &key) const
+ { return mProperties.find(key); }
+
+ const std::string &getName() const
+ { return mName; }
+
+ const std::string &getType() const
+ { return mType; }
+
+ const Rectangle &getBounds() const
+ { return mBounds; }
+
+ private:
+ Rectangle mBounds;
+ std::string mName;
+ std::string mType;
+ utils::NameMap<std::string> mProperties;
+};
+
+
/**
* A tile map.
*/
@@ -71,6 +112,8 @@ class Map
Map(int width, int height,
int tileWidth, int tileHeight);
+ ~Map();
+
/**
* Sets the size of the map. This will destroy any existing map data.
*/
@@ -129,9 +172,21 @@ class Map
/**
* Sets a map property
*/
- void setProperty(const std::string& key, const std::string& val)
+ void setProperty(const std::string &key, const std::string &val)
{ mProperties[key] = val; }
+ /**
+ * Adds an object.
+ */
+ void addObject(MapObject *object)
+ { mMapObjects.push_back(object); }
+
+ /**
+ * Returns the objects of the map.
+ */
+ const std::vector<MapObject*> &getObjects() const
+ { return mMapObjects; }
+
/**
* Find a path from one location to the next.
*/
@@ -154,6 +209,7 @@ class Map
std::map<std::string, std::string> mProperties;
std::vector<MetaTile> mMetaTiles;
+ std::vector<MapObject*> mMapObjects;
};
#endif
diff --git a/src/game-server/mapreader.cpp b/src/game-server/mapreader.cpp
index 8438c82c..e82fa10a 100644
--- a/src/game-server/mapreader.cpp
+++ b/src/game-server/mapreader.cpp
@@ -141,54 +141,44 @@ Map* MapReader::readMap(xmlNodePtr node, const std::string &path,
int objH = XML::getProperty(objectNode, "height", 0);
Rectangle rect = { objX, objY, objW, objH };
+ MapObject *newObject = new MapObject(rect, objName, objType);
- if (utils::compareStrI(objType, "WARP") == 0)
+ for_each_xml_child_node(propertiesNode, objectNode)
{
- std::string destMapName = std::string();
- int destX = -1;
- int destY = -1;
-
- for_each_xml_child_node(propertiesNode, objectNode)
+ if (!xmlStrEqual(propertiesNode->name, BAD_CAST "properties"))
{
- if (!xmlStrEqual(propertiesNode->name, BAD_CAST "properties"))
- {
- continue;
- }
-
- for_each_xml_child_node(propertyNode, propertiesNode)
+ continue;
+ }
+
+ for_each_xml_child_node(propertyNode, propertiesNode)
+ {
+ if (xmlStrEqual(propertyNode->name, BAD_CAST "property"))
{
- if (xmlStrEqual(propertyNode->name,
- BAD_CAST "property"))
- {
- std::string value = XML::getProperty(
- propertyNode, "name", std::string());
- value = utils::toUpper(value);
- if (utils::compareStrI(value, "DEST_MAP") == 0)
- {
- destMapName = getObjectProperty(propertyNode,
+ std::string key = XML::getProperty(
+ propertyNode, "name", std::string());
+ std::string value = getObjectProperty(propertyNode,
std::string());
- }
- else if (utils::compareStrI(value, "DEST_X") == 0)
- {
- destX = getObjectProperty(propertyNode, -1);
- }
- else if (utils::compareStrI(value, "DEST_Y") == 0)
- {
- destY = getObjectProperty(propertyNode, -1);
- }
- }
+ newObject->addProperty(key, value);
}
}
+ }
- if (!destMapName.empty() && destX != -1 && destY != -1)
+ if (utils::compareStrI(objType, "WARP") == 0)
+ {
+ std::string destMapName = newObject->getProperty("DEST_MAP");
+ int destX = utils::stringToInt(
+ newObject->getProperty("DEST_X"));
+ int destY = utils::stringToInt(
+ newObject->getProperty("DEST_Y"));
+
+ if (!destMapName.empty() && destX && destY)
{
MapComposite *destMap = MapManager::getMap(destMapName);
if (destMap)
{
things.push_back(new TriggerArea(
composite, rect,
- new WarpAction(destMap, destX, destY),
- false));
+ new WarpAction(destMap, destX, destY), false));
}
}
else
@@ -199,71 +189,36 @@ Map* MapReader::readMap(xmlNodePtr node, const std::string &path,
else if (utils::compareStrI(objType, "SPAWN") == 0)
{
MonsterClass *monster = 0;
- int maxBeings = 10; // Default value
- int spawnRate = 10; // Default value
-
- for_each_xml_child_node(propertiesNode, objectNode)
+ int maxBeings = utils::stringToInt(
+ newObject->getProperty("MAX_BEINGS"));
+ int spawnRate = utils::stringToInt(
+ newObject->getProperty("SPAWN_RATE"));
+ std::string monsterName =
+ newObject->getProperty("MONSTER_ID");
+ int monsterId = utils::stringToInt(monsterName);
+ if (monsterId)
{
- if (!xmlStrEqual(propertiesNode->name, BAD_CAST "properties"))
+ monster = monsterManager->getMonster(
+ monsterId);
+ if (!monster)
{
- continue;
+ LOG_WARN("Couldn't find monster ID "
+ << monsterId <<
+ " for spawn area");
}
-
- for_each_xml_child_node(propertyNode, propertiesNode)
+ }
+ else
+ {
+ monster = monsterManager->
+ getMonsterByName(monsterName);
+ if (!monster)
{
- if (xmlStrEqual(propertyNode->name, BAD_CAST "property"))
- {
- std::string value = XML::getProperty(
- propertyNode,
- "name",
- std::string());
- value = utils::toUpper(value);
- if (utils::compareStrI(value, "MONSTER_ID") == 0)
- {
- std::string monsterName =
- getObjectProperty(propertyNode,
- std::string());
- int monsterId = utils::stringToInt(monsterName);
- if (monsterId)
- {
- monster = monsterManager->getMonster(
- monsterId);
- if (!monster)
- {
- LOG_WARN("Couldn't find monster ID "
- << monsterId <<
- " for spawn area");
- }
- }
- else
- {
- monster = monsterManager->
- getMonsterByName(monsterName);
- if (!monster)
- {
- LOG_WARN("Couldn't find monster "
- << monsterName <<
- " for spawn area");
- }
- }
- }
- else if (utils::compareStrI(value,
- "MAX_BEINGS") == 0)
- {
- maxBeings = getObjectProperty(propertyNode,
- maxBeings);
- }
- else if (utils::compareStrI(value,
- "SPAWN_RATE") == 0)
- {
- spawnRate = getObjectProperty(propertyNode,
- spawnRate);
- }
- }
+ LOG_WARN("Couldn't find monster "
+ << monsterName <<
+ " for spawn area");
}
}
-
- if (monster)
+ if (monster && maxBeings && spawnRate)
{
things.push_back(new SpawnArea(composite, monster, rect,
maxBeings, spawnRate));
@@ -279,35 +234,11 @@ Map* MapReader::readMap(xmlNodePtr node, const std::string &path,
composite->setScript(s);
}
- int npcId = -1;
- std::string scriptText;
+ int npcId = utils::stringToInt(
+ newObject->getProperty("NPC_ID"));
+ std::string scriptText = newObject->getProperty("SCRIPT");
- for_each_xml_child_node(propertiesNode, objectNode)
- {
- if (!xmlStrEqual(propertiesNode->name, BAD_CAST "properties"))
- {
- continue;
- }
-
- for_each_xml_child_node(propertyNode, propertiesNode)
- {
- if (xmlStrEqual(propertyNode->name, BAD_CAST "property"))
- {
- std::string value = XML::getProperty(propertyNode, "name", std::string());
- value = utils::toUpper(value);
- if (utils::compareStrI(value, "NPC_ID") == 0)
- {
- npcId = getObjectProperty(propertyNode, npcId);
- }
- else if (utils::compareStrI(value, "SCRIPT") == 0)
- {
- scriptText = getObjectProperty(propertyNode, std::string());
- }
- }
- }
- }
-
- if (npcId != -1 && !scriptText.empty())
+ if (npcId && !scriptText.empty())
{
s->loadNPC(objName, npcId, objX, objY, scriptText.c_str());
}
@@ -326,36 +257,9 @@ Map* MapReader::readMap(xmlNodePtr node, const std::string &path,
composite->setScript(s);
}
- std::string scriptFilename;
- std::string scriptText;
-
- for_each_xml_child_node(propertiesNode, objectNode)
- {
- if (!xmlStrEqual(propertiesNode->name, BAD_CAST "properties"))
- {
- continue;
- }
-
- for_each_xml_child_node(propertyNode, propertiesNode)
- {
- if (xmlStrEqual(propertyNode->name, BAD_CAST "property"))
- {
- std::string value = XML::getProperty(propertyNode, "name",
- std::string());
- value = utils::toUpper(value);
- if (utils::compareStrI(value, "FILENAME") == 0)
- {
- scriptFilename = getObjectProperty(propertyNode,
- std::string());
- utils::trim(scriptFilename);
- }
- else if (utils::compareStrI(value, "TEXT") == 0)
- {
- scriptText = getObjectProperty(propertyNode, "");
- }
- }
- }
- }
+ std::string scriptFilename =
+ newObject->getProperty("FILENAME");
+ std::string scriptText = newObject->getProperty("TEXT");
if (!scriptFilename.empty())
{
@@ -371,6 +275,8 @@ Map* MapReader::readMap(xmlNodePtr node, const std::string &path,
LOG_WARN("Unrecognized format for script");
}
}
+
+ map->addObject(newObject);
}
}
}
diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp
index 7213bd09..16781937 100644
--- a/src/scripting/lua.cpp
+++ b/src/scripting/lua.cpp
@@ -2102,6 +2102,132 @@ static int get_distance(lua_State *s)
return 1;
}
+/**
+ * mana.map_get_objects(): table of all objects
+ * mana.map_get_objects(string type): table of all objects of type
+ * Gets the objects of a map.
+ */
+static int map_get_objects(lua_State *s)
+{
+ const bool filtered = (lua_gettop(s) == 1);
+ std::string filter;
+ if (filtered)
+ filter = luaL_checkstring(s, 1);
+
+ lua_pushlightuserdata(s, (void *)&registryKey);
+ lua_gettable(s, LUA_REGISTRYINDEX);
+ Script *t = static_cast<Script *>(lua_touserdata(s, -1));
+ const std::vector<MapObject*> &objects = t->getMap()->getMap()->getObjects();
+
+ if (!filtered)
+ pushSTLContainer<MapObject*>(s, objects);
+ else
+ {
+ std::vector<MapObject*> filteredObjects;
+ for (std::vector<MapObject*>::const_iterator it = objects.begin();
+ it != objects.end(); ++it)
+ {
+ if (utils::compareStrI((*it)->getType(), filter) == 0)
+ {
+ filteredObjects.push_back(*it);
+ }
+ }
+ pushSTLContainer<MapObject*>(s, filteredObjects);
+ }
+ return 1;
+}
+
+/**
+ * mana.map_object_get_property(handle object, string key)
+ * Returns the value of the object property 'key'.
+ */
+static int map_object_get_property(lua_State *s)
+{
+ std::string key = luaL_checkstring(s, 2);
+ if (!lua_islightuserdata(s, 1))
+ {
+ raiseScriptError(s, "map_object_get_property called with invalid"
+ "object handle");
+ return 0;
+ }
+ MapObject *obj = static_cast<MapObject *>(lua_touserdata(s, 1));
+ if (obj)
+ {
+ std::string property = obj->getProperty(key);
+ if (!property.empty())
+ {
+ lua_pushstring(s, property.c_str());
+ return 1;
+ }
+ else
+ {
+ // scripts can check for nil
+ return 0;
+ }
+ }
+ else
+ {
+ raiseScriptError(s, "map_object_get_property called with invalid"
+ "object handle");
+ return 0;
+ }
+}
+
+/**
+ * mana.map_object_get_bounds(object)
+ * Returns 4 int: x/y/width/height of object.
+ */
+static int map_object_get_bounds(lua_State *s)
+{
+ if (!lua_islightuserdata(s, 1))
+ {
+ raiseScriptError(s, "map_object_get_bounds called with invalid"
+ "object handle");
+ return 0;
+ }
+ MapObject *obj = static_cast<MapObject *>(lua_touserdata(s, 1));
+ const Rectangle &bounds = obj->getBounds();
+ lua_pushinteger(s, bounds.x);
+ lua_pushinteger(s, bounds.y);
+ lua_pushinteger(s, bounds.w);
+ lua_pushinteger(s, bounds.h);
+ return 4;
+}
+
+/**
+ * mana.map_object_get_name(object)
+ * Returns the name of the object.
+ */
+static int map_object_get_name(lua_State *s)
+{
+ if (!lua_islightuserdata(s, 1))
+ {
+ raiseScriptError(s, "map_object_get_name called with invalid"
+ "object handle");
+ return 0;
+ }
+ MapObject *obj = static_cast<MapObject *>(lua_touserdata(s, 1));
+ lua_pushstring(s, obj->getName().c_str());
+ return 1;
+}
+
+/**
+ * mana.map_object_get_type(object)
+ * Returns the type of the object.
+ */
+static int map_object_get_type(lua_State *s)
+{
+ if (!lua_islightuserdata(s, 1))
+ {
+ raiseScriptError(s, "map_object_get_type called with invalid"
+ "object handle");
+ return 0;
+ }
+ MapObject *obj = static_cast<MapObject *>(lua_touserdata(s, 1));
+ lua_pushstring(s, obj->getType().c_str());
+ return 1;
+}
+
static int require_loader(lua_State *s)
{
// Add .lua extension (maybe only do this when it doesn't have it already)
@@ -2209,6 +2335,11 @@ LuaScript::LuaScript():
{ "npc_ask_string", &npc_ask_string },
{ "log", &log },
{ "get_distance", &get_distance },
+ { "map_get_objects", &map_get_objects },
+ { "map_object_get_property", &map_object_get_property },
+ { "map_object_get_bounds", &map_object_get_bounds },
+ { "map_object_get_name", &map_object_get_name },
+ { "map_object_get_type", &map_object_get_type },
{ NULL, NULL }
};
luaL_register(mState, "mana", callbacks);
diff --git a/src/scripting/luautil.cpp b/src/scripting/luautil.cpp
index b7680c6b..a7521426 100644
--- a/src/scripting/luautil.cpp
+++ b/src/scripting/luautil.cpp
@@ -116,3 +116,8 @@ void push(lua_State *s, double val)
{
lua_pushnumber(s, val);
}
+
+void push(lua_State *s, MapObject *val)
+{
+ lua_pushlightuserdata(s, val);
+}
diff --git a/src/scripting/luautil.h b/src/scripting/luautil.h
index c55b04b7..82bb78cf 100644
--- a/src/scripting/luautil.h
+++ b/src/scripting/luautil.h
@@ -31,6 +31,8 @@ extern "C" {
#include <set>
#include <vector>
+#include "game-server/map.h"
+
class Being;
class NPC;
class Character;
@@ -52,8 +54,9 @@ Being *getBeing(lua_State *s, int p);
Useful for templates.*/
void push(lua_State *s, int val);
void push(lua_State *s, const std::string &val);
-void push(lua_State *s, Thing* val);
+void push(lua_State *s, Thing *val);
void push(lua_State *s, double val);
+void push(lua_State *s, MapObject *val);
/* Pushes an STL LIST */