Skip to content
Draft
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
106 changes: 106 additions & 0 deletions Common/Rewards/CardTransformReward.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
using BaseLib.Abstracts;
using BaseLib.Extensions;
using BaseLib.Patches.Content;
using MegaCrit.Sts2.Core.Entities.Players;
using MegaCrit.Sts2.Core.Localization;
using MegaCrit.Sts2.Core.Models.Cards;
using MegaCrit.Sts2.Core.Rewards;
using MegaCrit.Sts2.Core.Runs;
using MegaCrit.Sts2.Core.Saves.Runs;

namespace BaseLib.Common.Rewards;

/// <summary>
/// A reward class similar to the card removal one created by <see cref="ForbiddenGrimoire"/>,
/// only for transforming instead of removing cards
/// </summary>
/// <example>
/// In a relic or power's <c>AfterCombatEnd</c> override
/// <code>
/// room.AddExtraReward(Owner.Player, new CardTransformReward(Owner.Player) {Amount = Amount, Upgrade = true});
/// </code> </example>
public sealed class CardTransformReward(Player player) : CustomReward(player)
{
/// <summary>
/// A new <see cref="RewardType"/> defined with the <see cref="CustomEnumAttribute"/> attribute
/// </summary>
[CustomEnum] public static RewardType CardTransform;
/// <summary>
/// Reference to the <see cref="RewardType"/> <see cref="CardTransform"/> defined earlier
/// </summary>
protected override RewardType RewardType => CardTransform;

/// <summary>
/// Whether the card rewards should be upgraded or not
/// </summary>
public required bool Upgrade;
/// <summary>
/// How many cards can be selected in this reward screen
/// </summary>
public required int Amount;

/// <summary>
/// The description to show in the reward screen,
/// switches based on whether the reward will upgrade the transformed cards
/// </summary>
public override LocString Description
{
get
{
LocString locString = new LocString("gameplay_ui", "COMBAT_REWARD_CARD_TRANSFORM");
locString.Add("cards", Amount);
locString.Add("Upgrade", Upgrade);
return locString;
}
}
/// <inheritdoc/>
public override bool IsPopulated => true;
public static string RewardIcon => ImageHelperExtensions.GetModImagePath("ui/reward_screen/reward_icon_card_transform.png");
/// <inheritdoc/>
protected override string IconPath => RewardIcon;


/// <summary>
/// Serializing the reward, saving whether to upgrade and how many cards to transform in the vanilla fields
/// </summary>
public override SerializableReward ToSerializable()
{
return new SerializableReward()
{
RewardType = CardTransform,
GoldAmount = Amount,
WasGoldStolenBack = Upgrade
};
}

/// <summary>
/// Recreates the reward from the saved <see cref="SerializableReward"/>
/// </summary>
/// <param name="save">The <see cref="SerializableReward"/> that was created and saved from
/// <see cref="ToSerializable"/></param>
/// <param name="player">The <see cref="Player"/> the reward belongs to</param>
public CardTransformReward CreateFromSerializable(SerializableReward save, Player player)
{
return new CardTransformReward(player) {
// hijacking the gold amounts as a temp hack before worrying about extending the serialized values
Amount = save.GoldAmount,
Upgrade = save.WasGoldStolenBack
};
}

/// <inheritdoc/>
public override SerializableCustomReward<CustomReward> SerializeMethod => CreateFromSerializable;

/// <inheritdoc/>
public override void MarkContentAsSeen() { }

/// <inheritdoc />
public override Task Populate() { return Task.CompletedTask; }

/// <inheritdoc/>
protected override async Task<bool> OnSelect()
{
BaseLibMain.Logger.Info("Obtained card transformation from reward");
return await RunManager.Instance.RewardSynchronizer.DoLocalCardTransform(Amount, true);
}
}
78 changes: 78 additions & 0 deletions Common/Rewards/CardTransformRewardMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using BaseLib.Abstracts;
using BaseLib.Patches.Content;
using MegaCrit.Sts2.Core.Combat;
using MegaCrit.Sts2.Core.Entities.Players;
using MegaCrit.Sts2.Core.Helpers;
using MegaCrit.Sts2.Core.Logging;
using MegaCrit.Sts2.Core.Multiplayer.Game;
using MegaCrit.Sts2.Core.Multiplayer.Serialization;
using MegaCrit.Sts2.Core.Runs;

namespace BaseLib.Common.Rewards;

/// <summary>
/// Message for transforming a card from a new reward type
/// </summary>
public sealed class ZZ_CardTransformRewardMessage : CustomRewardMessage
{
internal void HandleCardTransformedMessage(ZZ_CardTransformRewardMessage message, ulong senderId)
{
BaseLibMain.Logger.Debug($"Handling message {message}");
var rs = RunManager.Instance.RewardSynchronizer;
if (CombatManager.Instance.IsInProgress)
{
rs.BufferCustomRewardMessage(message, senderId);
BaseLibMain.Logger.Debug($"Buffered card transform message for {rs.PlayerCollection()?.GetPlayer(senderId)}");
return;
}

Player? player = rs.PlayerCollection()?.GetPlayer(senderId);
if (player == rs.LocalPlayerRef())
{
throw new InvalidOperationException("CardTransformRewardMessage should not be sent to the player transforming the card");
}
TaskHelper.RunSafely(rs.DoCardTransform(player, message.Amount, message.Upgrade));
}

/// <inheritdoc/>
public override void Dispose(RunLocationTargetedMessageBuffer messageBuffer)
{
BaseLibMain.Logger.Debug($"Unregistering handler for {GetType()}");
messageBuffer.UnregisterMessageHandler<ZZ_CardTransformRewardMessage>(HandleCardTransformedMessage);
}

/// <inheritdoc/>
public override void Initialize(RunLocationTargetedMessageBuffer messageBuffer)
{
BaseLibMain.Logger.Debug($"Registering handler for {GetType()}");
messageBuffer.RegisterMessageHandler<ZZ_CardTransformRewardMessage>(HandleCardTransformedMessage);
}

/// <summary>
/// Whether to upgrade the card as well as transforming
/// </summary>
public required bool Upgrade;
/// <summary>
/// The amount of cards to select from
/// </summary>
public required int Amount;

/// <inheritdoc/>
public override LogLevel LogLevel => LogLevel.Debug;

/// <inheritdoc/>
public override void Deserialize(PacketReader reader)
{
Location = reader.Read<RunLocation>();
Amount = reader.ReadInt();
Upgrade = reader.ReadBool();
}

/// <inheritdoc/>
public override void Serialize(PacketWriter writer)
{
writer.Write(Location);
writer.WriteInt(Amount);
writer.WriteBool(Upgrade);
}
}