package Roguelike.Ability.ActiveAbility.EffectType; import Roguelike.Entity.EnvironmentEntity; import Roguelike.Global; import Roguelike.Global.Direction; import Roguelike.Ability.ActiveAbility.ActiveAbility; import Roguelike.Entity.GameEntity; import Roguelike.Pathfinding.BresenhamLine; import Roguelike.Sprite.SpriteAnimation.MoveAnimation; import Roguelike.Sprite.SpriteAnimation.MoveAnimation.MoveEquation; import Roguelike.Tiles.GameTile; import Roguelike.Tiles.Point; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.XmlReader.Element; public class EffectTypeTeleport extends AbstractEffectType { public enum ToMove { CASTER, TARGET } public enum MoveType { TOWARDS, AWAY } public enum DestinationType { EXACT, LINE, CONE } public enum Style { BLINK, CHARGE, LEAP } private ToMove toMove; private MoveType moveType; private DestinationType destinationType; private Style style; private int distance = 1; @Override public void update( ActiveAbility aa, float time, GameTile tile, GameEntity entity, EnvironmentEntity envEntity ) { GameTile destination = null; GameEntity entityToMove = null; if ( toMove == ToMove.CASTER ) { entityToMove = aa.getCaster(); destination = getDestination( aa.source, tile, entityToMove ); } else if ( toMove == ToMove.TARGET ) { entityToMove = entity; destination = getDestination( tile, aa.source, entityToMove ); } if ( destination != null && entityToMove != null && entityToMove.tile[0][0] != destination ) { int[] diff = destination.addGameEntity( entityToMove ); entityToMove.actionDelayAccumulator = 0; if ( style == Style.CHARGE ) { int distMoved = ( Math.abs( diff[0] ) + Math.abs( diff[1] ) ) / Global.TileSize; entityToMove.sprite.spriteAnimation = new MoveAnimation( 0.05f * distMoved, diff, MoveEquation.EXPONENTIAL ); } else if ( style == Style.LEAP ) { float distMoved = ( ( Math.abs( diff[0] ) + Math.abs( diff[1] ) ) / Global.TileSize ) / 3; entityToMove.sprite.spriteAnimation = new MoveAnimation( 0.25f, diff, MoveEquation.LEAP ); } } } private GameTile getDestination( GameTile src, GameTile target, GameEntity entity ) { if ( entity == null ) { return null; } Direction dir = null; if ( moveType == MoveType.TOWARDS ) { dir = Direction.getDirection( src, target ); } else { dir = Direction.getDirection( target, src ); } GameTile destination = null; if ( destinationType == DestinationType.EXACT ) { destination = target; } else if ( destinationType == DestinationType.LINE ) { destination = src.level.getGameTile( src.x + dir.getX() * distance, src.y + dir.getY() * distance ); } else { Array<Point> possibleTiles = Direction.buildCone( dir, Global.PointPool.obtain().set( src.x, src.y ), distance ); Point pos = possibleTiles.random(); destination = src.level.getGameTile( pos ); Global.PointPool.freeAll( possibleTiles ); } if ( destination != null && style != Style.CHARGE ) { if ( destination.getPassable( entity.getTravelType(), entity ) && destination.entity == null ) { return destination; } else { for ( Direction d : Direction.values() ) { GameTile tile = getTile( destination, d ); if ( tile.getPassable( entity.getTravelType(), entity ) && tile.entity == null ) { return tile; } } } } if (destination == null) { return src; } Array<Point> possibleTiles = BresenhamLine.lineNoDiag( src.x, src.y, destination.x, destination.y ); for ( int i = possibleTiles.size - 1; i >= 0; i-- ) { GameTile tile = src.level.getGameTile( possibleTiles.get( i ) ); if ( tile.getPassable( entity.getTravelType(), entity ) && tile.entity == null ) { Global.PointPool.freeAll( possibleTiles ); return tile; } } Global.PointPool.freeAll( possibleTiles ); return src; } private GameTile getTile( GameTile current, Direction dir ) { int nx = current.x + dir.getX(); int ny = current.y + dir.getY(); return current.level.getGameTile( nx, ny ); } @Override public void parse( Element xml ) { toMove = ToMove.valueOf( xml.get( "Move", "Caster" ).toUpperCase() ); moveType = MoveType.valueOf( xml.get( "Direction", "Towards" ).toUpperCase() ); destinationType = DestinationType.valueOf( xml.get( "Type", "Exact" ).toUpperCase() ); distance = xml.getInt( "Distance", 1 ); style = Style.valueOf( xml.get( "Style", "Blink" ).toUpperCase() ); } @Override public AbstractEffectType copy() { EffectTypeTeleport effect = new EffectTypeTeleport(); effect.toMove = toMove; effect.moveType = moveType; effect.destinationType = destinationType; effect.distance = distance; effect.style = style; return effect; } @Override public Array<String> toString( ActiveAbility aa ) { Array<String> lines = new Array<String>( ); String line = ""; line += Global.capitalizeString( style.toString() ) + "s the "; line += toMove.toString().toLowerCase() + " "; line += moveType.toString().toLowerCase() + " "; line += "to a point within " + distance; lines.add( line ); return lines; } }