Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug Fixes and GP Add/Remove Commands #78

Merged
merged 6 commits into from
May 16, 2020
Merged
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
4 changes: 2 additions & 2 deletions src/InteractiveSeven.Core/Diagnostics/Memory/GilAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ namespace InteractiveSeven.Core.Diagnostics.Memory
public class GilAccessor : IGilAccessor
{
private readonly IMemoryAccessor _memoryAccessor;
private readonly ILogger<GameMomentAccessor> _logger;
private readonly ILogger<GilAccessor> _logger;
private ApplicationSettings Settings => ApplicationSettings.Instance;
private static readonly object Padlock = new object();

public GilAccessor(IMemoryAccessor memoryAccessor, ILogger<GameMomentAccessor> logger)
public GilAccessor(IMemoryAccessor memoryAccessor, ILogger<GilAccessor> logger)
{
_memoryAccessor = memoryAccessor;
_logger = logger;
Expand Down
87 changes: 87 additions & 0 deletions src/InteractiveSeven.Core/Diagnostics/Memory/GpAccessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using InteractiveSeven.Core.FinalFantasy;
using InteractiveSeven.Core.Settings;
using Microsoft.Extensions.Logging;
using System;

namespace InteractiveSeven.Core.Diagnostics.Memory
{
public class GpAccessor : IGpAccessor
{
private readonly IMemoryAccessor _memoryAccessor;
private readonly ILogger<GpAccessor> _logger;
private ApplicationSettings Settings => ApplicationSettings.Instance;
private static readonly object Padlock = new object();

public GpAccessor(IMemoryAccessor memoryAccessor, ILogger<GpAccessor> logger)
{
_memoryAccessor = memoryAccessor;
_logger = logger;
}

public ushort GetGp()
{
try
{
lock (Padlock)
{
var buffer = new byte[Addresses.Gp.NumBytes];
_memoryAccessor.ReadMem(Settings.ProcessName, Addresses.Gp.Address, buffer);
return BitConverter.ToUInt16(buffer);
}
}
catch (Exception e)
{
_logger.LogError(e, "Error setting player GP.");
}

return 0;
}

public void AddGp(in ushort amount)
{
try
{
lock (Padlock)
{
var buffer = new byte[Addresses.Gp.NumBytes];
_memoryAccessor.ReadMem(Settings.ProcessName, Addresses.Gp.Address, buffer);
ushort currentBalance = BitConverter.ToUInt16(buffer);
currentBalance += amount;
_memoryAccessor.WriteMem(Settings.ProcessName, Addresses.Gp.Address,
BitConverter.GetBytes(currentBalance));
}
}
catch (Exception e)
{
_logger.LogError(e, "Error adding GP to player.");
}
}

public void RemoveGp(ushort amount)
{
try
{
lock (Padlock)
{
var buffer = new byte[Addresses.Gp.NumBytes];
_memoryAccessor.ReadMem(Settings.ProcessName, Addresses.Gp.Address, buffer);
ushort currentBalance = BitConverter.ToUInt16(buffer);
if (currentBalance >= amount)
{
currentBalance -= amount;
}
else
{
currentBalance = 0;
}
_memoryAccessor.WriteMem(Settings.ProcessName, Addresses.Gp.Address,
BitConverter.GetBytes(currentBalance));
}
}
catch (Exception e)
{
_logger.LogError(e, "Error adding GP to player.");
}
}
}
}
9 changes: 9 additions & 0 deletions src/InteractiveSeven.Core/Diagnostics/Memory/IGpAccessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace InteractiveSeven.Core.Diagnostics.Memory
{
public interface IGpAccessor
{
ushort GetGp();
void AddGp(in ushort amount);
void RemoveGp(ushort amount);
}
}
6 changes: 6 additions & 0 deletions src/InteractiveSeven.Core/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public static int SafeIntParse(this string text)
return result;
}

public static ushort SafeUshortParse(this string text)
{
ushort.TryParse(text, out ushort result);
return result;
}

public static string NoAt(this string text) => text.TrimStart('@');
}
}
1 change: 1 addition & 0 deletions src/InteractiveSeven.Core/FinalFantasy/Addresses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public static class Addresses
public static readonly MemLoc MenuBotRightSave = new MemLoc(0x91EFE1, 3); // order red, green, blue

public static readonly MemLoc Gil = new MemLoc(0xDC08B4, 4); // 4 bytes
public static readonly MemLoc Gp = new MemLoc(0xDC0A26, 2); // Max of 10,000?
public static readonly MemLoc GameMoment = new MemLoc(0xDC08DC, 2);

public static readonly MemLoc MenuVisibility = new MemLoc(0xDC08F8, 2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
public static class FF7Const
{
public const byte Empty = 0xFF;
public const ushort MaxGp = 10_000;
}
}
31 changes: 29 additions & 2 deletions src/InteractiveSeven.Core/Settings/CommandSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class CommandSettings : ObservableSettingsBase
{
private string[] _givePlayerGilCommandWords = { "FindGil", "GivePlayerGil" };
private string[] _removePlayerGilCommandWords = { "DropGil", "RemovePlayerGil" };
private string[] _givePlayerGpCommandWords = { "FindGp", "GivePlayerGp" };
private string[] _removePlayerGpCommandWords = { "DropGp", "RemovePlayerGp" };
private string[] _esunaCommandWords = { "Esuna", "Remedy" };
private string[] _healCommandWords = { "Heal", "Cure" };
private string[] _costsCommandWords = { "Costs", "Cost", "Price", "Prices" };
Expand Down Expand Up @@ -52,11 +54,16 @@ public CommandSettings()
("BrendanLock", () => new [] {"BrendanLock"}),
("BrendanUnlock", () => new [] {"BrendanUnlock"}),

(nameof(GiveGilCommandWords),
() => GiveGilCommandWords),
(nameof(GivePlayerGilCommandWords),
() => GivePlayerGilCommandWords),
(nameof(RemovePlayerGilCommandWords),
() => RemovePlayerGilCommandWords),

(nameof(GivePlayerGpCommandWords),
() => GivePlayerGpCommandWords),
(nameof(RemovePlayerGpCommandWords),
() => RemovePlayerGpCommandWords),

(nameof(EsunaCommandWords),
() => EsunaCommandWords),
(nameof(HealCommandWords),
Expand Down Expand Up @@ -153,6 +160,26 @@ public string[] RemovePlayerGilCommandWords
}
}

public string[] GivePlayerGpCommandWords
{
get => _givePlayerGpCommandWords;
set
{
_givePlayerGpCommandWords = RemoveAllDuplicates(value);
OnPropertyChanged();
}
}

public string[] RemovePlayerGpCommandWords
{
get => _removePlayerGpCommandWords;
set
{
_removePlayerGpCommandWords = RemoveAllDuplicates(value);
OnPropertyChanged();
}
}

public string[] EsunaCommandWords
{
get => _esunaCommandWords;
Expand Down
1 change: 1 addition & 0 deletions src/InteractiveSeven.Core/Settings/EquipmentSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,6 @@ public List<EquippableSettings> AllByName(string name, CharNames charName, Type
public List<EquippableSettings> AllArmlets { get; set; }
public List<EquippableSettings> AllAccessories { get; set; }
public PlayerGilSettings PlayerGilSettings { get; set; } = new PlayerGilSettings();
public PlayerGpSettings PlayerGpSettings { get; set; } = new PlayerGpSettings();
}
}
57 changes: 57 additions & 0 deletions src/InteractiveSeven.Core/Settings/PlayerGpSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
namespace InteractiveSeven.Core.Settings
{
public class PlayerGpSettings : ObservableSettingsBase
{
private ushort _giveMultiplier = 100;
private ushort _removeMultiplier = 100;
private bool _allowModOverride = true;
private bool _giveGpEnabled = false;
private bool _removeGpEnabled = false;

public bool GiveGpEnabled
{
get => _giveGpEnabled;
set
{
_giveGpEnabled = value;
OnPropertyChanged();
}
}
public bool RemoveGpEnabled
{
get => _removeGpEnabled;
set
{
_removeGpEnabled = value;
OnPropertyChanged();
}
}
public ushort GiveMultiplier
{
get => _giveMultiplier;
set
{
_giveMultiplier = value;
OnPropertyChanged();
}
}
public ushort RemoveMultiplier
{
get => _removeMultiplier;
set
{
_removeMultiplier = value;
OnPropertyChanged();
}
}
public bool AllowModOverride
{
get => _allowModOverride;
set
{
_allowModOverride = value;
OnPropertyChanged();
}
}
}
}
68 changes: 68 additions & 0 deletions src/InteractiveSeven.Twitch/Commands/GivePlayerGpCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using InteractiveSeven.Core;
using InteractiveSeven.Core.Diagnostics.Memory;
using InteractiveSeven.Core.Emitters;
using InteractiveSeven.Core.FinalFantasy.Constants;
using InteractiveSeven.Core.Settings;
using InteractiveSeven.Twitch.Model;
using InteractiveSeven.Twitch.Payments;
using System.Linq;
using TwitchLib.Client.Interfaces;

namespace InteractiveSeven.Twitch.Commands
{
public class GivePlayerGpCommand : BaseCommand
{
private readonly PaymentProcessor _paymentProcessor;
private readonly ITwitchClient _twitchClient;
private readonly IGpAccessor _gpAccessor;
private readonly IStatusHubEmitter _statusHubEmitter;
private PlayerGpSettings GpSettings => Settings.EquipmentSettings.PlayerGpSettings;

public GivePlayerGpCommand(PaymentProcessor paymentProcessor, ITwitchClient twitchClient,
IGpAccessor gpAccessor, IStatusHubEmitter statusHubEmitter)
: base(x => x.GivePlayerGpCommandWords,
x => x.EquipmentSettings.PlayerGpSettings.GiveGpEnabled)
{
_paymentProcessor = paymentProcessor;
_twitchClient = twitchClient;
_gpAccessor = gpAccessor;
_statusHubEmitter = statusHubEmitter;
}

public override void Execute(in CommandData commandData)
{
ushort amount = commandData.Arguments.FirstOrDefault().SafeUshortParse();

if (amount <= 0)
{
_twitchClient.SendMessage(commandData.Channel,
$"How much gp do you want to give to the player, {commandData.User.Username}?");
return;
}

ushort currentGp = _gpAccessor.GetGp();
if (FF7Const.MaxGp - currentGp > amount)
{
_twitchClient.SendMessage(commandData.Channel,
$"Max GP is {FF7Const.MaxGp:N0}. Current GP: {currentGp:N0}.");
return;
}

int gilCost = amount * GpSettings.GiveMultiplier;
GilTransaction gilTransaction = _paymentProcessor.ProcessPayment(
commandData, gilCost, GpSettings.AllowModOverride);

if (!gilTransaction.Paid)
{
_twitchClient.SendMessage(commandData.Channel,
$"You don't have {gilCost} gil, {commandData.User.Username}.");
return;
}

_gpAccessor.AddGp(amount);
string message = $"Added {amount} GP for player.";
_twitchClient.SendMessage(commandData.Channel, message);
_statusHubEmitter.ShowEvent(message);
}
}
}
13 changes: 7 additions & 6 deletions src/InteractiveSeven.Twitch/Commands/NameCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ private static bool ShouldTriggerFor(in CommandData commandData, string[] words,
private void TriggerDomainEvent(in CharNames charName, in CommandData data)
{
int gil = GetGilFromCommandData(data);

if (gil < 1)
{
_twitchClient.SendMessage(data.Channel, $"Be sure to include a gil amount in your name bid, {data.User.Username}");
return;
}

if (!CanOverrideBitRestriction(data.User))
{
(int balance, int withdrawn) = _gilBank.Withdraw(data.User, gil, true);
Expand All @@ -101,12 +108,6 @@ private void TriggerDomainEvent(in CharNames charName, in CommandData data)
}
}

if (gil < 1)
{
_twitchClient.SendMessage(data.Channel, $"Be sure to include a gil amount in your name bid, {data.User.Username}");
return;
}

string newName = data.Arguments.FirstOrDefault() ?? "";

var bidRecord = new BidRecord(data.User.Username, data.User.UserId, gil);
Expand Down
Loading