I don't like collections. I'm really weak with them.
Don't even get me started on Keys.
Also too, before you suggest Dictionaries, they might be better but I've never worked with them
and unless it's super-simple, I want to move on and not spend the next week learning about them.
So right now not interested in Dictionaries.
This is what's going on.
The app is very meta.
McGuffinTechs are workers who create McGuffins which are the currency.
McGuffinTechs are actually controls on the form.
They can be randomly recruited and they can randomly elope.
They get a recruitment bonus and an elopement penalty that will apply
to several things including if they get recruited again.
They can also be promoted and demoted.
If they elope, getting promoted gets more difficult.
All of this is done randomly. The only time controls are recruited on purpose
is to start the game and give the player some economy.
After that it's all die rolls.
But it is nerfed in favor the player.
I've already got another system doing the same thing in a much worse, much more convoluted and hard-to-follow and maintain way.
It doesn't maintain production counts per tech or have any kind of elopement penalties or ranks.
In fact, they don't do anything at all.
The program just adds up how many techs I've recruited and multiplies them to find out how many mcguffins
got produced that cycle.
I'm leaving it in place and slowly incorporating this into the code.
Right now it's just recruiting techs and some of them are eloping but it's not using the number in the app yet.
There are two instances of the same collection class.
The first class holds ALL techs. Think of it as Pool but even when recruited into the other class they stay in the Pool.
The second holds only those that have been recruited (and haven't eloped)
The reason I'm doing this is so that each tech maintains lifetime totals.
I could have techs move back and forth between classes but I decided I didn't want to mess with that so the Recruitment class just checks if a tech already exists before adding (recruiting) it.
I also have a flag to allow multiple instances of control arrays since I want all the controls in the Pool class but only one instance in the recruitment class.
For the sake of this (the code is already long) just assume everything got initialized properly. That is working fine.
E.g. I'm not getting any errors.
I don't want to get much farther into this if I have to do major revisions per your feedback.
Also too, I'm not worried about the numbers being generated. That's just adjusting constants and equations until I get something I like which I will work on after it's incorporated and working properly.
The code should work regardless as long as I'm not dividing by zero or something stupid like that.
Lastly, any time you see PartyMember, those are now McGuffinTechs. I haven't changed the procedure names yet but that's on the list of things to do.
Declarations (these are in a few different places but consolidated here):
Code:' Declarations. Private m_TechPool As cMcGuffinTechs Private WithEvents m_TechRecruits As cMcGuffinTechs Public Enum MCGUFFIN_TECH_RANK idx_McGuffinTechRank_Recruit = 0 idx_McGuffinTechRank_Tech1 idx_McGuffinTechRank_Tech2 idx_McGuffinTechRank_Tech3 idx_McGuffinTechRank_Tech4 idx_McGuffinTechRank_Tech5 idx_McGuffinTechRank_Tech6 idx_McGuffinTechRank_Tech7 idx_McGuffinTechRank_Tech8 idx_McGuffinTechRank_Tech9 End Enum Public Const MIN_MCGUFFIN_TECH_RANK As Long = idx_McGuffinTechRank_Recruit Public Const MAX_MCGUFFIN_TECH_RANK As Long = idx_McGuffinTechRank_Tech9 Public Const MAX_MCGUFFIN_VALUE As Long = 10
Populating the Pool:
Code:Private Sub CreateMcGuffinTechs() Dim m_CallStacker As New cCallStacker Dim m_McGuffinTech As cMcGuffinTech Dim ctl As VB.Control m_CallStacker.Add Name & ".CreateMcGuffinTechs(Private Sub)" Set m_TechPool = New cMcGuffinTechs For Each ctl In Controls Set m_McGuffinTech = New cMcGuffinTech m_McGuffinTech.Initialize ctl m_TechPool.Add m_McGuffinTech, True ' Load all controls into m_TechPool ' Once in, they never come out. Next ctl End Sub
Recruiting McGuffinTechs:
Code:Private Function AddPartyMember(ByRef Control As VB.Control) As RANDOM_PARTY_MEMBER_JOIN Dim m_CallStacker As New cCallStacker Dim m_McGuffinTech As cMcGuffinTech Dim n As Long m_CallStacker.Add Name & ".AddPartyMember(Private Function)" If Control Is descendent Then Exit Function AddPartyMember = Player.PartyMemberRandomJoin(Control) ' This is the part being used currently. ' This is the new code but eventually will be replaced with 'm_TechRecruits.Recruit m_TechPool.McGuffinTech(RollDie(m_TechPool.Count)) For n = 1 To m_TechPool.Count If m_TechPool.McGuffinTech(n).McGuffinTechName = Control.Name Then m_TechRecruits.Recruit m_TechPool.McGuffinTech(n) m_TechRecruits.RandomElope Exit Function End If Next n End Function
Checking output:
Code:Private Sub mnuCrouchingMenuVisibleSubmenu_Click() Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".mnuCrouchingMenuVisibleSubmenu_Click(Private Sub)" AddPlayerMessage "McGuffinTechs: " & m_TechRecruits.Count AddPlayerMessage vbCrLf & m_TechRecruits.DoProduction Stop End Sub
McGuffinTech Class:
Code:Option Explicit ' Simple Counts are stored as Long Integers. ' Other Values are calculated and stored as Doubles but presented to ' the Player as Longs to keep notifications and the interface tidy. ' // Constants, Types and Enums. Private Const Name As String = "cMcGuffinTech" Private Const FIRST_PROMOTION As Long = 100 ' / Constants, Types and Enums. ' // Objects. Private m_Control As VB.Control ' / Objects. ' // Events. Public Event Promoted(ByRef McGuffinTechName As String, ByRef NewRank As MCGUFFIN_TECH_RANK) Public Event Demoted(ByRef McGuffinTechName As String, ByRef NewRank As MCGUFFIN_TECH_RANK) Public Event Recruited(ByRef McGuffinTechName As String, ByRef RecruitmentBonus As Long) Public Event Eloped(ByRef McGuffinTechName As String, ByRef ElopementPenalty As Long) Public Event DescendentDisassembled(ByRef McGuffinTechName As String, ByRef DisassembledValue As Long) ' / Events. ' // Properties. Private nRank As MCGUFFIN_TECH_RANK Private nRecruitments As Long Private rRecruitmentBonus As Double Private nElopements As Long Private rElopementPenalty As Double Private nPromotions As Long Private nDemotions As Long Private fDemoted As Boolean Private rLifetimeCost As Double Private rLifetimeProduction As Double Private nDescendentsDisassembled As Long ' / Properties. Private Sub CalculateElopementPenalty() Dim m_CallStacker As New cCallStacker Dim n As Long m_CallStacker.Add Name & ".CalculateElopementPenalty(Private Sub)" rElopementPenalty = 0 For n = MIN_MCGUFFIN_TECH_RANK To nRank rElopementPenalty = rElopementPenalty + RollDie(MAX_MCGUFFIN_VALUE) Next n End Sub Private Sub CalculateRecruitmentBonus() Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".CalculateRecruitmentBonus(Private Sub)" rRecruitmentBonus = RollDie(MAX_MCGUFFIN_VALUE * (1 + nRank)) * (1 - DemotionPenalty) End Sub Public Property Get Control() As VB.Control Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Control(Public Property Get)" If m_Control Is Nothing Then Exit Property Set Control = m_Control End Property Public Property Get CycleCost() As Double Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".CycleCost(Public Property Get)" CycleCost = nRank + 1 End Property Private Function Demote() As Boolean Dim m_CallStacker As New cCallStacker Dim n As Long m_CallStacker.Add Name & ".Demote(Private Function)" If (RollDie(d2) = 2) Or (nElopements = 0) Then Exit Function ' Half a chance to not get Demoted. If nRank > idx_McGuffinTechRank_Recruit Then nRank = nRank - 1 ' It counts as getting Demoted even if you're at the lowest rank. ' Don't screw-up next time. nDemotions = nDemotions + 1 fDemoted = True Demote = True End Function Public Property Get Demoted() As Boolean Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Demoted(Public Property Get)" Demoted = fDemoted End Property Public Property Get DemotionPenalty() As Double Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".DemotionPenalty(Public Property Get)" If Not fDemoted Then Exit Property DemotionPenalty = 0.5 End Property Public Property Get Demotions() As Long Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Demotions(Public Property Get)" Demotions = nDemotions End Property Public Property Get DescendentsDisassembled() As Long Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".DescendentsDisassembled(Public Property Get)" DescendentsDisassembled = nDescendentsDisassembled End Property Private Sub DisassembleDescendent() Dim m_CallStacker As New cCallStacker Dim nValue As Long Dim n As Long m_CallStacker.Add Name & ".DisassembleDescendent(Private Sub)" If RollDie(d4) <> 4 Then Exit Sub For n = 1 To RollDie(d4) nDescendentsDisassembled = nDescendentsDisassembled + 1 nValue = DisassemblyValue RaiseEvent DescendentDisassembled(m_Control.Name, nValue) LifetimeProduction = rLifetimeProduction + nValue Next n End Sub Private Function DisassemblyValue() As Long Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".DisassemblyValue(Private Function)" DisassemblyValue = RollDie(MAX_MCGUFFIN_VALUE * (1 + nRank)) * (1 - DemotionPenalty) End Function Public Sub Elope() Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Elope(Public Sub)" nElopements = nElopements + 1 rLifetimeCost = rLifetimeCost + rElopementPenalty RaiseEvent Eloped(Name, ElopementPenalty) End Sub Public Property Get ElopementPenalty() As Long Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".ElopmentCost(Public Property Get)" ElopementPenalty = CLng(rElopementPenalty) End Property Public Property Get Elopements() As Long Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Elopements(Public Property Get)" Elopements = nElopements End Property Private Property Let Elopements(ByRef NumTimesEloped As Long) Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Elopements(Private Property Let)" If NumTimesEloped <= nElopements Then Exit Property nElopements = NumTimesEloped End Property Public Sub Initialize(ByRef Control As VB.Control) Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".LifetimeCost(Public Sub)" If Control Is Nothing Then Exit Sub Set m_Control = Control End Sub Public Property Get LifetimeCost() As Double Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".LifetimeCost(Public Property Get)" LifetimeCost = rLifetimeCost End Property Public Property Get LifetimeProduction() As Double Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".LifetimeProduction(Public Property Get)" LifetimeProduction = rLifetimeProduction End Property Private Property Let LifetimeProduction(ByRef ProductionByMcGuffinTech As Double) Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".LifetimeProduction(Private Property Let)" rLifetimeProduction = ProductionByMcGuffinTech Promote End Property Public Property Get McGuffinTechName() As String Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Name(Public Property Get)" If m_Control Is Nothing Then Exit Property McGuffinTechName = m_Control.Name End Property Private Property Get NextPromotionStandard() As Boolean Dim m_CallStacker As New cCallStacker Dim rNextPromotion Dim n As Long m_CallStacker.Add Name & ".NextPromotionStandard(Private Property Get)" If nRank = MAX_MCGUFFIN_TECH_RANK Then Exit Property For n = 1 To nRank + 1 rNextPromotion = 2 * (n + Elopements) * FIRST_PROMOTION Next n If LifetimeProduction >= rNextPromotion Then NextPromotionStandard = True End If End Property Public Property Get Production() As Double Dim m_CallStacker As New cCallStacker Dim rProduction As Double Dim rRank As Double ' Returns number of McGuffins produced in a Cycle. m_CallStacker.Add Name & ".Production(Public Property Get)" rRank = CDbl(nRank) ' Probably not necessary but do it explicitly instead of letting VB handle it. rProduction = ((1 + rRank) / 2) * Player.TotalMultiplier(idx_Player_Attribute_Development) * (1 - DemotionPenalty) Production = rProduction LifetimeProduction = rLifetimeProduction + rProduction - CycleCost rLifetimeCost = rLifetimeCost + CycleCost End Property Private Sub Promote() Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Promote(Private Sub)" If Not NextPromotionStandard Then Exit Sub nRank = nRank + 1 nPromotions = nPromotions + 1 fDemoted = False RaiseEvent Promoted(Name, nRank) End Sub Public Property Get Promotions() As Long Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Promotions(Public Property Get)" Promotions = nPromotions End Property Public Property Get Rank() As MCGUFFIN_TECH_RANK Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Rank(Public Property Get)" Rank = nRank End Property Public Sub Recruit() Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Recruit(Public Sub)" nRecruitments = nRecruitments + 1 CalculateRecruitmentBonus CalculateElopementPenalty ' Tech can be demoted if previously Eloped. If Demote Then rElopementPenalty = rElopementPenalty * 2 LifetimeProduction = LifetimeProduction + rRecruitmentBonus RaiseEvent Recruited(Name, RecruitmentBonus) End Sub Public Property Get RecruitmentBonus() As Long Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".RecruitmentBonus(Public Property Get)" RecruitmentBonus = CLng(rRecruitmentBonus) End Property Public Property Get Recruitments() As Long Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Recruit(Public Property Get)" Recruitments = nRecruitments End Property
' Pool/Recruitment (Collection) Class:
Code:Option Explicit ' // Constants, Types and Enums. Private Const Name As String = "cMcGuffinTechs" ' / Constants, Types and Enums. ' // Objects. Private colMcGuffinTechs As Collection ' / Objects. ' // Events. Public Event Recruited(ByRef McGuffinTechName As String, ByRef RecruitmentBonus As Long) Public Event Eloped(ByRef McGuffinTechName As String, ByRef ElopementCost As Long) Public Event McGuffinsProduced(ByRef NumberProduced As Long) ' / Events. Friend Function Add(ByRef McGuffinTech As cMcGuffinTech, ByRef AllowControlArrays As Boolean) As Boolean Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Class_Initialize(Friend Function)" Add = False ' Two Collections hold cMcGuffinTechs. ' One class holds all of them. ' The second Class does not allow more than one control instance in a given array. If Exists(McGuffinTech, AllowControlArrays) Then Exit Function colMcGuffinTechs.Add McGuffinTech Add = True End Function Public Property Get Count() As Long Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Class_Initialize(Public Property Get)" Count = colMcGuffinTechs.Count End Property Public Function DoProduction() As Long Dim m_CallStacker As New cCallStacker Dim m_McGuffinTech As cMcGuffinTech Dim rTotal As Double m_CallStacker.Add Name & ".DoProduction(Public Sub)" If colMcGuffinTechs.Count = 0 Then Exit Function For Each m_McGuffinTech In colMcGuffinTechs rTotal = rTotal + m_McGuffinTech.Production Next m_McGuffinTech DoProduction = CLng(rTotal) RaiseEvent McGuffinsProduced(CLng(rTotal)) End Function Public Function Elope(ByRef McGuffinTech As cMcGuffinTech) As Boolean Dim m_CallStacker As New cCallStacker Dim n As Long m_CallStacker.Add Name & ".Elope(Public Function)" Elope = False If colMcGuffinTechs.Count = 0 Then Exit Function For n = 1 To colMcGuffinTechs.Count If colMcGuffinTechs(n) Is McGuffinTech Then colMcGuffinTechs(n).Elope colMcGuffinTechs.Remove n Elope = True RaiseEvent Eloped(McGuffinTech.McGuffinTechName, McGuffinTech.ElopementPenalty) Exit Function End If Next n End Function Private Function Exists(ByRef McGuffinTech As cMcGuffinTech, ByRef AllowControlArrays As Boolean) As Boolean Dim m_CallStacker As New cCallStacker Dim m_McGuffinTech As cMcGuffinTech m_CallStacker.Add Name & ".Exists(Private Function)" Exists = False If colMcGuffinTechs.Count = 0 Then Exit Function If AllowControlArrays Then For Each m_McGuffinTech In colMcGuffinTechs If m_McGuffinTech Is McGuffinTech Then Exists = True Exit Function End If Next m_McGuffinTech Else For Each m_McGuffinTech In colMcGuffinTechs If m_McGuffinTech.McGuffinTechName = McGuffinTech.McGuffinTechName Then Exists = True Exit Function End If Next m_McGuffinTech End If End Function Public Property Get McGuffinTech(ByRef Index As Long) As cMcGuffinTech Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".McGuffinTech(Public Property Get)" If (Index < 1) Or (Index > colMcGuffinTechs.Count) Then Exit Property Set McGuffinTech = colMcGuffinTechs(Index) End Property Public Function RandomElope() As Boolean Dim m_CallStacker As New cCallStacker Dim m_McGuffinTech As cMcGuffinTech m_CallStacker.Add Name & ".RandomElope(Public Function)" If colMcGuffinTechs.Count = 0 Then Exit Function If RollDie(d8) <> 1 Then Exit Function Set m_McGuffinTech = colMcGuffinTechs(RollDie(colMcGuffinTechs.Count)) RandomElope = Elope(m_McGuffinTech) End Function Public Function Recruit(ByRef McGuffinTech As cMcGuffinTech) As Boolean Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".McGuffinTech(Public Function)" If Add(McGuffinTech, False) Then McGuffinTech.Recruit Recruit = True End If End Function Private Sub Class_Initialize() Dim m_CallStacker As New cCallStacker m_CallStacker.Add Name & ".Class_Initialize(Private Sub)" Set colMcGuffinTechs = New Collection End Sub


Reply With Quote