diff --git a/functions/pokefunctions.lua b/functions/pokefunctions.lua index 68ed268c..19da9600 100644 --- a/functions/pokefunctions.lua +++ b/functions/pokefunctions.lua @@ -35,8 +35,73 @@ find_pokemon_type = function(target_type, exclude_card, exclude_name) return found end +quantum_type_check = function(card, target_type) + if not card then return false end + + local card_type = get_type(card) + local groups = {} + + -- collect all quantum groups + for _, joker in ipairs(G.jokers.cards) do + if joker:has_attribute("quantum_types") then + local targets = joker.ability.extra.targets or {} + local group = {} + + for _, t in ipairs(targets) do + group[t.type] = true + end + + table.insert(groups, group) + end + end + + -- merge overlapping groups + local changed = true + while changed do + changed = false + + for i = #groups, 1, -1 do + for j = i - 1, 1, -1 do + local overlap = false + + for k in pairs(groups[i]) do + if groups[j][k] then + overlap = true + break + end + end + + if overlap then + for k in pairs(groups[i]) do + groups[j][k] = true + end + + table.remove(groups, i) + changed = true + break + end + end + end + end + + -- check merged groups + for _, group in ipairs(groups) do + if group[target_type] + and group[card_type] + and target_type ~= card_type + then + return true + end + end + + return false +end + is_type = function(card, target_type) - return card and get_type(card) == target_type + return card and ( + get_type(card) == target_type + or quantum_type_check(card, target_type) + ) end get_type = function(card) diff --git a/localization/en-us.lua b/localization/en-us.lua index 732c6ecc..11402ec8 100644 --- a/localization/en-us.lua +++ b/localization/en-us.lua @@ -2106,7 +2106,7 @@ return { "{C:attention}Ancient #1#s{}", "{X:attention,C:white}1+{} : Create a {C:tarot}Tarot{} card", "{X:attention,C:white}2+{} : Earn {C:money}$#2#{}", - "{X:attention,C:white}3+{} : Create a {C:item}Item{} card", + "{X:attention,C:white}3+{} : Create an {C:item}Item{} card", "{C:inactive,s:0.8}(Must have room)", "{X:attention,C:white}4+{} : Create a {C:attention}Tag{} once per round{C:inactive}#3#{}", } @@ -3842,7 +3842,7 @@ return { name = "Baltoy", text = { "discarded {C:attention}Hazard{} card", - "{C:inactive}(Evolves at {C:chips}+#1#{C:inactive} / #3# Chips", + "{C:inactive}(Evolves at {C:chips}+#1#{C:inactive} / #3# Chips)", } }, j_poke_claydol = { @@ -5479,6 +5479,28 @@ return { "{C:inactive}(Currently {X:mult,C:white} X#1# {C:inactive} Mult)", } }, + j_poke_shroodle = { + name = 'Shroodle', + text = { + "{C:attention}Nature:{} {B:1,V:4}#1#{}, {B:2,V:5}#2#{}, {B:3,V:6}#3#{}", + "{br:3}text", + "When {C:attention}Boss Blind{} is defeated", + "create a {C:attention}random{} tag", + "{C:inactive,s:0.8}(Evolves after triggering {C:attention,s:0.8}#4#{C:inactive,s:0.8} tags){}" + } + }, + j_poke_grafaiai = { + name = 'Grafaiai', + text = { + "{C:attention}Nature:{} {B:1,V:4}#1#{}, {B:2,V:5}#2#{}, {B:3,V:6}#3#{}", + "Jokers with a {C:attention}Nature{} type also", + "count as the other {C:attention}Nature{} Types", + "{br:3}text", + "When {C:attention}Boss Blind{} is defeated, create the", + "last {C:attention}tag{} used during this run", + "{C:inactive}(Last used: #4#){}" + } + }, j_poke_bramblin = { name = "Bramblin", text = { diff --git a/pokemon/pokejokers_32.lua b/pokemon/pokejokers_32.lua index c1dc373c..00589dd2 100644 --- a/pokemon/pokejokers_32.lua +++ b/pokemon/pokejokers_32.lua @@ -158,7 +158,199 @@ local ceruledge={ -- Maschiff 942 -- Mabosstiff 943 -- Shroodle 944 +local shroodle = { + name = "shroodle", + config = {extra = {targets = {{type = "Grass"}, {type = "Fire"}, {type = "Water"}}, count = 0}, evo_rqmt = 3}, + loc_vars = function(self, info_queue, card) + type_tooltip(self, info_queue, card) + local abbr = card.ability.extra + local vars = {} + local colours = {} + for i = 1, #abbr.targets do + vars[i] = abbr.targets[i].type + colours[i] = G.ARGS.LOC_COLOURS[string.lower(abbr.targets[i].type)] or G.C.UI.TEXT_INACTIVE + colours[i + #abbr.targets] = (abbr.targets[i].type == 'Lightning' and G.C.BLACK or G.C.WHITE) + end + vars[(1+#abbr.targets)] = math.max(0, (self.config.evo_rqmt - card.ability.extra.count)) + vars.colours = colours + + return {vars = vars} + end, + designer = "Sonfive", + rarity = 2, + cost = 6, + stage = "Basic", + ptype = "Dark", + gen = 9, + blueprint_compat = true, + + calculate = function(self, card, context) + if context.tag_triggered then + card.ability.extra.count = card.ability.extra.count + 1 + end + if (context.end_of_round and G.GAME.blind.boss) and not context.repetition and not context.individual then + G.E_MANAGER:add_event(Event({ + func = (function() + local tags = {} + for k, v in pairs(G.P_TAGS) do + if v.key ~= "tag_boss" then + tags[#tags + 1] = v + end + end + local temp_tag = pseudorandom_element(tags, pseudoseed('shroodle')) + local tag = Tag(temp_tag.key) + if tag.key == "tag_orbital" then + local _poker_hands = {} + for k, v in pairs(G.GAME.hands) do + if v.visible then + _poker_hands[#_poker_hands + 1] = k + end + end + tag.ability.orbital_hand = pseudorandom_element(_poker_hands, pseudoseed('shroodle')) + end + add_tag(tag) + play_sound('generic1', 0.9 + math.random()*0.1, 0.8) + play_sound('holo1', 1.2 + math.random()*0.1, 0.4) + return true + end) + })) + end + return scaling_evo(self, card, context, "j_poke_grafaiai", card.ability.extra.count, self.config.evo_rqmt) + end, + set_ability = function(self, card, initial, delay_sprites) + if initial then + self:set_nature(card) + end + end, + set_nature = function(self, card) + local targets = card.ability.extra.targets or {} + local total = #targets + local replace_count = math.min(3, total) + local start_index = total - replace_count + 1 + + local new_targets = {} + local used = {} + + -- mark existing (untouched) targets as used + for i = 1, start_index - 1 do + new_targets[i] = targets[i] + used[targets[i].type] = true + end + + -- build available pool excluding used types + local pool = {} + for _, t in ipairs(POKE_TYPES) do + if not used[t] then + table.insert(pool, t) + end + end + + -- replace last N targets without duplicates + for i = start_index, total do + if #pool == 0 then break end + + local choice = pseudorandom_element(pool, pseudoseed("shroodle_" .. i)) + new_targets[i] = { type = choice } + + for j, v in ipairs(pool) do + if v == choice then + table.remove(pool, j) + break + end + end + end + + card.ability.extra.targets = new_targets + end, +} -- Grafaiai 945 +local grafaiai = { + name = "grafaiai", + config = {extra = {targets = {{type = "Grass"}, {type = "Fire"}, {type = "Water"}}}}, + loc_vars = function(self, info_queue, card) + type_tooltip(self, info_queue, card) + local abbr = card.ability.extra + local vars = {} + local colours = {} + for i = 1, #abbr.targets do + vars[i] = abbr.targets[i].type + colours[i] = G.ARGS.LOC_COLOURS[string.lower(abbr.targets[i].type)] or G.C.UI.TEXT_INACTIVE + colours[i + #abbr.targets] = (abbr.targets[i].type == 'Lightning' and G.C.BLACK or G.C.WHITE) + end + vars[(1+#abbr.targets)] = G.GAME.last_tag and localize{type = 'name_text', key = G.GAME.last_tag, set = 'Tag'} or localize('k_none') + vars.colours = colours + + return {vars = vars} + end, + designer = "Sonfive", + rarity = "poke_safari", + cost = 6, + stage = "One", + ptype = "Dark", + gen = 9, + blueprint_compat = true, + + calculate = function(self, card, context) + if (context.end_of_round and G.GAME.blind.boss) and not context.repetition and not context.individual then + if G.GAME.last_tag then + G.E_MANAGER:add_event(Event({ + func = (function() + add_tag(Tag(G.GAME.last_tag)) + play_sound('generic1', 0.9 + math.random()*0.1, 0.8) + play_sound('holo1', 1.2 + math.random()*0.1, 0.4) + return true + end) + })) + end + end + end, + set_ability = function(self, card, initial, delay_sprites) + if initial then + self:set_nature(card) + end + end, + set_nature = function(self, card) + local targets = card.ability.extra.targets or {} + local total = #targets + local replace_count = math.min(3, total) + local start_index = total - replace_count + 1 + + local new_targets = {} + local used = {} + + -- mark existing (untouched) targets as used + for i = 1, start_index - 1 do + new_targets[i] = targets[i] + used[targets[i].type] = true + end + + -- build available pool excluding used types + local pool = {} + for _, t in ipairs(POKE_TYPES) do + if not used[t] then + table.insert(pool, t) + end + end + + -- replace last N targets without duplicates + for i = start_index, total do + if #pool == 0 then break end + + local choice = pseudorandom_element(pool, pseudoseed("shroodle_" .. i)) + new_targets[i] = { type = choice } + + for j, v in ipairs(pool) do + if v == choice then + table.remove(pool, j) + break + end + end + end + + card.ability.extra.targets = new_targets + end, +attributes = {"quantum_types"}, +} -- Bramblin 946 local bramblin={ name = "bramblin", @@ -484,5 +676,5 @@ local wiglett={ attributes = {"mult", "chips", "hand_type", "rank", "five", "six", "seven", "round_evo"}, } return {name = "Pokemon Jokers 931-960", - list = {charcadet, armarouge, ceruledge, bramblin, brambleghast, tinkatink, tinkatuff, tinkaton, wiglett}, + list = {charcadet, armarouge, ceruledge, shroodle, grafaiai, bramblin, brambleghast, tinkatink, tinkatuff, tinkaton, wiglett}, } diff --git a/pokermon.lua b/pokermon.lua index 5f911e43..600a5195 100644 --- a/pokermon.lua +++ b/pokermon.lua @@ -91,6 +91,7 @@ if SMODS.Attribute then SMODS.Attribute { key = "hazards" } SMODS.Attribute { key = "applies" } SMODS.Attribute { key = "drain" } + SMODS.Attribute { key = "quantum_types" } end --Load helper function files @@ -299,12 +300,13 @@ function SMODS.current_mod.calculate(self, context) end end --Garbodor - if context.end_of_round and context.game_over == false and context.main_eval and context.beat_boss == true then - G.GAME.poke_ante_discards_used = 0 - end if context.pre_discard and not context.hook then G.GAME.poke_ante_discards_used = (G.GAME.poke_ante_discards_used or 0) + 1 end + --Grafaiai + if context.tag_triggered then + G.GAME.last_tag = context.tag_triggered.key + end end local old_end = end_round