diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java index 2759de0bb..117c5e188 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java @@ -52,21 +52,23 @@ public final class MonsterMovementController implements EvaluateWalkable { } } - public static boolean monsterCanMoveTo(final Monster movingMonster, final PredefinedMap map, final LayeredTileMap tilemap, final CoordRect p) { + public static boolean monsterCanMoveTo(final Monster movingMonster, final PredefinedMap map, final LayeredTileMap tilemap, final CoordRect p, boolean ignoreAreas) { if (tilemap != null) { if (!tilemap.isWalkable(p)) return false; } if (map.getMonsterAt(p, movingMonster) != null) return false; - for (MapObject mObj : map.eventObjects) { - if (mObj == null) continue; - if (!mObj.isActive) continue; - if (!mObj.position.intersects(p)) continue; - switch (mObj.type) { + if (!ignoreAreas) { + for (MapObject mObj : map.eventObjects) { + if (mObj == null) continue; + if (!mObj.isActive) continue; + if (!mObj.position.intersects(p)) continue; + switch (mObj.type) { case newmap: case keyarea: case rest: return false; + } } } return true; @@ -82,7 +84,7 @@ public final class MonsterMovementController implements EvaluateWalkable { } else { determineMonsterNextPosition(m, area, world.model.player.position); - if (!monsterCanMoveTo(m, map, tileMap, m.nextPosition)) { + if (!monsterCanMoveTo(m, map, tileMap, m.nextPosition, area.ignoreAreas)) { cancelCurrentMonsterMovement(m); return; } @@ -152,12 +154,12 @@ public final class MonsterMovementController implements EvaluateWalkable { private final PathFinder pathfinder = new PathFinder(Constants.MAX_MAP_WIDTH, Constants.MAX_MAP_HEIGHT, this); public boolean findPathFor(Monster m, Coord to) { - return pathfinder.findPathBetween(m.rectPosition, to, m.nextPosition); + return pathfinder.findPathBetween(m.rectPosition, to, m.nextPosition, m); } @Override - public boolean isWalkable(CoordRect r) { - return monsterCanMoveTo(null, world.model.currentMap, world.model.currentTileMap, r); + public boolean isWalkable(CoordRect r, Monster m) { + return monsterCanMoveTo(null, world.model.currentMap, world.model.currentTileMap, r, m.area.ignoreAreas); } public void moveMonsterToNextPosition(final Monster m, final PredefinedMap map) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterSpawningController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterSpawningController.java index 830c0437e..969bab4e1 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterSpawningController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterSpawningController.java @@ -51,20 +51,20 @@ public final class MonsterSpawningController { } public boolean TEST_spawnInArea(PredefinedMap map, LayeredTileMap tileMap, MonsterSpawnArea a, MonsterType type) { return spawnInArea(map, tileMap, a, type, null); } private boolean spawnInArea(PredefinedMap map, LayeredTileMap tileMap, MonsterSpawnArea a, MonsterType type, Coord playerPosition) { - Coord p = getRandomFreePosition(map, tileMap, a.area, type.tileSize, playerPosition); + Coord p = getRandomFreePosition(map, tileMap, a, type.tileSize, playerPosition); if (p == null) return false; Monster m = a.spawn(p, type); monsterSpawnListeners.onMonsterSpawned(map, m); return true; } - public static Coord getRandomFreePosition(PredefinedMap map, LayeredTileMap tileMap, CoordRect area, Size requiredSize, Coord playerPosition) { + public static Coord getRandomFreePosition(PredefinedMap map, LayeredTileMap tileMap, MonsterSpawnArea a, Size requiredSize, Coord playerPosition) { CoordRect p = new CoordRect(requiredSize); for(int i = 0; i < 100; ++i) { p.topLeft.set( - area.topLeft.x + Constants.rnd.nextInt(area.size.width) - ,area.topLeft.y + Constants.rnd.nextInt(area.size.height)); - if (!MonsterMovementController.monsterCanMoveTo(null, map, tileMap, p)) continue; + a.area.topLeft.x + Constants.rnd.nextInt(a.area.size.width) + ,a.area.topLeft.y + Constants.rnd.nextInt(a.area.size.height)); + if (!MonsterMovementController.monsterCanMoveTo(null, map, tileMap, p, a.ignoreAreas)) continue; if (playerPosition != null && p.contains(playerPosition)) continue; return p.topLeft; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java index 40936ef55..a67c2a1b3 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java @@ -283,7 +283,7 @@ public final class MovementController implements TimedMessageTask.Callback { for (MonsterSpawnArea a : map.spawnAreas) { for (Monster m : a.monsters) { if (tileMap.isWalkable(m.rectPosition)) continue; - Coord p = MonsterSpawningController.getRandomFreePosition(map, tileMap, a.area, m.tileSize, playerPosition); + Coord p = MonsterSpawningController.getRandomFreePosition(map, tileMap, a, m.tileSize, playerPosition); if (p == null) continue; m.position.set(p); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/PathFinder.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/PathFinder.java index 94d551756..98ad9bd49 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/PathFinder.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/PathFinder.java @@ -1,5 +1,6 @@ package com.gpl.rpg.AndorsTrail.controller; +import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.util.Coord; import com.gpl.rpg.AndorsTrail.util.CoordRect; @@ -21,10 +22,10 @@ public class PathFinder { } public interface EvaluateWalkable { - public boolean isWalkable(CoordRect r); + public boolean isWalkable(CoordRect r, Monster m); } - public boolean findPathBetween(final CoordRect from, final Coord to, CoordRect nextStep) { + public boolean findPathBetween(final CoordRect from, final Coord to, CoordRect nextStep, Monster m) { int iterations = 0; if (from.contains(to)) return false; @@ -44,19 +45,19 @@ public class PathFinder { if (from.isAdjacentTo(p)) return true; - p.x -= 1; visit(nextStep, measureDistanceTo); - p.x += 2; visit(nextStep, measureDistanceTo); - p.x -= 1; p.y -= 1; visit(nextStep, measureDistanceTo); - p.y += 2; visit(nextStep, measureDistanceTo); - p.x -= 1; visit(nextStep, measureDistanceTo); - p.x += 2; visit(nextStep, measureDistanceTo); - p.y -= 2; visit(nextStep, measureDistanceTo); - p.x -= 2; visit(nextStep, measureDistanceTo); + p.x -= 1; visit(nextStep, measureDistanceTo, m); + p.x += 2; visit(nextStep, measureDistanceTo, m); + p.x -= 1; p.y -= 1; visit(nextStep, measureDistanceTo, m); + p.y += 2; visit(nextStep, measureDistanceTo, m); + p.x -= 1; visit(nextStep, measureDistanceTo, m); + p.x += 2; visit(nextStep, measureDistanceTo, m); + p.y -= 2; visit(nextStep, measureDistanceTo, m); + p.x -= 2; visit(nextStep, measureDistanceTo, m); } return false; } - private void visit(CoordRect r, Coord measureDistanceTo) { + private void visit(CoordRect r, Coord measureDistanceTo, Monster m) { final int x = r.topLeft.x; final int y = r.topLeft.y; @@ -68,7 +69,7 @@ public class PathFinder { final int i = (y * maxWidth) + x; if (visited[i]) return; visited[i] = true; - if (!map.isWalkable(r)) return; + if (!map.isWalkable(r, m)) return; int dx = (measureDistanceTo.x - x); int dy = (measureDistanceTo.y - y); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Monster.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Monster.java index 39d549671..b69170768 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Monster.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Monster.java @@ -6,6 +6,7 @@ import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection; import com.gpl.rpg.AndorsTrail.model.item.DropList; import com.gpl.rpg.AndorsTrail.model.item.ItemContainer; import com.gpl.rpg.AndorsTrail.model.item.Loot; +import com.gpl.rpg.AndorsTrail.model.map.MonsterSpawnArea; import com.gpl.rpg.AndorsTrail.savegames.LegacySavegameFormatReaderForMonster; import com.gpl.rpg.AndorsTrail.util.Coord; import com.gpl.rpg.AndorsTrail.util.CoordRect; @@ -25,10 +26,12 @@ public final class Monster extends Actor { private ItemContainer shopItems = null; private final MonsterType monsterType; + public final MonsterSpawnArea area; - public Monster(MonsterType monsterType) { + public Monster(MonsterType monsterType, MonsterSpawnArea area) { super(monsterType.tileSize, false, monsterType.isImmuneToCriticalHits()); this.monsterType = monsterType; + this.area = area; this.iconID = monsterType.iconID; this.nextPosition = new CoordRect(new Coord(), monsterType.tileSize); resetStatsToBaseTraits(); @@ -95,20 +98,20 @@ public final class Monster extends Actor { // ====== PARCELABLE =================================================================== - public static Monster newFromParcel(DataInputStream src, WorldContext world, int fileversion) throws IOException { + public static Monster newFromParcel(DataInputStream src, WorldContext world, int fileversion, MonsterSpawnArea area) throws IOException { String monsterTypeId = src.readUTF(); if (fileversion < 20) { monsterTypeId = monsterTypeId.replace(' ', '_').replace("\\'", "").toLowerCase(); } MonsterType monsterType = world.monsterTypes.getMonsterType(monsterTypeId); - if (fileversion < 25) return LegacySavegameFormatReaderForMonster.newFromParcel_pre_v25(src, fileversion, monsterType); + if (fileversion < 25) return LegacySavegameFormatReaderForMonster.newFromParcel_pre_v25(src, fileversion, monsterType, area); - return new Monster(src, world, fileversion, monsterType); + return new Monster(src, world, fileversion, monsterType, area); } - private Monster(DataInputStream src, WorldContext world, int fileversion, MonsterType monsterType) throws IOException { - this(monsterType); + private Monster(DataInputStream src, WorldContext world, int fileversion, MonsterType monsterType, MonsterSpawnArea area) throws IOException { + this(monsterType, area); boolean readCombatTraits = true; if (fileversion >= 25) readCombatTraits = src.readBoolean(); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MonsterSpawnArea.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MonsterSpawnArea.java index cbde9931b..7279bb45d 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MonsterSpawnArea.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MonsterSpawnArea.java @@ -21,6 +21,7 @@ public final class MonsterSpawnArea { public final String[] monsterTypeIDs; public final ArrayList monsters = new ArrayList(); public final boolean isUnique; // unique == non-respawnable + public final boolean ignoreAreas; //Can spawn on other game objects area. private final String group; public boolean isSpawning; public final boolean isSpawningForNewGame; @@ -32,6 +33,7 @@ public final class MonsterSpawnArea { , String areaID , String[] monsterTypeIDs , boolean isUnique + , boolean ignoreAreas , String group , boolean isSpawningForNewGame ) { @@ -41,6 +43,7 @@ public final class MonsterSpawnArea { this.areaID = areaID; this.monsterTypeIDs = monsterTypeIDs; this.isUnique = isUnique; + this.ignoreAreas = ignoreAreas; this.group = group; this.isSpawningForNewGame = isSpawningForNewGame; this.isSpawning = isSpawningForNewGame; @@ -79,7 +82,7 @@ public final class MonsterSpawnArea { spawn(p, context.monsterTypes.getMonsterType(monsterTypeID)); } public Monster spawn(Coord p, MonsterType type) { - Monster m = new Monster(type); + Monster m = new Monster(type, this); m.position.set(p); monsters.add(m); quantity.current++; @@ -125,7 +128,7 @@ public final class MonsterSpawnArea { if (fileversion >= 41) isSpawning = src.readBoolean(); quantity.current = src.readInt(); for(int i = 0; i < quantity.current; ++i) { - monsters.add(Monster.newFromParcel(src, world, fileversion)); + monsters.add(Monster.newFromParcel(src, world, fileversion, this)); } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java index aed27b394..6f412aed4 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java @@ -92,6 +92,7 @@ public final class TMXMapTranslator { mapObjects.add(MapObject.createMapChangeArea(position, object.name, map, place, group.name)); } else if (object.type.equalsIgnoreCase("spawn")) { boolean isActiveForNewGame = true; + boolean ignoreAreas = false; int maxQuantity = 1; int spawnChance = 10; String spawnGroup = object.name; @@ -108,6 +109,8 @@ public final class TMXMapTranslator { spawnChance = Integer.parseInt(p.value); } else if (p.name.equalsIgnoreCase("active")) { isActiveForNewGame = Boolean.parseBoolean(p.value); + } else if (p.name.equalsIgnoreCase("ignoreAreas")) { + ignoreAreas = Boolean.parseBoolean(p.value); } else if (p.name.equalsIgnoreCase("spawngroup")) { spawnGroup = p.value; } else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { @@ -135,6 +138,7 @@ public final class TMXMapTranslator { ,object.name ,monsterTypeIDs ,isUnique + ,ignoreAreas ,group.name ,isActiveForNewGame ); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForMonster.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForMonster.java index 2e34a8c4d..2b88477f8 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForMonster.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForMonster.java @@ -2,14 +2,15 @@ package com.gpl.rpg.AndorsTrail.savegames; import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.model.actor.MonsterType; +import com.gpl.rpg.AndorsTrail.model.map.MonsterSpawnArea; import com.gpl.rpg.AndorsTrail.util.Coord; import java.io.DataInputStream; import java.io.IOException; public final class LegacySavegameFormatReaderForMonster { - public static Monster newFromParcel_pre_v25(DataInputStream src, int fileversion, MonsterType monsterType) throws IOException { - Monster m = new Monster(monsterType); + public static Monster newFromParcel_pre_v25(DataInputStream src, int fileversion, MonsterType monsterType, MonsterSpawnArea area) throws IOException { + Monster m = new Monster(monsterType, area); m.position.set(new Coord(src, fileversion)); m.ap.current = src.readInt(); m.health.current = src.readInt();