Skip to content

Commit

Permalink
Merge pull request #96 from ethanmoffat/map_features
Browse files Browse the repository at this point in the history
Big merge: Implement most of the missing map display features

Includes:
- F12 map refresh
- Hopping stones (jump tiles)
- Spikes
- Map signs / map sign serializer fixes
- Click to walk fixes
- Water splashies (water tiles)
- Rendering of effects cast by other players
- Damage counters above players and NPCs
- Earthquakes
- HP/TP drain
  • Loading branch information
ethanmoffat committed Jan 27, 2021
2 parents 9981e2d + 3c38020 commit d4fde4d
Show file tree
Hide file tree
Showing 123 changed files with 2,572 additions and 1,536 deletions.
1 change: 1 addition & 0 deletions BatchMap/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ private static void Main(string[] args)
private static void SetupDependencies()
{
_typeRegistry = new UnityRegistry("EOLib.IO");
_typeRegistry.RegisterDiscoveredTypes();

_pubProvider = _typeRegistry.Resolve<IPubFileProvider>();
_mapFileProvider = _typeRegistry.Resolve<IMapFileProvider>();
Expand Down
6 changes: 3 additions & 3 deletions EOLib.IO/Map/MapPathToIDConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ public class MapPathToIDConverter
{
public int ConvertFromPathToID(string pathToMapFile)
{
var lastSlash = pathToMapFile.LastIndexOf('\\') < 0 ? pathToMapFile.LastIndexOf('/') : -1;
if (lastSlash < 0)
var lastDot = pathToMapFile.LastIndexOf('.');
if (lastDot < 5)
throw new IOException();

var strID = pathToMapFile.Substring(lastSlash + 1, 5);
var strID = pathToMapFile.Substring(lastDot - 5, 5);
return int.Parse(strID);
}
}
Expand Down
2 changes: 1 addition & 1 deletion EOLib.IO/Map/SignMapEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace EOLib.IO.Map
{
public class SignMapEntity : IMapEntity
{
public const int DATA_SIZE = 5;
public const int DATA_SIZE = 4;

public int X { get; private set; }

Expand Down
2 changes: 1 addition & 1 deletion EOLib.IO/Services/Serializers/MapFileSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ private int GetVariableSignLength(MemoryStream ms)
ms.Read(messageLengthRaw, 0, 2); //read two-byte length
ms.Seek(-4, SeekOrigin.Current); //skip back to beginning

return _numberEncoderService.DecodeNumber(messageLengthRaw) - 1;
return _numberEncoderService.DecodeNumber(messageLengthRaw);
}

#endregion
Expand Down
18 changes: 6 additions & 12 deletions EOLib.IO/Services/Serializers/SignMapEntitySerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,12 @@ public byte[] SerializeToByteArray(SignMapEntity mapEntity)

retBytes.AddRange(numberEncoderService.EncodeNumber(mapEntity.X, 1));
retBytes.AddRange(numberEncoderService.EncodeNumber(mapEntity.Y, 1));
retBytes.AddRange(numberEncoderService.EncodeNumber(mapEntity.Title.Length + mapEntity.Message.Length + 1, 2));

var fileMsg = new byte[mapEntity.Message.Length + mapEntity.Title.Length];

var rawTitle = mapStringEncoderService.EncodeMapString(mapEntity.Title);
Array.Copy(rawTitle, fileMsg, rawTitle.Length);

var rawMessage = mapStringEncoderService.EncodeMapString(mapEntity.Message);
Array.Copy(rawMessage, 0, fileMsg, rawTitle.Length, rawMessage.Length);
var fileMsg = mapStringEncoderService.EncodeMapString(mapEntity.Title + mapEntity.Message);
retBytes.AddRange(numberEncoderService.EncodeNumber(fileMsg.Length + 1, 2));

retBytes.AddRange(fileMsg);
retBytes.AddRange(numberEncoderService.EncodeNumber(rawTitle.Length, 1));
retBytes.AddRange(numberEncoderService.EncodeNumber(mapEntity.Title.Length, 1));

return retBytes.ToArray();
}
Expand All @@ -50,12 +44,12 @@ public SignMapEntity DeserializeFromByteArray(byte[] data)
.WithX(numberEncoderService.DecodeNumber(data[0]))
.WithY(numberEncoderService.DecodeNumber(data[1]));

var titleAndMessageLength = numberEncoderService.DecodeNumber(data[2], data[3]) - 1;
var titleAndMessageLength = numberEncoderService.DecodeNumber(data[2], data[3]);
if (data.Length != SignMapEntity.DATA_SIZE + titleAndMessageLength)
throw new ArgumentException("Data is improperly sized for deserialization", nameof(data));

var rawTitleAndMessage = data.Skip(4).Take(titleAndMessageLength).ToArray();
var titleLength = numberEncoderService.DecodeNumber(data[4 + titleAndMessageLength]);
var rawTitleAndMessage = data.Skip(SignMapEntity.DATA_SIZE).Take(titleAndMessageLength - 1).ToArray();
var titleLength = numberEncoderService.DecodeNumber(data[SignMapEntity.DATA_SIZE + titleAndMessageLength - 1]);

var titleAndMessage = mapStringEncoderService.DecodeMapString(rawTitleAndMessage);
sign = sign.WithTitle(titleAndMessage.Substring(0, titleLength))
Expand Down
32 changes: 24 additions & 8 deletions EOLib/Domain/Character/CharacterRenderProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public class CharacterRenderProperties : ICharacterRenderProperties
public int MapX { get; private set; }
public int MapY { get; private set; }

public int WalkFrame { get; private set; }
public int ActualWalkFrame { get; private set; }
public int RenderWalkFrame { get; private set; }
public int AttackFrame { get; private set; }
public int EmoteFrame { get; private set; }

Expand Down Expand Up @@ -123,11 +124,23 @@ public ICharacterRenderProperties WithMapY(int mapY)
return props;
}

public ICharacterRenderProperties WithNextWalkFrame()
public ICharacterRenderProperties WithNextWalkFrame(bool isSteppingStone = false)
{
var props = MakeCopy(this);
props.WalkFrame = (props.WalkFrame + 1) % MAX_NUMBER_OF_WALK_FRAMES;
props.CurrentAction = props.WalkFrame == 0 ? CharacterActionState.Standing : CharacterActionState.Walking;
props.ActualWalkFrame = (props.ActualWalkFrame + 1) % MAX_NUMBER_OF_WALK_FRAMES;

if (isSteppingStone && props.ActualWalkFrame > 1)
{
// force first walk frame when on a stepping stone (this is the graphic used for jump, Y adjusted)
props.RenderWalkFrame = 1;
}
else
{
props.RenderWalkFrame = props.ActualWalkFrame;
}

props.CurrentAction = props.RenderWalkFrame == 0 ? CharacterActionState.Standing : CharacterActionState.Walking;

return props;
}

Expand Down Expand Up @@ -159,7 +172,7 @@ public ICharacterRenderProperties WithNextSpellCastFrame()
public ICharacterRenderProperties ResetAnimationFrames()
{
var props = MakeCopy(this);
props.WalkFrame = 0;
props.RenderWalkFrame = 0;
props.AttackFrame = 0;
props.EmoteFrame = 0;
props.CurrentAction = CharacterActionState.Standing;
Expand Down Expand Up @@ -228,7 +241,8 @@ private static CharacterRenderProperties MakeCopy(ICharacterRenderProperties oth
MapX = other.MapX,
MapY = other.MapY,

WalkFrame = other.WalkFrame,
ActualWalkFrame = other.ActualWalkFrame,
RenderWalkFrame = other.RenderWalkFrame,
AttackFrame = other.AttackFrame,
EmoteFrame = other.EmoteFrame,

Expand Down Expand Up @@ -257,7 +271,8 @@ public override bool Equals(object obj)
Direction == properties.Direction &&
MapX == properties.MapX &&
MapY == properties.MapY &&
WalkFrame == properties.WalkFrame &&
ActualWalkFrame == properties.ActualWalkFrame &&
RenderWalkFrame == properties.RenderWalkFrame &&
AttackFrame == properties.AttackFrame &&
EmoteFrame == properties.EmoteFrame &&
SitState == properties.SitState &&
Expand All @@ -283,7 +298,8 @@ public override int GetHashCode()
hashCode = hashCode * -1521134295 + Direction.GetHashCode();
hashCode = hashCode * -1521134295 + MapX.GetHashCode();
hashCode = hashCode * -1521134295 + MapY.GetHashCode();
hashCode = hashCode * -1521134295 + WalkFrame.GetHashCode();
hashCode = hashCode * -1521134295 + ActualWalkFrame.GetHashCode();
hashCode = hashCode * -1521134295 + RenderWalkFrame.GetHashCode();
hashCode = hashCode * -1521134295 + AttackFrame.GetHashCode();
hashCode = hashCode * -1521134295 + EmoteFrame.GetHashCode();
hashCode = hashCode * -1521134295 + SitState.GetHashCode();
Expand Down
5 changes: 3 additions & 2 deletions EOLib/Domain/Character/ICharacterRenderProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public interface ICharacterRenderProperties : ICloneable
int MapX { get; }
int MapY { get; }

int WalkFrame { get; }
int ActualWalkFrame { get; }
int RenderWalkFrame { get; }
int AttackFrame { get; }
int EmoteFrame { get; }

Expand All @@ -49,7 +50,7 @@ public interface ICharacterRenderProperties : ICloneable
ICharacterRenderProperties WithMapX(int mapX);
ICharacterRenderProperties WithMapY(int mapY);

ICharacterRenderProperties WithNextWalkFrame();
ICharacterRenderProperties WithNextWalkFrame(bool isSteppingStone = false);
ICharacterRenderProperties WithNextAttackFrame();
ICharacterRenderProperties WithNextEmoteFrame();
ICharacterRenderProperties WithNextSpellCastFrame();
Expand Down
13 changes: 13 additions & 0 deletions EOLib/Domain/Extensions/CharacterExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using EOLib.Domain.Character;
using System;

namespace EOLib.Domain.Extensions
{
Expand Down Expand Up @@ -38,5 +39,17 @@ public static ICharacter WithAppliedData(this ICharacter original, ICharacter up
.WithRenderProperties(newRenderProps)
.WithStats(newStats);
}

public static ICharacter WithDamage(this ICharacter original, int damageTaken, bool isDead)
{
var stats = original.Stats;
stats = stats.WithNewStat(CharacterStat.HP, (short)Math.Max(stats[CharacterStat.HP] - damageTaken, 0));

var props = original.RenderProperties;
if (isDead)
props = props.WithDead();

return original.WithStats(stats).WithRenderProperties(props);
}
}
}
9 changes: 9 additions & 0 deletions EOLib/Domain/Map/CurrentMapStateRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public interface ICurrentMapStateRepository

HashSet<IWarp> PendingDoors { get; set; }

HashSet<MapCoordinate> VisibleSpikeTraps { get; set; }

WarpState MapWarpState { get; set; }
}

Expand All @@ -40,6 +42,8 @@ public interface ICurrentMapStateProvider

IReadOnlyCollection<IWarp> PendingDoors { get; }

IReadOnlyCollection<MapCoordinate> VisibleSpikeTraps { get; }

WarpState MapWarpState { get; set; }
}

Expand All @@ -60,6 +64,8 @@ public class CurrentMapStateRepository : ICurrentMapStateRepository, ICurrentMap

public HashSet<IWarp> PendingDoors { get; set; }

public HashSet<MapCoordinate> VisibleSpikeTraps { get; set; }

public WarpState MapWarpState { get; set; }

IReadOnlyCollection<ICharacter> ICurrentMapStateProvider.Characters => Characters;
Expand All @@ -72,6 +78,8 @@ public class CurrentMapStateRepository : ICurrentMapStateRepository, ICurrentMap

IReadOnlyCollection<IWarp> ICurrentMapStateProvider.PendingDoors => PendingDoors;

IReadOnlyCollection<MapCoordinate> ICurrentMapStateProvider.VisibleSpikeTraps => VisibleSpikeTraps;

public CurrentMapStateRepository()
{
ResetState();
Expand All @@ -87,6 +95,7 @@ public void ResetState()
MapItems = new HashSet<IItem>();
OpenDoors = new HashSet<IWarp>();
PendingDoors = new HashSet<IWarp>();
VisibleSpikeTraps = new HashSet<MapCoordinate>();

MapWarpState = WarpState.None;
}
Expand Down
2 changes: 2 additions & 0 deletions EOLib/Domain/Map/IMapCellState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ namespace EOLib.Domain.Map
{
public interface IMapCellState
{
bool InBounds { get; }

MapCoordinate Coordinate { get; }

IReadOnlyList<IItem> Items { get; }
Expand Down
8 changes: 8 additions & 0 deletions EOLib/Domain/Map/MapActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ public class MapActions : IMapActions
_characterProvider = characterProvider;
}

public void RequestRefresh()
{
var packet = new PacketBuilder(PacketFamily.Refresh, PacketAction.Request).Build();
_packetSendService.SendPacket(packet);
}

public ItemPickupResult PickUpItem(IItem item)
{
var pickupResult = _itemPickupValidator.ValidateItemPickup(_characterProvider.MainCharacter, item);
Expand All @@ -40,6 +46,8 @@ public ItemPickupResult PickUpItem(IItem item)

public interface IMapActions
{
void RequestRefresh();

ItemPickupResult PickUpItem(IItem item);
}
}
2 changes: 2 additions & 0 deletions EOLib/Domain/Map/MapCellState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ namespace EOLib.Domain.Map
{
public class MapCellState : IMapCellState
{
public bool InBounds { get; set; }

public MapCoordinate Coordinate { get; set; }

public IReadOnlyList<IItem> Items { get; set; }
Expand Down
3 changes: 2 additions & 1 deletion EOLib/Domain/Map/MapCellStateProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class MapCellStateProvider : IMapCellStateProvider
public IMapCellState GetCellStateAt(int x, int y)
{
if (x < 0 || y < 0 || x > CurrentMap.Properties.Width || y > CurrentMap.Properties.Height)
return new MapCellState {TileSpec = TileSpec.MapEdge};
return new MapCellState { InBounds = false, TileSpec = TileSpec.MapEdge };

var tileSpec = CurrentMap.Tiles[y, x];
var warp = CurrentMap.Warps[y, x];
Expand All @@ -42,6 +42,7 @@ public IMapCellState GetCellStateAt(int x, int y)

return new MapCellState
{
InBounds = true,
Coordinate = new MapCoordinate(x, y),
Items = items.ToList(),
TileSpec = tileSpec,
Expand Down
10 changes: 9 additions & 1 deletion EOLib/Domain/Map/Sign.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@ namespace EOLib.Domain.Map
{
public class Sign : ISign
{
public string Title { get; private set; }

public string Message { get; private set; }

public Sign(SignMapEntity sign)
{
Title = sign.Title;
Message = sign.Message;
}
}

public interface ISign
{
//todo: figure out properties
string Title { get; }

string Message { get; }
}
}
22 changes: 22 additions & 0 deletions EOLib/Domain/Notifiers/IEffectNotifier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using AutomaticTypeMapper;
using EOLib.Domain.Map;

namespace EOLib.Domain.Notifiers
{
public interface IEffectNotifier
{
void NotifyWarpLeaveEffect(short characterId, WarpAnimation anim);
void NotifyWarpEnterEffect(short characterId, WarpAnimation anim);
void NotifyPotionEffect(short playerId, int effectId);
void NotifyEarthquake(byte strength);
}

[AutoMappedType]
public class NoOpEffectNotifier : IEffectNotifier
{
public void NotifyWarpLeaveEffect(short characterId, WarpAnimation anim) { }
public void NotifyWarpEnterEffect(short characterId, WarpAnimation anim) { }
public void NotifyPotionEffect(short playerId, int effectId) { }
public void NotifyEarthquake(byte strength) { }
}
}
8 changes: 6 additions & 2 deletions EOLib/Domain/Notifiers/INPCActionNotifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ public interface INPCActionNotifier

void StartNPCAttackAnimation(int npcIndex);

void RemoveNPCFromView(int npcIndex, bool showDeathAnimation);
void RemoveNPCFromView(int npcIndex, int playerId, Optional<short> spellId, Optional<int> damage, bool showDeathAnimation);

void ShowNPCSpeechBubble(int npcIndex, string message);

void NPCTakeDamage(short npcIndex, int fromPlayerId, int damageToNpc, short npcPctHealth, Optional<int> spellId);
}

[AutoMappedType]
Expand All @@ -20,8 +22,10 @@ public class NoOpNPCActionNotifier : INPCActionNotifier

public void StartNPCAttackAnimation(int npcIndex) { }

public void RemoveNPCFromView(int npcIndex, bool showDeathAnimation) { }
public void RemoveNPCFromView(int npcIndex, int playerId, Optional<short> spellId, Optional<int> damage, bool showDeathAnimation) { }

public void ShowNPCSpeechBubble(int npcIndex, string message) { }

public void NPCTakeDamage(short npcIndex, int fromPlayerId, int damageToNpc, short npcPctHealth, Optional<int> spellId) { }
}
}
12 changes: 12 additions & 0 deletions EOLib/Domain/Notifiers/IOtherCharacterAnimationNotifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ public interface IOtherCharacterAnimationNotifier
void StartOtherCharacterWalkAnimation(int characterID);

void StartOtherCharacterAttackAnimation(int characterID);

void NotifyStartSpellCast(short playerId, short spellId);

void NotifySelfSpellCast(short playerId, short spellId, int spellHp, byte percentHealth);

void NotifyTargetOtherSpellCast(short sourcePlayerID, short targetPlayerID, short spellId, int recoveredHP, byte targetPercentHealth);
}

[AutoMappedType]
Expand All @@ -15,5 +21,11 @@ public class NoOpOtherCharacterAnimationNotifier : IOtherCharacterAnimationNotif
public void StartOtherCharacterWalkAnimation(int characterID) { }

public void StartOtherCharacterAttackAnimation(int characterID) { }

public void NotifyStartSpellCast(short playerId, short spellId) { }

public void NotifySelfSpellCast(short playerId, short spellId, int spellHp, byte percentHealth) { }

public void NotifyTargetOtherSpellCast(short sourcePlayerID, short targetPlayerID, short spellId, int recoveredHP, byte targetPercentHealth) { }
}
}

0 comments on commit d4fde4d

Please sign in to comment.