summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/mapmark.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-26 11:06:09 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-26 11:06:09 +0000
commitf2a19d9971bb076f4a80a9e41ba601bc862d0fdf (patch)
treebe553fe84132e1f25d5f33fb98f703378096b961 /crawl-ref/source/mapmark.cc
parentbc1a54904787e2f4779a99f2be1f72f6fd87679b (diff)
downloadcrawl-ref-f2a19d9971bb076f4a80a9e41ba601bc862d0fdf.tar.gz
crawl-ref-f2a19d9971bb076f4a80a9e41ba601bc862d0fdf.zip
Replaced timed markers with Lua markers. Breaks save compatibility.
KFEAT: feature names are now as in the dungeon_feature_type enum. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1930 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/mapmark.cc')
-rw-r--r--crawl-ref/source/mapmark.cc298
1 files changed, 153 insertions, 145 deletions
diff --git a/crawl-ref/source/mapmark.cc b/crawl-ref/source/mapmark.cc
index 696f042b4c..4867225072 100644
--- a/crawl-ref/source/mapmark.cc
+++ b/crawl-ref/source/mapmark.cc
@@ -9,6 +9,7 @@
#include "AppHdr.h"
#include "mapmark.h"
+#include "clua.h"
#include "direct.h"
#include "libutil.h"
#include "luadgn.h"
@@ -22,13 +23,13 @@
map_marker::marker_reader map_marker::readers[NUM_MAP_MARKER_TYPES] =
{
&map_feature_marker::read,
- &map_timed_feature_marker::read,
+ &map_lua_marker::read,
};
map_marker::marker_parser map_marker::parsers[NUM_MAP_MARKER_TYPES] =
{
&map_feature_marker::parse,
- &map_timed_feature_marker::parse,
+ &map_lua_marker::parse,
};
map_marker::map_marker(map_marker_type t, const coord_def &p)
@@ -64,13 +65,14 @@ map_marker *map_marker::read_marker(tagHeader &inf)
return readers[type]? (*readers[type])(inf, type) : NULL;
}
-map_marker *map_marker::parse_marker(const std::string &s) throw (std::string)
+map_marker *map_marker::parse_marker(
+ const std::string &s, const std::string &ctx) throw (std::string)
{
for (int i = 0; i < NUM_MAP_MARKER_TYPES; ++i)
{
if (parsers[i])
{
- if (map_marker *m = parsers[i](s))
+ if (map_marker *m = parsers[i](s, ctx))
return (m);
}
}
@@ -112,7 +114,8 @@ map_marker *map_feature_marker::read(tagHeader &inf, map_marker_type)
return (mapf);
}
-map_marker *map_feature_marker::parse(const std::string &s) throw (std::string)
+map_marker *map_feature_marker::parse(
+ const std::string &s, const std::string &) throw (std::string)
{
if (s.find("feat:") != 0)
return (NULL);
@@ -132,190 +135,195 @@ std::string map_feature_marker::describe() const
}
////////////////////////////////////////////////////////////////////////////
-// map_feature_marker
+// map_lua_marker
-map_timed_feature_marker::map_timed_feature_marker(
- const coord_def &_pos,
- int duration_turns,
- dungeon_feature_type _feat)
- : map_feature_marker(_pos, _feat), duration_ticks(duration_turns * 10),
- warn_threshold(-1000)
+map_lua_marker::map_lua_marker()
+ : map_marker(MAT_LUA_MARKER, coord_def()), initialised(false)
{
- type = MAT_TIMED_FEATURE;
}
-void map_timed_feature_marker::activate()
+map_lua_marker::map_lua_marker(const std::string &s, const std::string &)
+ : map_marker(MAT_LUA_MARKER, coord_def()), initialised(false)
{
- dungeon_events.register_listener(DET_TURN_ELAPSED, this);
+ lua_stack_cleaner clean(dlua);
+ if (dlua.loadstring(("return " + s).c_str(), "lua_marker"))
+ mprf(MSGCH_WARN, "lua_marker load error: %s", dlua.error.c_str());
+ if (!dlua.callfn("dgn_run_map", 1, 1))
+ mprf(MSGCH_WARN, "lua_marker exec error: %s", dlua.error.c_str());
+ check_register_table();
+}
- if (player_can_hear(pos))
+map_lua_marker::~map_lua_marker()
+{
+ // Remove the Lua marker table from the registry.
+ if (initialised)
{
- const dungeon_feature_type ft = grd(pos);
- switch (ft)
- {
- case DNGN_ENTER_BAZAAR:
- mprf(MSGCH_SOUND, "You %shear coins being counted.",
- duration_ticks < 1000? "can faintly " : "");
- break;
- case DNGN_ENTER_LABYRINTH:
- mprf(MSGCH_SOUND, "You hear a faint echoing snort.");
- break;
- default:
- break;
- }
+ lua_pushlightuserdata(dlua, this);
+ lua_pushnil(dlua);
+ lua_settable(dlua, LUA_REGISTRYINDEX);
}
}
-void map_timed_feature_marker::write(tagHeader &th) const
+void map_lua_marker::check_register_table()
{
- map_feature_marker::write(th);
- marshallShort(th, duration_ticks);
- marshallShort(th, warn_threshold);
-}
+ if (!lua_istable(dlua, -1))
+ {
+ mprf(MSGCH_WARN, "lua_marker: Expected table, didn't get it.");
+ initialised = false;
+ return;
+ }
-void map_timed_feature_marker::read(tagHeader &th)
-{
- map_feature_marker::read(th);
- duration_ticks = unmarshallShort(th);
- warn_threshold = unmarshallShort(th);
-}
+ // Got a table. Save it in the registry.
-std::string map_timed_feature_marker::describe() const
-{
- return make_stringf("timer: %d ticks (%s)",
- duration_ticks, dungeon_feature_name(feat));
+ // Key is this.
+ lua_pushlightuserdata(dlua, this);
+ // Move key before value.
+ lua_insert(dlua, -2);
+ lua_settable(dlua, LUA_REGISTRYINDEX);
+
+ initialised = true;
}
-const char *map_timed_feature_marker::bell_urgency(int ticks) const
+bool map_lua_marker::get_table() const
{
- if (ticks > 5000)
- return "stately ";
- else if (ticks > 4000)
- return "";
- else if (ticks > 2500)
- return "brisk ";
- else if (ticks > 1500)
- return "urgent ";
- else if (ticks > 0)
- return "frantic ";
- else
- return "last, dying notes of the ";
+ // First save the unmarshall Lua function.
+ lua_pushlightuserdata(dlua, const_cast<map_lua_marker*>(this));
+ lua_gettable(dlua, LUA_REGISTRYINDEX);
+ return (lua_istable(dlua, -1));
}
-const char *map_timed_feature_marker::noise_maker(int ticks) const
+void map_lua_marker::write(tagHeader &th) const
{
- switch (grd(pos))
+ map_marker::write(th);
+
+ lua_stack_cleaner clean(dlua);
+ bool init = initialised;
+ if (!get_table())
{
- case DNGN_ENTER_LABYRINTH:
- return (ticks > 0? "tolling of a bell" : "bell");
- case DNGN_ENTER_BAZAAR:
- return (ticks > 0? "ticking of an ancient clock" : "clock");
- default:
- return (ticks > 0?
- "trickling of a stream filled with giant, killer bugs."
- : "stream");
+ mprf(MSGCH_WARN, "Couldn't find table.");
+ init = false;
}
+
+ marshallByte(th, init);
+ if (!init)
+ return;
+
+ // Call dlua_marker_function(table, 'read')
+ lua_pushstring(dlua, "read");
+ if (!dlua.callfn("dlua_marker_function", 2, 1))
+ end(1, false, "lua_marker: write error: %s", dlua.error.c_str());
+
+ // Right, what's on top should be a function. Save it.
+ dlua_chunk reader(dlua);
+ if (!reader.error.empty())
+ end(1, false, "lua_marker: couldn't save read function: %s",
+ reader.error.c_str());
+
+ marshallString(th, reader.compiled_chunk());
+
+ // Okay, saved the reader. Now ask the writer to do its thing.
+
+ // Call: dlua_marker_method(table, fname, marker)
+ get_table();
+ lua_pushstring(dlua, "write");
+ lua_pushlightuserdata(dlua, const_cast<map_lua_marker*>(this));
+ lua_pushlightuserdata(dlua, &th);
+
+ if (!dlua.callfn("dlua_marker_method", 4))
+ end(1, false, "lua_marker::write error: %s", dlua.error.c_str());
}
-void map_timed_feature_marker::notify_dgn_event(const dgn_event &e)
+void map_lua_marker::read(tagHeader &th)
{
- if (!e.elapsed_ticks || e.type != DET_TURN_ELAPSED)
+ map_marker::read(th);
+
+ if (!(initialised = unmarshallByte(th)))
return;
- if (warn_threshold == -1000)
- warn_threshold = std::max(50, duration_ticks - 500);
-
- duration_ticks -= e.elapsed_ticks;
+ lua_stack_cleaner cln(dlua);
+ // Read the Lua chunk we saved.
+ const std::string compiled = unmarshallString(th, LUA_CHUNK_MAX_SIZE);
- if (duration_ticks < warn_threshold || duration_ticks <= 0)
- {
- if (duration_ticks > 900)
- warn_threshold = duration_ticks - 500;
- else
- warn_threshold = duration_ticks - 250;
-
- if (duration_ticks > 0 && player_can_hear(pos))
- mprf(MSGCH_SOUND, "You hear the %s%s.",
- bell_urgency(duration_ticks),
- noise_maker(duration_ticks));
-
- if (duration_ticks <= 0)
- timeout(true);
- }
+ dlua_chunk chunk = dlua_chunk::precompiled(compiled);
+ if (chunk.load(dlua))
+ end(1, false, "lua_marker::read error: %s", chunk.error.c_str());
+ dlua_push_userdata(dlua, this, MAPMARK_METATABLE);
+ lua_pushlightuserdata(dlua, &th);
+ if (!dlua.callfn("dlua_marker_read", 3, 1))
+ end(1, false, "lua_marker::read error: %s", dlua.error.c_str());
+
+ // Right, what's on top had better be a table.
+ check_register_table();
}
-void map_timed_feature_marker::timeout(bool verbose)
+map_marker *map_lua_marker::read(tagHeader &th, map_marker_type)
{
- if (verbose)
- {
- if (see_grid(pos))
- mprf("%s disappears!",
- feature_description(grd(pos), NUM_TRAPS, false,
- DESC_CAP_THE, false).c_str());
- else
- mpr("The walls and floor vibrate strangely for a moment.");
- }
+ map_marker *marker = new map_lua_marker;
+ marker->read(th);
+ return (marker);
+}
- // And it's gone forever.
- grd(pos) = feat;
+void map_lua_marker::push_fn_args(const char *fn) const
+{
+ get_table();
+ lua_pushstring(dlua, fn);
+ dlua_push_userdata(dlua, this, MAPMARK_METATABLE);
+}
- dungeon_terrain_changed(pos);
+bool map_lua_marker::callfn(const char *fn, bool warn_err) const
+{
+ const int top = lua_gettop(dlua);
+ push_fn_args(fn);
+ const bool res =
+ dlua.callfn("dlua_marker_method", lua_gettop(dlua) - top, 1);
+ if (!res && warn_err)
+ mprf(MSGCH_WARN, "mlua error: %s", dlua.error.c_str());
+ return (res);
+}
- // Stop listening for further ticks.
- dungeon_events.remove_listener(this);
+void map_lua_marker::activate()
+{
+ lua_stack_cleaner clean(dlua);
+ callfn("activate", true);
+}
- // Kill this marker.
- env_remove_marker(this);
+void map_lua_marker::notify_dgn_event(const dgn_event &e)
+{
+ lua_stack_cleaner clean(dlua);
+ push_fn_args("event");
+ clua_push_dgn_event(dlua, &e);
+ if (!dlua.callfn("dlua_marker_method", 4, 0))
+ mprf(MSGCH_WARN, "notify_dgn_event: Lua error: %s",
+ dlua.error.c_str());
}
-map_marker *map_timed_feature_marker::read(tagHeader &th, map_marker_type)
+std::string map_lua_marker::describe() const
{
- map_marker *mt = new map_timed_feature_marker();
- mt->read(th);
- return (mt);
+ lua_stack_cleaner cln(dlua);
+ if (!callfn("describe"))
+ return make_stringf("error: %s", dlua.error.c_str());
+
+ std::string desc;
+ if (lua_isstring(dlua, -1))
+ desc = lua_tostring(dlua, -1);
+ return desc;
}
-map_marker *map_timed_feature_marker::parse(const std::string &s)
- throw (std::string)
+map_marker *map_lua_marker::parse(
+ const std::string &s, const std::string &ctx) throw (std::string)
{
- if (s.find("timer:") != 0)
+ if (s.find("lua:") != 0)
return (NULL);
std::string raw = s;
- strip_tag(raw, "timer:", true);
-
- int navg = strip_number_tag(raw, "avg:");
- if (navg == TAG_UNFOUND)
- navg = 1;
-
- if (navg < 1 || navg > 20)
- throw make_stringf("Bad marker spec '%s' (avg out of bounds)",
- s.c_str());
-
- dungeon_feature_type feat = DNGN_FLOOR;
- std::string fname = strip_tag_prefix(raw, "feat:");
- if (!fname.empty()
- && (feat = dungeon_feature_by_name(fname)) == DNGN_UNSEEN)
+ strip_tag(raw, "lua:");
+ map_lua_marker *mark = new map_lua_marker(raw, ctx);
+ if (!mark->initialised)
{
- throw make_stringf("Bad feature name (%s) in marker spec '%s'",
- fname.c_str(), s.c_str());
+ delete mark;
+ throw make_stringf("Unable to initialise Lua marker from '%s'",
+ raw.c_str());
}
-
- std::vector<std::string> limits = split_string("-", raw);
- const int nlims = limits.size();
- if (nlims < 1 || nlims > 2)
- throw make_stringf("Malformed turn range (%s) in marker '%s'",
- raw.c_str(), s.c_str());
-
- const int low = atoi(limits[0].c_str());
- const int high = nlims == 1? low : atoi(limits[1].c_str());
-
- if (low == 0 || high < low)
- throw make_stringf("Malformed turn range (%s) in marker '%s'",
- raw.c_str(), s.c_str());
-
- const int duration = low == high? low : random_range(low, high, navg);
- return new map_timed_feature_marker(coord_def(0, 0),
- duration, feat);
+ return (mark);
}
//////////////////////////////////////////////////////////////////////////