-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunctions.lua
More file actions
377 lines (350 loc) · 13.8 KB
/
Copy pathfunctions.lua
File metadata and controls
377 lines (350 loc) · 13.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
---Debug messages
---@param message string Message to send
---@param level? string Log level, DEBUG by default, TRACE won't send unless dev mode is active since DebugPlus doesn't have that filter fsr
SPECF.say = function(message, level)
if level == "TRACE" and not SPECF.config.dev_messages then
return
end
message = message or "???"
level = level or "DEBUG"
while #level < 5 do
level = level.." "
end
sendMessageToConsole(level, "Spectrum Framework", message)
end
---Checks if any Spectrum hand has been played; this includes spectra from other suits. Logic copied from Paperback.
---Also enables Bunco exotics if a spectrum has been played and they're somehow not already enabled.
---@return boolean
SPECF.spectrum_played = function()
local spectrum_played = false
if G and G.GAME and G.GAME.hands then
for k, v in pairs(G.GAME.hands) do
if string.find(k, "Spectrum", nil, true) or string.find(k, "Specflush", nil, true) then
if G.GAME.hands[k].played > 0 then
spectrum_played = true
break
end
end
end
end
if spectrum_played and (SMODS.Mods["Bunco"] or {}).can_load then
if (exotic_in_pool and not exotic_in_pool())
or (BUNCOMOD and BUNCOMOD.funcs and not BUNCOMOD.funcs.exotic_in_pool())
then enable_exotics() end
end
return spectrum_played
end
---Gets the key with mod prefix for the spectrum hand that will score
---@param HandName string Name of the hand to check
---@return string lowest_key Key of the hand that will score
SPECF.getSpecKey = function(HandName)
if not G.GAME then return SPECF.prefix.."_"..HandName end
HandName = HandName or "Spectrum"
local lowest_key = nil
local lowest_order = math.huge
local escaped_name = HandName:gsub("([^%w])", "%%%1") -- escape magic chars
local suffix_pattern = "_" .. escaped_name .. "$"
for key, hand in pairs(G.GAME.hands) do
if key:match(suffix_pattern) and type(hand.order) == "number" then
if hand.order < lowest_order then
lowest_order = hand.order
lowest_key = key
end
end
end
return lowest_key
end
---Checks if Spectrum hands are easy to score for any reason
---@return boolean
SPECF.easy_spectra = function()
if G.GAME.spectrum_status then
return (G.GAME.spectrum_status == 1)
end
if SPECF.config.spectrum_status.current_option == 1 then
if G and G.GAME then
G.GAME.spectrum_status = 1
end
SPECF.say('Spectrum Score Status: Standard', "TRACE")
return true
elseif SPECF.config.spectrum_status.current_option == 3 then
if G and G.GAME then
G.GAME.spectrum_status = 3
end
SPECF.say('Spectrum Score Status: Special', "TRACE")
return false
end
if G.GAME and G.GAME.starting_params.easy_spectra then
if G and G.GAME then
G.GAME.spectrum_status = 1
end
SPECF.say('Deck defines Spectra as easy', "TRACE")
return true
end
if SMODS.Mods.SixSuits and SMODS.Mods.SixSuits.can_load and SMODS.Mods.SixSuits.config.allow_all_suits then
if G and G.GAME then
G.GAME.spectrum_status = 1
end
SPECF.say('SixSuits\'s all-suits config option checked', "TRACE")
return true
end
if SMODS.Mods.draft and SMODS.Mods.draft.can_load then
SPECF.say("Drafting", "TRACE")
local count = 0
for _ in pairs(SPECF.in_pool_suits()) do count = count + 1 end
SPECF.say("Count == "..count, "TRACE")
if count > 5 then
if G and G.GAME then
G.GAME.spectrum_status = 1
end
SPECF.say("Lots of suits", "TRACE")
return true
end
end
local deckkey = G.GAME.selected_back.effect.center.key or "deck not found oopsie"
local forceenhance = G.GAME.modifiers.cry_force_enhancement or "not found"
SPECF.say("Deck key: "..deckkey, "TRACE")
SPECF.say("Forced enhancement: "..forceenhance, "TRACE")
if deckkey == "b_cry_et_deck" and forceenhance == "m_wild" then --Force lower values for this deck because it counts out of order
if G and G.GAME then
G.GAME.spectrum_status = 1
end
SPECF.say("Cryptid all-wild deck detected", "TRACE")
return true
end
if G.GAME.starting_params.diverse_deck == nil then
local diversity = SPECF.suit_diversity()
G.GAME.spectrum_status = diversity and 1 or 3
return diversity
end
--[[if G.GAME.starting_params.diverse_deck then
SPECF.say('Deck detected as diverse.', "TRACE")
end]]
SPECF.say('Nothing detected', "TRACE")
return false
end
---Checks if a deck has easy access to five or more suits
---@return boolean
SPECF.suit_diversity = function ()
if G.GAME.starting_params.diverse_deck ~= nil then
SPECF.say('Deck diversity already determined', "TRACE")
return G.GAME.starting_params.diverse_deck
end
local suit_counts = {}
local wild_count = 0
local stone_count = 0
local total_count = #G.playing_cards
for k, card in pairs(G.playing_cards) do
if SMODS.has_any_suit(card) then
wild_count = wild_count + 1
--[[if wild_count == 1 then
SPECF.say('Deck contains at least 1 Wild Card', "TRACE")
end]]
elseif SMODS.has_no_suit(card) then
stone_count = stone_count +1
--[[if stone_count == 1 then
SPECF.say('Deck contains at least 1 Stone Card', "TRACE")
end]]
else
local suit = card.base.suit
suit_counts[suit] = (suit_counts[suit] or 0) + 1
end
end
local suit_diversity_met = true
local available_suits = 0
local available_factor = 1/8
local domination_factor = 1/3
for suit, count in pairs(suit_counts) do
local thispercentage = (count+wild_count) / total_count
local notthispercentage = (total_count - (count+stone_count)) / total_count
if thispercentage > available_factor then
available_suits = available_suits + 1
SPECF.say(suit..' contains '..count..' cards, counts as available', "TRACE")
end
if notthispercentage < domination_factor then
suit_diversity_met = false
SPECF.say(suit..' contains '..count..' cards, deck is '..suit..'-dominated', "TRACE")
end
end
SPECF.say('Deck contains '..available_suits..' available suits.', "TRACE")
if available_suits < 5 then
suit_diversity_met = false
SPECF.say('Deck is not suit diverse.', "TRACE")
else
SPECF.say('Deck is suit diverse.', "TRACE")
end
G.GAME.starting_params.diverse_deck = suit_diversity_met
return G.GAME.starting_params.diverse_deck
end
---Moves hands in hand list
---@param handlist table G.handlist
---@param modded_positions table Table of the hands to move; details TBA because I don't know how to do this part
SPECF.reposition_modded_hands = function(handlist, modded_positions)
-- Step 1: Extract modded hands from the list
local extracted_hands = {}
for i = #handlist, 1, -1 do
for mod_hand, _ in pairs(modded_positions) do
if handlist[i] == mod_hand then
extracted_hands[mod_hand] = handlist[i]
table.remove(handlist, i)
break
end
end
end
-- Step 2: Reinsert modded hands at their target positions
for mod_hand, target in pairs(modded_positions) do
for i, hand in ipairs(handlist) do
if hand == target.name then
local insert_position = i + (target.position == "below" and 1 or 0)
table.insert(handlist, insert_position, mod_hand)
break
end
end
end
end
---Returns a table of suits currently in pool
---@return table
SPECF.in_pool_suits = function ()
local ret = {}
for key, value in pairs(SMODS.Suits) do
if value.in_pool == nil or value:in_pool({}) then
ret[key] = value
end
end
return ret
end
---Reveals all hands; call this from DebugPlus if you want to
---@param reverse boolean Set this to `true` to hide normally-hidden hands instead.
---@return boolean
SPECF.reveal_hands = function (reverse)
for hand_name, hand_data in pairs(G.GAME.hands) do
if reverse and SMODS.PokerHand.obj_table[hand_name] and (SMODS.PokerHand.obj_table[hand_name].visible == false) then
hand_data.visible = false
else
hand_data.visible = true
end
end
if reverse then
SPECF.say("Hidden hands unrevealed", "INFO ")
else
SPECF.say("All hands revealed", "INFO ")
end
return true
end
---Activates Bunco's exotic system, if you want to do this for some reason
SPECF.enable_exotics = function()
if not G.GAME then return end
G.GAME.Exotic = true
SPECF.say('Attempted to enable Exotic System.', "TRACE")
end
---Deactivates Bunco's exotic system, if you want to do this for some reason
SPECF.disable_exotics = function()
if not G.GAME then return end
G.GAME.Exotic = false
SPECF.say('Attempted to disable Exotic System.', "TRACE")
end
---Levels Specflush hands to average of equivalent Spectrum and Flush hands
---Called after calculating context.before and context.after (TODO maybe: add context.using_consumeable?)
SPECF.specflush_sync = function ()
if not SPECF.config.specflush then return end
local hands = {
"Specflush", "Straight Specflush", "Specflush House", "Specflush Five"
}
for _,specflush in ipairs(hands) do
local flush = string.gsub(specflush,"Specflush", "Flush")
local spec = string.gsub(specflush,"Specflush", "Spectrum")
local sflev = 0
local flev = 0
local slev = 0
for key, hand in pairs(G.GAME.hands) do
local level = to_number(hand.level)
--SPECF.say("Hand key is "..key, "TRACE")
if key == SPECF.prefix.."_"..specflush then
--SPECF.say(key.." is level "..level, "TRACE")
sflev = math.max(sflev,level)
end
if key == flush --[[All Flush hands are vanilla iirc and so won't have a prefix]] then
--SPECF.say(key.." is level "..level, "TRACE")
flev = math.max(flev,level)
end
if key:match("_"..spec.."$") then
--SPECF.say(key.." is level "..level, "TRACE")
slev = math.max(slev,level)
end
end
--SPECF.say("Levels calculated:", "TRACE")
--SPECF.say(flush.." is level "..flev, "TRACE")
--SPECF.say(spec.." is level "..slev, "TRACE")
--SPECF.say(specflush.." is level "..sflev, "TRACE")
local diff = math.ceil((slev+flev)/2 - sflev)
if diff > 0 then
SMODS.smart_level_up_hand(nil, SPECF.prefix.."_"..specflush, true, diff)
else
--SPECF.say("No imbalance found with "..flush.."+"..spec.." against "..specflush, "TRACE")
end
end
--G.GAME.hands[hand].level
end
---Gets the planet associated with a hand.
---Hands with a defined planet get that planet.
---Specflush hands get the corresponding Spectrum or Flush planet at random.
---Anything else gets a totally random planet.
---@param hand string Key of the hand to check
---@return string key Key of the selected planet card
SPECF.getPlanet = function(hand)
hand = hand or G.GAME.last_hand_played
if not hand then return "c_mercury" end
local planet
if SMODS.PokerHand.obj_table[hand] and SMODS.PokerHand.obj_table[hand].planet then
if type(SMODS.PokerHand.obj_table[hand].planet) == "string" then
return SMODS.PokerHand.obj_table[hand].planet
elseif type(SMODS.PokerHand.obj_table[hand].planet) == "table" then
planet = pseudorandom_element(SMODS.PokerHand.obj_table[hand].planet, pseudoseed("handplanet"))
if type(planet) == "string" then
for k, v in pairs(G.P_CENTER_POOLS.Planet) do
if v.key == planet then
return planet
end
end
end
end
end
planet = nil
for k, v in pairs(G.P_CENTER_POOLS.Planet) do
if v.config.hand_type == hand then
return v.key
end
end
local flush = hand:gsub("spectrum_", ""):gsub("Specflush", "Flush")
local spectrum = hand:gsub("Specflush", "Spectrum")
local flushplanet
local specplanet
for k, v in pairs(G.P_CENTER_POOLS.Planet) do
if v.config.hand_type == flush then
flushplanet = v.key
elseif v.config.hand_type == spectrum then
specplanet = v.key
end
end
if flushplanet and specplanet then
planet = pseudorandom_element({flushplanet, specplanet}, pseudoseed("get_specflush_planet"))
else
planet = pseudorandom_element(G.P_CENTER_POOLS.Planet, pseudoseed("get_random_planet")).key
local hand2 = G.P_CENTERS[planet] and G.P_CENTERS[planet].config and G.P_CENTERS[planet].config.hand_type
while not (G.GAME.hands[hand2] and G.GAME.hands[hand2].visible) do
local i = (i or 0)+1
planet = pseudorandom_element(G.P_CENTER_POOLS.Planet, pseudoseed("get_random_planet")).key
hand2 = G.P_CENTERS[planet] and G.P_CENTERS[planet].config.hand_type
if i > 100 then SPECF.say("getPlanet got stuck in a loop!", "ERROR") break end
end
end
return planet
end
SMODS.current_mod.calculate = function (self, context)
if context.before or context.after or context.using_consumeable then
SPECF.specflush_sync()
end
end
--[[ This happens before the rest of the run-start stuff
function SMODS.current_mod.reset_game_globals(start)
end
]]