Wake Up Devlog Week 11
- Tristan Atkinson
- Dec 2, 2024
- 5 min read
Updated: Apr 20
This week, my sprint goal was to get two systems working:
Class selection on Main Menu
Room Progression system, with randomised encounter chances and room weighting
The quickest and easiest of these two was the class selection. This Widget opens between pressing ‘Start Run’ on the main menu and getting into the run itself. The left side of the screen has buttons in a vertical box with each class assigned to a button.
‘WB_ClassSelectButton’ is the widget i created to do this; it's a widget class consisting of a button with a text component inside it, as well as an instance editable variable called ‘Class’ which is a class reference to ‘BP_PlayerBase’, which means I can assign each button one of the Player Classes to store the value of.
When clicking one of these buttons, it will set the value of ‘Player CLass Chosen’ in the game instance, which dictates what Class is spawned on the Player spawner actor.

The event dispatcher used on the Class Selection widget calls an event which runs a for each loop with every child of the ‘ClassButtonVBox’ (where all the class select buttons are) to change their background colour accordingly (white if not selected class, green if is) to give feedback to the player that their selection has been logged.

The room choice widgets took me far longer to get working, and I had a decent bit of trouble working out how to get the more complicated mechanics working: mainly room-weighting. But by the end of the week it was working perfectly as intended.
‘WB_RoomBase’ is a widget which is placed in a horizontal box on the ‘WB_RoomChoice’ widget three times. The room bae widget randomises its chances for each of the three encounters.

The randomisation system is made with the intent that the Combat encounter generally has a higher chance of being the highest % encounter, while the other two still have a decent chance of being a high %.
The Combat Encounter’s chance is calculated by getting an int between 1 and 100, meaning it has a 1 in 2 chance of being over 50%, guaranteeing it as the highest chance out of three choices.
The calculations for the other two are a bit more complicated, as from here I had to make sure that the other chances would be calculated in a way that all three would add up to 100%.
Two values are stored before setting any of the room chances:
The random int between 1-100 used for the combat encounter is divided by 100 (between 0.01 and 1.0) and saved as a float called Random Num
A random int between 0-3 is selected (this int has 2 added to it when used later on.) called Divided Num
The equations used with these values is as follows:
Combat Chance = RandomNum * 100
Shop Chance = ((1.0-RandomNum) / (DividedNum+2)) * 100
Event Chance = (((1.0-RandomNum) / (DividedNum+2)) * ((DividedNum+2)-1))*100
Depending on a random boolean, the Shop and Event chance equations may be switched.
When the ‘Proceed’ button at the bottom is pressed, the Player’s chance is calculated.
The ‘Onclicked’ event first makes an array from the COmbat, Sop and Event chance floats, and saves them as the value of an array called 'PreSortedChances'.
A while loop is then run while the length of this array is greater than 0; the loop body gets the Lowest float of the ‘PreSortedChances’ array and adds it to the ‘SortedChances’ array, before removing the index of said minimum float from ‘PreSortedChances’.
This ‘SortedChances’ array will now have the individual chances sorted from lowest to highest.
After the while loop is completed, a random float between 0.0 and 1.0 is saved as ‘Random Float Selection’ and a for each loop is run from the ‘SortedChances’ array.
This for each loop uses a boolean called ‘RoomSelected?’ to tell if a room chance has already been selected before it ends, so it first checks if this is true or false; if true it does nothing, and if false it moves on.
This loop basically checks if the ‘RandomFloatSelection’ is less than or equal to each array element.
I.E., to get a room with a 10% chance, the ‘RandomFloatSelection’ must be 0.1 or lower.
When the loop finds a chance the float selection is lower than, it sets ‘RoomSelected?’ to true and saved the index of the chance.
From the completed output of the previous loop, a branch is used to check if ‘RoomSelected?’ is true or false. If false, then that means a room was not selected in the loop. This can occur when the Player gets an exceptionally high output from the random float.
For example, if the chances were 85%, 10% and 5%, and the random float was 0.9, then none of the rooms would be selected.
This branch is used to check whether this has occurred, and if it has, then it will set the ‘SelectedIndex’ to 2, I.E. the highest % chance encounter.
Using the selected index, it will then check whether said index of ‘Sortedchances’ is == to the float value of each of the three chances’ individual floats, and load the corresponding level.
The final task I had to do for this widget was to implement ‘Room-Weighting’; spending currency to weight one encounter’s % up and another’s down.

The ‘Weight Chance’ button on the widget checks if enough currency is held, communicating through its background colour whether it has been activated or if the Player doesn’t have enough currency.
It then checks if either of the two booleans used in the weighting process are true, resetting the values associated with the weighting process if true, and setting ‘IsWeightingUp?’ to true if not.

This boolean and the ‘IsweightingDown?’ booleans are used to set what values are going to be changed: when any of the buttons next to each encounter are clicked, the appropriate index for up and down (Combat 0, Shop 1, event 2) are set, and the button colour is changed to green if weighing up and red if weighing down.
The ‘CheckValues’ function called after the up and down index has been set first checks whether ‘IndexUp’’s chance is within 15 of 100. If it is, then it sets the value of the floats ‘AmountToAdd’ and ‘AmountToRemove’ to the difference between the increased float and 100, to ensure that the value cannot be increased to over 100%, and the same value is changed between the two chances.

This process is repeated in reverse for the ‘IndexDown’ chance, to check if its chance is within 15 of 0; ensuring that the value cannot be decreased to below 0.
After this function is called, the ‘AmountToAdd’ and ‘AmountToRemove’ are added and removed from the indexes’ specified chances, before taking away the cost from the Player’s currency and multiplying the cost by 2 for subsequent weighting.

Finally, the ‘reset weighting’ event is called, which resets the values used in the weighting process and resets the button colours to their original state.
Comments