Skip to content
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
2 changes: 1 addition & 1 deletion BreakableWallRandomizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace BreakableWallRandomizer
public class BreakableWallRandomizer : Mod, IGlobalSettings<BWR_Settings>
{
new public string GetName() => "Breakable Wall Randomizer";
public override string GetVersion() => "3.0.4.4";
public override string GetVersion() => "4.0.0.0";
public BWR_Settings GS { get; set; } = new();
private static BreakableWallRandomizer _instance;
public BreakableWallRandomizer() : base()
Expand Down
4 changes: 2 additions & 2 deletions BreakableWallRandomizer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
<Product>BreakableWallRandomizer</Product>
<Description>A Randomizer add-on for wall and floor objects.</Description>
<Copyright>Copyright ©2023</Copyright>
<AssemblyVersion>3.0.4.4</AssemblyVersion>
<FileVersion>3.0.4.4</FileVersion>
<AssemblyVersion>4.0.0.0</AssemblyVersion>
<FileVersion>4.0.0.0</FileVersion>
<OutputPath>bin\$(Configuration)\</OutputPath>
<LangVersion>latest</LangVersion>
</PropertyGroup>
Expand Down
10 changes: 10 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Breakable Wall Randomizer 4.0

Changelog:
- Introducing *Collapsers*: These represent *60?* new items that can be included into the randomized pool. Much like Walls, Planks and Dive Floors, they can have their own group set. (18/60) 30%
- Reworked Wall Groups: As of previous patch, Wall Groups were a bit arbitrary. With the introduction of Collapsers, these need some clearer definition. Now, if this setting is enabled, all objects will be replaced by room walls. A room wall will destroy all randomized breakables in a given room, much like how Wall Groups behaved before, but with the consistency that there will be one wall item/location per room. (0%)
- Rebuilt FStats integration. Half / Total remain the same, but instead of using individual groups, walls by Map Area are selected instead. (0%)
- Removed the Softlock setting: It was rarely used, not maintained, didn't keep track of other connection interops and with the introduction of yet another wall type, whichever walls were defined under these settings are potentially more outdated. Plus, the connection menu was already big enough and we still are introducing new options. (100%)
- Restored shop descriptions: They were a thing on BWR 2+, got dropped on BWR 3.0 as an oversight and I see no reason to impede their return - with some extra new descriptions too. (100%)
- Added a new wall: Wall-QG_Glass, which is the glass window that leads to the Queen's Gardens top Grub. This is a standard wall in every aspect, except it breaks in one hit instead of four. (100%)
- Added Extra Walls: There are three groups of these - walls such as the King's Pass breakables, Ancestral Mound planks and Hive Pillars. (0%)
22 changes: 22 additions & 0 deletions FSM/CustomCollide.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using UnityEngine;
using HutongGames.PlayMaker;

namespace BreakableWallRandomizer.Fsm
{
internal class SetTriggerCollider : FsmStateAction
{
private Collider2D thisCollider;
public override void OnEnter()
{
thisCollider = Owner.GetComponent<BoxCollider2D>();
thisCollider.isTrigger = false;
Rigidbody2D rb = Owner.GetComponent<Rigidbody2D>();
if (rb == null)
{
rb = Owner.AddComponent<Rigidbody2D>();
rb.bodyType = RigidbodyType2D.Kinematic;
}
Finish();
}
}
}
99 changes: 84 additions & 15 deletions IC/BreakableWallItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,28 @@ namespace BreakableWallRandomizer.IC
[Serializable]
public class BreakableWallItem : AbstractItem
{
public string sceneName;
public string gameObject;
public string fsmType;
public string sceneName;
public string persistentBool;
public bool extra;
public List<CondensedWallObject> groupWalls;
public BreakableWallItem(
string name, string sceneName, string gameObject, string fsmType, string persistentBool,
string sprite, List<CondensedWallObject> groupWalls
string sprite, bool extra, List<CondensedWallObject> groupWalls
)
{
this.name = name;
this.sceneName = sceneName;
this.gameObject = gameObject;
this.fsmType = fsmType;
this.persistentBool = persistentBool;
this.extra = extra;
this.groupWalls = groupWalls;
UIDef = new MsgUIDef()
{
name = new BoxedString(name.Replace("_", " ").Replace("-", " - ")),
shopDesc = new BoxedString(""),
shopDesc = GenerateShopDescription(),
sprite = new WallSprite(sprite)
};
tags = [BreakableWallItemTag()];
Expand All @@ -46,6 +48,8 @@ private InteropTag BreakableWallItemTag()
sprite = "wood_plank_02";
if (name.StartsWith("Dive_Floor-") || name.StartsWith("Dive_Group"))
sprite = "break_floor_glass";
if (name.StartsWith("Collapser-") || name.StartsWith("Collapser_Group"))
sprite = "collapser_short_0deg";

InteropTag tag = new();
tag.Properties["ModSource"] = "BreakableWallRandomizer";
Expand All @@ -55,21 +59,80 @@ private InteropTag BreakableWallItemTag()
return tag;
}

public BoxedString GenerateShopDescription()
{
string[] descriptions = {
"What am I supposed to put in this description? It's a wall.",
"Truly one of the walls of all time.",
"Quite possibly my most favouritest wall in the game.",
"Quite possibly my least favouritest wall in the game.",
"Call in Bob the Builder. He won't fix it, he'll break it.",
"Donate to Menderbug so that he can have a day off and break a wall instead of fixing one.",
"This is probably the most important wall in the game.",
"This is probably just another useless shortcut wall. Still...",
"Fun fact: this mod adds exactly X breakable wall checks, and even more dive floor checks!",
"Yes, you might need to do four Pantheons to break that one wall.",
"Writing shop descriptions for these things is kinda hard.",
"Vague and non-specific description somehow tangentially related to walls goes here.",
"I bet you don't even know where this one is, do you?",
"Wall is love, baby don't hurt me, don't hurt me, no more.",
"This wall is begging to be shattered. Do it for the thrill.",
"Behind this wall lies a mystery waiting to be uncovered. Unless there isn't.",
"I'm pretty sure the wall won't see this one coming.",
"This wall was asking for it. I just answered the call.",
"Rumour has it that breaking this wall will bring good luck. Worth a shot, right?",
"This wall is a roadblock on the path to victory. It's time to remove it.",
"Maybe, if you run really fast at this wall, it'll just let you through instead?",
"Hey kid, wanna buy some cracks?",
"This one's definitely the one you've been looking for. Trust me, I checked.",
"All craftsmanship is of the lowest quality.",
"Menderbug has been trying to get his hands on this one for years!",
"I'm sure this is the one wall you need for Myla's shop.",
"Is this even a wall? Or is it a plank? Or is it a dive floor? Or is it a collapser? You know, I do not.",
"Don't look at me, I'm just a description.",
"There are 56 rock walls in the game.",
"There are 51 wooden planks in the game.",
"There are 45 dive floors in the game.",
"There are many collapsers in the game.",

"Dearest Homothety (AKA \"Moth\") (AKA \"Randoman\"): I am writing to inform you of a glaring error in your randomization algorithm for the game Hollow Knight. Though I was assured that the item locations were random, and indeed was swayed by your very name, there was not one but TWO so-called \"vanilla\" locations. Please, I implore you, fix your game.",
"I'll cast some Bad Magic to break this wall for ya -- for a small fee.",
"Bring in a Sock Mower to mow down this wall. What even *is* a Sockmower?",
"FlibberZERO this wall.",
"You Onrywon't be seeing this wall any more after you purchase this product.",
"You can thank Bentechy66 for this wall even being a thing by breaking it.",
"Broken walls are no longer hard as a GlowSTONEtrees. They're transparent.",
"The road to Roma 337 walls contains.",
"Nerthul salutes you and encourages you to spend geo on this and hope for the best.",

"Hot Loading Screen Tip: Walls which you've unlocked, but haven't checked, will be transparent. You can walk through them!",
"Hot Loading Screen Tip: If Group Walls are enabled, you can walk through any walls in that room if the item's obtained.",
"Hot Loading Screen Tip: If Group Walls are enabled, breaking any wall in that room will grant you the group's check.",
"Hot Loading Screen Tip: Breakable Walls in the white palace follow the WP Rando setting.",
"Hot Loading Screen Tip: There's a miner, looking for shiny stuff behind walls and will reward you for breaking them.",
"Hot Loading Screen Tip: They say a fluke thing who sells junk might accept your wall credit card.",
"Hot Loading Screen Tip: Breakable Walls in the Abyssal Temple follow the Abyssal Temple Rando setting."
};

System.Random rng = new();
return new BoxedString(descriptions[rng.Next(0, descriptions.Length)]);
}

public override void GiveImmediate(GiveInfo info)
{
// Set data in the save to indicate we got the wall
if (name.StartsWith("Wall_Group") || name.StartsWith("Plank_Group") || name.StartsWith("Dive_Group"))
if (name.StartsWith("Wall_Group") || name.StartsWith("Plank_Group") || name.StartsWith("Dive_Group") || name.StartsWith("Collapser_Group"))
{
foreach (CondensedWallObject wall in groupWalls)
{
if (!BreakableWallModule.Instance.UnlockedBreakableWalls.Contains(wall.name))
BreakableWallModule.Instance.UnlockedBreakableWalls.Add(wall.name);
if (wall.name.StartsWith("Wall") && !BreakableWallModule.Instance.UnlockedWalls.Contains(name))
BreakableWallModule.Instance.UnlockedWalls.Add(wall.name);
if (wall.name.StartsWith("Plank") && !BreakableWallModule.Instance.UnlockedPlanks.Contains(name))
BreakableWallModule.Instance.UnlockedPlanks.Add(wall.name);
if (wall.name.StartsWith("Dive_Floor") && !BreakableWallModule.Instance.UnlockedDives.Contains(name))
BreakableWallModule.Instance.UnlockedDives.Add(wall.name);
if (name.StartsWith("Collapser") && !BreakableWallModule.Instance.UnlockedCollapsers.Contains(name))
BreakableWallModule.Instance.UnlockedCollapsers.Add(name);

// If we're already in the same scene as the wall, break it.
if (GameManager.instance.sceneName == wall.sceneName)
Expand All @@ -78,23 +141,29 @@ public override void GiveImmediate(GiveInfo info)
}
else
{
if (!BreakableWallModule.Instance.UnlockedBreakableWalls.Contains(name))
BreakableWallModule.Instance.UnlockedBreakableWalls.Add(name);
if (name.StartsWith("Wall") && !BreakableWallModule.Instance.UnlockedWalls.Contains(name))
BreakableWallModule.Instance.UnlockedWalls.Add(name);
if (name.StartsWith("Plank") && !BreakableWallModule.Instance.UnlockedPlanks.Contains(name))
BreakableWallModule.Instance.UnlockedPlanks.Add(name);
if (name.StartsWith("Dive_Floor") && !BreakableWallModule.Instance.UnlockedDives.Contains(name))
BreakableWallModule.Instance.UnlockedDives.Add(name);

// If we're already in the same scene as the wall, break it.
if (GameManager.instance.sceneName == sceneName)
GameObject.Find(gameObject).LocateMyFSM(fsmType).SetState("BreakSameScene");
if (name.StartsWith("Collapser") && !BreakableWallModule.Instance.UnlockedCollapsers.Contains(name))
BreakableWallModule.Instance.UnlockedCollapsers.Add(name);
}
if (persistentBool != "")
PlayerData.instance.SetBool(persistentBool, true);

BreakableWallModule.Instance.CompletedChallenges();
foreach (CondensedWallObject wall in groupWalls)
{
if (!BreakableWallModule.Instance.UnlockedBreakables.Contains(wall.name))
BreakableWallModule.Instance.UnlockedBreakables.Add(wall.name);
if (GameManager.instance.sceneName == wall.sceneName)
GameObject.Find(wall.gameObject).LocateMyFSM(wall.fsmType).SetState("BreakSameScene");
}
if (!BreakableWallModule.Instance.UnlockedBreakables.Contains(name))
BreakableWallModule.Instance.UnlockedBreakables.Add(name);
if (persistentBool != "")
PlayerData.instance.SetBool(persistentBool, true);

BreakableWallModule.Instance.CompletedChallenges();
}
}
}
8 changes: 8 additions & 0 deletions IC/Shop/BreakableCost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,12 @@ public override void OnPay() { }
public override bool HasPayEffects() => false;
public override string GetCostText() => $"{amount} dive floors";
}

public sealed record CollapserCost(int amount) : Cost
{
public override bool CanPay() => BreakableWallModule.Instance.UnlockedCollapsers.Count >= amount;
public override void OnPay() { }
public override bool HasPayEffects() => false;
public override string GetCostText() => $"{amount} collapser floors";
}
}
4 changes: 4 additions & 0 deletions IC/Shop/BreakableCostDisplayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ protected override bool SupportsCost(Cost c)
return c is PlankCost;
if (cost == "Dive")
return c is DiveCost;
if (cost == "Collapser")
return c is CollapserCost;
return false;
}
protected override int GetSingleCostDisplayAmount(Cost c)
Expand All @@ -26,6 +28,8 @@ protected override int GetSingleCostDisplayAmount(Cost c)
return ((PlankCost)c).amount;
if (cost == "Dive")
return ((DiveCost)c).amount;
if (cost == "Collapser")
return ((CollapserCost)c).amount;
return 0;
}
}
Expand Down
2 changes: 1 addition & 1 deletion IC/Shop/CostSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public CostDisplayer GetDisplayer(Cost c)

public bool MatchesCost(Cost c)
{
return c is WallCost && displayer == "Wall" || c is PlankCost && displayer == "Plank" || c is DiveCost && displayer == "Dive";
return c is WallCost && displayer == "Wall" || c is PlankCost && displayer == "Plank" || c is DiveCost && displayer == "Dive" || c is CollapserCost && displayer == "Collapser";
}
}
}
3 changes: 2 additions & 1 deletion IC/ShopLocation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public WallShop()
Displayers = [
new WallCostSupport("Wall", "mine_break_wall_03_0deg"),
new WallCostSupport("Plank", "wood_plank_02"),
new WallCostSupport("Dive", "break_floor_glass")
new WallCostSupport("Dive", "break_floor_glass"),
new WallCostSupport("Collapser", "collapser_short_0deg")
]
};
tags = [ShopTag()];
Expand Down
Loading
Loading