Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions RogueEssence/Data/TileData.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
using RogueEssence.Dungeon;
using RogueEssence.Dev;
using RogueEssence.Content;
using RogueElements;
using Newtonsoft.Json;
using Microsoft.Xna.Framework;

namespace RogueEssence.Data
Expand All @@ -22,7 +25,8 @@ public enum TriggerType
Trap,
Switch,
Blocker,
Unlockable
Unlockable,
Object
}

public LocalText Name { get; set; }
Expand Down Expand Up @@ -52,21 +56,43 @@ public enum TriggerType
public TriggerType StepType;
public Loc MinimapIcon;
public Color MinimapColor;

/// <summary>
/// Allows the tile to be destroyed by certain attacks.
/// </summary>
public bool Destructible;

/// <summary>
/// Any supereffective move used against this tile will destroy it. If this is none, any attack will destroy it. Only used if Destructible is true.
/// </summary>
[JsonConverter(typeof(ElementListConverter))]
[Dev.DataType(0, DataManager.DataType.Element, false)]
public List<string> EffectiveElements;

/// <summary>
/// The minimum damage needed to destroy the tile. Only used if Destructible is true.
/// </summary>
public int PowerNeededToDestroy;

public PriorityList<SingleCharEvent> LandedOnTiles;
public PriorityList<SingleCharEvent> InteractWithTiles;

/// <summary>
/// Triggers right before the tile is destroyed. Only used if Destructible is true.
/// </summary>
public PriorityList<SingleCharEvent> OnTileDestroyed;

public TileData()
{
Name = new LocalText();
Desc = new LocalText();
Comment = "";
Anim = new ObjAnimData();
EffectiveElements = new List<string>();
LandedOnTiles = new PriorityList<SingleCharEvent>();
InteractWithTiles = new PriorityList<SingleCharEvent>();
OnTileDestroyed = new PriorityList<SingleCharEvent>();
}


public string GetColoredName()
{
return String.Format("[color=#00FF00]{0}[color]", Name.ToLocal());
Expand Down
17 changes: 15 additions & 2 deletions RogueEssence/Dungeon/BaseDungeonScene.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,22 @@ protected virtual void DrawItems(SpriteBatch spriteBatch, bool showHiddenItem)
{
foreach(Loc viewLoc in IterateRelevantDraw(wrapped, wrapSize, item))
{
TerrainTile tile = ZoneManager.Instance.CurrentMap.Tiles[item.TileLoc.X][item.TileLoc.Y].Data;
Tile rootTile = ZoneManager.Instance.CurrentMap.Tiles[item.TileLoc.X][item.TileLoc.Y];
TerrainTile tile = rootTile.Data;
TerrainData terrain = tile.GetData();
if (terrain.BlockType == TerrainData.Mobility.Impassable || terrain.BlockType == TerrainData.Mobility.Block)

//Object tiles should hide items beneath them
bool hiddenBehindObject = false;
if (!String.IsNullOrEmpty(rootTile.Effect.ID))
{
TileData effect = DataManager.Instance.GetTile(rootTile.Effect.ID);
if (effect.StepType == TileData.TriggerType.Object)
{
hiddenBehindObject = true;
}
}

if (terrain.BlockType == TerrainData.Mobility.Impassable || terrain.BlockType == TerrainData.Mobility.Block || hiddenBehindObject)
{
if (showHiddenItem)
item.Draw(spriteBatch, viewLoc, Color.White * 0.7f);
Expand Down
10 changes: 5 additions & 5 deletions RogueEssence/Dungeon/Characters/CharAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ private Loc GetLanding(Loc ownerLoc, Dir8 dir, int mod)
for (int ii = 0; ii < modRange; ii++)
{
targetLoc += addLoc;
if (ZoneManager.Instance.CurrentMap.TileBlocked(targetLoc, true))
if (ZoneManager.Instance.CurrentMap.TileAttackBlocked(targetLoc, true))
break;
}
return targetLoc + HitOffset;
Expand Down Expand Up @@ -1320,7 +1320,7 @@ public Loc GetFarthestLanding(Character owner, Loc ownerLoc, Dir8 dir, int mod)
for (int ii = 0; ii < modRange; ii++)
{
targetLoc += addLoc;
if (ZoneManager.Instance.CurrentMap.TileBlocked(targetLoc, true))
if (ZoneManager.Instance.CurrentMap.TileAttackBlocked(targetLoc, true))
break;
}
return targetLoc;
Expand Down Expand Up @@ -1415,14 +1415,14 @@ public override bool IsWide()
}


if (ZoneManager.Instance.CurrentMap.TileBlocked(leftLoc, true))
if (ZoneManager.Instance.CurrentMap.TileAttackBlocked(leftLoc, true))
sideL[side] = false;
if (ZoneManager.Instance.CurrentMap.TileBlocked(rightLoc, true))
if (ZoneManager.Instance.CurrentMap.TileAttackBlocked(rightLoc, true))
sideR[side] = false;
}
}

if (ZoneManager.Instance.CurrentMap.TileBlocked(targetLoc, true))
if (ZoneManager.Instance.CurrentMap.TileAttackBlocked(targetLoc, true))
sideM = false;
}
return null;
Expand Down
4 changes: 2 additions & 2 deletions RogueEssence/Dungeon/Characters/Hitbox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ private void preCalculateCoverage(StablePriorityQueue<int, Loc> tilesToHit, int
tilesToHit.Enqueue(calculateTimeToHit(Origin) + delay, Origin);

Loc backup = Origin;
if (MaxRadius > 0 && ZoneManager.Instance.CurrentMap.TileBlocked(Origin, true))
if (MaxRadius > 0 && ZoneManager.Instance.CurrentMap.TileAttackBlocked(Origin, true))
backup += Dir.Reverse().GetLoc();

Grid.FloodFill(new Rect(Origin - new Loc(MaxRadius), new Loc(MaxRadius * 2 + 1)),
Expand All @@ -467,7 +467,7 @@ private void preCalculateCoverage(StablePriorityQueue<int, Loc> tilesToHit, int
return true;
if (!IsInSquareHitbox(testLoc, Origin, MaxRadius, HitArea, Dir))
return true;
if (ZoneManager.Instance.CurrentMap.TileBlocked(testLoc, true))
if (ZoneManager.Instance.CurrentMap.TileAttackBlocked(testLoc, true))
return true;

return false;
Expand Down
2 changes: 1 addition & 1 deletion RogueEssence/Dungeon/DSceneAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ public bool IsTargeted(Loc tile, TileAlignment tileAlignment)
return true;

TerrainData.Mobility mobility = TerrainData.Mobility.Lava | TerrainData.Mobility.Water | TerrainData.Mobility.Abyss;
if (ZoneManager.Instance.CurrentMap.TileBlocked(tile, mobility))
if (ZoneManager.Instance.CurrentMap.TileAttackBlocked(tile, mobility))
return true;
else
return false;
Expand Down
4 changes: 2 additions & 2 deletions RogueEssence/Dungeon/DSceneMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ public IEnumerator<YieldInstruction> ProcessObjectInteract(Character character,
if (tile != null && !String.IsNullOrEmpty(tile.Effect.ID))
{
TileData entry = DataManager.Instance.GetTile(tile.Effect.ID);
if (entry.StepType == TileData.TriggerType.Blocker || entry.StepType == TileData.TriggerType.Unlockable)
if (entry.StepType == TileData.TriggerType.Blocker || entry.StepType == TileData.TriggerType.Unlockable || entry.StepType == TileData.TriggerType.Object)
{
yield return CoroutineManager.Instance.StartCoroutine(tile.Effect.LandedOnTile(character));
yield return CoroutineManager.Instance.StartCoroutine(ActivateTraps(character));
Expand Down Expand Up @@ -1446,7 +1446,7 @@ public IEnumerator<YieldInstruction> ThrowTo(Character character, Character atta
for (int ii = 0; ii < range; ii++)
{
Loc nextLoc = endLoc + dir.GetLoc();
if (ZoneManager.Instance.CurrentMap.TileBlocked(nextLoc, true))
if (ZoneManager.Instance.CurrentMap.TileAttackBlocked(nextLoc, true))
break;
endLoc = nextLoc;
}
Expand Down
17 changes: 15 additions & 2 deletions RogueEssence/Dungeon/DungeonScene.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1049,8 +1049,21 @@ protected override void DrawItems(SpriteBatch spriteBatch, bool showHiddenItem)
{
foreach (Loc viewLoc in IterateRelevantDraw(wrapped, wrapSize, item))
{
TerrainData terrain = ZoneManager.Instance.CurrentMap.Tiles[item.TileLoc.X][item.TileLoc.Y].Data.GetData();
if (terrain.BlockType == TerrainData.Mobility.Impassable || terrain.BlockType == TerrainData.Mobility.Block)
Tile rootTile = ZoneManager.Instance.CurrentMap.Tiles[item.TileLoc.X][item.TileLoc.Y];
TerrainData terrain = rootTile.Data.GetData();

//Object tiles should hide items beneath them
bool hiddenBehindObject = false;
if (!String.IsNullOrEmpty(rootTile.Effect.ID))
{
TileData effect = DataManager.Instance.GetTile(rootTile.Effect.ID);
if (effect.StepType == TileData.TriggerType.Object)
{
hiddenBehindObject = true;
}
}

if (terrain.BlockType == TerrainData.Mobility.Impassable || terrain.BlockType == TerrainData.Mobility.Block || hiddenBehindObject)
{
if (showHiddenItem)
item.Draw(spriteBatch, viewLoc, Color.White * 0.5f);
Expand Down
44 changes: 44 additions & 0 deletions RogueEssence/Dungeon/GameEffects/BattleContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,28 @@ public IEnumerator<YieldInstruction> ProcessHitLoc(Loc loc)
actionContext.Target = charTarget;
yield return CoroutineManager.Instance.StartCoroutine(DungeonScene.Instance.HitTarget(actionContext, charTarget));//hit the character
}

Tile tile = ZoneManager.Instance.CurrentMap.GetTile(actionContext.TargetTile);
if (!String.IsNullOrEmpty(tile.Effect.ID))
{
TileData entry = DataManager.Instance.GetTile(tile.Effect.GetID());
if (entry != null && entry.Destructible && actionContext.ActionType == BattleActionType.Skill)
{
BattleData data = actionContext.Data;
if (data != null)
{
BasePowerState powerState = data.SkillStates.GetWithDefault<BasePowerState>();
//Check if the attack is from the specific element or from no element, and deals enough damage
if ((entry.EffectiveElements.Contains(data.Element) || entry.EffectiveElements.Count == 0)
&& powerState != null && powerState.Power >= entry.PowerNeededToDestroy)
{
yield return CoroutineManager.Instance.StartCoroutine(tile.Effect.OnTileDestroyed(charTarget));
tile.Effect = new EffectTile(tile.Effect.TileLoc);
}
}
}
}

//do thing to tile
yield return CoroutineManager.Instance.StartCoroutine(actionContext.User.HitTile(actionContext));
}
Expand All @@ -241,6 +263,28 @@ public IEnumerator<YieldInstruction> ProcessHitTile(Loc loc)
BattleContext actionContext = new BattleContext(this, false);
actionContext.TargetTile = loc;

Tile tile = ZoneManager.Instance.CurrentMap.GetTile(actionContext.TargetTile);
if (!String.IsNullOrEmpty(tile.Effect.ID))
{
TileData entry = DataManager.Instance.GetTile(tile.Effect.GetID());
if (entry != null && entry.Destructible && actionContext.ActionType == BattleActionType.Skill)
{
BattleData data = actionContext.Data;
Character charTarget = actionContext.User;
if (data != null && charTarget != null)
{
BasePowerState powerState = data.SkillStates.GetWithDefault<BasePowerState>();
//Check if the attack is from the specific element or from no element, and deals enough damage
if ((entry.EffectiveElements.Contains(data.Element) || entry.EffectiveElements.Count == 0)
&& powerState != null && powerState.Power >= entry.PowerNeededToDestroy)
{
yield return CoroutineManager.Instance.StartCoroutine(tile.Effect.OnTileDestroyed(charTarget));
tile.Effect = new EffectTile(tile.Effect.TileLoc);
}
}
}
}

//do thing to tile
yield return CoroutineManager.Instance.StartCoroutine(actionContext.User.HitTile(actionContext));
}
Expand Down
38 changes: 37 additions & 1 deletion RogueEssence/Dungeon/Maps/BaseMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,42 @@ public int GetItem(Loc loc)
}
return -1;
}

public bool TileAttackBlocked(Loc loc)
{
return TileAttackBlocked(loc, false);
}

public bool TileAttackBlocked(Loc loc, bool inclusive)
{
return TileAttackBlocked(loc, inclusive, false);
}

public bool TileAttackBlocked(Loc loc, bool inclusive, bool diagonal)
{
return TileAttackBlocked(loc, inclusive ? TerrainData.Mobility.All : TerrainData.Mobility.Passable, diagonal);
}

public bool TileAttackBlocked(Loc loc, TerrainData.Mobility mobility)
{
return TileAttackBlocked(loc, mobility, false);
}

public bool TileAttackBlocked(Loc loc, TerrainData.Mobility mobility, bool diagonal)
{
Tile tile = Tiles[loc.X][loc.Y];
if (!String.IsNullOrEmpty(tile.Effect.ID))
{
TileData effect = DataManager.Instance.GetTile(tile.Effect.ID);
if (effect.StepType == TileData.TriggerType.Object)
{
//Objects should allow attacks through but not movement
return false;
}
}

return TileBlocked(loc, mobility, diagonal);
}

public bool TileBlocked(Loc loc)
{
Expand Down Expand Up @@ -185,7 +221,7 @@ public bool EffectTileBlocked(TileData effect, bool diagonal)
//doesn't apply here; for now, assume all effects block diagonal if they block at all
//if (diagonal && !effect.BlockDiagonal)
// return false;
if (effect.StepType == TileData.TriggerType.Unlockable || effect.StepType == TileData.TriggerType.Blocker)
if (effect.StepType == TileData.TriggerType.Unlockable || effect.StepType == TileData.TriggerType.Blocker || effect.StepType == TileData.TriggerType.Object)
return true;

return false;
Expand Down
17 changes: 17 additions & 0 deletions RogueEssence/Dungeon/Tiles/EffectTile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,23 @@ public IEnumerator<YieldInstruction> LandedOnTile(Character character)
yield break;
}
}

public IEnumerator<YieldInstruction> OnTileDestroyed(Character character)
{
SingleCharContext context = new SingleCharContext(character);
// should the context be extended to the caller?
DungeonScene.EventEnqueueFunction<SingleCharEvent> function = (StablePriorityQueue<GameEventPriority, EventQueueElement<SingleCharEvent>> queue, Priority maxPriority, ref Priority nextPriority) =>
{
TileData entry = DataManager.Instance.GetTile(ID);
AddEventsToQueue<SingleCharEvent>(queue, maxPriority, ref nextPriority, entry.OnTileDestroyed, context.User);
};
foreach (EventQueueElement<SingleCharEvent> effect in DungeonScene.IterateEvents<SingleCharEvent>(function))
{
yield return CoroutineManager.Instance.StartCoroutine(effect.Event.Apply(effect.Owner, effect.OwnerChar, context));
if (context.CancelState.Cancel)
yield break;
}
}

public void DrawDebug(SpriteBatch spriteBatch, Loc offset) { }
public void Draw(SpriteBatch spriteBatch, Loc offset)
Expand Down