hotfix: weak reference to CalamityMod
for overriding the Plantera boss bag
This commit is contained in:
parent
cf7416010d
commit
a0c69dc497
2 changed files with 16 additions and 160 deletions
|
@ -5,7 +5,6 @@ using Terraria.ID;
|
||||||
using Terraria.ModLoader;
|
using Terraria.ModLoader;
|
||||||
using Terraria.GameContent.ItemDropRules;
|
using Terraria.GameContent.ItemDropRules;
|
||||||
using Continuity.Content.Items;
|
using Continuity.Content.Items;
|
||||||
using continuity.Utilities;
|
|
||||||
|
|
||||||
namespace Continuity.Content
|
namespace Continuity.Content
|
||||||
{
|
{
|
||||||
|
@ -22,6 +21,7 @@ namespace Continuity.Content
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JITWhenModsEnabled("CalamityMod")]
|
||||||
public class PlanteraBossBag : GlobalItem
|
public class PlanteraBossBag : GlobalItem
|
||||||
{
|
{
|
||||||
public override void ModifyItemLoot(Item item, ItemLoot itemLoot)
|
public override void ModifyItemLoot(Item item, ItemLoot itemLoot)
|
||||||
|
@ -29,31 +29,34 @@ namespace Continuity.Content
|
||||||
if (item.type == ItemID.PlanteraBossBag)
|
if (item.type == ItemID.PlanteraBossBag)
|
||||||
{
|
{
|
||||||
itemLoot.Add(ItemDropRule.Common(ModContent.ItemType<PalishadeTissue>(), 1, 25, 35));
|
itemLoot.Add(ItemDropRule.Common(ModContent.ItemType<PalishadeTissue>(), 1, 25, 35));
|
||||||
short[] toRemove = {
|
|
||||||
ItemID.TheAxe,
|
|
||||||
ItemID.PygmyStaff,
|
|
||||||
ItemID.Seedling,
|
|
||||||
ItemID.ThornHook,
|
|
||||||
};
|
|
||||||
foreach (var i in toRemove)
|
|
||||||
{
|
|
||||||
itemLoot.RemoveWhere(rule => rule is CommonDropNotScalingWithLuck drop
|
|
||||||
&& drop.itemId == i);
|
|
||||||
}
|
|
||||||
itemLoot.RemoveWhere(rule => rule is CommonDrop drop
|
itemLoot.RemoveWhere(rule => rule is CommonDrop drop
|
||||||
&& drop.itemId == ItemID.TempleKey);
|
&& drop.itemId == ItemID.TempleKey);
|
||||||
|
|
||||||
foreach (var rule in itemLoot.Get())
|
foreach (var rule in itemLoot.Get())
|
||||||
{
|
{
|
||||||
itemLoot.RemoveWhere(rule => rule is OneFromRulesRule);
|
itemLoot.RemoveWhere(rule => rule is OneFromRulesRule);
|
||||||
|
|
||||||
if (ModLoader.HasMod("CalamityMod"))
|
if (ModLoader.HasMod("CalamityMod"))
|
||||||
{
|
{
|
||||||
itemLoot.RemoveWhere(rule => rule is CalamityDropHelper.AllOptionsAtOnceWithPityDropRule);
|
itemLoot.RemoveWhere(rule => rule is CalamityMod.DropHelper.AllOptionsAtOnceWithPityDropRule);
|
||||||
|
|
||||||
if (ModLoader.TryGetMod("CalamityMod", out Mod calamityMod) && calamityMod.TryFind<ModItem>("BlossomFlux", out ModItem BlossomFlux)) {
|
if (ModLoader.TryGetMod("CalamityMod", out Mod calamityMod) && calamityMod.TryFind<ModItem>("BlossomFlux", out ModItem BlossomFlux)) {
|
||||||
itemLoot.RemoveWhere(rule => rule is CommonDrop drop
|
itemLoot.RemoveWhere(rule => rule is CommonDrop drop
|
||||||
&& drop.itemId == BlossomFlux.Type);
|
&& drop.itemId == BlossomFlux.Type);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
short[] toRemove = {
|
||||||
|
ItemID.TheAxe,
|
||||||
|
ItemID.PygmyStaff,
|
||||||
|
ItemID.Seedling,
|
||||||
|
ItemID.ThornHook,
|
||||||
|
};
|
||||||
|
foreach (var i in toRemove)
|
||||||
|
{
|
||||||
|
itemLoot.RemoveWhere(rule => rule is CommonDropNotScalingWithLuck drop
|
||||||
|
&& drop.itemId == i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,147 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
|
||||||
using Terraria.GameContent.ItemDropRules;
|
|
||||||
using Terraria.Utilities;
|
|
||||||
using Terraria;
|
|
||||||
|
|
||||||
// Repurposed from https://github.com/CalamityTeam/CalamityModPublic/blob/1.4.4/Utilities/DropHelper.cs
|
|
||||||
namespace continuity.Utilities
|
|
||||||
{
|
|
||||||
internal class CalamityDropHelper
|
|
||||||
{
|
|
||||||
public struct Fraction
|
|
||||||
{
|
|
||||||
internal readonly int numerator;
|
|
||||||
internal readonly int denominator;
|
|
||||||
|
|
||||||
public Fraction(int n, int d)
|
|
||||||
{
|
|
||||||
numerator = n < 0 ? 0 : n;
|
|
||||||
denominator = d <= 0 ? 1 : d;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static implicit operator float(Fraction f) => f.numerator / (float)f.denominator;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public struct WeightedItemStack
|
|
||||||
{
|
|
||||||
public const float DefaultWeight = 1f;
|
|
||||||
public const float MinisiculeWeight = 1E-6f;
|
|
||||||
|
|
||||||
internal int itemID;
|
|
||||||
internal float weight;
|
|
||||||
internal int minQuantity;
|
|
||||||
internal int maxQuantity;
|
|
||||||
|
|
||||||
internal WeightedItemStack(int id, float w)
|
|
||||||
{
|
|
||||||
itemID = id;
|
|
||||||
weight = w;
|
|
||||||
minQuantity = 1;
|
|
||||||
maxQuantity = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal WeightedItemStack(int id, float w, int quantity)
|
|
||||||
{
|
|
||||||
itemID = id;
|
|
||||||
weight = w;
|
|
||||||
minQuantity = quantity;
|
|
||||||
maxQuantity = quantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal WeightedItemStack(int id, float w, int min, int max)
|
|
||||||
{
|
|
||||||
itemID = id;
|
|
||||||
weight = w;
|
|
||||||
minQuantity = min;
|
|
||||||
maxQuantity = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal int ChooseQuantity(UnifiedRandom rng) => rng.Next(minQuantity, maxQuantity + 1);
|
|
||||||
|
|
||||||
// Allow for implicitly casting integer item IDs into weighted item stacks.
|
|
||||||
// Stack size is assumed to be 1. Weight is assumed to be default.
|
|
||||||
public static implicit operator WeightedItemStack(int id)
|
|
||||||
{
|
|
||||||
return new WeightedItemStack(id, DefaultWeight, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AllOptionsAtOnceWithPityDropRule : IItemDropRule
|
|
||||||
{
|
|
||||||
public WeightedItemStack[] stacks;
|
|
||||||
public Fraction dropRate;
|
|
||||||
public bool usesLuck;
|
|
||||||
public List<IItemDropRuleChainAttempt> ChainedRules { get; set; }
|
|
||||||
|
|
||||||
public AllOptionsAtOnceWithPityDropRule(Fraction dropRate, bool luck, params WeightedItemStack[] stacks)
|
|
||||||
{
|
|
||||||
this.dropRate = dropRate;
|
|
||||||
this.stacks = stacks;
|
|
||||||
usesLuck = luck;
|
|
||||||
ChainedRules = new List<IItemDropRuleChainAttempt>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public AllOptionsAtOnceWithPityDropRule(Fraction dropRate, bool luck, params int[] itemIDs)
|
|
||||||
{
|
|
||||||
this.dropRate = dropRate;
|
|
||||||
stacks = new WeightedItemStack[itemIDs.Length];
|
|
||||||
for (int i = 0; i < stacks.Length; ++i)
|
|
||||||
stacks[i] = itemIDs[i]; // implicit conversion operator
|
|
||||||
usesLuck = luck;
|
|
||||||
ChainedRules = new List<IItemDropRuleChainAttempt>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanDrop(DropAttemptInfo info) => true;
|
|
||||||
|
|
||||||
public ItemDropAttemptResult TryDroppingItem(DropAttemptInfo info)
|
|
||||||
{
|
|
||||||
bool droppedAnything = false;
|
|
||||||
|
|
||||||
// Roll for each drop individually.
|
|
||||||
foreach (WeightedItemStack stack in stacks)
|
|
||||||
{
|
|
||||||
bool rngRoll = usesLuck ? info.player.RollLuck(dropRate.denominator) < dropRate.numerator : info.rng.NextFloat() < dropRate;
|
|
||||||
droppedAnything |= rngRoll;
|
|
||||||
if (rngRoll)
|
|
||||||
CommonCode.DropItem(info, stack.itemID, stack.ChooseQuantity(info.rng));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If everything fails to drop, force drop one item from the set.
|
|
||||||
if (!droppedAnything)
|
|
||||||
{
|
|
||||||
WeightedItemStack stack = info.rng.NextFromList(stacks);
|
|
||||||
CommonCode.DropItem(info, stack.itemID, stack.ChooseQuantity(info.rng));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calamity style drops cannot fail. You will always get at least one item.
|
|
||||||
ItemDropAttemptResult result = default;
|
|
||||||
result.State = ItemDropAttemptResultState.Success;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReportDroprates(List<DropRateInfo> drops, DropRateInfoChainFeed ratesInfo)
|
|
||||||
{
|
|
||||||
int numDrops = stacks.Length;
|
|
||||||
float rawDropRate = dropRate;
|
|
||||||
// Combinatorics:
|
|
||||||
// OPTION 1: [The item drops = Raw Drop Rate]
|
|
||||||
// +
|
|
||||||
// OPTION 2: [ALL items fail to drop = (1-x)^n] * [This item is chosen as pity = 1/n]
|
|
||||||
float dropRateWithPityRoll = rawDropRate + (float)(Math.Pow(1f - rawDropRate, numDrops) * (1f / numDrops));
|
|
||||||
float dropRateAdjustedForParent = dropRateWithPityRoll * ratesInfo.parentDroprateChance;
|
|
||||||
|
|
||||||
// Report the drop rate of each individual item. This calculation includes the fact that each individual item can be guaranteed as pity.
|
|
||||||
foreach (WeightedItemStack stack in stacks)
|
|
||||||
drops.Add(new DropRateInfo(stack.itemID, stack.minQuantity, stack.maxQuantity, dropRateAdjustedForParent, ratesInfo.conditions));
|
|
||||||
|
|
||||||
Chains.ReportDroprates(ChainedRules, rawDropRate, drops, ratesInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Reference in a new issue