#include <terrain_map.h> inherit "/std/object"; #define WORLD_MAP TERRAIN_MAP_WORLD_MAP private nosave int *_area; private nosave int _detail; private nosave string *_features; private nosave mapping _locations; private nosave object _env, _pl; private nosave int *_co_ords; private nosave int _fudge; /** @ignore yes */ void create() { do_setup++; ::create(); do_setup--; add_alias("map"); add_plural("maps"); _locations = ([ ]); add_extra_look(this_object()); if(!do_setup) { this_object()->setup(); } } /** @ignore yes */ string extra_look() { return "Marked on the map are " + query_multiple_short(_features->query_base_description() + keys(_locations)) + "."; } /** @ignore yes * Function to remove features that should not be shown on maps with * this level of detail. */ int filter_features(string feature) { #ifdef DEBUG debug_printf("%s %d %d", feature, feature->query_max_range() / TERRAIN_MAP_ONE_MILE, _detail / TERRAIN_MAP_ONE_MILE); #endif return (!feature->query_max_range() || feature->query_max_range() >= _detail); } /** * Function to setup the details of the map. * The first two params give the coordinates of the top left corner * of the map and the second two the coordinates of the lower right corner. * The detail indicates the level of detail. This is given in terms of the * distance from which objects are visible. For example a low-detail map * might show objects that are visible from 200 miles or more whereas a * more detailed map may show items down to 50 miles visibility. * * @param x1 x part of the top left corner * @param y1 y part of the top left corner * @param x2 x part of the lower right corner * @param y2 y part of the lower right corner */ void setup_map(int x1, int y1, int x2, int y2, int detail) { _area = ({ x1, y1, x2, y2 }); _detail = detail; _features = WORLD_MAP->query_features_in_region(x1, y1, x2, y2); _features = filter(_features, "filter_features", this_object()); } /** * Function to set the map to one of the standard areas. If you wish to * have the map cover a custom area use setup_map. * * @param area the area of Discworld the map should cover. */ void set_map(string area) { int width, height, detail, x1, y1, x2, y2; switch(area) { case "sur": width = (TERRAIN_MAP_ONE_MILE * 300); height = (TERRAIN_MAP_ONE_MILE * 200); x1 = -150575040 - width; y1 = -2173248 - height; x2 = -150575040 + width; y2 = -2173248 + height; detail = (TERRAIN_MAP_ONE_MILE * 50); break; case "world": x1 = TERRAIN_MAP_WORLD_LOW_X / 10; y1 = TERRAIN_MAP_WORLD_LOW_Y / 10; x2 = TERRAIN_MAP_WORLD_HIGH_X / 10; y2 = TERRAIN_MAP_WORLD_HIGH_Y / 10; detail = (TERRAIN_MAP_ONE_MILE * 200); break; } setup_map(x1, y1, x2, y2, detail); } /** @ignore yes * Recalc our current position. */ void recalc_coords() { int accuracy; if(!_co_ords || this_player() != _pl || environment(this_player()) != _env) { _pl = this_player(); _env = environment(_pl); _co_ords = _env->query_co_ord(); accuracy = 500 - _pl->query_skill_bonus("other.direction"); if(accuracy < 1) accuracy = 1; _fudge = TERRAIN_MAP_ONE_MILE * accuracy; // Where we _think_ we are. _co_ords[0] += -(_fudge/2) + random(_fudge); _co_ords[1] += -(_fudge/2) + random(_fudge); _co_ords[2] += -(_fudge/2) + random(_fudge); } } /** @ignore yes */ int do_consult(string find) { string feature, *res; object ob; mapping direcs; if(this_player()->check_dark(environment(this_player())->query_light())) return notify_fail("Sorry the light levels are not conducive to " "reading a map.\n"); recalc_coords(); if(_co_ords[0] < _area[0] || _co_ords[1] < _area[1] || _co_ords[0] > _area[2] || _co_ords[1] > _area[3]) return notify_fail("Sorry, you do not appear to be anywhere on this " "map.\n"); res = ({ }); foreach(feature in _features) { ob = feature->query_region_ob(); if(ob) { #ifdef DEBUG debug_printf("%O max range %d", feature, feature->query_max_range()/TERRAIN_MAP_ONE_MILE); #endif direcs = ob->query_feature_desc_from(_co_ords[0], _co_ords[1], _co_ords[2], 1); if(direcs) { if(find == "" || strsrch(lower_case(feature->query_base_description()), lower_case(find)) != -1) res += ({ feature->calc_map_feature_desc(direcs, _fudge) }); } } } if(res == ({ })) { if(find != "") return notify_fail("You cannot find " + find + " on your map.\n"); else return notify_fail("You cannot find anything on your map.\n"); } write("You consult your map and estimate that " + query_multiple_short(res) + "\n"); this_player()->add_succeeded_mess(this_object(), ""); return 1; } /** @ignore yes */ int do_add(string location) { if(member_array(lower_case(location), keys(_locations)) != -1) return notify_fail("A location with the name " + location + " already exists on this map.\n"); _locations[lower_case(location)] = _co_ords; this_player()->add_succeeded_mess(this_object(), "$N $V a new location " "to $D.\n"); return 1; } /** @ignore yes */ void init() { this_player()->add_command("consult", this_object(), "<direct:object>", (: do_consult("") :)); this_player()->add_command("find", this_object(), "<string'place'> on <direct:object>", (: do_consult($4[0]) :)); this_player()->add_command("add", this_object(), "<string'description'> to <direct:object>", (: do_add($4[0]) :)); } /** @ignore yes */ mapping int_query_static_auto_load() { return ([ "::": ::int_query_static_auto_load(), "features": _features, "detail": _detail, "area": _area, ]); } /** @ignore yes */ mixed query_static_auto_load() { if((file_name(this_object()))[0..7] != "/std/map" ) return 0; return int_query_static_auto_load(); } /** @ignore yes */ void init_static_arg(mapping args) { if(args["::"]) ::init_static_arg(args["::"]); if(args["features"]) _features = args["features"]; if(args["detail"]) _detail = args["detail"]; if(args["area"]) _area = args["area"]; }