<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" />
<title></title>
<style type=\"text/css\">
-#playerPosition { position: absolute; z-index: 2; font-size: 19pt; color: red; text-shadow: rgba(0, 0, 0, 1) 2px 2px 2px; }
+#playerPosition { position: absolute; z-index: 3; font-size: 19pt; color: red; text-shadow: rgba(0, 0, 0, 1) 2px 2px 2px; }
+img { z-index: 1; position: absolute; }
+.namedarea { position: absolute; z-index: 2; font-size: 16pt; text-shadow: black 0.1em 0.1em 0.2em; text-align: center; }
+.namedarea span { display: inline-block; vertical-align: middle; line-height: 1em; }
+.settlement { color: white; }
+.other { color: #cccccc; }
</style>
</head>
<body>
<div id=\"maps\">
{{maps}}
+{{areas}}
<div id=\"playerPosition\">x</div>
</div>
<map id="fields0" x="179" y="292" />
<map id="lodar19" x="343" y="373" />
<map id="wild14_clearing" x="318" y="433" />
- <map id="fallhaven_nw" x="210" y="390" />
+ <map id="fallhaven_nw" x="210" y="390" area="fallhaven" />
<map id="waterway12" x="458" y="228" />
<map id="waterway11" x="582" y="228" />
<map id="mountainlake10a" x="725" y="31" />
<map id="blackwater_mountain4" x="14" y="411" />
<map id="waterway15" x="412" y="197" />
<map id="waterway11_east" x="613" y="229" />
- <map id="fallhaven_ne" x="241" y="390" />
+ <map id="fallhaven_ne" x="241" y="390" area="fallhaven" />
<map id="waterway10" x="551" y="259" />
<map id="wild3" x="173" y="394" />
<map id="wild2" x="152" y="394" />
<map id="roadbeforecrossroads9" x="356" y="428" />
<map id="wild13" x="293" y="444" />
<map id="roadbeforecrossroads6" x="293" y="413" />
- <map id="flagstone0" x="95" y="477" />
+ <map id="flagstone0" x="95" y="477" area="flagstone" />
<map id="wild14" x="314" y="449" />
<map id="roadbeforecrossroads7" x="314" y="428" />
<map id="wild11" x="238" y="442" />
<map id="waytomountaincave0" x="628" y="255" />
<map id="waytomountaincave2" x="623" y="305" />
<map id="wild11_clearing" x="241" y="463" />
- <map id="fallhaven_sw" x="210" y="421" />
+ <map id="fallhaven_sw" x="210" y="421" area="fallhaven" />
<map id="waterwayextention" x="343" y="189" />
<map id="mountainlake3" x="757" y="128" />
<map id="waytominingtown0" x="314" y="412" />
<map id="gapfiller1" x="259" y="442" />
<map id="lostmine0" x="426" y="369" />
<map id="gapfiller3" x="179" y="383" />
- <map id="fallhaven_se" x="241" y="421" />
+ <map id="fallhaven_se" x="241" y="421" area="fallhaven" />
<map id="gapfiller4" x="194" y="390" />
<map id="fields10" x="96" y="292" />
<map id="waytolake0" x="650" y="266" />
<map id="fields11" x="238" y="226" />
<map id="fields12" x="259" y="222" />
- <map id="vilegard_n" x="360" y="479" />
+ <map id="vilegard_n" x="360" y="479" area="vilegard" />
<map id="waytolostmine0" x="395" y="355" />
<map id="roadbeforecrossroads1" x="232" y="330" />
<map id="waytolake3" x="673" y="208" />
- <map id="vilegard_s" x="360" y="500" />
+ <map id="vilegard_s" x="360" y="500" area="vilegard" />
<map id="waytolake1" x="671" y="255" />
<map id="waytolake2" x="671" y="229" />
<map id="waytolostmine2" x="426" y="309" />
<map id="mountainlake12" x="672" y="8" />
<map id="mountainlake11" x="702" y="4" />
<map id="mountainlake10" x="733" y="0" />
- <map id="loneford2" x="238" y="259" />
+ <map id="loneford2" x="238" y="259" area="loneford" />
<map id="loneford1" x="210" y="286" />
- <map id="crossglen" x="148" y="363" />
- <map id="remgard1" x="674" y="83" />
- <map id="remgard0" x="643" y="76" />
- <map id="remgard3" x="653" y="107" />
- <map id="remgard2" x="674" y="114" />
- <map id="remgard4" x="622" y="107" />
- <map id="road1" x="356" y="453" />
- <map id="crossroads" x="179" y="308" />
+ <map id="crossglen" x="148" y="363" area="crossglen" />
+ <map id="remgard1" x="674" y="83" area="remgard" />
+ <map id="remgard0" x="643" y="76" area="remgard" />
+ <map id="remgard3" x="653" y="107" area="remgard" />
+ <map id="remgard2" x="674" y="114" area="remgard" />
+ <map id="remgard4" x="622" y="107" area="remgard" />
+ <map id="road1" x="356" y="453" area="fflask" />
+ <map id="crossroads" x="179" y="308" area="crossroads" />
<map id="road3" x="403" y="467" />
<map id="road2" x="382" y="463" />
<map id="road5" x="455" y="470" />
<map id="road4" x="429" y="462" />
+ <namedarea id="crossglen" name="Crossglen" type="settlement"/>
+ <namedarea id="loneford" name="Loneford" type="settlement"/>
+ <namedarea id="flagstone" name="Flagstone Prison" type="other"/>
+ <namedarea id="fallhaven" name="Fallhaven" type="settlement"/>
+ <namedarea id="fflask" name="Fomaing Flask Tavern" type="other"/>
+ <namedarea id="crossroads" name="Crossroads Guardhouse" type="other"/>
+ <namedarea id="remgard" name="Remgard" type="settlement"/>
+ <namedarea id="vilegard" name="Vilegard" type="settlement"/>
</segment>
<segment id="blackwater" x="10" y="214">
<map id="blackwater_mountain15" x="81" y="302" />
<map id="blackwater_mountain40" x="77" y="354" />
<map id="blackwater_mountain32" x="128" y="214" />
<map id="blackwater_mountain14" x="60" y="333" />
- <map id="blackwater_mountain11" x="39" y="302" />
+ <map id="blackwater_mountain11" x="39" y="302" area="prim" />
<map id="blackwater_mountain30" x="130" y="245" />
<map id="blackwater_mountain12" x="10" y="323" />
<map id="blackwater_mountain10" x="39" y="333" />
+ <namedarea id="prim" name="Prim" type="settlement"/>
</segment>
<segment id="pwcave" x="288" y="42">
<map id="pwcave4" x="319" y="99" />
public static final boolean DEVELOPMENT_DEBUGRESOURCES = false;\r
public static final boolean DEVELOPMENT_FORCE_STARTNEWGAME = false;\r
public static final boolean DEVELOPMENT_FORCE_CONTINUEGAME = false;\r
- public static final boolean DEVELOPMENT_DEBUGBUTTONS = false;\r
+ public static final boolean DEVELOPMENT_DEBUGBUTTONS = true;\r
public static final boolean DEVELOPMENT_VALIDATEDATA = false;\r
public static final boolean DEVELOPMENT_DEBUGMESSAGES = false;\r
public static final boolean DEVELOPMENT_INCOMPATIBLE_SAVEGAMES = DEVELOPMENT_DEBUGRESOURCES;\r
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.HashSet;
import android.content.Context;
import android.content.Intent;
import com.gpl.rpg.AndorsTrail.model.map.MapLayer;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment;
+import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.NamedWorldMapArea;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.WorldMapSegmentMap;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
import com.gpl.rpg.AndorsTrail.util.Coord;
+import com.gpl.rpg.AndorsTrail.util.CoordRect;
import com.gpl.rpg.AndorsTrail.util.L;
+import com.gpl.rpg.AndorsTrail.util.Size;
public final class WorldMapController {
return new File(getWorldmapDirectory(), Constants.FILENAME_WORLDMAP_HTMLFILE_PREFIX + segmentName + Constants.FILENAME_WORLDMAP_HTMLFILE_SUFFIX);
}
+ private static boolean shouldDisplayMapOnWorldmap(String mapName) {
+ File f = WorldMapController.getFileForMap(mapName);
+ return f.exists();
+ }
private static String getWorldMapSegmentAsHtml(Resources res, WorldContext world, String segmentName) throws IOException {
WorldMapSegment segment = world.maps.worldMapSegments.get(segmentName);
- StringBuffer sb = new StringBuffer();
-
+ HashSet<String> displayedMapNames = new HashSet<String>();
Coord offsetWorldmapTo = new Coord(999999, 999999);
for (WorldMapSegmentMap map : segment.maps.values()) {
- File f = WorldMapController.getFileForMap(map.mapName);
- if (!f.exists()) continue;
+ if (!shouldDisplayMapOnWorldmap(map.mapName)) continue;
+ displayedMapNames.add(map.mapName);
offsetWorldmapTo.x = Math.min(offsetWorldmapTo.x, map.worldPosition.x);
offsetWorldmapTo.y = Math.min(offsetWorldmapTo.y, map.worldPosition.y);
}
+ StringBuffer mapsAsHtml = new StringBuffer();
for (WorldMapSegmentMap segmentMap : segment.maps.values()) {
File f = WorldMapController.getFileForMap(segmentMap.mapName);
if (!f.exists()) continue;
- PredefinedMap map = world.maps.findPredefinedMap(segmentMap.mapName);
-
- sb
+ Size size = getMapSize(segmentMap, world);
+ mapsAsHtml
.append("<img src=\"")
.append(f.getName())
.append("\" id=\"")
- .append(map.name)
- .append("\" style=\"width: ")
- .append(map.size.width * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
- .append("px; height: ")
- .append(map.size.height * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
- .append("px; position: absolute; left: ")
+ .append(segmentMap.mapName)
+ .append("\" style=\"width:")
+ .append(size.width * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
+ .append("px; height:")
+ .append(size.height * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
+ .append("px; left:")
.append((segmentMap.worldPosition.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
- .append("px; top: ")
+ .append("px; top:")
.append((segmentMap.worldPosition.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px;\" />");
+ if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) mapsAsHtml.append("\n");
+ }
+
+ StringBuffer namedAreasAsHtml = new StringBuffer();
+ for (NamedWorldMapArea area : segment.namedAreas.values()) {
+ CoordRect r = determineNamedAreaBoundary(area, segment, world, displayedMapNames);
+ if (r == null) continue;
+ namedAreasAsHtml
+ .append("<div class=\"namedarea ")
+ .append(area.type)
+ .append("\" style=\"width:")
+ .append(r.size.width * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
+ .append("px; line-height:")
+ .append(r.size.height * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
+ .append("px; left:")
+ .append((r.topLeft.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
+ .append("px; top:")
+ .append((r.topLeft.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
+ .append("px;\"><span>")
+ .append(area.name)
+ .append("</span></div>");
+ if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) namedAreasAsHtml.append("\n");
}
return res.getString(R.string.worldmap_template)
- .replace("{{maps}}", sb.toString())
+ .replace("{{maps}}", mapsAsHtml.toString())
+ .replace("{{areas}}", namedAreasAsHtml.toString())
.replace("{{offsetx}}", Integer.toString(offsetWorldmapTo.x * WorldMapController.WORLDMAP_DISPLAY_TILESIZE))
.replace("{{offsety}}", Integer.toString(offsetWorldmapTo.y * WorldMapController.WORLDMAP_DISPLAY_TILESIZE));
}
+ private static Size getMapSize(WorldMapSegmentMap map, WorldContext world) {
+ return world.maps.findPredefinedMap(map.mapName).size;
+ }
+
+ private static CoordRect determineNamedAreaBoundary(NamedWorldMapArea area, WorldMapSegment segment, WorldContext world, HashSet<String> displayedMapNames) {
+ Coord topLeft = null;
+ Coord bottomRight = null;
+
+ for (String mapName : area.mapNames) {
+ if (!displayedMapNames.contains(mapName)) continue;
+ WorldMapSegmentMap map = segment.maps.get(mapName);
+ Size size = getMapSize(map, world);
+ if (topLeft == null) {
+ topLeft = new Coord(map.worldPosition);
+ } else {
+ topLeft.x = Math.min(topLeft.x, map.worldPosition.x);
+ topLeft.y = Math.min(topLeft.y, map.worldPosition.y);
+ }
+ if (bottomRight == null) {
+ bottomRight = new Coord(map.worldPosition.x + size.width, map.worldPosition.y + size.height);
+ } else {
+ bottomRight.x = Math.max(bottomRight.x, map.worldPosition.x + size.width);
+ bottomRight.y = Math.max(bottomRight.y, map.worldPosition.y + size.height);
+ }
+ }
+ if (topLeft == null) return null;
+ return new CoordRect(topLeft, new Size(bottomRight.x - topLeft.x, bottomRight.y - topLeft.y));
+ }
+
private static void updateWorldMapSegment(Resources res, WorldContext world, String segmentName) throws IOException {
String mapAsHtml = getWorldMapSegmentAsHtml(res, world, segmentName);
File outputFile = getCombinedWorldMapFile(segmentName);
package com.gpl.rpg.AndorsTrail.model.map;
import java.util.HashMap;
+import java.util.HashSet;
import com.gpl.rpg.AndorsTrail.util.Coord;
public final class WorldMapSegment {
public final String name;
public final HashMap<String, WorldMapSegmentMap> maps = new HashMap<String, WorldMapSegmentMap>();
+ public final HashMap<String, NamedWorldMapArea> namedAreas = new HashMap<String, NamedWorldMapArea>();
public WorldMapSegment(String name) {
this.name = name;
this.worldPosition = worldPosition;
}
}
+
+ // Towns, cities, villages, taverns, named dungeons
+ public static final class NamedWorldMapArea {
+ public final String id;
+ public final String name;
+ public final String type; // "settlement" or "other"
+ public final HashSet<String> mapNames = new HashSet<String>();
+ public NamedWorldMapArea(String id, String name, String type) {
+ this.id = id;
+ this.name = name;
+ this.type = type;
+ }
+ }
}
package com.gpl.rpg.AndorsTrail.resource.parsers;
import java.io.IOException;
+import java.util.ArrayList;
import org.xmlpull.v1.XmlPullParserException;
import com.gpl.rpg.AndorsTrail.model.map.MapCollection;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment;
+import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.NamedWorldMapArea;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.WorldMapSegmentMap;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.L;
+import com.gpl.rpg.AndorsTrail.util.Pair;
import com.gpl.rpg.AndorsTrail.util.XmlResourceParserUtils;
public final class WorldMapParser {
String segmentName = xrp.getAttributeValue(null, "id");
final WorldMapSegment segment = new WorldMapSegment(segmentName);
+ final ArrayList<Pair<String, String>> mapsInNamedAreas = new ArrayList<Pair<String,String>>();
XmlResourceParserUtils.readCurrentTagUntilEnd(xrp, new XmlResourceParserUtils.TagHandler() {
@Override
public void handleTag(XmlResourceParser xrp, String tagName) throws XmlPullParserException, IOException {
);
WorldMapSegmentMap map = new WorldMapSegmentMap(mapName, mapPosition);
segment.maps.put(mapName, map);
+
+ String namedArea = xrp.getAttributeValue(null, "area");
+ if (namedArea != null) mapsInNamedAreas.add(new Pair<String, String>(mapName, namedArea));
+ } else if (tagName.equals("namedarea")) {
+ String id = xrp.getAttributeValue(null, "id");
+ String name = xrp.getAttributeValue(null, "name");
+ String type = xrp.getAttributeValue(null, "type");
+ segment.namedAreas.put(id, new NamedWorldMapArea(id, name, type));
}
}
});
+ for (Pair<String, String> m : mapsInNamedAreas) {
+ segment.namedAreas.get(m.second).mapNames.add(m.first);
+ }
+
return segment;
}