diff --git a/Brainstorm.lua b/Brainstorm.lua index 1072050..d048208 100644 --- a/Brainstorm.lua +++ b/Brainstorm.lua @@ -10,6 +10,18 @@ function initBrainstorm() local settings_file = STR_UNPACK(nativefs.read((lovely.mod_dir .. "/Brainstorm/settings.lua"))) if settings_file ~= nil then Brainstorm.SETTINGS = settings_file + if not Brainstorm.SETTINGS.autoreroll.searchJoker then + Brainstorm.SETTINGS.autoreroll.searchJoker = "" + end + if not Brainstorm.SETTINGS.autoreroll.searchJokerID then + Brainstorm.SETTINGS.autoreroll.searchJokerID = 1 + end + if not Brainstorm.SETTINGS.autoreroll.searchJokerLocation then + Brainstorm.SETTINGS.autoreroll.searchJokerLocation = "any" + end + if not Brainstorm.SETTINGS.autoreroll.searchJokerLocationID then + Brainstorm.SETTINGS.autoreroll.searchJokerLocationID = 1 + end end end _RELEASE_MODE = not Brainstorm.SETTINGS.debug_mode diff --git a/Brainstorm_UI.lua b/Brainstorm_UI.lua index e3b9a4d..1458bba 100644 --- a/Brainstorm_UI.lua +++ b/Brainstorm_UI.lua @@ -45,14 +45,175 @@ Brainstorm.SearchPackList = { ["Jumbo Spectral"] = {"p_spectral_jumbo_1"}, ["Mega Spectral"] = {"p_spectral_mega_1"}, } + +Brainstorm.SearchJokerList = { + ["None"] = "", + ["8 Ball"] = "j_8_ball", + ["Abstract Joker"] = "j_abstract", + ["Acrobat"] = "j_acrobat", + ["Ancient Joker"] = "j_ancient", + ["Arrowhead"] = "j_arrowhead", + ["Astronomer"] = "j_astronomer", + ["Banner"] = "j_banner", + ["Baron"] = "j_baron", + ["Baseball Card"] = "j_baseball", + ["Blackboard"] = "j_blackboard", + ["Bloodstone"] = "j_bloodstone", + ["Blue Joker"] = "j_blue_joker", + ["Blueprint"] = "j_blueprint", + ["Bootstraps"] = "j_bootstraps", + ["Brainstorm"] = "j_brainstorm", + ["Bull"] = "j_bull", + ["Burglar"] = "j_burglar", + ["Burnt Joker"] = "j_burnt", + ["Business Card"] = "j_business", + ["Caino"] = "j_caino", + ["Campfire"] = "j_campfire", + ["Card Sharp"] = "j_card_sharp", + ["Cartomancer"] = "j_cartomancer", + ["Castle"] = "j_castle", + ["Cavendish"] = "j_cavendish", + ["Ceremonial Dagger"] = "j_ceremonial", + ["Certificate"] = "j_certificate", + ["Chaos the Clown"] = "j_chaos", + ["Chicot"] = "j_chicot", + ["Clever Joker"] = "j_clever", + ["Cloud 9"] = "j_cloud_9", + ["Constellation"] = "j_constellation", + ["Crafty Joker"] = "j_crafty", + ["Crazy Joker"] = "j_crazy", + ["Credit Card"] = "j_credit_card", + ["Delayed Gratification"] = "j_delayed_grat", + ["Devious Joker"] = "j_devious", + ["Diet Cola"] = "j_diet_cola", + ["DNA"] = "j_dna", + ["Driver's License"] = "j_drivers_license", + ["Droll Joker"] = "j_droll", + ["Drunkard"] = "j_drunkard", + ["Dusk"] = "j_dusk", + ["Egg"] = "j_egg", + ["Erosion"] = "j_erosion", + ["Even Steven"] = "j_even_steven", + ["Faceless Joker"] = "j_faceless", + ["Fibonacci"] = "j_fibonacci", + ["Flash Card"] = "j_flash", + ["Flower Pot"] = "j_flower_pot", + ["Fortune Teller"] = "j_fortune_teller", + ["Four Fingers"] = "j_four_fingers", + ["Gift Card"] = "j_gift", + ["Glass Joker"] = "j_glass", + ["Gluttonous Joker"] = "j_gluttenous_joker", + ["Golden Joker"] = "j_golden", + ["Golden Ticket"] = "j_ticket", + ["Green Joker"] = "j_green_joker", + ["Greedy Joker"] = "j_greedy_joker", + ["Gros Michel"] = "j_gros_michel", + ["Hack"] = "j_hack", + ["Half Joker"] = "j_half", + ["Hallucination"] = "j_hallucination", + ["Hanging Chad"] = "j_hanging_chad", + ["Hiker"] = "j_hiker", + ["Hit the Road"] = "j_hit_the_road", + ["Hologram"] = "j_hologram", + ["Ice Cream"] = "j_ice_cream", + ["Invisible Joker"] = "j_invisible", + ["Joker"] = "j_joker", + ["Joker Stencil"] = "j_stencil", + ["Jolly Joker"] = "j_jolly", + ["Juggler"] = "j_juggler", + ["Luchador"] = "j_luchador", + ["Lucky Cat"] = "j_lucky_cat", + ["Lusty Joker"] = "j_lusty_joker", + ["Mad Joker"] = "j_mad", + ["Madness"] = "j_madness", + ["Mail-In Rebate"] = "j_mail", + ["Marble Joker"] = "j_marble", + ["Matador"] = "j_matador", + ["Merry Andy"] = "j_merry_andy", + ["Midas Mask"] = "j_midas_mask", + ["Mime"] = "j_mime", + ["Misprint"] = "j_misprint", + ["Mr. Bones"] = "j_mr_bones", + ["Mystic Summit"] = "j_mystic_summit", + ["Obelisk"] = "j_obelisk", + ["Odd Todd"] = "j_odd_todd", + ["Onyx Agate"] = "j_onyx_agate", + ["Oops! All 6s"] = "j_oops", + ["Pareidolia"] = "j_pareidolia", + ["Perkeo"] = "j_perkeo", + ["Photograph"] = "j_photograph", + ["Popcorn"] = "j_popcorn", + ["Raised Fist"] = "j_raised_fist", + ["Ramen"] = "j_ramen", + ["Red Card"] = "j_red_card", + ["Reserved Parking"] = "j_reserved_parking", + ["Ride the Bus"] = "j_ride_the_bus", + ["Riff-raff"] = "j_riff_raff", + ["Rocket"] = "j_rocket", + ["Rough Gem"] = "j_rough_gem", + ["Runner"] = "j_runner", + ["Satellite"] = "j_satellite", + ["Scary Face"] = "j_scary_face", + ["Scholar"] = "j_scholar", + ["Seance"] = "j_seance", + ["Seeing Double"] = "j_seeing_double", + ["Seltzer"] = "j_selzer", + ["Shoot the Moon"] = "j_shoot_the_moon", + ["Shortcut"] = "j_shortcut", + ["Showman"] = "j_ring_master", + ["Sixth Sense"] = "j_sixth_sense", + ["Sly Joker"] = "j_sly", + ["Smeared Joker"] = "j_smeared", + ["Smiley Face"] = "j_smiley", + ["Sock and Buskin"] = "j_sock_and_buskin", + ["Space Joker"] = "j_space", + ["Spare Trousers"] = "j_trousers", + ["Splash"] = "j_splash", + ["Square Joker"] = "j_square", + ["Steel Joker"] = "j_steel_joker", + ["Stone Joker"] = "j_stone", + ["Stuntman"] = "j_stuntman", + ["Supernova"] = "j_supernova", + ["Superposition"] = "j_superposition", + ["Swashbuckler"] = "j_swashbuckler", + ["The Duo"] = "j_duo", + ["The Family"] = "j_family", + ["The Idol"] = "j_idol", + ["The Order"] = "j_order", + ["The Tribe"] = "j_tribe", + ["The Trio"] = "j_trio", + ["Throwback"] = "j_throwback", + ["To Do List"] = "j_todo_list", + ["To the Moon"] = "j_to_the_moon", + ["Trading Card"] = "j_trading", + ["Triboulet"] = "j_triboulet", + ["Troubadour"] = "j_troubadour", + ["Turtle Bean"] = "j_turtle_bean", + ["Vagabond"] = "j_vagabond", + ["Vampire"] = "j_vampire", + ["Walkie Talkie"] = "j_walkie_talkie", + ["Wee Joker"] = "j_wee", + ["Wily Joker"] = "j_wily", + ["Wrathful Joker"] = "j_wrathful_joker", + ["Yorick"] = "j_yorick", + ["Zany Joker"] = "j_zany", +} Brainstorm.seedsPerFrame = { ["500"] = 500, ["750"] = 750, ["1000"] = 1000, } +Brainstorm.SearchJokerLocationList = { + ["In Any Location"] = "any", + ["In Any Buffoon Pack"] = "pack", + ["In Shop Slots"] = "shop", +} + local searchTagKeys = {"None", "Charm Tag", "Double Tag", "Uncommon Tag", "Rare Tag", "Holographic Tag", "Foil Tag", "Polychrome Tag", "Investment Tag", "Voucher Tag", "Boss Tag", "Juggle Tag", "Coupon Tag", "Economy Tag", "Skip Tag", "D6 Tag"} local searchPackKeys = {"None", "Arcana", "Celestial", "Standard", "Buffoon", "Spectral", "Normal Arcana", "Jumbo Arcana", "Mega Arcana", "Normal Celestial", "Jumbo Celestial", "Mega Celestial", "Normal Standard", "Jumbo Standard", "Mega Standard", "Normal Buffoon", "Jumbo Buffoon", "Mega Buffoon", "Normal Spectral", "Jumbo Spectral", "Mega Spectral"} +local searchJokerKeys = {"None", "8 Ball", "Abstract Joker", "Acrobat", "Ancient Joker", "Arrowhead", "Astronomer", "Banner", "Baron", "Baseball Card", "Blackboard", "Bloodstone", "Blue Joker", "Blueprint", "Bootstraps", "Brainstorm", "Bull", "Burglar", "Burnt Joker", "Business Card", "Caino", "Campfire", "Card Sharp", "Cartomancer", "Castle", "Cavendish", "Ceremonial Dagger", "Certificate", "Chaos the Clown", "Chicot", "Clever Joker", "Cloud 9", "Constellation", "Crafty Joker", "Crazy Joker", "Credit Card", "Delayed Gratification", "Devious Joker", "Diet Cola", "DNA", "Driver's License", "Droll Joker", "Drunkard", "Dusk", "Egg", "Erosion", "Even Steven", "Faceless Joker", "Fibonacci", "Flash Card", "Flower Pot", "Fortune Teller", "Four Fingers", "Gift Card", "Glass Joker", "Gluttonous Joker", "Golden Joker", "Golden Ticket", "Green Joker", "Greedy Joker", "Gros Michel", "Hack", "Half Joker", "Hallucination", "Hanging Chad", "Hiker", "Hit the Road", "Hologram", "Ice Cream", "Invisible Joker", "Joker", "Joker Stencil", "Jolly Joker", "Juggler", "Luchador", "Lucky Cat", "Lusty Joker", "Mad Joker", "Madness", "Mail-In Rebate", "Marble Joker", "Matador", "Merry Andy", "Midas Mask", "Mime", "Misprint", "Mr. Bones", "Mystic Summit", "Obelisk", "Odd Todd", "Onyx Agate", "Oops! All 6s", "Pareidolia", "Perkeo", "Photograph", "Popcorn", "Raised Fist", "Ramen", "Red Card", "Reserved Parking", "Ride the Bus", "Riff-raff", "Rocket", "Rough Gem", "Runner", "Satellite", "Scary Face", "Scholar", "Seance", "Seeing Double", "Seltzer", "Shoot the Moon", "Shortcut", "Showman", "Sixth Sense", "Sly Joker", "Smeared Joker", "Smiley Face", "Sock and Buskin", "Space Joker", "Spare Trousers", "Splash", "Square Joker", "Steel Joker", "Stone Joker", "Stuntman", "Supernova", "Superposition", "Swashbuckler", "The Duo", "The Family", "The Idol", "The Order", "The Tribe", "The Trio", "Throwback", "To Do List", "To the Moon", "Trading Card", "Triboulet", "Troubadour", "Turtle Bean", "Vagabond", "Vampire", "Walkie Talkie", "Wee Joker", "Wily Joker", "Wrathful Joker", "Yorick", "Zany Joker"} +local searchJokerLocationKeys = {"In Any Location", "In Any Buffoon Pack", "In Shop Slots"} local seedsPerFrame = {"500", "750", "1000"} -- print(Brainstorm.FUNCS.inspect(searchTagKeys)) @@ -99,6 +260,22 @@ function create_tabs(args) opt_callback = "change_search_pack", current_option = Brainstorm.SETTINGS.autoreroll.searchPackID or 1, }), + create_option_cycle({ + label = "AutoReroll Search Joker", + scale = 0.8, + w = 4, + options = searchJokerKeys, + opt_callback = "change_search_joker", + current_option = Brainstorm.SETTINGS.autoreroll.searchJokerID or 1, + }), + create_option_cycle({ + label = "Search Joker Location", + scale = 0.8, + w = 4, + options = searchJokerLocationKeys, + opt_callback = "change_search_joker_location", + current_option = Brainstorm.SETTINGS.autoreroll.searchJokerLocationID or 1, + }), create_option_cycle({ label = "Charm Tag/Arcana Pack: Number of Souls", scale = 0.8, diff --git a/Brainstorm_reroll.lua b/Brainstorm_reroll.lua index b2e7d6e..a871019 100644 --- a/Brainstorm_reroll.lua +++ b/Brainstorm_reroll.lua @@ -15,6 +15,18 @@ G.FUNCS.change_search_pack = function(x) nativefs.write(lovely.mod_dir .. "/Brainstorm/settings.lua", STR_PACK(Brainstorm.SETTINGS)) end +G.FUNCS.change_search_joker = function(x) + Brainstorm.SETTINGS.autoreroll.searchJokerID = x.to_key + Brainstorm.SETTINGS.autoreroll.searchJoker = Brainstorm.SearchJokerList[x.to_val] + nativefs.write(lovely.mod_dir .. "/Brainstorm/settings.lua", STR_PACK(Brainstorm.SETTINGS)) +end + +G.FUNCS.change_search_joker_location = function(x) + Brainstorm.SETTINGS.autoreroll.searchJokerLocationID = x.to_key + Brainstorm.SETTINGS.autoreroll.searchJokerLocation = Brainstorm.SearchJokerLocationList[x.to_val] + nativefs.write(lovely.mod_dir .. "/Brainstorm/settings.lua", STR_PACK(Brainstorm.SETTINGS)) +end + G.FUNCS.change_search_soul_count = function(x) Brainstorm.SETTINGS.autoreroll.searchForSoul = x.to_val nativefs.write(lovely.mod_dir .. "/Brainstorm/settings.lua", STR_PACK(Brainstorm.SETTINGS)) @@ -55,6 +67,10 @@ function Brainstorm.auto_reroll() -- This part is meant to mimic how Balatro rerolls for Gold Stake local extra_num = -0.561892350821 local seed_found = nil + + if Brainstorm.SETTINGS.debug_mode and Brainstorm.SETTINGS.autoreroll.searchJoker and Brainstorm.SETTINGS.autoreroll.searchJoker ~= "" then + sendDebugMessage("[Brainstorm] AUTO-REROLL ACTIVE - Searching for joker: " .. Brainstorm.SETTINGS.autoreroll.searchJoker) + end while not seed_found and rerollsThisFrame < Brainstorm.SETTINGS.autoreroll.seedsPerFrame do rerollsThisFrame = rerollsThisFrame + 1 extra_num = extra_num + 0.561892350821 @@ -89,7 +105,87 @@ function Brainstorm.auto_reroll() end end end - if seed_found and Brainstorm.SETTINGS.autoreroll.searchPack and #Brainstorm.SETTINGS.autoreroll.searchPack > 0 then + -- Check for joker search (works independently or with pack search) + if seed_found and Brainstorm.SETTINGS.autoreroll.searchJoker and Brainstorm.SETTINGS.autoreroll.searchJoker ~= "" then + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Checking seed: " .. seed_found .. " for joker: " .. Brainstorm.SETTINGS.autoreroll.searchJoker) + end + local joker_found = false + local location = Brainstorm.SETTINGS.autoreroll.searchJokerLocation or "any" + + -- Check shop slots if location is "shop" or "any" + if location == "shop" or location == "any" then + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Checking shop slots...") + end + if simulate_shop_jokers(seed_found) then + joker_found = true + end + end + + -- Check buffoon packs if location is "pack" or "any" (and not already found) + if not joker_found and (location == "pack" or location == "any") then + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Checking buffoon packs...") + end + -- Check both shop pack slots for buffoon packs + for slot = 1, 2 do + local slot_cume, slot_it, slot_center = 0, 0, nil + for k, v in ipairs(G.P_CENTER_POOLS['Booster']) do + if (not _type or _type == v.kind) then slot_cume = slot_cume + (v.weight or 1) end + end + local slot_poll = pseudorandom(Brainstorm.pseudoseed("shop_pack"..slot..seed_found))*slot_cume + for k, v in ipairs(G.P_CENTER_POOLS['Booster']) do + if not _type or _type == v.kind then slot_it = slot_it + (v.weight or 1) end + if slot_it >= slot_poll and slot_it - (v.weight or 1) <= slot_poll then + slot_center = v + break + end + end + -- If this slot has a buffoon pack, check for the joker + if slot_center then + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Slot " .. slot .. " pack: " .. slot_center.key) + end + if string.find(slot_center.key, "buffoon") then + -- If pack search is active, verify this is the right pack type + local pack_type_matches = true + if Brainstorm.SETTINGS.autoreroll.searchPack and #Brainstorm.SETTINGS.autoreroll.searchPack > 0 then + pack_type_matches = false + for i = 1, #Brainstorm.SETTINGS.autoreroll.searchPack do + if Brainstorm.SETTINGS.autoreroll.searchPack[i] == slot_center.key then + pack_type_matches = true + break + end + end + end + + if pack_type_matches then + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Found buffoon pack, simulating...") + end + if simulate_buffoon_pack_jokers(slot_center.key, seed_found) then + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] *** JOKER FOUND! ***") + end + joker_found = true + break -- Early exit once joker is found + else + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Joker not in this pack") + end + end + end + end + end + end + end + + if not joker_found then + seed_found = nil + end + elseif seed_found and Brainstorm.SETTINGS.autoreroll.searchPack and #Brainstorm.SETTINGS.autoreroll.searchPack > 0 then + -- Pack-only search (no joker specified) local cume, it, center = 0, 0, nil for k, v in ipairs(G.P_CENTER_POOLS['Booster']) do if (not _type or _type == v.kind) then cume = cume + (v.weight or 1 ) end @@ -177,6 +273,184 @@ function wait(seconds) end end +function simulate_buffoon_pack_jokers(pack_key, predict_seed) + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] simulate_buffoon_pack_jokers called with pack: " .. pack_key .. ", seed: " .. (predict_seed or "nil")) + end + + -- Determine joker count based on pack type + local joker_count = 2 -- Default for Normal Buffoon + if string.find(pack_key, "jumbo") then + joker_count = 4 -- Jumbo Buffoon: 4 jokers, pick 1 + elseif string.find(pack_key, "mega") then + joker_count = 4 -- Mega Buffoon: 4 jokers, pick 2 + end + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Simulating " .. joker_count .. " jokers") + end + + -- Initialize a temporary RNG state for this simulation + -- This mimics how Balatro's G.GAME.pseudorandom works but for prediction + local temp_random_state = {} + + -- Simulate each joker slot in the pack + -- Note: Jokers within packs use 'buf' as key_append, with ante 1 for first shop + -- IMPORTANT: In Balatro, calling pseudoseed with the same key multiple times + -- returns different values because it maintains and advances state for each key + for i = 1, joker_count do + -- Determine rarity using Balatro's algorithm + -- Seed pattern: 'rarity' + ante + 'buf' (ante = 1 for first shop) + -- We need to simulate state advancement, so we'll use a helper that tracks calls + local rarity_key = "rarity1buf" + if not temp_random_state[rarity_key] then + temp_random_state[rarity_key] = pseudohash(rarity_key .. (predict_seed or '')) + end + temp_random_state[rarity_key] = math.abs(tonumber(string.format("%.13f", (2.134453429141 + temp_random_state[rarity_key] * 1.72431234) % 1))) + local rarity_seed_value = (temp_random_state[rarity_key] + (pseudohash(predict_seed) or 0)) / 2 + local rarity_roll = pseudorandom(rarity_seed_value) + + local rarity = 1 -- Common + local rarity_name = "Common" + if rarity_roll > 0.95 then + rarity = 3 -- Rare + rarity_name = "Rare" + elseif rarity_roll > 0.7 then + rarity = 2 -- Uncommon + rarity_name = "Uncommon" + end + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Joker #" .. i .. " rarity roll: " .. rarity_roll .. " -> " .. rarity_name) + end + + -- Select joker from the rarity pool + -- Seed pattern: 'Joker' + rarity + 'buf' + ante + local joker_key = "Joker" .. rarity .. "buf1" + if not temp_random_state[joker_key] then + temp_random_state[joker_key] = pseudohash(joker_key .. (predict_seed or '')) + end + temp_random_state[joker_key] = math.abs(tonumber(string.format("%.13f", (2.134453429141 + temp_random_state[joker_key] * 1.72431234) % 1))) + local joker_seed_value = (temp_random_state[joker_key] + (pseudohash(predict_seed) or 0)) / 2 + local joker_center = pseudorandom_element(G.P_JOKER_RARITY_POOLS[rarity], joker_seed_value) + + -- Check if this is the joker we're searching for + if joker_center then + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Generated: " .. joker_center.key .. " (" .. (joker_center.name or "unknown") .. ")") + end + if joker_center.key == Brainstorm.SETTINGS.autoreroll.searchJoker then + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] *** MATCH! ***") + end + return true + end + else + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] ERROR: Failed to generate joker") + end + end + end + + return false +end + +function simulate_shop_jokers(predict_seed) + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] simulate_shop_jokers called with seed: " .. (predict_seed or "nil")) + end + + -- Shop has exactly 2 joker slots (joker_max = 2) + local shop_slots = 2 + + -- Initialize a temporary RNG state for this simulation + local temp_random_state = {} + + -- Simulate each shop slot + for i = 1, shop_slots do + -- First, determine what type of card this slot gets (Joker, Tarot, Planet, etc.) + -- Seed pattern: 'cdt' + ante + local type_key = "cdt1" + if not temp_random_state[type_key] then + temp_random_state[type_key] = pseudohash(type_key .. (predict_seed or '')) + end + temp_random_state[type_key] = math.abs(tonumber(string.format("%.13f", (2.134453429141 + temp_random_state[type_key] * 1.72431234) % 1))) + local type_seed_value = (temp_random_state[type_key] + (pseudohash(predict_seed) or 0)) / 2 + local type_poll = pseudorandom(type_seed_value) + + -- Determine rates (default values from base game) + local joker_rate = 20 + local tarot_rate = 4 + local planet_rate = 4 + local playing_card_rate = 4 + local spectral_rate = 0 + local total_rate = joker_rate + tarot_rate + planet_rate + playing_card_rate + spectral_rate + + -- Check if this slot generates a Joker + local polled_rate = type_poll * total_rate + if polled_rate <= joker_rate then + -- This slot generates a Joker! Now determine which one + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Shop slot #" .. i .. " generates a Joker") + end + + -- Determine rarity using 'sho' key_append + -- Seed pattern: 'rarity' + ante + 'sho' + local rarity_key = "rarity1sho" + if not temp_random_state[rarity_key] then + temp_random_state[rarity_key] = pseudohash(rarity_key .. (predict_seed or '')) + end + temp_random_state[rarity_key] = math.abs(tonumber(string.format("%.13f", (2.134453429141 + temp_random_state[rarity_key] * 1.72431234) % 1))) + local rarity_seed_value = (temp_random_state[rarity_key] + (pseudohash(predict_seed) or 0)) / 2 + local rarity_roll = pseudorandom(rarity_seed_value) + + local rarity = 1 -- Common + local rarity_name = "Common" + if rarity_roll > 0.95 then + rarity = 3 -- Rare + rarity_name = "Rare" + elseif rarity_roll > 0.7 then + rarity = 2 -- Uncommon + rarity_name = "Uncommon" + end + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Rarity roll: " .. rarity_roll .. " -> " .. rarity_name) + end + + -- Select joker from the rarity pool + -- Seed pattern: 'Joker' + rarity + 'sho' + ante + local joker_key = "Joker" .. rarity .. "sho1" + if not temp_random_state[joker_key] then + temp_random_state[joker_key] = pseudohash(joker_key .. (predict_seed or '')) + end + temp_random_state[joker_key] = math.abs(tonumber(string.format("%.13f", (2.134453429141 + temp_random_state[joker_key] * 1.72431234) % 1))) + local joker_seed_value = (temp_random_state[joker_key] + (pseudohash(predict_seed) or 0)) / 2 + local joker_center = pseudorandom_element(G.P_JOKER_RARITY_POOLS[rarity], joker_seed_value) + + -- Check if this is the joker we're searching for + if joker_center then + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Generated: " .. joker_center.key .. " (" .. (joker_center.name or "unknown") .. ")") + end + if joker_center.key == Brainstorm.SETTINGS.autoreroll.searchJoker then + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] *** MATCH! ***") + end + return true + end + else + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] ERROR: Failed to generate joker") + end + end + else + if Brainstorm.SETTINGS.debug_mode then + sendDebugMessage("[Brainstorm] Shop slot #" .. i .. " generates non-Joker (type_poll: " .. polled_rate .. ")") + end + end + end + + return false +end + function Brainstorm.pseudoseed(key, predict_seed) if key == "seed" then return math.random()