mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-14 09:48:02 +00:00
Adventure - Pathfinding update (#3675)
* Adventure - reward scene controller button availability * Adventure A* & main quest prep * Update pom.xml * box2d natives --------- Co-authored-by: kevlahnota <anthonycalosa@gmail.com>
This commit is contained in:
BIN
forge-gui-android/libs/arm64-v8a/libgdx-box2d.so
Normal file
BIN
forge-gui-android/libs/arm64-v8a/libgdx-box2d.so
Normal file
Binary file not shown.
BIN
forge-gui-android/libs/armeabi-v7a/libgdx-box2d.so
Normal file
BIN
forge-gui-android/libs/armeabi-v7a/libgdx-box2d.so
Normal file
Binary file not shown.
BIN
forge-gui-android/libs/x86/libgdx-box2d.so
Normal file
BIN
forge-gui-android/libs/x86/libgdx-box2d.so
Normal file
Binary file not shown.
BIN
forge-gui-android/libs/x86_64/libgdx-box2d.so
Normal file
BIN
forge-gui-android/libs/x86_64/libgdx-box2d.so
Normal file
Binary file not shown.
BIN
forge-gui-mobile-dev/libs/gdx-box2d-platform-natives.jar
Normal file
BIN
forge-gui-mobile-dev/libs/gdx-box2d-platform-natives.jar
Normal file
Binary file not shown.
@@ -256,5 +256,11 @@
|
||||
<artifactId>gdx-controllers-desktop</artifactId>
|
||||
<version>2.2.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.badlogicgames.gdx</groupId>
|
||||
<artifactId>gdx-box2d-platform</artifactId>
|
||||
<version>1.11.0</version>
|
||||
<classifier>natives-desktop</classifier>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -80,6 +80,16 @@
|
||||
<version>5.2.3</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.badlogicgames.gdx</groupId>
|
||||
<artifactId>gdx-box2d</artifactId>
|
||||
<version>1.11.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.badlogicgames.gdx</groupId>
|
||||
<artifactId>gdx-ai</artifactId>
|
||||
<version>1.8.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package forge.adventure.character;
|
||||
|
||||
import com.badlogic.gdx.ai.steer.Steerable;
|
||||
import com.badlogic.gdx.ai.steer.SteeringAcceleration;
|
||||
import com.badlogic.gdx.ai.steer.SteeringBehavior;
|
||||
import com.badlogic.gdx.ai.steer.behaviors.*;
|
||||
import com.badlogic.gdx.ai.steer.utils.paths.LinePath;
|
||||
import com.badlogic.gdx.ai.utils.Location;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
@@ -16,12 +22,16 @@ import forge.adventure.player.AdventurePlayer;
|
||||
import forge.adventure.util.Current;
|
||||
import forge.adventure.util.MapDialog;
|
||||
import forge.adventure.util.Reward;
|
||||
import forge.adventure.util.pathfinding.MovementBehavior;
|
||||
import forge.adventure.util.pathfinding.NavigationVertex;
|
||||
import forge.adventure.util.pathfinding.ProgressableGraphPath;
|
||||
import forge.card.CardRarity;
|
||||
import forge.deck.Deck;
|
||||
import forge.item.PaperCard;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -30,7 +40,20 @@ import java.util.stream.Collectors;
|
||||
* EnemySprite
|
||||
* Character sprite that represents an Enemy
|
||||
*/
|
||||
public class EnemySprite extends CharacterSprite {
|
||||
public class EnemySprite extends CharacterSprite implements Steerable<Vector2> {
|
||||
|
||||
private static final SteeringAcceleration<Vector2> steerOutput =
|
||||
new SteeringAcceleration<Vector2>(new Vector2());
|
||||
|
||||
Vector2 position;
|
||||
float orientation;
|
||||
Vector2 linearVelocity = new Vector2(1, 0);
|
||||
float angularVelocity;
|
||||
float maxSpeed;
|
||||
boolean independentFacing;
|
||||
SteeringBehavior<Vector2> behavior;
|
||||
boolean tagged;
|
||||
|
||||
EnemyData data;
|
||||
public MapDialog dialog; //Dialog to show on contact. Overrides standard battle (can be started as an action)
|
||||
public MapDialog defeatDialog; //Dialog to show on defeat. Overrides standard death (can be removed as an action)
|
||||
@@ -53,9 +76,12 @@ public class EnemySprite extends CharacterSprite {
|
||||
public float threatRange = 0.0f; //If range < threatRange, begin pursuit
|
||||
public float pursueRange = 0.0f; //If range > pursueRange, abandon pursuit
|
||||
public float fleeRange = 0.0f; //If range < fleeRange, attempt to move away to fleeRange
|
||||
private boolean aggro = false;
|
||||
public float speedModifier = 0.0f; // Increase or decrease default speed
|
||||
public boolean aggro = false;
|
||||
public boolean ignoreDungeonEffect = false;
|
||||
public String questStageID;
|
||||
private ProgressableGraphPath<NavigationVertex> navPath;
|
||||
public Vector2 fleeTarget;
|
||||
|
||||
public EnemySprite(EnemyData enemyData) {
|
||||
this(0,enemyData);
|
||||
@@ -64,16 +90,19 @@ public class EnemySprite extends CharacterSprite {
|
||||
public EnemySprite(int id, EnemyData enemyData) {
|
||||
super(id,enemyData.sprite);
|
||||
data = enemyData;
|
||||
initializeBaseMovementBehavior();
|
||||
}
|
||||
|
||||
public void parseWaypoints(String waypoints){
|
||||
String[] wp = waypoints.replaceAll("\\s", "").split(",");
|
||||
for (String s : wp) {
|
||||
movementBehaviors.addLast(new MovementBehavior());
|
||||
if (s.startsWith("wait")) {
|
||||
movementBehaviors.peekLast().duration = Float.parseFloat(s.substring(4));
|
||||
} else {
|
||||
movementBehaviors.peekLast().destination = Integer.parseInt(s);
|
||||
if (!movementBehaviors.isEmpty()) {
|
||||
if (s.startsWith("wait")) {
|
||||
movementBehaviors.peekLast().duration = Float.parseFloat(s.substring(4));
|
||||
} else {
|
||||
movementBehaviors.peekLast().destination = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,7 +112,13 @@ public class EnemySprite extends CharacterSprite {
|
||||
float scale = data == null ? 1f : data.scale;
|
||||
if (scale < 0)
|
||||
scale = 1f;
|
||||
boundingRect.set(getX(), getY(), getWidth()*scale, getHeight()*scale);
|
||||
|
||||
float width = getWidth()*scale* collisionHeight;
|
||||
float height = getHeight()*scale* collisionHeight;
|
||||
float x = getX() + (getWidth() - width)/2;
|
||||
float y = getY() + (getHeight() - height)/2;
|
||||
|
||||
boundingRect.set(x, y, width, height);
|
||||
unfreezeRange = 30f * scale;
|
||||
}
|
||||
|
||||
@@ -94,6 +129,183 @@ public class EnemySprite extends CharacterSprite {
|
||||
moveBy(diff.x, diff.y,delta);
|
||||
}
|
||||
|
||||
public void initializeBaseMovementBehavior() {
|
||||
Location<Vector2> seekTarget = new Location<Vector2>() {
|
||||
@Override
|
||||
public Vector2 getPosition() {
|
||||
return navPath.nodes.get(0).pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getOrientation() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(float orientation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float vectorToAngle(Vector2 vector) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2 angleToVector(Vector2 outVector, float angle) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location<Vector2> newLocation() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Seek<Vector2> seek = new Seek<>(this);
|
||||
seek.setTarget(seekTarget);
|
||||
|
||||
Array<Vector2> wp = new Array<>();
|
||||
if (navPath != null && navPath.nodes != null) {
|
||||
for (NavigationVertex v : navPath.nodes)
|
||||
wp.add(v.pos);
|
||||
}
|
||||
LinePath<Vector2> linePath = null;
|
||||
FollowPath<Vector2, LinePath.LinePathParam> followWaypoints = null;
|
||||
if (wp.size == 1) {
|
||||
wp.insert(0, pos());
|
||||
}
|
||||
if (wp.size >= 2) {
|
||||
linePath = new LinePath<Vector2>(wp, false);
|
||||
followWaypoints = new FollowPath<>(this, linePath);
|
||||
followWaypoints.setPathOffset(0.5f);
|
||||
}
|
||||
|
||||
Arrive<Vector2> moveDirectlyToDestination = new Arrive<>(this, new Location<Vector2>() {
|
||||
@Override
|
||||
public Vector2 getPosition() {
|
||||
if (navPath == null || navPath.nodes.size == 0)
|
||||
return pos();
|
||||
return navPath.get(0).pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getOrientation() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(float orientation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float vectorToAngle(Vector2 vector) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2 angleToVector(Vector2 outVector, float angle) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location<Vector2> newLocation() {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.setTimeToTarget(0.01f)
|
||||
.setArrivalTolerance(0f)
|
||||
.setDecelerationRadius(10);
|
||||
|
||||
if (followWaypoints != null)
|
||||
setBehavior(followWaypoints);
|
||||
else
|
||||
setBehavior(moveDirectlyToDestination);
|
||||
}
|
||||
|
||||
public void setBehavior(SteeringBehavior<Vector2> behavior) {
|
||||
this.behavior = behavior;
|
||||
}
|
||||
|
||||
public SteeringBehavior<Vector2> getBehavior() {
|
||||
return behavior;
|
||||
}
|
||||
|
||||
public void update(float delta) {
|
||||
if(behavior != null) {
|
||||
behavior.calculateSteering(steerOutput);
|
||||
while (steerOutput.isZero() && navPath != null && navPath.getCount() > 1) {
|
||||
navPath.remove(0);
|
||||
behavior.calculateSteering(steerOutput);
|
||||
}
|
||||
applySteering(delta);
|
||||
}
|
||||
}
|
||||
|
||||
private void applySteering(float delta) {
|
||||
if(!steerOutput.linear.isZero()) {
|
||||
Vector2 force = steerOutput.linear.scl(delta);
|
||||
force.setLength(Math.min(speed() * delta, force.len()));
|
||||
moveBy(force.x, force.y);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float vectorToAngle (Vector2 vector) {
|
||||
return (float)Math.atan2(-vector.x, vector.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2 angleToVector (Vector2 outVector, float angle) {
|
||||
outVector.x = -(float)Math.sin(angle);
|
||||
outVector.y = (float)Math.cos(angle);
|
||||
return outVector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2 getLinearVelocity() {
|
||||
return linearVelocity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getAngularVelocity() {
|
||||
return angularVelocity;
|
||||
}
|
||||
@Override
|
||||
public float getBoundingRadius() {
|
||||
return getWidth()/2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTagged() {
|
||||
return tagged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2 getPosition() {
|
||||
return pos();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getOrientation() {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation(float value) {
|
||||
orientation = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location<Vector2> newLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTagged(boolean value) {
|
||||
tagged = value;
|
||||
}
|
||||
|
||||
public void freezeMovement(){
|
||||
_freeze = true;
|
||||
setPosition(_previousPosition6.x, _previousPosition6.y);
|
||||
@@ -102,15 +314,15 @@ public class EnemySprite extends CharacterSprite {
|
||||
// Combined with player doing the same, should no longer be colliding to immediately re-enter battle if mob still present
|
||||
}
|
||||
|
||||
public Vector2 getTargetVector(PlayerSprite player, float delta) {
|
||||
public Vector2 getTargetVector(PlayerSprite player, ArrayList<NavigationVertex> sortedGraphNodes, float delta) {
|
||||
//todo - this can be integrated into overworld movement as well, giving flee behaviors or moving to generated waypoints
|
||||
Vector2 target = pos();
|
||||
Vector2 routeToPlayer = new Vector2(player.pos()).sub(target);
|
||||
Vector2 spriteToPlayer = new Vector2(player.pos()).sub(target);
|
||||
|
||||
if (_freeze){
|
||||
//Mob has defeated player in battle, hold still until player has a chance to move away.
|
||||
//Without this moving enemies can immediately restart battle.
|
||||
if (routeToPlayer.len() < unfreezeRange) {
|
||||
if (spriteToPlayer.len() < unfreezeRange) {
|
||||
timer += delta;
|
||||
return Vector2.Zero;
|
||||
}
|
||||
@@ -119,53 +331,81 @@ public class EnemySprite extends CharacterSprite {
|
||||
}
|
||||
}
|
||||
|
||||
NavigationVertex targetPoint = null;
|
||||
if (threatRange > 0 || fleeRange > 0){
|
||||
if (routeToPlayer.len() <= threatRange || (aggro && routeToPlayer.len() <= pursueRange))
|
||||
if (spriteToPlayer.len() <= threatRange || (aggro && spriteToPlayer.len() <= pursueRange))
|
||||
{
|
||||
if (sortedGraphNodes != null) {
|
||||
for (NavigationVertex candidate : sortedGraphNodes) {
|
||||
Vector2 candidateToPlayer = new Vector2(candidate.pos).sub(player.pos());
|
||||
if ((candidateToPlayer.x * candidateToPlayer.x) + (candidateToPlayer.y * candidateToPlayer.y) <
|
||||
(spriteToPlayer.x * spriteToPlayer.x) + (spriteToPlayer.y * spriteToPlayer.y)) {
|
||||
targetPoint = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
aggro = true;
|
||||
return routeToPlayer;
|
||||
if (targetPoint != null) {
|
||||
return targetPoint.pos;
|
||||
}
|
||||
return new Vector2(player.pos());
|
||||
}
|
||||
if (routeToPlayer.len() <= fleeRange)
|
||||
if (spriteToPlayer.len() <= fleeRange)
|
||||
{
|
||||
Float fleeDistance = fleeRange - routeToPlayer.len();
|
||||
return new Vector2(target).sub(player.pos()).setLength(fleeDistance);
|
||||
//todo: replace with inverse A* variant, seeking max total distance from player in X generations
|
||||
// of movement, valuing each node by distance from player divided by closest distance(s) in path
|
||||
// in order to make close passes to escape less appealing than maintaining moderate distance
|
||||
float fleeDistance = fleeRange - spriteToPlayer.len();
|
||||
return new Vector2(pos()).sub(player.pos()).setLength(fleeDistance).add(pos());
|
||||
}
|
||||
if (aggro && spriteToPlayer.len() > pursueRange) {
|
||||
aggro = false;
|
||||
initializeBaseMovementBehavior();
|
||||
}
|
||||
}
|
||||
|
||||
if (movementBehaviors.size() > 0){
|
||||
if (movementBehaviors.peek() != null){
|
||||
MovementBehavior peek = movementBehaviors.peek();
|
||||
//TODO - This first block needs to be redone, doesn't work as intended and can also possibly skip behaviors in rare situations
|
||||
// if (peek.getDuration() == 0 && target.equals(_previousPosition6) && timer >= _movementTimeout)
|
||||
// {
|
||||
// //stationary in an untimed behavior, move on to next behavior attempt to get unstuck
|
||||
// if (movementBehaviors.size() > 1) {
|
||||
// MovementBehavior current = movementBehaviors.pop();
|
||||
// current.currentTargetVector = null;
|
||||
// movementBehaviors.addLast(current);
|
||||
// }
|
||||
// }
|
||||
//else
|
||||
if (peek.getDuration() == 0 && peek.getNextTargetVector(pos()).dst(pos()) < 2){
|
||||
//this is a location based behavior that has been completed. Move on to the next behavior
|
||||
|
||||
MovementBehavior current = movementBehaviors.pop();
|
||||
current.currentTargetVector = null;
|
||||
movementBehaviors.addLast(current);
|
||||
|
||||
if (movementBehaviors.peek().getDuration() == 0 && target.equals(_previousPosition6) && timer >= _movementTimeout)
|
||||
{
|
||||
//stationary in an untimed behavior, move on to next behavior attempt to get unstuck
|
||||
if (movementBehaviors.size() > 1) {
|
||||
movementBehaviors.addLast(movementBehaviors.pop());
|
||||
timer = 0.0f;
|
||||
}
|
||||
}
|
||||
else if (movementBehaviors.peek().pos().sub(pos()).len() < 0.3){
|
||||
//this is a location based behavior that has been completed. Move on if there are more behaviors
|
||||
if (movementBehaviors.size() > 1) {
|
||||
movementBehaviors.addLast(movementBehaviors.pop());
|
||||
timer = 0.0f;
|
||||
}
|
||||
}
|
||||
else if ( movementBehaviors.peek().getDuration() > 0)
|
||||
else if ( peek.getDuration() > 0)
|
||||
{
|
||||
if (timer >= movementBehaviors.peek().getDuration() + delta)
|
||||
if (timer >= peek.getDuration() + delta)
|
||||
{
|
||||
//this is a timed behavior that has been completed. Move to the next behavior and restart the timer
|
||||
movementBehaviors.addLast(movementBehaviors.pop());
|
||||
timer = 0.0f;
|
||||
MovementBehavior current = movementBehaviors.pop();
|
||||
current.currentTargetVector = null;
|
||||
movementBehaviors.addLast(current);
|
||||
}
|
||||
else{
|
||||
timer += delta;//this is a timed behavior that has not been completed, continue this behavior
|
||||
return new Vector2(pos());
|
||||
}
|
||||
}
|
||||
if (movementBehaviors.peek().pos().len() > 0.3)
|
||||
target = new Vector2(movementBehaviors.peek().pos()).sub(pos());
|
||||
else target = Vector2.Zero;
|
||||
if (peek.getNextTargetVector(pos()).dst(pos()) > 0.3) {
|
||||
target = new Vector2(peek.getNextTargetVector(pos()));
|
||||
}
|
||||
else target = new Vector2(pos());
|
||||
}
|
||||
else target = Vector2.Zero;
|
||||
else target = new Vector2(pos());
|
||||
return target;
|
||||
}
|
||||
public void updatePositon()
|
||||
@@ -313,7 +553,7 @@ public class EnemySprite extends CharacterSprite {
|
||||
}
|
||||
|
||||
public float speed() {
|
||||
return data.speed;
|
||||
return Float.max(data.speed + speedModifier, 0);
|
||||
}
|
||||
|
||||
public float getLifetime() {
|
||||
@@ -322,44 +562,71 @@ public class EnemySprite extends CharacterSprite {
|
||||
return Math.max(data.lifetime, lifetime);
|
||||
}
|
||||
|
||||
//Pathfinding integration below this line
|
||||
|
||||
public class MovementBehavior {
|
||||
|
||||
//temporary placeholders for overworld behavior integration
|
||||
public boolean wander = false;
|
||||
public boolean flee = false;
|
||||
public boolean stop = false;
|
||||
//end temporary
|
||||
|
||||
float duration = 0.0f;
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
|
||||
int destination = 0;
|
||||
|
||||
public float getX(){
|
||||
return x;
|
||||
}
|
||||
public float getY(){
|
||||
return y;
|
||||
}
|
||||
public float getDuration(){
|
||||
return duration;
|
||||
}
|
||||
public int getDestination(){
|
||||
return destination;
|
||||
}
|
||||
|
||||
public void setX(float newVal){
|
||||
x = newVal;
|
||||
}
|
||||
public void setY(float newVal){
|
||||
y = newVal;
|
||||
}
|
||||
|
||||
public Vector2 pos() {
|
||||
return new Vector2(getX(), getY());
|
||||
}
|
||||
public void setNavPath(ProgressableGraphPath<NavigationVertex> navPath) {
|
||||
this.navPath = navPath;
|
||||
}
|
||||
|
||||
public ProgressableGraphPath<NavigationVertex> getNavPath() {
|
||||
return navPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getZeroLinearSpeedThreshold() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZeroLinearSpeedThreshold(float value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxLinearSpeed() {
|
||||
return 500;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxLinearSpeed(float maxLinearSpeed) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxLinearAcceleration() {
|
||||
return 5000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxLinearAcceleration(float maxLinearAcceleration) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxAngularSpeed() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxAngularSpeed(float maxAngularSpeed) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxAngularAcceleration() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxAngularAcceleration(float maxAngularAcceleration) {
|
||||
|
||||
}
|
||||
|
||||
public void steer(Vector2 currentVector) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -316,6 +316,7 @@ public class RewardScene extends UIScene {
|
||||
if (type == Type.Shop) {
|
||||
this.shopActor = shopActor;
|
||||
this.changes = shopActor.getMapStage().getChanges();
|
||||
addToSelectable(restockButton);
|
||||
}
|
||||
for (Actor actor : new Array.ArrayIterator<>(generated)) {
|
||||
actor.remove();
|
||||
@@ -323,6 +324,7 @@ public class RewardScene extends UIScene {
|
||||
((RewardActor) actor).dispose();
|
||||
}
|
||||
}
|
||||
addToSelectable(doneButton);
|
||||
generated.clear();
|
||||
|
||||
Actor card = ui.findActor("cards");
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package forge.adventure.stage;
|
||||
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.controllers.Controllers;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
@@ -14,6 +13,7 @@ import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
|
||||
import com.badlogic.gdx.maps.tiled.objects.TiledMapTileMapObject;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.*;
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.Group;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
@@ -23,9 +23,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Button;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Dialog;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Image;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.Scaling;
|
||||
import com.badlogic.gdx.utils.*;
|
||||
import com.badlogic.gdx.utils.Timer;
|
||||
import com.github.tommyettinger.textra.TextraButton;
|
||||
import com.github.tommyettinger.textra.TextraLabel;
|
||||
@@ -37,6 +35,9 @@ import forge.adventure.data.*;
|
||||
import forge.adventure.pointofintrest.PointOfInterestChanges;
|
||||
import forge.adventure.scene.*;
|
||||
import forge.adventure.util.*;
|
||||
import forge.adventure.util.pathfinding.NavigationMap;
|
||||
import forge.adventure.util.pathfinding.NavigationVertex;
|
||||
import forge.adventure.util.pathfinding.ProgressableGraphPath;
|
||||
import forge.adventure.world.WorldSave;
|
||||
import forge.assets.FBufferedImage;
|
||||
import forge.assets.FImageComplex;
|
||||
@@ -53,6 +54,7 @@ import forge.sound.SoundSystem;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
import java.util.Queue;
|
||||
|
||||
|
||||
/**
|
||||
@@ -61,9 +63,10 @@ import java.util.*;
|
||||
public class MapStage extends GameStage {
|
||||
public static MapStage instance;
|
||||
final Array<MapActor> actors = new Array<>();
|
||||
|
||||
TiledMap map;
|
||||
Array<Rectangle> collisionRect = new Array<>();
|
||||
public com.badlogic.gdx.physics.box2d.World gdxWorld;
|
||||
public TiledMap tiledMap;
|
||||
public Array<Rectangle> collisionRect = new Array<>();
|
||||
public Map<Float, NavigationMap> navMaps = new HashMap<>();
|
||||
private boolean isInMap = false;
|
||||
MapLayer spriteLayer;
|
||||
private PointOfInterestChanges changes;
|
||||
@@ -87,7 +90,13 @@ public class MapStage extends GameStage {
|
||||
private boolean respawnEnemies;
|
||||
private boolean canFailDungeon = false;
|
||||
protected ArrayList<EnemySprite> enemies = new ArrayList<>();
|
||||
protected Map<Integer, Vector2> waypoints = new HashMap<>();
|
||||
public Map<Integer, Vector2> waypoints = new HashMap<>();
|
||||
|
||||
//todo: add additional graphs for other sprite sizes if desired. Current implementation
|
||||
// allows for mobs of any size to fit into 16x16 tiles for navigation purposes
|
||||
float collisionWidthMod = 0.4f;
|
||||
float defaultSpriteSize = 16f;
|
||||
float navMapSize = defaultSpriteSize * collisionWidthMod;
|
||||
|
||||
public boolean getDialogOnlyInput() {
|
||||
return dialogOnlyInput;
|
||||
@@ -126,6 +135,7 @@ public class MapStage extends GameStage {
|
||||
private boolean freezeAllEnemyBehaviors = false;
|
||||
|
||||
protected MapStage() {
|
||||
gdxWorld = new World(new Vector2(0, 0),false);
|
||||
dialog = Controls.newDialog("");
|
||||
eventTouchDown = new InputEvent();
|
||||
eventTouchDown.setPointer(-1);
|
||||
@@ -309,10 +319,11 @@ public class MapStage extends GameStage {
|
||||
}
|
||||
|
||||
public void loadMap(TiledMap map, String sourceMap, String targetMap, int spawnTargetId) {
|
||||
gdxWorld = new World(new Vector2(0, 0),false);
|
||||
isLoadingMatch = false;
|
||||
isInMap = true;
|
||||
GameHUD.getInstance().showHideMap(false);
|
||||
this.map = map;
|
||||
this.tiledMap = map;
|
||||
for (MapActor actor : new Array.ArrayIterator<>(actors)) {
|
||||
actor.remove();
|
||||
foregroundSprites.removeActor(actor);
|
||||
@@ -320,6 +331,7 @@ public class MapStage extends GameStage {
|
||||
positions.clear();
|
||||
actors.clear();
|
||||
collisionRect.clear();
|
||||
waypoints.clear();
|
||||
|
||||
if (collisionGroup != null)
|
||||
collisionGroup.remove();
|
||||
@@ -401,8 +413,9 @@ public class MapStage extends GameStage {
|
||||
} while (oldSize != collisionRect.size);
|
||||
if (spriteLayer == null) System.err.print("Warning: No spriteLayer present in map.\n");
|
||||
|
||||
replaceWaypoints();
|
||||
|
||||
navMaps.clear();
|
||||
navMaps.put(navMapSize, new NavigationMap(navMapSize));
|
||||
navMaps.get(navMapSize).initializeGeometryGraph();
|
||||
getPlayerSprite().stop();
|
||||
}
|
||||
|
||||
@@ -428,17 +441,6 @@ public class MapStage extends GameStage {
|
||||
}
|
||||
}
|
||||
|
||||
void replaceWaypoints() {
|
||||
for (EnemySprite enemy : enemies) {
|
||||
for (EnemySprite.MovementBehavior behavior : enemy.movementBehaviors) {
|
||||
if (behavior.getDestination() > 0 && waypoints.containsKey(behavior.getDestination())) {
|
||||
behavior.setX(waypoints.get(behavior.getDestination()).x);
|
||||
behavior.setY(waypoints.get(behavior.getDestination()).y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public boolean containsOrEquals(Rectangle r1, Rectangle r2) {
|
||||
float xmi = r2.x;
|
||||
float xma = xmi + r2.width;
|
||||
@@ -456,7 +458,7 @@ public class MapStage extends GameStage {
|
||||
for (MapObject collision : cell.getTile().getObjects()) {
|
||||
if (collision instanceof RectangleMapObject) {
|
||||
Rectangle r = ((RectangleMapObject) collision).getRectangle();
|
||||
collisionRect.add(new Rectangle((Math.round(layer.getTileWidth() * x) + r.x), (Math.round(layer.getTileHeight() * y) + r.y), Math.round(r.width), Math.round(r.height)));
|
||||
collisionRect.add(new Rectangle(((layer.getTileWidth() * x) + r.x), ((layer.getTileHeight() * y) + r.y), Math.round(r.width), Math.round(r.height)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -657,6 +659,10 @@ public class MapStage extends GameStage {
|
||||
if (dialogObject != null && !dialogObject.toString().isEmpty()) {
|
||||
mob.parseWaypoints(dialogObject.toString());
|
||||
}
|
||||
if (prop.containsKey("speedModifier")) //Increase or decrease default speed for this mob
|
||||
{
|
||||
mob.speedModifier = Float.parseFloat(prop.get("speedModifier").toString());
|
||||
}
|
||||
|
||||
enemies.add(mob);
|
||||
addMapActor(obj, mob);
|
||||
@@ -1026,8 +1032,6 @@ public class MapStage extends GameStage {
|
||||
for (Integer i : idsToRemove) deleteObject(i);
|
||||
}
|
||||
|
||||
final Rectangle tempBoundingRect = new Rectangle();
|
||||
|
||||
@Override
|
||||
protected void onActing(float delta) {
|
||||
if (isPaused() || isDialogOnlyInput())
|
||||
@@ -1040,6 +1044,9 @@ public class MapStage extends GameStage {
|
||||
}
|
||||
else return;
|
||||
}
|
||||
float mobSize = navMapSize; //todo: replace with actual size if multiple nav maps implemented
|
||||
ArrayList<NavigationVertex> verticesNearPlayer = new ArrayList<>(navMaps.get(mobSize).navGraph.getNodes());
|
||||
verticesNearPlayer.sort(Comparator.comparingInt(o -> Math.round((o.pos.x - player.pos().x) * (o.pos.x - player.pos().x) + (o.pos.y - player.pos().y) * (o.pos.y - player.pos().y))));
|
||||
|
||||
if (!freezeAllEnemyBehaviors) {
|
||||
while (it.hasNext()) {
|
||||
@@ -1048,35 +1055,52 @@ public class MapStage extends GameStage {
|
||||
continue;
|
||||
}
|
||||
mob.updatePositon();
|
||||
mob.targetVector = mob.getTargetVector(player, delta);
|
||||
Vector2 currentVector = new Vector2(mob.targetVector);
|
||||
|
||||
ProgressableGraphPath<NavigationVertex> navPath = new ProgressableGraphPath<>(0);
|
||||
if (mob.getData().flying) {
|
||||
navPath.add(new NavigationVertex(mob.getTargetVector(player, null,delta)));
|
||||
} else {
|
||||
Vector2 destination = mob.getTargetVector(player, verticesNearPlayer, delta);
|
||||
|
||||
if (destination.epsilonEquals(mob.pos()) && !mob.aggro) {
|
||||
mob.setAnimation(CharacterSprite.AnimationTypes.Idle);
|
||||
continue;
|
||||
}
|
||||
if (destination.equals(mob.targetVector) && mob.getNavPath() != null)
|
||||
navPath = mob.getNavPath();
|
||||
|
||||
if (navPath.nodes.size == 0 || !destination.equals(mob.targetVector)) {
|
||||
mob.targetVector = destination;
|
||||
navPath = navMaps.get(mobSize).findShortestPath(mobSize, mob.pos(), mob.targetVector);
|
||||
}
|
||||
|
||||
if (mob.aggro) {
|
||||
navPath.add(new NavigationVertex(player.pos()));
|
||||
}
|
||||
}
|
||||
|
||||
if (navPath == null || navPath.getCount() == 0 || navPath.get(0) == null) {
|
||||
mob.setAnimation(CharacterSprite.AnimationTypes.Idle);
|
||||
continue;
|
||||
}
|
||||
Vector2 currentVector = null;
|
||||
|
||||
while (navPath.getCount() > 0 && navPath.get(0) != null && (navPath.get(0).pos == null || navPath.get(0).pos.dst(mob.pos()) < 0.5f)) {
|
||||
|
||||
navPath.remove(0);
|
||||
|
||||
}
|
||||
if (navPath.getCount() != 0) {
|
||||
currentVector = new Vector2(navPath.get(0).pos).sub(mob.pos());
|
||||
}
|
||||
mob.setNavPath(navPath);
|
||||
mob.clearActions();
|
||||
if (mob.targetVector.len() == 0.0f) {
|
||||
if (currentVector == null || (currentVector.x == 0.0f && currentVector.y == 0.0f)) {
|
||||
mob.setAnimation(CharacterSprite.AnimationTypes.Idle);
|
||||
continue;
|
||||
}
|
||||
|
||||
currentVector.setLength(Math.min(mob.speed() * delta, mob.targetVector.len()));
|
||||
|
||||
tempBoundingRect.set(mob.getX() + currentVector.x, mob.getY() + currentVector.y, mob.getWidth() * 0.4f, mob.getHeight() * 0.4f);
|
||||
|
||||
if (!mob.getData().flying && isColliding(tempBoundingRect))//if direct path is not possible
|
||||
{
|
||||
currentVector = adjustMovement(currentVector,tempBoundingRect);
|
||||
tempBoundingRect.set(mob.getX() + currentVector.x, mob.getY(), mob.getWidth() * 0.4f, mob.getHeight() * 0.4f);
|
||||
if (isColliding(tempBoundingRect))//if only x path is not possible
|
||||
{
|
||||
tempBoundingRect.set(mob.getX(), mob.getY() + currentVector.y, mob.getWidth() * 0.4f, mob.getHeight() * 0.4f);
|
||||
if (!isColliding(tempBoundingRect))//if y path is possible
|
||||
{
|
||||
mob.moveBy(0, currentVector.y, delta);
|
||||
}
|
||||
} else {
|
||||
mob.moveBy(currentVector.x, 0, delta);
|
||||
}
|
||||
} else {
|
||||
mob.moveBy(currentVector.x, currentVector.y, delta);
|
||||
}
|
||||
mob.steer(currentVector);
|
||||
mob.update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1087,9 +1111,6 @@ public class MapStage extends GameStage {
|
||||
if (positions.size() > 4)
|
||||
positions.remove();
|
||||
|
||||
|
||||
|
||||
|
||||
for (MapActor actor : new Array.ArrayIterator<>(actors)) {
|
||||
if (actor.collideWithPlayer(player)) {
|
||||
if (actor instanceof EnemySprite) {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package forge.adventure.util.pathfinding;
|
||||
|
||||
import com.badlogic.gdx.ai.utils.Collision;
|
||||
import com.badlogic.gdx.ai.utils.Ray;
|
||||
import com.badlogic.gdx.ai.utils.RaycastCollisionDetector;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.Fixture;
|
||||
import com.badlogic.gdx.physics.box2d.RayCastCallback;
|
||||
import com.badlogic.gdx.physics.box2d.World;
|
||||
|
||||
public class Box2dRaycastCollisionDetector implements RaycastCollisionDetector<Vector2> {
|
||||
|
||||
World world;
|
||||
Box2dRaycastCollisionDetector.Box2dRaycastCallback callback;
|
||||
|
||||
public Box2dRaycastCollisionDetector (World world) {
|
||||
this(world, new Box2dRaycastCollisionDetector.Box2dRaycastCallback());
|
||||
}
|
||||
|
||||
public Box2dRaycastCollisionDetector (World world, Box2dRaycastCollisionDetector.Box2dRaycastCallback callback) {
|
||||
this.world = world;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean collides (Ray<Vector2> ray) {
|
||||
return findCollision(null, ray);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean findCollision (Collision<Vector2> outputCollision, Ray<Vector2> inputRay) {
|
||||
callback.collided = false;
|
||||
if (!inputRay.start.epsilonEquals(inputRay.end, MathUtils.FLOAT_ROUNDING_ERROR)) {
|
||||
callback.outputCollision = outputCollision;
|
||||
world.rayCast(callback, inputRay.start, inputRay.end);
|
||||
}
|
||||
return callback.collided;
|
||||
}
|
||||
|
||||
public static class Box2dRaycastCallback implements RayCastCallback {
|
||||
public Collision<Vector2> outputCollision;
|
||||
public boolean collided;
|
||||
|
||||
public Box2dRaycastCallback () {
|
||||
}
|
||||
|
||||
@Override
|
||||
public float reportRayFixture (Fixture fixture, Vector2 point, Vector2 normal, float fraction) {
|
||||
if (outputCollision != null) outputCollision.set(point, normal);
|
||||
collided = true;
|
||||
return fraction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package forge.adventure.util.pathfinding;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.Heuristic;
|
||||
|
||||
public class EuclidianHeuristic implements Heuristic<NavigationVertex> {
|
||||
|
||||
@Override
|
||||
public float estimate(NavigationVertex start, NavigationVertex end) {
|
||||
return start.pos.dst(end.pos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package forge.adventure.util.pathfinding;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import forge.adventure.stage.MapStage;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
public class MovementBehavior {
|
||||
public float duration = 0.0f;
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
|
||||
public String destination = "";
|
||||
|
||||
public float getX(){
|
||||
return x;
|
||||
}
|
||||
public float getY(){
|
||||
return y;
|
||||
}
|
||||
public float getDuration(){
|
||||
return duration;
|
||||
}
|
||||
public Vector2 currentTargetVector;
|
||||
public Vector2 getNextTargetVector(Vector2 currentPosition){
|
||||
if (currentTargetVector != null) {
|
||||
return currentTargetVector;
|
||||
}
|
||||
if (destination.isEmpty()) {
|
||||
currentTargetVector = new Vector2(currentPosition);
|
||||
} else {
|
||||
if (destination.startsWith("r")) {
|
||||
String[] randomWaypoints = destination.replaceAll("r", "").split("-");
|
||||
if (randomWaypoints.length > 0) {
|
||||
int selectedWaypoint = Integer.parseInt(Aggregates.random(randomWaypoints));
|
||||
if (MapStage.getInstance().waypoints.containsKey(selectedWaypoint)) {
|
||||
currentTargetVector = new Vector2(MapStage.getInstance().waypoints.get(selectedWaypoint));
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentTargetVector = new Vector2(currentPosition);
|
||||
}
|
||||
} else if (destination.startsWith("w")) {
|
||||
currentTargetVector = new Vector2(currentPosition);
|
||||
duration = Float.parseFloat(destination.replaceAll("w", ""));
|
||||
} else if (MapStage.getInstance().waypoints.containsKey(Integer.parseInt(destination))) {
|
||||
currentTargetVector = new Vector2(MapStage.getInstance().waypoints.get(Integer.parseInt(destination)));
|
||||
}
|
||||
}
|
||||
|
||||
return currentTargetVector;
|
||||
}
|
||||
|
||||
public void setX(float newVal){
|
||||
x = newVal;
|
||||
}
|
||||
public void setY(float newVal){
|
||||
y = newVal;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package forge.adventure.util.pathfinding;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.Connection;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
public class NavigationEdge implements Connection<NavigationVertex> {
|
||||
NavigationVertex fromVertex;
|
||||
NavigationVertex toVertex;
|
||||
float cost;
|
||||
|
||||
public NavigationEdge(NavigationVertex from, NavigationVertex to) {
|
||||
this.fromVertex = from;
|
||||
this.toVertex = to;
|
||||
cost = Vector2.dst(fromVertex.pos.x, fromVertex.pos.y, toVertex.pos.x, toVertex.pos.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCost() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigationVertex getFromNode() {
|
||||
return fromVertex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigationVertex getToNode() {
|
||||
return toVertex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package forge.adventure.util.pathfinding;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.Connection;
|
||||
import com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder;
|
||||
import com.badlogic.gdx.ai.pfa.indexed.IndexedGraph;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class NavigationGraph implements IndexedGraph<NavigationVertex> {
|
||||
private int lastNodeIndex = 0;
|
||||
Map<Integer, NavigationVertex> nodes = new HashMap<>();
|
||||
|
||||
EuclidianHeuristic navigationHeuristic = new EuclidianHeuristic();
|
||||
|
||||
public NavigationVertex addVertex(NavigationVertex node){
|
||||
node.index = lastNodeIndex;
|
||||
lastNodeIndex++;
|
||||
nodes.put(node.index,node);
|
||||
return node;
|
||||
}
|
||||
|
||||
public NavigationVertex addVertex(Vector2 position) {
|
||||
return addVertex(new NavigationVertex(position));
|
||||
}
|
||||
|
||||
public NavigationVertex addVertex(float x, float y) {
|
||||
return addVertex(new NavigationVertex(x,y));
|
||||
}
|
||||
|
||||
public void removeVertex(NavigationVertex node) {
|
||||
for (NavigationVertex v : node.incomingEdges.keys()) {
|
||||
v.removeEdges(node);
|
||||
}
|
||||
nodes.remove(node.index >=0? node.index: lookupIndex(node));
|
||||
}
|
||||
|
||||
public void removeVertex(Vector2 position) {
|
||||
removeVertex(getVertexByPosition(position));
|
||||
}
|
||||
|
||||
public void removeVertex(float x, float y) {
|
||||
removeVertex(new Vector2(x,y));
|
||||
}
|
||||
|
||||
public void removeVertices(Collection<NavigationVertex> vertices) {
|
||||
for (NavigationVertex v : vertices) {
|
||||
removeVertex(v);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeVertexIf(Predicate<NavigationVertex> predicate) {
|
||||
removeVertices(nodes.values().stream().filter(predicate).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public int lookupIndex(NavigationVertex item) {
|
||||
return lookupIndex(item.pos);
|
||||
}
|
||||
|
||||
public int lookupIndex(Vector2 pos) {
|
||||
for (int i : nodes.keySet())
|
||||
if (nodes.get(i).pos.equals(pos)) return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void addEdge(NavigationVertex fromNode, NavigationVertex toNode) {
|
||||
if (fromNode.index < 0) {
|
||||
fromNode = getVertexByPosition(fromNode.pos);
|
||||
}
|
||||
if (toNode.index < 0) {
|
||||
toNode = getVertexByPosition(toNode.pos);
|
||||
}
|
||||
|
||||
if (edgeExists(fromNode, toNode)) {
|
||||
System.out.println(fromNode.pos + " is already connected to " + toNode.pos);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(fromNode.index < 0) || toNode.index < 0) {
|
||||
NavigationEdge fromAToB = new NavigationEdge(fromNode, toNode);
|
||||
NavigationEdge fromBToA = new NavigationEdge(toNode, fromNode);
|
||||
fromNode.outgoingEdges.put(toNode, fromAToB);
|
||||
fromNode.incomingEdges.put(toNode, fromBToA);
|
||||
toNode.outgoingEdges.put(fromNode, fromBToA);
|
||||
toNode.incomingEdges.put(fromNode, fromAToB);
|
||||
}
|
||||
}
|
||||
|
||||
public void addEdge(Vector2 fromNode, NavigationVertex toNode) {
|
||||
addEdge(new NavigationVertex(fromNode), toNode);
|
||||
}
|
||||
|
||||
public void addEdge(NavigationVertex fromNode, Vector2 toNode) {
|
||||
addEdge(fromNode, new NavigationVertex(toNode));
|
||||
}
|
||||
|
||||
public void addEdgeUnchecked(NavigationVertex fromNode, NavigationVertex toNode) {
|
||||
//Assumes that nodes are in graph, are not connected already, and have correct index
|
||||
|
||||
NavigationEdge fromAToB = new NavigationEdge(fromNode, toNode);
|
||||
NavigationEdge fromBToA = new NavigationEdge(toNode, fromNode);
|
||||
|
||||
fromNode.outgoingEdges.put(toNode, fromAToB);
|
||||
fromNode.incomingEdges.put(toNode, fromBToA);
|
||||
toNode.outgoingEdges.put(fromNode, fromBToA);
|
||||
toNode.incomingEdges.put(fromNode, fromAToB);
|
||||
}
|
||||
|
||||
public int getIndex(NavigationVertex node) {
|
||||
return node.index;
|
||||
}
|
||||
|
||||
public int getNodeCount() {
|
||||
return lastNodeIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Array<Connection<NavigationVertex>> getConnections(NavigationVertex fromNode) {
|
||||
return fromNode.getAllConnections();
|
||||
}
|
||||
|
||||
public boolean edgeExists(NavigationVertex fromNode, NavigationVertex toNode) {
|
||||
if (fromNode.index < 0) {
|
||||
fromNode = getVertexByPosition(fromNode.pos);
|
||||
}
|
||||
if (toNode.index < 0) {
|
||||
toNode = getVertexByPosition(toNode.pos);
|
||||
}
|
||||
return fromNode.outgoingEdges.containsKey(toNode);
|
||||
}
|
||||
|
||||
public Collection<NavigationVertex> getNodes() {
|
||||
return nodes.values();
|
||||
}
|
||||
|
||||
public ProgressableGraphPath<NavigationVertex> findPath(Vector2 origin, Vector2 destination) {
|
||||
ProgressableGraphPath<NavigationVertex> navPath = new ProgressableGraphPath<>();
|
||||
|
||||
NavigationVertex originVertex = getVertexByPosition(origin);
|
||||
NavigationVertex destinationVertex = getVertexByPosition(destination);
|
||||
|
||||
if (originVertex.index > -1 && destinationVertex.index > -1) {
|
||||
|
||||
new IndexedAStarPathFinder<>(this).searchNodePath(originVertex, destinationVertex, navigationHeuristic, navPath);
|
||||
}
|
||||
return navPath;
|
||||
}
|
||||
|
||||
public NavigationVertex getVertexByPosition(Vector2 position) {
|
||||
return nodes.get(lookupIndex(position));
|
||||
}
|
||||
|
||||
public boolean containsNode(Vector2 nodePosition) {
|
||||
return nodes.containsKey(lookupIndex(nodePosition));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
package forge.adventure.util.pathfinding;
|
||||
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.*;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import forge.adventure.stage.MapStage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class NavigationMap {
|
||||
float spriteSize = 16f;
|
||||
boolean rayCollided = false;
|
||||
|
||||
public NavigationGraph navGraph = new NavigationGraph();
|
||||
|
||||
Array<Rectangle> navBounds = new Array<>();
|
||||
float half = (spriteSize / 2);
|
||||
|
||||
public NavigationMap(float spriteSize) {
|
||||
this.spriteSize = spriteSize;
|
||||
this.half = spriteSize / 2;
|
||||
}
|
||||
|
||||
RayCastCallback callback = new RayCastCallback() {
|
||||
@Override
|
||||
public float reportRayFixture(Fixture fixture, Vector2 vector2, Vector2 vector21, float v) {
|
||||
if (v < 1.0)
|
||||
rayCollided = true;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
public void initializeGeometryGraph() {
|
||||
navGraph = new NavigationGraph();
|
||||
|
||||
for (int i = 0; i < MapStage.getInstance().collisionRect.size; i++) {
|
||||
Rectangle r1 = MapStage.getInstance().collisionRect.get(i);
|
||||
|
||||
if (r1.width < 3 && r1.height < 3)
|
||||
continue;
|
||||
int offsetX = -8;
|
||||
int offsetY = 0;
|
||||
|
||||
BodyDef bodyDef = new BodyDef();
|
||||
bodyDef.type = BodyDef.BodyType.StaticBody;
|
||||
bodyDef.position.set(r1.x + r1.getWidth() / 2 + offsetX, r1.y + r1.getHeight() / 2 + offsetY);
|
||||
Body body = MapStage.getInstance().gdxWorld.createBody(bodyDef);
|
||||
|
||||
PolygonShape polygonShape = new PolygonShape();
|
||||
polygonShape.setAsBox(((r1.getWidth() + spriteSize) / 2), ((r1.getHeight() + spriteSize) / 2));
|
||||
FixtureDef fixture = new FixtureDef();
|
||||
fixture.shape = polygonShape;
|
||||
fixture.density = 1;
|
||||
|
||||
body.createFixture(fixture);
|
||||
polygonShape.dispose();
|
||||
}
|
||||
|
||||
float width = Float.parseFloat(MapStage.getInstance().tiledMap.getProperties().get("width").toString());
|
||||
float height = Float.parseFloat(MapStage.getInstance().tiledMap.getProperties().get("height").toString());
|
||||
float tileHeight = Float.parseFloat(MapStage.getInstance().tiledMap.getProperties().get("tileheight").toString());
|
||||
float tileWidth = Float.parseFloat(MapStage.getInstance().tiledMap.getProperties().get("tilewidth").toString());
|
||||
|
||||
NavigationVertex[][] points = new NavigationVertex[(int)width][(int)height];
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
for (int j = 0; j < height; j++) {
|
||||
points[i][j] = navGraph.addVertex(i* tileWidth + (tileWidth/ 2), j*tileHeight + (tileHeight/ 2));
|
||||
if (i > 0) {
|
||||
navGraph.addEdgeUnchecked(points[i][j],points[i-1][j]);
|
||||
}
|
||||
|
||||
if (j > 0) {
|
||||
navGraph.addEdgeUnchecked(points[i][j],points[i][j-1]);
|
||||
}
|
||||
|
||||
if (i > 0 && j > 0) {
|
||||
navGraph.addEdgeUnchecked(points[i][j],points[i-1][j-1]);
|
||||
}
|
||||
|
||||
if (i > 0 && j + 1 < height) {
|
||||
navGraph.addEdgeUnchecked(points[i][j],points[i-1][j+1]);
|
||||
}
|
||||
//remaining connections will be added by subsequent nodes
|
||||
}
|
||||
}
|
||||
|
||||
Array<Fixture> fixtures = new Array<>();
|
||||
if (MapStage.getInstance().gdxWorld != null) {
|
||||
MapStage.getInstance().gdxWorld.getFixtures(fixtures);
|
||||
for (Fixture fix : fixtures) {
|
||||
navGraph.removeVertexIf(vertex -> fix.testPoint(vertex.pos));
|
||||
}
|
||||
}
|
||||
|
||||
navGraph.removeVertexIf(v -> navGraph.getConnections(v).isEmpty());
|
||||
|
||||
//Add additional vertices for map waypoints
|
||||
for (Vector2 waypointVector : MapStage.getInstance().waypoints.values()) {
|
||||
NavigationVertex waypointVertex = navGraph.addVertex(waypointVector);
|
||||
|
||||
ArrayList<NavigationVertex> vertices = new ArrayList<>(navGraph.nodes.values());
|
||||
vertices.sort(Comparator.comparingInt(o -> Math.round((o.pos.x - waypointVector.x) * (o.pos.x - waypointVector.x) + (o.pos.y - waypointVector.y) * (o.pos.y - waypointVector.y))));
|
||||
|
||||
for (int i = 0, j=0; i < vertices.size() && j < 4; i++) {
|
||||
if (waypointVector.epsilonEquals(vertices.get(i).pos))
|
||||
continue; //rayCast() crashes if params are equal
|
||||
rayCollided = false;
|
||||
MapStage.getInstance().gdxWorld.rayCast(callback, waypointVector, vertices.get(i).pos);
|
||||
if (!rayCollided) {
|
||||
navGraph.addEdgeUnchecked(waypointVertex, vertices.get(i));
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ProgressableGraphPath<NavigationVertex> findShortestPath(Float spriteSize, Vector2 origin, Vector2 destination) {
|
||||
Array<Fixture> fixtures = new Array<>();
|
||||
MapStage.getInstance().gdxWorld.getFixtures(fixtures);
|
||||
|
||||
boolean originPrecalculated = navGraph.containsNode(origin);
|
||||
boolean destinationPrecalculated = navGraph.containsNode(destination);
|
||||
|
||||
try {
|
||||
if (!originPrecalculated)
|
||||
navGraph.addVertex(origin);
|
||||
|
||||
if (!destinationPrecalculated)
|
||||
navGraph.addVertex(destination);
|
||||
|
||||
ArrayList<NavigationVertex> vertices = new ArrayList<>();
|
||||
|
||||
if (!(originPrecalculated && destinationPrecalculated)) {
|
||||
vertices.addAll(navGraph.nodes.values());
|
||||
vertices.sort(Comparator.comparingInt(o -> Math.round((o.pos.x - origin.x) * (o.pos.x - origin.x) + (o.pos.y - origin.y) * (o.pos.y - origin.y))));
|
||||
}
|
||||
|
||||
if (!originPrecalculated) {
|
||||
for (int i = 0, j=0; i < vertices.size() && j < 10; i++) {
|
||||
if (origin.epsilonEquals(vertices.get(i).pos))
|
||||
continue; //rayCast() crashes if params are equal
|
||||
rayCollided = false;
|
||||
MapStage.getInstance().gdxWorld.rayCast(callback, origin, vertices.get(i).pos);
|
||||
if (!rayCollided) {
|
||||
navGraph.addEdge(origin, vertices.get(i));
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!destinationPrecalculated) {
|
||||
for (int i = 0, j=0; i < vertices.size() && j < 10; i++) {
|
||||
if (destination.epsilonEquals(vertices.get(i).pos))
|
||||
continue; //shouldn't happen, but would crash during rayCast if it did
|
||||
rayCollided = false;
|
||||
MapStage.getInstance().gdxWorld.rayCast(callback, vertices.get(i).pos, destination);
|
||||
if (!rayCollided) {
|
||||
navGraph.addEdge(destination, vertices.get(i));
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ProgressableGraphPath<NavigationVertex> shortestPath = navGraph.findPath(origin, destination);
|
||||
|
||||
if (false) { //todo - re-evaluate. 8-way node links may be smooth enough to skip the extra raycast overhead
|
||||
//Trim path by cutting any unnecessary nodes
|
||||
for (int i = 0; i < shortestPath.getCount(); i++) {
|
||||
for (int j = shortestPath.getCount() - 1; j > i + 1; j--) {
|
||||
rayCollided = false;
|
||||
MapStage.getInstance().gdxWorld.rayCast(callback, shortestPath.get(i).pos, shortestPath.get(j).pos);
|
||||
if (!rayCollided) {
|
||||
shortestPath.remove(j - 1);
|
||||
i = 0;
|
||||
j = shortestPath.getCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!originPrecalculated)
|
||||
navGraph.removeVertex(origin);
|
||||
if (!destinationPrecalculated)
|
||||
navGraph.removeVertex(destination);
|
||||
return shortestPath;
|
||||
}
|
||||
catch(Exception e){
|
||||
if (!originPrecalculated && navGraph.lookupIndex(origin) > -1)
|
||||
navGraph.removeVertex(origin);
|
||||
if (!destinationPrecalculated && navGraph.lookupIndex(destination) > -1)
|
||||
navGraph.removeVertex(destination);
|
||||
throw(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package forge.adventure.util.pathfinding;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.Connection;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
|
||||
public class NavigationVertex {
|
||||
public Vector2 pos = Vector2.Zero;
|
||||
public ObjectMap<NavigationVertex, NavigationEdge> incomingEdges = new ObjectMap<>();
|
||||
public ObjectMap<NavigationVertex, NavigationEdge> outgoingEdges = new ObjectMap<>();
|
||||
int index = -1;
|
||||
|
||||
public NavigationVertex(Vector2 position) {
|
||||
pos = position;
|
||||
}
|
||||
|
||||
public NavigationVertex(float x, float y) {
|
||||
pos = new Vector2(x, y);
|
||||
}
|
||||
|
||||
public boolean hasEdgeTo(NavigationVertex otherNode) {
|
||||
return incomingEdges.containsKey(otherNode);
|
||||
}
|
||||
|
||||
public Array<Connection<NavigationVertex>> getAllConnections() {
|
||||
|
||||
Array<Connection<NavigationVertex>> ret = new Array<>();
|
||||
|
||||
for (NavigationEdge e : incomingEdges.values()) {
|
||||
ret.add(e);
|
||||
}
|
||||
for (NavigationEdge e : outgoingEdges.values()) {
|
||||
ret.add(e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void removeEdges(NavigationVertex node) {
|
||||
outgoingEdges.remove(node);
|
||||
incomingEdges.remove(node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package forge.adventure.util.pathfinding;
|
||||
|
||||
import com.badlogic.gdx.ai.pfa.GraphPath;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class ProgressableGraphPath<N> implements GraphPath<N> {
|
||||
public final Array<N> nodes;
|
||||
|
||||
/** Creates a {@code DefaultGraphPath} with no nodes. */
|
||||
public ProgressableGraphPath () {
|
||||
this(new Array<N>());
|
||||
}
|
||||
|
||||
/** Creates a {@code DefaultGraphPath} with the given capacity and no nodes. */
|
||||
public ProgressableGraphPath (int capacity) {
|
||||
this(new Array<N>(capacity));
|
||||
}
|
||||
|
||||
/** Creates a {@code DefaultGraphPath} with the given nodes. */
|
||||
public ProgressableGraphPath (Array<N> nodes) {
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear () {
|
||||
nodes.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount () {
|
||||
return nodes.size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add (N node) {
|
||||
nodes.add(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public N get (int index) {
|
||||
return nodes.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reverse () {
|
||||
nodes.reverse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<N> iterator () {
|
||||
return nodes.iterator();
|
||||
}
|
||||
|
||||
public void remove (int index) { nodes.removeIndex(index);}
|
||||
}
|
||||
36
forge-gui/res/adventure/common/decks/standard/archivist.dck
Normal file
36
forge-gui/res/adventure/common/decks/standard/archivist.dck
Normal file
@@ -0,0 +1,36 @@
|
||||
[metadata]
|
||||
Name=Archivist
|
||||
[Main]
|
||||
3 Ancient Den|BRC|1
|
||||
4 Archive Trap|PLIST|1
|
||||
3 Archivist|ULG|1
|
||||
2 Archivist of Oghma|CLB|2
|
||||
2 Automatic Librarian|DMU|1
|
||||
4 Bury in Books|J22|1
|
||||
4 Compulsive Research|CLB|1
|
||||
4 Field Research|ZNR|1
|
||||
3 Geist of the Archives|EMN|1
|
||||
2 Ghost Quarter|SLD|1
|
||||
2 Island|JMP|1
|
||||
1 Island|JMP|3
|
||||
1 Island|JMP|4
|
||||
1 Island|JMP|5
|
||||
2 Island|JMP|7
|
||||
4 Jace's Archivist|M12|1
|
||||
2 Key to the Archive|YMID|1
|
||||
3 Magus of the Moat|FUT|1
|
||||
2 Oath of Lieges|EXO|1
|
||||
2 Ormos, Archive Keeper|JMP|1
|
||||
4 Overwhelmed Archivist|MID|1
|
||||
1 Plains|JMP|1
|
||||
1 Plains|JMP|7
|
||||
1 Preston, the Vanisher|J22|1
|
||||
4 Razortide Bridge|BRC|1
|
||||
4 Seat of the Synod|J22|1
|
||||
2 Temple of Enlightenment|SCD|1
|
||||
1 Tolarian Academy|VMA|1
|
||||
1 Tome of the Infinite|J21|1
|
||||
4 Walking Archive|PLIST|1
|
||||
2 Winds of Abandon|PLIST|1
|
||||
[Sideboard]
|
||||
1 Wizard's Spellbook|AFR|1
|
||||
@@ -0,0 +1,24 @@
|
||||
[metadata]
|
||||
Name=Golem Sentinel
|
||||
[Main]
|
||||
4 Amaranthine Wall|DOM|1
|
||||
4 Consulate Skygate|BBD|1
|
||||
4 Living Wall|30A|1
|
||||
3 Plains|DMU|1
|
||||
7 Plains|DMU|2
|
||||
6 Plains|DMU|3
|
||||
5 Plains|DMU|4
|
||||
4 Rolling Stones|STH|1
|
||||
4 Secluded Steppe|J21|1
|
||||
4 Shield-Wall Sentinel|DMU|1
|
||||
4 Stalwart Shield-Bearers|ROE|1
|
||||
4 Steel Wall|TD2|1
|
||||
1 Sunweb|MIR|1
|
||||
4 Walking Bulwark|DMU|1
|
||||
4 Wall of Junk|DMR|1
|
||||
4 Wall of Spears|DPA|1
|
||||
1 Wall of Swords|30A|1
|
||||
4 Weathered Sentinels|NCC|1
|
||||
4 Wingmantle Chaplain|DMU|1
|
||||
[Sideboard]
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
[metadata]
|
||||
Name=Golem Sentinel 2
|
||||
[Main]
|
||||
4 Buried Ruin|ONC|1
|
||||
4 Chief of the Foundry|BRC|1
|
||||
4 Chronomaton|DDM|1
|
||||
4 Cryptic Caves|M20|1
|
||||
4 Darksteel Citadel|BRC|1
|
||||
4 Desert|AFC|1
|
||||
4 Haunted Guardian|AVR|1
|
||||
4 Lightning-Core Excavator|J21|1
|
||||
4 Locthwain Gargoyle|J22|1
|
||||
4 Patchwork Automaton|NEO|1
|
||||
4 Steel Overseer|J22|1
|
||||
4 Urza's Saga|MH2|1
|
||||
4 Walking Ballista|J22|1
|
||||
4 Wall of Forgotten Pharaohs|AKR|1
|
||||
4 Wall of Junk|DMR|1
|
||||
[Sideboard]
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
[metadata]
|
||||
Name=Golem Sentinel 3
|
||||
[Main]
|
||||
4 Buried Ruin|ONC|1
|
||||
4 Chief of the Foundry|BRC|1
|
||||
4 Chronomaton|DDM|1
|
||||
4 Cryptic Caves|M20|1
|
||||
4 Custodian of the Trove|DTK|1
|
||||
4 Darksteel Citadel|BRC|1
|
||||
4 Desert|AFC|1
|
||||
4 Haunted Guardian|AVR|1
|
||||
4 Lightning-Core Excavator|J21|1
|
||||
4 Locthwain Gargoyle|J22|1
|
||||
4 Patchwork Automaton|NEO|1
|
||||
4 Steel Overseer|J22|1
|
||||
4 Urza's Saga|MH2|1
|
||||
4 Walking Ballista|J22|1
|
||||
4 Wall of Forgotten Pharaohs|AKR|1
|
||||
[Sideboard]
|
||||
|
||||
34
forge-gui/res/adventure/common/decks/standard/pirate2.dck
Normal file
34
forge-gui/res/adventure/common/decks/standard/pirate2.dck
Normal file
@@ -0,0 +1,34 @@
|
||||
[metadata]
|
||||
Name=Pirate 2
|
||||
[Main]
|
||||
2 Abrade|SCD|1
|
||||
2 Admiral Beckett Brass|PLIST|1
|
||||
4 Aether Hub|KLR|1
|
||||
1 Aethersphere Harvester|KLR|1
|
||||
1 Canyon Slough|AKR|1
|
||||
2 Captain Lannery Storm|J22|1
|
||||
1 Censor|J21|1
|
||||
3 Chandra, Torch of Defiance|Q06|1
|
||||
4 Deadeye Tracker|XLN|1
|
||||
4 Dire Fleet Captain|XLN|1
|
||||
2 Dire Fleet Ravager|XLN|1
|
||||
3 Dragonskull Summit|DMC|1
|
||||
2 Dreamcaller Siren|XLN|1
|
||||
3 Drowned Catacomb|SLD|1
|
||||
4 Fatal Push|F17|1
|
||||
3 Fathom Fleet Captain|XLN|1
|
||||
2 Fell Flagship|XLN|1
|
||||
1 Fetid Pools|AKR|1
|
||||
2 Fiery Cannonade|CMR|1
|
||||
3 Island|LTR|1
|
||||
3 Jace, Cunning Castaway|PS18|1
|
||||
3 Kari Zev, Skyship Raider|J22|1
|
||||
2 Lightning-Rig Crew|CMR|1
|
||||
3 Lookout's Dispersal|J22|1
|
||||
2 March of the Drowned|XLN|1
|
||||
2 Mountain|WHO|1
|
||||
4 Spirebluff Canal|KLR|1
|
||||
3 Swamp|LTR|1
|
||||
4 Unlicensed Disintegration|KLD|1
|
||||
[Sideboard]
|
||||
|
||||
29
forge-gui/res/adventure/common/decks/standard/pirate3.dck
Normal file
29
forge-gui/res/adventure/common/decks/standard/pirate3.dck
Normal file
@@ -0,0 +1,29 @@
|
||||
[metadata]
|
||||
Name=Pirate 3
|
||||
[Main]
|
||||
4 Captain Lannery Storm|J22|1
|
||||
2 Captivating Crew|XLN|1
|
||||
4 Chart a Course|JMP|1
|
||||
2 Daring Saboteur|NCC|1
|
||||
3 Dire Fleet Hoarder|2XM|1
|
||||
4 Dragonskull Summit|DMC|1
|
||||
2 Dreamcaller Siren|XLN|1
|
||||
4 Drowned Catacomb|SLD|1
|
||||
2 Evolving Wilds|SIS|1
|
||||
4 Fatal Push|F17|1
|
||||
4 Fathom Fleet Captain|XLN|1
|
||||
2 Fell Flagship|XLN|1
|
||||
2 Island|LTR|1
|
||||
4 Kitesail Freebooter|XLN|1
|
||||
4 Lookout's Dispersal|J22|1
|
||||
2 Mountain|WHO|1
|
||||
4 Negate|MOM|1
|
||||
4 Ruin Raider|XLN|1
|
||||
4 Siren Stormtamer|CMR|1
|
||||
4 Spirebluff Canal|KLR|1
|
||||
2 Swamp|LTR|1
|
||||
4 Tezzeret the Schemer|KLR|1
|
||||
2 Walk the Plank|XLN|1
|
||||
2 Wanted Scoundrels|XLN|1
|
||||
[Sideboard]
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
[metadata]
|
||||
Name=Pirate Captain 2
|
||||
[Main]
|
||||
1 Blood Money|CLB|2
|
||||
2 Deadeye Tracker|XLN|1
|
||||
4 Deadly Derision|MOM|1
|
||||
4 Desperate Castaways|MB1|1
|
||||
2 Dire Fleet Hoarder|2XM|1
|
||||
2 Dire Fleet Interloper|XLN|1
|
||||
2 Dire Fleet Poisoner|J21|1
|
||||
1 Dire Fleet Ravager|XLN|1
|
||||
4 Drain Life|5ED|1
|
||||
4 Fathom Fleet Captain|XLN|1
|
||||
2 Sleek Schooner|XLN|1
|
||||
2 Kitesail Freebooter|XLN|1
|
||||
2 March of the Drowned|XLN|1
|
||||
1 Marut|CLB|1
|
||||
4 Pirate's Cutlass|CMR|1
|
||||
1 Pitiless Plunderer|RIX|1
|
||||
2 Reckoner Bankbuster|NEO|1
|
||||
1 Revel in Riches|XLN|1
|
||||
6 Swamp|XLN|1
|
||||
8 Swamp|XLN|2
|
||||
2 Swamp|XLN|3
|
||||
4 Swamp|XLN|4
|
||||
1 Treasure Chest|AFR|3
|
||||
1 Treasure Vault|AFR|1
|
||||
2 Undercity Scrounger|NEO|1
|
||||
[Sideboard]
|
||||
25
forge-gui/res/adventure/common/decks/standard/spirit.dck
Normal file
25
forge-gui/res/adventure/common/decks/standard/spirit.dck
Normal file
@@ -0,0 +1,25 @@
|
||||
[metadata]
|
||||
Name=Spirit
|
||||
[Main]
|
||||
2 Dreamshackle Geist|DBL|1
|
||||
4 Dungeon Geists|DKA|1
|
||||
4 Ephara's Dispersal|MOM|1
|
||||
2 Geist of the Archives|EMN|1
|
||||
10 Island|MOM|1
|
||||
4 Island|MOM|2
|
||||
4 Island|MOM|3
|
||||
1 Kira, Great Glass-Spinner|JMP|1
|
||||
4 Lantern Bearer|DBL|1
|
||||
1 Latch Seeker|AVR|1
|
||||
2 Mirrorhall Mimic|DBL|1
|
||||
1 Murmuring Phantasm|JMP|1
|
||||
4 Patrician Geist|DBL|1
|
||||
4 Shriekgeist|IMA|1
|
||||
4 Sinister Sabotage|SCD|1
|
||||
1 Stormbound Geist|DKA|1
|
||||
4 Supreme Phantom|M19|1
|
||||
2 Think Tank|ODY|1
|
||||
4 Thoughtbound Phantasm|GRN|1
|
||||
4 Tocasia's Dig Site|BRO|1
|
||||
[Sideboard]
|
||||
|
||||
38
forge-gui/res/adventure/common/maps/map/_template.tmx
Normal file
38
forge-gui/res/adventure/common/maps/map/_template.tmx
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="16" tileheight="16" infinite="0" nextlayerid="7" nextobjectid="8">
|
||||
<layer id="1" name="Background" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztwTEBAAAAwqD1T20JT6AAAHgaCWAAAQ==
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="Ground" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztwTEBAAAAwqD1T20JT6AAAHgaCWAAAQ==
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="3" name="Walls" width="30" height="20">
|
||||
<properties>
|
||||
<property name="spriteLayer" type="bool" value="true"/>
|
||||
</properties>
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztwTEBAAAAwqD1T20JT6AAAHgaCWAAAQ==
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="4" name="Overlay" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztwTEBAAAAwqD1T20JT6AAAHgaCWAAAQ==
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="5" name="Objects"/>
|
||||
<objectgroup id="6" name="Waypoints">
|
||||
<object id="1" template="../obj/collision.tx" x="-32" y="0" width="32" height="320"/>
|
||||
<object id="2" template="../obj/collision.tx" x="-32" y="320" width="544" height="32"/>
|
||||
<object id="3" template="../obj/collision.tx" x="480" y="0" width="32" height="320"/>
|
||||
<object id="4" template="../obj/collision.tx" x="-32" y="-32" width="544" height="32"/>
|
||||
<object id="5" template="../obj/waypoint.tx" name="5" x="224" y="32"/>
|
||||
<object id="6" x="-64" y="-96" width="608" height="64">
|
||||
<text wrap="1">See https://github.com/Card-Forge/forge/wiki/Create-new-Maps for instructions & tips</text>
|
||||
</object>
|
||||
<object id="7" template="../obj/entry_up.tx" x="96" y="320"/>
|
||||
</objectgroup>
|
||||
</map>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="60" height="61" tilewidth="16" tileheight="16" infinite="0" nextlayerid="8" nextobjectid="184">
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="60" height="61" tilewidth="16" tileheight="16" infinite="0" nextlayerid="8" nextobjectid="188">
|
||||
<properties>
|
||||
<property name="canFailDungeon" type="bool" value="true"/>
|
||||
<property name="dungeonEffect">{
|
||||
@@ -937,7 +937,7 @@
|
||||
</property>
|
||||
<property name="spawn.Easy" type="bool" value="true"/>
|
||||
<property name="threatRange" type="int" value="30"/>
|
||||
<property name="waypoints" value=""/>
|
||||
<property name="waypoints" value="184,r185-186,186"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="54" template="../../obj/manashards.tx" x="568.5" y="927.5"/>
|
||||
@@ -1560,6 +1560,10 @@
|
||||
<object id="120" template="../../obj/waypoint.tx" x="263.667" y="463"/>
|
||||
<object id="166" template="../../obj/waypoint.tx" x="784" y="887.45"/>
|
||||
<object id="167" template="../../obj/waypoint.tx" x="734.545" y="794.73"/>
|
||||
<object id="168" template="../../obj/waypoint.tx" x="751.273" y="886.55"/>
|
||||
<object id="168" template="../../obj/waypoint.tx" x="751.273" y="886.55" visible="0"/>
|
||||
<object id="184" template="../../obj/waypoint.tx" x="256" y="512"/>
|
||||
<object id="185" template="../../obj/waypoint.tx" x="224" y="480"/>
|
||||
<object id="186" template="../../obj/waypoint.tx" x="192" y="512"/>
|
||||
<object id="187" template="../../obj/waypoint.tx" x="224" y="576"/>
|
||||
</objectgroup>
|
||||
</map>
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="30" height="40" tilewidth="16" tileheight="16" infinite="0" nextlayerid="8" nextobjectid="20">
|
||||
<tileset firstgid="1" source="../../tileset/main.tsx"/>
|
||||
<tileset firstgid="10113" source="../../tileset/rivers.tsx"/>
|
||||
<tileset firstgid="27393" source="../../tileset/main-nocollide.tsx"/>
|
||||
<tileset firstgid="37505" source="../../tileset/dungeon.tsx"/>
|
||||
<tileset firstgid="41985" source="../../tileset/FarmFood.tsx"/>
|
||||
<layer id="1" name="Background" width="30" height="40">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJyLZWFgiB3Fo3gUj+JRjBMnWgyMvaKWDAwSQHzecuDsPz1AdjdZDVy4g+yGhfm0Wdgxuh5i1RHCT61xm4dLD6X2ngP6NXkAwhrmV2ScxomK8cmhyxPr12YrwvYSwqTaa4jFrzB7J7ATh4m1F5Zvkiyw+5VW9oLKC0lLhgZ8aYkW9hKDR+2ln720zEejeBSP4lE8ikcxAMAE71k=
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="Ground" width="30" height="40">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztlktOwzAQhr2gaQVsOQewQ+otWPJq98AdvOEAOE1bNSycBQgOE9hUPMqGozDFNh3cOH61pUj80q82ztjfTOyMQshMbGR2Cu6BM3AfPAAPwTu5+GVoPJPxfc0uYoLDhx45ZHK858nSlQluV2cqqxoxJ0VxoYJ1+EDjMlEbhXEK9ynkRoFLgUOZGPt+1qGC+bwvuc8Vz1sxXuX1ANXbi+BCXRzy7gbk+8UOlcw7mnvrMAfHyPPzcQ3vCgOnudg3dX6H8r8yk3vMIuvFUvup9vEF8VJxrqxnuBXJNnkVOi0I6RRxa1xtE3JACF01N0Q+3GZNTROPeid8xn3nrrP8dMzn7RJzEpBPOzDHGI3R897dIGRPs9JhIaykx+2jWBe1EbeEuY+aTdLjngyxdxVjY+1acR8SQi4awlNNip+/U6n790k910Ulyv2IV58f/SyVlnp9uWfcHt/5Y9y3X+LqWgbXpbWuQ70jWDO3+KaG27Sw8H21xlYy349M3lzg+xviGO55Y9aHsFVP0nsZ9mUjnGtS6VmXy3esSbif+3IXJRM39Ds1lrtItSq+u+q4MXtp07rtr60nLYu7bP1z/fUJ3KlgJA==
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="3" name="Walls" width="30" height="40">
|
||||
<properties>
|
||||
<property name="spriteLayer" type="bool" value="true"/>
|
||||
</properties>
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzdld9OE0EUxmcv4a6F/qH/0Cvju5gYjZqAAone+AAlQRSF6iOgie2WtvRWo2JpLTa+g6RaLDwDGn0Bv+OeyR7b2W67hV7wJV92ujszvznnzExjJaVmikp9g492lTquOn6JNilfVSPL5jHbYr422m0wwnCs5PbV7MOCY1oDsYNyiUksPZ9mmkTssO2Y1kDMoFxyW8znxdTSOZg5A65mybwOI2J2RI2kk3DK8J58uOvWOIj+cbHmDurzHf7KpnqlK0rNw23xnnxE34vjc2M7MOoThUPCS2CuVJzahWy3jnGuZRCurke32n+uBkmem5Pq/3ONoo7Iqz5Xg5jy3FC+B+lySG16fYuJHPbeK73W90JI5NtPYPtK3ysU/y3b3Vd3bP97IYh67zSKZ1twX+mcFM1jhtUVxH51QPx6Ts0NytnLKlXLur8fhJV6GPYft1NWqlQenad1uqrUn1Xzt0XDvF28SyDOm+wkfByAT/HW4Ua2/9sy5nsRc9pb/FwAZ05wT9DnHuc7x32e47nis5b34N1AvLcNMS8bxhJzES6UHd9FO1Xp7+fHvQbedfjXkNzXYOThBM5rEi6gbQfgUqwfevaWvktM3B9gVKmm8H24S7kOwP0J7m+PvWXiDis/LumNYU9Nguuli8p9O6XUu6nJc0+ncY6mJ8/10nlzvf77L2q8XsqX3XtYeknMueDRxx6D6yWZh6BxbcHr3F6DH8HPzoG7yXMTLwfPW0o94XYG7Rh8yRqfuyEYpCjmnIUP4C/8jMB7cAPehz+fAZdiSMCfLIf/WDmMddGnhd9zQ8Q5CrfGcTU5tn1mxJmha5nkfPvVdlguiXJNNdUxNjn+p8qtbY3XQ7nIeU00ApeYlFvaL2nL+U28j5z/CMdO7xvMTlvuWFP8ftw1Zs6KWOh3StQ8yhz9zHCdN3htppoP4kom1bfGtY1YbuwZfk/7l/ZW3XLqHOen15kaxE1aLlPmKyq4LcOceh1NXmd9RG6LmaQmj9cxH4hvfwG8OnNz
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="7" name="Shading" width="30" height="40" opacity="0.55">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztw0EJADAMBLCanLsam5s9TsKgj5JAqgB2O53TbicAAAB/HhT3BM0=
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="4" name="Overlay" width="30" height="40">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJxjYBgcYPq8gTHzOpqasqkMDOVTibcDm3p0M4kB24BmbCfBXlLVDwZwg4pxTEp6ISc+6GHWQAD09EpqeicWoMc1enrFln6pUQagxw85ZQA1ADYzqZn+6Ql8lg20C+gPWFcMtAvwg8AFDAyzFwy0K4YfeLSQPDliALH5SGQBZfbAgDuRabgHj7uo5RZ0ILiAoQGZL0Qje4gFwnSwH58dnTQqY0Px2AkDYUSoGQWjYBSMglEwCgYTAADYSDkG
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="5" name="Objects">
|
||||
<object id="13" template="../../obj/entry_down.tx" x="224" y="184" width="32" height="16">
|
||||
<properties>
|
||||
<property name="teleport" value="../common/maps/map/main_story_explore/library_of_varsil_1.tmx"/>
|
||||
<property name="teleportObjectId" value="7"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="14" template="../../obj/portal.tx" x="144" y="256">
|
||||
<properties>
|
||||
<property name="portalState" value="inactive"/>
|
||||
<property name="sprite" value="sprites/portal3.atlas"/>
|
||||
<property name="teleport" value="../common/maps/map/main_story/main_story_explore/library_of_varsil_1.tmx"/>
|
||||
</properties>
|
||||
</object>
|
||||
</objectgroup>
|
||||
<objectgroup id="6" name="Waypoints">
|
||||
<object id="1" template="../../obj/collision.tx" x="-32" y="0" width="144" height="640"/>
|
||||
<object id="2" template="../../obj/collision.tx" x="-32" y="640" width="544" height="32"/>
|
||||
<object id="3" template="../../obj/collision.tx" x="368" y="0" width="144" height="640"/>
|
||||
<object id="4" template="../../obj/collision.tx" x="-32" y="-32" width="544" height="32"/>
|
||||
<object id="5" template="../../obj/waypoint.tx" name="5" x="336" y="288"/>
|
||||
<object id="7" template="../../obj/entry_up.tx" x="176" y="640" width="128" height="16"/>
|
||||
<object id="8" template="../../obj/waypoint.tx" name="8" x="128" y="288"/>
|
||||
<object id="9" template="../../obj/waypoint.tx" name="9" x="232" y="448"/>
|
||||
<object id="10" template="../../obj/enemy.tx" x="128" y="336">
|
||||
<properties>
|
||||
<property name="enemy" value="Archivist"/>
|
||||
<property name="pursueRange" type="int" value="60"/>
|
||||
<property name="threatRange" type="int" value="30"/>
|
||||
<property name="waypoints" value="r5-8-9"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="11" template="../../obj/enemy.tx" x="336" y="336">
|
||||
<properties>
|
||||
<property name="enemy" value="Archivist"/>
|
||||
<property name="pursueRange" type="int" value="60"/>
|
||||
<property name="threatRange" type="int" value="30"/>
|
||||
<property name="waypoints" value="r5-8-9"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="12" template="../../obj/enemy.tx" x="232" y="232">
|
||||
<properties>
|
||||
<property name="enemy" value="Archivist"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="15" template="../../obj/collision.tx" x="112" y="0" width="256" height="160"/>
|
||||
<object id="16" template="../../obj/collision.tx" x="112" y="464" width="96" height="176"/>
|
||||
<object id="17" template="../../obj/collision.tx" x="256" y="160" width="112" height="64"/>
|
||||
<object id="18" template="../../obj/collision.tx" x="112" y="160" width="112" height="64"/>
|
||||
<object id="19" template="../../obj/collision.tx" x="272" y="464" width="96" height="176"/>
|
||||
</objectgroup>
|
||||
</map>
|
||||
@@ -0,0 +1,244 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="16" tileheight="16" infinite="0" nextlayerid="7" nextobjectid="45">
|
||||
<tileset firstgid="1" source="../../tileset/main.tsx"/>
|
||||
<tileset firstgid="10113" source="../../tileset/buildings.tsx"/>
|
||||
<layer id="1" name="Background" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzjVWdg4B3Fo3gUj+JRPIpH8SgexVTDAA08eeE=
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="Ground" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJxjYBhaYIsEBNMbbJeAYHoDeQEGBkUB6ph1EGjOISJxOz9DgqoAQwKx6g9TyY3U9O9A2dvIz8DQRCRWAdqpLEC8+mZ+/H5QoBHGFzZ7gXL7iMRtQPe38hOvfv9ouoKD0fxLH3tHwxk74FVH2Ati0wvA6t6BqoMpAQDikGk6
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="3" name="Walls" width="30" height="20">
|
||||
<properties>
|
||||
<property name="spriteLayer" type="bool" value="true"/>
|
||||
</properties>
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJwz4WNgMBlCGAYoNccciC8BsbIKA4OqCoQG4Ut82DEMXELShwurQs0xw2KvKdSsgyr4MQgsF0XY2yJOvD5jPPbSEuCzFxQuSmjhhM5HB+jy6HGlRIR/QWFyAC2M0PnoAF0eHR8exOHMooZQh4uNCxDSOxj9i56WVCHsBnzpCkeexdCDz15GKfyYSQrTXmL1DMZwVsUSZugYHaDn9WRJzDxMyF5c+Q9f/sWV1w+rDP5ykhBoFMcUa8YiRqy9M3kZGKYRidEBsfpm8FKnzoeBgW6DkIIBPQOT6g==
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="4" name="Overlay" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztw7ENAAAIA6D+ov/f6NrVHRIS2m4yFQDg6wBDvwEe
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="5" name="Objects">
|
||||
<object id="25" template="../../obj/dialog.tx" x="192" y="200">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "Anatomical studies of various mundane animals are found on this shelf. Open on top is a text on snakes. Why did it have to be snakes?",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="26" template="../../obj/dialog.tx" x="128" y="200">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "This shelf contains books of recipes, but many of the ingredients are unfamiliar to you.",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="27" template="../../obj/dialog.tx" x="352" y="200">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "Here you find not so much books as collections of paperwork. It appears to consist of a series of caravan manifests and shipping ledgers affixed to maps. Comments and questions scribbled onto a set of calendars indicate that whomever collected these records suspected that the associated merchants were frequently conducting additional undocumented business along their routes.",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="28" template="../../obj/dialog.tx" x="400" y="200">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "'The Impact of Personal Teleportation on Intercity Commerce' - Doesn't exactly sound like a page turner.",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="29" template="../../obj/dialog.tx" x="64" y="240">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "Here you find a collection of copied plans for various goblin inventions. The transcriber added notes alongside each rating each on a scale between 'Will definitely explode' to 'Won't work well enough to explode'.",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="30" template="../../obj/dialog.tx" x="144" y="240">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "Whatever knowledge was once contained in these texts is lost, their pages long ago having been soaked in the same dark liquid that appears to have stained the shelves below them.",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="31" template="../../obj/dialog.tx" x="368" y="240">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "Dust covered tomes of nondescript subjects fill this shelf. You have a feeling these have been untouched for quite some time.",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="32" template="../../obj/dialog.tx" x="352" y="112">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "This shelf holds a journal with a sturdy cover which stands apart from the faded scrolls around it. The entries are a mystery to you, however, as they are written in some form of code.",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="33" template="../../obj/dialog.tx" x="400" y="112">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "'Azgothian poems from a Midsummer Morning'. This book gives you a creepy feeling and you wisely leave the cover closed.",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="34" template="../../obj/dialog.tx" x="400" y="64">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "Here you find a collection of biographies of wizards you've never heard of, and a quick skim of the contents makes you wonder who would bother to write these.",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="35" template="../../obj/dialog.tx" x="128" y="64">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "A collection of children's drawings fill this bookcase, although unlike most similar collections these all seem to depict arcane subjects.",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="36" template="../../obj/dialog.tx" x="80" y="64">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "Here you find a blueprint of the library itself. Unfortunately, there doesn't seem to be any list of secret passages to take advantage of.",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="39" template="../../obj/enemy.tx" x="232" y="112">
|
||||
<properties>
|
||||
<property name="enemy" value="Spirit"/>
|
||||
<property name="pursueRange" type="int" value="100"/>
|
||||
<property name="threatRange" type="int" value="40"/>
|
||||
<property name="waypoints" value="r5-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-37-38"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="40" template="../../obj/enemy.tx" x="88" y="144">
|
||||
<properties>
|
||||
<property name="enemy" value="Golem"/>
|
||||
<property name="threatRange" type="int" value="50"/>
|
||||
<property name="waypoints" value="r5-8-15,r18-21,r11-12-13-16-18-21"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="41" template="../../obj/enemy.tx" x="384" y="144">
|
||||
<properties>
|
||||
<property name="enemy" value="Golem"/>
|
||||
<property name="threatRange" type="int" value="50"/>
|
||||
<property name="waypoints" value="r5-8-15,r19-20,r19-20-37-38-14-17"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="42" template="../../obj/enemy.tx" x="384" y="256">
|
||||
<properties>
|
||||
<property name="enemy" value="Archivist"/>
|
||||
<property name="threatRange" type="int" value="40"/>
|
||||
<property name="waypoints" value="r10-14-23,r19-20,r19-20-37-38,r8-10-14-18-21"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="43" template="../../obj/enemy.tx" x="80" y="256">
|
||||
<properties>
|
||||
<property name="enemy" value="Archivist"/>
|
||||
<property name="threatRange" type="int" value="40"/>
|
||||
<property name="waypoints" value="22, r11-12, r18-21, 5, r8-15, r18-21, r11-12, r9-13"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="44" template="../../obj/enemy.tx" x="232" y="56">
|
||||
<properties>
|
||||
<property name="enemy" value="Archivist"/>
|
||||
</properties>
|
||||
</object>
|
||||
</objectgroup>
|
||||
<objectgroup id="6" name="Waypoints">
|
||||
<object id="1" template="../../obj/collision.tx" x="-32" y="0" width="32" height="320"/>
|
||||
<object id="2" template="../../obj/collision.tx" x="-32" y="320" width="544" height="32"/>
|
||||
<object id="3" template="../../obj/collision.tx" x="480" y="0" width="32" height="320"/>
|
||||
<object id="4" template="../../obj/collision.tx" x="-32" y="-32" width="544" height="32"/>
|
||||
<object id="5" template="../../obj/waypoint.tx" name="5" x="232" y="144"/>
|
||||
<object id="7" template="../../obj/entry_up.tx" x="208" y="304" width="64" height="16">
|
||||
<properties>
|
||||
<property name="teleport" value="../common/maps/map/main_story_explore/library_of_varsil_0.tmx"/>
|
||||
<property name="teleportObjectId" value="13"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="8" template="../../obj/waypoint.tx" name="8" x="232" y="208"/>
|
||||
<object id="9" template="../../obj/waypoint.tx" name="9" x="48" y="208"/>
|
||||
<object id="10" template="../../obj/waypoint.tx" name="10" x="416" y="208"/>
|
||||
<object id="11" template="../../obj/waypoint.tx" name="11" x="48" y="128"/>
|
||||
<object id="12" template="../../obj/waypoint.tx" name="12" x="48" y="160"/>
|
||||
<object id="13" template="../../obj/waypoint.tx" name="13" x="48" y="80"/>
|
||||
<object id="14" template="../../obj/waypoint.tx" name="14" x="416" y="80"/>
|
||||
<object id="15" template="../../obj/waypoint.tx" name="15" x="232" y="80"/>
|
||||
<object id="16" template="../../obj/waypoint.tx" name="16" x="48" y="256"/>
|
||||
<object id="17" template="../../obj/waypoint.tx" name="17" x="416" y="256"/>
|
||||
<object id="18" template="../../obj/waypoint.tx" name="18" x="130" y="158"/>
|
||||
<object id="19" template="../../obj/waypoint.tx" name="19" x="334" y="158"/>
|
||||
<object id="20" template="../../obj/waypoint.tx" name="20" x="334" y="128"/>
|
||||
<object id="21" template="../../obj/waypoint.tx" name="21" x="130" y="128"/>
|
||||
<object id="22" template="../../obj/waypoint.tx" name="22" x="128" y="256">
|
||||
<properties>
|
||||
<property name="type" value="waypoint"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="23" template="../../obj/waypoint.tx" name="23" x="336" y="256"/>
|
||||
<object id="24" template="../../obj/entry_down.tx" x="224" y="32" width="32" height="16">
|
||||
<properties>
|
||||
<property name="teleport" value="../common/maps/map/main_story_explore/library_of_varsil_2.tmx"/>
|
||||
<property name="teleportObjectId" value="7"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="37" template="../../obj/waypoint.tx" name="37" x="416" y="128"/>
|
||||
<object id="38" template="../../obj/waypoint.tx" name="38" x="416" y="160"/>
|
||||
</objectgroup>
|
||||
</map>
|
||||
@@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="16" tileheight="16" infinite="0" nextlayerid="7" nextobjectid="48">
|
||||
<tileset firstgid="1" source="../../tileset/main.tsx"/>
|
||||
<tileset firstgid="10113" source="../../tileset/buildings.tsx"/>
|
||||
<layer id="1" name="Background" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzjVWdg4B3Fo3gUj+JRPIpH8SgexVTDAA08eeE=
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="Ground" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJxjYBhaYIsEBNMbbJeAYHoDeQEGBkUB6ph1EGjOISJxOz9DgqoAQwKx6g9TyY3U9O9A2dvIz8DQRCRWAdqpLEC8+mZ+/H5QoBHGFzZ7gXL7iMRtQPe38hOvfv9ouoKD0fxLH3tHwxk74FVH2Ati0wvA6t6BqoMpAQDikGk6
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="3" name="Walls" width="30" height="20">
|
||||
<properties>
|
||||
<property name="spriteLayer" type="bool" value="true"/>
|
||||
</properties>
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJwz4WNgMBlCGAYoNccciC8BsbIKAquqoPJB+BJUHQxcwqIPHatC9ZlhsdcUatZBFfwYBJrEEfY2ihOvzxiPvbQE+OxVUmFowBdmyiqY5mGLD2QxJSL8e4BAeB3EYi8h9YM5nFnUEOr+SSLYyOK4AC69q0QJ20tLgM9e9PQBSmfo6QYdoKWnBmxsQvYySjEwMElBaHQME0cH2NSiY0L20hIQE87Y8iQx4QzKq8mSmPoJ2YsvDx4mIv+i539kPYMtnHNEGBiyRRDqkNkw0CKOKdaIJJYjgspGNgObvTN5GRimEYnRAbH6ZvBSp86HgYFug5CCARwpl9Q=
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="4" name="Overlay" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztwTEBAAAAwqD1T20JT6AAAHgaCWAAAQ==
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="5" name="Objects">
|
||||
<object id="25" template="../../obj/enemy.tx" x="80" y="272">
|
||||
<properties>
|
||||
<property name="enemy" value="Mimic"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="26" template="../../obj/dialog.tx" x="272" y="112"/>
|
||||
<object id="27" template="../../obj/dialog.tx" x="352" y="112"/>
|
||||
<object id="28" template="../../obj/dialog.tx" x="320" y="200">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "'Magical Meteorology', 'The Destructive Power of the Heavens', these books all seem to focus on things falling from the sky.",
|
||||
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="29" template="../../obj/dialog.tx" x="368" y="200"/>
|
||||
<object id="30" template="../../obj/dialog.tx" x="80" y="200"/>
|
||||
<object id="31" template="../../obj/dialog.tx" x="144" y="200">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"text": "Here you find a collection of biographies of wizards you've never heard of. None of them seem to have done anything significant.",
|
||||
"options": [{
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="32" template="../../obj/dialog.tx" x="176" y="200"/>
|
||||
<object id="34" template="../../obj/dialog.tx" x="400" y="64"/>
|
||||
<object id="35" template="../../obj/dialog.tx" x="112" y="64"/>
|
||||
<object id="36" template="../../obj/dialog.tx" x="96" y="240"/>
|
||||
<object id="37" template="../../obj/dialog.tx" x="176" y="240"/>
|
||||
<object id="38" template="../../obj/dialog.tx" x="352" y="240"/>
|
||||
<object id="39" template="../../obj/dialog.tx" x="384" y="240"/>
|
||||
<object id="40" template="../../obj/enemy.tx" x="232" y="160">
|
||||
<properties>
|
||||
<property name="enemy" value="Golem Sentinel"/>
|
||||
<property name="pursueRange" type="int" value="60"/>
|
||||
<property name="threatRange" type="int" value="40"/>
|
||||
<property name="waypoints" value="r5-8-15-18-19-20-21,r5-8-15-18-19-20-21-22-23"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="41" template="../../obj/enemy.tx" x="48" y="224">
|
||||
<properties>
|
||||
<property name="enemy" value="Black Golem"/>
|
||||
<property name="threatRange" type="int" value="50"/>
|
||||
<property name="waypoints" value="22,r11-12,r18-21,5,r8-15, r18-21, r11-12,r9-13"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="42" template="../../obj/enemy.tx" x="416" y="224">
|
||||
<properties>
|
||||
<property name="enemy" value="Black Golem"/>
|
||||
<property name="threatRange" type="int" value="50"/>
|
||||
<property name="waypoints" value="23,r45-46,r19-20,r8-15,r19-20,r45-46,r10-14"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="43" template="../../obj/enemy.tx" x="232" y="48">
|
||||
<properties>
|
||||
<property name="enemy" value="Spirit"/>
|
||||
<property name="spawn.Easy" type="bool" value="true"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="44" template="../../obj/enemy.tx" x="232" y="112">
|
||||
<properties>
|
||||
<property name="enemy" value="Spirit"/>
|
||||
<property name="pursueRange" type="int" value="100"/>
|
||||
<property name="spawn.Easy" type="bool" value="false"/>
|
||||
<property name="threatRange" type="int" value="40"/>
|
||||
<property name="waypoints" value="r5-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-45-46,w2"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="47" template="../../obj/treasure.tx" x="304" y="272"/>
|
||||
</objectgroup>
|
||||
<objectgroup id="6" name="Waypoints">
|
||||
<object id="1" template="../../obj/collision.tx" x="-32" y="0" width="32" height="320"/>
|
||||
<object id="2" template="../../obj/collision.tx" x="-32" y="320" width="544" height="32"/>
|
||||
<object id="3" template="../../obj/collision.tx" x="480" y="0" width="32" height="320"/>
|
||||
<object id="4" template="../../obj/collision.tx" x="-32" y="-32" width="544" height="32"/>
|
||||
<object id="5" template="../../obj/waypoint.tx" name="5" x="232" y="144"/>
|
||||
<object id="7" template="../../obj/entry_up.tx" x="208" y="304" width="64" height="16">
|
||||
<properties>
|
||||
<property name="teleport" value="../common/maps/map/main_story_explore/library_of_varsil_1.tmx"/>
|
||||
<property name="teleportObjectId" value="24"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="8" template="../../obj/waypoint.tx" name="8" x="232" y="208"/>
|
||||
<object id="9" template="../../obj/waypoint.tx" name="9" x="48" y="208"/>
|
||||
<object id="10" template="../../obj/waypoint.tx" name="10" x="416" y="208"/>
|
||||
<object id="11" template="../../obj/waypoint.tx" name="11" x="48" y="128"/>
|
||||
<object id="12" template="../../obj/waypoint.tx" name="12" x="48" y="160"/>
|
||||
<object id="13" template="../../obj/waypoint.tx" name="13" x="48" y="80"/>
|
||||
<object id="14" template="../../obj/waypoint.tx" name="14" x="416" y="80"/>
|
||||
<object id="15" template="../../obj/waypoint.tx" name="15" x="232" y="80"/>
|
||||
<object id="16" template="../../obj/waypoint.tx" name="16" x="48" y="256"/>
|
||||
<object id="17" template="../../obj/waypoint.tx" name="17" x="416" y="256"/>
|
||||
<object id="18" template="../../obj/waypoint.tx" name="18" x="130" y="158"/>
|
||||
<object id="19" template="../../obj/waypoint.tx" name="19" x="334" y="158"/>
|
||||
<object id="20" template="../../obj/waypoint.tx" name="20" x="334" y="128"/>
|
||||
<object id="21" template="../../obj/waypoint.tx" name="21" x="130" y="128"/>
|
||||
<object id="22" template="../../obj/waypoint.tx" name="22" x="128" y="256"/>
|
||||
<object id="23" template="../../obj/waypoint.tx" name="23" x="336" y="256"/>
|
||||
<object id="24" template="../../obj/entry_down.tx" x="224" y="32" width="32" height="16">
|
||||
<properties>
|
||||
<property name="teleport" value="../common/maps/map/main_story_explore/library_of_varsil_3.tmx"/>
|
||||
<property name="teleportObjectId" value="7"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="45" template="../../obj/waypoint.tx" name="45" x="416" y="160"/>
|
||||
<object id="46" template="../../obj/waypoint.tx" name="46" x="416" y="128"/>
|
||||
</objectgroup>
|
||||
</map>
|
||||
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="16" tileheight="16" infinite="0" nextlayerid="7" nextobjectid="49">
|
||||
<tileset firstgid="1" source="../../tileset/main.tsx"/>
|
||||
<tileset firstgid="10113" source="../../tileset/buildings.tsx"/>
|
||||
<layer id="1" name="Background" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzjVWdg4B3Fo3gUj+JRPIpH8SgexVTDAA08eeE=
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="Ground" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJxjYBhaYIsEBNMbbJeAYHoDeQEGBkUB6ph1EGjOISJxOz9DgqoAQwKx6g9TyY3U9O9A2dvIz8DQRCRWAdqpLEC8+mZ+/H5QoBHGFzZ7gXL7iMRtQPe38hOvfv9ouoKD0fxLH3tHwxk74FVH2Ati0wvA6t6BqoMpAQDikGk6
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="3" name="Walls" width="30" height="20">
|
||||
<properties>
|
||||
<property name="spriteLayer" type="bool" value="true"/>
|
||||
</properties>
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzVVlsOwiAQXI2/9c806WelXsCq10PjGYyewGtU7Qk4kRAgJSsL+Io4yQSa7DDphAXaKUD7R7R4d52NpJCcM4CG6dFHYeoshKOj2Bjd2uO7MmtdZE3P9OijwrYEbn335aALUWEZ8P0mQr4ql5oBx1nVzhyDytbVxnxVJh3KCH9jxDK+ZZzzZDHUUXMKMW2O/4v3ka+XMYh9xbEm5DuqwhxXj76pmhxzps5It6cxQudjas5U/6X2b+fRXZk+V3PMOYadcydYnGev+54KgEMiMVJ1x+Izd77Fr98gz/AOyNmTVw==
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="4" name="Overlay" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztwTEBAAAAwqD1T20JT6AAAHgaCWAAAQ==
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="5" name="Objects">
|
||||
<object id="38" template="../../obj/enemy.tx" x="232" y="58">
|
||||
<properties>
|
||||
<property name="enemy" value="Golem Sentinel"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="39" template="../../obj/enemy.tx" x="192" y="144">
|
||||
<properties>
|
||||
<property name="enemy" value="Golem Sentinel"/>
|
||||
<property name="pursueRange" type="int" value="60"/>
|
||||
<property name="threatRange" type="int" value="40"/>
|
||||
<property name="waypoints" value="r11-12-15-18-21, r8-19-20-43-44"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="40" template="../../obj/enemy.tx" x="272" y="144">
|
||||
<properties>
|
||||
<property name="enemy" value="Golem Sentinel"/>
|
||||
<property name="pursueRange" type="int" value="60"/>
|
||||
<property name="threatRange" type="int" value="40"/>
|
||||
<property name="waypoints" value="r8-19-20-43-44, r11-12-15-18-21"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="41" template="../../obj/enemy.tx" x="424" y="144">
|
||||
<properties>
|
||||
<property name="enemy" value="Spirit"/>
|
||||
<property name="pursueRange" type="int" value="100"/>
|
||||
<property name="threatRange" type="int" value="50"/>
|
||||
<property name="waypoints" value="r10-14-17-43-44,w10"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="42" template="../../obj/enemy.tx" x="40" y="144">
|
||||
<properties>
|
||||
<property name="enemy" value="Spirit"/>
|
||||
<property name="pursueRange" type="int" value="100"/>
|
||||
<property name="threatRange" type="int" value="50"/>
|
||||
<property name="waypoints" value="r9-11-12-13-16,w10"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="45" template="../../obj/enemy.tx" x="232" y="184">
|
||||
<properties>
|
||||
<property name="enemy" value="Black Golem"/>
|
||||
<property name="pursueRange" type="int" value="60"/>
|
||||
<property name="threatRange" type="int" value="40"/>
|
||||
<property name="waypoints" value="r8-15,w5,5,w5,r12-19-20-21,w5"/>
|
||||
</properties>
|
||||
</object>
|
||||
</objectgroup>
|
||||
<objectgroup id="6" name="Waypoints">
|
||||
<object id="1" template="../../obj/collision.tx" x="-32" y="0" width="32" height="320"/>
|
||||
<object id="2" template="../../obj/collision.tx" x="-32" y="320" width="544" height="32"/>
|
||||
<object id="3" template="../../obj/collision.tx" x="480" y="0" width="32" height="320"/>
|
||||
<object id="4" template="../../obj/collision.tx" x="-32" y="-32" width="544" height="32"/>
|
||||
<object id="5" template="../../obj/waypoint.tx" name="5" x="232" y="144"/>
|
||||
<object id="7" template="../../obj/entry_up.tx" x="208" y="304" width="64" height="16">
|
||||
<properties>
|
||||
<property name="teleport" value="../common/maps/map/main_story_explore/library_of_varsil_2.tmx"/>
|
||||
<property name="teleportObjectId" value="24"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="8" template="../../obj/waypoint.tx" name="8" x="232" y="208"/>
|
||||
<object id="9" template="../../obj/waypoint.tx" name="9" x="48" y="208"/>
|
||||
<object id="10" template="../../obj/waypoint.tx" name="10" x="416" y="208"/>
|
||||
<object id="11" template="../../obj/waypoint.tx" name="11" x="48" y="128"/>
|
||||
<object id="12" template="../../obj/waypoint.tx" name="12" x="48" y="160"/>
|
||||
<object id="13" template="../../obj/waypoint.tx" name="13" x="48" y="80"/>
|
||||
<object id="14" template="../../obj/waypoint.tx" name="14" x="416" y="80"/>
|
||||
<object id="15" template="../../obj/waypoint.tx" name="15" x="232" y="80"/>
|
||||
<object id="16" template="../../obj/waypoint.tx" name="16" x="48" y="256"/>
|
||||
<object id="17" template="../../obj/waypoint.tx" name="17" x="416" y="256"/>
|
||||
<object id="18" template="../../obj/waypoint.tx" name="18" x="130" y="158"/>
|
||||
<object id="19" template="../../obj/waypoint.tx" name="19" x="334" y="158"/>
|
||||
<object id="20" template="../../obj/waypoint.tx" name="20" x="334" y="128"/>
|
||||
<object id="21" template="../../obj/waypoint.tx" name="21" x="130" y="128"/>
|
||||
<object id="22" template="../../obj/waypoint.tx" name="22" x="128" y="256"/>
|
||||
<object id="23" template="../../obj/waypoint.tx" name="23" x="336" y="256"/>
|
||||
<object id="24" template="../../obj/entry_down.tx" x="224" y="32" width="32" height="16">
|
||||
<properties>
|
||||
<property name="teleport" value="../common/maps/map/main_story_explore/library_of_varsil_4.tmx"/>
|
||||
<property name="teleportObjectId" value="40"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="26" template="../../obj/dialog.tx" x="144" y="240"/>
|
||||
<object id="27" template="../../obj/dialog.tx" x="64" y="240"/>
|
||||
<object id="28" template="../../obj/dialog.tx" x="128" y="200"/>
|
||||
<object id="29" template="../../obj/dialog.tx" x="192" y="200"/>
|
||||
<object id="30" template="../../obj/dialog.tx" x="368" y="240"/>
|
||||
<object id="31" template="../../obj/dialog.tx" x="400" y="199"/>
|
||||
<object id="32" template="../../obj/dialog.tx" x="352" y="200"/>
|
||||
<object id="33" template="../../obj/dialog.tx" x="400" y="112"/>
|
||||
<object id="34" template="../../obj/dialog.tx" x="352" y="112"/>
|
||||
<object id="35" template="../../obj/dialog.tx" x="80" y="64"/>
|
||||
<object id="36" template="../../obj/dialog.tx" x="400" y="64"/>
|
||||
<object id="37" template="../../obj/dialog.tx" x="400" y="240"/>
|
||||
<object id="43" template="../../obj/waypoint.tx" name="43" x="416" y="128"/>
|
||||
<object id="44" template="../../obj/waypoint.tx" name="44" x="416" y="160"/>
|
||||
<object id="47" template="../../obj/enemy.tx" x="80" y="256">
|
||||
<properties>
|
||||
<property name="enemy" value="Construct"/>
|
||||
<property name="threatRange" type="int" value="50"/>
|
||||
<property name="waypoints" value="r16-22,r11-12,r18-21,5,r8-15, r18-21, r11-12,r9-13"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="48" template="../../obj/enemy.tx" x="384" y="256">
|
||||
<properties>
|
||||
<property name="enemy" value="Construct"/>
|
||||
<property name="threatRange" type="int" value="50"/>
|
||||
<property name="waypoints" value="23,10, r5-19-20"/>
|
||||
</properties>
|
||||
</object>
|
||||
</objectgroup>
|
||||
</map>
|
||||
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="16" tileheight="16" infinite="0" nextlayerid="7" nextobjectid="43">
|
||||
<tileset firstgid="1" source="../../tileset/main.tsx"/>
|
||||
<tileset firstgid="10113" source="../../tileset/buildings.tsx"/>
|
||||
<tileset firstgid="11905" source="../../tileset/dungeon.tsx"/>
|
||||
<tileset firstgid="16385" source="../../tileset/dungeon-nocollide.tsx"/>
|
||||
<tileset firstgid="20865" source="../../tileset/buildings-nocollide.tsx"/>
|
||||
<layer id="1" name="Background" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzjVWdg4B1CGAbQxQbaXaN4FI/iUTyKR/EoHsUwDADG93lF
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="Ground" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJxjYBgFowATNPIzMDTz099eeQEGBkUB+toJ8qsK0E5lAfr6GeRXBSim1M/RNgNjLymA1vaK+FLX3hBrPHI+hPWTau91oH038NhJLKBlOE/B4296patQtHimhb1XaBC/lIIwX4aGgbAXBgbK3u0SqHgoAQAY1RaZ
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="3" name="Walls" width="30" height="20">
|
||||
<properties>
|
||||
<property name="spriteLayer" type="bool" value="true"/>
|
||||
</properties>
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJwz4WNgMBmB2ByIL9EYm2Gx1xSIaQ2MR+0dlvZetMZvb7QNcTjWBmFmJJC9wAbTrms+mGKU+jcOyZ54LHbiArSw9yowLEWh4XnRioEhBMq+Ys3QQIm94ta47b1mjapOEMq/DKXDfRkYInxJszfcjzj/ooMr1phitIxfYHpKwKWPVvai+3GSNaoYOfZKIKUPfP6VwBK+lNiLDKiZj2byMjBMIxKj20usvhm8lNXV6GCg2w6kYACuCn5U
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="4" name="Overlay" width="30" height="20">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJxjYBgFo2AUjALaAHEf6qojFoQTaR6x6kYBdkDteCMWEBtvEaPxOwoGEAAAArYDtw==
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="5" name="Objects">
|
||||
<object id="26" template="../../obj/scroll.tx" x="272" y="80">
|
||||
<properties>
|
||||
<property name="reward" value="[ { "type": "card", "cardName": "Myr Convert", "count": 1 }, { "type": "card", "cardName": "Coretapper", "count": 1 }, { "type": "card", "cardName": "Myr Custodian", "count": 1 }, { "type": "card", "cardName": "Myr Adapter", "count": 1 } ]"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="27" template="../../obj/enemy.tx" x="232" y="172">
|
||||
<properties>
|
||||
<property name="enemy" value="Myr Superion"/>
|
||||
<property name="pursueRange" type="int" value="200"/>
|
||||
<property name="spawn.Hard" type="bool" value="false"/>
|
||||
<property name="spawn.Normal" type="bool" value="false"/>
|
||||
<property name="threatRange" type="int" value="50"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="28" template="../../obj/enemy.tx" x="232" y="162">
|
||||
<properties>
|
||||
<property name="effect" value="{ "startBattleWithCard": [ "Alpha Myr", "Omega Myr"]}"/>
|
||||
<property name="enemy" value="Myr Superion"/>
|
||||
<property name="pursueRange" type="int" value="200"/>
|
||||
<property name="spawn.Easy" type="bool" value="false"/>
|
||||
<property name="spawn.Hard" type="bool" value="false"/>
|
||||
<property name="spawn.Normal" type="bool" value="true"/>
|
||||
<property name="threatRange" type="int" value="50"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="29" template="../../obj/enemy.tx" x="232" y="152">
|
||||
<properties>
|
||||
<property name="effect" value="{ "startBattleWithCard": [ "Myr Turbine", "Alpha Myr", "Omega Myr"]}"/>
|
||||
<property name="enemy" value="Myr Superion"/>
|
||||
<property name="pursueRange" type="int" value="200"/>
|
||||
<property name="spawn.Easy" type="bool" value="false"/>
|
||||
<property name="spawn.Hard" type="bool" value="true"/>
|
||||
<property name="spawn.Normal" type="bool" value="false"/>
|
||||
<property name="threatRange" type="int" value="50"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="33" template="../../obj/dialog.tx" x="176" y="112" width="128" height="64"/>
|
||||
<object id="34" template="../../obj/portal.tx" x="232" y="88">
|
||||
<properties>
|
||||
<property name="portalState" value="open"/>
|
||||
<property name="sprite" value="sprites/portal3.atlas"/>
|
||||
<property name="teleport" value="../common/maps/map/main_story_explore/library_of_varsil_0.tmx"/>
|
||||
<property name="teleportObjectId" value="14"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="35" template="../../obj/dialog.tx" x="176" y="272" width="128" height="64"/>
|
||||
<object id="36" template="../../obj/collision.tx" x="-32" y="0" width="32" height="320"/>
|
||||
<object id="37" template="../../obj/collision.tx" x="272" y="176" width="176" height="112"/>
|
||||
<object id="38" template="../../obj/collision.tx" x="480" y="0" width="32" height="320"/>
|
||||
<object id="39" template="../../obj/collision.tx" x="-32" y="-32" width="544" height="32"/>
|
||||
<object id="40" template="../../obj/entry_up.tx" x="208" y="304" width="64" height="16">
|
||||
<properties>
|
||||
<property name="teleport" value="../common/maps/map/main_story_explore/library_of_varsil_3.tmx"/>
|
||||
<property name="teleportObjectId" value="24"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="41" template="../../obj/collision.tx" x="92" y="309" width="544" height="32"/>
|
||||
<object id="42" template="../../obj/collision.tx" x="32" y="144" width="176" height="144"/>
|
||||
</objectgroup>
|
||||
<objectgroup id="6" name="Waypoints">
|
||||
<object id="5" template="../../obj/waypoint.tx" name="WP1" x="232" y="144"/>
|
||||
</objectgroup>
|
||||
</map>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="50" height="40" tilewidth="16" tileheight="16" infinite="0" nextlayerid="6" nextobjectid="104">
|
||||
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="50" height="40" tilewidth="16" tileheight="16" infinite="0" nextlayerid="7" nextobjectid="118">
|
||||
<editorsettings>
|
||||
<export target="wastetown..tmx" format="tmx"/>
|
||||
<export target="waste_town.abandoned.tmx" format="tmx"/>
|
||||
</editorsettings>
|
||||
<properties>
|
||||
<property name="preventEscape" type="bool" value="true"/>
|
||||
@@ -13,12 +13,12 @@
|
||||
<tileset firstgid="30977" source="../../tileset/rivers-nocolide.tsx"/>
|
||||
<layer id="1" name="Background" width="50" height="40">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztk0EKwjAURLN3p+cQREHrzQqCincQT+E99CAuvIUJrRDEtjHWziTO4pEufmEe/085MqYkZl4Ys1vhc/TBcY3P8C1bu4vJEp9Du6i4F/gMfZBTz53L1XbkVr8O322cWH/Om+p13Z/VTnv7fUqsQ24vF5t98dKZaUYdQmcQQggRx8EjZMaf7fqPhXf5m5yYYfYIzdZ0Qyx3FZIx1AV9VzE7yeGuGF1ib+dfPIZ2yeGmfuWD9PjUqW0Onf+Zrc2ryxudP8YvReTBhTy4kAcX8uBiKI8HlhcNkA==
|
||||
eJztmUsOgjAURTt3pK7D/4e6BHfEx6hxCRrjKlyGiS7EgbuQFyBpCIUCr320YXCDA0zuyX23H/UHjPkd1pIzdvLofWDovqP30FbHOIvxlt5Hn0WiH6f3gCGXeg4sn7gj3/QJEtlGlvXnGSVP6P48ZTrHnx+WdQhyecfeV7nOTBzqELUHLGW9iRxaE/YhY0PLul/G48p6ffDcYIEzjQvnGmCA+bK9K9m+UieTiyCVd8R3q77XVK9tkgVW54v8y5iwBQywp2D0hJIjy2Uh2fNVvclmyMRciZLloeJRlcUEx7SkI00yoZgrkSW/BmMzmGKBPX7D1TjacOpkgPvXLNd3XRy6WK4BY7dAfzd0ZgE55O+QOnl0cdS996p6NckRFnSiiqGMq4pbVxZY53YTa6lMmL8NU3HUnaeucmDfA3uOngMUIP9OQsVRdLa1kQOEOVtUHGuO+7+iKY4/AhwTSA==
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="Ground" width="50" height="40">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzVWc1uEzEQdtpDtT95hg03pPIMRaENPEGFOC+8B6WPwA0O20q0Vd6plVBDzj2gcgKJddejTgaPPf5JGkay4v0bzzf/dpQKo7ZU6n0/DmqldqrVsVsFMgukrud/XedZZ2RkvqkHnjvo+nzNOGD9l/1aH8o0PlonZ9UgM8zhehOU0yZPTWAT7d+pdnlKAj/QdrH5GMTw/4KxY3x6tMF4XSeNmNz5rVBqzzMuCztP17cXAr54PO/HrcdXWlMTYvPAlOHP3fc9iyXO16T0vbTr0KU/H47c8dqi+p0rb/9u3DhgzVzx2pIeJGf9ceHInXOgD4Fhqz9at3+acN4cDtBdjv4D86P9ILXLl4lSXyfh/DkcI2adWKK24HpCV6505VYuB2wCR6i/+nLS2/G/96AX5HDY8ljryGuYH9gB02dGtp9j9VGKgyNXHQC5IFb18PWOkDdiawvg+MHgwfeXaM7pCPRO90E+G3K9ipQ0jqoYho8+CdYBveN61lWPzyCnUpt0xA6LctDha+aXzl8xdd7Wnz0jfsvhAP+gPuKzCaZ5Meit6H8n9eMoi2HAXP9qG2h79PHygOlNOXyrxwxd67k0jqhegbT+Q/oOwHFK3lta5GjqQb7SgRnjtfGQEvY1CY6TahXH3Qv3+xI9A95ZAhacVyU4GqM/jUOyLzkUxseRyQdXgnxgI1zrpH2Z9q3jMa/rAskisccvw2tuwfDO//kDxfQAc2MPTsYZui+N39Q9VcwZ1AnKMff7vT730+Wblv764eo9YghihNsDxsTHrcGB4wPkxmexuc/fGpJDNa4ZqYVLY7MFuo/fgdy0MLWkILWQ1u6U/le6R27q1RoBuKZIRlw/MG4bBryvPYvwfUr4PDXEPxtU36iM8BzXf/p8Hee42L4he825wUFrf8i6uXDY9rYh+TkFB9dLxfKCM+HQPWEqjpxE/38K0c824cD28GGge+1UHPeWvXsqdRGybJM9UmjbcMSeF28bDnzOEoJFikPHVWos/AX21dQX
|
||||
eJzVWUtOG0EQ7SELNB+fYcwOCc5A5IDDCRBiPXAPPkdgRxZDpJDIdwIpwnjNAsEKJKaZLlEudfXfYEoquedX3a/+3RbCj5pCiMOOtyohVsp5/lZ6CvOktpN/XaWZJ1Nrvql6mSvo+veCccD837u5joo4OVInl2W/ZhjD9UdQSpt8NoFNpH/H2uUzCfxA2kXnYxDDXwVjy/h09oHxukjKmNz5Jxdi1cJ/c71M07dXDnIxr3d8a/GVRtWE0DwwYuRz923PQonzNSBb7Pwv9Do06c+GI3W8Nqh+p8rbz7UZB8yZKl4b0oOkrD8mHKlzDvQhwLr6I3X7UvvL5nCA7lL0H1ge7QepXS6GQvwa+svncGTMPKFEbQH9IM0Hplxpyq1cDkiNA3qymN7clpP2B+Z5dfPp8lhjyWtZyffm58w3DwNx7IqDI1MdAJwQq5JtvWNsbw447hg8+P4MjTkdgd7pPshmw1iSOMq8ZxudOswPesf1rC3fn0FOteW5adHr8CfzS8c/mDqv68/WKjcckGuoj/jYZJL3esu732H1zkXeM4zlr7SBtEcXL2+Ydov+W8ljdC3HrnHUMv4t9e/TdwCOM/LeTLOOuurXVxgwY7w6Ga6Efc0Fx0k5j+N+0/y+i54B7zgCi299qJX+JA6Xfcm2Y3zsqHzwzyEf6MhUHziSvrU34HWdo7W42ONJyZpoMBzYP3+jkB5gouzBrXGM7rvGb+yeKqTOnaAc87jR6XMjfn2jwl4/bL2HL0GMcHvAkPi4VThwfMC68Vls6lpdkxwqcY1JLZwpm03RffwO5KapqiU5qYW0dsf0HK575LqarxGAa4TWiOsHxq3DgPe1lwG+Twmfp/r4Z43qG10jPMf1nz5fxDkutq/PXnOicNDa7zNvKhy6va1Pfo7BwfVSobLgTBhwuMqOxZGS6P9PPvpZJhzYHjYMdK8di+NRs3ePpTZgLctkjxhaNhyh58XLhgOfs/hgccUh4yo2Fl4BWmjU8A==
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="3" name="Walls" width="50" height="40">
|
||||
@@ -26,7 +26,7 @@
|
||||
<property name="spriteLayer" type="bool" value="true"/>
|
||||
</properties>
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztmE1OAjEUx58JRDCBlQvDmDCyQnBjNG5040ov4MLLmLkDRghH0Avgx4KNew8gxngGFRea2AITam2nr18zY+SXNAxD6fTf/2tfpwALFuDohRBl3YcsGBQAgj9abgpzHSdFsb7zkv8x3C7b/Z/tO3vdKWUTkztbALukBNXk54+aAE/N+XeZDh9chLh6e0v6bevoOFwBqFUnY/WDOvO9S8q4DfDRVj/7KgC4rarrJUHWsgkYHY9kDo0KUx0uiOfbkGi4I/HTD+3bxOg4q0w/XelgITEUfdbt21Hp6DBrFdURz0OX8H50DNZH3fnhC53xEeUBVzpInEMPIML2x5WvL6vTT5EOma/PRMdyOblkRZr5wyc6Oi4Du2f53N8k6YhzjIyGZQ5zCcYPfr6sW/ZfNMdDpk0T32Q64nXAFFlfXORuEXmZ53XO46Gm5zo6agbxpJubTfcorvzgY36/BXDQUtej0H0vf3/Dox8Y6DtGN9T/zRZTHdT/r1kM9BXnGaez/fK4gmtbladE7ywmOt5w1Sak8W5PcR1X12SsjjYBjkm5X/v9OzsPZNcm5GXdZXlo4OqRHBfF10k6sGcx2PODWd1IdL8ruY9dt239wMS/qi8DB/s0l3GFGTvbPbMMtu+vRb/nlRRfZ6/vmh7wY66KK95jE89Nzh1c40JHHtDRkVbONOE/+sGSN2/+ux95I20d3yTbck0=
|
||||
eJztWElOwzAU/UitaJHaFQvUIDV01YENArGBDSu4AAsug3KHIlr1CHCBMiy6Yc8BKEKcASgLkHAm1Zg4/p6SoPZJVibH+c/vD44BllgCh6ELXt425IFxCcD5p+22NOdxWk7md1GxP4c7Vb33advp834lH5/c3QbYI82pp39/2gZ4bs+veTxs4NLF9dtfkR9bhsfRGkCjHszVLzSp6wFpsx7AZ0/87WsH4K4u7pcGkssCYHg8kRialkIeJhDH24RwuCf+M3L1x8TwOK+FR1M8aBAf8r6a+uOIePSpXOXziOPQJFg9+gr5MYlHh5MDbegRQ2Z+kuqAbJzzQPwchgAe1h5Tur6uh0eWR5qmL4THajW95YUs64dNyPC4cvS+ZXN9k8YjrjE8tDRrmElg9GBjZlPT/qQYd6kxVXTj8YjzgCp4tpio3UkoSpw3GY0nkprL8Ggo+JNsbVZdo5jSg/X5gy7AYVfcz4e/7mXvb1nUAwP/H2Pgyj/ThSoPX//vyAdGgv2Ms2i9PKvhxhbVqaR/FhUe77huAbL4t/fB48HGdLsaNhFuyHvHHYAT0h42/j6n44B3roKi5F0ajy1cP1LjvPg8jQd2Lwa7fxD19ZLuDzj3sXlbVw+M/4tsGRtYp5n0K8zcYdfMstxo29/KdvcrA/ss7Yt+SGrAzrnIr1iNi5JLZLGIPLKqmSpYRD1oFE2bRdejaMiaxw9yRHM0
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="5" name="Overlay" width="50" height="40">
|
||||
@@ -35,7 +35,7 @@
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="4" name="Objects">
|
||||
<object id="38" template="../../obj/entry_up.tx" x="364" y="592" width="56" height="16"/>
|
||||
<object id="38" template="../../obj/entry_up.tx" x="364" y="624" width="56" height="16"/>
|
||||
<object id="55" template="../../obj/treasure.tx" x="432" y="304" visible="0">
|
||||
<properties>
|
||||
<property name="reward">[{
|
||||
@@ -110,48 +110,60 @@
|
||||
<object id="67" template="../../obj/enemy.tx" x="495.333" y="236.667">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="speedModifier" type="float" value="5"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="68" template="../../obj/enemy.tx" x="473.333" y="350.667">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="69" template="../../obj/enemy.tx" x="219.333" y="212.667">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="70" template="../../obj/enemy.tx" x="240.667" y="396.667">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="71" template="../../obj/enemy.tx" x="658" y="303.333">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="speedModifier" type="float" value="2"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="72" template="../../obj/enemy.tx" x="534.667" y="482">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
<property name="fleeRange" value="5000"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="threatRange" type="int" value="2000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="73" template="../../obj/enemy.tx" x="354.667" y="291.333">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="74" template="../../obj/enemy.tx" x="79.3333" y="398.667">
|
||||
<object id="74" template="../../obj/enemy.tx" x="48" y="272">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="speedModifier" type="float" value="5"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
@@ -159,42 +171,46 @@
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"condition": [{"checkMapFlag": {"key":"demonsActive"}, "not": true}]
|
||||
"text": "A fountain borders the walkway here. The stonework is chipped and dirty, but the water appears to be surprisingly clean and clear.",
|
||||
"options": [{
|
||||
"name": "(Continue)"}]
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="76" template="../../obj/dialog.tx" x="688" y="160" width="64" height="64">
|
||||
<object id="76" template="../../obj/dialog.tx" x="656" y="175" width="117" height="98">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"condition": [{"checkMapFlag": {"key":"demonsActive"}, "not": true}],
|
||||
"text": "One of the few sounds in the area, the water wheel on this old mill creaks as it spins gradually in the slowly moving and oddly colored water.",
|
||||
"options": [{
|
||||
"name": "(Continue)"}]
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="77" template="../../obj/dialog.tx" x="400" y="448" width="160" height="128" visible="1">
|
||||
<object id="77" template="../../obj/dialog.tx" x="400" y="448" width="160" height="190" visible="1">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"condition": [{"checkMapFlag": {"key":"demonsActive"}, "not": true}],
|
||||
"text": "These shops are as lifeless as the rest of the town, but it looks as though there might be some items left behind, suspiciously untouched after however long.",
|
||||
"options": [{
|
||||
"name": "(Continue)"}]
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="78" template="../../obj/dialog.tx" x="240" y="448" width="128" height="128">
|
||||
<object id="78" template="../../obj/dialog.tx" x="202" y="448" width="166" height="159">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"condition": [{"checkMapFlag": {"key":"demonsActive"}, "not": true}],
|
||||
"text": "The inn is locked up tightly. The town hall in contrast is missing its' front door, but you find nothing out of the ordinary inside, just well organized crumbling papers coveered in illegibly smeared ink.",
|
||||
"options": [{
|
||||
"name": "(Continue)"}]
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
@@ -203,9 +219,10 @@
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"condition": [{"checkMapFlag": {"key":"demonsActive"}, "not": true}],
|
||||
"text": "The vines covering these houses look sickly, as if they are searching for sustenance not found in the soil here.",
|
||||
"options": [{
|
||||
"name": "(Continue)"}]
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
@@ -224,32 +241,31 @@
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"condition": [{"checkMapFlag": {"key":"demonsActive"}, "not": true}],
|
||||
"text": "'Deathly still' seems a fitting description for the graveyard. You find yourself almost wishing for the dead to rise just to have something happen.",
|
||||
"options": [{
|
||||
"name": "(Continue)"}]
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="83" template="../../obj/dialog.tx" x="336" y="544" width="112" height="16">
|
||||
<object id="83" template="../../obj/dialog.tx" x="336" y="560" width="112" height="16">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"condition": [{"checkQuestFlag": {"key":"demonsActive"}},{"checkQuestFlag": {"key":"escaped", "not": true}}],
|
||||
"action": ["setQuestFlag": {"key":"demonsActive", "val": 0}]
|
||||
<property name="dialog">[{
|
||||
"condition": [{"checkMapFlag":"demonsActive"},{"checkMapFlag": "escaped", "not": true}],
|
||||
"action": [{"setMapFlag": {"key":"demonsActive", "val": 0}}]
|
||||
},
|
||||
{
|
||||
"condition": [{"checkQuestFlag": {"key":"introShown", "not": true}}],
|
||||
"action": ["setQuestFlag": {"key":"introShown", "val": 1}],
|
||||
"condition": [{"checkMapFlag": "introShown", "not": true}],
|
||||
"action": [{"advanceMapFlag": "introShown"}],
|
||||
"text": "Just as the merchant described, an empty town lies behind these gates. Even the wind seems more still here as if afraid to disturb anything.",
|
||||
"options": [{
|
||||
"name": "(Continue)",
|
||||
"options": [{"name": "(Continue)",
|
||||
"text": "As you move closer, it becomes obvious that most of the buildings are intact but in a state of disrepair or are outright overgrown. It is doubtful that anyone has resided here in quite some time.",
|
||||
"options": [{"name": "Time to go portal hunting. I don't guess I can ask anyone for directions..."}]
|
||||
}
|
||||
]
|
||||
}
|
||||
]</property>
|
||||
}]
|
||||
}]
|
||||
</property>
|
||||
<property name="hidden" type="bool" value="true"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="84" template="../../obj/manashards.tx" x="560" y="448" visible="0"/>
|
||||
@@ -293,14 +309,21 @@
|
||||
<property name="reward" value="[ { "type": "card", "cardName": "Abandoned Outpost", "count": 1 } ]"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="93" template="../../obj/enemy.tx" x="370.667" y="147.333"/>
|
||||
<object id="93" template="../../obj/enemy.tx" x="370.667" y="147.333">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="94" template="../../obj/dialog.tx" x="240" y="272" width="80" height="80" visible="1">
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"condition": [{"checkMapFlag": {"key":"demonsActive"}, "not": true}],
|
||||
"text": "Perhaps just a trick of the mind, you can't shake the feeling that you're being watched as you explore the area.",
|
||||
"options": [{
|
||||
"name": "(Continue)"}]
|
||||
"name": "(Continue)", "action": [{"deleteMapObject":-1}]}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
@@ -309,13 +332,14 @@
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"condition": [{"checkMapFlag": {"key":"demonsActive"}, "not": true}]
|
||||
"text": "And here lies gruesome confirmation of the merchant's tale, by way of the remains of a merfolk tail. It appears that there was indeed one of the aquatic people here far from their normal territory which it will never return to.",
|
||||
"options": [{
|
||||
"name": "(Continue)",
|
||||
"text": "Investigating the scene will have to wait, however, as it appears you have determined the cause of death. Seemingly out of nowhere, demons come running at you from all directions.",
|
||||
"options": [{
|
||||
"name": "RUN!!!",
|
||||
"action": ["setQuestFlag": {"key":"demonsActive", "val": 1},{"deleteMapObject": 258}, {"activateMapObject": 230},{"activateMapObject": 248},{"activateMapObject": 246},{"activateMapObject": 247},{"deleteMapObject": -1},{"setMapFlag": 258}]
|
||||
"action": [{"setMapFlag": {"key":"demonsActive", "val": 1}},{"deleteMapObject": -1}, {"activateMapObject": 67},{"activateMapObject": 68},{"activateMapObject": 69},{"activateMapObject": 70},{"activateMapObject": 71},{"activateMapObject": 72},{"activateMapObject": 73},{"activateMapObject": 74},{"activateMapObject": 93},{"activateMapObject": 98},{"activateMapObject": 99},{"activateMapObject": 100},{"activateMapObject": 101},{"activateMapObject": 102},{"activateMapObject": 103}]
|
||||
}]
|
||||
}]
|
||||
}
|
||||
@@ -326,8 +350,8 @@
|
||||
<properties>
|
||||
<property name="dialog">[
|
||||
{
|
||||
"condition": [{"checkQuestFlag": {"key":"demonsActive"}},{"checkQuestFlag": {"key":"escaped"}, "not": true}]
|
||||
"action": ["setQuestFlag": {"key":"escaped", "val": 1}]
|
||||
"condition": [{"checkMapFlag": {"key":"demonsActive"}},{"checkMapFlag": {"key":"escaped"}, "not": true}]
|
||||
"action": [{"setMapFlag": {"key":"escaped", "val": 1}}]
|
||||
}
|
||||
]</property>
|
||||
</properties>
|
||||
@@ -353,38 +377,51 @@
|
||||
<object id="98" template="../../obj/enemy.tx" x="32" y="96">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="speedModifier" type="float" value="8"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="99" template="../../obj/enemy.tx" x="657" y="133">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="100" template="../../obj/enemy.tx" x="359" y="496">
|
||||
<object id="100" template="../../obj/enemy.tx" x="200" y="488">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
<property name="fleeRange" value="5000"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="speedModifier" type="float" value="7.5"/>
|
||||
<property name="threatRange" type="int" value="1000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="101" template="../../obj/enemy.tx" x="383" y="383">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="speedModifier" type="float" value="2.5"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="102" template="../../obj/enemy.tx" x="32" y="480">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="speedModifier" type="float" value="1"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="103" template="../../obj/enemy.tx" x="736" y="368">
|
||||
<object id="103" template="../../obj/enemy.tx" x="624" y="416">
|
||||
<properties>
|
||||
<property name="enemy" value="Demon"/>
|
||||
<property name="inactive" type="bool" value="true"/>
|
||||
<property name="threatRange" type="int" value="5000"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="116" template="../../obj/collision.tx" x="330" y="640" width="126" height="29"/>
|
||||
<object id="117" template="../../obj/waypoint.tx" x="384" y="239"/>
|
||||
</objectgroup>
|
||||
</map>
|
||||
@@ -4697,9 +4697,8 @@
|
||||
<objectgroup draworder="index" id="3">
|
||||
<object id="2" x="0" y="0" width="4" height="16"/>
|
||||
<object id="3" x="4" y="0" width="12" height="8"/>
|
||||
<object id="4" x="4" y="8" width="4" height="4"/>
|
||||
<object id="5" x="8" y="8" width="2" height="2"/>
|
||||
<object id="6" x="4" y="12" width="2" height="2"/>
|
||||
<object id="5" x="6" y="8" width="4" height="3"/>
|
||||
<object id="6" x="4" y="8" width="2" height="6"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="2218">
|
||||
@@ -4711,9 +4710,8 @@
|
||||
<objectgroup draworder="index" id="2">
|
||||
<object id="1" x="0" y="0" width="16" height="7"/>
|
||||
<object id="2" x="11" y="7" width="5" height="9"/>
|
||||
<object id="3" x="5" y="7" width="6" height="4"/>
|
||||
<object id="4" x="2" y="7" width="3" height="2"/>
|
||||
<object id="6" x="8" y="11" width="3" height="2"/>
|
||||
<object id="4" x="2" y="7" width="9" height="2"/>
|
||||
<object id="6" x="6" y="9" width="5" height="3"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="2316">
|
||||
@@ -5020,9 +5018,8 @@
|
||||
<tile id="2533">
|
||||
<objectgroup draworder="index" id="2">
|
||||
<object id="1" x="0" y="13" width="16" height="3"/>
|
||||
<object id="3" x="0" y="11" width="14" height="2"/>
|
||||
<object id="4" x="0" y="5" width="10" height="6"/>
|
||||
<object id="6" x="0" y="-1" width="7" height="6"/>
|
||||
<object id="4" x="0" y="5" width="10" height="8"/>
|
||||
<object id="6" x="0" y="0" width="7" height="5"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="2534">
|
||||
@@ -5036,7 +5033,6 @@
|
||||
<object id="3" x="0" y="12" width="12" height="4"/>
|
||||
<object id="6" x="4" y="9" width="8" height="3"/>
|
||||
<object id="7" x="7" y="6" width="5" height="3"/>
|
||||
<object id="8" x="11" y="0" width="1" height="6"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="2632">
|
||||
@@ -5743,8 +5739,7 @@
|
||||
<objectgroup draworder="index" id="2">
|
||||
<object id="1" x="0" y="0" width="16" height="8"/>
|
||||
<object id="2" x="4" y="8" width="12" height="3"/>
|
||||
<object id="3" x="8" y="11" width="8" height="1"/>
|
||||
<object id="4" x="11" y="12" width="5" height="4"/>
|
||||
<object id="4" x="11" y="11" width="5" height="5"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="3330">
|
||||
|
||||
@@ -837,17 +837,17 @@
|
||||
<object id="4" x="12" y="7" width="4" height="3"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="325">
|
||||
<tile id="325" probability="0.2">
|
||||
<objectgroup draworder="index" id="2">
|
||||
<object id="1" x="0" y="3" width="16" height="10"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="326">
|
||||
<tile id="326" probability="0.2">
|
||||
<objectgroup draworder="index" id="2">
|
||||
<object id="1" x="0" y="4" width="16" height="9"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="327">
|
||||
<tile id="327" probability="0.2">
|
||||
<objectgroup draworder="index" id="2">
|
||||
<object id="1" x="0" y="3" width="16" height="10"/>
|
||||
</objectgroup>
|
||||
@@ -962,7 +962,7 @@
|
||||
<object id="1" x="0" y="0" width="16" height="16"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="504">
|
||||
<tile id="504" probability="0.2">
|
||||
<objectgroup draworder="index" id="2">
|
||||
<object id="1" x="3" y="0" width="10" height="16"/>
|
||||
</objectgroup>
|
||||
@@ -1003,7 +1003,7 @@
|
||||
<object id="4" x="12" y="12" width="1" height="4"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="511">
|
||||
<tile id="511" probability="0.05">
|
||||
<objectgroup draworder="index" id="2">
|
||||
<object id="1" x="0" y="3" width="16" height="10"/>
|
||||
</objectgroup>
|
||||
@@ -1064,7 +1064,7 @@
|
||||
<object id="1" x="0" y="3" width="7" height="10"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="684">
|
||||
<tile id="684" probability="0.2">
|
||||
<objectgroup draworder="index" id="2">
|
||||
<object id="1" x="3" y="0" width="10" height="16"/>
|
||||
</objectgroup>
|
||||
@@ -1160,7 +1160,7 @@
|
||||
<object id="1" x="3" y="0" width="10" height="16"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="864">
|
||||
<tile id="864" probability="0.2">
|
||||
<objectgroup draworder="index" id="2">
|
||||
<object id="1" x="3" y="0" width="10" height="16"/>
|
||||
</objectgroup>
|
||||
@@ -1200,7 +1200,7 @@
|
||||
<object id="1" x="0" y="8" width="16" height="8"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<tile id="872">
|
||||
<tile id="872" probability="0.05">
|
||||
<objectgroup draworder="index" id="2">
|
||||
<object id="1" x="3" y="0" width="10" height="16"/>
|
||||
</objectgroup>
|
||||
@@ -11242,4 +11242,57 @@
|
||||
<object id="1" x="3" y="3" width="10" height="10"/>
|
||||
</objectgroup>
|
||||
</tile>
|
||||
<wangsets>
|
||||
<wangset name="Grey, Green Water" type="edge" tile="328">
|
||||
<wangcolor name="" color="#ff0000" tile="-1" probability="1"/>
|
||||
<wangcolor name="" color="#00ff00" tile="-1" probability="1"/>
|
||||
<wangtile tileid="144" wangid="0,0,0,0,1,0,1,0"/>
|
||||
<wangtile tileid="145" wangid="0,0,1,0,1,0,0,0"/>
|
||||
<wangtile tileid="146" wangid="1,0,0,0,0,0,1,0"/>
|
||||
<wangtile tileid="151" wangid="1,0,2,0,2,0,1,0"/>
|
||||
<wangtile tileid="152" wangid="1,0,1,0,2,0,2,0"/>
|
||||
<wangtile tileid="324" wangid="1,0,1,0,0,0,0,0"/>
|
||||
<wangtile tileid="325" wangid="0,0,1,0,0,0,1,0"/>
|
||||
<wangtile tileid="326" wangid="0,0,1,0,0,0,1,0"/>
|
||||
<wangtile tileid="327" wangid="0,0,1,0,0,0,1,0"/>
|
||||
<wangtile tileid="328" wangid="0,0,1,0,0,0,1,0"/>
|
||||
<wangtile tileid="331" wangid="2,0,2,0,1,0,1,0"/>
|
||||
<wangtile tileid="332" wangid="2,0,1,0,1,0,2,0"/>
|
||||
<wangtile tileid="504" wangid="1,0,0,0,1,0,0,0"/>
|
||||
<wangtile tileid="505" wangid="0,0,1,0,1,0,0,0"/>
|
||||
<wangtile tileid="506" wangid="0,0,0,0,1,0,1,0"/>
|
||||
<wangtile tileid="507" wangid="1,0,1,0,1,0,0,0"/>
|
||||
<wangtile tileid="508" wangid="0,0,1,0,1,0,1,0"/>
|
||||
<wangtile tileid="509" wangid="0,0,1,0,1,0,0,0"/>
|
||||
<wangtile tileid="510" wangid="0,0,0,0,1,0,1,0"/>
|
||||
<wangtile tileid="511" wangid="0,0,1,0,0,0,1,0"/>
|
||||
<wangtile tileid="512" wangid="1,0,1,0,1,0,1,0"/>
|
||||
<wangtile tileid="684" wangid="1,0,0,0,1,0,0,0"/>
|
||||
<wangtile tileid="685" wangid="1,0,1,0,0,0,0,0"/>
|
||||
<wangtile tileid="686" wangid="1,0,0,0,0,0,1,0"/>
|
||||
<wangtile tileid="687" wangid="1,0,1,0,0,0,1,0"/>
|
||||
<wangtile tileid="688" wangid="1,0,0,0,1,0,1,0"/>
|
||||
<wangtile tileid="689" wangid="1,0,1,0,0,0,0,0"/>
|
||||
<wangtile tileid="690" wangid="1,0,0,0,0,0,1,0"/>
|
||||
<wangtile tileid="691" wangid="0,0,1,0,0,0,0,0"/>
|
||||
<wangtile tileid="692" wangid="0,0,0,0,0,0,1,0"/>
|
||||
<wangtile tileid="864" wangid="1,0,0,0,1,0,0,0"/>
|
||||
<wangtile tileid="865" wangid="1,0,1,0,1,0,0,0"/>
|
||||
<wangtile tileid="866" wangid="0,0,1,0,1,0,1,0"/>
|
||||
<wangtile tileid="867" wangid="0,0,1,0,2,0,2,0"/>
|
||||
<wangtile tileid="868" wangid="0,0,2,0,2,0,1,0"/>
|
||||
<wangtile tileid="869" wangid="2,0,2,0,1,0,0,0"/>
|
||||
<wangtile tileid="870" wangid="2,0,0,0,1,0,2,0"/>
|
||||
<wangtile tileid="871" wangid="0,0,0,0,1,0,0,0"/>
|
||||
<wangtile tileid="872" wangid="1,0,0,0,1,0,0,0"/>
|
||||
<wangtile tileid="1044" wangid="1,0,0,0,1,0,0,0"/>
|
||||
<wangtile tileid="1045" wangid="1,0,1,0,0,0,1,0"/>
|
||||
<wangtile tileid="1046" wangid="1,0,0,0,1,0,1,0"/>
|
||||
<wangtile tileid="1047" wangid="2,0,1,0,0,0,2,0"/>
|
||||
<wangtile tileid="1048" wangid="2,0,2,0,0,0,1,0"/>
|
||||
<wangtile tileid="1049" wangid="1,0,2,0,2,0,0,0"/>
|
||||
<wangtile tileid="1050" wangid="1,0,0,0,2,0,2,0"/>
|
||||
<wangtile tileid="1051" wangid="1,0,0,0,0,0,0,0"/>
|
||||
</wangset>
|
||||
</wangsets>
|
||||
</tileset>
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
golem_4.png
|
||||
size: 64,96
|
||||
format: RGBA8888
|
||||
filter: Nearest,Nearest
|
||||
repeat: none
|
||||
Avatar
|
||||
xy: 0, 0
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 0, 16
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 16, 16
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 32, 16
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 48, 16
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 0, 32
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 16, 32
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 32, 32
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 48, 32
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 0, 48
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 16, 48
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 32, 48
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 48, 48
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 0, 64
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 16, 64
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 32, 64
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 48, 64
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 0, 80
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 16, 80
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 32, 80
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 48, 80
|
||||
size: 16, 16
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,68 @@
|
||||
myr.png
|
||||
size: 64,96
|
||||
format: RGBA8888
|
||||
filter: Nearest,Nearest
|
||||
repeat: none
|
||||
Avatar
|
||||
xy: 0, 0
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 0, 16
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 16, 16
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 32, 16
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 48, 16
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 0, 32
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 16, 32
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 32, 32
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 48, 32
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 0, 48
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 16, 48
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 32, 48
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 48, 48
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 0, 64
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 16, 64
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 32, 64
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 48, 64
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 0, 80
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 16, 80
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 32, 80
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 48, 80
|
||||
size: 16, 16
|
||||
BIN
forge-gui/res/adventure/common/sprites/enemy/construct/myr.png
Normal file
BIN
forge-gui/res/adventure/common/sprites/enemy/construct/myr.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1,68 @@
|
||||
pirate2.png
|
||||
size: 64,96
|
||||
format: RGBA8888
|
||||
filter: Nearest,Nearest
|
||||
repeat: none
|
||||
Avatar
|
||||
xy: 0, 0
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 0, 16
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 16, 16
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 32, 16
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 48, 16
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 0, 32
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 16, 32
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 32, 32
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 48, 32
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 0, 48
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 16, 48
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 32, 48
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 48, 48
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 0, 64
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 16, 64
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 32, 64
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 48, 64
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 0, 80
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 16, 80
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 32, 80
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 48, 80
|
||||
size: 16, 16
|
||||
@@ -0,0 +1,68 @@
|
||||
archivist.png
|
||||
size: 64,96
|
||||
format: RGBA8888
|
||||
filter: Nearest,Nearest
|
||||
repeat: none
|
||||
Avatar
|
||||
xy: 0, 0
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 0, 16
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 16, 16
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 32, 16
|
||||
size: 16, 16
|
||||
Idle
|
||||
xy: 48, 16
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 0, 32
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 16, 32
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 32, 32
|
||||
size: 16, 16
|
||||
Walk
|
||||
xy: 48, 32
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 0, 48
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 16, 48
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 32, 48
|
||||
size: 16, 16
|
||||
Attack
|
||||
xy: 48, 48
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 0, 64
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 16, 64
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 32, 64
|
||||
size: 16, 16
|
||||
Hit
|
||||
xy: 48, 64
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 0, 80
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 16, 80
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 32, 80
|
||||
size: 16, 16
|
||||
Death
|
||||
xy: 48, 80
|
||||
size: 16, 16
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
@@ -190,6 +190,13 @@
|
||||
"Mythic Rare"
|
||||
]
|
||||
}
|
||||
],
|
||||
"questTags": [
|
||||
"Wizard",
|
||||
"Human",
|
||||
"IdentityBlue",
|
||||
"BiomeBlue",
|
||||
"BiomeColorless"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1743,6 +1750,57 @@
|
||||
"BiomeBlack"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Archivist",
|
||||
"sprite": "sprites/enemy/humanoid/human/wizard/archivist.atlas",
|
||||
"deck": [
|
||||
"decks/standard/archivist.dck"
|
||||
],
|
||||
"life": 20,
|
||||
"rewards": [
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 4,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 0.5,
|
||||
"count": 2,
|
||||
"addMaxCount": 4,
|
||||
"rarity": [
|
||||
"uncommon",
|
||||
"rare"
|
||||
],
|
||||
"cardTypes": [
|
||||
"Creature",
|
||||
"Artifact",
|
||||
"Enchantment",
|
||||
"Instant",
|
||||
"Sorcery"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
"probability": 0.3,
|
||||
"count": 100,
|
||||
"addMaxCount": 200
|
||||
}
|
||||
],
|
||||
"colors": "U",
|
||||
"questTags": [
|
||||
"Human",
|
||||
"Wizard",
|
||||
"Mystic",
|
||||
"IdentityBlue",
|
||||
"Dungeon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Armored Knight",
|
||||
"sprite": "sprites/enemy/humanoid/knight.atlas",
|
||||
@@ -3238,11 +3296,7 @@
|
||||
"Furnace",
|
||||
"IdentityColorless",
|
||||
"Construct",
|
||||
"Robot",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
"Robot"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -4080,7 +4134,7 @@
|
||||
"difficulty": 0.1,
|
||||
"speed": 15,
|
||||
"scale": 0.4,
|
||||
"flying":true
|
||||
"flying":true,
|
||||
"life": 25,
|
||||
"rewards": [
|
||||
{
|
||||
@@ -12930,65 +12984,54 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Golem that is Generous",
|
||||
"nameOverride": "Shiny Golem",
|
||||
"sprite": "sprites/enemy/construct/golem.atlas",
|
||||
"name": "Golem Sentinel",
|
||||
"sprite": "sprites/enemy/construct/golem_4.atlas",
|
||||
"deck": [
|
||||
"decks/standard/golem.json"
|
||||
"decks/standard/golem_sentinel.dck",
|
||||
"decks/standard/golem_sentinel_2.dck",
|
||||
"decks/standard/golem_sentinel_3.dck"
|
||||
],
|
||||
"ai": "",
|
||||
"spawnRate": 0.1,
|
||||
"spawnRate": 1,
|
||||
"difficulty": 0.1,
|
||||
"speed": 20,
|
||||
"life": 13,
|
||||
"life": 20,
|
||||
"rewards": [
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 1,
|
||||
"count": 1,
|
||||
"editions": [
|
||||
"M22",
|
||||
"M21"
|
||||
],
|
||||
"colors": [
|
||||
"red"
|
||||
],
|
||||
"rarity": [
|
||||
"rare"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "life",
|
||||
"probability": 1,
|
||||
"count": 1,
|
||||
"addMaxCount": 3
|
||||
},
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 3,
|
||||
"addMaxCount": 3
|
||||
"count": 1,
|
||||
"addMaxCount": 4
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
"probability": 0.7,
|
||||
"count": 100,
|
||||
"addMaxCount": 200
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"cardName": "Black Lotus"
|
||||
"count": 3,
|
||||
"rarity": [
|
||||
"Uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
"probability": 1,
|
||||
"count": 10,
|
||||
"addMaxCount": 90
|
||||
"type": "card",
|
||||
"probability": 0.5,
|
||||
"count": 3,
|
||||
"rarity": [
|
||||
"Rare"
|
||||
]
|
||||
}
|
||||
],
|
||||
"colors": "GW",
|
||||
"colors": "C",
|
||||
"questTags": [
|
||||
"Golem",
|
||||
"IdentityColorless",
|
||||
"Construct",
|
||||
"IdentityGreen",
|
||||
"IdentityWhite",
|
||||
"IdentitySelesnya"
|
||||
"Dungeon"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -18726,6 +18769,58 @@
|
||||
"BiomeBlack"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Myr Superion",
|
||||
"sprite": "sprites/enemy/construct/myr.atlas",
|
||||
"deck": [
|
||||
"decks/standard/Myr_Superion.dck"
|
||||
],
|
||||
"boss": true,
|
||||
"ai": "",
|
||||
"spawnRate": 1,
|
||||
"difficulty": 0.5,
|
||||
"speed": 20,
|
||||
"life": 25,
|
||||
"rewards": [
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 1,
|
||||
"addMaxCount": 4
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
"probability": 0.7,
|
||||
"count": 100,
|
||||
"addMaxCount": 200
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 1,
|
||||
"count": 3,
|
||||
"rarity": [
|
||||
"Uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 0.5,
|
||||
"count": 3,
|
||||
"rarity": [
|
||||
"Rare"
|
||||
]
|
||||
}
|
||||
],
|
||||
"colors": "C",
|
||||
"questTags": [
|
||||
"Myr",
|
||||
"IdentityColorless",
|
||||
"Construct",
|
||||
"Robot",
|
||||
"Dungeon",
|
||||
"Boss"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Naga Warrior",
|
||||
"sprite": "sprites/enemy/humanoid/naga/nagawarrior.atlas",
|
||||
@@ -19678,6 +19773,168 @@
|
||||
"Pirate"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Pirate 2",
|
||||
"nameOverride": "Buccaneer",
|
||||
"sprite": "sprites/enemy/humanoid/human/rogue/pirate2.atlas",
|
||||
"deck": [
|
||||
"decks/standard/pirate2.dck"
|
||||
],
|
||||
"ai": "",
|
||||
"spawnRate": 0.8,
|
||||
"difficulty": 0.1,
|
||||
"speed": 24,
|
||||
"life": 16,
|
||||
"rewards": [
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 1,
|
||||
"rarity": [
|
||||
"Common"
|
||||
],
|
||||
"cardTypes": [
|
||||
"Creature",
|
||||
"Artifact",
|
||||
"Enchantment",
|
||||
"Instant",
|
||||
"Sorcery"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 0.25,
|
||||
"count": 1,
|
||||
"rarity": [
|
||||
"Rare"
|
||||
],
|
||||
"cardTypes": [
|
||||
"Creature",
|
||||
"Artifact",
|
||||
"Enchantment",
|
||||
"Instant",
|
||||
"Sorcery"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
"probability": 1,
|
||||
"count": 30,
|
||||
"addMaxCount": 100
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 0.5,
|
||||
"count": 2,
|
||||
"colors": [
|
||||
"Red"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 0.5,
|
||||
"count": 1,
|
||||
"colors": [
|
||||
"Blue"
|
||||
]
|
||||
}
|
||||
],
|
||||
"colors": "BRU",
|
||||
"questTags": [
|
||||
"Aggressive",
|
||||
"Human",
|
||||
"Warrior",
|
||||
"Water",
|
||||
"Bandit",
|
||||
"Thief",
|
||||
"IdentityBlack",
|
||||
"IdentityBlue",
|
||||
"IdentityRed",
|
||||
"IdentityGrixis",
|
||||
"Dungeon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Pirate 3",
|
||||
"nameOverride": "Plunderer",
|
||||
"sprite": "sprites/enemy/humanoid/human/rogue/pirate3.atlas",
|
||||
"deck": [
|
||||
"decks/standard/pirate3.dck"
|
||||
],
|
||||
"ai": "",
|
||||
"spawnRate": 0.8,
|
||||
"difficulty": 0.1,
|
||||
"speed": 24,
|
||||
"life": 16,
|
||||
"rewards": [
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 1,
|
||||
"rarity": [
|
||||
"Common"
|
||||
],
|
||||
"cardTypes": [
|
||||
"Creature",
|
||||
"Artifact",
|
||||
"Enchantment",
|
||||
"Instant",
|
||||
"Sorcery"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 0.25,
|
||||
"count": 1,
|
||||
"rarity": [
|
||||
"Rare"
|
||||
],
|
||||
"cardTypes": [
|
||||
"Creature",
|
||||
"Artifact",
|
||||
"Enchantment",
|
||||
"Instant",
|
||||
"Sorcery"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
"probability": 1,
|
||||
"count": 30,
|
||||
"addMaxCount": 100
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 0.5,
|
||||
"count": 2,
|
||||
"colors": [
|
||||
"Red"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 0.5,
|
||||
"count": 1,
|
||||
"colors": [
|
||||
"Blue"
|
||||
]
|
||||
}
|
||||
],
|
||||
"colors": "BRU",
|
||||
"questTags": [
|
||||
"Aggressive",
|
||||
"Human",
|
||||
"Warrior",
|
||||
"Water",
|
||||
"Bandit",
|
||||
"Thief",
|
||||
"IdentityBlack",
|
||||
"IdentityBlue",
|
||||
"IdentityRed",
|
||||
"IdentityGrixis",
|
||||
"Dungeon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Pirate Captain",
|
||||
"nameOverride": "",
|
||||
@@ -19752,6 +20009,85 @@
|
||||
"Pirate"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Pirate Captain 2",
|
||||
"nameOverride": "Pirate Captain",
|
||||
"sprite": "sprites/enemy/humanoid/human/rogue/pirate3.atlas",
|
||||
"deck": [
|
||||
"decks/standard/pirate_captain_2.dck"
|
||||
],
|
||||
"ai": "",
|
||||
"spawnRate": 0.8,
|
||||
"difficulty": 0.1,
|
||||
"speed": 24,
|
||||
"life": 20,
|
||||
"rewards": [
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 1,
|
||||
"rarity": [
|
||||
"Common"
|
||||
],
|
||||
"cardTypes": [
|
||||
"Creature",
|
||||
"Artifact",
|
||||
"Enchantment",
|
||||
"Instant",
|
||||
"Sorcery"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 0.25,
|
||||
"count": 1,
|
||||
"rarity": [
|
||||
"Rare"
|
||||
],
|
||||
"cardTypes": [
|
||||
"Creature",
|
||||
"Artifact",
|
||||
"Enchantment",
|
||||
"Instant",
|
||||
"Sorcery"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
"probability": 1,
|
||||
"count": 30,
|
||||
"addMaxCount": 100
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 0.5,
|
||||
"count": 2,
|
||||
"colors": [
|
||||
"Black"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 0.5,
|
||||
"count": 1,
|
||||
"colors": [
|
||||
"Black"
|
||||
]
|
||||
}
|
||||
],
|
||||
"colors": "B",
|
||||
"questTags": [
|
||||
"Leader",
|
||||
"Aggressive",
|
||||
"Human",
|
||||
"Warrior",
|
||||
"Water",
|
||||
"Bandit",
|
||||
"Thief",
|
||||
"IdentityBlack",
|
||||
"Dungeon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Plant",
|
||||
"sprite": "sprites/enemy/plant/plant.atlas",
|
||||
@@ -23086,6 +23422,63 @@
|
||||
"BiomeBlack"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Spirit",
|
||||
"sprite": "sprites/enemy/undead/ghost_3.atlas",
|
||||
"deck": [
|
||||
"decks/standard/spirit.dck"
|
||||
],
|
||||
"ai": "",
|
||||
"flying": true,
|
||||
"spawnRate": 1,
|
||||
"difficulty": 0.1,
|
||||
"speed": 31,
|
||||
"life": 20,
|
||||
"rewards": [
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 4,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 0.5,
|
||||
"count": 2,
|
||||
"addMaxCount": 4,
|
||||
"rarity": [
|
||||
"uncommon",
|
||||
"rare"
|
||||
],
|
||||
"cardTypes": [
|
||||
"Creature",
|
||||
"Artifact",
|
||||
"Enchantment",
|
||||
"Instant",
|
||||
"Sorcery"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
"probability": 0.3,
|
||||
"count": 100,
|
||||
"addMaxCount": 200
|
||||
}
|
||||
],
|
||||
"colors": "U",
|
||||
"questTags": [
|
||||
"Undead",
|
||||
"Spirit",
|
||||
"Flying",
|
||||
"Ghost",
|
||||
"IdentityBlue",
|
||||
"Dungeon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Stegosaurus",
|
||||
"sprite": "sprites/enemy/beast/dinosaur/dinosaur_stegosaurus.atlas",
|
||||
|
||||
@@ -2867,6 +2867,18 @@
|
||||
"map": "../common/maps/map/towns/plains_town.tmx",
|
||||
"radiusFactor": 0.8
|
||||
},
|
||||
{
|
||||
"name": "Quest_APortalToNowhere",
|
||||
"type": "dungeon",
|
||||
"count": 1,
|
||||
"spriteAtlas": "../common/maps/tileset/buildings.atlas",
|
||||
"sprite": "WasteTown",
|
||||
"map": "../common/maps/map/main_story/waste_town_abandoned.tmx",
|
||||
"radiusFactor": 0.8,
|
||||
"questTags": [
|
||||
"Quest_APortalToNowhere"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Red Castle",
|
||||
"type": "castle",
|
||||
|
||||
Reference in New Issue
Block a user