package Roguelike.Tiles;
import Roguelike.Entity.Entity;
import Roguelike.Entity.EnvironmentEntity;
import Roguelike.Entity.GameEntity;
import Roguelike.Fields.Field;
import Roguelike.Fields.Field.FieldLayer;
import Roguelike.Global;
import Roguelike.Global.Passability;
import Roguelike.Items.Item;
import Roguelike.Levels.Level;
import Roguelike.Lights.Light;
import Roguelike.Pathfinding.PathfindingTile;
import Roguelike.Sprite.Sprite;
import Roguelike.Sprite.SpriteEffect;
import Roguelike.Sprite.TilingSprite;
import Roguelike.Util.EnumBitflag;
import Roguelike.Util.FastEnumMap;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import java.util.HashMap;
import java.util.Map;
public class GameTile implements PathfindingTile
{
private static final Color tempColour = new Color();
public int x;
public int y;
public TileData tileData;
public HashMap<Light, LightData> lightMap = new HashMap<Light, LightData>();
public Color ambientColour = new Color();
public Color light = new Color();
public GameEntity entity;
public GameEntity prevEntity;
public EnvironmentEntity environmentEntity;
public FastEnumMap<FieldLayer, Field> fields = new FastEnumMap<FieldLayer, Field>( FieldLayer.class );
public boolean hasFields;
public boolean hasFieldLight;
public Level level;
public Array<SpriteEffect> spriteEffects = new Array<SpriteEffect>();
public Array<Item> items = new Array<Item>( false, 16 );
public FastEnumMap<OrbType, Integer> orbs = new FastEnumMap<OrbType, Integer>( OrbType.class );
public String metaValue;
public boolean visible;
public boolean tempVisible;
public boolean seen;
public EnumBitflag<Global.Direction> seenBitflag = new EnumBitflag<Global.Direction>( );
public EnumBitflag<Global.Direction> unseenBitflag = new EnumBitflag<Global.Direction>( );
public TileData.SpriteGroup spriteGroup;
public Light lightObj;
public float ranVal;
public GameTile( int x, int y, Level level, TileData tileData, float ranVal )
{
this.x = x;
this.y = y;
this.level = level;
this.tileData = tileData;
this.ranVal = ranVal;
float total = 0;
for ( TileData.SpriteGroup group : tileData.spriteGroups )
{
total += group.chance;
if (total >= ranVal)
{
spriteGroup = group;
break;
}
}
if (spriteGroup == null)
{
spriteGroup = tileData.spriteGroups.first();
}
lightObj = spriteGroup.light;
light = new Color( Color.WHITE );
}
public float getMaxSpriteEffectDuration()
{
float max = 0;
for (SpriteEffect effect : spriteEffects)
{
float duration = effect.Sprite.getRemainingLifetime();
if (duration > max)
{
max = duration;
}
}
return max;
}
public boolean hasEntityStayedOnTile()
{
if (prevEntity != entity)
{
prevEntity = null;
}
return prevEntity != null;
}
public Array<Sprite> getSprites()
{
return spriteGroup.sprites;
}
public TilingSprite getTilingSprite()
{
return spriteGroup.tilingSprite;
}
public final void addEnvironmentEntity( EnvironmentEntity entity )
{
entity.removeFromTile();
for ( int x = 0; x < entity.size; x++ )
{
for ( int y = 0; y < entity.size; y++ )
{
GameTile tile = level.Grid[ this.x + x ][ this.y + y ];
tile.environmentEntity = entity;
entity.tile[ x ][ y ] = tile;
}
}
}
public final void processFieldEffectsForEntity( Entity e, float cost )
{
if ( fields.size > 0 )
{
for ( FieldLayer layer : FieldLayer.values() )
{
Field field = fields.get( layer );
if ( field != null )
{
field.processOnTurnEffectsForEntity( e, cost );
}
}
}
}
public final void addField( Field field )
{
clearField( field.layer );
fields.put( field.layer, field );
field.tile = this;
hasFields = fields.size > 0;
updateFieldLightFlag();
}
public final void clearField( FieldLayer layer )
{
if ( fields.containsKey( layer ) )
{
Field field = fields.get( layer );
if ( field != null )
{
field.tile = null;
}
fields.remove( layer );
hasFields = fields.size > 0;
updateFieldLightFlag();
}
}
public final void updateFieldLightFlag()
{
hasFieldLight = false;
if (hasFields)
{
for (FieldLayer layer : FieldLayer.values())
{
Field field = fields.get( layer );
if (field != null && field.getSpriteGroup().light != null)
{
hasFieldLight = true;
break;
}
}
}
}
public final int[] addGameEntity( GameEntity obj )
{
GameTile oldTile = obj.tile[ 0 ][ 0 ];
obj.removeFromTile();
for ( int x = 0; x < obj.size; x++ )
{
for ( int y = 0; y < obj.size; y++ )
{
GameTile tile = level.Grid[ this.x + x ][ this.y + y ];
tile.entity = obj;
obj.tile[ x ][ y ] = tile;
}
}
if ( oldTile != null ) { return getPosDiff( oldTile ); }
return new int[]{ 0, 0 };
}
public final int[] getPosDiff( GameTile prevTile )
{
int[] oldPos = new int[]{ prevTile.x * Global.TileSize, prevTile.y * Global.TileSize };
int[] newPos = { x * Global.TileSize, y * Global.TileSize };
int[] diff = { oldPos[ 0 ] - newPos[ 0 ], oldPos[ 1 ] - newPos[ 1 ] };
return diff;
}
public final float getDist( GameTile prevTile )
{
return Vector2.dst( prevTile.x, prevTile.y, x, y );
}
@Override
public final boolean getPassable( EnumBitflag<Passability> travelType, Object self )
{
if ( fields.size > 0 )
{
for ( FieldLayer layer : FieldLayer.values() )
{
Field field = fields.get( layer );
if ( field != null )
{
if ( field.allowPassability.intersect( travelType ) )
{
return true;
}
else if ( field.restrictPassability.intersect( travelType ) ) { return false; }
}
}
}
if ( environmentEntity != null && environmentEntity != self && !environmentEntity.passableBy.intersect( travelType ) && !environmentEntity.canTakeDamage )
{
return false;
}
boolean passable = tileData.passableBy.intersect( travelType );
if ( !passable ) { return false; }
if ( entity == null || entity == self || travelType.contains( Passability.ENTITY ) )
{
return true;
}
if ( entity != null && self instanceof GameEntity )
{
GameEntity selfEntity = (GameEntity)self;
if ( !selfEntity.isAllies( entity ) )
{
return true;
}
else if ( hasEntityStayedOnTile() )
{
return true;
}
else if (entity.dialogue == null && selfEntity.canSwap && entity.canMove)
{
return true;
}
}
return false;
}
@Override
public int getInfluence( EnumBitflag<Passability> travelType, Object self )
{
if (environmentEntity != null && !environmentEntity.passableBy.intersect( travelType ) && environmentEntity.canTakeDamage)
{
return 100;
}
return 0;
}
public void setLight( Light light, float intensity, Color colour )
{
lightMap.put( light, Global.LightDataPool.obtain().set( intensity, colour ) );
}
public void clearLight( Light light )
{
LightData data = lightMap.get( light );
Global.LightDataPool.free( data );
lightMap.remove( light );
}
public void composeLight()
{
light.set( ambientColour );
for ( Map.Entry<Light, LightData> pair : lightMap.entrySet() )
{
tempColour.set( pair.getValue().colour );
tempColour.mul( tempColour.a );
tempColour.a = 1;
tempColour.mul( pair.getValue().intensity );
light.add( tempColour );
}
}
public enum OrbType
{
EXPERIENCE("Oryx/uf_split/uf_items/crystal_sun"),
HEALTH("Oryx/uf_split/uf_items/crystal_blood");
public final String spriteName;
OrbType(String spriteName)
{
this.spriteName = spriteName;
}
}
public static class LightData
{
public float intensity;
public Color colour;
public LightData()
{
}
public LightData set( float intensity, Color colour )
{
this.intensity = intensity;
this.colour = colour;
return this;
}
}
}