Implement too many changes to list
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
using KernelPanic.Combat;
|
||||
using KernelPanic.Data;
|
||||
|
||||
namespace KernelPanic.Run
|
||||
{
|
||||
public enum RepositoryOfferKind
|
||||
{
|
||||
NewCard,
|
||||
CardUpgrade,
|
||||
StatUpgrade
|
||||
}
|
||||
|
||||
public enum CardUpgradeKind
|
||||
{
|
||||
CostDown,
|
||||
MagnitudeUp,
|
||||
DrawRider
|
||||
}
|
||||
|
||||
public enum RunStatUpgradeKind
|
||||
{
|
||||
MaxCycles,
|
||||
MaxUptime,
|
||||
Heal,
|
||||
Ram
|
||||
}
|
||||
|
||||
public sealed class RepositoryOffer
|
||||
{
|
||||
private RepositoryOffer(
|
||||
RepositoryOfferKind kind,
|
||||
string commandName,
|
||||
string displayName,
|
||||
string description,
|
||||
int price)
|
||||
{
|
||||
Kind = kind;
|
||||
CommandName = commandName;
|
||||
DisplayName = displayName;
|
||||
Description = description;
|
||||
Price = price;
|
||||
}
|
||||
|
||||
public RepositoryOfferKind Kind { get; }
|
||||
public string CommandName { get; }
|
||||
public string DisplayName { get; }
|
||||
public string Description { get; }
|
||||
public int Price { get; }
|
||||
public CardDefinition CardDefinition { get; private set; }
|
||||
public CardInstance TargetCard { get; private set; }
|
||||
public CardUpgradeKind CardUpgradeKind { get; private set; }
|
||||
public RunStatUpgradeKind StatUpgradeKind { get; private set; }
|
||||
public bool Sold { get; private set; }
|
||||
|
||||
public static RepositoryOffer NewCard(CardDefinition card, int price)
|
||||
{
|
||||
string name = DisplayNameFor(card);
|
||||
RepositoryOffer offer = new(RepositoryOfferKind.NewCard, SafeCommandName(card?.Id, name), name, RulesTextFor(card), price)
|
||||
{
|
||||
CardDefinition = card
|
||||
};
|
||||
return offer;
|
||||
}
|
||||
|
||||
public static RepositoryOffer CardUpgrade(CardInstance target, CardUpgradeKind upgradeKind, int price)
|
||||
{
|
||||
string cardName = DisplayNameFor(target?.Definition);
|
||||
string description = UpgradeDescription(target, upgradeKind);
|
||||
RepositoryOffer offer = new(RepositoryOfferKind.CardUpgrade, SafeCommandName(target?.Definition?.Id, cardName), $"upgrade {cardName}", description, price)
|
||||
{
|
||||
TargetCard = target,
|
||||
CardUpgradeKind = upgradeKind
|
||||
};
|
||||
return offer;
|
||||
}
|
||||
|
||||
public static RepositoryOffer StatUpgrade(RunStatUpgradeKind upgradeKind, int price)
|
||||
{
|
||||
return new RepositoryOffer(RepositoryOfferKind.StatUpgrade, upgradeKind.ToString().ToLowerInvariant(), StatName(upgradeKind), StatDescription(upgradeKind), price)
|
||||
{
|
||||
StatUpgradeKind = upgradeKind
|
||||
};
|
||||
}
|
||||
|
||||
public void MarkSold()
|
||||
{
|
||||
Sold = true;
|
||||
}
|
||||
|
||||
private static string RulesTextFor(CardDefinition card)
|
||||
{
|
||||
if (card == null)
|
||||
{
|
||||
return "--";
|
||||
}
|
||||
|
||||
CardInstance preview = new(card);
|
||||
return CardEffectFactory.GetRulesText(preview);
|
||||
}
|
||||
|
||||
private static string UpgradeDescription(CardInstance target, CardUpgradeKind upgradeKind)
|
||||
{
|
||||
if (target?.Definition == null)
|
||||
{
|
||||
return "--";
|
||||
}
|
||||
|
||||
return upgradeKind switch
|
||||
{
|
||||
CardUpgradeKind.CostDown => $"cost {CombatManager.GetCardCost(target)} -> {UnityEngine.Mathf.Max(0, CombatManager.GetCardCost(target) - 1)}",
|
||||
CardUpgradeKind.MagnitudeUp => $"effect magnitude +{CombatTuning.UpgradeMagnitudeBonus}",
|
||||
CardUpgradeKind.DrawRider => "add rider: draw 1 after resolving",
|
||||
_ => "--"
|
||||
};
|
||||
}
|
||||
|
||||
private static string StatName(RunStatUpgradeKind upgradeKind)
|
||||
{
|
||||
return upgradeKind switch
|
||||
{
|
||||
RunStatUpgradeKind.MaxCycles => "+1 max cycles",
|
||||
RunStatUpgradeKind.MaxUptime => "+max uptime",
|
||||
RunStatUpgradeKind.Heal => "heal uptime",
|
||||
RunStatUpgradeKind.Ram => "+1 RAM",
|
||||
_ => upgradeKind.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
private static string StatDescription(RunStatUpgradeKind upgradeKind)
|
||||
{
|
||||
return upgradeKind switch
|
||||
{
|
||||
RunStatUpgradeKind.MaxCycles => $"+{CombatTuning.StatUpgradeMaxCycles} max cycles this run",
|
||||
RunStatUpgradeKind.MaxUptime => $"+{CombatTuning.StatUpgradeMaxUptime} max uptime this run",
|
||||
RunStatUpgradeKind.Heal => $"heal {CombatTuning.StatUpgradeHeal} uptime now",
|
||||
RunStatUpgradeKind.Ram => $"+{CombatTuning.StatUpgradeRam} RAM this run",
|
||||
_ => "--"
|
||||
};
|
||||
}
|
||||
|
||||
private static string DisplayNameFor(CardDefinition card)
|
||||
{
|
||||
if (card == null)
|
||||
{
|
||||
return "--";
|
||||
}
|
||||
|
||||
return string.IsNullOrWhiteSpace(card.DisplayName) ? card.Id : card.DisplayName;
|
||||
}
|
||||
|
||||
private static string SafeCommandName(string id, string fallback)
|
||||
{
|
||||
string value = string.IsNullOrWhiteSpace(id) ? fallback : id;
|
||||
return string.IsNullOrWhiteSpace(value) ? "package" : value.Replace(' ', '-');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using KernelPanic.Data;
|
||||
|
||||
@@ -11,7 +10,8 @@ namespace KernelPanic.Run
|
||||
{
|
||||
public IReadOnlyList<RewardChoice> GeneratePostWaveChoices(RunConfig runConfig, int waveNumber)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// TODO: Generate real post-wave rewards once card reward pools and upgrade rules exist.
|
||||
return new[] { new RewardChoice(RewardChoiceType.Skip, null) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,16 +10,23 @@ namespace KernelPanic.Run
|
||||
public sealed class RunConfig
|
||||
{
|
||||
public RunConfig(DistroDefinition distro, Language primaryLanguage, Language secondaryLanguage, IReadOnlyList<CardDefinition> startingDeck)
|
||||
: this(distro, primaryLanguage, secondaryLanguage, startingDeck, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public RunConfig(DistroDefinition distro, Language primaryLanguage, Language secondaryLanguage, IReadOnlyList<CardDefinition> startingDeck, int runSeed)
|
||||
{
|
||||
Distro = distro;
|
||||
PrimaryLanguage = primaryLanguage;
|
||||
SecondaryLanguage = secondaryLanguage;
|
||||
StartingDeck = startingDeck;
|
||||
RunSeed = runSeed;
|
||||
}
|
||||
|
||||
public DistroDefinition Distro { get; }
|
||||
public Language PrimaryLanguage { get; }
|
||||
public Language SecondaryLanguage { get; }
|
||||
public IReadOnlyList<CardDefinition> StartingDeck { get; }
|
||||
public int RunSeed { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using KernelPanic.Core;
|
||||
using KernelPanic.Data;
|
||||
|
||||
namespace KernelPanic.Run
|
||||
{
|
||||
/// <summary>
|
||||
/// Scene-transition handoff for a just-configured run. This is intentionally a plain static
|
||||
/// context instead of a ScriptableObject asset because the payload is transient runtime state,
|
||||
/// not reusable authored content.
|
||||
/// </summary>
|
||||
public static class RunContext
|
||||
{
|
||||
private static PendingRun pendingRun;
|
||||
|
||||
public static bool HasPendingRun => pendingRun != null;
|
||||
|
||||
public static void Set(DistroDefinition distro, IReadOnlyList<CardDefinition> equippedCards, Language primaryLanguage, Language secondaryLanguage)
|
||||
{
|
||||
pendingRun = new PendingRun(distro, equippedCards, primaryLanguage, secondaryLanguage, Environment.TickCount);
|
||||
}
|
||||
|
||||
public static bool TryCreateRunConfig(LanguageDeckDatabase languageDeckDatabase, out RunConfig config)
|
||||
{
|
||||
if (pendingRun == null || pendingRun.Distro == null)
|
||||
{
|
||||
config = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
config = pendingRun.CreateRunConfig(languageDeckDatabase);
|
||||
pendingRun = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
private sealed class PendingRun
|
||||
{
|
||||
private readonly DistroDefinition distro;
|
||||
private readonly List<CardDefinition> equippedCards = new();
|
||||
private readonly Language primaryLanguage;
|
||||
private readonly Language secondaryLanguage;
|
||||
private readonly int runSeed;
|
||||
|
||||
public PendingRun(DistroDefinition distro, IReadOnlyList<CardDefinition> cards, Language primaryLanguage, Language secondaryLanguage, int runSeed)
|
||||
{
|
||||
this.distro = distro;
|
||||
this.primaryLanguage = primaryLanguage;
|
||||
this.secondaryLanguage = secondaryLanguage;
|
||||
this.runSeed = runSeed;
|
||||
|
||||
if (cards == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cards.Count; i++)
|
||||
{
|
||||
if (cards[i] != null && !cards[i].IsRunOnly)
|
||||
{
|
||||
equippedCards.Add(cards[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DistroDefinition Distro => distro;
|
||||
|
||||
public RunConfig CreateRunConfig(LanguageDeckDatabase languageDeckDatabase)
|
||||
{
|
||||
List<CardDefinition> startingDeck = new(equippedCards);
|
||||
AddLanguageDeck(languageDeckDatabase, primaryLanguage, startingDeck);
|
||||
AddLanguageDeck(languageDeckDatabase, secondaryLanguage, startingDeck);
|
||||
return new RunConfig(distro, primaryLanguage, secondaryLanguage, startingDeck, runSeed);
|
||||
}
|
||||
|
||||
private static void AddLanguageDeck(LanguageDeckDatabase languageDeckDatabase, Language language, List<CardDefinition> target)
|
||||
{
|
||||
LanguageDeckDefinition deck = languageDeckDatabase == null ? null : languageDeckDatabase.FindByLanguage(language);
|
||||
if (deck == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int entryIndex = 0; entryIndex < deck.Entries.Count; entryIndex++)
|
||||
{
|
||||
LanguageDeckDefinition.LanguageDeckEntry entry = deck.Entries[entryIndex];
|
||||
for (int copy = 0; copy < entry.Count; copy++)
|
||||
{
|
||||
if (entry.Card != null && !entry.Card.IsRunOnly)
|
||||
{
|
||||
target.Add(entry.Card);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
using KernelPanic.Combat;
|
||||
using KernelPanic.Core;
|
||||
using KernelPanic.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KernelPanic.Run
|
||||
@@ -14,9 +18,30 @@ namespace KernelPanic.Run
|
||||
[SerializeField] private bool isRunActive;
|
||||
[SerializeField] private bool isPlayerDead;
|
||||
|
||||
private readonly List<CardInstance> runDeck = new();
|
||||
private readonly List<RepositoryOffer> repositoryOffers = new();
|
||||
private readonly HashSet<string> soldOfferKeys = new(StringComparer.OrdinalIgnoreCase);
|
||||
private int bits;
|
||||
private int rerollsThisVisit;
|
||||
private int maxUptimeBonus;
|
||||
private int maxCyclesBonus;
|
||||
private int ramBonus;
|
||||
private bool repositoryVisitActive;
|
||||
|
||||
public int CurrentWaveNumber => currentWaveNumber;
|
||||
public bool IsRunActive => isRunActive;
|
||||
public bool IsPlayerDead => isPlayerDead;
|
||||
public RunConfig CurrentConfig { get; private set; }
|
||||
public IReadOnlyList<CardInstance> RunDeck => runDeck;
|
||||
public IReadOnlyList<RepositoryOffer> RepositoryOffers => repositoryOffers;
|
||||
public bool RepositoryVisitActive => repositoryVisitActive;
|
||||
public int Bits => bits;
|
||||
public int RerollCost => CombatTuning.RerollBaseCost + (rerollsThisVisit * CombatTuning.RerollCostStep);
|
||||
public int MaxUptimeBonus => maxUptimeBonus;
|
||||
public int MaxCyclesBonus => maxCyclesBonus;
|
||||
public int RamBonus => ramBonus;
|
||||
|
||||
public event Action RepositoryChanged;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
@@ -32,25 +57,376 @@ namespace KernelPanic.Run
|
||||
|
||||
public void StartRun(RunConfig config)
|
||||
{
|
||||
CurrentConfig = config;
|
||||
isRunActive = true;
|
||||
isPlayerDead = false;
|
||||
currentWaveNumber = 1;
|
||||
bits = 0;
|
||||
rerollsThisVisit = 0;
|
||||
maxUptimeBonus = 0;
|
||||
maxCyclesBonus = 0;
|
||||
ramBonus = 0;
|
||||
InitializeRunDeck(config);
|
||||
StartCombat();
|
||||
}
|
||||
|
||||
public void StartCombat()
|
||||
{
|
||||
combatManager?.StartCombat();
|
||||
combatManager?.StartCombat(CurrentConfig);
|
||||
}
|
||||
|
||||
public void AddBits(int amount)
|
||||
{
|
||||
if (!isRunActive || amount <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bits += amount;
|
||||
RepositoryChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void GenerateRepositoryOffers(CardDatabase cardDatabase, LanguageDeckDatabase languageDeckDatabase)
|
||||
{
|
||||
repositoryOffers.Clear();
|
||||
rerollsThisVisit = 0;
|
||||
soldOfferKeys.Clear();
|
||||
FillRepositoryOffers(cardDatabase, languageDeckDatabase);
|
||||
repositoryVisitActive = true;
|
||||
RepositoryChanged?.Invoke();
|
||||
}
|
||||
|
||||
public bool RerollRepositoryOffers(CardDatabase cardDatabase, LanguageDeckDatabase languageDeckDatabase)
|
||||
{
|
||||
int cost = RerollCost;
|
||||
if (bits < cost)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bits -= cost;
|
||||
rerollsThisVisit++;
|
||||
repositoryOffers.Clear();
|
||||
FillRepositoryOffers(cardDatabase, languageDeckDatabase);
|
||||
repositoryVisitActive = true;
|
||||
RepositoryChanged?.Invoke();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool BuyOffer(RepositoryOffer offer, CombatantState playerState)
|
||||
{
|
||||
if (offer == null || offer.Sold || bits < offer.Price)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool applied = offer.Kind switch
|
||||
{
|
||||
RepositoryOfferKind.NewCard => AddCardToRunDeck(offer.CardDefinition),
|
||||
RepositoryOfferKind.CardUpgrade => ApplyCardUpgrade(offer.TargetCard, offer.CardUpgradeKind),
|
||||
RepositoryOfferKind.StatUpgrade => ApplyStatUpgrade(offer.StatUpgradeKind, playerState),
|
||||
_ => false
|
||||
};
|
||||
|
||||
if (!applied)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bits -= offer.Price;
|
||||
offer.MarkSold();
|
||||
soldOfferKeys.Add(OfferKey(offer));
|
||||
RepositoryChanged?.Invoke();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool RemoveCard(CardInstance card)
|
||||
{
|
||||
if (card == null || bits < CombatTuning.RemoveCardCost || runDeck.Count <= 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!runDeck.Remove(card))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bits -= CombatTuning.RemoveCardCost;
|
||||
RepositoryChanged?.Invoke();
|
||||
return true;
|
||||
}
|
||||
|
||||
public int EffectiveMaxUptime()
|
||||
{
|
||||
return Mathf.Max(1, (CurrentConfig?.Distro?.BaseUptime ?? 1) + maxUptimeBonus);
|
||||
}
|
||||
|
||||
public int EffectiveRam()
|
||||
{
|
||||
return Mathf.Max(1, (CurrentConfig?.Distro?.BaseRam ?? 1) + ramBonus);
|
||||
}
|
||||
|
||||
public int EffectiveMaxCycles()
|
||||
{
|
||||
return Mathf.Max(1, (CurrentConfig?.Distro?.BaseCyclesPerTurn ?? 1) + maxCyclesBonus);
|
||||
}
|
||||
|
||||
private void HandleWaveCleared(WaveClearedEvent payload)
|
||||
{
|
||||
currentWaveNumber = Mathf.Max(currentWaveNumber + 1, payload.WaveNumber + 1);
|
||||
repositoryOffers.Clear();
|
||||
rerollsThisVisit = 0;
|
||||
soldOfferKeys.Clear();
|
||||
repositoryVisitActive = false;
|
||||
GameEvents.RaiseWaveAdvanced(new WaveAdvancedEvent(currentWaveNumber));
|
||||
}
|
||||
|
||||
private void HandleRunEnded(RunEndedEvent payload)
|
||||
{
|
||||
isRunActive = false;
|
||||
isPlayerDead = payload.PlayerDied;
|
||||
bits = 0;
|
||||
repositoryOffers.Clear();
|
||||
repositoryVisitActive = false;
|
||||
runDeck.Clear();
|
||||
maxUptimeBonus = 0;
|
||||
maxCyclesBonus = 0;
|
||||
ramBonus = 0;
|
||||
RepositoryChanged?.Invoke();
|
||||
}
|
||||
|
||||
private void InitializeRunDeck(RunConfig config)
|
||||
{
|
||||
runDeck.Clear();
|
||||
if (config?.StartingDeck == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < config.StartingDeck.Count; i++)
|
||||
{
|
||||
CardDefinition definition = config.StartingDeck[i];
|
||||
if (definition != null && !definition.IsRunOnly)
|
||||
{
|
||||
runDeck.Add(new CardInstance(definition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FillRepositoryOffers(CardDatabase cardDatabase, LanguageDeckDatabase languageDeckDatabase)
|
||||
{
|
||||
int guard = 0;
|
||||
while (repositoryOffers.Count < CombatTuning.ShopSize && guard < 80)
|
||||
{
|
||||
guard++;
|
||||
RepositoryOffer offer = CreateRandomOffer(cardDatabase, languageDeckDatabase);
|
||||
if (offer == null || soldOfferKeys.Contains(OfferKey(offer)) || repositoryOffers.Any(existing => IsDuplicateOffer(existing, offer)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
repositoryOffers.Add(offer);
|
||||
}
|
||||
}
|
||||
|
||||
private RepositoryOffer CreateRandomOffer(CardDatabase cardDatabase, LanguageDeckDatabase languageDeckDatabase)
|
||||
{
|
||||
int roll = UnityEngine.Random.Range(0, 100);
|
||||
if (roll < 45)
|
||||
{
|
||||
return CreateCardOffer(cardDatabase, languageDeckDatabase);
|
||||
}
|
||||
|
||||
if (roll < 75)
|
||||
{
|
||||
return CreateUpgradeOffer();
|
||||
}
|
||||
|
||||
return CreateStatOffer();
|
||||
}
|
||||
|
||||
private RepositoryOffer CreateCardOffer(CardDatabase cardDatabase, LanguageDeckDatabase languageDeckDatabase)
|
||||
{
|
||||
List<CardDefinition> pool = BuildCardOfferPool(cardDatabase, languageDeckDatabase);
|
||||
if (pool.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
CardDefinition selected = pool[UnityEngine.Random.Range(0, pool.Count)];
|
||||
return RepositoryOffer.NewCard(selected, selected.IsRunOnly ? CombatTuning.NewCardOfferCost + 1 : CombatTuning.NewCardOfferCost);
|
||||
}
|
||||
|
||||
private RepositoryOffer CreateUpgradeOffer()
|
||||
{
|
||||
List<CardInstance> candidates = runDeck.Where(card => card != null && card.CanReceiveRepositoryUpgrade).ToList();
|
||||
if (candidates.Count == 0)
|
||||
{
|
||||
return CreateStatOffer();
|
||||
}
|
||||
|
||||
CardInstance target = candidates[UnityEngine.Random.Range(0, candidates.Count)];
|
||||
CardUpgradeKind kind = (CardUpgradeKind)UnityEngine.Random.Range(0, 3);
|
||||
if (kind == CardUpgradeKind.CostDown && CombatManager.GetCardCost(target) <= 0)
|
||||
{
|
||||
kind = CardUpgradeKind.MagnitudeUp;
|
||||
}
|
||||
|
||||
return RepositoryOffer.CardUpgrade(target, kind, CombatTuning.UpgradeOfferCost);
|
||||
}
|
||||
|
||||
private static RepositoryOffer CreateStatOffer()
|
||||
{
|
||||
RunStatUpgradeKind kind = (RunStatUpgradeKind)UnityEngine.Random.Range(0, 4);
|
||||
return RepositoryOffer.StatUpgrade(kind, CombatTuning.StatUpgradeCost);
|
||||
}
|
||||
|
||||
private List<CardDefinition> BuildCardOfferPool(CardDatabase cardDatabase, LanguageDeckDatabase languageDeckDatabase)
|
||||
{
|
||||
List<CardDefinition> pool = new();
|
||||
AddLanguageCards(languageDeckDatabase, CurrentConfig?.PrimaryLanguage ?? Language.Python, pool, 3);
|
||||
AddLanguageCards(languageDeckDatabase, CurrentConfig?.SecondaryLanguage ?? Language.JavaScript, pool, 3);
|
||||
|
||||
if (cardDatabase != null)
|
||||
{
|
||||
for (int i = 0; i < cardDatabase.AllCards.Count; i++)
|
||||
{
|
||||
CardDefinition card = cardDatabase.AllCards[i];
|
||||
if (card == null || card.IsToken)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (card.IsRunOnly || card.Language == CurrentConfig.PrimaryLanguage || card.Language == CurrentConfig.SecondaryLanguage)
|
||||
{
|
||||
pool.Add(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
private static void AddLanguageCards(LanguageDeckDatabase languageDeckDatabase, Language language, List<CardDefinition> pool, int weight)
|
||||
{
|
||||
LanguageDeckDefinition deck = languageDeckDatabase == null ? null : languageDeckDatabase.FindByLanguage(language);
|
||||
if (deck == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < deck.Entries.Count; i++)
|
||||
{
|
||||
CardDefinition card = deck.Entries[i].Card;
|
||||
if (card == null || card.IsToken || card.IsRunOnly)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int copy = 0; copy < Mathf.Max(1, weight); copy++)
|
||||
{
|
||||
pool.Add(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsDuplicateOffer(RepositoryOffer left, RepositoryOffer right)
|
||||
{
|
||||
if (left.Kind != right.Kind)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return left.Kind switch
|
||||
{
|
||||
RepositoryOfferKind.NewCard => left.CardDefinition == right.CardDefinition,
|
||||
RepositoryOfferKind.CardUpgrade => left.TargetCard == right.TargetCard && left.CardUpgradeKind == right.CardUpgradeKind,
|
||||
RepositoryOfferKind.StatUpgrade => left.StatUpgradeKind == right.StatUpgradeKind,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
private static string OfferKey(RepositoryOffer offer)
|
||||
{
|
||||
if (offer == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return offer.Kind switch
|
||||
{
|
||||
RepositoryOfferKind.NewCard => $"card:{offer.CardDefinition?.Id}",
|
||||
RepositoryOfferKind.CardUpgrade => $"upgrade:{offer.TargetCard?.Definition?.Id}:{offer.TargetCard?.GetHashCode()}:{offer.CardUpgradeKind}",
|
||||
RepositoryOfferKind.StatUpgrade => $"stat:{offer.StatUpgradeKind}",
|
||||
_ => offer.DisplayName
|
||||
};
|
||||
}
|
||||
|
||||
private bool AddCardToRunDeck(CardDefinition card)
|
||||
{
|
||||
if (card == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
runDeck.Add(new CardInstance(card));
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool ApplyCardUpgrade(CardInstance card, CardUpgradeKind kind)
|
||||
{
|
||||
if (card == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return kind switch
|
||||
{
|
||||
CardUpgradeKind.CostDown => card.ApplyCostUpgrade(-1),
|
||||
CardUpgradeKind.MagnitudeUp => card.ApplyMagnitudeUpgrade(CombatTuning.UpgradeMagnitudeBonus),
|
||||
CardUpgradeKind.DrawRider => card.ApplyDrawRider(1),
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
private bool ApplyStatUpgrade(RunStatUpgradeKind kind, CombatantState playerState)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case RunStatUpgradeKind.MaxCycles:
|
||||
maxCyclesBonus += CombatTuning.StatUpgradeMaxCycles;
|
||||
if (playerState != null)
|
||||
{
|
||||
playerState.MaxCycles += CombatTuning.StatUpgradeMaxCycles;
|
||||
playerState.Cycles += CombatTuning.StatUpgradeMaxCycles;
|
||||
}
|
||||
return true;
|
||||
case RunStatUpgradeKind.MaxUptime:
|
||||
maxUptimeBonus += CombatTuning.StatUpgradeMaxUptime;
|
||||
if (playerState != null)
|
||||
{
|
||||
playerState.MaxUptime += CombatTuning.StatUpgradeMaxUptime;
|
||||
}
|
||||
return true;
|
||||
case RunStatUpgradeKind.Heal:
|
||||
if (playerState == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
playerState.CurrentUptime = Mathf.Min(playerState.MaxUptime, playerState.CurrentUptime + CombatTuning.StatUpgradeHeal);
|
||||
return true;
|
||||
case RunStatUpgradeKind.Ram:
|
||||
ramBonus += CombatTuning.StatUpgradeRam;
|
||||
if (playerState != null)
|
||||
{
|
||||
playerState.Ram += CombatTuning.StatUpgradeRam;
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user