Skip to content

Commit

Permalink
Add Degree Indicator
Browse files Browse the repository at this point in the history
  • Loading branch information
doombubbles committed Oct 14, 2023
1 parent b72659f commit 9063259
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 43 deletions.
4 changes: 3 additions & 1 deletion LATEST.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
- Fixed Paragon costs getting included for Temple Sacrifice UI
- Updated degree calculations for v39 changes
- Added Degree Indicator to the paragon investment slider
- Added mod setting to control the default Slider Contribution Penalty of 5%
4 changes: 2 additions & 2 deletions ModHelperData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

public static class ModHelperData
{
public const string WorksOnVersion = "38.1";
public const string Version = "2.3.4";
public const string WorksOnVersion = "39.0";
public const string Version = "2.4.0";
public const string Name = "Sacrifice Helper";

public const string Description =
Expand Down
122 changes: 90 additions & 32 deletions SacrificeHelperMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@
using Il2CppAssets.Scripts.Simulation.Towers.Behaviors;
using Il2CppAssets.Scripts.Unity.UI_New.InGame.TowerSelectionMenu;
using BTD_Mod_Helper;
using BTD_Mod_Helper.Api;
using BTD_Mod_Helper.Api.Components;
using BTD_Mod_Helper.Api.Enums;
using BTD_Mod_Helper.Api.ModOptions;
using BTD_Mod_Helper.Extensions;
using HarmonyLib;
using Il2Cpp;
using Il2CppAssets.Scripts.Unity.UI_New.InGame;
using Il2CppAssets.Scripts.Unity.UI_New.InGame.TowerSelectionMenu.TowerSelectionMenuThemes;
using Il2CppAssets.Scripts.Unity.UI_New.Popups;
using Il2CppAssets.Scripts.Unity.UI_New.Utils;
using MelonLoader;
using SacrificeHelper;
using UnityEngine;

[assembly: MelonInfo(typeof(SacrificeHelperMod), ModHelperData.Name, ModHelperData.Version, ModHelperData.RepoOwner)]
[assembly: MelonGame("Ninja Kiwi", "BloonsTD6")]
Expand All @@ -20,61 +23,76 @@ namespace SacrificeHelper;

public class SacrificeHelperMod : BloonsTD6Mod
{
public static readonly ModSettingDouble SliderContributionPenalty = new(0.05f)
{
description = "The popup added in BTD6 v39 comes with a default 5% penalty to manually invested cash.\n" +
"Setting this to 0 would stop it, or negative would counteract it.",
stepSize = .01f,
min = -.99,
max = 1,
icon = VanillaSprites.UpgradeContainerParagonUnlocked
};

public static readonly ModSettingCategory ParagonPowerMaximums = new("Paragon Power Maximums");

public static readonly ModSettingInt MaxFromPops = new(90000)
public static readonly ModSettingInt MaxPowerFromPops = new(90000)
{
displayName = "Max Paragon Power From Pops\n(-1 for unlimited)",
min = -1,
max = 200000,
icon = VanillaSprites.PopIcon,
category = ParagonPowerMaximums
category = ParagonPowerMaximums,
};

public static readonly ModSettingInt MaxFromCash = new(10000)
public static readonly ModSettingInt MaxPowerFromCash = new(60000)
{
displayName = "Max Paragon Power From Cash\n(-1 for unlimited)",
min = -1,
max = 200000,
icon = VanillaSprites.CoinIcon,
category = ParagonPowerMaximums
};

public static readonly ModSettingInt MaxFromNonTier5s = new(10000)
public static readonly ModSettingInt MaxPowerFromNonTier5s = new(10000)
{
displayName = "Max Paragon Power From Non Tier 5s\n(-1 for unlimited)",
min = -1,
max = 200000,
icon = VanillaSprites.UpgradeContainerGrey,
modifyOption = option => option.Icon.AddText(new Info("Text", InfoPreset.FillParent), "<5", 100),
category = ParagonPowerMaximums
};

public static readonly ModSettingInt MaxFromTier5s = new(90000)
public static readonly ModSettingInt MaxPowerFromTier5s = new(50000)
{
displayName = "Max Paragon Power From Tier 5s\n(-1 for unlimited)",
min = -1,
max = 200000,
icon = VanillaSprites.UpgradeContainerTier5,
modifyOption = option => option.Icon.AddText(new Info("Text", InfoPreset.FillParent), "5", 100),
category = ParagonPowerMaximums
};

public static readonly ModSettingCategory ParagonPowerWeights = new("Paragon Power Weights");

private static readonly ModSettingInt PopsPerPoint = new(180)
private static readonly ModSettingInt PopsScaleFactor = new(180)
{
displayName = "Pops per Point of Paragon Power",
min = 1,
icon = VanillaSprites.PopIcon,
category = ParagonPowerWeights
};

private static readonly ModSettingInt CashPerPoint = new(25)
private static readonly ModSettingInt CashScaleFactor = new(20000)
{
displayName = "Cash per Point of Paragon Power",
displayName = "Paragon Power Scale Factor for Cash",
min = 1,
icon = VanillaSprites.CoinIcon,
category = ParagonPowerWeights
category = ParagonPowerWeights,
description = "As of v39, the Paragon Upgrade Price is divided by this to get the final value"
};

private static readonly ModSettingInt NonTier5sScaleFactor = new(100)
private static readonly ModSettingInt NonTier5ScaleFactor = new(100)
{
displayName = "Paragon Power Scale Factor for Non Tier 5s",
min = 0,
Expand All @@ -83,7 +101,7 @@ public class SacrificeHelperMod : BloonsTD6Mod
category = ParagonPowerWeights
};

private static readonly ModSettingInt Tier5sScaleFactor = new(10000)
private static readonly ModSettingInt Tier5ScaleFactor = new(6000)
{
displayName = "Paragon Power Scale Factor for Tier 5s",
min = 0,
Expand Down Expand Up @@ -120,35 +138,39 @@ public class SacrificeHelperMod : BloonsTD6Mod

public override void OnNewGameModel(GameModel result)
{
result.paragonDegreeDataModel.maxPowerFromPops = MaxFromPops;
if (result.paragonDegreeDataModel.maxPowerFromPops < 0)
var degreeData = result.paragonDegreeDataModel;

degreeData.maxPowerFromPops = MaxPowerFromPops;
if (degreeData.maxPowerFromPops < 0)
{
result.paragonDegreeDataModel.maxPowerFromPops = int.MaxValue;
degreeData.maxPowerFromPops = degreeData.MaxInvestment;
}

result.paragonDegreeDataModel.maxPowerFromMoneySpent = MaxFromCash;
if (result.paragonDegreeDataModel.maxPowerFromMoneySpent < 0)
degreeData.maxPowerFromMoneySpent = MaxPowerFromCash;
if (degreeData.maxPowerFromMoneySpent < 0)
{
result.paragonDegreeDataModel.maxPowerFromMoneySpent = int.MaxValue;
degreeData.maxPowerFromMoneySpent = degreeData.MaxInvestment;
}

result.paragonDegreeDataModel.maxPowerFromNonTier5Count = MaxFromNonTier5s;
if (result.paragonDegreeDataModel.maxPowerFromNonTier5Count < 0)
degreeData.maxPowerFromNonTier5Count = MaxPowerFromNonTier5s;
if (degreeData.maxPowerFromNonTier5Count < 0)
{
result.paragonDegreeDataModel.maxPowerFromNonTier5Count = int.MaxValue;
degreeData.maxPowerFromNonTier5Count = degreeData.MaxInvestment;
}

result.paragonDegreeDataModel.maxPowerFromTier5Count = MaxFromTier5s;
if (result.paragonDegreeDataModel.maxPowerFromTier5Count < 0)
degreeData.maxPowerFromTier5Count = MaxPowerFromTier5s;
if (degreeData.maxPowerFromTier5Count < 0)
{
result.paragonDegreeDataModel.maxPowerFromTier5Count = int.MaxValue;
degreeData.maxPowerFromTier5Count = degreeData.MaxInvestment;
}

result.paragonDegreeDataModel.popsOverX = PopsPerPoint;
result.paragonDegreeDataModel.moneySpentOverX = CashPerPoint;
result.paragonDegreeDataModel.nonTier5TowersMultByX = NonTier5sScaleFactor;
result.paragonDegreeDataModel.tier5TowersMultByX = Tier5sScaleFactor;

degreeData.popsOverX = PopsScaleFactor;
degreeData.moneySpentOverX = CashScaleFactor;
degreeData.nonTier5TowersMultByX = NonTier5ScaleFactor;
degreeData.tier5TowersMultByX = Tier5ScaleFactor;

degreeData.paidContributionPenalty = SliderContributionPenalty;

templeSacrificesOff = false;
}

Expand All @@ -167,7 +189,7 @@ private static void Postfix(TowerSelectionMenu __instance)
{
var themeManager = __instance.themeManager;
var currentTheme = themeManager.CurrentTheme;

if (currentTheme == null) return;

var ui = currentTheme.GetComponent<SacrificeHelperUI>();
Expand All @@ -177,8 +199,8 @@ private static void Postfix(TowerSelectionMenu __instance)
}
}
}


[HarmonyPatch(typeof(MenuThemeManager), nameof(MenuThemeManager.SetTheme))]
internal static class MenuThemeManager_SetTheme
{
Expand All @@ -196,4 +218,40 @@ private static void Postfix(MenuThemeManager __instance, BaseTSMTheme newTheme)
}
}
}

[HarmonyPatch(typeof(ParagonConfirmationPopup), nameof(ParagonConfirmationPopup.UpdateCurrentInvestment))]
internal static class ParagonConfirmationPopup_UpdateCurrentInvestment
{
[HarmonyPostfix]
private static void Postfix(ParagonConfirmationPopup __instance, float current)
{
var tower = TowerSelectionMenu.instance.selectedTower;

var degree = Utils.GetParagonDegree(tower, out _, current);

var text = __instance.transform.GetComponentFromChildrenByName<NK_TextMeshProUGUI>("DegreeText");
text.SetText(degree.ToString());
text.color = degree >= 100 ? Color.green : Color.white;
}
}

[HarmonyPatch(typeof(ParagonConfirmationPopup), nameof(ParagonConfirmationPopup.Init),
typeof(Il2CppSystem.Action<double>), typeof(Il2CppSystem.Action), typeof(int), typeof(int), typeof(int),
typeof(PopupScreen.BackGround), typeof(Popup.TransitionAnim))]
internal static class ParagonConfirmationPopup_Init
{
[HarmonyPostfix]
private static void Postfix(ParagonConfirmationPopup __instance)
{
var tower = TowerSelectionMenu.instance.selectedTower;
var degree = Utils.GetParagonDegree(tower, out _);

var mainObject = __instance.animator.gameObject;

var indicator = ModHelperImage.Create(new Info("DegreeIndicator", 0, -450, 250, 250),
VanillaSprites.UpgradeContainerParagon);
mainObject.AddModHelperComponent(indicator);
indicator.AddText(new Info("DegreeText", InfoPreset.FillParent), degree.ToString(), 100f);
}
}
}
22 changes: 14 additions & 8 deletions Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ private static float GetTowerSetWorth(string towerSet, Tower tower) => InGame.in
activeAt = -1
};

public static int GetParagonDegree(TowerToSimulation tower, out ParagonTower.InvestmentInfo investmentInfo)
public static int GetParagonDegree(TowerToSimulation tower, out ParagonTower.InvestmentInfo investmentInfo, float bonus = 0)
{
var degreeDataModel = InGame.instance.GetGameModel().paragonDegreeDataModel;
var degree = 0;
Expand All @@ -124,17 +124,23 @@ public static int GetParagonDegree(TowerToSimulation tower, out ParagonTower.Inv

var paragonCost = tower.GetUpgradeCost(0, 6, -1, true);

// TODO seems like a bug with BTD6, should the paragon upgrade cost really be included ???
tower.tower.worth += paragonCost;

var paragonTower = FakeParagonTower(tower.tower);

paragonTower.upgradeCost = paragonCost;

var bonusInvestment = new ParagonTower.InvestmentInfo
{
powerFromMoneySpent = (bonus * degreeDataModel.moneySpentOverX) /
((1 + degreeDataModel.paidContributionPenalty) * paragonCost)
};

investmentInfo = InGame.instance.GetAllTowerToSim()
.Where(tts => tts.Def.baseId == tower.Def.baseId || tts.Def.GetChild<ParagonSacrificeBonusModel>() != null)
.OrderBy(tts => paragonTower.GetTowerInvestment(tts.tower, 3).totalInvestment)
.Where(tts =>
tts.Def.baseId == tower.Def.baseId || tts.Def.GetChild<ParagonSacrificeBonusModel>() != null)
.OrderBy(tts => paragonTower.GetTowerInvestment(tts.tower).totalInvestment)
.Select(tts => paragonTower.GetTowerInvestment(tts.tower, tts.Def.tier >= 5 ? index++ : 3))
.Aggregate(paragonTower.CombineInvestments);
.Aggregate(bonusInvestment, paragonTower.CombineInvestments);

tower.tower.worth -= paragonCost;

var requirements = degreeDataModel.powerDegreeRequirements;

Expand Down

0 comments on commit 9063259

Please sign in to comment.