diff --git a/lovely/dump/back.lua b/lovely/dump/back.lua deleted file mode 100644 index 997b2bc..0000000 --- a/lovely/dump/back.lua +++ /dev/null @@ -1,321 +0,0 @@ -LOVELY_INTEGRITY = 'd3c881055f5938773f6b44e7c8b207117963612b2eaf889f5b7ef8b61e1143cd' - ---Class -Back = Object:extend() - ---Class Methods -function Back:init(selected_back) - if not selected_back then selected_back = G.P_CENTERS.b_red end - self.atlas = selected_back.unlocked and selected_back.atlas or nil - self.name = selected_back.name or 'Red Deck' - - self.effect = { - center = selected_back, - text_UI = '', - config = copy_table(selected_back.config) - } - self.loc_name = localize{type = 'name_text', set = 'Back', key = self.effect.center.key} - - local pos = (self.effect.center.unlocked and self.effect.center.pos) or {x = 4, y = 0} - self.pos = self.pos or {} - self.pos.x = pos.x - self.pos.y = pos.y -end - -function Back:get_name() - if self.effect.center.unlocked then return self.loc_name else return localize('k_locked') end -end - -function Back:generate_UI(other, ui_scale, min_dims, challenge) - min_dims = min_dims or 0.7 - ui_scale = ui_scale or 0.9 - local back_config = other or self.effect.center - local name_to_check = other and other.name or self.name - local effect_config = other and other.config or self.effect.config - challenge = G.CHALLENGES[get_challenge_int_from_id(challenge or '') or ''] or {name = 'ERROR'} - - local loc_args, loc_nodes = nil, {} - - if not back_config.unlocked then - local localized_by_smods - local key_override - if back_config.locked_loc_vars and type(back_config.locked_loc_vars) == 'function' then - local res = back_config:locked_loc_vars() or {} - loc_args = res.vars or {} - key_override = res.key - end - if G.localization.descriptions.Back[key_override or back_config.key].unlock_parsed then - localize{type = 'unlocks', key = key_override or back_config.key, set = 'Back', nodes = loc_nodes, vars = loc_args} - localized_by_smods = true - end - if not back_config.unlock_condition then - if not localized_by_smods then - localize{type = 'descriptions', key = 'demo_locked', set = "Other", nodes = loc_nodes, vars = loc_args} - end - elseif back_config.unlock_condition.type == 'win_deck' then - local other_name = localize('k_unknown') - if G.P_CENTERS[back_config.unlock_condition.deck].unlocked then - other_name = localize{type = 'name_text', set = 'Back', key = back_config.unlock_condition.deck} - end - loc_args = loc_args or {other_name} - localize{type = 'descriptions', key = 'deck_locked_win', set = "Other", nodes = loc_nodes, vars = loc_args} - elseif back_config.unlock_condition.type == 'discover_amount' then - loc_args = loc_args or {tostring(back_config.unlock_condition.amount)} - localize{type = 'descriptions', key = 'deck_locked_discover', set = "Other", nodes = loc_nodes, vars = loc_args} - elseif back_config.unlock_condition.type == 'win_stake' then - local other_name = localize{type = 'name_text', set = 'Stake', key = G.P_CENTER_POOLS.Stake[back_config.unlock_condition.stake].key} - loc_args = loc_args or {other_name, colours = {get_stake_col(back_config.unlock_condition.stake)}} - localize{type = 'descriptions', key = 'deck_locked_stake', set = "Other", nodes = loc_nodes, vars = loc_args} - end - else - local key_override - if back_config.loc_vars and type(back_config.loc_vars) == 'function' then - local res = back_config:loc_vars() or {} - loc_args = res.vars or {} - key_override = res.key - elseif name_to_check == 'Blue Deck' then loc_args = {effect_config.hands} - elseif name_to_check == 'Red Deck' then loc_args = {effect_config.discards} - elseif name_to_check == 'Yellow Deck' then loc_args = {effect_config.dollars} - elseif name_to_check == 'Green Deck' then loc_args = {effect_config.extra_hand_bonus, effect_config.extra_discard_bonus} - elseif name_to_check == 'Black Deck' then loc_args = {effect_config.joker_slot, -effect_config.hands} - elseif name_to_check == 'Magic Deck' then loc_args = {localize{type = 'name_text', key = 'v_crystal_ball', set = 'Voucher'}, localize{type = 'name_text', key = 'c_fool', set = 'Tarot'}} - elseif name_to_check == 'Nebula Deck' then loc_args = {localize{type = 'name_text', key = 'v_telescope', set = 'Voucher'}, -1} - elseif name_to_check == 'Ghost Deck' then - elseif name_to_check == 'Abandoned Deck' then - elseif name_to_check == 'Checkered Deck' then - elseif name_to_check == 'Zodiac Deck' then loc_args = {localize{type = 'name_text', key = 'v_tarot_merchant', set = 'Voucher'}, - localize{type = 'name_text', key = 'v_planet_merchant', set = 'Voucher'}, - localize{type = 'name_text', key = 'v_overstock_norm', set = 'Voucher'}} - elseif name_to_check == 'Painted Deck' then loc_args = {effect_config.hand_size,effect_config.joker_slot} - elseif name_to_check == 'Anaglyph Deck' then loc_args = {localize{type = 'name_text', key = 'tag_double', set = 'Tag'}} - elseif name_to_check == 'Plasma Deck' then loc_args = {effect_config.ante_scaling} - elseif name_to_check == 'Erratic Deck' then - end - localize{type = 'descriptions', key = key_override or back_config.key, set = 'Back', nodes = loc_nodes, vars = loc_args} - end - - return - {n=G.UIT.ROOT, config={align = "cm", minw = min_dims*5, minh = min_dims*2.5, id = self.name, colour = G.C.CLEAR}, nodes={ - name_to_check == 'Challenge Deck' and UIBox_button({button = 'deck_view_challenge', label = {localize(challenge.id, 'challenge_names')}, minw = 2.2, minh = 1, scale = 0.6, id = challenge}) - or desc_from_rows(loc_nodes, true, min_dims*5) - }} -end - -function Back:change_to(new_back) - if not new_back then new_back = G.P_CENTERS.b_red end - self.atlas = new_back.unlocked and new_back.atlas or nil - self.name = new_back.name or 'Red Deck' - self.effect = { - center = new_back, - text_UI = '', - config = copy_table(new_back.config) - } - self.loc_name = localize{type = 'name_text', set = 'Back', key = self.effect.center.key} - local pos = self.effect.center.unlocked and copy_table(new_back.pos) or {x = 4, y = 0} - self.pos.x = pos.x - self.pos.y = pos.y -end - -function Back:save() - local backTable = { - name = self.name, - pos = self.pos, - effect = self.effect, - key = self.effect.center.key or 'b_red' - } - - return backTable -end - -function Back:trigger_effect(args) - if not args then return end - local obj = self.effect.center - if obj.trigger_effect and type(obj.trigger_effect) == 'function' then - local o = {obj:trigger_effect(args)} - if o then return unpack(o) end - end - - if self.name == 'Anaglyph Deck' and args.context == 'eval' and G.GAME.last_blind and G.GAME.last_blind.boss then - G.E_MANAGER:add_event(Event({ - func = (function() - add_tag(Tag('tag_double')) - 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 - if self.name == 'Plasma Deck' and args.context == 'blind_amount' then - return - end - - if self.name == 'Plasma Deck' and args.context == 'final_scoring_step' then - local tot = args.chips + args.mult - args.chips = math.floor(tot/2) - args.mult = math.floor(tot/2) - update_hand_text({delay = 0}, {mult = args.mult, chips = args.chips}) - - G.E_MANAGER:add_event(Event({ - func = (function() - local text = localize('k_balanced') - play_sound('gong', 0.94, 0.3) - play_sound('gong', 0.94*1.5, 0.2) - play_sound('tarot1', 1.5) - ease_colour(G.C.UI_CHIPS, {0.8, 0.45, 0.85, 1}) - ease_colour(G.C.UI_MULT, {0.8, 0.45, 0.85, 1}) - attention_text({ - scale = 1.4, text = text, hold = 2, align = 'cm', offset = {x = 0,y = -2.7},major = G.play - }) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - blocking = false, - delay = 4.3, - func = (function() - ease_colour(G.C.UI_CHIPS, G.C.BLUE, 2) - ease_colour(G.C.UI_MULT, G.C.RED, 2) - return true - end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - blocking = false, - no_delete = true, - delay = 6.3, - func = (function() - G.C.UI_CHIPS[1], G.C.UI_CHIPS[2], G.C.UI_CHIPS[3], G.C.UI_CHIPS[4] = G.C.BLUE[1], G.C.BLUE[2], G.C.BLUE[3], G.C.BLUE[4] - G.C.UI_MULT[1], G.C.UI_MULT[2], G.C.UI_MULT[3], G.C.UI_MULT[4] = G.C.RED[1], G.C.RED[2], G.C.RED[3], G.C.RED[4] - return true - end) - })) - return true - end) - })) - - delay(0.6) - return args.chips, args.mult - end -end - -function Back:apply_to_run() - local obj = self.effect.center - if obj.apply and type(obj.apply) == 'function' then - obj:apply() - end - - if self.effect.config.voucher then - G.GAME.used_vouchers[self.effect.config.voucher] = true - G.GAME.cry_owned_vouchers[self.effect.config.voucher] = true - G.GAME.starting_voucher_count = (G.GAME.starting_voucher_count or 0) + 1 - Card.apply_to_run(nil, G.P_CENTERS[self.effect.config.voucher]) - end - if self.effect.config.hands then - G.GAME.starting_params.hands = G.GAME.starting_params.hands + self.effect.config.hands - end - if self.effect.config.consumables then - delay(0.4) - G.E_MANAGER:add_event(Event({ - func = function() - for k, v in ipairs(self.effect.config.consumables) do - local card = create_card('Tarot', G.consumeables, nil, nil, nil, nil, v, 'deck') - card:add_to_deck() - G.consumeables:emplace(card) - end - return true - end - })) - end - - - if self.effect.config.dollars then - G.GAME.starting_params.dollars = G.GAME.starting_params.dollars + self.effect.config.dollars - end - if self.effect.config.remove_faces then - G.GAME.starting_params.no_faces = true - end - - if self.effect.config.spectral_rate then - G.GAME.spectral_rate = self.effect.config.spectral_rate - end - if self.effect.config.discards then - G.GAME.starting_params.discards = G.GAME.starting_params.discards + self.effect.config.discards - end - if self.effect.config.reroll_discount then - G.GAME.starting_params.reroll_cost = G.GAME.starting_params.reroll_cost - self.effect.config.reroll_discount - end - - - if self.effect.config.edition then - G.E_MANAGER:add_event(Event({ - func = function() - local i = 0 - while i < self.effect.config.edition_count do - local card = pseudorandom_element(G.playing_cards, pseudoseed('edition_deck')) - if not card.edition then - i = i + 1 - card:set_edition({[self.effect.config.edition] = true}, nil, true) - end - end - return true - end - })) - end - if self.effect.config.vouchers then - for k, v in pairs(self.effect.config.vouchers) do - G.GAME.used_vouchers[v ] = true - G.GAME.cry_owned_vouchers[v ] = true - G.GAME.starting_voucher_count = (G.GAME.starting_voucher_count or 0) + 1 - Card.apply_to_run(nil, G.P_CENTERS[v]) - end - end - if self.name == 'Checkered Deck' then - G.E_MANAGER:add_event(Event({ - func = function() - for k, v in pairs(G.playing_cards) do - if v.base.suit == 'Clubs' then - v:change_suit('Spades') - end - if v.base.suit == 'Diamonds' then - v:change_suit('Hearts') - end - end - return true - end - })) - end - if self.effect.config.randomize_rank_suit then - G.GAME.starting_params.erratic_suits_and_ranks = true - end - if self.effect.config.joker_slot then - G.GAME.starting_params.joker_slots = G.GAME.starting_params.joker_slots + self.effect.config.joker_slot - end - if self.effect.config.hand_size then - G.GAME.starting_params.hand_size = G.GAME.starting_params.hand_size + self.effect.config.hand_size - end - if self.effect.config.ante_scaling then - G.GAME.starting_params.ante_scaling = self.effect.config.ante_scaling - end - if self.effect.config.consumable_slot then - G.GAME.starting_params.consumable_slots = G.GAME.starting_params.consumable_slots + self.effect.config.consumable_slot - end - if self.effect.config.no_interest then - G.GAME.modifiers.no_interest = true - end - if self.effect.config.extra_hand_bonus then - G.GAME.modifiers.money_per_hand = self.effect.config.extra_hand_bonus - end - if self.effect.config.extra_discard_bonus then - G.GAME.modifiers.money_per_discard = self.effect.config.extra_discard_bonus - end -end - -function Back:load(backTable) - self.name = backTable.name - self.pos = backTable.pos - self.effect = backTable.effect - self.effect.center = G.P_CENTERS[backTable.key] or G.P_CENTERS.b_red - - - self.loc_name = localize{type = 'name_text', set = 'Back', key = self.effect.center.key} -end diff --git a/lovely/dump/blind.lua b/lovely/dump/blind.lua deleted file mode 100644 index 3559228..0000000 --- a/lovely/dump/blind.lua +++ /dev/null @@ -1,865 +0,0 @@ -LOVELY_INTEGRITY = 'ceaf7d365cb8eac62c7dcf3be1ef07cc6b0dac3977bde52960496d7f844a668d' - ---class -Blind = Moveable:extend() - ---class methods -function Blind:init(X, Y, W, H) - Moveable.init(self,X, Y, W, H) - - self.children = {} - self.config = {} - self.tilt_var = {mx = 0, my = 0, amt = 0} - self.ambient_tilt = 0.3 - self.chips = 0 - self.zoom = true - self.states.collide.can = true - self.colour = copy_table(G.C.BLACK) - self.dark_colour = darken(self.colour, 0.2) - self.children.animatedSprite = AnimatedSprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ANIMATION_ATLAS['blind_chips'], G.P_BLINDS.bl_small.pos) - self.children.animatedSprite.states = self.states - self.children.animatedSprite.states.visible = false - self.children.animatedSprite.states.drag.can = true - self.states.collide.can = true - self.states.drag.can = true - self.loc_debuff_lines = {'',''} - - self.shadow_height = 0 - - if getmetatable(self) == Blind then - table.insert(G.I.CARD, self) - end -end - -function Blind:change_colour(blind_col) - blind_col = blind_col or get_blind_main_colour(self.config.blind.key or '') - local dark_col = mix_colours(blind_col, G.C.BLACK, 0.4) - ease_colour(G.C.DYN_UI.MAIN, blind_col) - ease_colour(G.C.DYN_UI.DARK, dark_col) - - if not self.boss and self.name then - blind_col = darken(G.C.BLACK, 0.05) - dark_col = lighten(G.C.BLACK, 0.07) - else - dark_col = mix_colours(blind_col, G.C.BLACK, 0.2) - end - ease_colour(G.C.DYN_UI.BOSS_MAIN, blind_col) - ease_colour(G.C.DYN_UI.BOSS_DARK, dark_col) -end - -function Blind:set_text() - if self.config.blind then - if self.disabled then - self.loc_name = self.name == '' and self.name or localize{type ='name_text', key = self.config.blind.key, set = 'Blind'} - self.loc_debuff_text = '' - EMPTY(self.loc_debuff_lines) - else - local loc_vars = nil - if self.name == 'The Ox' then - loc_vars = {localize(G.GAME.current_round.most_played_poker_hand, 'poker_hands')} - end - local target = {type = 'raw_descriptions', key = self.config.blind.key, set = 'Blind', vars = loc_vars or self.config.blind.vars} - local obj = self.config.blind - if obj.loc_vars and type(obj.loc_vars) == 'function' then - local res = obj:loc_vars() or {} - target.vars = res.vars or target.vars - target.key = res.key or target.key - end - local loc_target = localize(target) - if loc_target then - self.loc_name = self.name == '' and self.name or localize{type ='name_text', key = self.config.blind.key, set = 'Blind'} - self.loc_debuff_text = '' - EMPTY(self.loc_debuff_lines) - for k, v in ipairs(loc_target) do - self.loc_debuff_text = self.loc_debuff_text..v..(k <= #loc_target and ' ' or '') - self.loc_debuff_lines[k] = v - end - else - self.loc_name = ''; self.loc_debuff_text = '' - EMPTY(self.loc_debuff_lines) - end - end - end -end - -function Blind:set_blind(blind, reset, silent) - if not reset then - if blind then - self.in_blind = true - end - self.config.blind = blind or {} - self.name = blind and blind.name or '' - self.dollars = blind and blind.dollars or 0 - self.sound_pings = self.dollars + 2 - if G.GAME.modifiers.no_blind_reward and G.GAME.modifiers.no_blind_reward[self:get_type()] then self.dollars = 0 end - self.debuff = blind and blind.debuff or {} - self.pos = blind and blind.pos - self.mult = blind and blind.mult or 0 - self.disabled = false - self.discards_sub = nil - self.hands_sub = nil - self.boss = blind and not not blind.boss - self.blind_set = false - self.triggered = nil - self.prepped = true - self:set_text() - - local obj = self.config.blind - self.children.animatedSprite.atlas = G.ANIMATION_ATLAS[obj.atlas] or G.ANIMATION_ATLAS['blind_chips'] - G.GAME.last_blind = G.GAME.last_blind or {} - G.GAME.last_blind.boss = self.boss - G.GAME.last_blind.name = self.name - - if blind and blind.name then - self:change_colour() - else - self:change_colour(G.C.BLACK) - end - - self.chips = get_blind_amount(G.GAME.round_resets.ante)*self.mult*G.GAME.starting_params.ante_scaling - self.chip_text = number_format(self.chips) - - if not blind then self.chips = 0 end - - G.GAME.current_round.dollars_to_be_earned = self.dollars > 0 and (string.rep(localize('$'), self.dollars)..'') or ('') - G.HUD_blind.alignment.offset.y = -10 - G.HUD_blind:recalculate(false) - - if blind and blind.name and blind.name ~= '' then - self:alert_debuff(true) - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.05, - blockable = false, - func = (function() - G.HUD_blind:get_UIE_by_ID("HUD_blind_name").states.visible = false - G.HUD_blind:get_UIE_by_ID("dollars_to_be_earned").parent.parent.states.visible = false - G.HUD_blind.alignment.offset.y = 0 - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.15, - blockable = false, - func = (function() - G.HUD_blind:get_UIE_by_ID("HUD_blind_name").states.visible = true - G.HUD_blind:get_UIE_by_ID("dollars_to_be_earned").parent.parent.states.visible = true - G.HUD_blind:get_UIE_by_ID("dollars_to_be_earned").config.object:pop_in(0) - G.HUD_blind:get_UIE_by_ID("HUD_blind_name").config.object:pop_in(0) - G.HUD_blind:get_UIE_by_ID("HUD_blind_count"):juice_up() - self.children.animatedSprite:set_sprite_pos(self.config.blind.pos) - self.blind_set = true - G.ROOM.jiggle = G.ROOM.jiggle + 3 - if not reset and not silent then - self:juice_up() - if blind then play_sound('chips1', math.random()*0.1 + 0.55, 0.42);play_sound('gold_seal', math.random()*0.1 + 1.85, 0.26)--play_sound('cancel') - end - end - return true - end) - })) - return true - end) - })) - end - - - self.config.h_popup_config ={align="tm", offset = {x=0,y=-0.1},parent = self} - end - - if self.name == 'The Eye' and not reset then - self.hands = { - ["Flush Five"] = false, - ["Flush House"] = false, - ["Five of a Kind"] = false, - ["Straight Flush"] = false, - ["Four of a Kind"] = false, - ["Full House"] = false, - ["Flush"] = false, - ["Straight"] = false, - ["Three of a Kind"] = false, - ["Two Pair"] = false, - ["Pair"] = false, - ["High Card"] = false, - } - end - if self.name == 'The Mouth' and not reset then - self.only_hand = false - end - if self.name == 'The Fish' and not reset then - self.prepped = nil - end - if self.name == 'The Water' and not reset then - self.discards_sub = G.GAME.current_round.discards_left - ease_discard(-self.discards_sub) - end - if self.name == 'The Needle' and not reset then - self.hands_sub = G.GAME.round_resets.hands - 1 - ease_hands_played(-self.hands_sub) - end - if self.name == 'The Manacle' and not reset then - G.hand:change_size(-1) - end - if self.name == 'Amber Acorn' and not reset and #G.jokers.cards > 0 then - G.jokers:unhighlight_all() - for k, v in ipairs(G.jokers.cards) do - v:flip() - end - if #G.jokers.cards > 1 then - G.E_MANAGER:add_event(Event({ trigger = 'after', delay = 0.2, func = function() - G.E_MANAGER:add_event(Event({ func = function() G.jokers:shuffle('aajk'); play_sound('cardSlide1', 0.85);return true end })) - delay(0.15) - G.E_MANAGER:add_event(Event({ func = function() G.jokers:shuffle('aajk'); play_sound('cardSlide1', 1.15);return true end })) - delay(0.15) - G.E_MANAGER:add_event(Event({ func = function() G.jokers:shuffle('aajk'); play_sound('cardSlide1', 1);return true end })) - delay(0.5) - return true end })) - end - end - - if not reset then - if blind then - self.in_blind = true - end - local obj = self.config.blind - if obj.set_blind and type(obj.set_blind) == 'function' then - obj:set_blind() - end - end - --add new debuffs - for _, v in ipairs(G.playing_cards) do - self:debuff_card(v) - end - for _, v in ipairs(G.jokers.cards) do - if not reset then self:debuff_card(v, true) end - end - - G.ARGS.spin.real = (G.SETTINGS.reduced_motion and 0 or 1)*(self.config.blind.boss and (self.config.blind.boss.showdown and 0.5 or 0.25) or 0) -end - -function Blind:alert_debuff(first) - if self.loc_debuff_text and self.loc_debuff_text ~= '' then - self.block_play = true - G.E_MANAGER:add_event(Event({ - blockable = false, - blocking = false, - func = (function() - if self.disabled then self.block_play = nil; return true end - if G.STATE == G.STATES.SELECTING_HAND then - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = G.SETTINGS.GAMESPEED*0.05, - blockable = false, - func = (function() - play_sound('whoosh1', 0.55, 0.62) - for i = 1, 4 do - local wait_time = (0.1*(i-1)) - G.E_MANAGER:add_event(Event({ blockable = false, trigger = 'after', delay = G.SETTINGS.GAMESPEED*wait_time, - func = function() - if i == 1 then self:juice_up() end - play_sound('cancel', 0.7 + 0.05*i, 0.7) - return true end })) - end - local hold_time = G.SETTINGS.GAMESPEED*(#self.loc_debuff_text*0.035 + 1.3) - local disp_text = self:get_loc_debuff_text() - attention_text({ - scale = 0.7, text = disp_text, maxw = 12, hold = hold_time, align = 'cm', offset = {x = 0,y = -1},major = G.play - }) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 1, - blocking = false, - blockable = false, - func = (function() - self.block_play = nil - if G.buttons then - local _buttons = G.buttons:get_UIE_by_ID('play_button') - _buttons.disable_button = nil - end - return true - end) - })) - return true - end) - })) - return true - end - end) - })) - end -end - -function Blind:get_loc_debuff_text() - local obj = self.config.blind - if obj.get_loc_debuff_text and type(obj.get_loc_debuff_text) == 'function' then - return obj:get_loc_debuff_text() - end - local disp_text = (self.config.blind.name == 'The Wheel' and G.GAME.probabilities.normal or '')..self.loc_debuff_text - if (self.config.blind.name == 'The Mouth') and self.only_hand then disp_text = disp_text..' ['..localize(self.only_hand, 'poker_hands')..']' end - return disp_text -end - -function Blind:defeat(silent) - local dissolve_time = 1.3 - local extra_time = 0 - self.dissolve = 0 - self.dissolve_colours = {G.C.BLACK, G.C.RED} - self:juice_up() - self.children.particles = Particles(0, 0, 0,0, { - timer_type = 'TOTAL', - timer = 0.01*dissolve_time, - scale = 0.1, - speed = 1.5, - lifespan = 0.7*dissolve_time, - attach = self, - colours = self.dissolve_colours, - fill = true - }) - - local blind_name_dynatext = G.HUD_blind:get_UIE_by_ID('HUD_blind_name').config.object - blind_name_dynatext:pop_out(2) - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 0.5*dissolve_time, - func = (function() self.children.particles.max = 0 return true end) - })) - if not silent then - for i = 1, math.min(self.sound_pings or 3, 7) do - extra_time = extra_time + (0.4+0.15*i)*dissolve_time - G.E_MANAGER:add_event(Event({ blockable = false, trigger = 'after', delay = (0.15 - 0.01*(self.sound_pings or 3))*i*dissolve_time, - func = function() - play_sound('cancel', 0.8 - 0.05*i, 1.7) - if i == math.min((self.sound_pings or 3)+1, 6) then play_sound('whoosh2', 0.7, 0.42) end - return true end })) - end - end - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - blockable = false, - ref_table = self, - ref_value = 'dissolve', - ease_to = 1, - delay = 0.7*dissolve_time, - func = (function(t) return t end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 0.8*dissolve_time, - func = (function() - G.HUD_blind.alignment.offset.y = -10 - return true - end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 0.95*dissolve_time, - func = (function() - self.dissolve = nil - self:set_blind(nil, nil, true) return true end) - })) - for k, v in ipairs(G.jokers.cards) do - if v.facing == 'back' then v:flip() end - end - local obj = self.config.blind - if obj.defeat and type(obj.defeat) == 'function' then - obj:defeat() - end - if self.name == 'Crimson Heart' then - for _, v in ipairs(G.jokers.cards) do - v.ability.crimson_heart_chosen = nil - end - end - if self.name == 'The Manacle' and not self.disabled then - G.hand:change_size(1) - end -end - -function Blind:get_type() - if self.name == "Small Blind" then - return 'Small' - elseif self.name == "Big Blind" then - return 'Big' - elseif self.name and self.name ~= '' then - return 'Boss' - end -end - -function Blind:disable() - self.disabled = true - for k, v in ipairs(G.jokers.cards) do - if v.facing == 'back' then v:flip() end - end - local obj = self.config.blind - if obj.disable and type(obj.disable) == 'function' then - obj:disable() - end - if self.name == 'Crimson Heart' then - for _, v in ipairs(G.jokers.cards) do - v.ability.crimson_heart_chosen = nil - end - end - if self.name == 'The Water' then - ease_discard(self.discards_sub) - end - if self.name == 'The Wheel' or self.name == 'The House' or self.name == 'The Mark' or self.name == 'The Fish' then - for i = 1, #G.hand.cards do - if G.hand.cards[i].facing == 'back' then - G.hand.cards[i]:flip() - end - end - for k, v in pairs(G.playing_cards) do - v.ability.wheel_flipped = nil - end - end - if self.name == 'The Needle' then - ease_hands_played(self.hands_sub) - end - if self.name == 'The Wall' then - self.chips = self.chips/2 - self.chip_text = number_format(self.chips) - end - if self.name == 'Cerulean Bell' then - for k, v in ipairs(G.playing_cards) do - v.ability.forced_selection = nil - end - end - if self.name == 'The Manacle' then - G.hand:change_size(1) - end - if self.name == 'The Serpent' then - end - if self.name == 'Violet Vessel' then - self.chips = self.chips/3 - self.chip_text = number_format(self.chips) - end - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - if self.boss and to_big(G.GAME.chips) - G.GAME.blind.chips >= to_big(0) then - G.STATE = G.STATES.NEW_ROUND - G.STATE_COMPLETE = false - end - return true - end - })) - for _, v in ipairs(G.playing_cards) do - self:debuff_card(v) - end - for _, v in ipairs(G.jokers.cards) do - self:debuff_card(v) - end - self:set_text() - self:wiggle() -end - -function Blind:wiggle() - self.children.animatedSprite:juice_up(0.3) - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.06*G.SETTINGS.GAMESPEED, blockable = false, blocking = false, func = function() - play_sound('tarot2', 0.76, 0.4);return true end})) - play_sound('tarot2', 1, 0.4) -end - -function Blind:juice_up(_a, _b) - self.children.animatedSprite:juice_up(_a or 0.2, _b or 0.2) -end - -function Blind:hover() - if not G.CONTROLLER.dragging.target or G.CONTROLLER.using_touch then - if not self.hovering and self.states.visible and self.children.animatedSprite.states.visible then - self.hovering = true - self.hover_tilt = 2 - self.children.animatedSprite:juice_up(0.05, 0.02) - play_sound('chips1', math.random()*0.1 + 0.55, 0.12) - Node.hover(self) - end - end -end - -function Blind:stop_hover() - self.hovering = false - self.hover_tilt = 0 - Node.stop_hover(self) -end - -function Blind:draw() - if not self.states.visible then return end - self.tilt_var = self.tilt_var or {} - self.tilt_var.mx, self.tilt_var.my =G.CONTROLLER.cursor_position.x,G.CONTROLLER.cursor_position.y - - self.children.animatedSprite.role.draw_major = self - self.children.animatedSprite:draw_shader('dissolve', 0.1) - self.children.animatedSprite:draw_shader('dissolve') - - for k, v in pairs(self.children) do - if k ~= 'animatedSprite' then - v.VT.scale = self.VT.scale - v:draw() - end - end - add_to_drawhash(self) -end - -function Blind:press_play() - if self.disabled then return end - local obj = self.config.blind - if obj.press_play and type(obj.press_play) == 'function' then - return obj:press_play() - end - if self.name == "The Hook" then - G.E_MANAGER:add_event(Event({ func = function() - local any_selected = nil - local _cards = {} - for k, v in ipairs(G.hand.cards) do - _cards[#_cards+1] = v - end - for i = 1, 2 do - if G.hand.cards[i] then - local selected_card, card_key = pseudorandom_element(_cards, pseudoseed('hook')) - G.hand:add_to_highlighted(selected_card, true) - table.remove(_cards, card_key) - any_selected = true - play_sound('card1', 1) - end - end - if any_selected then G.FUNCS.discard_cards_from_highlighted(nil, true) end - return true end })) - self.triggered = true - delay(0.7) - return true - end - if self.name == 'Crimson Heart' then - if G.jokers.cards[1] then - self.triggered = true - self.prepped = true - end - end - if self.name == 'The Fish' then - self.prepped = true - end - if self.name == "The Tooth" then - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function() - for i = 1, #G.play.cards do - G.E_MANAGER:add_event(Event({func = function() G.play.cards[i]:juice_up(); return true end })) - ease_dollars(-1) - delay(0.23) - end - return true end })) - self.triggered = true - return true - end -end - -function Blind:modify_hand(cards, poker_hands, text, mult, hand_chips) - if self.disabled then return mult, hand_chips, false end - local obj = self.config.blind - if obj.modify_hand and type(obj.modify_hand) == 'function' then - return obj:modify_hand(cards, poker_hands, text, mult, hand_chips) - end - if self.name == "The Flint" then - self.triggered = true - return math.max(math.floor(mult*0.5 + 0.5), 1), math.max(math.floor(hand_chips*0.5 + 0.5), 0), true - end - return mult, hand_chips, false -end - -function Blind:debuff_hand(cards, hand, handname, check) - if self.disabled then return end - local obj = self.config.blind - if obj.debuff_hand and type(obj.debuff_hand) == 'function' then - return obj:debuff_hand(cards, hand, handname, check) - end - if self.debuff then - self.triggered = false - if self.debuff.hand and next(hand[self.debuff.hand]) then - self.triggered = true - return true - end - if self.name == "The Psychic" and #cards > 5 then - self.triggered = true - return true - end - if self.debuff.h_size_ge and #cards < self.debuff.h_size_ge then - self.triggered = true - return true - end - if self.debuff.h_size_le and #cards > self.debuff.h_size_le then - self.triggered = true - return true - end - if self.name == "The Eye" then - if self.hands[handname] then - self.triggered = true - return true - end - if not check then self.hands[handname] = true end - end - if self.name == "The Mouth" then - if self.only_hand and self.only_hand ~= handname then - self.triggered = true - return true - end - if not check then self.only_hand = handname end - end - end - if self.name == 'The Arm' then - self.triggered = false - if G.GAME.hands[handname].level > 1 then - self.triggered = true - if not check then - level_up_hand(self.children.animatedSprite, handname, nil, -1) - self:wiggle() - end - end - end - if self.name == 'The Ox' then - self.triggered = false - if handname == G.GAME.current_round.most_played_poker_hand then - self.triggered = true - if not check then - ease_dollars(-G.GAME.dollars, true) - self:wiggle() - end - end - end -end - -function Blind:drawn_to_hand() - if not self.disabled then - local obj = self.config.blind - if obj.drawn_to_hand and type(obj.drawn_to_hand) == 'function' then - obj:drawn_to_hand() - end if self.name == 'Cerulean Bell' then - local any_forced = nil - for k, v in ipairs(G.hand.cards) do - if v.ability.forced_selection then - any_forced = true - end - end - if not any_forced then - G.hand:unhighlight_all() - local forced_card = pseudorandom_element(G.hand.cards, pseudoseed('cerulean_bell')) - forced_card.ability.forced_selection = true - G.hand:add_to_highlighted(forced_card) - end - end - if self.name == 'Crimson Heart' and self.prepped and G.jokers.cards[1] then - local prev_chosen_set = {} - local fallback_jokers = {} - local jokers = {} - for i = 1, #G.jokers.cards do - if G.jokers.cards[i].ability.crimson_heart_chosen then - prev_chosen_set[G.jokers.cards[i]] = true - G.jokers.cards[i].ability.crimson_heart_chosen = nil - if G.jokers.cards[i].debuff then SMODS.recalc_debuff(G.jokers.cards[i]) end - end - end - for i = 1, #G.jokers.cards do - if not G.jokers.cards[i].debuff then - if not prev_chosen_set[G.jokers.cards[i]] then - jokers[#jokers+1] = G.jokers.cards[i] - end - table.insert(fallback_jokers, G.jokers.cards[i]) - end - end - if #jokers == 0 then jokers = fallback_jokers end - local _card = pseudorandom_element(jokers, pseudoseed('crimson_heart')) - if _card then - _card.ability.crimson_heart_chosen = true - SMODS.recalc_debuff(_card) - _card:juice_up() - self:wiggle() - end - end - end - self.prepped = nil -end - -function Blind:stay_flipped(area, card) - if not self.disabled then - local obj = self.config.blind - if obj.stay_flipped and type(obj.stay_flipped) == 'function' then - return obj:stay_flipped(area, card) - end - if area == G.hand then - if self.name == 'The Wheel' and pseudorandom(pseudoseed('wheel')) < G.GAME.probabilities.normal/7 then - return true - end - if self.name == 'The House' and G.GAME.current_round.hands_played == 0 and G.GAME.current_round.discards_used == 0 then - return true - end - if self.name == 'The Mark' and card:is_face(true) then - return true - end - if self.name == 'The Fish' and self.prepped then - return true - end - end - end -end - -function Blind:debuff_card(card, from_blind) - local obj = self.config.blind - if not self.disabled and obj.recalc_debuff and type(obj.recalc_debuff) == 'function' then - if obj:recalc_debuff(card, from_blind) then - card:set_debuff(true) - if card.debuff then card.debuffed_by_blind = true end - else - card:set_debuff(false) - end - return - elseif not self.disabled and obj.debuff_card and type(obj.debuff_card) == 'function' then - sendWarnMessage(("Blind object %s has debuff_card function, recalc_debuff is preferred"):format(obj.key), obj.set) - if obj:debuff_card(card, from_blind) then - card:set_debuff(true) - if card.debuff then card.debuffed_by_blind = true end - else - card:set_debuff(false) - end - return - end - if self.debuff and not self.disabled and card.area ~= G.jokers then - if self.debuff.suit and card:is_suit(self.debuff.suit, true) then - card:set_debuff(true) - if card.debuff then card.debuffed_by_blind = true end - return - end - if self.debuff.is_face =='face' and card:is_face(true) then - card:set_debuff(true) - if card.debuff then card.debuffed_by_blind = true end - return - end - if self.name == 'The Pillar' and card.ability.played_this_ante then - card:set_debuff(true) - if card.debuff then card.debuffed_by_blind = true end - return - end - if self.debuff.value and self.debuff.value == card.base.value then - card:set_debuff(true) - if card.debuff then card.debuffed_by_blind = true end - return - end - if self.debuff.nominal and self.debuff.nominal == card.base.nominal then - card:set_debuff(true) - if card.debuff then card.debuffed_by_blind = true end - return - end - end - if self.name == 'Crimson Heart' and not self.disabled and card.area == G.jokers then - if card.ability.crimson_heart_chosen then - card:set_debuff(true); - if card.debuff then card.debuffed_by_blind = true end - return - end - end - if self.name == 'Verdant Leaf' and not self.disabled and card.area ~= G.jokers then card:set_debuff(true); if card.debuff then card.debuffed_by_blind = true end; return end - card:set_debuff(false) -end - -function Blind:move(dt) - Moveable.move(self, dt) - self:align() -end - -function Blind:change_dim(w, h) - self.T.w = w or self.T.w - self.T.h = h or self.T.h - self.children.animatedSprite.T.w = w or self.T.w - self.children.animatedSprite.T.h = h or self.T.h - self.children.animatedSprite:rescale() -end - -function Blind:align() - for k, v in pairs(self.children) do - if k == 'animatedSprite' then - if not v.states.drag.is then - v.T.r = 0.02*math.sin(2*G.TIMERS.REAL+self.T.x) - v.T.y = self.T.y + 0.03*math.sin(0.666*G.TIMERS.REAL+self.T.x) - self.shadow_height = 0.1 - (0.04 + 0.03*math.sin(0.666*G.TIMERS.REAL+self.T.x)) - v.T.x = self.T.x + 0.03*math.sin(0.436*G.TIMERS.REAL+self.T.x) - end - else - v.T.x = self.T.x - v.T.y = self.T.y - v.T.r = self.T.r - end - end -end - -function Blind:save() - local blindTable = { - in_blind = self.in_blind, - name = self.name, - dollars = self.dollars, - debuff = self.debuff, - pos = self.pos, - mult = self.mult, - disabled = self.disabled, - discards_sub = self.discards_sub, - hands_sub = self.hands_sub, - boss = self.boss, - config_blind = '', - chips = self.chips, - chip_text =self.chip_text, - hands = self.hands, - only_hand = self.only_hand, - triggered = self.triggered - } - - for k, v in pairs(G.P_BLINDS) do - if v and v.name and v.name == blindTable.name then - blindTable.config_blind = k - end - end - - return blindTable -end - -function Blind:load(blindTable) - self.in_blind = blindTable.in_blind - self.config.blind = G.P_BLINDS[blindTable.config_blind] or {} - - self.name = blindTable.name - self.dollars = blindTable.dollars - self.debuff = blindTable.debuff - self.pos = blindTable.pos - self.mult = blindTable.mult - self.disabled = blindTable.disabled - self.discards_sub = blindTable.discards_sub - self.hands_sub = blindTable.hands_sub - self.boss = blindTable.boss - self.chips = blindTable.chips - self.chip_text = blindTable.chip_text - self.hands = blindTable.hands - self.only_hand = blindTable.only_hand - self.triggered = blindTable.triggered - - G.ARGS.spin.real = (G.SETTINGS.reduced_motion and 0 or 1)*(self.config.blind.boss and (self.config.blind.boss.showdown and 1 or 0.3) or 0) - - if G.P_BLINDS[blindTable.config_blind] then - if self.config.blind.atlas then - self.children.animatedSprite.atlas = G.ANIMATION_ATLAS[self.config.blind.atlas] - end - self.blind_set = true - self.children.animatedSprite.states.visible = true - self.children.animatedSprite:set_sprite_pos(self.config.blind.pos) - self.children.animatedSprite:juice_up(0.3) - self:align() - self.children.animatedSprite:hard_set_VT() - else - self.children.animatedSprite.states.visible = false - end - - self.children.animatedSprite.states = self.states - self:change_colour() - if self.dollars > 0 then - G.GAME.current_round.dollars_to_be_earned = string.rep(localize('$'), self.dollars)..'' - G.HUD_blind:get_UIE_by_ID("dollars_to_be_earned").config.object:pop_in(0) - end - if G.GAME.blind.name and G.GAME.blind.name ~= '' then - G.HUD_blind.alignment.offset.y = 0 - end - self:set_text() -end diff --git a/lovely/dump/card.lua b/lovely/dump/card.lua deleted file mode 100644 index 8cb98aa..0000000 --- a/lovely/dump/card.lua +++ /dev/null @@ -1,5351 +0,0 @@ -LOVELY_INTEGRITY = 'd333bdf58ea96ab32bdb8d74d1b3a666732aeed72e1f1374e45a87d167ad1109' - ---class -Card = Moveable:extend() - ---class methods -function Card:init(X, Y, W, H, card, center, params) - self.params = (type(params) == 'table') and params or {} - - Moveable.init(self,X, Y, W, H) - - self.CT = self.VT - self.config = { - card = card or {}, - center = center - } - self.tilt_var = {mx = 0, my = 0, dx = 0, dy = 0, amt = 0} - self.ambient_tilt = 0.2 - - self.states.collide.can = true - self.states.hover.can = true - self.states.drag.can = true - self.states.click.can = true - - self.playing_card = self.params.playing_card - G.sort_id = (G.sort_id or 0) + 1 - self.sort_id = G.sort_id - - if self.params.viewed_back then self.back = 'viewed_back' - else self.back = 'selected_back' end - self.bypass_discovery_center = self.params.bypass_discovery_center - self.bypass_discovery_ui = self.params.bypass_discovery_ui - self.bypass_lock = self.params.bypass_lock - self.no_ui = self.config.card and self.config.card.no_ui - self.children = {} - self.base_cost = 0 - self.extra_cost = 0 - self.cost = 0 - self.sell_cost = 0 - self.sell_cost_label = 0 - self.children.shadow = Moveable(0, 0, 0, 0) - self.unique_val = 1-self.ID/1603301 - self.edition = nil - self.zoom = true - self:set_ability(center, true) - self:set_base(card, true) - - self.discard_pos = { - r = 3.6*(math.random()-0.5), - x = math.random(), - y = math.random() - } - - self.facing = 'front' - self.sprite_facing = 'front' - self.flipping = nil - self.area = nil - self.highlighted = false - self.click_timeout = 0.3 - self.T.scale = 0.95 - self.debuff = false - - self.rank = nil - self.added_to_deck = nil - - if self.children.front then self.children.front.VT.w = 0 end - self.children.back.VT.w = 0 - self.children.center.VT.w = 0 - - if self.children.front then self.children.front.parent = self; self.children.front.layered_parallax = nil end - self.children.back.parent = self; self.children.back.layered_parallax = nil - self.children.center.parent = self; self.children.center.layered_parallax = nil - - self:set_cost() - - if getmetatable(self) == Card then - table.insert(G.I.CARD, self) - end -end - -function Card:update_alert() - if self.ability.set == 'Default' and self.config.center and self.config.center.key == 'c_base' and self.seal then - if G.P_SEALS[self.seal].alerted and self.children.alert then - self.children.alert:remove() - self.children.alert = nil - elseif not G.P_SEALS[self.seal].alerted and not self.children.alert and G.P_SEALS[self.seal].discovered then - self.children.alert = UIBox{ - definition = create_UIBox_card_alert(), - config = {align="tli", - offset = {x = 0.1, y = 0.1}, - parent = self} - } - end - end - if (self.ability.set == 'Joker' or self.ability.set == 'Voucher' or self.ability.consumeable or self.ability.set == 'Edition' or self.ability.set == 'Booster') then - if self.area and self.area.config.collection and self.config.center then - if self.config.center.alerted and self.children.alert then - self.children.alert:remove() - self.children.alert = nil - elseif not self.config.center.alerted and not self.children.alert and self.config.center.discovered then - self.children.alert = UIBox{ - definition = create_UIBox_card_alert(), - config = {align=(self.ability.set == 'Voucher' and (self.config.center.order%2)==1) and "tli" or "tri", - offset = {x = (self.ability.set == 'Voucher' and (self.config.center.order%2)==1) and 0.1 or -0.1, y = 0.1}, - parent = self} - } - end - end - end -end - -function Card:set_base(card, initial) - card = card or {} - - self.config.card = card - for k, v in pairs(G.P_CARDS) do - if card == v then self.config.card_key = k end - end - - if next(card) then - self:set_sprites(nil, card) - end - - local suit_base_nominal_original = nil - if self.base and self.base.suit_nominal_original then suit_base_nominal_original = self.base.suit_nominal_original end - self.base = { - name = self.config.card.name, - suit = self.config.card.suit, - value = self.config.card.value, - nominal = 0, - suit_nominal = 0, - face_nominal = 0, - colour = G.C.SUITS[self.config.card.suit], - times_played = 0 - } - - local rank = SMODS.Ranks[self.base.value] or {} - self.base.nominal = rank.nominal or 0 - self.base.face_nominal = rank.face_nominal or 0 - self.base.id = rank.id - - if initial then self.base.original_value = self.base.value end - - local suit = SMODS.Suits[self.base.suit] or {} - self.base.suit_nominal = suit.suit_nominal or 0 - self.base.suit_nominal_original = suit_base_nominal_original or suit.suit_nominal or 0 - - if not initial and G.GAME and G.GAME.blind then G.GAME.blind:debuff_card(self) end - if self.playing_card and not initial then check_for_unlock({type = 'modify_deck'}) end -end - -function Card:set_sprites(_center, _front) - if _front then - local _atlas, _pos = get_front_spriteinfo(_front) - if self.children.front then - self.children.front.atlas = _atlas - self.children.front:set_sprite_pos(_pos) - else - self.children.front = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, _atlas, _pos) - self.children.front.states.hover = self.states.hover - self.children.front.states.click = self.states.click - self.children.front.states.drag = self.states.drag - self.children.front.states.collide.can = false - self.children.front:set_role({major = self, role_type = 'Glued', draw_major = self}) - end - end - if _center then - if _center.set then - if self.children.center then - self.children.center.atlas = G.ASSET_ATLAS[(_center.atlas or (_center.set == 'Joker' or _center.consumeable or _center.set == 'Voucher') and _center.set) or 'centers'] - self.children.center:set_sprite_pos(_center.pos) - else - if _center.set == 'Joker' and not _center.unlocked and not self.params.bypass_discovery_center then - self.children.center = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ASSET_ATLAS["Joker"], G.j_locked.pos) - elseif self.config.center.set == 'Voucher' and not self.config.center.unlocked and not self.params.bypass_discovery_center then - self.children.center = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ASSET_ATLAS["Voucher"], G.v_locked.pos) - elseif self.config.center.consumeable and self.config.center.demo then - self.children.center = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ASSET_ATLAS["Tarot"], G.c_locked.pos) - elseif not self.params.bypass_discovery_center and (_center.set == 'Edition' or _center.set == 'Joker' or _center.consumeable or _center.set == 'Voucher' or _center.set == 'Booster') and not _center.discovered then - self.children.center = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ASSET_ATLAS[(_center.undiscovered and (_center.undiscovered[G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or _center.undiscovered.atlas)) - or (SMODS.UndiscoveredSprites[_center.set] and (SMODS.UndiscoveredSprites[_center.set][G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or SMODS.UndiscoveredSprites[_center.set].atlas)) - or _center.set] or G.ASSET_ATLAS["Joker"], - (_center.undiscovered and _center.undiscovered.pos) or (SMODS.UndiscoveredSprites[_center.set] and SMODS.UndiscoveredSprites[_center.set].pos) or - (_center.set == 'Joker' and G.j_undiscovered.pos) or - (_center.set == 'Edition' and G.j_undiscovered.pos) or - (_center.set == 'Tarot' and G.t_undiscovered.pos) or - (_center.set == 'Planet' and G.p_undiscovered.pos) or - (_center.set == 'Spectral' and G.s_undiscovered.pos) or - (_center.set == 'Voucher' and G.v_undiscovered.pos) or - (_center.set == 'Booster' and G.booster_undiscovered.pos) or G.j_undiscovered.pos) - elseif _center.set == 'Joker' or _center.consumeable or _center.set == 'Voucher' then - self.children.center = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ASSET_ATLAS[_center[G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or _center.atlas or _center.set], self.config.center.pos) - else - self.children.center = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ASSET_ATLAS[_center.atlas or 'centers'], _center.pos) - end - self.children.center.states.hover = self.states.hover - self.children.center.states.click = self.states.click - self.children.center.states.drag = self.states.drag - self.children.center.states.collide.can = false - self.children.center:set_role({major = self, role_type = 'Glued', draw_major = self}) - end - if _center.name == 'Half Joker' and (_center.discovered or self.bypass_discovery_center) then - self.children.center.scale.y = self.children.center.scale.y/1.7 - end - if _center.name == "cry-Cube" and (_center.discovered or self.bypass_discovery_center) then - self.children.center.scale.y = self.children.center.scale.y*0.1 - self.children.center.scale.x = self.children.center.scale.x*0.1 - end - if _center.name == 'cry-Jimball' and (_center.discovered or self.bypass_discovery_center) then - self.children.center.scale.y = self.children.center.scale.x - self.children.center.scale.y = self.children.center.scale.y*57/69 - self.children.center.scale.x = self.children.center.scale.x*57/69 - end - if _center.name == 'cry-Potion' and (_center.discovered or self.bypass_discovery_center) then - self.children.center.scale.y = self.children.center.scale.x - self.children.center.scale.y = self.children.center.scale.y*35/69 - self.children.center.scale.x = self.children.center.scale.x*35/69 - end - if _center.name == 'cry-magnet' and (_center.discovered or self.bypass_discovery_center) then - self.children.center.scale.y = self.children.center.scale.x - self.children.center.scale.y = self.children.center.scale.y*35/71 - self.children.center.scale.x = self.children.center.scale.x*35/71 - end - if _center.name == 'Photograph' and (_center.discovered or self.bypass_discovery_center) then - self.children.center.scale.y = self.children.center.scale.y/1.2 - end - if _center.name == 'Square Joker' and (_center.discovered or self.bypass_discovery_center) then - self.children.center.scale.y = self.children.center.scale.x - end - end - - if _center.soul_pos then - self.children.floating_sprite = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ASSET_ATLAS[_center[G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or _center.atlas or _center.set], self.config.center.soul_pos) - self.children.floating_sprite.role.draw_major = self - self.children.floating_sprite.states.hover.can = false - self.children.floating_sprite.states.click.can = false - end - - if _center.set_sprites and type(_center.set_sprites) == 'function' then - _center:set_sprites(self, _front) - end - if true then - self.children.back = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ASSET_ATLAS[(G.GAME.viewed_back or G.GAME.selected_back) and ((G.GAME.viewed_back or G.GAME.selected_back)[G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or (G.GAME.viewed_back or G.GAME.selected_back).atlas) or 'centers'], self.params.bypass_back or (self.playing_card and G.GAME[self.back].pos or G.P_CENTERS['b_red'].pos)) - self.children.back.states.hover = self.states.hover - self.children.back.states.click = self.states.click - self.children.back.states.drag = self.states.drag - self.children.back.states.collide.can = false - self.children.back:set_role({major = self, role_type = 'Glued', draw_major = self}) - end - end -end - -function Card:set_ability(center, initial, delay_sprites) - local X, Y, W, H = self.T.x, self.T.y, self.T.w, self.T.h - - local old_center = self.config.center - if old_center and not next(SMODS.find_card(old_center.key, true)) then - G.GAME.used_jokers[old_center.key] = nil - end - if self.added_to_deck and old_center and not self.debuff then - self:remove_from_deck() - self.added_to_deck = true - end - self.config.center = center - self.sticker_run = nil - for k, v in pairs(G.P_CENTERS) do - if center == v then self.config.center_key = k end - end - - if self.params.discover and not center.discovered then - unlock_card(center) - discover_card(center) - end - - if center.name == "Half Joker" and (center.discovered or self.bypass_discovery_center) then - H = H/1.7 - self.T.h = H - end - - if center.name == "Photograph" and (center.discovered or self.bypass_discovery_center) then - H = H/1.2 - self.T.h = H - end - - if center.name == "Square Joker" and (center.discovered or self.bypass_discovery_center) then - H = W - self.T.h = H - end - - if (center.name == "cry-Wee Fibonacci" or center.name == "cry-reverse") and (center.discovered or self.bypass_discovery_center) then - H = H*0.7 - W = W*0.7 - self.T.h = H - self.T.w = W - end - if center.name == "cry-biggestm" and (center.discovered or self.bypass_discovery_center) then - H = H*1.7 - W = W*1.7 - self.T.h = H - self.T.w = W - end - if center.name == "cry-Booster Joker" and (center.discovered or self.bypass_discovery_center) then - H = H*1.17 - W = W*1.17 - self.T.h = H - self.T.w = W - end - if center.name == "cry-Cube" and (center.discovered or self.bypass_discovery_center) then - H = H*0.1 - W = W*0.1 - self.T.h = H - self.T.w = W - end - if center.name == "cry-Potion" and (center.discovered or self.bypass_discovery_center) then - H = W - self.T.h = H - H = H*35/69 - W = W*35/69 - self.T.h = H - self.T.w = W - end - if center.name == "cry-Jimball" and (center.discovered or self.bypass_discovery_center) then - H = W - self.T.h = H - H = H*57/69 - W = W*57/69 - self.T.h = H - self.T.w = W - end - if center.name == "cry-magnet" and (center.discovered or self.bypass_discovery_center) then - H = W - self.T.h = H - H = H*35/71 - W = W*35/71 - self.T.h = H - self.T.w = W - end - if center.name == "Wee Joker" and (center.discovered or self.bypass_discovery_center) then - H = H*0.7 - W = W*0.7 - self.T.h = H - self.T.w = W - end - - if delay_sprites then - G.E_MANAGER:add_event(Event({ - func = function() - if not self.REMOVED then - self:set_sprites(center) - end - return true - end - })) - else - self:set_sprites(center) - end - - if self.ability and old_center and old_center.config.bonus then - self.ability.bonus = self.ability.bonus - old_center.config.bonus - end - - local new_ability = { - name = center.name, - effect = center.effect, - set = center.set, - mult = center.config.mult or 0, - h_mult = center.config.h_mult or 0, - h_x_mult = center.config.h_x_mult or 0, - h_dollars = center.config.h_dollars or 0, - p_dollars = center.config.p_dollars or 0, - t_mult = center.config.t_mult or 0, - t_chips = center.config.t_chips or 0, - x_mult = center.config.Xmult or 1, - e_mult = center.config.Emult or 0, - ee_mult = center.config.EEmult or 0, - eee_mult = center.config.EEEmult or 0, - hyper_mult = type(center.config.Hmult) == 'table' and center.config.Hmult or {0, 0}, - x_chips = center.config.Xchips or 0, - e_chips = center.config.Echips or 0, - ee_chips = center.config.EEchips or 0, - eee_chips = center.config.EEEchips or 0, - hyper_chips = type(center.config.Hchips) == 'table' and center.config.Hchips or {0, 0}, - h_size = center.config.h_size or 0, - d_size = center.config.d_size or 0, - extra = copy_table(center.config.extra) or nil, - extra_value = 0, - type = center.config.type or '', - order = center.order or nil, - forced_selection = self.ability and self.ability.forced_selection or nil, - perma_bonus = self.ability and self.ability.perma_bonus or 0, - eternal = self.ability and self.ability.eternal, - perishable = self.ability and self.ability.perishable, - perish_tally = self.ability and self.ability.perish_tally, - rental = self.ability and self.ability.rental - } - self.ability = self.ability or {} - new_ability.extra_value = nil - self.ability.extra_value = self.ability.extra_value or 0 - for k, v in pairs(new_ability) do - self.ability[k] = v - end - -- reset keys do not persist an ability change - local reset_keys = {'name', 'effect', 'set', 'extra', 'played_this_ante'} - for _, mod in ipairs(SMODS.mod_list) do - if mod.set_ability_reset_keys then - local keys = mod.set_ability_reset_keys() - for _, v in pairs(keys) do table.insert(reset_keys, v) end - end - end - for _, k in ipairs(reset_keys) do - self.ability[k] = new_ability[k] - end - - self.ability.bonus = (self.ability.bonus or 0) + (center.config.bonus or 0) - if not self.ability.name then self.ability.name = center.key end - for k, v in pairs(center.config) do - if k ~= 'bonus' then - if type(v) == 'table' then - self.ability[k] = copy_table(v) - else - self.ability[k] = v - end - end - end - - if center.consumeable then - self.ability.consumeable = center.config - end - - if self.ability.name == 'Gold Card' and self.seal == 'Gold' and self.playing_card then - check_for_unlock({type = 'double_gold'}) - end - if self.ability.name == "Invisible Joker" then - self.ability.invis_rounds = 0 - end - if self.ability.name == 'To Do List' 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 - local old_hand = self.ability.to_do_poker_hand - self.ability.to_do_poker_hand = nil - - while not self.ability.to_do_poker_hand do - self.ability.to_do_poker_hand = pseudorandom_element(_poker_hands, pseudoseed((self.area and self.area.config.type == 'title') and 'false_to_do' or 'to_do')) - if self.ability.to_do_poker_hand == old_hand then self.ability.to_do_poker_hand = nil end - end - end - if self.ability.name == 'Caino' then - self.ability.caino_xmult = 1 - end - if self.ability.name == 'Yorick' then - self.ability.yorick_discards = self.ability.extra.discards - end - if self.ability.name == 'Loyalty Card' then - self.ability.burnt_hand = 0 - self.ability.loyalty_remaining = self.ability.extra.every - end - - self.ability.cry_prob = 1 - self.base_cost = center.cost or 1 - - self.ability.hands_played_at_create = G.GAME and G.GAME.hands_played or 0 - - self.label = center.label or self.config.card and self.config.card.label or self.ability.set - if self.ability.set == 'Joker' then self.label = self.ability.name end - if self.ability.set == 'Edition' then self.label = self.ability.name end - if self.ability.consumeable then self.label = self.ability.name end - if self.ability.set == 'Voucher' then self.label = self.ability.name end - if self.ability.set == 'Booster' then - self.label = self.ability.name - self.mouse_damping = 1.5 - end - - local obj = self.config.center - if obj.set_ability and type(obj.set_ability) == 'function' then - obj:set_ability(self, initial, delay_sprites) - end - - if not G.OVERLAY_MENU then - if self.config.center.key then - G.GAME.used_jokers[self.config.center.key] = true - end - - end - - if G.jokers and self.area == G.jokers then - check_for_unlock({type = 'modify_jokers'}) - end - - if self.added_to_deck and old_center and not self.debuff then - self.added_to_deck = false - self:add_to_deck() - end - if G.consumeables and self.area == G.consumeables then - check_for_unlock({type = 'modify_jokers'}) - end - - if not initial and G.GAME and G.GAME.blind then G.GAME.blind:debuff_card(self) end - if self.playing_card and not initial then check_for_unlock({type = 'modify_deck'}) end -end - -function Card:set_cost() - self.extra_cost = 0 + G.GAME.inflation - if self.edition then - for k, v in pairs(G.P_CENTER_POOLS.Edition) do - if self.edition[v.key:sub(3)] then - if v.extra_cost then - self.extra_cost = self.extra_cost + v.extra_cost - end - end - end - end - self.cost = math.max(1, math.floor((self.base_cost + self.extra_cost + 0.5)*(100-G.GAME.discount_percent)/100)) - if self.ability.set == 'Joker' then - self.cost = cry_format(self.cost * G.GAME.cry_shop_joker_price_modifier,'%.2f') end - if self.misprint_cost_fac then - self.cost = cry_format(self.cost * self.misprint_cost_fac,'%.2f') - if not G.GAME.modifiers.cry_misprint_min then self.cost = math.floor(self.cost) end end - if self.ability.set == 'Booster' and G.GAME.modifiers.booster_ante_scaling then self.cost = self.cost + G.GAME.round_resets.ante - 1 end - if self.ability.set == 'Booster' and (not G.SETTINGS.tutorial_complete) and G.SETTINGS.tutorial_progress and (not G.SETTINGS.tutorial_progress.completed_parts['shop_1']) then - self.cost = self.cost + 3 - end - if (self.ability.set == 'Planet' or (self.ability.set == 'Booster' and self.ability.name:find('Celestial'))) and #find_joker('Astronomer') > 0 then self.cost = 0 end - if self.ability.rental and (not (self.ability.set == "Planet" and #find_joker('Astronomer') > 0) and self.ability.set ~= "Booster") then self.cost = 1 end - self.sell_cost = math.max(1, math.floor(self.cost/2)) + (self.ability.extra_value or 0) - if self.area and self.ability.couponed and (self.area == G.shop_jokers or self.area == G.shop_booster) then self.cost = 0 end - self.sell_cost_label = (self.facing == 'back' and '?') or (G.GAME.modifiers.cry_no_sell_value and 0) or self.sell_cost -end - -function Card:set_edition(edition, immediate, silent) - self.edition = nil - if not edition then return end - if edition.holo then - if not self.edition then self.edition = {} end - self.edition.mult = G.P_CENTERS.e_holo.config.extra - self.edition.holo = true - self.edition.type = 'holo' - elseif edition.foil then - if not self.edition then self.edition = {} end - self.edition.chips = G.P_CENTERS.e_foil.config.extra - self.edition.foil = true - self.edition.type = 'foil' - elseif edition.polychrome then - if not self.edition then self.edition = {} end - self.edition.x_mult = G.P_CENTERS.e_polychrome.config.extra - self.edition.polychrome = true - self.edition.type = 'polychrome' - elseif edition.negative then - if not self.edition then - self.edition = {} - if self.added_to_deck then --Need to override if adding negative to an existing joker - if self.ability.consumeable then - G.consumeables.config.card_limit = G.consumeables.config.card_limit + 1 - else - G.jokers.config.card_limit = G.jokers.config.card_limit + 1 - end - end - end - self.edition.negative = true - self.edition.type = 'negative' - end - - if self.area and self.area == G.jokers then - if self.edition then - if self.edition.type and G.P_CENTERS['e_'..(self.edition.type)] and not G.P_CENTERS['e_'..(self.edition.type)].discovered then - discover_card(G.P_CENTERS['e_'..(self.edition.type)]) - end - else - if not G.P_CENTERS['e_base'].discovered then - discover_card(G.P_CENTERS['e_base']) - end - end - end - - if self.edition and (not Talisman.config_file.disable_anims or (not Talisman.calculating_joker and not Talisman.calculating_score and not Talisman.calculating_card)) and not silent then - G.CONTROLLER.locks.edition = true - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = not immediate and 0.2 or 0, - blockable = not immediate, - func = function() - self:juice_up(1, 0.5) - if self.edition.foil then play_sound('foil1', 1.2, 0.4) end - if self.edition.holo then play_sound('holo1', 1.2*1.58, 0.4) end - if self.edition.polychrome then play_sound('polychrome1', 1.2, 0.7) end - if self.edition.negative then play_sound('negative', 1.5, 0.4) end - return true - end - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.1, - func = function() - G.CONTROLLER.locks.edition = false - return true - end - })) - end - - if G.jokers and self.area == G.jokers then - check_for_unlock({type = 'modify_jokers'}) - end - - self:set_cost() -end - -function Card:set_seal(_seal, silent, immediate) - self.seal = nil - if _seal then - self.seal = _seal - if not silent then - G.CONTROLLER.locks.seal = true - local sound = G.P_SEALS[_seal].sound or {sound = 'gold_seal', per = 1.2, vol = 0.4} - if immediate then - self:juice_up(0.3, 0.3) - play_sound(sound.sound, sound.per, sound.vol) - G.CONTROLLER.locks.seal = false - else - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.3, - func = function() - self:juice_up(0.3, 0.3) - play_sound(sound.sound, sound.per, sound.vol) - return true - end - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.15, - func = function() - G.CONTROLLER.locks.seal = false - return true - end - })) - end - end - end - if self.ability.name == 'Gold Card' and self.seal == 'Gold' and self.playing_card then - check_for_unlock({type = 'double_gold'}) - end - self:set_cost() -end - -function Card:get_seal(bypass_debuff) - if self.debuff and not bypass_debuff then return end - return self.seal -end - -function Card:set_eternal(_eternal) - self.ability.eternal = nil - if self.config.center.eternal_compat and not self.ability.perishable then - self.ability.eternal = _eternal - end -end - -function Card:set_perishable(_perishable) - self.ability.perishable = nil - if self.config.center.perishable_compat and not self.ability.eternal then - self.ability.perishable = true - self.ability.perish_tally = G.GAME.perishable_rounds - end -end - -function Card:set_rental(_rental) - self.ability.rental = _rental - self:set_cost() -end - -function Card:set_debuff(should_debuff) - for _, mod in ipairs(SMODS.mod_list) do - if mod.set_debuff and type(mod.set_debuff) == 'function' then - local res = mod.set_debuff(self) - if res == 'prevent_debuff' then - if self.debuff then - self.debuff = false - if self.area == G.jokers then self:add_to_deck(true) end - self.debuffed_by_blind = false - end - return - end - should_debuff = should_debuff or res - end - end - for k, v in pairs(self.ability.debuff_sources or {}) do - if v == 'prevent_debuff' then - if self.debuff then - self.debuff = false - if self.area == G.jokers then self:add_to_deck(true) end - end - self.debuffed_by_blind = false - return - end - should_debuff = should_debuff or v - end - - if self.ability.perishable and not self.ability.perish_tally then self.ability.perish_tally = G.GAME.perishable_rounds end - if self.ability.perishable and self.ability.perish_tally <= 0 then - if not self.debuff then - self.debuff = true - if self.area == G.jokers then self:remove_from_deck(true) end - end - return - end - if should_debuff ~= self.debuff then - if self.area == G.jokers then if should_debuff then self:remove_from_deck(true) else self:add_to_deck(true) end end - self.debuff = should_debuff - end - if not self.debuff then self.debuffed_by_blind = false end - -end - -function Card:remove_UI() - self.ability_UIBox_table = nil - self.config.h_popup = nil - self.config.h_popup_config = nil - self.no_ui = true -end - -function Card:change_suit(new_suit) - local new_code = SMODS.Suits[new_suit].card_key - local new_val = SMODS.Ranks[self.base.value].card_key - local new_card = G.P_CARDS[new_code..'_'..new_val] - - self:set_base(new_card) - G.GAME.blind:debuff_card(self) -end - -function Card:add_to_deck(from_debuff) - if not self.config.center.discovered then - discover_card(self.config.center) - end - if not self.added_to_deck then - self.added_to_deck = true - if self.ability.set == 'Enhanced' or self.ability.set == 'Default' then - if self.ability.name == 'Gold Card' and self.seal == 'Gold' and self.playing_card then - check_for_unlock({type = 'double_gold'}) - end - return - end - - if self.edition then - if self.edition.type and G.P_CENTERS['e_'..(self.edition.type)] and not G.P_CENTERS['e_'..(self.edition.type)].discovered then - discover_card(G.P_CENTERS['e_'..(self.edition.type)]) - end - else - if not G.P_CENTERS['e_base'].discovered then - discover_card(G.P_CENTERS['e_base']) - end - end - local obj = self.config.center - if obj and obj.add_to_deck and type(obj.add_to_deck) == 'function' then - obj:add_to_deck(self, from_debuff) - end if self.ability.h_size ~= 0 then - G.hand:change_size(self.ability.h_size) - end - if self.ability.d_size > 0 then - G.GAME.round_resets.discards = G.GAME.round_resets.discards + self.ability.d_size - ease_discard(self.ability.d_size) - end - if self.ability.name == 'Credit Card' then - G.GAME.bankrupt_at = G.GAME.bankrupt_at - self.ability.extra - end - if self.ability.name == 'Chicot' and G.GAME.blind and G.GAME.blind.boss and not G.GAME.blind.disabled then - G.GAME.blind:disable() - play_sound('timpani') - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('ph_boss_disabled')}) - end - if self.ability.name == 'Chaos the Clown' then - G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls + 1 - calculate_reroll_cost(true) - end - if self.ability.name == 'Turtle Bean' then - G.hand:change_size(self.ability.extra.h_size) - end - if self.ability.name == 'Oops! All 6s' then - for k, v in pairs(G.GAME.probabilities) do - G.GAME.probabilities[k] = v*2 - end - end - if self.ability.name == 'To the Moon' then - G.GAME.interest_amount = G.GAME.interest_amount + self.ability.extra - end - if self.ability.name == 'Astronomer' then - G.E_MANAGER:add_event(Event({func = function() - for k, v in pairs(G.I.CARD) do - if v.set_cost then v:set_cost() end - end - return true end })) - end - if self.ability.name == 'Troubadour' then - G.hand:change_size(self.ability.extra.h_size) - G.GAME.round_resets.hands = G.GAME.round_resets.hands + self.ability.extra.h_plays - end - if self.ability.name == 'Stuntman' then - G.hand:change_size(-self.ability.extra.h_size) - end - if true then - if from_debuff then - self.ability.joker_added_to_deck_but_debuffed = nil - else - if self.edition and self.edition.card_limit then - if self.ability.consumeable then - G.consumeables.config.card_limit = G.consumeables.config.card_limit + self.edition.card_limit - else - G.jokers.config.card_limit = G.jokers.config.card_limit + self.edition.card_limit - end - end - end - end - if G.GAME.blind and G.GAME.blind.in_blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end - end -end - -function Card:remove_from_deck(from_debuff) - if self.added_to_deck then - self.added_to_deck = false - local obj = self.config.center - if obj and obj.remove_from_deck and type(obj.remove_from_deck) == 'function' then - obj:remove_from_deck(self, from_debuff) - end if self.ability.h_size ~= 0 then - G.hand:change_size(-self.ability.h_size) - end - if self.ability.d_size > 0 then - G.GAME.round_resets.discards = G.GAME.round_resets.discards - self.ability.d_size - ease_discard(-self.ability.d_size) - end - if self.ability.name == 'Credit Card' then - G.GAME.bankrupt_at = G.GAME.bankrupt_at + self.ability.extra - end - if self.ability.name == 'Chaos the Clown' then - G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls - 1 - calculate_reroll_cost(true) - end - if self.ability.name == 'Turtle Bean' then - G.hand:change_size(-self.ability.extra.h_size) - end - if self.ability.name == 'Oops! All 6s' then - for k, v in pairs(G.GAME.probabilities) do - G.GAME.probabilities[k] = v/2 - end - end - if self.ability.name == 'To the Moon' then - G.GAME.interest_amount = G.GAME.interest_amount - self.ability.extra - end - if self.ability.name == 'Astronomer' then - G.E_MANAGER:add_event(Event({func = function() - for k, v in pairs(G.I.CARD) do - if v.set_cost then v:set_cost() end - end - return true end })) - end - if self.ability.name == 'Troubadour' then - G.hand:change_size(-self.ability.extra.h_size) - G.GAME.round_resets.hands = G.GAME.round_resets.hands - self.ability.extra.h_plays - end - if self.ability.name == 'Stuntman' then - G.hand:change_size(self.ability.extra.h_size) - end - if G.jokers then - if from_debuff then - self.ability.joker_added_to_deck_but_debuffed = true - else - if self.edition and self.edition.card_limit then - if self.ability.consumeable then - G.consumeables.config.card_limit = G.consumeables.config.card_limit - self.edition.card_limit - elseif self.ability.set == 'Joker' then - G.jokers.config.card_limit = G.jokers.config.card_limit - self.edition.card_limit - end - end - end - end - if G.GAME.blind and G.GAME.blind.in_blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end - end -end - -function Card:generate_UIBox_unlock_table(hidden) - local loc_vars = {no_name = true, not_hidden = not hidden} - - return generate_card_ui(self.config.center, nil, loc_vars, 'Locked') -end - -function Card:generate_UIBox_ability_table() - local card_type, hide_desc = self.ability.set or "None", nil - local loc_vars = nil - local main_start, main_end = nil,nil - local no_badge = nil - - if not self.bypass_lock and self.config.center.unlocked ~= false and - (self.ability.set == 'Joker' or self.ability.set == 'Edition' or self.ability.consumeable or self.ability.set == 'Voucher' or self.ability.set == 'Booster') and - not self.config.center.discovered and - ((self.area ~= G.jokers and self.area ~= G.consumeables and self.area) or not self.area) then - card_type = 'Undiscovered' - end - if self.config.center.unlocked == false and not self.bypass_lock then --For everyting that is locked - card_type = "Locked" - if self.area and self.area == G.shop_demo then loc_vars = {}; no_badge = true end - elseif card_type == 'Undiscovered' and not self.bypass_discovery_ui then -- Any Joker or tarot/planet/voucher that is not yet discovered - hide_desc = true - elseif self.debuff then - loc_vars = { debuffed = true, playing_card = not not self.base.colour, value = self.base.value, suit = self.base.suit, colour = self.base.colour } - elseif card_type == 'Default' or card_type == 'Enhanced' then - loc_vars = { playing_card = not not self.base.colour, value = self.base.value, suit = self.base.suit, colour = self.base.colour, - nominal_chips = self.base.nominal > 0 and self.base.nominal or nil, - bonus_chips = (self.ability.bonus + (self.ability.perma_bonus or 0)) > 0 and (self.ability.bonus + (self.ability.perma_bonus or 0)) or nil, - } - elseif self.ability.set == 'Joker' then -- all remaining jokers - if self.ability.name == 'Joker' then loc_vars = {self.ability.mult} - elseif self.ability.name == 'Jolly Joker' or self.ability.name == 'Zany Joker' or - self.ability.name == 'Mad Joker' or self.ability.name == 'Crazy Joker' or - self.ability.name == 'Droll Joker' then - loc_vars = {self.ability.t_mult, localize(self.ability.type, 'poker_hands')} - elseif self.ability.name == 'Sly Joker' or self.ability.name == 'Wily Joker' or - self.ability.name == 'Clever Joker' or self.ability.name == 'Devious Joker' or - self.ability.name == 'Crafty Joker' then - loc_vars = {self.ability.t_chips, localize(self.ability.type, 'poker_hands')} - elseif self.ability.name == 'Half Joker' then loc_vars = {self.ability.extra.mult, self.ability.extra.size} - elseif self.ability.name == 'Fortune Teller' then loc_vars = {self.ability.extra, (G.GAME.consumeable_usage_total and G.GAME.consumeable_usage_total.tarot or 0)} - elseif self.ability.name == 'Steel Joker' then loc_vars = {self.ability.extra, 1 + self.ability.extra*(self.ability.steel_tally or 0)} - elseif self.ability.name == 'Chaos the Clown' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Space Joker' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged), self.ability.extra} - elseif self.ability.name == 'Stone Joker' then loc_vars = {self.ability.extra, self.ability.extra*(self.ability.stone_tally or 0)} - elseif self.ability.name == 'Drunkard' then loc_vars = {self.ability.d_size} - elseif self.ability.name == 'Green Joker' then loc_vars = {self.ability.extra.hand_add, self.ability.extra.discard_sub, self.ability.mult} - elseif self.ability.name == 'Credit Card' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Greedy Joker' or self.ability.name == 'Lusty Joker' or - self.ability.name == 'Wrathful Joker' or self.ability.name == 'Gluttonous Joker' then loc_vars = {self.ability.extra.s_mult, localize(self.ability.extra.suit, 'suits_singular')} - elseif self.ability.name == 'Blue Joker' then loc_vars = {self.ability.extra, self.ability.extra*((G.deck and G.deck.cards) and #G.deck.cards or 52)} - elseif self.ability.name == 'Sixth Sense' then loc_vars = {} - elseif self.ability.name == 'Mime' then - elseif self.ability.name == 'Hack' then loc_vars = {self.ability.extra+1} - elseif self.ability.name == 'Pareidolia' then - elseif self.ability.name == 'Faceless Joker' then loc_vars = {self.ability.extra.dollars, self.ability.extra.faces} - elseif self.ability.name == 'Oops! All 6s' then - elseif self.ability.name == 'Juggler' then loc_vars = {self.ability.h_size} - elseif self.ability.name == 'Golden Joker' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Joker Stencil' then loc_vars = {self.ability.x_mult} - elseif self.ability.name == 'Four Fingers' then - elseif self.ability.name == 'Ceremonial Dagger' then loc_vars = {self.ability.mult} - elseif self.ability.name == 'Banner' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Misprint' then - local r_mults = {} - for i = self.ability.extra.min, self.ability.extra.max do - r_mults[#r_mults+1] = tostring(i) - end - local loc_mult = ' '..(localize('k_mult'))..' ' - main_start = { - {n=G.UIT.T, config={text = ' +',colour = G.C.MULT, scale = 0.32}}, - {n=G.UIT.O, config={object = DynaText({string = r_mults, colours = {G.C.RED},pop_in_rate = 9999999, silent = true, random_element = true, pop_delay = 0.5, scale = 0.32, min_cycle_time = 0})}}, - {n=G.UIT.O, config={object = DynaText({string = { - {string = 'rand()', colour = G.C.JOKER_GREY},{string = "#@"..(G.deck and G.deck.cards[1] and G.deck.cards[#G.deck.cards].base.id or 11)..(G.deck and G.deck.cards[1] and G.deck.cards[#G.deck.cards].base.suit:sub(1,1) or 'D'), colour = G.C.RED}, - loc_mult, loc_mult, loc_mult, loc_mult, loc_mult, loc_mult, loc_mult, loc_mult, loc_mult, loc_mult, loc_mult, loc_mult, loc_mult}, - colours = {G.C.UI.TEXT_DARK},pop_in_rate = 9999999, silent = true, random_element = true, pop_delay = 0.2011, scale = 0.32, min_cycle_time = 0})}}, - } - elseif self.ability.name == 'Mystic Summit' then loc_vars = {self.ability.extra.mult, self.ability.extra.d_remaining} - elseif self.ability.name == 'Marble Joker' then - elseif self.ability.name == 'Loyalty Card' then loc_vars = {self.ability.extra.Xmult, self.ability.extra.every + 1, localize{type = 'variable', key = (self.ability.loyalty_remaining == 0 and 'loyalty_active' or 'loyalty_inactive'), vars = {self.ability.loyalty_remaining}}} - elseif self.ability.name == '8 Ball' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged),self.ability.extra} - elseif self.ability.name == 'Dusk' then loc_vars = {self.ability.extra+1} - elseif self.ability.name == 'Raised Fist' then - elseif self.ability.name == 'Fibonacci' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Scary Face' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Abstract Joker' then loc_vars = {self.ability.extra, (G.jokers and G.jokers.cards and #G.jokers.cards or 0)*self.ability.extra} - elseif self.ability.name == 'Delayed Gratification' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Gros Michel' then loc_vars = {self.ability.extra.mult, cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged), self.ability.extra.odds} - elseif self.ability.name == 'Even Steven' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Odd Todd' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Scholar' then loc_vars = {self.ability.extra.mult, self.ability.extra.chips} - elseif self.ability.name == 'Business Card' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged),self.ability.extra} - elseif self.ability.name == 'Supernova' then - elseif self.ability.name == 'Spare Trousers' then loc_vars = {self.ability.extra, localize('Two Pair', 'poker_hands'), self.ability.mult} - elseif self.ability.name == 'Superposition' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Ride the Bus' then loc_vars = {self.ability.extra, self.ability.mult} - elseif self.ability.name == 'Egg' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Burglar' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Blackboard' then loc_vars = {self.ability.extra, localize('Spades', 'suits_plural'), localize('Clubs', 'suits_plural')} - elseif self.ability.name == 'Runner' then loc_vars = {self.ability.extra.chips, self.ability.extra.chip_mod} - elseif self.ability.name == 'Ice Cream' then loc_vars = {self.ability.extra.chips, self.ability.extra.chip_mod} - elseif self.ability.name == 'DNA' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Splash' then - elseif self.ability.name == 'Constellation' then loc_vars = {self.ability.extra, self.ability.x_mult} - elseif self.ability.name == 'Hiker' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'To Do List' then loc_vars = {self.ability.extra.dollars, localize(self.ability.to_do_poker_hand, 'poker_hands')} - elseif self.ability.name == 'Smeared Joker' then - elseif self.ability.name == 'Blueprint' then - self.ability.blueprint_compat_ui = self.ability.blueprint_compat_ui or ''; self.ability.blueprint_compat_check = nil - main_end = (self.area and self.area == G.jokers) and { - {n=G.UIT.C, config={align = "bm", minh = 0.4}, nodes={ - {n=G.UIT.C, config={ref_table = self, align = "m", colour = G.C.JOKER_GREY, r = 0.05, padding = 0.06, func = 'blueprint_compat'}, nodes={ - {n=G.UIT.T, config={ref_table = self.ability, ref_value = 'blueprint_compat_ui',colour = G.C.UI.TEXT_LIGHT, scale = 0.32*0.8}}, - }} - }} - } or nil - elseif self.ability.name == 'Cartomancer' then - elseif self.ability.name == 'Astronomer' then loc_vars = {self.ability.extra} - - elseif self.ability.name == 'Golden Ticket' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Mr. Bones' then - elseif self.ability.name == 'Acrobat' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Sock and Buskin' then loc_vars = {self.ability.extra+1} - elseif self.ability.name == 'Swashbuckler' then loc_vars = {self.ability.mult} - elseif self.ability.name == 'Troubadour' then loc_vars = {self.ability.extra.h_size, -self.ability.extra.h_plays} - elseif self.ability.name == 'Certificate' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Throwback' then loc_vars = {self.ability.extra, self.ability.x_mult} - elseif self.ability.name == 'Hanging Chad' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Rough Gem' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Bloodstone' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged), self.ability.extra.odds, self.ability.extra.Xmult} - elseif self.ability.name == 'Arrowhead' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Onyx Agate' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Glass Joker' then loc_vars = {self.ability.extra, self.ability.x_mult} - elseif self.ability.name == 'Showman' then - elseif self.ability.name == 'Flower Pot' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Wee Joker' then loc_vars = {self.ability.extra.chips, self.ability.extra.chip_mod} - elseif self.ability.name == 'Merry Andy' then loc_vars = {self.ability.d_size, self.ability.h_size} - elseif self.ability.name == 'The Idol' then loc_vars = {self.ability.extra, localize(G.GAME.current_round.idol_card.rank, 'ranks'), localize(G.GAME.current_round.idol_card.suit, 'suits_plural'), colours = {G.C.SUITS[G.GAME.current_round.idol_card.suit]}} - elseif self.ability.name == 'Seeing Double' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Matador' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Hit the Road' then loc_vars = {self.ability.extra, self.ability.x_mult} - elseif self.ability.name == 'The Duo' or self.ability.name == 'The Trio' - or self.ability.name == 'The Family' or self.ability.name == 'The Order' or self.ability.name == 'The Tribe' then loc_vars = {self.ability.x_mult, localize(self.ability.type, 'poker_hands')} - - elseif self.ability.name == 'Cavendish' then loc_vars = {self.ability.extra.Xmult, cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged), self.ability.extra.odds} - elseif self.ability.name == 'Card Sharp' then loc_vars = {self.ability.extra.Xmult} - elseif self.ability.name == 'Red Card' then loc_vars = {self.ability.extra, self.ability.mult} - elseif self.ability.name == 'Madness' then loc_vars = {self.ability.extra, self.ability.x_mult} - elseif self.ability.name == 'Square Joker' then loc_vars = {self.ability.extra.chips, self.ability.extra.chip_mod} - elseif self.ability.name == 'Seance' then loc_vars = {localize(self.ability.extra.poker_hand, 'poker_hands')} - elseif self.ability.name == 'Riff-raff' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Vampire' then loc_vars = {self.ability.extra, self.ability.x_mult} - elseif self.ability.name == 'Shortcut' then - elseif self.ability.name == 'Hologram' then loc_vars = {self.ability.extra, self.ability.x_mult} - elseif self.ability.name == 'Vagabond' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Baron' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Cloud 9' then loc_vars = {self.ability.extra, self.ability.extra*(self.ability.nine_tally or 0)} - elseif self.ability.name == 'Rocket' then loc_vars = {self.ability.extra.dollars, self.ability.extra.increase} - elseif self.ability.name == 'Obelisk' then loc_vars = {self.ability.extra, self.ability.x_mult} - elseif self.ability.name == 'Midas Mask' then - elseif self.ability.name == 'Luchador' then - local has_message= (G.GAME and self.area and (self.area == G.jokers)) - if has_message then - local disableable = G.GAME.blind and ((not G.GAME.blind.disabled) and (G.GAME.blind:get_type() == 'Boss')) - main_end = { - {n=G.UIT.C, config={align = "bm", minh = 0.4}, nodes={ - {n=G.UIT.C, config={ref_table = self, align = "m", colour = disableable and G.C.GREEN or G.C.RED, r = 0.05, padding = 0.06}, nodes={ - {n=G.UIT.T, config={text = ' '..localize(disableable and 'k_active' or 'ph_no_boss_active')..' ',colour = G.C.UI.TEXT_LIGHT, scale = 0.32*0.9}}, - }} - }} - } - end - elseif self.ability.name == 'Photograph' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Gift Card' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Turtle Bean' then loc_vars = {self.ability.extra.h_size, self.ability.extra.h_mod} - elseif self.ability.name == 'Erosion' then loc_vars = {self.ability.extra, math.max(0,self.ability.extra*(G.playing_cards and (G.GAME.starting_deck_size - #G.playing_cards) or 0)), G.GAME.starting_deck_size} - elseif self.ability.name == 'Reserved Parking' then loc_vars = {self.ability.extra.dollars, cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged), self.ability.extra.odds} - elseif self.ability.name == 'Mail-In Rebate' then loc_vars = {self.ability.extra, localize(G.GAME.current_round.mail_card.rank, 'ranks')} - elseif self.ability.name == 'To the Moon' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Hallucination' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged), self.ability.extra} - elseif self.ability.name == 'Lucky Cat' then loc_vars = {self.ability.extra, self.ability.x_mult} - elseif self.ability.name == 'Baseball Card' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Bull' then loc_vars = {self.ability.extra, self.ability.extra*math.max(0,G.GAME.dollars) or 0} - elseif self.ability.name == 'Diet Cola' then loc_vars = {localize{type = 'name_text', set = 'Tag', key = 'tag_double', nodes = {}}} - elseif self.ability.name == 'Trading Card' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Flash Card' then loc_vars = {self.ability.extra, self.ability.mult} - elseif self.ability.name == 'Popcorn' then loc_vars = {self.ability.mult, self.ability.extra} - elseif self.ability.name == 'Ramen' then loc_vars = {self.ability.x_mult, self.ability.extra} - elseif self.ability.name == 'Ancient Joker' then loc_vars = {self.ability.extra, localize(G.GAME.current_round.ancient_card.suit, 'suits_singular'), colours = {G.C.SUITS[G.GAME.current_round.ancient_card.suit]}} - elseif self.ability.name == 'Walkie Talkie' then loc_vars = {self.ability.extra.chips, self.ability.extra.mult} - elseif self.ability.name == 'Seltzer' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Castle' then loc_vars = {self.ability.extra.chip_mod, localize(G.GAME.current_round.castle_card.suit, 'suits_singular'), self.ability.extra.chips, colours = {G.C.SUITS[G.GAME.current_round.castle_card.suit]}} - elseif self.ability.name == 'Smiley Face' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Campfire' then loc_vars = {self.ability.extra, self.ability.x_mult} - elseif self.ability.name == 'Stuntman' then loc_vars = {self.ability.extra.chip_mod, self.ability.extra.h_size} - elseif self.ability.name == 'Invisible Joker' then loc_vars = {self.ability.extra, self.ability.invis_rounds} - elseif self.ability.name == 'Brainstorm' then - self.ability.blueprint_compat_ui = self.ability.blueprint_compat_ui or ''; self.ability.blueprint_compat_check = nil - main_end = (self.area and self.area == G.jokers) and { - {n=G.UIT.C, config={align = "bm", minh = 0.4}, nodes={ - {n=G.UIT.C, config={ref_table = self, align = "m", colour = G.C.JOKER_GREY, r = 0.05, padding = 0.06, func = 'blueprint_compat'}, nodes={ - {n=G.UIT.T, config={ref_table = self.ability, ref_value = 'blueprint_compat_ui',colour = G.C.UI.TEXT_LIGHT, scale = 0.32*0.8}}, - }} - }} - } or nil - elseif self.ability.name == 'Satellite' then - local planets_used = 0 - for k, v in pairs(G.GAME.consumeable_usage) do if v.set == 'Planet' then planets_used = planets_used + 1 end end - loc_vars = {self.ability.extra, planets_used*self.ability.extra} - elseif self.ability.name == 'Shoot the Moon' then loc_vars = {self.ability.extra} - elseif self.ability.name == "Driver's License" then loc_vars = {self.ability.extra, self.ability.driver_tally or '0'} - elseif self.ability.name == 'Burnt Joker' then - elseif self.ability.name == 'Bootstraps' then loc_vars = {self.ability.extra.mult, self.ability.extra.dollars, self.ability.extra.mult*math.floor((G.GAME.dollars + (G.GAME.dollar_buffer or 0))/self.ability.extra.dollars)} - elseif self.ability.name == 'Caino' then loc_vars = {self.ability.extra, self.ability.caino_xmult} - elseif self.ability.name == 'Triboulet' then loc_vars = {self.ability.extra} - elseif self.ability.name == 'Yorick' then loc_vars = {self.ability.extra.xmult, self.ability.extra.discards, self.ability.yorick_discards, self.ability.x_mult} - elseif self.ability.name == 'Chicot' then - elseif self.ability.name == 'Perkeo' then loc_vars = {self.ability.extra} - end - end - local badges = {} - if (card_type ~= 'Locked' and card_type ~= 'Undiscovered' and card_type ~= 'Default') or self.debuff then - badges.card_type = card_type - end - if self.ability.set == 'Joker' and self.bypass_discovery_ui and (not no_badge) then - badges.force_rarity = true - end - if self.edition then - if self.edition.type == 'negative' and self.ability.consumeable then - badges[#badges + 1] = 'negative_consumable' - elseif self.edition.type == 'negative' and (self.ability.set == 'Enhanced' or self.ability.set == 'Default') then - badges[#badges + 1] = 'negative_playing_card' - else - badges[#badges + 1] = (self.edition.type == 'holo' and 'holographic' or self.edition.type) - end - end - if self.seal then badges[#badges + 1] = string.lower(self.seal)..'_seal' end - if self.ability.eternal and not self.ability.cry_absolute then badges[#badges + 1] = 'eternal' end - if self.ability.perishable and not layer then - loc_vars = loc_vars or {}; loc_vars.perish_tally=self.ability.perish_tally - badges[#badges + 1] = 'perishable' - end - if self.ability.rental then badges[#badges + 1] = 'rental' end - if self.pinned then - if self.ability.set == 'Booster' then - badges[#badges + 1] = 'cry_pinned_booster' - elseif self.ability.set == 'Voucher' then - badges[#badges + 1] = 'cry_pinned_voucher' - elseif self.ability.consumeable then - badges[#badges + 1] = 'cry_pinned_consumeable' - else - badges[#badges + 1] = 'pinned_left' - end -end - - for k, v in ipairs(SMODS.Sticker.obj_buffer) do - if self.ability[v] and not SMODS.Stickers[v].hide_badge then - badges[#badges+1] = v - end - end - if self.sticker or ((self.sticker_run and self.sticker_run~='NONE') and G.SETTINGS.run_stake_stickers) then loc_vars = loc_vars or {}; loc_vars.sticker=(self.sticker or self.sticker_run) end - - return generate_card_ui(self.config.center, nil, loc_vars, card_type, badges, hide_desc, main_start, main_end, self) -end - -function Card:get_nominal(mod) - local mult = 1 - local rank_mult = 1 - if mod == 'suit' then mult = 10000 end - if self.ability.effect == 'Stone Card' or (self.config.center.no_suit and self.config.center.no_rank) then - mult = -10000 - elseif self.config.center.no_suit then - mult = 0 - elseif self.config.center.no_rank then - rank_mult = 0 - end - return 10*self.base.nominal*rank_mult + self.base.suit_nominal*mult + (self.base.suit_nominal_original or 0)*0.0001*mult + 10*self.base.face_nominal*rank_mult + 0.000001*self.unique_val -end - -function Card:get_id() - if SMODS.has_no_rank(self) and not self.vampired then - return -math.random(100, 1000000) - end - return self.base.id -end - -function Card:is_face(from_boss) - if self.debuff and not from_boss then return end - local id = self:get_id() - local rank = SMODS.Ranks[self.base.value] - if not id then return end - if (id > 0 and rank and rank.face) or next(find_joker("Pareidolia")) then - return true - end -end - -function Card:get_original_rank() - return self.base.original_value -end - -function Card:get_chip_bonus() - if self.debuff then return 0 end - if self.ability.effect == 'Stone Card' or self.config.center.replace_base_card then - return self.ability.bonus + (self.ability.perma_bonus or 0) - end - return self.base.nominal + self.ability.bonus + (self.ability.perma_bonus or 0) -end - -function Card:get_chip_mult() - if self.debuff then return 0 end - if self.ability.set == 'Joker' then return 0 end - if self.ability.effect == "Lucky Card" then - if pseudorandom('lucky_mult') < cry_prob(self.ability.cry_prob, 5, self.ability.cry_rigged)/5 then - self.lucky_trigger = true - return self.ability.mult - else - return 0 - end - else - return self.ability.mult - end -end - -function Card:get_chip_x_mult(context) - if self.debuff then return 0 end - if self.ability.set == 'Joker' then return 0 end - if self.ability.x_mult <= 1 then return 0 end - return self.ability.x_mult -end - -function Card:get_chip_h_mult() - if self.debuff then return 0 end - return self.ability.h_mult -end - -function Card:get_chip_h_x_mult() - if self.debuff then return 0 end - return self.ability.h_x_mult -end - -function Card:get_edition() - if self.debuff then return end - if self.edition then - local ret = {card = self} - if self.edition.p_dollars then - ret.p_dollars_mod = self.edition.p_dollars - end - if self.edition.x_mult then - ret.x_mult_mod = self.edition.x_mult - end - if self.edition.mult then - ret.mult_mod = self.edition.mult - end - if self.edition.chips then - ret.chip_mod = self.edition.chips - end - return ret - end -end - -function Card:get_end_of_round_effect(context) - if self.debuff then return {} end - local ret = {} - if self.ability.h_dollars > 0 then - ret.h_dollars = self.ability.h_dollars - ret.card = self - end - if self.seal == 'Blue' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit and not self.ability.extra_enhancement then - local card_type = 'Planet' - G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 - G.E_MANAGER:add_event(Event({ - trigger = 'before', - delay = 0.0, - func = (function() - if G.GAME.last_hand_played then - local _planet = 0 - for k, v in pairs(G.P_CENTER_POOLS.Planet) do - if v.config.hand_type == G.GAME.last_hand_played then - _planet = v.key - end - end - local card = create_card(card_type,G.consumeables, nil, nil, nil, nil, _planet, 'blusl') - card:add_to_deck() - G.consumeables:emplace(card) - G.GAME.consumeable_buffer = 0 - end - return true - end)})) - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('k_plus_planet'), colour = G.C.SECONDARY_SET.Planet}) - ret.effect = true - end - return ret -end - - -function Card:get_p_dollars() - if self.debuff then return 0 end - local ret = 0 - local obj = G.P_SEALS[self.seal] or {} - if obj.get_p_dollars and type(obj.get_p_dollars) == 'function' then - ret = ret + obj:get_p_dollars(self) - elseif self.seal == 'Gold' then - ret = ret + 3 - end - if self.ability.p_dollars > 0 then - if self.ability.effect == "Lucky Card" then - if pseudorandom('lucky_money') < cry_prob(self.ability.cry_prob, 15, self.ability.cry_rigged)/15 then - self.lucky_trigger = true - ret = ret + self.ability.p_dollars - end - else - ret = ret + self.ability.p_dollars - end - end - if ret > 0 then - G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + ret - if not Talisman.config_file.disable_anims then G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)})) else G.GAME.dollar_buffer = 0 end - end - return ret -end - -function Card:use_consumeable(area, copier) - stop_use() - if not copier then set_consumeable_usage(self) end - if self.debuff then return nil end - local used_tarot = copier or self - if self.ability.rental then - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - blocking = false, - blockable = false, - func = (function() - ease_dollars(-G.GAME.cry_consumeable_rental_rate) - return true - end)})) - end - local gone = false - if self.ability.banana then - if not self.ability.extinct then - if (pseudorandom('oops_it_banana') < G.GAME.probabilities.normal/G.GAME.cry_consumeable_banana_odds) then - local gone = true - self.ability.extinct = true - G.E_MANAGER:add_event(Event({ - func = function() - play_sound('tarot1') - self.T.r = -0.2 - self:juice_up(0.3, 0.4) - self.states.drag.is = true - self.children.center.pinch.x = true - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false, - func = function() - if self.area then self.area:remove_card(self) end - self:remove() - self = nil - return true; end})) - return true - end - })) - card_eval_status_text(self, 'jokers', nil, nil, nil, {message = localize('k_extinct_ex'), delay = 0.1}) - return true - end - end - end - if gone == false then - - if self.ability.consumeable.max_highlighted then - update_hand_text({immediate = true, nopulse = true, delay = 0}, {mult = 0, chips = 0, level = '', handname = ''}) - end - - local obj = self.config.center - if obj.use and type(obj.use) == 'function' then - obj:use(self, area, copier) - return - end if self.ability.consumeable.mod_conv or self.ability.consumeable.suit_conv then - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - play_sound('tarot1') - used_tarot:juice_up(0.3, 0.5) - return true end })) - for i=1, #G.hand.highlighted do - local percent = 1.15 - (i-0.999)/(#G.hand.highlighted-0.998)*0.3 - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.15,func = function() G.hand.highlighted[i]:flip();play_sound('card1', percent);G.hand.highlighted[i]:juice_up(0.3, 0.3);return true end })) - end - delay(0.2) - if self.ability.name == 'Death' then - local rightmost = G.hand.highlighted[1] - for i=1, #G.hand.highlighted do if G.hand.highlighted[i].T.x > rightmost.T.x then rightmost = G.hand.highlighted[i] end end - for i=1, #G.hand.highlighted do - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function() - if G.hand.highlighted[i] ~= rightmost and not G.hand.highlighted[i].ability.eternal then - copy_card(rightmost, G.hand.highlighted[i]) - end - return true end })) - end - elseif self.ability.name == 'Strength' then - for i=1, #G.hand.highlighted do - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function() - local card = G.hand.highlighted[i] - local suit_prefix = string.sub(card.base.suit, 1, 1)..'_' - local rank_suffix = card.base.id == 14 and 2 or math.min(card.base.id+1, 14) - if rank_suffix < 10 then rank_suffix = tostring(rank_suffix) - elseif rank_suffix == 10 then rank_suffix = 'T' - elseif rank_suffix == 11 then rank_suffix = 'J' - elseif rank_suffix == 12 then rank_suffix = 'Q' - elseif rank_suffix == 13 then rank_suffix = 'K' - elseif rank_suffix == 14 then rank_suffix = 'A' - end - card:set_base(G.P_CARDS[suit_prefix..rank_suffix]) - return true end })) - end - elseif self.ability.consumeable.suit_conv then - for i=1, #G.hand.highlighted do - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function() G.hand.highlighted[i]:change_suit(self.ability.consumeable.suit_conv);return true end })) - end - else - for i=1, #G.hand.highlighted do - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function() G.hand.highlighted[i]:set_ability(G.P_CENTERS[self.ability.consumeable.mod_conv]);return true end })) - end - end - for i=1, #G.hand.highlighted do - local percent = 0.85 + (i-0.999)/(#G.hand.highlighted-0.998)*0.3 - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.15,func = function() G.hand.highlighted[i]:flip();play_sound('tarot2', percent, 0.6);G.hand.highlighted[i]:juice_up(0.3, 0.3);return true end })) - end - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2,func = function() G.hand:unhighlight_all(); return true end })) - delay(0.5) - end - if self.ability.name == 'Black Hole' then - update_hand_text({sound = 'button', volume = 0.7, pitch = 0.8, delay = 0.3}, {handname=localize('k_all_hands'),chips = '...', mult = '...', level=''}) - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function() - play_sound('tarot1') - self:juice_up(0.8, 0.5) - G.TAROT_INTERRUPT_PULSE = true - return true end })) - update_hand_text({delay = 0}, {mult = '+', StatusText = true}) - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.9, func = function() - play_sound('tarot1') - self:juice_up(0.8, 0.5) - return true end })) - update_hand_text({delay = 0}, {chips = '+', StatusText = true}) - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.9, func = function() - play_sound('tarot1') - self:juice_up(0.8, 0.5) - G.TAROT_INTERRUPT_PULSE = nil - return true end })) - update_hand_text({sound = 'button', volume = 0.7, pitch = 0.9, delay = 0}, {level='+1'}) - delay(1.3) - for k, v in pairs(G.GAME.hands) do - level_up_hand(self, k, true) - end - update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''}) - end - if self.ability.name == 'Talisman' or self.ability.name == 'Deja Vu' or self.ability.name == 'Trance' or self.ability.name == 'Medium' then - for q = 1, #G.hand.highlighted do - local conv_card = G.hand.highlighted[q] - G.E_MANAGER:add_event(Event({func = function() - play_sound('tarot1') - used_tarot:juice_up(0.3, 0.5) - return true end })) - - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function() - conv_card:set_seal(self.ability.extra, nil, true) - return true end })) - end - delay(0.5) - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2,func = function() G.hand:unhighlight_all(); return true end })) - end--[[ - G.E_MANAGER:add_event(Event({func = function() - play_sound('tarot1') - used_tarot:juice_up(0.3, 0.5) - return true end })) - - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1,func = function() - conv_card:set_seal(self.ability.extra, nil, true) - return true end })) - - delay(0.5) - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2,func = function() G.hand:unhighlight_all(); return true end })) - end - --]] - if self.ability.name == 'Aura' then - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - local over = false - local edition = poll_edition('aura', nil, true, true) - local aura_card = G.hand.highlighted[1] - aura_card:set_edition(edition, true) - used_tarot:juice_up(0.3, 0.5) - return true end })) - end - if self.ability.name == 'Cryptid' then - G.E_MANAGER:add_event(Event({ - func = function() - local _first_dissolve = nil - local new_cards = {} - for i = 1, self.ability.extra do - G.playing_card = (G.playing_card and G.playing_card + 1) or 1 - for q = 1, #G.hand.highlighted do - local _card = copy_card(G.hand.highlighted[q], nil, nil, G.playing_card) - _card:add_to_deck() - G.deck.config.card_limit = G.deck.config.card_limit + 1 - table.insert(G.playing_cards, _card) - G.hand:emplace(_card) - _card:start_materialize(nil, _first_dissolve) - _first_dissolve = true - if _card.config.center.key == "c_cryptid" then check_for_unlock({type = "cryptid_the_cryptid"}) end - new_cards[#new_cards+1] = _card - end - end - playing_card_joker_effects(new_cards) - return true - end - })) - end - if self.ability.name == 'Sigil' or self.ability.name == 'Ouija' then - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - play_sound('tarot1') - used_tarot:juice_up(0.3, 0.5) - return true end })) - for i=1, #G.hand.cards do - local percent = 1.15 - (i-0.999)/(#G.hand.cards-0.998)*0.3 - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.15,func = function() G.hand.cards[i]:flip();play_sound('card1', percent);G.hand.cards[i]:juice_up(0.3, 0.3);return true end })) - end - delay(0.2) - if self.ability.name == 'Sigil' then - local _suit = pseudorandom_element({'S','H','D','C'}, pseudoseed('sigil')) - for i=1, #G.hand.cards do - G.E_MANAGER:add_event(Event({func = function() - local card = G.hand.cards[i] - local suit_prefix = _suit..'_' - local rank_suffix = card.base.id < 10 and tostring(card.base.id) or - card.base.id == 10 and 'T' or card.base.id == 11 and 'J' or - card.base.id == 12 and 'Q' or card.base.id == 13 and 'K' or - card.base.id == 14 and 'A' - card:set_base(G.P_CARDS[suit_prefix..rank_suffix]) - return true end })) - end - end - if self.ability.name == 'Ouija' then - local _rank = pseudorandom_element({'2','3','4','5','6','7','8','9','T','J','Q','K','A'}, pseudoseed('ouija')) - for i=1, #G.hand.cards do - G.E_MANAGER:add_event(Event({func = function() - local card = G.hand.cards[i] - local suit_prefix = string.sub(card.base.suit, 1, 1)..'_' - local rank_suffix =_rank - card:set_base(G.P_CARDS[suit_prefix..rank_suffix]) - return true end })) - end - G.hand:change_size(-1) - end - for i=1, #G.hand.cards do - local percent = 0.85 + (i-0.999)/(#G.hand.cards-0.998)*0.3 - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.15,func = function() G.hand.cards[i]:flip();play_sound('tarot2', percent, 0.6);G.hand.cards[i]:juice_up(0.3, 0.3);return true end })) - end - delay(0.5) - end - if self.ability.consumeable.hand_type then - update_hand_text({sound = 'button', volume = 0.7, pitch = 0.8, delay = 0.3}, {handname=localize(self.ability.consumeable.hand_type, 'poker_hands'),chips = G.GAME.hands[self.ability.consumeable.hand_type].chips, mult = G.GAME.hands[self.ability.consumeable.hand_type].mult, level=G.GAME.hands[self.ability.consumeable.hand_type].level}) - level_up_hand(used_tarot, self.ability.consumeable.hand_type) - update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''}) - end - if self.ability.consumeable.remove_card then - local destroyed_cards = {} - if self.ability.name == 'The Hanged Man' then - for i=#G.hand.highlighted, 1, -1 do - destroyed_cards[#destroyed_cards+1] = G.hand.highlighted[i] - end - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - play_sound('tarot1') - used_tarot:juice_up(0.3, 0.5) - return true end })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.2, - func = function() - for i=#G.hand.highlighted, 1, -1 do - local card = G.hand.highlighted[i] - if SMODS.has_enhancement(card, 'm_glass') then - card:shatter() - else - card:start_dissolve(nil, i == #G.hand.highlighted) - end - end - return true end })) - elseif self.ability.name == 'Familiar' or self.ability.name == 'Grim' or self.ability.name == 'Incantation' then - destroyed_cards[#destroyed_cards+1] = pseudorandom_element(G.hand.cards, pseudoseed('random_destroy')) - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - play_sound('tarot1') - used_tarot:juice_up(0.3, 0.5) - return true end })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.1, - func = function() - for i=#destroyed_cards, 1, -1 do - local card = destroyed_cards[i] - if SMODS.has_enhancement(card, 'm_glass') then - card:shatter() - else - card:start_dissolve(nil, i ~= #destroyed_cards) - end - end - return true end })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.7, - func = function() - local cards = {} - for i=1, self.ability.extra do - cards[i] = true - local _suit, _rank = nil, nil - if self.ability.name == 'Familiar' then - _rank = pseudorandom_element({'J', 'Q', 'K'}, pseudoseed('familiar_create')) - _suit = pseudorandom_element({'S','H','D','C'}, pseudoseed('familiar_create')) - elseif self.ability.name == 'Grim' then - _rank = 'A' - _suit = pseudorandom_element({'S','H','D','C'}, pseudoseed('grim_create')) - elseif self.ability.name == 'Incantation' then - _rank = pseudorandom_element({'2', '3', '4', '5', '6', '7', '8', '9', 'T'}, pseudoseed('incantation_create')) - _suit = pseudorandom_element({'S','H','D','C'}, pseudoseed('incantation_create')) - end - _suit = _suit or 'S'; _rank = _rank or 'A' - local cen_pool = {} - for k, v in pairs(G.P_CENTER_POOLS["Enhanced"]) do - if v.key ~= 'm_stone' then - cen_pool[#cen_pool+1] = v - end - end - create_playing_card({front = G.P_CARDS[_suit..'_'.._rank], center = pseudorandom_element(cen_pool, pseudoseed('spe_card'))}, G.hand, nil, i ~= 1, {G.C.SECONDARY_SET.Spectral}) - end - playing_card_joker_effects(cards) - return true end })) - elseif self.ability.name == 'Immolate' then - local temp_hand = {} - for k, v in ipairs(G.hand.cards) do - if not v.ability.eternal then - temp_hand[#temp_hand+1] = v - end - end - table.sort(temp_hand, function (a, b) return not a.playing_card or not b.playing_card or a.playing_card < b.playing_card end) - pseudoshuffle(temp_hand, pseudoseed('immolate')) - - for i = 1, self.ability.extra.destroy do destroyed_cards[#destroyed_cards+1] = temp_hand[i] end - - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - play_sound('tarot1') - used_tarot:juice_up(0.3, 0.5) - return true end })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.1, - func = function() - for i=#destroyed_cards, 1, -1 do - local card = destroyed_cards[i] - if SMODS.has_enhancement(card, 'm_glass') then - card:shatter() - else - card:start_dissolve(nil, i == #destroyed_cards) - end - end - return true end })) - delay(0.5) - ease_dollars(self.ability.extra.dollars) - end - delay(0.3) - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({remove_playing_cards = true, removed = destroyed_cards}) - end - G.GAME.selected_back:trigger_effect({context = 'remove_playing_cards', removed = destroyed_cards}) - end - if self.ability.name == 'The Fool' then - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - if G.consumeables.config.card_limit > #G.consumeables.cards then - play_sound('timpani') - local card = create_card('Tarot_Planet', G.consumeables, nil, nil, nil, nil, G.GAME.last_tarot_planet, 'fool') - card:add_to_deck() - G.consumeables:emplace(card) - used_tarot:juice_up(0.3, 0.5) - end - return true end })) - delay(0.6) - end - if self.ability.name == 'The Hermit' then - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - play_sound('timpani') - used_tarot:juice_up(0.3, 0.5) - ease_dollars(math.max(0,math.min(G.GAME.dollars, self.ability.extra)), true) - return true end })) - delay(0.6) - end - if self.ability.name == 'Temperance' then - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - play_sound('timpani') - used_tarot:juice_up(0.3, 0.5) - ease_dollars(self.ability.money, true) - return true end })) - delay(0.6) - end - if self.ability.name == 'The Emperor' or self.ability.name == 'The High Priestess' then - for i = 1, math.min((self.ability.consumeable.tarots or self.ability.consumeable.planets), G.consumeables.config.card_limit - #G.consumeables.cards) do - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - if G.consumeables.config.card_limit > #G.consumeables.cards then - play_sound('timpani') - local card = create_card((self.ability.name == 'The Emperor' and 'Tarot') or (self.ability.name == 'The High Priestess' and 'Planet'), G.consumeables, nil, nil, nil, nil, nil, (self.ability.name == 'The Emperor' and 'emp') or (self.ability.name == 'The High Priestess' and 'pri')) - card:add_to_deck() - G.consumeables:emplace(card) - used_tarot:juice_up(0.3, 0.5) - end - return true end })) - end - delay(0.6) - end - if self.ability.name == 'Judgement' or self.ability.name == 'The Soul' then - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - play_sound('timpani') - local card = create_card('Joker', G.jokers, self.ability.name == 'The Soul', nil, nil, nil, nil, self.ability.name == 'Judgement' and 'jud' or 'sou') - card:add_to_deck() - G.jokers:emplace(card) - if self.ability.name == 'The Soul' then check_for_unlock{type = 'spawn_legendary'} end - used_tarot:juice_up(0.3, 0.5) - return true end })) - delay(0.6) - end - if self.ability.name == 'Ankh' then - --Need to check for edgecases - if there are max Jokers and all are eternal OR there is a max of 1 joker this isn't possible already - --If there are max Jokers and exactly 1 is not eternal, that joker cannot be the one selected - --otherwise, the selected joker can be totally random and all other non-eternal jokers can be removed - local deletable_jokers = {} - for k, v in pairs(G.jokers.cards) do - if not v.ability.eternal then deletable_jokers[#deletable_jokers + 1] = v end - end - local chosen_joker = pseudorandom_element(G.jokers.cards, pseudoseed('ankh_choice')) - local _first_dissolve = nil - G.E_MANAGER:add_event(Event({trigger = 'before', delay = 0.75, func = function() - for k, v in pairs(deletable_jokers) do - if v ~= chosen_joker then - v:start_dissolve(nil, _first_dissolve) - _first_dissolve = true - end - end - return true end })) - G.E_MANAGER:add_event(Event({trigger = 'before', delay = 0.4, func = function() - local card = copy_card(chosen_joker, nil, nil, nil, chosen_joker.edition and chosen_joker.edition.negative) - card:start_materialize() - card:add_to_deck() - if card.edition and card.edition.negative then - card:set_edition(nil, true) - end - G.jokers:emplace(card) - return true end })) - end - if self.ability.name == 'Wraith' then - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - play_sound('timpani') - local card = create_card('Joker', G.jokers, nil, 0.99, nil, nil, nil, 'wra') - card:add_to_deck() - G.jokers:emplace(card) - used_tarot:juice_up(0.3, 0.5) - if G.GAME.dollars ~= 0 then - ease_dollars(-G.GAME.dollars, true) - end - return true end })) - delay(0.6) - end - if self.ability.name == 'The Wheel of Fortune' or self.ability.name == 'Ectoplasm' or self.ability.name == 'Hex' then - local temp_pool = (self.ability.name == 'The Wheel of Fortune' and self.eligible_strength_jokers) or - ((self.ability.name == 'Ectoplasm' or self.ability.name == 'Hex') and self.eligible_editionless_jokers) or {} - if self.ability.name == 'Ectoplasm' or self.ability.name == 'Hex' or pseudorandom('wheel_of_fortune') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then -if self.ability.name == 'The Wheel of Fortune' then self.cry_wheel_success = true end - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - local over = false - local eligible_card = pseudorandom_element(temp_pool, pseudoseed( - (self.ability.name == 'The Wheel of Fortune' and 'wheel_of_fortune') or - (self.ability.name == 'Ectoplasm' and 'ectoplasm') or - (self.ability.name == 'Hex' and 'hex') - )) - local edition = nil - if self.ability.name == 'Ectoplasm' then - edition = {negative = true} - elseif self.ability.name == 'Hex' then - edition = {polychrome = true} - elseif self.ability.name == 'The Wheel of Fortune' then - edition = poll_edition('wheel_of_fortune', nil, true, true) - end - eligible_card:set_edition(edition, true) - if self.ability.name == 'The Wheel of Fortune' or self.ability.name == 'Ectoplasm' or self.ability.name == 'Hex' then check_for_unlock({type = 'have_edition'}) end - if self.ability.name == 'Hex' then - local _first_dissolve = nil - for k, v in pairs(G.jokers.cards) do - if v ~= eligible_card and (not v.ability.eternal) then v:start_dissolve(nil, _first_dissolve);_first_dissolve = true end - end - end - if self.ability.name == 'Ectoplasm' then - G.GAME.ecto_minus = G.GAME.ecto_minus or 1 - G.hand:change_size(-G.GAME.ecto_minus) - G.GAME.ecto_minus = G.GAME.ecto_minus + 1 - end - used_tarot:juice_up(0.3, 0.5) - return true end })) - else - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - attention_text({ - text = localize('k_nope_ex'), - scale = 1.3, - hold = 1.4, - major = used_tarot, - backdrop_colour = G.C.SECONDARY_SET.Tarot, - align = (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) and 'tm' or 'cm', - offset = {x = 0, y = (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) and -0.2 or 0}, - silent = true - }) - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.06*G.SETTINGS.GAMESPEED, blockable = false, blocking = false, func = function() - play_sound('tarot2', 0.76, 0.4);return true end})) - play_sound('tarot2', 1, 0.4) - used_tarot:juice_up(0.3, 0.5) - return true end })) - end - delay(0.6) - end -end - -end -function Card:can_use_consumeable(any_state, skip_check) - if not skip_check and ((G.play and #G.play.cards > 0) or - (G.CONTROLLER.locked) or - (G.GAME.STOP_USE and G.GAME.STOP_USE > 0)) - then return false end - if G.GAME.cry_pinned_consumeables > 0 and not self.pinned then - return false - end - if G.STATE ~= G.STATES.HAND_PLAYED and G.STATE ~= G.STATES.DRAW_TO_HAND and G.STATE ~= G.STATES.PLAY_TAROT or any_state then - - local obj = self.config.center - if obj.can_use and type(obj.can_use) == 'function' then - return obj:can_use(self) - end if self.ability.name == 'The Hermit' or self.ability.consumeable.hand_type or self.ability.name == 'Temperance' or self.ability.name == 'Black Hole' then - return true - end - if self.ability.name == 'The Wheel of Fortune' then - if next(self.eligible_strength_jokers) then return true end - end - if self.ability.name == 'Ankh' then - --if there is at least one joker - for k, v in pairs(G.jokers.cards) do - if v.ability.set == 'Joker' and G.jokers.config.card_limit > 1 then - return true - end - end - end - --]] - if self.ability.name == 'Aura' then - if self.area ~= G.hand then - return G.hand and (#G.hand.highlighted == 1) and G.hand.highlighted[1] and (not G.hand.highlighted[1].edition) - else - local idx = 1 - if G.hand.highlighted[1] == self then - local idx = 2 - end - return (#G.hand.highlighted == 2) and (not G.hand.highlighted[idx].edition) - end - end - if self.ability.name == 'Ectoplasm' or self.ability.name == 'Hex' then - if next(self.eligible_editionless_jokers) then return true end - end - if self.ability.name == 'The Emperor' or self.ability.name == 'The High Priestess' then - if #G.consumeables.cards < G.consumeables.config.card_limit or self.area == G.consumeables then return true end - end - if self.ability.name == 'The Fool' then - if (#G.consumeables.cards < G.consumeables.config.card_limit or self.area == G.consumeables) - and G.GAME.last_tarot_planet and G.GAME.last_tarot_planet ~= 'c_fool' then return true end - end - if self.ability.name == 'Judgement' or self.ability.name == 'The Soul' or self.ability.name == 'Wraith' then - if #G.jokers.cards < G.jokers.config.card_limit or self.area == G.jokers then - return true - else - return false - end - end - if G.STATE == G.STATES.SELECTING_HAND or G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED then - if self.ability.consumeable.max_highlighted then - if (self.ability.consumeable.mod_num - ((G.GAME.modifiers.cry_consumable_reduce and (self.ability.name ~= 'Death')) and (self.ability.consumeable.mod_num > 1) and 1 or 0)) >= #G.hand.highlighted + (self.area == G.hand and -1 or 0) and #G.hand.highlighted + (self.area == G.hand and -1 or 0) >= 1 then - return true - end - end - if (self.ability.name == 'Familiar' or self.ability.name == 'Grim' or - self.ability.name == 'Incantation' or self.ability.name == 'Immolate' or - self.ability.name == 'Sigil' or self.ability.name == 'Ouija') - and #G.hand.cards > 1 then - return true - end - end - end - return false -end - -function Card:check_use() - if self.ability.name == 'Ankh' then - if #G.jokers.cards >= G.jokers.config.card_limit then - alert_no_space(self, G.jokers) - return true - end - end -end - -function Card:sell_card() - G.CONTROLLER.locks.selling_card = true - stop_use() - local area = self.area - G.CONTROLLER:save_cardarea_focus(area == G.jokers and 'jokers' or 'consumeables') - - if self.children.use_button then self.children.use_button:remove(); self.children.use_button = nil end - if self.children.sell_button then self.children.sell_button:remove(); self.children.sell_button = nil end - - if self.config.center.set == 'Joker' then - if G.GAME.jokers_sold then - local contained = false - for i = 1, #G.GAME.jokers_sold do - if self.config.center.key == G.GAME.jokers_sold[i] then contained = true end - end - if not contained then table.insert(G.GAME.jokers_sold, self.config.center.key) end - else - G.GAME.jokers_sold = {self.config.center.key} - end - end - self:calculate_joker{selling_self = true} - - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2,func = function() - if not G.GAME.modifiers.cry_no_sell_value then play_sound('coin2') end - self:juice_up(0.3, 0.4) - return true - end})) - delay(0.2) - G.E_MANAGER:add_event(Event({trigger = 'immediate',func = function() - if not G.GAME.modifiers.cry_no_sell_value then ease_dollars(self.sell_cost) end - if G.GAME.modifiers.cry_no_sell_value then self:start_dissolve({G.C.RED}) else self:start_dissolve({G.C.GOLD}) end - delay(0.3) - - inc_career_stat('c_cards_sold', 1) - if self.ability.set == 'Joker' then - inc_career_stat('c_jokers_sold', 1) - end - if self.ability.set == 'Joker' and G.GAME.blind and G.GAME.blind.name == 'Verdant Leaf' then - G.E_MANAGER:add_event(Event({trigger = 'immediate',func = function() - G.GAME.blind:disable() - return true - end})) - end - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.3, blocking = false, - func = function() - G.E_MANAGER:add_event(Event({trigger = 'immediate', - func = function() - G.E_MANAGER:add_event(Event({trigger = 'immediate', - func = function() - G.CONTROLLER.locks.selling_card = nil - G.CONTROLLER:recall_cardarea_focus(area == G.jokers and 'jokers' or 'consumeables') - return true - end})) - return true - end})) - return true - end})) - return true - end})) -end - -function Card:can_sell_card(context) - if (G.play and #G.play.cards > 0) or - (G.CONTROLLER.locked) or - (G.GAME.STOP_USE and G.GAME.STOP_USE > 0) --or - --G.STATE == G.STATES.BLIND_SELECT - then return false end - if (G.SETTINGS.tutorial_complete or G.GAME.pseudorandom.seed ~= 'TUTORIAL' or G.GAME.round_resets.ante > 1) and - self.area and - self.area.config.type == 'joker' and - not self.ability.eternal then - return true - end - return false -end - -function Card:calculate_dollar_bonus() - if self.debuff then return end - if self.ability.set == "Joker" then - if self.ability.name == 'Golden Joker' then - return self.ability.extra - end - --asdf - local obj = self.config.center - if obj.calc_dollar_bonus and type(obj.calc_dollar_bonus) == 'function' then - return obj:calc_dollar_bonus(self) - end - if self.ability.name == 'Cloud 9' and self.ability.nine_tally and self.ability.nine_tally > 0 then - return self.ability.extra*(self.ability.nine_tally) - end - if self.ability.name == 'Rocket' then - return self.ability.extra.dollars - end - if self.ability.name == 'Satellite' then - local planets_used = 0 - for k, v in pairs(G.GAME.consumeable_usage) do - if v.set == 'Planet' then planets_used = planets_used + 1 end - end - if planets_used == 0 then return end - return self.ability.extra*planets_used - end - if self.ability.name == 'Delayed Gratification' and G.GAME.current_round.discards_used == 0 and G.GAME.current_round.discards_left > 0 then - return G.GAME.current_round.discards_left*self.ability.extra - end - end -end - -function Card:open() - if self.ability.set == "Booster" then - stop_use() - G.STATE_COMPLETE = false - self.opening = true - - if not self.config.center.discovered then - discover_card(self.config.center) - end - self.states.hover.can = false - - booster_obj = self.config.center - if booster_obj and SMODS.Centers[booster_obj.key] then - G.STATE = G.STATES.SMODS_BOOSTER_OPENED - SMODS.OPENED_BOOSTER = self - end if self.ability.name:find('Arcana') then - G.STATE = G.STATES.TAROT_PACK - G.GAME.pack_size = self.ability.extra - elseif self.ability.name:find('Celestial') then - G.STATE = G.STATES.PLANET_PACK - G.GAME.pack_size = self.ability.extra - elseif self.ability.name:find('Spectral') then - G.STATE = G.STATES.SPECTRAL_PACK - G.GAME.pack_size = self.ability.extra - elseif self.ability.name:find('Standard') then - G.STATE = G.STATES.STANDARD_PACK - G.GAME.pack_size = self.ability.extra - elseif self.ability.name:find('Buffoon') then - G.STATE = G.STATES.BUFFOON_PACK - G.GAME.pack_size = self.ability.extra - end - - G.GAME.pack_choices = self.config.center.config.choose or 1 - G.GAME.pack_choices = ((self.ability.choose and self.ability.extra) and math.min(math.floor(self.ability.extra), self.ability.choose)) or 1 - if G.GAME.modifiers.cry_misprint_min then - G.GAME.pack_size = self.ability.extra - if G.GAME.pack_size < 1 then G.GAME.pack_size = 1 end - self.ability.extra = G.GAME.pack_size - G.GAME.pack_choices = math.min(math.floor(G.GAME.pack_size), self.ability.choose) - --G.GAME.pack_choices = math.min(math.floor(G.GAME.pack_size),cry_format(G.GAME.pack_choices * cry_log_random(pseudoseed('cry_misprint_p'..G.GAME.round_resets.ante),G.GAME.modifiers.cry_misprint_min,G.GAME.modifiers.cry_misprint_max),"%.2f")) - end - if G.GAME.cry_oboe then - self.ability.extra = self.ability.extra + G.GAME.cry_oboe - G.GAME.pack_choices = G.GAME.pack_choices + G.GAME.cry_oboe - G.GAME.cry_oboe = nil - G.GAME.pack_size = self.ability.extra - end - if G.GAME.boostertag then - self.ability.extra = self.ability.extra * 2 - G.GAME.pack_choices = G.GAME.pack_choices * 2 - G.GAME.boostertag = nil - G.GAME.pack_size = self.ability.extra - end - - if self.cost > 0 then - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function() - inc_career_stat('c_shop_dollars_spent', self.cost) - self:juice_up() - return true end })) - ease_dollars(-self.cost) - else - delay(0.2) - end - - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - self:explode() - local pack_cards = {} - - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 1.3*math.sqrt(G.SETTINGS.GAMESPEED), blockable = false, blocking = false, func = function() - local _size = self.ability.extra - - for i = 1, _size do - local card = nil - if booster_obj.create_card and type(booster_obj.create_card) == "function" then - local _card_to_spawn = booster_obj:create_card(self, i) - if type((_card_to_spawn or {}).is) == 'function' and _card_to_spawn:is(Card) then - card = _card_to_spawn - else - card = SMODS.create_card(_card_to_spawn) - end - elseif self.ability.name:find('Arcana') then - if G.GAME.used_vouchers.v_omen_globe and pseudorandom('omen_globe') > 0.8 then - card = create_card("Spectral", G.pack_cards, nil, nil, true, true, nil, 'ar2') - else - card = create_card("Tarot", G.pack_cards, nil, nil, true, true, nil, 'ar1') - end - elseif self.ability.name:find('Celestial') then - if G.GAME.used_vouchers.v_telescope and i == 1 then - local _planet, _hand, _tally = nil, nil, 0 - for k, v in ipairs(G.handlist) do - if G.GAME.hands[v].visible and G.GAME.hands[v].played > _tally then - _hand = v - _tally = G.GAME.hands[v].played - end - end - if _hand then - for k, v in pairs(G.P_CENTER_POOLS.Planet) do - if v.config.hand_type == _hand then - _planet = v.key - end - end - end - card = create_card("Planet", G.pack_cards, nil, nil, true, true, _planet, 'pl1') - else - if G.GAME.used_vouchers.v_cry_satellite_uplink and pseudorandom('cry_satellite_uplink') > 0.8 then - card = create_card("Code", G.pack_cards, nil, nil, true, true, nil, 'pl2') - else - card = create_card("Planet", G.pack_cards, nil, nil, true, true, nil, 'pl1') - end - end - elseif self.ability.name:find('Spectral') then - card = create_card("Spectral", G.pack_cards, nil, nil, true, true, nil, 'spe') - elseif self.ability.name:find('Standard') then - card = create_card((pseudorandom(pseudoseed('stdset'..G.GAME.round_resets.ante)) > 0.6) and "Enhanced" or "Base", G.pack_cards, nil, nil, nil, true, nil, 'sta') - local edition_rate = 2 - local edi = self.edition or {} -if edi.type and not (G.GAME.modifiers.cry_force_edition and G.GAME.modifiers.cry_force_edition ~= 'random') then - card:set_edition({[edi.type] = true}) -elseif not G.GAME.modifiers.cry_force_random_edition then - local edition = poll_edition('standard_edition'..G.GAME.round_resets.ante, edition_rate, true) - card:set_edition(edition) -end - - card:set_seal(SMODS.poll_seal({mod = 10})) - elseif self.ability.name:find('Buffoon') then - card = create_card("Joker", G.pack_cards, nil, nil, true, true, nil, 'buf') - - end - local edi = self.edition or {} - if edi.type and not self.ability.name:find('Standard') then - if card.ability.name ~= "cry-meteor" - and card.ability.name ~= "cry-exoplanet" - and card.ability.name ~= "cry-stardust" then - card:set_edition({[edi.type] = true}) - end - end - if self.ability.eternal then - card.ability.eternal = self.ability.eternal - end - if self.ability.perishable and not layer then - card.ability.perishable = self.ability.perishable - end - if self.ability.rental then - card.ability.rental = self.ability.rental - end - if self.pinned then - card.pinned = self.pinned - end - if self.ability.banana then - card.ability.banana = self.ability.banana - end - card.T.x = self.T.x - card.T.y = self.T.y - card:start_materialize({G.C.WHITE, G.C.WHITE}, nil, 1.5*G.SETTINGS.GAMESPEED) - pack_cards[i] = card - end - return true - end})) - - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 1.3*math.sqrt(G.SETTINGS.GAMESPEED), blockable = false, blocking = false, func = function() - if G.pack_cards then - if G.pack_cards and G.pack_cards.VT.y < G.ROOM.T.h then - for k, v in ipairs(pack_cards) do - G.pack_cards:emplace(v) - end - return true - end - end - end})) - - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({open_booster = true, card = self}) - end - G.GAME.selected_back:trigger_effect({context = 'open_booster', card = self}) - - if G.GAME.modifiers.inflation then - G.GAME.inflation = G.GAME.inflation + 1 - G.E_MANAGER:add_event(Event({func = function() - for k, v in pairs(G.I.CARD) do - if v.set_cost then v:set_cost() end - end - return true end })) - end - - return true end })) - end -end - -function Card:redeem() - if self.ability.set == "Voucher" then - stop_use() - if not self.config.center.discovered then - discover_card(self.config.center) - end - if self.shop_voucher then G.GAME.current_round.voucher = nil end - G.GAME.cry_voucher_centers[self.config.center_key].config.extra = self.ability.extra - if self.ability.extra_disp then G.GAME.cry_voucher_centers[self.config.center_key].config.extra_disp = self.ability.extra_disp end - - self.states.hover.can = false - G.GAME.cry_owned_vouchers[self.config.center_key] = true - G.GAME.used_vouchers[self.config.center_key] = true - local top_dynatext = nil - local bot_dynatext = nil - - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function() - top_dynatext = DynaText({string = localize{type = 'name_text', set = self.config.center.set, key = self.config.center.key}, colours = {G.C.WHITE}, rotate = 1,shadow = true, bump = true,float=true, scale = 0.9, pop_in = 0.6/G.SPEEDFACTOR, pop_in_rate = 1.5*G.SPEEDFACTOR}) - bot_dynatext = DynaText({string = localize('k_redeemed_ex'), colours = {G.C.WHITE}, rotate = 2,shadow = true, bump = true,float=true, scale = 0.9, pop_in = 1.4/G.SPEEDFACTOR, pop_in_rate = 1.5*G.SPEEDFACTOR, pitch_shift = 0.25}) - self:juice_up(0.3, 0.5) - play_sound('card1') - play_sound('coin1') - self.children.top_disp = UIBox{ - definition = {n=G.UIT.ROOT, config = {align = 'tm', r = 0.15, colour = G.C.CLEAR, padding = 0.15}, nodes={ - {n=G.UIT.O, config={object = top_dynatext}} - }}, - config = {align="tm", offset = {x=0,y=0},parent = self} - } - self.children.bot_disp = UIBox{ - definition = {n=G.UIT.ROOT, config = {align = 'tm', r = 0.15, colour = G.C.CLEAR, padding = 0.15}, nodes={ - {n=G.UIT.O, config={object = bot_dynatext}} - }}, - config = {align="bm", offset = {x=0,y=0},parent = self} - } - return true end })) - if self.cost ~= 0 then - ease_dollars(-self.cost) - inc_career_stat('c_shop_dollars_spent', self.cost) - end - inc_career_stat('c_vouchers_bought', 1) - set_voucher_usage(self) - check_for_unlock({type = 'run_redeem'}) - -- G.GAME.current_round.voucher = nil - if self.shop_cry_bonusvoucher then G.GAME.cry_bonusvouchersused[self.shop_cry_bonusvoucher] = true end - - G.GAME.current_round.cry_voucher_edition = nil - G.GAME.current_round.cry_voucher_stickers = {eternal = false, perishable = false, rental = false, pinned = false, banana = false} - self:apply_to_run() - - delay(0.6) - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({buying_card = true, card = self}) - end - G.GAME.selected_back:trigger_effect({context = 'buying_card', card = self}) - if G.GAME.modifiers.inflation then - G.GAME.inflation = G.GAME.inflation + 1 - G.E_MANAGER:add_event(Event({func = function() - for k, v in pairs(G.I.CARD) do - if v.set_cost then v:set_cost() end - end - return true end })) - end - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 2.6, func = function() - top_dynatext:pop_out(4) - bot_dynatext:pop_out(4) - return true end })) - - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.5, func = function() - self.children.top_disp:remove() - self.children.top_disp = nil - self.children.bot_disp:remove() - self.children.bot_disp = nil - return true end })) - end -end - -function Card:apply_to_run(center) - local center_table = { - name = center and center.name or self and self.ability.name, - extra = self and G.GAME.cry_voucher_centers[self.config.center_key].config.extra or center and center.config.extra - } - local obj = center or self.config.center - if obj.redeem and type(obj.redeem) == 'function' then - obj:redeem(self) - return - end if center_table.name == 'Overstock' or center_table.name == 'Overstock Plus' then - G.E_MANAGER:add_event(Event({func = function() - change_shop_size(center_table.extra) - return true end })) - end - if center_table.name == 'Tarot Merchant' or center_table.name == 'Tarot Tycoon' then - G.E_MANAGER:add_event(Event({func = function() - G.GAME.tarot_rate = 4*center_table.extra - return true end })) - end - if center_table.name == 'Planet Merchant' or center_table.name == 'Planet Tycoon' then - G.E_MANAGER:add_event(Event({func = function() - G.GAME.planet_rate = 4*center_table.extra - return true end })) - end - if center_table.name == 'Hone' or center_table.name == 'Glow Up' then - G.E_MANAGER:add_event(Event({func = function() - G.GAME.edition_rate = center_table.extra - return true end })) - end - if center_table.name == 'Magic Trick' or center_table.name == 'Illusion' then - G.E_MANAGER:add_event(Event({func = function() - G.GAME.playing_card_rate = center_table.extra - return true end })) - end - if center_table.name == 'Telescope' or center_table.name == 'Observatory' then - end - if center_table.name == 'Crystal Ball' then - G.E_MANAGER:add_event(Event({func = function() - G.consumeables.config.card_limit = G.consumeables.config.card_limit + center_table.extra - return true end })) - end - - if center_table.name == 'Clearance Sale' or center_table.name == 'Liquidation' then - G.E_MANAGER:add_event(Event({func = function() - G.GAME.discount_percent = center_table.extra - for k, v in pairs(G.I.CARD) do - if v.set_cost then v:set_cost() end - end - return true end })) - end - if center_table.name == 'Reroll Surplus' or center_table.name == 'Reroll Glut' then - G.E_MANAGER:add_event(Event({func = function() - G.GAME.round_resets.reroll_cost = G.GAME.round_resets.reroll_cost - center_table.extra - G.GAME.current_round.reroll_cost = math.max(0, G.GAME.current_round.reroll_cost - center_table.extra) - return true end })) - end - if center_table.name == 'Seed Money' or center_table.name == 'Money Tree' then - G.E_MANAGER:add_event(Event({func = function() - G.GAME.interest_cap = center_table.extra - return true end })) - end - if center_table.name == 'Grabber' or center_table.name == 'Nacho Tong' then - G.GAME.round_resets.hands = G.GAME.round_resets.hands + center_table.extra - ease_hands_played(center_table.extra) - end - if center_table.name == 'Paint Brush' or center_table.name == 'Palette' then - G.hand:change_size(center_table.extra) - end - if center_table.name == 'Wasteful' or center_table.name == 'Recyclomancy' then - G.GAME.round_resets.discards = G.GAME.round_resets.discards + center_table.extra - ease_discard(center_table.extra) - end - if center_table.name == 'Blank' then - check_for_unlock({type = 'blank_redeems'}) - end - if center_table.name == 'Antimatter' then - G.E_MANAGER:add_event(Event({func = function() - if G.jokers then - G.jokers.config.card_limit = G.jokers.config.card_limit + center_table.extra - end - return true end })) - end - - if center_table.name == 'Hieroglyph' or center_table.name == 'Petroglyph' then - ease_ante(math.floor(-center_table.extra)) - G.GAME.round_resets.blind_ante = G.GAME.round_resets.blind_ante or G.GAME.round_resets.ante - G.GAME.round_resets.blind_ante = G.GAME.round_resets.blind_ante-center_table.extra - - if center_table.name == 'Hieroglyph' then - G.GAME.round_resets.hands = G.GAME.round_resets.hands - center_table.extra - ease_hands_played(-center_table.extra) - end - if center_table.name == 'Petroglyph' then - G.GAME.round_resets.discards = G.GAME.round_resets.discards - center_table.extra - ease_discard(-center_table.extra) - end - end -end - -function Card:explode(dissolve_colours, explode_time_fac) - local explode_time = 1.3*(explode_time_fac or 1)*(math.sqrt(G.SETTINGS.GAMESPEED)) - self.dissolve = 0 - self.dissolve_colours = dissolve_colours - or {G.C.WHITE} - - local start_time = G.TIMERS.TOTAL - local percent = 0 - play_sound('explosion_buildup1') - self.juice = { - scale = 0, - r = 0, - handled_elsewhere = true, - start_time = start_time, - end_time = start_time + explode_time - } - - local childParts1 = Particles(0, 0, 0,0, { - timer_type = 'TOTAL', - timer = 0.01*explode_time, - scale = 0.2, - speed = 2, - lifespan = 0.2*explode_time, - attach = self, - colours = self.dissolve_colours, - fill = true - }) - local childParts2 = nil - - G.E_MANAGER:add_event(Event({ - blockable = false, - func = (function() - if self.juice then - percent = (G.TIMERS.TOTAL - start_time)/explode_time - self.juice.r = 0.05*(math.sin(5*G.TIMERS.TOTAL) + math.cos(0.33 + 41.15332*G.TIMERS.TOTAL) + math.cos(67.12*G.TIMERS.TOTAL))*percent - self.juice.scale = percent*0.15 - end - if G.TIMERS.TOTAL - start_time > 1.5*explode_time then return true end - end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - blockable = false, - ref_table = self, - ref_value = 'dissolve', - ease_to = 0.3, - delay = 0.9*explode_time, - func = (function(t) return t end) - })) - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 0.9*explode_time, - func = (function() - childParts2 = Particles(0, 0, 0,0, { - timer_type = 'TOTAL', - pulse_max = 30, - timer = 0.003, - scale = 0.6, - speed = 15, - lifespan = 0.5, - attach = self, - colours = self.dissolve_colours, - }) - childParts2:set_role({r_bond = 'Weak'}) - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - blockable = false, - ref_table = self, - ref_value = 'dissolve', - ease_to = 1, - delay = 0.1*explode_time, - func = (function(t) return t end) - })) - self:juice_up() - G.VIBRATION = G.VIBRATION + 1 - play_sound('explosion_release1') - childParts1:fade(0.3*explode_time) return true end) - })) - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 1.4*explode_time, - func = (function() - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - blockable = false, - blocking = false, - ref_value = 'scale', - ref_table = childParts2, - ease_to = 0, - delay = 0.1*explode_time - })) - return true end) - })) - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 1.5*explode_time, - func = (function() self:remove() return true end) - })) -end - -function Card:shatter() - local dissolve_time = 0.7 - self.shattered = true - self.dissolve = 0 - self.dissolve_colours = {{1,1,1,0.8}} - self:juice_up() - local childParts = Particles(0, 0, 0,0, { - timer_type = 'TOTAL', - timer = 0.007*dissolve_time, - scale = 0.3, - speed = 4, - lifespan = 0.5*dissolve_time, - attach = self, - colours = self.dissolve_colours, - fill = true - }) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 0.5*dissolve_time, - func = (function() childParts:fade(0.15*dissolve_time) return true end) - })) - G.E_MANAGER:add_event(Event({ - blockable = false, - func = (function() - play_sound('glass'..math.random(1, 6), math.random()*0.2 + 0.9,0.5) - play_sound('generic1', math.random()*0.2 + 0.9,0.5) - return true end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - blockable = false, - ref_table = self, - ref_value = 'dissolve', - ease_to = 1, - delay = 0.5*dissolve_time, - func = (function(t) return t end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 0.55*dissolve_time, - func = (function() self:remove() return true end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 0.51*dissolve_time, - })) -end - -function Card:start_dissolve(dissolve_colours, silent, dissolve_time_fac, no_juice) - local dissolve_time = 0.7*(dissolve_time_fac or 1) - self.dissolve = 0 - self.dissolve_colours = dissolve_colours - or {G.C.BLACK, G.C.ORANGE, G.C.RED, G.C.GOLD, G.C.JOKER_GREY} - if not no_juice then self:juice_up() end - local childParts = Particles(0, 0, 0,0, { - timer_type = 'TOTAL', - timer = 0.01*dissolve_time, - scale = 0.1, - speed = 2, - lifespan = 0.7*dissolve_time, - attach = self, - colours = self.dissolve_colours, - fill = true - }) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 0.7*dissolve_time, - func = (function() childParts:fade(0.3*dissolve_time) return true end) - })) - if not silent then - G.E_MANAGER:add_event(Event({ - blockable = false, - func = (function() - play_sound('whoosh2', math.random()*0.2 + 0.9,0.5) - play_sound('crumple'..math.random(1, 5), math.random()*0.2 + 0.9,0.5) - return true end) - })) - end - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - blockable = false, - ref_table = self, - ref_value = 'dissolve', - ease_to = 1, - delay = 1*dissolve_time, - func = (function(t) return t end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 1.05*dissolve_time, - func = (function() self:remove() return true end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 1.051*dissolve_time, - })) -end - -function Card:start_materialize(dissolve_colours, silent, timefac) - local dissolve_time = 0.6*(timefac or 1) - self.states.visible = true - self.states.hover.can = false - self.dissolve = 1 - self.dissolve_colours = dissolve_colours or - (self.ability.set == 'Joker' and {G.C.RARITY[self.config.center.rarity]}) or - (self.ability.set == 'Planet' and {G.C.SECONDARY_SET.Planet}) or - (self.ability.set == 'Tarot' and {G.C.SECONDARY_SET.Tarot}) or - (self.ability.set == 'Spectral' and {G.C.SECONDARY_SET.Spectral}) or - (self.ability.set == 'Booster' and {G.C.BOOSTER}) or - (self.ability.set == 'Voucher' and {G.C.SECONDARY_SET.Voucher, G.C.CLEAR}) or - {G.C.GREEN} - self:juice_up() - self.children.particles = Particles(0, 0, 0,0, { - timer_type = 'TOTAL', - timer = 0.025*dissolve_time, - scale = 0.25, - speed = 3, - lifespan = 0.7*dissolve_time, - attach = self, - colours = self.dissolve_colours, - fill = true - }) - if not silent then - if not G.last_materialized or G.last_materialized +0.01 < G.TIMERS.REAL or G.last_materialized > G.TIMERS.REAL then - G.last_materialized = G.TIMERS.REAL - G.E_MANAGER:add_event(Event({ - blockable = false, - func = (function() - play_sound('whoosh1', math.random()*0.1 + 0.6,0.3) - play_sound('crumple'..math.random(1,5), math.random()*0.2 + 1.2,0.8) - return true end) - })) - end - end - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 0.5*dissolve_time, - func = (function() if self.children.particles then self.children.particles.max = 0 end return true end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - blockable = false, - ref_table = self, - ref_value = 'dissolve', - ease_to = 0, - delay = 1*dissolve_time, - func = (function(t) return t end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 1.05*dissolve_time, - func = (function() self.states.hover.can = true; if self.children.particles then self.children.particles:remove(); self.children.particles = nil end return true end) - })) -end - -function Card:calculate_seal(context) - if self.debuff then return nil end local obj = G.P_SEALS[self.seal] or {} - if obj.calculate and type(obj.calculate) == 'function' then - local o = obj:calculate(self, context) - if o then return o end - end - if context.repetition then - if self.seal == 'Red' then - return { - message = localize('k_again_ex'), - repetitions = 1, - card = self - } - end - end - if context.discard then - if self.seal == 'Purple' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then - G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 - G.E_MANAGER:add_event(Event({ - trigger = 'before', - delay = 0.0, - func = (function() - local card = create_card('Tarot',G.consumeables, nil, nil, nil, nil, nil, '8ba') - card:add_to_deck() - G.consumeables:emplace(card) - G.GAME.consumeable_buffer = 0 - return true - end)})) - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('k_plus_tarot'), colour = G.C.PURPLE}) - end - end -end - -function Card:calculate_rental() - if self.ability.rental then - ease_dollars(-G.GAME.rental_rate) - card_eval_status_text(self, 'dollars', -G.GAME.rental_rate) - end -end - -function Card:calculate_perishable() - if self.ability.perishable and not self.ability.perish_tally then self.ability.perish_tally = G.GAME.perishable_rounds end - if self.ability.perishable and self.ability.perish_tally > 0 then - if self.ability.perish_tally == 1 then - self.ability.perish_tally = 0 - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('k_disabled_ex'),colour = G.C.FILTER, delay = 0.45}) - self:set_debuff() - else - self.ability.perish_tally = self.ability.perish_tally - 1 - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_remaining',vars={self.ability.perish_tally}},colour = G.C.FILTER, delay = 0.45}) - end - end -end - -function Card:calculate_joker(context) -for k, v in pairs(SMODS.Stickers) do - if self.ability[v.key] then - if v.calculate and type(v.calculate) == 'function' then - local override_card = v:calculate(self, context) - if override_card then return override_card end - end - end -end - if self.debuff then return nil end - local obj = self.config.center - if self.ability.set ~= "Enhanced" and obj.calculate and type(obj.calculate) == 'function' then - local o, t = obj:calculate(self, context) - if o or t then return o, t end - end - if self.ability.set == "Planet" and not self.debuff then - if context.joker_main then - if G.GAME.used_vouchers.v_observatory and self.ability.consumeable.hand_type == context.scoring_name then - return { - message = localize{type = 'variable', key = 'a_xmult', vars = {G.GAME.cry_voucher_centers['v_observatory'].config.extra}}, - Xmult_mod = G.GAME.cry_voucher_centers['v_observatory'].config.extra - - } - end - end - end - if self.ability.set == "Joker" and not self.debuff then - if self.ability.name == "Blueprint" then - local other_joker = nil - for i = 1, #G.jokers.cards do - if G.jokers.cards[i] == self then other_joker = G.jokers.cards[i+1] end - end - if other_joker and other_joker ~= self and not context.no_blueprint then - context.blueprint = (context.blueprint and (context.blueprint + 1)) or 1 - context.copy_depth = (context.copy_depth and (context.copy_depth + 1)) or 1 - context.blueprint_card = context.blueprint_card or self - if context.blueprint > #G.jokers.cards + 1 then return end - context.no_callback = true - local other_joker_ret, trig = other_joker:calculate_joker(context) - if other_joker_ret then - other_joker_ret.card = context.blueprint_card or self - context.no_callback = not (context.copy_depth <= 1) - context.copy_depth = context.copy_depth - 1; - other_joker_ret.colour = G.C.BLUE - return other_joker_ret - end - end - end - if self.ability.name == "Brainstorm" then - local other_joker = G.jokers.cards[1] - if other_joker and other_joker ~= self and not context.no_blueprint then - context.blueprint = (context.blueprint and (context.blueprint + 1)) or 1 - context.copy_depth = (context.copy_depth and (context.copy_depth + 1)) or 1 - context.blueprint_card = context.blueprint_card or self - if context.blueprint > #G.jokers.cards + 1 then return end - context.no_callback = true - local other_joker_ret, trig = other_joker:calculate_joker(context) - if other_joker_ret then - other_joker_ret.card = context.blueprint_card or self - context.no_callback = not (context.copy_depth <= 1) - context.copy_depth = context.copy_depth - 1; - other_joker_ret.colour = G.C.RED - return other_joker_ret - end - end - end - if context.open_booster then - if self.ability.name == 'Hallucination' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then - if pseudorandom('halu'..G.GAME.round_resets.ante) < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then - G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 - G.E_MANAGER:add_event(Event({ - trigger = 'before', - delay = 0.0, - func = (function() - local card = create_card('Tarot',G.consumeables, nil, nil, nil, nil, nil, 'hal') - card:add_to_deck() - G.consumeables:emplace(card) - G.GAME.consumeable_buffer = 0 - return true - end)})) - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('k_plus_tarot'), colour = G.C.PURPLE}) - end - end - elseif context.buying_card then - - elseif context.selling_self then - if self.ability.name == 'Luchador' then - if G.GAME.blind and ((not G.GAME.blind.disabled) and (G.GAME.blind:get_type() == 'Boss')) then - card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('ph_boss_disabled')}) - G.GAME.blind:disable() - return nil, true - end - end - if self.ability.name == 'Diet Cola' then - G.E_MANAGER:add_event(Event({ - func = (function() - add_tag(Tag('tag_double')) - 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) - })) - return nil, true - end - if self.ability.name == 'Invisible Joker' and (self.ability.invis_rounds >= self.ability.extra) and not context.blueprint then - local eval = function(card) return (card.ability.loyalty_remaining == 0) and not G.RESET_JIGGLES end - juice_card_until(self, eval, true) - local jokers = {} - for i=1, #G.jokers.cards do - if G.jokers.cards[i] ~= self then - jokers[#jokers+1] = G.jokers.cards[i] - end - end - if #jokers > 0 then - if #G.jokers.cards <= G.jokers.config.card_limit then - card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_duplicated_ex')}) - local chosen_joker = pseudorandom_element(jokers, pseudoseed('invisible')) - local card = copy_card(chosen_joker, nil, nil, nil, chosen_joker.edition and chosen_joker.edition.negative) - if card.ability.invis_rounds then card.ability.invis_rounds = 0 end - card:add_to_deck() - G.jokers:emplace(card) return nil, true - else - card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_no_room_ex')}) - end - else - card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_no_other_jokers')}) - end - end - elseif context.selling_card then - if self.ability.name == 'Campfire' and not context.blueprint then - self.ability.x_mult = self.ability.x_mult + self.ability.extra - G.E_MANAGER:add_event(Event({ - func = function() card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('k_upgrade_ex')}); return true - end})) - end - if self.ability.name == 'Campfire' and not context.blueprint then return nil, true end - elseif context.reroll_shop then - if self.ability.name == 'Flash Card' and not context.blueprint then - self.ability.mult = self.ability.mult + self.ability.extra - G.E_MANAGER:add_event(Event({ - func = (function() - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_mult', vars = {self.ability.mult}}, colour = G.C.MULT}) - return true - end)})) - end - if self.ability.name == 'Flash Card' and not context.blueprint then return nil, true end - elseif context.ending_shop then - if self.ability.name == 'Perkeo' then - local eligibleJokers = {} - for i = 1, #G.consumeables.cards do - if G.consumeables.cards[i].ability.consumeable then - eligibleJokers[#eligibleJokers + 1] = G.consumeables.cards[i] - end - end - if #eligibleJokers > 0 then - G.E_MANAGER:add_event(Event({ - func = function() - local card = copy_card(pseudorandom_element(eligibleJokers, pseudoseed('perkeo')), nil) - card:set_edition({negative = true}, true) - card:add_to_deck() - G.consumeables:emplace(card) - return true - end})) - card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_duplicated_ex')}) - return nil, true - end - return - end - return - elseif context.skip_blind then - if self.ability.name == 'Throwback' and not context.blueprint then - G.E_MANAGER:add_event(Event({ - func = function() - card_eval_status_text(self, 'extra', nil, nil, nil, { - message = localize{type = 'variable', key = 'a_xmult', vars = {self.ability.x_mult}}, - colour = G.C.RED, - card = self - }) - return true - end})) - return nil, true end - return - elseif context.skipping_booster then - if self.ability.name == 'Red Card' and not context.blueprint then - self.ability.mult = self.ability.mult + self.ability.extra - G.E_MANAGER:add_event(Event({ - func = function() - card_eval_status_text(self, 'extra', nil, nil, nil, { - message = localize{type = 'variable', key = 'a_mult', vars = {self.ability.extra}}, - colour = G.C.RED, - delay = 0.45, - card = self - }) - return true - end})) - return nil, true end - return - elseif context.playing_card_added and not self.getting_sliced then - if self.ability.name == 'Hologram' and (not context.blueprint) - and context.cards and context.cards[1] then - self.ability.x_mult = self.ability.x_mult + #context.cards*self.ability.extra - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {self.ability.x_mult}}}) - return nil, true end - elseif context.first_hand_drawn then - if self.ability.name == 'Certificate' then - G.E_MANAGER:add_event(Event({ - func = function() - local _card = create_playing_card({ - front = pseudorandom_element(G.P_CARDS, pseudoseed('cert_fr')), - center = G.P_CENTERS.c_base}, G.hand, nil, nil, {G.C.SECONDARY_SET.Enhanced}) - _card:set_seal(SMODS.poll_seal({guaranteed = true, type_key = 'certsl'})) - G.GAME.blind:debuff_card(_card) - G.hand:sort() - if context.blueprint_card then context.blueprint_card:juice_up() else self:juice_up() end - return true - end})) - - playing_card_joker_effects({true}) - return nil, true end - if self.ability.name == 'DNA' and not context.blueprint then - local eval = function() return G.GAME.current_round.hands_played == 0 end - juice_card_until(self, eval, true) - end - if self.ability.name == 'Trading Card' and not context.blueprint then - local eval = function() return G.GAME.current_round.discards_used == 0 and not G.RESET_JIGGLES end - juice_card_until(self, eval, true) - end - elseif context.setting_blind and not self.getting_sliced then - if self.ability.name == 'Chicot' and not context.blueprint - and context.blind.boss and not self.getting_sliced then - G.E_MANAGER:add_event(Event({func = function() - G.E_MANAGER:add_event(Event({func = function() - G.GAME.blind:disable() - play_sound('timpani') - delay(0.4) - return true end })) - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('ph_boss_disabled')}) - return true end })) - return nil, true end - if self.ability.name == 'Madness' and not context.blueprint and not context.blind.boss then - self.ability.x_mult = self.ability.x_mult + self.ability.extra - local destructable_jokers = {} - for i = 1, #G.jokers.cards do - if G.jokers.cards[i] ~= self and not G.jokers.cards[i].ability.eternal and not G.jokers.cards[i].getting_sliced then destructable_jokers[#destructable_jokers+1] = G.jokers.cards[i] end - end - local joker_to_destroy = #destructable_jokers > 0 and pseudorandom_element(destructable_jokers, pseudoseed('madness')) or nil - - if joker_to_destroy and not (context.blueprint_card or self).getting_sliced then - joker_to_destroy.getting_sliced = true - G.E_MANAGER:add_event(Event({func = function() - (context.blueprint_card or self):juice_up(0.8, 0.8) - joker_to_destroy:start_dissolve({G.C.RED}, nil, 1.6) - return true end })) - end - if not (context.blueprint_card or self).getting_sliced then - card_eval_status_text((context.blueprint_card or self), 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {self.ability.x_mult}}}) - end - return nil, true end - if self.ability.name == 'Burglar' and not (context.blueprint_card or self).getting_sliced then - G.E_MANAGER:add_event(Event({func = function() - ease_discard(-G.GAME.current_round.discards_left, nil, true) - ease_hands_played(self.ability.extra) - card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_hands', vars = {self.ability.extra}}}) - return true end })) - return nil, true end - if self.ability.name == 'Riff-raff' and not (context.blueprint_card or self).getting_sliced and #G.jokers.cards + G.GAME.joker_buffer < G.jokers.config.card_limit then - local jokers_to_create = math.min(2, G.jokers.config.card_limit - (#G.jokers.cards + G.GAME.joker_buffer)) - G.GAME.joker_buffer = G.GAME.joker_buffer + jokers_to_create - G.E_MANAGER:add_event(Event({ - func = function() - for i = 1, jokers_to_create do - local card = create_card('Joker', G.jokers, nil, 0, nil, nil, nil, 'rif') - card:add_to_deck() - G.jokers:emplace(card) - card:start_materialize() - G.GAME.joker_buffer = 0 - end - return true - end})) - card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_plus_joker'), colour = G.C.BLUE}) - return nil, true end - if self.ability.name == 'Cartomancer' and not (context.blueprint_card or self).getting_sliced and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then - G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 - G.E_MANAGER:add_event(Event({ - func = (function() - G.E_MANAGER:add_event(Event({ - func = function() - local card = create_card('Tarot',G.consumeables, nil, nil, nil, nil, nil, 'car') - card:add_to_deck() - G.consumeables:emplace(card) - G.GAME.consumeable_buffer = 0 - return true - end})) - card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_plus_tarot'), colour = G.C.PURPLE}) - return true - end)})) - return nil, true end - if self.ability.name == 'Ceremonial Dagger' and not context.blueprint then - local my_pos = nil - for i = 1, #G.jokers.cards do - if G.jokers.cards[i] == self then my_pos = i; break end - end - if my_pos and G.jokers.cards[my_pos+1] and not self.getting_sliced and not G.jokers.cards[my_pos+1].ability.eternal and not G.jokers.cards[my_pos+1].getting_sliced then - local sliced_card = G.jokers.cards[my_pos+1] - if sliced_card.config.center.rarity == "cry_exotic" then check_for_unlock({type = "what_have_you_done"}) end - sliced_card.getting_sliced = true - G.GAME.joker_buffer = G.GAME.joker_buffer - 1 - G.E_MANAGER:add_event(Event({func = function() - G.GAME.joker_buffer = 0 - self.ability.mult = self.ability.mult + sliced_card.sell_cost*2 - self:juice_up(0.8, 0.8) - sliced_card:start_dissolve({HEX("57ecab")}, nil, 1.6) - play_sound('slice1', 0.96+math.random()*0.08) - return true end })) - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_mult', vars = {self.ability.mult+2*sliced_card.sell_cost}}, colour = G.C.RED, no_juice = true}) - return nil, true end - end - if self.ability.name == 'Marble Joker' and not (context.blueprint_card or self).getting_sliced then - G.E_MANAGER:add_event(Event({ - func = function() - local front = pseudorandom_element(G.P_CARDS, pseudoseed('marb_fr')) - G.playing_card = (G.playing_card and G.playing_card + 1) or 1 - local card = Card(G.play.T.x + G.play.T.w/2, G.play.T.y, G.CARD_W, G.CARD_H, front, G.P_CENTERS.m_stone, {playing_card = G.playing_card}) - card:start_materialize({G.C.SECONDARY_SET.Enhanced}) - G.play:emplace(card) - table.insert(G.playing_cards, card) - return true - end})) - card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_plus_stone'), colour = G.C.SECONDARY_SET.Enhanced}) - - G.E_MANAGER:add_event(Event({ - func = function() - G.deck.config.card_limit = G.deck.config.card_limit + 1 - return true - end})) - draw_card(G.play,G.deck, 90,'up', nil) - - playing_card_joker_effects({true}) - return nil, true end - return - elseif context.destroying_card and not context.blueprint then - if self.ability.name == 'Sixth Sense' and #context.full_hand == 1 and context.full_hand[1]:get_id() == 6 and not context.full_hand[1].ability.eternal and G.GAME.current_round.hands_played == 0 then - if #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then - G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 - G.E_MANAGER:add_event(Event({ - trigger = 'before', - delay = 0.0, - func = (function() - local card = create_card('Spectral',G.consumeables, nil, nil, nil, nil, nil, 'sixth') - card:add_to_deck() - G.consumeables:emplace(card) - G.GAME.consumeable_buffer = 0 - return true - end)})) - card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_plus_spectral'), colour = G.C.SECONDARY_SET.Spectral}) - end - return true - end - return nil - elseif context.cards_destroyed then - if self.ability.name == 'Caino' and not context.blueprint then - local faces = 0 - for k, v in ipairs(context.glass_shattered) do - if v:is_face() then - faces = faces + 1 - end - end - if faces > 0 then - G.E_MANAGER:add_event(Event({ - func = function() - G.E_MANAGER:add_event(Event({ - func = function() - self.ability.caino_xmult = self.ability.caino_xmult + faces*self.ability.extra - return true - end - })) - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {self.ability.caino_xmult + faces*self.ability.extra}}}) - return true - end - })) - end - - return - end - if self.ability.name == 'Glass Joker' and not context.blueprint then - local glasses = 0 - for k, v in ipairs(context.glass_shattered) do - if v.shattered then - glasses = glasses + 1 - end - end - if glasses > 0 then - G.E_MANAGER:add_event(Event({ - func = function() - G.E_MANAGER:add_event(Event({ - func = function() - self.ability.x_mult = self.ability.x_mult + self.ability.extra*glasses - return true - end - })) - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {self.ability.x_mult + self.ability.extra*glasses}}}) - return true - end - })) - end - - return - end - - elseif context.remove_playing_cards then - if self.ability.name == 'Caino' and not context.blueprint then - local face_cards = 0 - for k, val in ipairs(context.removed) do - if val:is_face() then face_cards = face_cards + 1 end - end - if face_cards > 0 then - self.ability.caino_xmult = self.ability.caino_xmult + face_cards*self.ability.extra - G.E_MANAGER:add_event(Event({ - func = function() card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {self.ability.caino_xmult}}}); return true - end})) return nil, true - end - return - end - - if self.ability.name == 'Glass Joker' and not context.blueprint then - local glass_cards = 0 - for k, val in ipairs(context.removed) do - if val.shattered then glass_cards = glass_cards + 1 end - end - if glass_cards > 0 then - G.E_MANAGER:add_event(Event({ - func = function() - G.E_MANAGER:add_event(Event({ - func = function() - self.ability.x_mult = self.ability.x_mult + self.ability.extra*glass_cards - return true - end - })) - card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {self.ability.x_mult + self.ability.extra*glass_cards}}}) - return true - end - })) return nil, true - end - return - end - elseif context.using_consumeable then - if self.ability.name == 'Glass Joker' and not context.blueprint and context.consumeable.ability.name == 'The Hanged Man' then - local shattered_glass = 0 - for k, val in ipairs(G.hand.highlighted) do - if SMODS.has_enhancement(val, 'm_glass') then shattered_glass = shattered_glass + 1 end - end - if shattered_glass > 0 then - self.ability.x_mult = self.ability.x_mult + self.ability.extra*shattered_glass - G.E_MANAGER:add_event(Event({ - func = function() card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}}}); return true - end})) - return nil, true end - return - end - if self.ability.name == 'Fortune Teller' and not context.blueprint and (context.consumeable.ability.set == "Tarot") then - G.E_MANAGER:add_event(Event({ - func = function() card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_mult',vars={G.GAME.consumeable_usage_total.tarot}}}); return true - end})) - return nil, true end - if self.ability.name == 'Constellation' and not context.blueprint and context.consumeable.ability.set == 'Planet' then - self.ability.x_mult = self.ability.x_mult + self.ability.extra - G.E_MANAGER:add_event(Event({ - func = function() card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}}}); return true - end})) - return - nil, true end - return - elseif context.debuffed_hand then - if self.ability.name == 'Matador' then - if G.GAME.blind.triggered then - ease_dollars(self.ability.extra) - G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + self.ability.extra - if not Talisman.config_file.disable_anims then G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)})) else G.GAME.dollar_buffer = 0 end - return { - message = localize('$')..self.ability.extra, - dollars = self.ability.extra, - colour = G.C.MONEY - } - end - end - elseif context.pre_discard then - if self.ability.name == 'Burnt Joker' and G.GAME.current_round.discards_used <= 0 and not context.hook then - local text,disp_text = G.FUNCS.get_poker_hand_info(G.hand.highlighted) - card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_upgrade_ex')}) - update_hand_text({sound = 'button', volume = 0.7, pitch = 0.8, delay = 0.3}, {handname=localize(text, 'poker_hands'),chips = G.GAME.hands[text].chips, mult = G.GAME.hands[text].mult, level=G.GAME.hands[text].level}) - level_up_hand(context.blueprint_card or self, text, nil, 1) - update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''}) - return nil, true end - elseif context.discard then - if self.ability.name == 'Ramen' and not context.blueprint then - if self.ability.x_mult - self.ability.extra <= 1 then - G.E_MANAGER:add_event(Event({ - func = function() - play_sound('tarot1') - self.T.r = -0.2 - self:juice_up(0.3, 0.4) - self.states.drag.is = true - self.children.center.pinch.x = true - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false, - func = function() - G.jokers:remove_card(self) - self:remove() - self = nil - return true; end})) - return true - end - })) - return { - message = localize('k_eaten_ex'), - colour = G.C.FILTER - } - else - self.ability.x_mult = self.ability.x_mult - self.ability.extra - return { - delay = 0.2, - message = localize{type='variable',key='a_xmult_minus',vars={self.ability.extra}}, - colour = G.C.RED - } - end - end - if self.ability.name == 'Yorick' and not context.blueprint then - if self.ability.yorick_discards <= 1 then - self.ability.yorick_discards = self.ability.extra.discards - self.ability.x_mult = self.ability.x_mult + self.ability.extra.xmult - return { - delay = 0.2, - message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}}, - colour = G.C.RED - } - else - self.ability.yorick_discards = self.ability.yorick_discards - 1 - return nil, true - end - return - end - if self.ability.name == 'Trading Card' and not context.blueprint and - G.GAME.current_round.discards_used <= 0 and #context.full_hand == 1 and not context.other_card.ability.eternal then - ease_dollars(self.ability.extra) - return { - message = localize('$')..self.ability.extra, - colour = G.C.MONEY, - delay = 0.45, - remove = true, - card = self - } - end - - if self.ability.name == 'Castle' and - not context.other_card.debuff and - context.other_card:is_suit(G.GAME.current_round.castle_card.suit) and not context.blueprint then - self.ability.extra.chips = self.ability.extra.chips + self.ability.extra.chip_mod - - return { - message = localize('k_upgrade_ex'), - card = self, - colour = G.C.CHIPS - } - end - if self.ability.name == 'Mail-In Rebate' and - not context.other_card.debuff and - context.other_card:get_id() == G.GAME.current_round.mail_card.id then - ease_dollars(self.ability.extra) - return { - message = localize('$')..self.ability.extra, - colour = G.C.MONEY, - card = self - } - end - if self.ability.name == 'Hit the Road' and - not context.other_card.debuff and - context.other_card:get_id() == 11 and not context.blueprint then - self.ability.x_mult = self.ability.x_mult + self.ability.extra - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}}, - colour = G.C.RED, - delay = 0.45, - card = self - } - end - if self.ability.name == 'Green Joker' and not context.blueprint and context.other_card == context.full_hand[#context.full_hand] then - local prev_mult = self.ability.mult - self.ability.mult = math.max(0, self.ability.mult - self.ability.extra.discard_sub) - if self.ability.mult ~= prev_mult then - return { - message = localize{type='variable',key='a_mult_minus',vars={self.ability.extra.discard_sub}}, - colour = G.C.RED, - card = self - } - end - end - - if self.ability.name == 'Faceless Joker' and context.other_card == context.full_hand[#context.full_hand] then - local face_cards = 0 - for k, v in ipairs(context.full_hand) do - if v:is_face() then face_cards = face_cards + 1 end - end - if face_cards >= self.ability.extra.faces then - G.E_MANAGER:add_event(Event({ - func = function() - ease_dollars(self.ability.extra.dollars) - card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('$')..self.ability.extra.dollars,colour = G.C.MONEY, delay = 0.45}) - return true - end})) - return - nil, true end - end - return - elseif context.end_of_round then - if context.individual then - - elseif context.repetition then - if context.cardarea == G.hand then - if self.ability.name == 'Mime' and - (next(context.card_effects[1]) or #context.card_effects > 1) then - return { - message = localize('k_again_ex'), - repetitions = self.ability.extra, - card = self - } - end - end - elseif not context.blueprint then - if self.ability.name == 'Campfire' and G.GAME.blind.boss and self.ability.x_mult > 1 then - self.ability.x_mult = 1 - return { - message = localize('k_reset'), - colour = G.C.RED - } - end - if self.ability.name == 'Rocket' and G.GAME.blind.boss then - self.ability.extra.dollars = self.ability.extra.dollars + self.ability.extra.increase - return { - message = localize('k_upgrade_ex'), - colour = G.C.MONEY - } - end - if self.ability.name == 'Turtle Bean' and not context.blueprint then - if self.ability.extra.h_size - self.ability.extra.h_mod <= 0 then - G.E_MANAGER:add_event(Event({ - func = function() - play_sound('tarot1') - self.T.r = -0.2 - self:juice_up(0.3, 0.4) - self.states.drag.is = true - self.children.center.pinch.x = true - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false, - func = function() - G.jokers:remove_card(self) - self:remove() - self = nil - return true; end})) - return true - end - })) - return { - message = localize('k_eaten_ex'), - colour = G.C.FILTER - } - else - self.ability.extra.h_size = self.ability.extra.h_size - self.ability.extra.h_mod - G.hand:change_size(- self.ability.extra.h_mod) - return { - message = localize{type='variable',key='a_handsize_minus',vars={self.ability.extra.h_mod}}, - colour = G.C.FILTER - } - end - end - if self.ability.name == 'Invisible Joker' and not context.blueprint then - self.ability.invis_rounds = self.ability.invis_rounds + 1 - if self.ability.invis_rounds == self.ability.extra then - local eval = function(card) return not card.REMOVED end - juice_card_until(self, eval, true) - end - return { - message = (self.ability.invis_rounds < self.ability.extra) and (self.ability.invis_rounds..'/'..self.ability.extra) or localize('k_active_ex'), - colour = G.C.FILTER - } - end - if self.ability.name == 'Popcorn' and not context.blueprint then - if self.ability.mult - self.ability.extra <= 0 then - G.E_MANAGER:add_event(Event({ - func = function() - play_sound('tarot1') - self.T.r = -0.2 - self:juice_up(0.3, 0.4) - self.states.drag.is = true - self.children.center.pinch.x = true - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false, - func = function() - G.jokers:remove_card(self) - self:remove() - self = nil - return true; end})) - return true - end - })) - return { - message = localize('k_eaten_ex'), - colour = G.C.RED - } - else - self.ability.mult = self.ability.mult - self.ability.extra - return { - message = localize{type='variable',key='a_mult_minus',vars={self.ability.extra}}, - colour = G.C.MULT - } - end - end - if self.ability.name == 'To Do List' and not context.blueprint then - local _poker_hands = {} - for k, v in pairs(G.GAME.hands) do - if v.visible and k ~= self.ability.to_do_poker_hand then _poker_hands[#_poker_hands+1] = k end - end - self.ability.to_do_poker_hand = pseudorandom_element(_poker_hands, pseudoseed('to_do')) - return { - message = localize('k_reset') - } - end - if self.ability.name == 'Egg' then - self.ability.extra_value = self.ability.extra_value + self.ability.extra - self:set_cost() - return { - message = localize('k_val_up'), - colour = G.C.MONEY - } - end - if self.ability.name == 'Gift Card' then - for k, v in ipairs(G.jokers.cards) do - if v.set_cost then - v.ability.extra_value = (v.ability.extra_value or 0) + self.ability.extra - v:set_cost() - end - end - for k, v in ipairs(G.consumeables.cards) do - if v.set_cost then - v.ability.extra_value = (v.ability.extra_value or 0) + self.ability.extra - v:set_cost() - end - end - return { - message = localize('k_val_up'), - colour = G.C.MONEY - } - end - if self.ability.name == 'Hit the Road' and to_big(self.ability.x_mult) > to_big(1) then - self.ability.x_mult = 1 - return { - message = localize('k_reset'), - colour = G.C.RED - } - end - - if self.ability.name == 'Gros Michel' or self.ability.name == 'Cavendish' then - if pseudorandom(self.ability.name == 'Cavendish' and 'cavendish' or 'gros_michel') < cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged)/self.ability.extra.odds then - G.E_MANAGER:add_event(Event({ - func = function() - play_sound('tarot1') - self.T.r = -0.2 - self:juice_up(0.3, 0.4) - self.states.drag.is = true - self.children.center.pinch.x = true - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false, - func = function() - G.jokers:remove_card(self) - self:remove() - self = nil - return true; end})) - return true - end - })) - if self.ability.name == 'Gros Michel' then G.GAME.pool_flags.gros_michel_extinct = true end - return { - message = localize('k_extinct_ex') - } - else - return { - message = localize('k_safe_ex') - } - end - end - if self.ability.name == 'Mr. Bones' and context.game_over and - to_big(G.GAME.chips)/G.GAME.blind.chips >= to_big(0.25) then - G.E_MANAGER:add_event(Event({ - func = function() - G.hand_text_area.blind_chips:juice_up() - G.hand_text_area.game_chips:juice_up() - play_sound('tarot1') - self:start_dissolve() - return true - end - })) - return { - message = localize('k_saved_ex'), - saved = true, - colour = G.C.RED - } - end - end - elseif context.individual then - if context.cardarea == G.play then - if self.ability.name == 'Hiker' then - context.other_card.ability.perma_bonus = context.other_card.ability.perma_bonus or 0 - context.other_card.ability.perma_bonus = context.other_card.ability.perma_bonus + self.ability.extra - return { - extra = {message = localize('k_upgrade_ex'), colour = G.C.CHIPS}, - colour = G.C.CHIPS, - card = self - } - end - if self.ability.name == 'Lucky Cat' and context.other_card.lucky_trigger and not context.blueprint then - self.ability.x_mult = self.ability.x_mult + self.ability.extra - return { - extra = {focus = self, message = localize('k_upgrade_ex'), colour = G.C.MULT}, - card = self - } - end - if self.ability.name == 'Wee Joker' and - context.other_card:get_id() == 2 and not context.blueprint then - self.ability.extra.chips = self.ability.extra.chips + self.ability.extra.chip_mod - - return { - extra = {focus = self, message = localize('k_upgrade_ex')}, - card = self, - colour = G.C.CHIPS - } - end - if self.ability.name == 'Photograph' then - local first_face = nil - for i = 1, #context.scoring_hand do - if context.scoring_hand[i]:is_face() then first_face = context.scoring_hand[i]; break end - end - if context.other_card == first_face then - return { - x_mult = self.ability.extra, - colour = G.C.RED, - card = self - } - end - end - if self.ability.name == '8 Ball' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then - if (context.other_card:get_id() == 8) and (pseudorandom('8ball') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra) then - G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 - return { - extra = {focus = self, message = localize('k_plus_tarot'), func = function() - G.E_MANAGER:add_event(Event({ - trigger = 'before', - delay = 0.0, - func = (function() - local card = create_card('Tarot',G.consumeables, nil, nil, nil, nil, nil, '8ba') - card:add_to_deck() - G.consumeables:emplace(card) - G.GAME.consumeable_buffer = 0 - return true - end)})) - end}, - colour = G.C.SECONDARY_SET.Tarot, - card = self - } - end - end - if self.ability.name == 'The Idol' and - context.other_card:get_id() == G.GAME.current_round.idol_card.id and - context.other_card:is_suit(G.GAME.current_round.idol_card.suit) then - return { - x_mult = self.ability.extra, - colour = G.C.RED, - card = self - } - end - if self.ability.name == 'Scary Face' and ( - context.other_card:is_face()) then - return { - chips = self.ability.extra, - card = self - } - end - if self.ability.name == 'Smiley Face' and ( - context.other_card:is_face()) then - return { - mult = self.ability.extra, - card = self - } - end - if self.ability.name == 'Golden Ticket' and - SMODS.has_enhancement(context.other_card, 'm_gold') then - G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + self.ability.extra - if not Talisman.config_file.disable_anims then G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)})) else G.GAME.dollar_buffer = 0 end - return { - dollars = self.ability.extra, - card = self - } - end - if self.ability.name == 'Scholar' and - context.other_card:get_id() == 14 then - return { - chips = self.ability.extra.chips, - mult = self.ability.extra.mult, - card = self - } - end - if self.ability.name == 'Walkie Talkie' and - (context.other_card:get_id() == 10 or context.other_card:get_id() == 4) then - return { - chips = self.ability.extra.chips, - mult = self.ability.extra.mult, - card = self - } - end - if self.ability.name == 'Business Card' and - context.other_card:is_face() and - pseudorandom('business') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then - G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + 2 - if not Talisman.config_file.disable_anims then G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)})) else G.GAME.dollar_buffer = 0 end - return { - dollars = 2, - card = self - } - end - if self.ability.name == 'Fibonacci' and ( - context.other_card:get_id() == 2 or - context.other_card:get_id() == 3 or - context.other_card:get_id() == 5 or - context.other_card:get_id() == 8 or - context.other_card:get_id() == 14) then - return { - mult = self.ability.extra, - card = self - } - end - if self.ability.name == 'Even Steven' and - context.other_card:get_id() <= 10 and - context.other_card:get_id() >= 0 and - context.other_card:get_id()%2 == 0 - then - return { - mult = self.ability.extra, - card = self - } - end - if self.ability.name == 'Odd Todd' and - ((context.other_card:get_id() <= 10 and - context.other_card:get_id() >= 0 and - context.other_card:get_id()%2 == 1) or - (context.other_card:get_id() == 14)) - then - return { - chips = self.ability.extra, - card = self - } - end - if self.ability.effect == 'Suit Mult' and - context.other_card:is_suit(self.ability.extra.suit) then - return { - mult = self.ability.extra.s_mult, - card = self - } - end - if self.ability.name == 'Rough Gem' and - context.other_card:is_suit("Diamonds") then - G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + self.ability.extra - if not Talisman.config_file.disable_anims then G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)})) else G.GAME.dollar_buffer = 0 end - return { - dollars = self.ability.extra, - card = self - } - end - if self.ability.name == 'Onyx Agate' and - context.other_card:is_suit("Clubs") then - return { - mult = self.ability.extra, - card = self - } - end - if self.ability.name == 'Arrowhead' and - context.other_card:is_suit("Spades") then - return { - chips = self.ability.extra, - card = self - } - end - if self.ability.name == 'Bloodstone' and - context.other_card:is_suit("Hearts") and - pseudorandom('bloodstone') < cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged)/self.ability.extra.odds then - return { - x_mult = self.ability.extra.Xmult, - card = self - } - end - if self.ability.name == 'Ancient Joker' and - context.other_card:is_suit(G.GAME.current_round.ancient_card.suit) then - return { - x_mult = self.ability.extra, - card = self - } - end - if self.ability.name == 'Triboulet' and - (context.other_card:get_id() == 12 or context.other_card:get_id() == 13) then - return { - x_mult = self.ability.extra, - colour = G.C.RED, - card = self - } - end - end - if context.cardarea == G.hand then - if self.ability.name == 'Shoot the Moon' and - context.other_card:get_id() == 12 then - if context.other_card.debuff then - return { - message = localize('k_debuffed'), - colour = G.C.RED, - card = self, - } - else - return { - h_mult = 13, - card = self - } - end - end - if self.ability.name == 'Baron' and - context.other_card:get_id() == 13 then - if context.other_card.debuff then - return { - message = localize('k_debuffed'), - colour = G.C.RED, - card = self, - } - else - return { - x_mult = self.ability.extra, - card = self - } - end - end - if self.ability.name == 'Reserved Parking' and - context.other_card:is_face() and - pseudorandom('parking') < cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged)/self.ability.extra.odds then - if context.other_card.debuff then - return { - message = localize('k_debuffed'), - colour = G.C.RED, - card = self, - } - else - G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + self.ability.extra.dollars - if not Talisman.config_file.disable_anims then G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)})) else G.GAME.dollar_buffer = 0 end - return { - dollars = self.ability.extra.dollars, - card = self - } - end - end - if self.ability.name == 'Raised Fist' then - local temp_Mult, temp_ID = 15, 15 - local raised_card = nil - for i=1, #G.hand.cards do - if temp_ID >= G.hand.cards[i].base.id and not SMODS.has_no_rank(G.hand.cards[i]) then - temp_Mult = G.hand.cards[i].base.nominal - temp_ID = G.hand.cards[i].base.id - raised_card = G.hand.cards[i] - end - end - if raised_card == context.other_card then - if context.other_card.debuff then - return { - message = localize('k_debuffed'), - colour = G.C.RED, - card = self, - } - else - return { - h_mult = 2*temp_Mult, - card = self, - } - end - end - end - end - elseif context.repetition then - if context.cardarea == G.play then - if self.ability.name == 'Sock and Buskin' and ( - context.other_card:is_face()) then - return { - message = localize('k_again_ex'), - repetitions = self.ability.extra, - card = self - } - end - if self.ability.name == 'Hanging Chad' and ( - context.other_card == context.scoring_hand[1]) then - return { - message = localize('k_again_ex'), - repetitions = self.ability.extra, - card = self - } - end - if self.ability.name == 'Dusk' and G.GAME.current_round.hands_left == 0 then - return { - message = localize('k_again_ex'), - repetitions = self.ability.extra, - card = self - } - end - if self.ability.name == 'Seltzer' then - return { - message = localize('k_again_ex'), - repetitions = 1, - card = self - } - end - if self.ability.name == 'Hack' and ( - context.other_card:get_id() == 2 or - context.other_card:get_id() == 3 or - context.other_card:get_id() == 4 or - context.other_card:get_id() == 5) then - return { - message = localize('k_again_ex'), - repetitions = self.ability.extra, - card = self - } - end - end - if context.cardarea == G.hand then - if self.ability.name == 'Mime' and - (next(context.card_effects[1]) or #context.card_effects > 1) then - return { - message = localize('k_again_ex'), - repetitions = self.ability.extra, - card = self - } - end - end - elseif context.other_joker then - if self.ability.name == 'Baseball Card' and (context.other_joker.config.center.rarity == 2 or context.other_joker.config.center.rarity == "Uncommon") and self ~= context.other_joker then - G.E_MANAGER:add_event(Event({ - func = function() - context.other_joker:juice_up(0.5, 0.5) - return true - end - })) - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.extra}}, - Xmult_mod = self.ability.extra - } - end - else - if context.cardarea == G.jokers then - if context.before then - if self.ability.name == 'Spare Trousers' and (next(context.poker_hands['Two Pair']) or next(context.poker_hands['Full House'])) and not context.blueprint then - self.ability.mult = self.ability.mult + self.ability.extra - return { - message = localize('k_upgrade_ex'), - colour = G.C.RED, - card = self - } - end - if self.ability.name == 'Space Joker' and pseudorandom('space') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then - return { - card = self, - level_up = true, - message = localize('k_level_up_ex') - } - end - if self.ability.name == 'Square Joker' and #context.full_hand == 4 and not context.blueprint then - self.ability.extra.chips = self.ability.extra.chips + self.ability.extra.chip_mod - return { - message = localize('k_upgrade_ex'), - colour = G.C.CHIPS, - card = self - } - end - if self.ability.name == 'Runner' and next(context.poker_hands['Straight']) and not context.blueprint then - self.ability.extra.chips = self.ability.extra.chips + self.ability.extra.chip_mod - return { - message = localize('k_upgrade_ex'), - colour = G.C.CHIPS, - card = self - } - end - if self.ability.name == 'Midas Mask' and not context.blueprint then - local faces = {} - for k, v in ipairs(context.scoring_hand) do - if v:is_face() then - faces[#faces+1] = v - v:set_ability(G.P_CENTERS.m_gold, nil, true) - G.E_MANAGER:add_event(Event({ - func = function() - v:juice_up() - return true - end - })) - end - end - if #faces > 0 then - return { - message = localize('k_gold'), - colour = G.C.MONEY, - card = self - } - end - end - if self.ability.name == 'Vampire' and not context.blueprint then - local enhanced = {} - for k, v in ipairs(context.scoring_hand) do - if v.config.center ~= G.P_CENTERS.c_base and not v.debuff and not v.vampired then - enhanced[#enhanced+1] = v - v.vampired = true - v:set_ability(G.P_CENTERS.c_base, nil, true) - G.E_MANAGER:add_event(Event({ - func = function() - v:juice_up() - v.vampired = nil - return true - end - })) - end - end - - if #enhanced > 0 then - self.ability.x_mult = self.ability.x_mult + self.ability.extra*#enhanced - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}}, - colour = G.C.MULT, - card = self - } - end - end - if self.ability.name == 'To Do List' and context.scoring_name == self.ability.to_do_poker_hand then - ease_dollars(self.ability.extra.dollars) - G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + self.ability.extra.dollars - if not Talisman.config_file.disable_anims then G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)})) else G.GAME.dollar_buffer = 0 end - return { - message = localize('$')..self.ability.extra.dollars, - dollars = self.ability.extra.dollars, - colour = G.C.MONEY - } - end - if self.ability.name == 'DNA' and G.GAME.current_round.hands_played == 0 then - if #context.full_hand == 1 then - G.playing_card = (G.playing_card and G.playing_card + 1) or 1 - local _card = copy_card(context.full_hand[1], nil, nil, G.playing_card) - _card:add_to_deck() - G.deck.config.card_limit = G.deck.config.card_limit + 1 - table.insert(G.playing_cards, _card) - G.hand:emplace(_card) - _card.states.visible = nil - - G.E_MANAGER:add_event(Event({ - func = function() - _card:start_materialize() - return true - end - })) - return { - message = localize('k_copied_ex'), - colour = G.C.CHIPS, - card = self, - playing_cards_created = {true} - } - end - end - if self.ability.name == 'Ride the Bus' and not context.blueprint then - local faces = false - for i = 1, #context.scoring_hand do - if context.scoring_hand[i]:is_face() then faces = true end - end - if faces then - local last_mult = self.ability.mult - self.ability.mult = 0 - if last_mult > 0 then - return { - card = self, - message = localize('k_reset') - } - end - else - self.ability.mult = self.ability.mult + self.ability.extra - end - end - if self.ability.name == 'Obelisk' and not context.blueprint then - local reset = true - local play_more_than = (G.GAME.hands[context.scoring_name].played or 0) - for k, v in pairs(G.GAME.hands) do - if k ~= context.scoring_name and v.played >= play_more_than and v.visible then - reset = false - end - end - if reset then - if to_big(self.ability.x_mult) > to_big(1) then - self.ability.x_mult = 1 - return { - card = self, - message = localize('k_reset') - } - end - else - self.ability.x_mult = self.ability.x_mult + self.ability.extra - end - end - if self.ability.name == 'Green Joker' and not context.blueprint then - self.ability.mult = self.ability.mult + self.ability.extra.hand_add - return { - card = self, - message = localize{type='variable',key='a_mult',vars={self.ability.extra.hand_add}} - } - end - elseif context.after then - if self.ability.name == 'Ice Cream' and not context.blueprint then - if self.ability.extra.chips - self.ability.extra.chip_mod <= 0 then - G.E_MANAGER:add_event(Event({ - func = function() - play_sound('tarot1') - self.T.r = -0.2 - self:juice_up(0.3, 0.4) - self.states.drag.is = true - self.children.center.pinch.x = true - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false, - func = function() - G.jokers:remove_card(self) - self:remove() - self = nil - return true; end})) - return true - end - })) - return { - message = localize('k_melted_ex'), - colour = G.C.CHIPS - } - else - self.ability.extra.chips = self.ability.extra.chips - self.ability.extra.chip_mod - return { - message = localize{type='variable',key='a_chips_minus',vars={self.ability.extra.chip_mod}}, - colour = G.C.CHIPS - } - end - end - if self.ability.name == 'Seltzer' and not context.blueprint then - if self.ability.extra - 1 <= 0 then - G.E_MANAGER:add_event(Event({ - func = function() - play_sound('tarot1') - self.T.r = -0.2 - self:juice_up(0.3, 0.4) - self.states.drag.is = true - self.children.center.pinch.x = true - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false, - func = function() - G.jokers:remove_card(self) - self:remove() - self = nil - return true; end})) - return true - end - })) - return { - message = localize('k_drank_ex'), - colour = G.C.FILTER - } - else - self.ability.extra = self.ability.extra - 1 - return { - message = self.ability.extra..'', - colour = G.C.FILTER - } - end - end - elseif context.joker_main then - if self.ability.name == 'Loyalty Card' then - self.ability.loyalty_remaining = (self.ability.extra.every-1-(G.GAME.hands_played - self.ability.hands_played_at_create))%(self.ability.extra.every+1) - if context.blueprint then - if self.ability.loyalty_remaining == self.ability.extra.every then - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.extra.Xmult}}, - Xmult_mod = self.ability.extra.Xmult - } - end - else - if self.ability.loyalty_remaining == 0 then - local eval = function(card) return (card.ability.loyalty_remaining == 0) end - juice_card_until(self, eval, true) - elseif self.ability.loyalty_remaining == self.ability.extra.every then - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.extra.Xmult}}, - Xmult_mod = self.ability.extra.Xmult - } - end - end - end - if self.ability.name ~= 'Seeing Double' and to_big(self.ability.x_mult) > to_big(1) and (self.ability.type == '' or next(context.poker_hands[self.ability.type])) then - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}}, - colour = G.C.RED, - Xmult_mod = self.ability.x_mult - } - end - if to_big(self.ability.t_mult) > to_big(0) and next(context.poker_hands[self.ability.type]) then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.t_mult}}, - mult_mod = self.ability.t_mult - } - end - if to_big(self.ability.t_chips) > to_big(0) and next(context.poker_hands[self.ability.type]) then - return { - message = localize{type='variable',key='a_chips',vars={self.ability.t_chips}}, - chip_mod = self.ability.t_chips - } - end - if self.ability.name == 'Half Joker' and #context.full_hand <= self.ability.extra.size then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.extra.mult}}, - mult_mod = self.ability.extra.mult - } - end - if self.ability.name == 'Abstract Joker' then - local x = 0 - for i = 1, #G.jokers.cards do - if G.jokers.cards[i].ability.set == 'Joker' then x = x + 1 end - end - return { - message = localize{type='variable',key='a_mult',vars={x*self.ability.extra}}, - mult_mod = x*self.ability.extra - } - end - if self.ability.name == 'Acrobat' and G.GAME.current_round.hands_left == 0 then - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.extra}}, - Xmult_mod = self.ability.extra - } - end - if self.ability.name == 'Mystic Summit' and G.GAME.current_round.discards_left == self.ability.extra.d_remaining then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.extra.mult}}, - mult_mod = self.ability.extra.mult - } - end - if self.ability.name == 'Misprint' then - local temp_Mult = pseudorandom('misprint', self.ability.extra.min, self.ability.extra.max) - return { - message = localize{type='variable',key='a_mult',vars={temp_Mult}}, - mult_mod = temp_Mult - } - end - if self.ability.name == 'Banner' and G.GAME.current_round.discards_left > 0 then - return { - message = localize{type='variable',key='a_chips',vars={G.GAME.current_round.discards_left*self.ability.extra}}, - chip_mod = G.GAME.current_round.discards_left*self.ability.extra - } - end - if self.ability.name == 'Stuntman' then - return { - message = localize{type='variable',key='a_chips',vars={self.ability.extra.chip_mod}}, - chip_mod = self.ability.extra.chip_mod, - } - end - if self.ability.name == 'Matador' then - if G.GAME.blind.triggered then - ease_dollars(self.ability.extra) - G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + self.ability.extra - if not Talisman.config_file.disable_anims then G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)})) else G.GAME.dollar_buffer = 0 end - return { - message = localize('$')..self.ability.extra, - dollars = self.ability.extra, - colour = G.C.MONEY - } - end - end - if self.ability.name == 'Supernova' then - return { - message = localize{type='variable',key='a_mult',vars={G.GAME.hands[context.scoring_name].played}}, - mult_mod = G.GAME.hands[context.scoring_name].played - } - end - if self.ability.name == 'Ceremonial Dagger' and to_big(self.ability.mult) > to_big(0) then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.mult}}, - mult_mod = self.ability.mult - } - end - if self.ability.name == 'Vagabond' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then - if G.GAME.dollars <= self.ability.extra then - G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 - G.E_MANAGER:add_event(Event({ - trigger = 'before', - delay = 0.0, - func = (function() - local card = create_card('Tarot',G.consumeables, nil, nil, nil, nil, nil, 'vag') - card:add_to_deck() - G.consumeables:emplace(card) - G.GAME.consumeable_buffer = 0 - return true - end)})) - return { - message = localize('k_plus_tarot'), - card = self - } - end - end - if self.ability.name == 'Superposition' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then - local aces = 0 - for i = 1, #context.scoring_hand do - if context.scoring_hand[i]:get_id() == 14 then aces = aces + 1 end - end - if aces >= 1 and next(context.poker_hands["Straight"]) then - local card_type = 'Tarot' - G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 - G.E_MANAGER:add_event(Event({ - trigger = 'before', - delay = 0.0, - func = (function() - local card = create_card(card_type,G.consumeables, nil, nil, nil, nil, nil, 'sup') - card:add_to_deck() - G.consumeables:emplace(card) - G.GAME.consumeable_buffer = 0 - return true - end)})) - return { - message = localize('k_plus_tarot'), - colour = G.C.SECONDARY_SET.Tarot, - card = self - } - end - end - if self.ability.name == 'Seance' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then - if next(context.poker_hands[self.ability.extra.poker_hand]) then - G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 - G.E_MANAGER:add_event(Event({ - trigger = 'before', - delay = 0.0, - func = (function() - local card = create_card('Spectral',G.consumeables, nil, nil, nil, nil, nil, 'sea') - card:add_to_deck() - G.consumeables:emplace(card) - G.GAME.consumeable_buffer = 0 - return true - end)})) - return { - message = localize('k_plus_spectral'), - colour = G.C.SECONDARY_SET.Spectral, - card = self - } - end - end - if self.ability.name == 'Flower Pot' then - local suits = { - ['Hearts'] = 0, - ['Diamonds'] = 0, - ['Spades'] = 0, - ['Clubs'] = 0 - } - for i = 1, #context.scoring_hand do - if not SMODS.has_any_suit(context.scoring_hand[i]) then - if context.scoring_hand[i]:is_suit('Hearts', true) and suits["Hearts"] == 0 then suits["Hearts"] = suits["Hearts"] + 1 - elseif context.scoring_hand[i]:is_suit('Diamonds', true) and suits["Diamonds"] == 0 then suits["Diamonds"] = suits["Diamonds"] + 1 - elseif context.scoring_hand[i]:is_suit('Spades', true) and suits["Spades"] == 0 then suits["Spades"] = suits["Spades"] + 1 - elseif context.scoring_hand[i]:is_suit('Clubs', true) and suits["Clubs"] == 0 then suits["Clubs"] = suits["Clubs"] + 1 end - end - end - for i = 1, #context.scoring_hand do - if SMODS.has_any_suit(context.scoring_hand[i]) then - if context.scoring_hand[i]:is_suit('Hearts') and suits["Hearts"] == 0 then suits["Hearts"] = suits["Hearts"] + 1 - elseif context.scoring_hand[i]:is_suit('Diamonds') and suits["Diamonds"] == 0 then suits["Diamonds"] = suits["Diamonds"] + 1 - elseif context.scoring_hand[i]:is_suit('Spades') and suits["Spades"] == 0 then suits["Spades"] = suits["Spades"] + 1 - elseif context.scoring_hand[i]:is_suit('Clubs') and suits["Clubs"] == 0 then suits["Clubs"] = suits["Clubs"] + 1 end - end - end - if suits["Hearts"] > 0 and - suits["Diamonds"] > 0 and - suits["Spades"] > 0 and - suits["Clubs"] > 0 then - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.extra}}, - Xmult_mod = self.ability.extra - } - end - end - if self.ability.name == 'Seeing Double' then - local suits = { - ['Hearts'] = 0, - ['Diamonds'] = 0, - ['Spades'] = 0, - ['Clubs'] = 0 - } - for i = 1, #context.scoring_hand do - if not SMODS.has_any_suit(context.scoring_hand[i]) then - if context.scoring_hand[i]:is_suit('Hearts') then suits["Hearts"] = suits["Hearts"] + 1 end - if context.scoring_hand[i]:is_suit('Diamonds') then suits["Diamonds"] = suits["Diamonds"] + 1 end - if context.scoring_hand[i]:is_suit('Spades') then suits["Spades"] = suits["Spades"] + 1 end - if context.scoring_hand[i]:is_suit('Clubs') then suits["Clubs"] = suits["Clubs"] + 1 end - end - end - for i = 1, #context.scoring_hand do - if SMODS.has_any_suit(context.scoring_hand[i]) then - if context.scoring_hand[i]:is_suit('Clubs') and suits["Clubs"] == 0 then suits["Clubs"] = suits["Clubs"] + 1 - elseif context.scoring_hand[i]:is_suit('Diamonds') and suits["Diamonds"] == 0 then suits["Diamonds"] = suits["Diamonds"] + 1 - elseif context.scoring_hand[i]:is_suit('Spades') and suits["Spades"] == 0 then suits["Spades"] = suits["Spades"] + 1 - elseif context.scoring_hand[i]:is_suit('Hearts') and suits["Hearts"] == 0 then suits["Hearts"] = suits["Hearts"] + 1 end - end - end - if (suits["Hearts"] > 0 or - suits["Diamonds"] > 0 or - suits["Spades"] > 0) and - suits["Clubs"] > 0 then - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.extra}}, - Xmult_mod = self.ability.extra - } - end - end - if self.ability.name == 'Wee Joker' then - return { - message = localize{type='variable',key='a_chips',vars={self.ability.extra.chips}}, - chip_mod = self.ability.extra.chips, - colour = G.C.CHIPS - } - end - if self.ability.name == 'Castle' and (to_big(self.ability.extra.chips) > to_big(0)) then - return { - message = localize{type='variable',key='a_chips',vars={self.ability.extra.chips}}, - chip_mod = self.ability.extra.chips, - colour = G.C.CHIPS - } - end - if self.ability.name == 'Blue Joker' and #G.deck.cards > 0 then - return { - message = localize{type='variable',key='a_chips',vars={self.ability.extra*#G.deck.cards}}, - chip_mod = self.ability.extra*#G.deck.cards, - colour = G.C.CHIPS - } - end - if self.ability.name == 'Erosion' and (G.GAME.starting_deck_size - #G.playing_cards) > 0 then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.extra*(G.GAME.starting_deck_size - #G.playing_cards)}}, - mult_mod = self.ability.extra*(G.GAME.starting_deck_size - #G.playing_cards), - colour = G.C.MULT - } - end - if self.ability.name == 'Square Joker' then - return { - message = localize{type='variable',key='a_chips',vars={self.ability.extra.chips}}, - chip_mod = self.ability.extra.chips, - colour = G.C.CHIPS - } - end - if self.ability.name == 'Runner' then - return { - message = localize{type='variable',key='a_chips',vars={self.ability.extra.chips}}, - chip_mod = self.ability.extra.chips, - colour = G.C.CHIPS - } - end - if self.ability.name == 'Ice Cream' then - return { - message = localize{type='variable',key='a_chips',vars={self.ability.extra.chips}}, - chip_mod = self.ability.extra.chips, - colour = G.C.CHIPS - } - end - if self.ability.name == 'Stone Joker' and self.ability.stone_tally > 0 then - return { - message = localize{type='variable',key='a_chips',vars={self.ability.extra*self.ability.stone_tally}}, - chip_mod = self.ability.extra*self.ability.stone_tally, - colour = G.C.CHIPS - } - end - if self.ability.name == 'Steel Joker' and self.ability.steel_tally > 0 then - return { - message = localize{type='variable',key='a_xmult',vars={1 + self.ability.extra*self.ability.steel_tally}}, - Xmult_mod = 1 + self.ability.extra*self.ability.steel_tally, - colour = G.C.MULT - } - end - if self.ability.name == 'Bull' and (G.GAME.dollars + (G.GAME.dollar_buffer or 0)) > 0 then - return { - message = localize{type='variable',key='a_chips',vars={self.ability.extra*math.max(0,(G.GAME.dollars + (G.GAME.dollar_buffer or 0))) }}, - chip_mod = self.ability.extra*math.max(0,(G.GAME.dollars + (G.GAME.dollar_buffer or 0))), - colour = G.C.CHIPS - } - end - if self.ability.name == "Driver's License" then - if (self.ability.driver_tally or 0) >= 16 then - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.extra}}, - Xmult_mod = self.ability.extra - } - end - end - if self.ability.name == "Blackboard" then - local black_suits, all_cards = 0, 0 - for k, v in ipairs(G.hand.cards) do - all_cards = all_cards + 1 - if v:is_suit('Clubs', nil, true) or v:is_suit('Spades', nil, true) then - black_suits = black_suits + 1 - end - end - if black_suits == all_cards then - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.extra}}, - Xmult_mod = self.ability.extra - } - end - end - if self.ability.name == "Joker Stencil" then - if (G.jokers.config.card_limit - #G.jokers.cards) > 0 then - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}}, - Xmult_mod = self.ability.x_mult - } - end - end - if self.ability.name == 'Swashbuckler' and to_big(self.ability.mult) > to_big(0) then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.mult}}, - mult_mod = self.ability.mult - } - end - if self.ability.name == 'Joker' then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.mult}}, - mult_mod = self.ability.mult - } - end - if self.ability.name == 'Spare Trousers' and to_big(self.ability.mult) > to_big(0) then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.mult}}, - mult_mod = self.ability.mult - } - end - if self.ability.name == 'Ride the Bus' and to_big(self.ability.mult) > to_big(0) then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.mult}}, - mult_mod = self.ability.mult - } - end - if self.ability.name == 'Flash Card' and to_big(self.ability.mult) > to_big(0) then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.mult}}, - mult_mod = self.ability.mult - } - end - if self.ability.name == 'Popcorn' and to_big(self.ability.mult) > to_big(0) then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.mult}}, - mult_mod = self.ability.mult - } - end - if self.ability.name == 'Green Joker' and to_big(self.ability.mult) > to_big(0) then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.mult}}, - mult_mod = self.ability.mult - } - end - if self.ability.name == 'Fortune Teller' and G.GAME.consumeable_usage_total and G.GAME.consumeable_usage_total.tarot > 0 then - return { - message = localize{type='variable',key='a_mult',vars={G.GAME.consumeable_usage_total.tarot}}, - mult_mod = G.GAME.consumeable_usage_total.tarot - } - end - if self.ability.name == 'Gros Michel' then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.extra.mult}}, - mult_mod = self.ability.extra.mult, - } - end - if self.ability.name == 'Cavendish' then - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.extra.Xmult}}, - Xmult_mod = self.ability.extra.Xmult, - } - end - if self.ability.name == 'Red Card' and to_big(self.ability.mult) > to_big(0) then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.mult}}, - mult_mod = self.ability.mult - } - end - if self.ability.name == 'Card Sharp' and G.GAME.hands[context.scoring_name] and G.GAME.hands[context.scoring_name].played_this_round > 1 then - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.extra.Xmult}}, - Xmult_mod = self.ability.extra.Xmult, - } - end - if self.ability.name == 'Bootstraps' and math.floor((G.GAME.dollars + (G.GAME.dollar_buffer or 0))/self.ability.extra.dollars) >= 1 then - return { - message = localize{type='variable',key='a_mult',vars={self.ability.extra.mult*math.floor((G.GAME.dollars + (G.GAME.dollar_buffer or 0))/self.ability.extra.dollars)}}, - mult_mod = self.ability.extra.mult*math.floor((G.GAME.dollars + (G.GAME.dollar_buffer or 0))/self.ability.extra.dollars) - } - end - if self.ability.name == 'Caino' and to_big(self.ability.caino_xmult) > to_big(1) then - return { - message = localize{type='variable',key='a_xmult',vars={self.ability.caino_xmult}}, - Xmult_mod = self.ability.caino_xmult - } - end - end - end - end - end - end - -function Card:is_suit(suit, bypass_debuff, flush_calc) - if flush_calc then - if SMODS.has_no_suit(self) then - return false - end - if SMODS.has_any_suit(self) and not self.debuff then - return true - end - if next(find_joker('Smeared Joker')) and (self.base.suit == 'Hearts' or self.base.suit == 'Diamonds') == (suit == 'Hearts' or suit == 'Diamonds') then - return true - end - return self.base.suit == suit - else - if self.debuff and not bypass_debuff then return end - if SMODS.has_no_suit(self) then - return false - end - if SMODS.has_any_suit(self) then - return true - end - if next(find_joker('Smeared Joker')) and (self.base.suit == 'Hearts' or self.base.suit == 'Diamonds') == (suit == 'Hearts' or suit == 'Diamonds') then - return true - end - return self.base.suit == suit - end -end - -function Card:set_card_area(area) - self.area = area - self.parent = area - self.layered_parallax = area.layered_parallax -end - -function Card:remove_from_area() - self.area = nil - self.parent = nil - self.layered_parallax = {x = 0, y = 0} -end - -function Card:align() - if self.children.floating_sprite then - self.children.floating_sprite.T.y = self.T.y - self.children.floating_sprite.T.x = self.T.x - self.children.floating_sprite.T.r = self.T.r - end - - if self.children.focused_ui then self.children.focused_ui:set_alignment() end -end - -function Card:flip() - if self.facing == 'front' then - self.flipping = 'f2b' - self.facing='back' - self.pinch.x = true - elseif self.facing == 'back' then - self.ability.wheel_flipped = nil - self.flipping = 'b2f' - self.facing='front' - self.pinch.x = true - end -end - -function Card:update(dt) - if self.flipping == 'f2b' then - if self.sprite_facing == 'front' or true then - if self.VT.w <= 0 then - self.sprite_facing = 'back' - self.pinch.x =false - end - end - end - if self.flipping == 'b2f' then - if self.sprite_facing == 'back' or true then - if self.VT.w <= 0 then - self.sprite_facing = 'front' - self.pinch.x =false - end - end - end - - if not self.states.focus.is and self.children.focused_ui then - self.children.focused_ui:remove() - self.children.focused_ui = nil - end - - self:update_alert() - if self.ability.set == 'Joker' and not self.sticker_run then - self.sticker_run = get_joker_win_sticker(self.config.center) or 'NONE' - end - - if self.ability.consumeable and self.ability.consumeable.max_highlighted then - self.ability.consumeable.mod_num = self.ability.consumeable.max_highlighted - end - local obj = self.config.center - if obj.update and type(obj.update) == 'function' then - obj:update(self, dt) - end - local obj = G.P_SEALS[self.seal] or {} - if obj.update and type(obj.update) == 'function' then - obj:update(self, dt) - end - if G.STAGE == G.STAGES.RUN then - if self.ability and self.ability.perma_debuff then self.debuff = true end - if self.cry_debuff_immune then - self.debuff = false - end - - if self.area and ((self.area == G.jokers) or (self.area == G.consumeables)) then - self.bypass_lock = true - self.bypass_discovery_center = true - self.bypass_discovery_ui = true - end - self.sell_cost_label = (self.facing == 'back' and '?') or (G.GAME.modifiers.cry_no_sell_value and 0) or self.sell_cost - - if self.ability.name == 'Temperance' then - self.ability.money = 0 - for i = 1, #G.jokers.cards do - if G.jokers.cards[i].ability.set == 'Joker' then - self.ability.money = self.ability.money + G.jokers.cards[i].sell_cost - end - end - self.ability.money = math.min(self.ability.money, self.ability.extra) - end - if self.ability.name == 'Throwback' then - self.ability.x_mult = 1 + G.GAME.skips*self.ability.extra - end - if self.ability.name == "Driver's License" then - self.ability.driver_tally = 0 - for k, v in pairs(G.playing_cards) do - if next(SMODS.get_enhancements(v)) then self.ability.driver_tally = self.ability.driver_tally+1 end - end - end - if self.ability.name == "Steel Joker" then - self.ability.steel_tally = 0 - for k, v in pairs(G.playing_cards) do - if SMODS.has_enhancement(v, 'm_steel') then self.ability.steel_tally = self.ability.steel_tally+1 end - end - end - if self.ability.name == "Cloud 9" then - self.ability.nine_tally = 0 - for k, v in pairs(G.playing_cards) do - if v:get_id() == 9 then self.ability.nine_tally = self.ability.nine_tally+1 end - end - end - if self.ability.name == "Stone Joker" then - self.ability.stone_tally = 0 - for k, v in pairs(G.playing_cards) do - if SMODS.has_enhancement(v, 'm_stone') then self.ability.stone_tally = self.ability.stone_tally+1 end - end - end - if self.ability.name == "Joker Stencil" then - self.ability.x_mult = (G.jokers.config.card_limit - #G.jokers.cards) - for i = 1, #G.jokers.cards do - if G.jokers.cards[i].ability.name == 'Joker Stencil' then self.ability.x_mult = self.ability.x_mult + 1 end - end - end - if self.ability.name == 'The Wheel of Fortune' then - self.eligible_strength_jokers = EMPTY(self.eligible_strength_jokers) - for k, v in pairs(G.jokers.cards) do - if v.ability.set == 'Joker' and (not v.edition) then - table.insert(self.eligible_strength_jokers, v) - end - end - end - if self.ability.name == 'Ectoplasm' or self.ability.name == 'Hex' then - self.eligible_editionless_jokers = EMPTY(self.eligible_editionless_jokers) - for k, v in pairs(G.jokers.cards) do - if v.ability.set == 'Joker' and (not v.edition) then - table.insert(self.eligible_editionless_jokers, v) - end - end - end - if self.ability.name == 'Blueprint' or self.ability.name == 'Brainstorm' then - local other_joker = nil - if self.ability.name == 'Brainstorm' then - other_joker = G.jokers.cards[1] - elseif self.ability.name == 'Blueprint' then - for i = 1, #G.jokers.cards do - if G.jokers.cards[i] == self then other_joker = G.jokers.cards[i+1] end - end - end - if other_joker and other_joker ~= self and other_joker.config.center.blueprint_compat then - self.ability.blueprint_compat = 'compatible' - else - self.ability.blueprint_compat = 'incompatible' - end - end - if self.ability.name == 'Swashbuckler' then - local sell_cost = 0 - for i = 1, #G.jokers.cards do - if G.jokers.cards[i] ~= self and (G.jokers.cards[i].area and G.jokers.cards[i].area == G.jokers) then - sell_cost = sell_cost + G.jokers.cards[i].sell_cost - end - end - self.ability.mult = sell_cost - end - else - if self.ability.name == 'Temperance' then - self.ability.money = 0 - end - end -end - -function Card:hard_set_T(X, Y, W, H) - local x = (X or self.T.x) - local y = (Y or self.T.y) - local w = (W or self.T.w) - local h = (H or self.T.h) - Moveable.hard_set_T(self,x, y, w, h) - if self.children.front then self.children.front:hard_set_T(x, y, w, h) end - self.children.back:hard_set_T(x, y, w, h) - self.children.center:hard_set_T(x, y, w, h) -end - -function Card:move(dt) - Moveable.move(self, dt) - --self:align() - if self.children.h_popup then - self.children.h_popup:set_alignment(self:align_h_popup()) - end -end - -function Card:align_h_popup() - local focused_ui = self.children.focused_ui and true or false - local popup_direction = (self.children.buy_button or (self.area and self.area.config.view_deck) or (self.area and self.area.config.type == 'shop')) and 'cl' or - (self.T.y < G.CARD_H*0.8) and 'bm' or - 'tm' - return { - major = self.children.focused_ui or self, - parent = self, - xy_bond = 'Strong', - r_bond = 'Weak', - wh_bond = 'Weak', - offset = { - x = popup_direction ~= 'cl' and 0 or - focused_ui and -0.05 or - (self.ability.consumeable and 0.0) or - (self.ability.set == 'Voucher' and 0.0) or - -0.05, - y = focused_ui and ( - popup_direction == 'tm' and (self.area and self.area == G.hand and -0.08 or-0.15) or - popup_direction == 'bm' and 0.12 or - 0 - ) or - popup_direction == 'tm' and -0.13 or - popup_direction == 'bm' and 0.1 or - 0 - }, - type = popup_direction, - --lr_clamp = true - } -end - -function Card:hover() -if Handy.controller.process_card_hover(self) then return end - self:juice_up(0.05, 0.03) - play_sound('paper1', math.random()*0.2 + 0.9, 0.35) - - --if this is the focused card - if self.states.focus.is and not self.children.focused_ui then - self.children.focused_ui = G.UIDEF.card_focus_ui(self) - end - - if self.facing == 'front' and (not self.states.drag.is or G.CONTROLLER.HID.touch) and not self.no_ui and not G.debug_tooltip_toggle then - if self.children.alert and not self.config.center.alerted then - self.config.center.alerted = true - G:save_progress() - elseif self.children.alert and self.seal and not G.P_SEALS[self.seal].alerted then - G.P_SEALS[self.seal].alerted = true - G:save_progress() - end - - self.ability_UIBox_table = self:generate_UIBox_ability_table() - self.config.h_popup = G.UIDEF.card_h_popup(self) - self.config.h_popup_config = self:align_h_popup() - - Node.hover(self) - end -end - -function Card:stop_hover() - Node.stop_hover(self) -end - -function Card:juice_up(scale, rot_amount) - --G.VIBRATION = G.VIBRATION + 0.4 - local rot_amt = rot_amount and 0.4*(math.random()>0.5 and 1 or -1)*rot_amount or (math.random()>0.5 and 1 or -1)*0.16 - scale = scale and scale*0.4 or 0.11 - Moveable.juice_up(self, scale, rot_amt) -end - -function Card:draw(layer) - layer = layer or 'both' - - self.hover_tilt = 1 - - if not self.states.visible then return end - if self.VT.x < -3 or self.VT.x > G.TILE_W + 2.5 then return end - - if (layer == 'shadow' or layer == 'both') then - self.ARGS.send_to_shader = self.ARGS.send_to_shader or {} - self.ARGS.send_to_shader[1] = math.min(self.VT.r*3, 1) + math.sin(G.TIMERS.REAL/28) + 1 + (self.juice and self.juice.r*20 or 0) + self.tilt_var.amt - self.ARGS.send_to_shader[2] = G.TIMERS.REAL - - for k, v in pairs(self.children) do - v.VT.scale = self.VT.scale - end - end - - G.shared_shadow = self.sprite_facing == 'front' and self.children.center or self.children.back - - --Draw the shadow - if not self.no_shadow and G.SETTINGS.GRAPHICS.shadows == 'On' and((layer == 'shadow' or layer == 'both') and (self.ability.effect ~= 'Glass Card' and not self.greyed and self:should_draw_shadow() ) and ((self.area and self.area ~= G.discard and self.area.config.type ~= 'deck') or not self.area or self.states.drag.is)) then - self.shadow_height = 0*(0.08 + 0.4*math.sqrt(self.velocity.x^2)) + ((((self.highlighted and self.area == G.play) or self.states.drag.is) and 0.35) or (self.area and self.area.config.type == 'title_2') and 0.04 or 0.1) - G.shared_shadow:draw_shader('dissolve', self.shadow_height) - end - - if (layer == 'card' or layer == 'both') and self.area ~= G.hand then - if self.children.focused_ui then self.children.focused_ui:draw() end - end - - if (layer == 'card' or layer == 'both') then - -- for all hover/tilting: - self.tilt_var = self.tilt_var or {mx = 0, my = 0, dx = self.tilt_var.dx or 0, dy = self.tilt_var.dy or 0, amt = 0} - local tilt_factor = 0.3 - if self.states.focus.is then - self.tilt_var.mx, self.tilt_var.my = G.CONTROLLER.cursor_position.x + self.tilt_var.dx*self.T.w*G.TILESCALE*G.TILESIZE, G.CONTROLLER.cursor_position.y + self.tilt_var.dy*self.T.h*G.TILESCALE*G.TILESIZE - self.tilt_var.amt = math.abs(self.hover_offset.y + self.hover_offset.x - 1 + self.tilt_var.dx + self.tilt_var.dy - 1)*tilt_factor - elseif self.states.hover.is then - self.tilt_var.mx, self.tilt_var.my = G.CONTROLLER.cursor_position.x, G.CONTROLLER.cursor_position.y - self.tilt_var.amt = math.abs(self.hover_offset.y + self.hover_offset.x - 1)*tilt_factor - elseif self.ambient_tilt then - local tilt_angle = G.TIMERS.REAL*(1.56 + (self.ID/1.14212)%1) + self.ID/1.35122 - self.tilt_var.mx = ((0.5 + 0.5*self.ambient_tilt*math.cos(tilt_angle))*self.VT.w+self.VT.x+G.ROOM.T.x)*G.TILESIZE*G.TILESCALE - self.tilt_var.my = ((0.5 + 0.5*self.ambient_tilt*math.sin(tilt_angle))*self.VT.h+self.VT.y+G.ROOM.T.y)*G.TILESIZE*G.TILESCALE - self.tilt_var.amt = self.ambient_tilt*(0.5+math.cos(tilt_angle))*tilt_factor - end - --Any particles - if self.children.particles then self.children.particles:draw() end - - --Draw any tags/buttons - if self.children.price then self.children.price:draw() end - if self.children.buy_button then - if self.highlighted then - self.children.buy_button.states.visible = true - self.children.buy_button:draw() - if self.children.buy_and_use_button then - self.children.buy_and_use_button:draw() - end - else - self.children.buy_button.states.visible = false - end - end - if self.children.use_button and self.highlighted then self.children.use_button:draw() end - - if self.vortex then - if self.facing == 'back' then - self.children.back:draw_shader('vortex') - else - self.children.center:draw_shader('vortex') - if self.children.front then - self.children.front:draw_shader('vortex') - end - end - - love.graphics.setShader() - elseif self.sprite_facing == 'front' then - --Draw the main part of the card - if (self.edition and (self.edition.negative or self.edition.cry_oversat)) or (self.ability.name == 'Antimatter' and (self.config.center.discovered or self.bypass_discovery_center)) then - self.children.center:draw_shader('negative', nil, self.ARGS.send_to_shader) - if self.children.front and self.ability.effect ~= 'Stone Card' and not self.config.center.replace_base_card then - self.children.front:draw_shader('negative', nil, self.ARGS.send_to_shader) - end - elseif not self:should_draw_base_shader() then - -- Don't render base dissolve shader. - elseif not self.greyed then - self.children.center:draw_shader('dissolve') - --If the card has a front, draw that next - if self.children.front and self.ability.effect ~= 'Stone Card' and not self.config.center.replace_base_card then - self.children.front:draw_shader('dissolve') - end - end - - --If the card is not yet discovered - if self.ability.set == 'Enhanced' then self.ability.consumeable = nil end - if not self.config.center.discovered and (self.ability.consumeable or self.config.center.unlocked) and not self.config.center.demo and not self.bypass_discovery_center then - local shared_sprite = (self.ability.set == 'Edition' or self.ability.set == 'Joker') and G.shared_undiscovered_joker or G.shared_undiscovered_tarot - local scale_mod = -0.05 + 0.05*math.sin(1.8*G.TIMERS.REAL) - local rotate_mod = 0.03*math.sin(1.219*G.TIMERS.REAL) - - shared_sprite.role.draw_major = self - if (self.config.center.undiscovered and not self.config.center.undiscovered.no_overlay) or not( SMODS.UndiscoveredSprites[self.ability.set] and SMODS.UndiscoveredSprites[self.ability.set].no_overlay) then - shared_sprite:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod) - else - end - end - - if self.ability.name == 'Invisible Joker' and (self.config.center.discovered or self.bypass_discovery_center) then - if self:should_draw_base_shader() then - self.children.center:draw_shader('voucher', nil, self.ARGS.send_to_shader) - end - end - - local center = self.config.center - if center.draw and type(center.draw) == 'function' then - center:draw(self, layer) - end - if center.set == 'Default' or center.set == 'Enhanced' and not center.replace_base_card then - if not center.no_suit then - local suit = SMODS.Suits[self.base.suit] or {} - if suit.draw and type(suit.draw) == 'function' then - suit:draw(self, layer) - end - end - if not center.no_rank then - local rank = SMODS.Ranks[self.base.value] or {} - if rank.draw and type(rank.draw) == 'function' then - rank:draw(self, layer) - end - end - end - --If the card has any edition/seal, add that here - if true then - - if (self.ability.set == 'Voucher' or self.config.center.demo) and (self.ability.name ~= 'Antimatter' or not (self.config.center.discovered or self.bypass_discovery_center)) then - if self:should_draw_base_shader() then - self.children.center:draw_shader('voucher', nil, self.ARGS.send_to_shader) - end - end - if (self.ability.set == 'Booster' or self.ability.set == 'Spectral') and self:should_draw_base_shader() then - self.children.center:draw_shader('booster', nil, self.ARGS.send_to_shader) - end - if self.edition then - for k, v in pairs(G.P_CENTER_POOLS.Edition) do - if self.edition[v.key:sub(3)] and v.shader then - if type(v.draw) == 'function' then - v:draw(self, layer) - else - self.children.center:draw_shader(v.shader, nil, self.ARGS.send_to_shader) - if self.children.front and self.ability.effect ~= 'Stone Card' and not self.config.center.replace_base_card then - self.children.front:draw_shader(v.shader, nil, self.ARGS.send_to_shader) - end - end - end - end - end - if (self.edition and (self.edition.negative or self.edition.cry_oversat)) or (self.ability.name == 'Antimatter' and (self.config.center.discovered or self.bypass_discovery_center)) then - self.children.center:draw_shader('negative_shine', nil, self.ARGS.send_to_shader) - end - local seal = G.P_SEALS[self.seal or {}] or {} - if type(seal.draw) == 'function' then - seal:draw(self, layer) - elseif self.seal then - G.shared_seals[self.seal].role.draw_major = self - G.shared_seals[self.seal]:draw_shader('dissolve', nil, nil, nil, self.children.center) - if self.seal == 'Gold' then G.shared_seals[self.seal]:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center) end - end - if self.ability.eternal then - G.shared_sticker_eternal.role.draw_major = self - G.shared_sticker_eternal:draw_shader('dissolve', nil, nil, nil, self.children.center) - G.shared_sticker_eternal:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center) - end - if self.ability.perishable and not layer then - G.shared_sticker_perishable.role.draw_major = self - G.shared_sticker_perishable:draw_shader('dissolve', nil, nil, nil, self.children.center) - G.shared_sticker_perishable:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center) - end - if self.ability.rental then - G.shared_sticker_rental.role.draw_major = self - G.shared_sticker_rental:draw_shader('dissolve', nil, nil, nil, self.children.center) - G.shared_sticker_rental:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center) - end - if self.sticker and G.shared_stickers[self.sticker] then - G.shared_stickers[self.sticker].role.draw_major = self - G.shared_stickers[self.sticker]:draw_shader('dissolve', nil, nil, nil, self.children.center) - G.shared_stickers[self.sticker]:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center) - elseif (self.sticker_run and G.shared_stickers[self.sticker_run]) and G.SETTINGS.run_stake_stickers then - G.shared_stickers[self.sticker_run].role.draw_major = self - G.shared_stickers[self.sticker_run]:draw_shader('dissolve', nil, nil, nil, self.children.center) - G.shared_stickers[self.sticker_run]:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center) - end - - for k, v in pairs(SMODS.Stickers) do - if self.ability[v.key] then - if v and v.draw and type(v.draw) == 'function' then - v:draw(self, layer) - else - G.shared_stickers[v.key].role.draw_major = self - G.shared_stickers[v.key]:draw_shader('dissolve', nil, nil, nil, self.children.center) - G.shared_stickers[v.key]:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center) - end - end - end - if self.ability.name == 'The Soul' and (self.config.center.discovered or self.bypass_discovery_center) then - local scale_mod = 0.05 + 0.05*math.sin(1.8*G.TIMERS.REAL) + 0.07*math.sin((G.TIMERS.REAL - math.floor(G.TIMERS.REAL))*math.pi*14)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^3 - local rotate_mod = 0.1*math.sin(1.219*G.TIMERS.REAL) + 0.07*math.sin((G.TIMERS.REAL)*math.pi*5)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^2 - - G.shared_soul.role.draw_major = self - G.shared_soul:draw_shader('dissolve',0, nil, nil, self.children.center,scale_mod, rotate_mod,nil, 0.1 + 0.03*math.sin(1.8*G.TIMERS.REAL),nil, 0.6) - G.shared_soul:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod) - end - - if self.ability.name == 'cry-Gateway' and (self.config.center.discovered or self.bypass_discovery_center) then - local scale_mod2 = 0.07-- + 0.02*math.cos(1.8*G.TIMERS.REAL) + 0.00*math.cos((G.TIMERS.REAL - math.floor(G.TIMERS.REAL))*math.pi*14)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^3 - local rotate_mod2 = 0--0.05*math.cos(1.219*G.TIMERS.REAL) + 0.00*math.cos((G.TIMERS.REAL)*math.pi*5)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^2 - self.children.floating_sprite2:draw_shader('dissolve',0, nil, nil, self.children.center,scale_mod2, rotate_mod2,nil, 0.1--[[ + 0.03*math.cos(1.8*G.TIMERS.REAL)--]],nil, 0.6) - self.children.floating_sprite2:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod2, rotate_mod2) - - local scale_mod = 0.05 + 0.05*math.sin(1.8*G.TIMERS.REAL) + 0.07*math.sin((G.TIMERS.REAL - math.floor(G.TIMERS.REAL))*math.pi*14)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^3 - local rotate_mod = 0.1*math.sin(1.219*G.TIMERS.REAL) + 0.07*math.sin((G.TIMERS.REAL)*math.pi*5)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^2 - - self.children.floating_sprite.role.draw_major = self - self.children.floating_sprite:draw_shader('dissolve',0, nil, nil, self.children.center,scale_mod, rotate_mod,nil, 0.1 + 0.03*math.sin(1.8*G.TIMERS.REAL),nil, 0.6) - self.children.floating_sprite:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod) - - end - if self.config.center.soul_pos and (self.config.center.discovered or self.bypass_discovery_center) then - if self.config.center.soul_pos and self.config.center.soul_pos.extra and (self.config.center.discovered or self.bypass_discovery_center) then - local scale_mod = 0.07-- + 0.02*math.cos(1.8*G.TIMERS.REAL) + 0.00*math.cos((G.TIMERS.REAL - math.floor(G.TIMERS.REAL))*math.pi*14)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^3 - local rotate_mod = 0--0.05*math.cos(1.219*G.TIMERS.REAL) + 0.00*math.cos((G.TIMERS.REAL)*math.pi*5)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^2 - self.children.floating_sprite2:draw_shader('dissolve',0, nil, nil, self.children.center,scale_mod, rotate_mod,nil, 0.1--[[ + 0.03*math.cos(1.8*G.TIMERS.REAL)--]],nil, 0.6) - self.children.floating_sprite2:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod) - end - local scale_mod = 0.07 + 0.02*math.sin(1.8*G.TIMERS.REAL) + 0.00*math.sin((G.TIMERS.REAL - math.floor(G.TIMERS.REAL))*math.pi*14)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^3 - local rotate_mod = 0.05*math.sin(1.219*G.TIMERS.REAL) + 0.00*math.sin((G.TIMERS.REAL)*math.pi*5)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^2 - - if self.ability.name == 'Hologram' then - self.hover_tilt = self.hover_tilt*1.5 - self.children.floating_sprite:draw_shader('hologram', nil, self.ARGS.send_to_shader, nil, self.children.center, 2*scale_mod, 2*rotate_mod) - self.hover_tilt = self.hover_tilt/1.5 - else - self.children.floating_sprite:draw_shader('dissolve',0, nil, nil, self.children.center,scale_mod, rotate_mod,nil, 0.1 + 0.03*math.sin(1.8*G.TIMERS.REAL),nil, 0.6) - self.children.floating_sprite:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod) - if self.edition then - for k, v in pairs(G.P_CENTER_POOLS.Edition) do - if v.apply_to_float then - if self.edition[v.key:sub(3)] then - self.children.floating_sprite:draw_shader(v.shader, nil, nil, nil, self.children.center, scale_mod, rotate_mod) - end - end - end - end - end - - end - if self.debuff then - self.children.center:draw_shader('debuff', nil, self.ARGS.send_to_shader) - if self.children.front and self.ability.effect ~= 'Stone Card' and not self.config.center.replace_base_card then - self.children.front:draw_shader('debuff', nil, self.ARGS.send_to_shader) - end - end - if self.greyed then - self.children.center:draw_shader('played', nil, self.ARGS.send_to_shader) - if self.children.front and self.ability.effect ~= 'Stone Card' and not self.config.center.replace_base_card then - self.children.front:draw_shader('played', nil, self.ARGS.send_to_shader) - end - end - end - if self.pinned then - G.shared_stickers['pinned'].role.draw_major = self - G.shared_stickers['pinned']:draw_shader('dissolve', nil, nil, nil, self.children.center) - G.shared_stickers['pinned']:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center) - end - elseif self.sprite_facing == 'back' then - local overlay = G.C.WHITE - if self.area and self.area.config.type == 'deck' and self.rank > 3 then - self.back_overlay = self.back_overlay or {} - self.back_overlay[1] = 0.5 + ((#self.area.cards - self.rank)%7)/50 - self.back_overlay[2] = 0.5 + ((#self.area.cards - self.rank)%7)/50 - self.back_overlay[3] = 0.5 + ((#self.area.cards - self.rank)%7)/50 - self.back_overlay[4] = 1 - overlay = self.back_overlay - end - - if self.area and self.area.config.type == 'deck' then - self.children.back:draw(overlay) - local currentBack = self.params.viewed_back and G.GAME.viewed_back or G.GAME.selected_back - if currentBack.effect.config.cry_force_edition and not currentBack.effect.config.cry_antimatter then - if currentBack.effect.config.cry_force_edition_shader then - self.children.back:draw_shader(currentBack.effect.config.cry_force_edition_shader , nil, self.ARGS.send_to_shader, true) - else - self.children.back:draw_shader(currentBack.effect.config.cry_force_edition , nil, self.ARGS.send_to_shader, true) - end - end - if currentBack.effect.config.cry_force_seal and not currentBack.effect.config.hide_seal and not currentBack.effect.config.cry_antimatter then - G.shared_seals[currentBack.effect.config.cry_force_seal]:draw_shader('dissolve', nil, nil, true, self.children.center) - if currentBack.effect.config.cry_force_seal == 'Gold' then G.shared_seals[currentBack.effect.config.cry_force_seal]:draw_shader('voucher', nil, self.ARGS.send_to_shader, true, self.children.center) end - end - if currentBack.effect.config.cry_force_sticker and not currentBack.effect.config.cry_antimatter then - for k, v in pairs(SMODS.Stickers) do - if currentBack.effect.config.cry_force_sticker == v.key then - if v and v.draw and type(v.draw) == 'function' then - v:draw(self) - else - G.shared_stickers[v.key].role.draw_major = self - G.shared_stickers[v.key]:draw_shader('dissolve', nil, nil, true, self.children.center) - G.shared_stickers[v.key]:draw_shader('voucher', nil, self.ARGS.send_to_shader, true, self.children.center) - end - end - end - end - if currentBack.effect.config.cry_antimatter or currentBack.effect.config.cry_force_edition == 'negative' then - self.children.back:draw_shader('negative', nil, self.ARGS.send_to_shader, true) - self.children.center:draw_shader('negative_shine', nil, self.ARGS.send_to_shader, true) - end - else - local currentBack = self.params.viewed_back and G.GAME.viewed_back or G.GAME.selected_back - if currentBack and currentBack.effect.config.cry_antimatter or currentBack.effect.config.cry_force_edition == 'negative' then - self.children.back:draw_shader('negative', nil, self.ARGS.send_to_shader) - self.children.center:draw_shader('negative_shine', nil, self.ARGS.send_to_shader) - else - self.children.back:draw_shader('dissolve') - end - end - - if self.sticker and G.shared_stickers[self.sticker] then - G.shared_stickers[self.sticker].role.draw_major = self - G.shared_stickers[self.sticker]:draw_shader('dissolve', nil, nil, true, self.children.center) - if self.sticker == 'Gold' then G.shared_stickers[self.sticker]:draw_shader('voucher', nil, self.ARGS.send_to_shader, true, self.children.center) end - end - end - - for k, v in pairs(self.children) do - if not v.custom_draw and k ~= 'focused_ui' and k ~= "front" and k ~= "back" and k ~= "soul_parts" and k ~= "center" and k ~= 'floating_sprite' and k ~= 'floating_sprite2' and k~= "shadow" and k~= "use_button" and k ~= 'buy_button' and k ~= 'buy_and_use_button' and k~= "debuff" and k ~= 'price' and k~= 'particles' and k ~= 'h_popup' then v:draw() end - end - - if (layer == 'card' or layer == 'both') and self.area == G.hand then - if self.children.focused_ui then self.children.focused_ui:draw() end - end - - add_to_drawhash(self) - self:draw_boundingrect() - end -end - -function Card:release(dragged) - if dragged:is(Card) and self.area then - self.area:release(dragged) - end -end - -function Card:highlight(is_higlighted) - self.highlighted = is_higlighted - if true then - if self.highlighted and self.area and self.area.config.type ~= 'shop' then - local x_off = (self.ability.consumeable and -0.1 or 0) - self.children.use_button = UIBox{ - definition = G.UIDEF.use_and_sell_buttons(self), - config = {align= - ((self.area == G.jokers) or (self.area == G.consumeables)) and "cr" or - "bmi" - , offset = - ((self.area == G.jokers) or (self.area == G.consumeables)) and {x=x_off - 0.4,y=0} or - {x=0,y=0.65}, - parent =self} - } - elseif self.children.use_button then - self.children.use_button:remove() - self.children.use_button = nil - end - end - if self.ability.consumeable or self.ability.set == 'Joker' then - if not self.highlighted and self.area and self.area.config.type == 'joker' and - (#G.jokers.cards >= G.jokers.config.card_limit or (self.edition and self.edition.negative)) then - if G.shop_jokers then G.shop_jokers:unhighlight_all() end - end - end -end - -function Card:click() -if Handy.controller.process_card_click(self) then return end - if self.area and self.area:can_highlight(self) then - if (self.area == G.hand) and (G.STATE == G.STATES.HAND_PLAYED) then return end - if self.highlighted ~= true then - self.area:add_to_highlighted(self) - else - self.area:remove_from_highlighted(self) - play_sound('cardSlide2', nil, 0.3) - end - end - if self.area and self.area == G.deck and self.area.cards[1] == self then - G.FUNCS.deck_info() - end -end - -function Card:save() - cardTable = { - sort_id = self.sort_id, - save_fields = { - center = self.config.center_key, - card = self.config.card_key, - }, - params = self.params, - no_ui = self.no_ui, - base_cost = self.base_cost, - extra_cost = self.extra_cost, - cost = self.cost, - sell_cost = self.sell_cost, - facing = self.facing, - sprite_facing = self.facing, - flipping = nil, - highlighted = self.highligted, - debuff = self.debuff, - rank = self.rank, - added_to_deck = self.added_to_deck, - joker_added_to_deck_but_debuffed = self.joker_added_to_deck_but_debuffed, - label = self.label, - playing_card = self.playing_card, - base = self.base, - shop_voucher = self.shop_voucher, - shop_cry_bonusvoucher = self.shop_cry_bonusvoucher, - ability = self.ability, - pinned = self.pinned, - edition = self.edition, - seal = self.seal, - bypass_discovery_center = self.bypass_discovery_center, - bypass_discovery_ui = self.bypass_discovery_ui, - bypass_lock = self.bypass_lock, - unique_val = self.unique_val, - unique_val__saved_ID = self.ID, - ignore_base_shader = self.ignore_base_shader, - ignore_shadow = self.ignore_shadow, - } - return cardTable -end - -function Card:load(cardTable, other_card) - local scale = 1 - self.config = {} - self.config.center_key = cardTable.save_fields.center - self.config.center = G.P_CENTERS[self.config.center_key] - self.params = cardTable.params - self.sticker_run = nil - - local H = G.CARD_H - local W = G.CARD_W - local obj = self.config.center - if obj.load and type(obj.load) == 'function' then - obj:load(self, cardTable, other_card) - elseif self.config.center.name == "Half Joker" then - self.T.h = H*scale/1.7*scale - self.T.w = W*scale - elseif self.config.center.name == "cry-Wee Fibonacci" or self.config.center.name == "cry-reverse" then - self.T.h = H*scale*0.7*scale - self.T.w = W*scale*0.7*scale - elseif self.config.center.name == "cry-biggestm" then - self.T.h = H*scale*1.7*scale - self.T.w = W*scale*1.7*scale - elseif self.config.center.name == "cry-Booster Joker" then - self.T.h = H*scale*1.17*scale - self.T.w = W*scale*1.17*scale - elseif self.config.center.name == "cry-Cube" then - self.T.h = H*scale*0.1*scale - self.T.w = W*scale*0.1*scale - elseif self.config.center.name == "cry-Jimball" then - H = W - self.T.h = H*scale*57/69*scale - self.T.w = W*scale*57/69*scale - elseif self.config.center.name == "cry-Potion" then - H = W - self.T.h = H*scale*35/69*scale - self.T.w = W*scale*35/69*scale - elseif self.config.center.name == "cry-magnet" then - H = W - self.T.h = H*scale*35/71*scale - self.T.w = W*scale*35/71*scale - elseif self.config.center.name == "Wee Joker" then - self.T.h = H*scale*0.7*scale - self.T.w = W*scale*0.7*scale - elseif self.config.center.name == "Photograph" then - self.T.h = H*scale/1.2*scale - self.T.w = W*scale - elseif self.config.center.name == "Square Joker" then - H = W - self.T.h = H*scale - self.T.w = W*scale - elseif self.config.center.set == 'Booster' then - self.T.h = H*1.27 - self.T.w = W*1.27 - else - self.T.h = H*scale - self.T.w = W*scale - end - self.VT.h = self.T.H - self.VT.w = self.T.w - - self.config.card_key = cardTable.save_fields.card - self.config.card = G.P_CARDS[self.config.card_key] - - self.no_ui = cardTable.no_ui - self.base_cost = cardTable.base_cost - self.extra_cost = cardTable.extra_cost - self.cost = cardTable.cost - self.sell_cost = cardTable.sell_cost - self.facing = cardTable.facing - self.sprite_facing = cardTable.sprite_facing - self.flipping = cardTable.flipping - self.highlighted = cardTable.highlighted - self.debuff = cardTable.debuff - self.rank = cardTable.rank - self.added_to_deck = cardTable.added_to_deck - self.label = cardTable.label - self.playing_card = cardTable.playing_card - self.base = cardTable.base - self.sort_id = cardTable.sort_id - self.bypass_discovery_center = cardTable.bypass_discovery_center - self.bypass_discovery_ui = cardTable.bypass_discovery_ui - self.bypass_lock = cardTable.bypass_lock - self.unique_val = cardTable.unique_val or self.unique_val - if cardTable.unique_val__saved_ID and G.ID <= cardTable.unique_val__saved_ID then - G.ID = cardTable.unique_val__saved_ID + 1 - end - - self.ignore_base_shader = cardTable.ignore_base_shader or {} - self.ignore_shadow = cardTable.ignore_shadow or {} - - self.shop_voucher = cardTable.shop_voucher - self.shop_cry_bonusvoucher = cardTable.shop_cry_bonusvoucher - self.ability = cardTable.ability - self.pinned = cardTable.pinned - self.edition = cardTable.edition - self.seal = cardTable.seal - - remove_all(self.children) - self.children = {} - self.children.shadow = Moveable(0, 0, 0, 0) - - self:set_sprites(self.config.center, self.config.card) -end - -function Card:remove() - self.removed = true - - if self.area then self.area:remove_card(self) end - - self:remove_from_deck() - if self.ability.joker_added_to_deck_but_debuffed then - if self.edition and self.edition.card_limit then - if self.ability.consumeable then - G.consumeables.config.card_limit = G.consumeables.config.card_limit - self.edition.card_limit - elseif self.ability.set == 'Joker' then - G.jokers.config.card_limit = G.jokers.config.card_limit - self.edition.card_limit - end - end - end - - if not G.OVERLAY_MENU then - if not next(SMODS.find_card(self.config.center.key, true)) then - G.GAME.used_jokers[self.config.center.key] = nil - end - end - - if G.playing_cards then - for k, v in ipairs(G.playing_cards) do - if v == self then - table.remove(G.playing_cards, k) - break - end - end - for k, v in ipairs(G.playing_cards) do - v.playing_card = k - end - end - - remove_all(self.children) - - for k, v in pairs(G.I.CARD) do - if v == self then - table.remove(G.I.CARD, k) - end - end - Moveable.remove(self) -end diff --git a/lovely/dump/cardarea.lua b/lovely/dump/cardarea.lua deleted file mode 100644 index 343cc8d..0000000 --- a/lovely/dump/cardarea.lua +++ /dev/null @@ -1,727 +0,0 @@ -LOVELY_INTEGRITY = 'e8693aca875516bf9cb3c84fcb6f392131135da095f221f2ef0e6ac727b926df' - ---Class -CardArea = Moveable:extend() - ---Class Methods -function CardArea:init(X, Y, W, H, config) - Moveable.init(self, X, Y, W, H) - - self.states.drag.can = false - self.states.hover.can = false - self.states.click.can = false - - - self.config = config or {} - self.card_w = config.card_w or G.CARD_W - self.cards = {} - self.children = {} - self.highlighted = {} - self.config.highlighted_limit = config.highlight_limit or G.GAME.modifiers.cry_highlight_limit or 5 - self.config.card_limit = config.card_limit or 52 - self.config.temp_limit = self.config.card_limit - self.config.card_count = 0 - self.config.type = config.type or 'deck' - self.config.sort = config.sort or 'desc' - self.config.lr_padding = config.lr_padding or 0.1 - self.shuffle_amt = 0 - - if getmetatable(self) == CardArea then - table.insert(G.I.CARDAREA, self) - end -end - -function CardArea:emplace(card, location, stay_flipped) -if self == G.jokers then - Cartomancer.handle_joker_added(card) -end - if card.edition and card.edition.card_limit and (self == G.hand) then - self.config.real_card_limit = (self.config.real_card_limit or self.config.card_limit) + card.edition.card_limit - self.config.card_limit = math.max(0, self.config.real_card_limit) - end - if location == 'front' or self.config.type == 'deck' then - table.insert(self.cards, 1, card) - else - self.cards[#self.cards+1] = card - end - if card.cry_flipped then card.facing = 'back'; card.sprite_facing = 'back' end - if not (card.cry_flipped and (self == G.shop_jokers or self == G.shop_vouchers or self == G.shop_booster)) and card.facing == 'back' and self.config.type ~= 'discard' and self.config.type ~= 'deck' and not stay_flipped then - card:flip() - end - if self == G.hand and stay_flipped then - card.ability.wheel_flipped = true - end - - if #self.cards > self.config.card_limit then - if self == G.deck then - self.config.card_limit = #self.cards - end - end - - card:set_card_area(self) - self:set_ranks() - self:align_cards() - - if self == G.jokers then - local joker_tally = 0 - for i = 1, #G.jokers.cards do - if G.jokers.cards[i].ability.set == 'Joker' then joker_tally = joker_tally + 1 end - end - if joker_tally > G.GAME.max_jokers then G.GAME.max_jokers = joker_tally end - check_for_unlock({type = 'modify_jokers'}) - end - if self == G.deck then check_for_unlock({type = 'modify_deck', deck = self}) end -end - -function CardArea:remove_card(card, discarded_only) - if not self.cards then return end - local _cards = discarded_only and {} or self.cards - if discarded_only then - for k, v in ipairs(self.cards) do - if v.ability and v.ability.discarded then - _cards[#_cards+1] = v - end - end - end - if self.config.type == 'discard' or self.config.type == 'deck' then - card = card or _cards[#_cards] - else - card = card or _cards[1] - end - for i = #self.cards,1,-1 do - if self.cards[i] == card then - if card.edition and card.edition.card_limit and (self == G.hand) then - self.config.real_card_limit = (self.config.real_card_limit or self.config.card_limit) - card.edition.card_limit - self.config.card_limit = math.max(0, self.config.real_card_limit) - end - card:remove_from_area() - table.remove(self.cards, i) - self:remove_from_highlighted(card, true) - break - end - end - self:set_ranks() - if self == G.deck then check_for_unlock({type = 'modify_deck', deck = self}) end - return card -end - -function CardArea:change_size(delta) - if delta ~= 0 then - G.E_MANAGER:add_event(Event({ - func = function() - self.config.real_card_limit = (self.config.real_card_limit or self.config.card_limit) + delta - self.config.card_limit = math.max(0, self.config.real_card_limit) - if delta > 0 and self.config.real_card_limit > 1 and self == G.hand and self.cards[1] and (G.STATE == G.STATES.DRAW_TO_HAND or G.STATE == G.STATES.SELECTING_HAND) then - local card_count = math.abs(delta) - for i=1, card_count do - draw_card(G.deck,G.hand, i*100/card_count,nil, nil , nil, 0.07) - G.E_MANAGER:add_event(Event({func = function() self:sort() return true end})) - end - end - if self == G.hand then check_for_unlock({type = 'min_hand_size'}) end - return true - end})) - end -end - -function CardArea:can_highlight(card) - if G.CONTROLLER.HID.controller then - if self.config.type == 'hand' - then - return true - end - else - if self.config.type == 'hand' or - self.config.type == 'joker' or - self.config.type == 'consumeable' or - (self.config.type == 'shop' and self.config.highlighted_limit > 0) - then - return true - end - end - return false -end - -function CardArea:add_to_highlighted(card, silent) - --if self.config.highlighted_limit <= #self.highlighted then return end - if self.config.type == 'shop' then - if self.highlighted[1] then - self:remove_from_highlighted(self.highlighted[1]) - end - --if not G.FUNCS.check_for_buy_space(card) then return false end - self.highlighted[#self.highlighted+1] = card - card:highlight(true) - if not silent then play_sound('cardSlide1') end - elseif self.config.type == 'joker' or self.config.type == 'consumeable' then - if #self.highlighted >= self.config.highlighted_limit then - self:remove_from_highlighted(self.highlighted[1]) - end - self.highlighted[#self.highlighted+1] = card - card:highlight(true) - if not silent then play_sound('cardSlide1') end - else - if #self.highlighted >= self.config.highlighted_limit then - card:highlight(false) - else - self.highlighted[#self.highlighted+1] = card - card:highlight(true) - if not silent then play_sound('cardSlide1') end - end - if self == G.hand and G.STATE == G.STATES.SELECTING_HAND then - self:parse_highlighted() - end - end -end - -function CardArea:parse_highlighted() - G.boss_throw_hand = nil - local text,disp_text,poker_hands = G.FUNCS.get_poker_hand_info(self.highlighted) - if text == 'NULL' then - update_hand_text({immediate = true, nopulse = true, delay = 0}, {mult = 0, chips = 0, level = '', handname = ''}) - else - if G.GAME.blind and G.GAME.blind:debuff_hand(self.highlighted, poker_hands, text, true) then - G.boss_throw_hand = true - else - - end - local backwards = nil - for k, v in pairs(self.highlighted) do - if v.facing == 'back' then - backwards = true - end - end - if backwards then - update_hand_text({immediate = true, nopulse = nil, delay = 0}, {handname='????', level='?', mult = '?', chips = '?'}) - else - update_hand_text({immediate = true, nopulse = nil, delay = 0}, {handname=disp_text, level=G.GAME.hands[text].level, mult = cry_ascend(G.GAME.hands[text].mult), chips = cry_ascend(G.GAME.hands[text].chips)}) - end - end -end - -function CardArea:remove_from_highlighted(card, force) - if (not force) and card and card.ability.forced_selection and self == G.hand then return end - for i = #self.highlighted,1,-1 do - if self.highlighted[i] == card then - table.remove(self.highlighted, i) - break - end - end - card:highlight(false) - if self == G.hand and G.STATE == G.STATES.SELECTING_HAND then - self:parse_highlighted() - end -end - -function CardArea:unhighlight_all() - for i = #self.highlighted,1,-1 do - if self.highlighted[i].ability.forced_selection and self == G.hand then - else - self.highlighted[i]:highlight(false) - table.remove(self.highlighted, i) - end - end - if self == G.hand and G.STATE == G.STATES.SELECTING_HAND then - self:parse_highlighted() - end -end - -function CardArea:set_ranks() - for k, card in ipairs(self.cards) do - card.rank = k - card.states.collide.can = true - if k > 1 and self.config.type == 'deck' then - card.states.drag.can = false - card.states.collide.can = false - elseif self.config.type == 'play' or self.config.type == 'shop' or self.config.type == 'consumeable' then - card.states.drag.can = false - else - card.states.drag.can = true - end - end -end - -function CardArea:move(dt) - --Set sliding up/down for the hand area - if self == G.hand then - local desired_y = G.TILE_H - G.hand.T.h - 1.9*((not G.deck_preview and (G.STATE == G.STATES.SELECTING_HAND or G.STATE == G.STATES.DRAW_TO_HAND)) and 1 or 0) - G.hand.T.y = 15*G.real_dt*desired_y + (1-15*G.real_dt)*G.hand.T.y - if math.abs(desired_y - G.hand.T.y) < 0.01 then G.hand.T.y = desired_y end - if G.STATE == G.STATES.TUTORIAL then - G.play.T.y = G.hand.T.y - (3 + 0.6) - end - end - Moveable.move(self, dt) - self:align_cards() -end - -function CardArea:update(dt) - if self == G.hand then - if G.GAME.modifiers.minus_hand_size_per_X_dollar then - self.config.last_poll_size = self.config.last_poll_size or 0 - if math.floor(G.GAME.dollars/G.GAME.modifiers.minus_hand_size_per_X_dollar) ~= self.config.last_poll_size then - self:change_size(self.config.last_poll_size - math.floor(G.GAME.dollars/G.GAME.modifiers.minus_hand_size_per_X_dollar)) - self.config.last_poll_size = math.floor(G.GAME.dollars/G.GAME.modifiers.minus_hand_size_per_X_dollar) - end - end - for k, v in pairs(self.cards) do - if v.ability.forced_selection and not self.highlighted[1] then - self:add_to_highlighted(v) - end - end - end - if self == G.deck then - self.states.collide.can = true - self.states.hover.can = true - self.states.click.can = true - end - --Check and see if controller is being used - if G.CONTROLLER.HID.controller and self ~= G.hand then self:unhighlight_all() end - if self == G.deck and self.config.card_limit > #G.playing_cards then self.config.card_limit = #G.playing_cards end - self.config.temp_limit = math.max(#self.cards, self.config.card_limit) - self.config.card_count = #self.cards -end - -function CardArea:draw() - if not self.states.visible then return end - if G.VIEWING_DECK and (self==G.deck or self==G.hand or self==G.play) then return end - - local state = G.TAROT_INTERRUPT or G.STATE - - self.ARGS.invisible_area_types = self.ARGS.invisible_area_types or {discard=1, voucher=1, play=1, consumeable=1, title = 1, title_2 = 1} - if self.ARGS.invisible_area_types[self.config.type] or - (self.config.type == 'hand' and ({[G.STATES.SHOP]=1, [G.STATES.TAROT_PACK]=1, [G.STATES.SPECTRAL_PACK]=1, [G.STATES.STANDARD_PACK]=1,[G.STATES.BUFFOON_PACK]=1,[G.STATES.PLANET_PACK]=1, [G.STATES.ROUND_EVAL]=1, [G.STATES.BLIND_SELECT]=1})[state]) or - (self.config.type == 'hand' and state == G.STATES.SMODS_BOOSTER_OPENED) or - (self.config.type == 'deck' and self ~= G.deck) or - (self.config.type == 'shop' and self ~= G.shop_vouchers) then - else - if not self.children.area_uibox then - local card_count = self ~= G.shop_vouchers and {n=G.UIT.R, config={align = self == G.jokers and 'cl' or self == G.hand and 'cm' or 'cr', padding = 0.03, no_fill = true}, nodes={ - {n=G.UIT.B, config={w = 0.1,h=0.1}}, - {n=G.UIT.T, config={ref_table = self.config, ref_value = 'card_count', scale = 0.3, colour = G.C.WHITE}}, - {n=G.UIT.T, config={text = '/', scale = 0.3, colour = G.C.WHITE}}, - {n=G.UIT.T, config={ref_table = self.config, ref_value = 'card_limit', scale = 0.3, colour = G.C.WHITE}}, - {n=G.UIT.B, config={w = 0.1,h=0.1}} - }} or nil - - self.children.area_uibox = UIBox{ - definition = - {n=G.UIT.ROOT, config = {align = 'cm', colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={minw = self.T.w,minh = self.T.h,align = "cm", padding = 0.1, mid = true, r = 0.1, colour = self ~= G.shop_vouchers and {0,0,0,0.1} or nil, ref_table = self}, nodes={ - self == G.shop_vouchers and - {n=G.UIT.C, config={align = "cm", paddin = 0.1, func = 'shop_voucher_empty', visible = false}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = G.GAME.modifiers.cry_no_vouchers and (very_fair_quip[1] or '') or 'DEFEAT', scale = 0.6, colour = G.C.WHITE}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = G.GAME.modifiers.cry_no_vouchers and (very_fair_quip[2] or '') or G.GAME.modifiers.cry_voucher_restock_antes and G.GAME.round_resets.ante % G.GAME.modifiers.cry_voucher_restock_antes == 0 and 'TWO BOSS BLINDS' or 'BOSS BLIND', scale = 0.4, colour = G.C.WHITE}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = G.GAME.modifiers.cry_no_vouchers and (very_fair_quip[3] or '') or 'TO RESTOCK', scale = 0.4, colour = G.C.WHITE}} - }}, - }} or nil, - }}, - card_count - }}, - config = { align = 'cm', offset = {x=0,y=0}, major = self, parent = self} - } - end - self.children.area_uibox:draw() - if self == G.jokers then - Cartomancer.add_visibility_controls() - end - end - - self:draw_boundingrect() - add_to_drawhash(self) - - self.ARGS.draw_layers = self.ARGS.draw_layers or self.config.draw_layers or {'shadow', 'card'} - for k, v in ipairs(self.ARGS.draw_layers) do - if self.config.type == 'deck' then - for i = #self.cards, 1, -1 do - if self.cards[i] ~= G.CONTROLLER.focused.target then - if i == 1 or i%(self.config.thin_draw or 9) == 0 or i == #self.cards or math.abs(self.cards[i].VT.x - self.T.x) > 1 or math.abs(self.cards[i].VT.y - self.T.y) > 1 then - if G.CONTROLLER.dragging.target ~= self.cards[i] then self.cards[i]:draw(v) end - end - end - end - end - - if self.config.type == 'joker' or self.config.type == 'consumeable' or self.config.type == 'shop' or self.config.type == 'title_2' then - for i = 1, #self.cards do - if self.cards[i] ~= G.CONTROLLER.focused.target then - if not self.cards[i].highlighted then - if G.CONTROLLER.dragging.target ~= self.cards[i] then self.cards[i]:draw(v) end - end - end - end - for i = 1, #self.cards do - if self.cards[i] ~= G.CONTROLLER.focused.target then - if self.cards[i].highlighted then - if G.CONTROLLER.dragging.target ~= self.cards[i] then self.cards[i]:draw(v) end - end - end - end - end - - if self.config.type == 'discard' then - for i = 1, #self.cards do - if self.cards[i] ~= G.CONTROLLER.focused.target then - if math.abs(self.cards[i].VT.x - self.T.x) > 1 then - if G.CONTROLLER.dragging.target ~= self.cards[i] then self.cards[i]:draw(v) end - end - end - end - end - - if self.config.type == 'hand' or self.config.type == 'play' or self.config.type == 'title' or self.config.type == 'voucher' then - for i = 1, #self.cards do - if self.cards[i] ~= G.CONTROLLER.focused.target or self == G.hand then - if G.CONTROLLER.dragging.target ~= self.cards[i] then self.cards[i]:draw(v) end - end - end - end - end - - if self == G.deck then - if G.CONTROLLER.HID.controller and G.STATE == G.STATES.SELECTING_HAND and not self.children.peek_deck then - self.children.peek_deck = UIBox{ - definition = - {n=G.UIT.ROOT, config = {align = 'cm', padding = 0.1, r =0.1, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", r =0.1, colour = adjust_alpha(G.C.L_BLACK, 0.5),func = 'set_button_pip', focus_args = {button = 'triggerleft', orientation = 'bm', scale = 0.6, type = 'none'}}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = 'PEEK', scale = 0.48, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = 'DECK', scale = 0.38, colour = G.C.WHITE, shadow = true}} - }}, - }}, - }}, - config = { align = 'cl', offset = {x=-0.5,y=0.1}, major = self, parent = self} - } - self.children.peek_deck.states.collide.can = false - elseif (not G.CONTROLLER.HID.controller or G.STATE ~= G.STATES.SELECTING_HAND) and self.children.peek_deck then - self.children.peek_deck:remove() - self.children.peek_deck = nil - end - if not self.children.view_deck then - self.children.view_deck = UIBox{ - definition = - {n=G.UIT.ROOT, config = {align = 'cm', padding = 0.1, r =0.1, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05, r =0.1, colour = adjust_alpha(G.C.BLACK, 0.5),func = 'set_button_pip', focus_args = {button = 'triggerright', orientation = 'bm', scale = 0.6}, button = 'deck_info'}, nodes={ - {n=G.UIT.R, config={align = "cm", maxw = 2}, nodes={ - {n=G.UIT.T, config={text = localize('k_view'), scale = 0.48, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", maxw = 2}, nodes={ - {n=G.UIT.T, config={text = localize('k_deck'), scale = 0.38, colour = G.C.WHITE, shadow = true}} - }}, - }}, - }}, - config = { align = 'cm', offset = {x=0,y=0}, major = self.cards[1] or self, parent = self} - } - self.children.view_deck.states.collide.can = false - end - if G.deck_preview or self.states.collide.is or (G.buttons and G.buttons.states.collide.is and G.CONTROLLER.HID.controller) then self.children.view_deck:draw() end - if self.children.peek_deck then self.children.peek_deck:draw() end - end -end - -function CardArea:align_cards() - if self.config.type == 'hand' then - self.config.temp_limit = math.min(self.config.card_limit, #G.playing_cards) - end - if (self == G.hand or self == G.deck or self == G.discard or self == G.play) and G.view_deck and G.view_deck[1] and G.view_deck[1].cards then return end - if self.config.type == 'deck' then - local display_limit - if not Cartomancer.SETTINGS.compact_deck_enabled then - display_limit = 999999 - else - display_limit = Cartomancer.SETTINGS.compact_deck_visible_cards - end - - local deck_height = (self.config.deck_height or 0.15)/52 - local total_cards = #self.cards <= display_limit and #self.cards or display_limit -- limit height - local fixedX, fixedY, fixedR = nil, nil, nil - - for k, card in ipairs(self.cards) do - if card.facing == 'front' then card:flip() end - - if not card.states.drag.is then - if fixedX then - card.T.x = fixedX - card.T.y = fixedY - card.T.r = fixedR -- rotation - card.states.visible = false - else - card.T.x = self.T.x + 0.5*(self.T.w - card.T.w) + self.shadow_parrallax.x*deck_height*(total_cards/(self == G.deck and 1 or 2) - k) + 0.9*self.shuffle_amt*(1 - k*0.01)*(k%2 == 1 and 1 or -0) - card.T.y = self.T.y + 0.5*(self.T.h - card.T.h) + self.shadow_parrallax.y*deck_height*(total_cards/(self == G.deck and 1 or 2) - k) - card.T.r = 0 + 0.3*self.shuffle_amt*(1 + k*0.05)*(k%2 == 1 and 1 or -0) - card.T.x = card.T.x + card.shadow_parrallax.x/30 - card.states.visible = true - - if k >= display_limit then - fixedX = card.T.x - fixedY = card.T.y - fixedR = card.T.r - end - end - end - end - end - if self.config.type == 'discard' then - for k, card in ipairs(self.cards) do - if card.facing == 'front' then card:flip() end - - if not card.states.drag.is then - card.T.x = self.T.x + (self.T.w - card.T.w)*card.discard_pos.x - card.T.y = self.T.y + (self.T.h - card.T.h)* card.discard_pos.y - card.T.r = card.discard_pos.r - end - end - end - if self.config.type == 'hand' and (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) then - for k, card in ipairs(self.cards) do - if not card.states.drag.is then - card.T.r = 0.4*(-#self.cards/2 - 0.5 + k)/(#self.cards)+ (G.SETTINGS.reduced_motion and 0 or 1)*0.02*math.sin(2*G.TIMERS.REAL+card.T.x) - local max_cards = math.max(#self.cards, self.config.temp_limit) - card.T.x = self.T.x + (self.T.w-self.card_w)*((k-1)/math.max(max_cards-1, 1) - 0.5*(#self.cards-max_cards)/math.max(max_cards-1, 1)) + 0.5*(self.card_w - card.T.w) - local highlight_height = G.HIGHLIGHT_H - if not card.highlighted then highlight_height = 0 end - card.T.y = G.hand.T.y - 1.8*card.T.h - highlight_height + (G.SETTINGS.reduced_motion and 0 or 1)*0.1*math.sin(0.666*G.TIMERS.REAL+card.T.x) + math.abs(1.3*(-#self.cards/2 + k-0.5)/(#self.cards))^2-0.3 - card.T.x = card.T.x + card.shadow_parrallax.x/30 - end - end - table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end) - end - if self.config.type == 'hand' and not (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) then - - for k, card in ipairs(self.cards) do - if not card.states.drag.is then - card.T.r = 0.2*(-#self.cards/2 - 0.5 + k)/(#self.cards)+ (G.SETTINGS.reduced_motion and 0 or 1)*0.02*math.sin(2*G.TIMERS.REAL+card.T.x) - local max_cards = math.max(#self.cards, self.config.temp_limit) - card.T.x = self.T.x + (self.T.w-self.card_w)*((k-1)/math.max(max_cards-1, 1) - 0.5*(#self.cards-max_cards)/math.max(max_cards-1, 1)) + 0.5*(self.card_w - card.T.w) - - local highlight_height = G.HIGHLIGHT_H - if not card.highlighted then highlight_height = 0 end - card.T.y = self.T.y + self.T.h/2 - card.T.h/2 - highlight_height + (G.SETTINGS.reduced_motion and 0 or 1)*0.03*math.sin(0.666*G.TIMERS.REAL+card.T.x) + math.abs(0.5*(-#self.cards/2 + k-0.5)/(#self.cards))-0.2 - card.T.x = card.T.x + card.shadow_parrallax.x/30 - end - end - table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end) - end - if self.config.type == 'title' or (self.config.type == 'voucher' and #self.cards == 1) then - for k, card in ipairs(self.cards) do - if not card.states.drag.is then - card.T.r = 0.2*(-#self.cards/2 - 0.5 + k)/(#self.cards)+ (G.SETTINGS.reduced_motion and 0 or 1)*0.02*math.sin(2*G.TIMERS.REAL+card.T.x) - local max_cards = math.max(#self.cards, self.config.temp_limit) - card.T.x = self.T.x + (self.T.w-self.card_w)*((k-1)/math.max(max_cards-1, 1) - 0.5*(#self.cards-max_cards)/math.max(max_cards-1, 1)) + 0.5*(self.card_w - card.T.w) - local highlight_height = G.HIGHLIGHT_H - if not card.highlighted then highlight_height = 0 end - card.T.y = self.T.y + self.T.h/2 - card.T.h/2 - highlight_height + (G.SETTINGS.reduced_motion and 0 or 1)*0.03*math.sin(0.666*G.TIMERS.REAL+card.T.x) + math.abs(0.5*(-#self.cards/2 + k-0.5)/(#self.cards))-(#self.cards>1 and 0.2 or 0) - card.T.x = card.T.x + card.shadow_parrallax.x/30 - end - end - table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end) - end - if self.config.type == 'voucher' and #self.cards > 1 then - local self_w = math.max(self.T.w, 3.2) - for k, card in ipairs(self.cards) do - if not card.states.drag.is then - card.T.r = 0.2*(-#self.cards/2 - 0.5 + k)/(#self.cards)+ (G.SETTINGS.reduced_motion and 0 or 1)*0.02*math.sin(2*G.TIMERS.REAL+card.T.x+card.T.y) + (k%2 == 0 and 1 or -1)*0.08 - local max_cards = math.max(#self.cards, self.config.temp_limit) - card.T.x = self.T.x + (self_w-self.card_w)*((k-1)/math.max(max_cards-1, 1) - 0.5*(#self.cards-max_cards)/math.max(max_cards-1, 1)) + 0.5*(self.card_w - card.T.w) + (k%2 == 1 and 1 or -1)*0.27 + (self.T.w-self_w)/2 - local highlight_height = G.HIGHLIGHT_H - if not card.highlighted then highlight_height = 0 end - card.T.y = self.T.y + self.T.h/2 - card.T.h/2 - highlight_height + (G.SETTINGS.reduced_motion and 0 or 1)*0.03*math.sin(0.666*G.TIMERS.REAL+card.T.x) + math.abs(0.5*(-#self.cards/2 + k-0.5)/(#self.cards))-(#self.cards>1 and 0.2 or 0) - card.T.x = card.T.x + card.shadow_parrallax.x/30 - end - end - table.sort(self.cards, function (a, b) return a.ability.order < b.ability.order end) - end - if self.config.type == 'play' or self.config.type == 'shop' then - for k, card in ipairs(self.cards) do - if not card.states.drag.is then - card.T.r = 0 - local max_cards = math.max(#self.cards, self.config.temp_limit) - card.T.x = self.T.x + (self.T.w-self.card_w)*((k-1)/math.max(max_cards-1, 1) - 0.5*(#self.cards-max_cards)/math.max(max_cards-1, 1)) + 0.5*(self.card_w - card.T.w) + (self.config.card_limit == 1 and 0.5*(self.T.w - card.T.w) or 0) - local highlight_height = G.HIGHLIGHT_H - if not card.highlighted then highlight_height = 0 end - card.T.y = self.T.y + self.T.h/2 - card.T.h/2 - highlight_height - card.T.x = card.T.x + card.shadow_parrallax.x/30 - end - end - table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end) - end - if self == G.jokers and G.jokers.cart_jokers_expanded then - local align_cards = Cartomancer.expand_G_jokers() - - -- This should work fine without cryptid. But because cryptid's patch is priority=0, it has to be this way - if not G.GAME.modifiers.cry_conveyor then - table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end) - end - - if align_cards then - G.jokers:hard_set_cards() - end - elseif self.config.type == 'joker' or self.config.type == 'title_2' then - for k, card in ipairs(self.cards) do - if not card.states.drag.is then - card.T.r = 0.1*(-#self.cards/2 - 0.5 + k)/(#self.cards)+ (G.SETTINGS.reduced_motion and 0 or 1)*0.02*math.sin(2*G.TIMERS.REAL+card.T.x) - local max_cards = math.max(#self.cards, self.config.temp_limit) - card.T.x = self.T.x + (self.T.w-self.card_w)*((k-1)/math.max(max_cards-1, 1) - 0.5*(#self.cards-max_cards)/math.max(max_cards-1, 1)) + 0.5*(self.card_w - card.T.w) - if #self.cards > 2 or (#self.cards > 1 and self == G.consumeables) or (#self.cards > 1 and self.config.spread) then - card.T.x = self.T.x + (self.T.w-self.card_w)*((k-1)/(#self.cards-1)) + 0.5*(self.card_w - card.T.w) - elseif #self.cards > 1 and self ~= G.consumeables then - card.T.x = self.T.x + (self.T.w-self.card_w)*((k - 0.5)/(#self.cards)) + 0.5*(self.card_w - card.T.w) - else - card.T.x = self.T.x + self.T.w/2 - self.card_w/2 + 0.5*(self.card_w - card.T.w) - end - local highlight_height = G.HIGHLIGHT_H/2 - if not card.highlighted then highlight_height = 0 end - card.T.y = self.T.y + self.T.h/2 - card.T.h/2 - highlight_height+ (G.SETTINGS.reduced_motion and 0 or 1)*0.03*math.sin(0.666*G.TIMERS.REAL+card.T.x) - card.T.x = card.T.x + card.shadow_parrallax.x/30 - end - end - table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*((a.pinned and not a.ignore_pinned) and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*((b.pinned and not b.ignore_pinned) and b.sort_id or 0) end) - end - if self.config.type == 'consumeable'then - for k, card in ipairs(self.cards) do - if not card.states.drag.is then - if #self.cards > 1 then - card.T.x = self.T.x + (self.T.w-self.card_w)*((k-1)/(#self.cards-1)) + 0.5*(self.card_w - card.T.w) - else - card.T.x = self.T.x + self.T.w/2 - self.card_w/2 + 0.5*(self.card_w - card.T.w) - end - local highlight_height = G.HIGHLIGHT_H - if not card.highlighted then highlight_height = 0 end - card.T.y = self.T.y + self.T.h/2 - card.T.h/2 - highlight_height + (not card.highlighted and (G.SETTINGS.reduced_motion and 0 or 1)*0.05*math.sin(2*1.666*G.TIMERS.REAL+card.T.x) or 0) - card.T.x = card.T.x + card.shadow_parrallax.x/30 - end - end - table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end) - end - for k, card in ipairs(self.cards) do - card.rank = k - end - if self.children.view_deck then - self.children.view_deck:set_role{major = self.cards[1] or self} - end -end - -function CardArea:hard_set_T(X, Y, W, H) - local x = (X or self.T.x) - local y = (Y or self.T.y) - local w = (W or self.T.w) - local h = (H or self.T.h) - Moveable.hard_set_T(self,x, y, w, h) - self:calculate_parrallax() - self:align_cards() - self:hard_set_cards() -end - -function CardArea:hard_set_cards() - for k, card in pairs(self.cards) do - card:hard_set_T() - card:calculate_parrallax() - end -end - -function CardArea:shuffle(_seed) - pseudoshuffle(self.cards, pseudoseed(_seed or 'shuffle')) - self:set_ranks() -end - -function CardArea:sort(method) - self.config.sort = method or self.config.sort - if self.config.sort == 'desc' then - table.sort(self.cards, function (a, b) return a:get_nominal() > b:get_nominal() end ) - elseif self.config.sort == 'asc' then - table.sort(self.cards, function (a, b) return a:get_nominal() < b:get_nominal() end ) - elseif self.config.sort == 'suit desc' then - table.sort(self.cards, function (a, b) return a:get_nominal('suit') > b:get_nominal('suit') end ) - elseif self.config.sort == 'suit asc' then - table.sort(self.cards, function (a, b) return a:get_nominal('suit') < b:get_nominal('suit') end ) - elseif self.config.sort == 'order' then - table.sort(self.cards, function (a, b) return (a.config.card.order or a.config.center.order) < (b.config.card.order or b.config.center.order) end ) - end -end - -function CardArea:draw_card_from(area, stay_flipped, discarded_only) - if area:is(CardArea) then - if #self.cards < self.config.card_limit or self == G.deck or self == G.hand then - local card = area:remove_card(nil, discarded_only) - if card then - if area == G.discard then - card.T.r = 0 - end - if self == G.hand and not card.states.visible then - card.states.visible = true - end - local stay_flipped = G.GAME and G.GAME.blind and G.GAME.blind:stay_flipped(self, card) - if (self == G.hand) and G.GAME.modifiers.flipped_cards then - if pseudorandom(pseudoseed('flipped_card')) < 1/G.GAME.modifiers.flipped_cards then - stay_flipped = true - end - end - self:emplace(card, nil, stay_flipped) - return true - end - end - end -end - -function CardArea:click() - if self == G.deck then - G.FUNCS.deck_info() - end -end - -function CardArea:save() - if not self.cards then return end - local cardAreaTable = { - cards = {}, - config = self.config, - } - for i = 1, #self.cards do - cardAreaTable.cards[#cardAreaTable.cards + 1] = self.cards[i]:save() - end - - return cardAreaTable -end - -function CardArea:load(cardAreaTable) - - if self.cards then remove_all(self.cards) end - self.cards = {} - if self.children then remove_all(self.children) end - self.children = {} - - self.config = cardAreaTable.config - - for i = 1, #cardAreaTable.cards do - loading = true - local card = Card(0, 0, G.CARD_W, G.CARD_H, G.P_CENTERS.j_joker, G.P_CENTERS.c_base) - loading = nil - card:load(cardAreaTable.cards[i]) - self.cards[#self.cards + 1] = card - if card.highlighted then - self.highlighted[#self.highlighted + 1] = card - end - card:set_card_area(self) - end - self:set_ranks() - self:align_cards() - self:hard_set_cards() -end - -function CardArea:remove() - if self.cards then remove_all(self.cards) end - self.cards = nil - if self.children then remove_all(self.children) end - self.children = nil - for k, v in pairs(G.I.CARDAREA) do - if v == self then - table.remove(G.I.CARDAREA, k) - end - end - Moveable.remove(self) -end diff --git a/lovely/dump/engine/animatedsprite.lua b/lovely/dump/engine/animatedsprite.lua deleted file mode 100644 index f39766a..0000000 --- a/lovely/dump/engine/animatedsprite.lua +++ /dev/null @@ -1,109 +0,0 @@ -LOVELY_INTEGRITY = '8f16206d263b8b20d4f441ae0cdc8450eef3f2bd3b801abb44802f6b1578b809' - ---Class -AnimatedSprite = Sprite:extend() - ---Class Methods -function AnimatedSprite:init(X, Y, W, H, new_sprite_atlas, sprite_pos) - Sprite.init(self,X, Y, W, H, new_sprite_atlas, sprite_pos) - self.offset = {x = 0, y = 0} - - table.insert(G.ANIMATIONS, self) - if getmetatable(self) == AnimatedSprite then - table.insert(G.I.SPRITE, self) - end -end - -function AnimatedSprite:rescale() - self.scale_mag = math.min(self.scale.x/self.T.w,self.scale.y/self.T.h) -end - -function AnimatedSprite:reset() - self.atlas = G.ANIMATION_ATLAS[self.atlas.name] - self:set_sprite_pos({x = self.animation.x, y = self.animation.y}) -end - -function AnimatedSprite:set_sprite_pos(sprite_pos) - self.animation = { - x= sprite_pos and sprite_pos.x or 0, - y=sprite_pos and sprite_pos.y or 0, - frames=self.atlas.frames,current=0, - w=self.scale.x, h=self.scale.y} - - self.frame_offset = 0 - - self.current_animation = { - current = 0, - frames = self.animation.frames, - w = self.animation.w, - h = self.animation.h} - - self.image_dims = self.image_dims or {} - self.image_dims[1], self.image_dims[2] = self.atlas.image:getDimensions() - - self.sprite = love.graphics.newQuad( - 0, - self.animation.h*self.animation.y, - self.animation.w, - self.animation.h, - self.image_dims[1], self.image_dims[2]) - self.offset_seconds = G.TIMERS.REAL -end - -function AnimatedSprite:get_pos_pixel() - self.RETS.get_pos_pixel = self.RETS.get_pos_pixel or {} - self.RETS.get_pos_pixel[1] = self.current_animation.current - self.RETS.get_pos_pixel[2] = self.animation.y - self.RETS.get_pos_pixel[3] = self.animation.w - self.RETS.get_pos_pixel[4] = self.animation.h - return self.RETS.get_pos_pixel -end - -function AnimatedSprite:draw_self() - if not self.states.visible then return end - - prep_draw(self, 1) - love.graphics.scale(1/self.scale_mag) - love.graphics.setColor(G.C.WHITE) - love.graphics.draw( - self.atlas.image, - self.sprite, - 0 ,0, - 0, - self.VT.w/(self.T.w), - self.VT.h/(self.T.h) - ) - love.graphics.pop() -end - -function AnimatedSprite:animate() - local new_frame = math.floor(G.ANIMATION_FPS*(G.TIMERS.REAL - self.offset_seconds))%self.current_animation.frames - if new_frame ~= self.current_animation.current then - self.current_animation.current = new_frame - self.frame_offset = math.floor(self.animation.w*(self.current_animation.current)) - self.sprite:setViewport( - self.frame_offset, - self.animation.h*self.animation.y, - self.animation.w, - self.animation.h) - end - if self.float then - self.T.r = 0.02*math.sin(2*G.TIMERS.REAL+self.T.x) - self.offset.y = -(1+0.3*math.sin(0.666*G.TIMERS.REAL+self.T.y))*self.shadow_parrallax.y - self.offset.x = -(0.7+0.2*math.sin(0.666*G.TIMERS.REAL+self.T.x))*self.shadow_parrallax.x - end -end - -function AnimatedSprite:remove() - for k, v in pairs(G.ANIMATIONS) do - if v == self then - table.remove(G.ANIMATIONS, k) - end - end - for k, v in pairs(G.I.SPRITE) do - if v == self then - table.remove(G.I.SPRITE, k) - end - end - Sprite.remove(self) -end diff --git a/lovely/dump/engine/controller.lua b/lovely/dump/engine/controller.lua deleted file mode 100644 index 3af61ba..0000000 --- a/lovely/dump/engine/controller.lua +++ /dev/null @@ -1,1452 +0,0 @@ -LOVELY_INTEGRITY = 'd36e3953c2739cd4ea15794fb5e4031a2dac09fc33baadd0a2820e4726891304' - ----@class Controller -Controller = Object:extend() - ---The controller contains all engine logic for how human input interacts with any game objects. -function Controller:init() - ---Each of these are calculated per frame to pass along to the corresponding nodes for input handling -self.clicked = {target = nil, handled = true, prev_target = nil} --The node that was clicked this frame -self.focused = {target = nil, handled = true, prev_target = nil } --The node that is being focused on this frame, only applies when using controller -self.dragging = {target = nil, handled = true, prev_target = nil} --The node being dragged this frame -self.hovering = {target = nil, handled = true, prev_target = nil} --The node being hovered this frame -self.released_on = {target = nil, handled = true, prev_target = nil} --The node that the cursor 'Released' on, like letting go of LMB - -self.collision_list = {} --A list of all node that the cursor currently collides with - ---Input values to be determined by this controller - the actual game objects should not have to see any of this -self.cursor_down = {T = {x=0, y=0}, target = nil, time = 0, handled = true} -self.cursor_up = {T = {x=0, y=0}, target = nil, time = 0.1, handled = true} -self.cursor_hover = {T = {x=0, y=0}, target = nil, time = 0, handled = true} -self.cursor_collider = nil --The node that collides with the cursor this frame -self.cursor_position = {x=0,y=0} --NOT IN GAME UNITS - ---For key presses, hold times, and if they are released directly from LOVE -self.pressed_keys = {} -self.held_keys = {} -self.held_key_times = {} -self.released_keys = {} - ---For button presses, hold times, and if they are released directly from LOVE -self.pressed_buttons = {} -self.held_buttons = {} -self.held_button_times = {} -self.released_buttons = {} - ---For all controller interrupts -self.interrupt = { - focus = false, -} - ---For all controller locks -self.locks = {} -self.locked = nil - ---Buttons pressed and released during axis updates -self.axis_buttons = { - l_stick = {current = '', previous = ''}, - r_stick = {current = '', previous = ''}, - l_trig = {current = '', previous = ''}, - r_trig = {current = '', previous = ''} -} - ---The speed that the controller thumbstick moves the cursor -self.axis_cursor_speed = 20 - ---A registry of buttons, each a valid button input name corresponding to a node (likely a button). This is modified with the registry functions -self.button_registry = {} - ---A node representing where the cursor should 'snap' to. When this is set, then next frame should have the cursor to that position or on that node. Use :snap_to -self.snap_cursor_to = nil - ---A stack of cursor positions, this stack changes depending on the depth of menus on screen so the game can remember where you last had your cursor ---This needs to keep track of both positions and nodes if possible, as well as the depth -self.cursor_context = { - layer = 1, - stack = {} -} - -self.cardarea_context = {} - ---Human Interface device flags, these are set per frame to ensure that correct controller updates are taking place -self.HID = { - last_type = '', - dpad = false, - pointer = true, - touch = false, - controller = false, - mouse = true, - axis_cursor = false, -} - ---The gamepad most recently used, if any -self.GAMEPAD = {object = nil, mapping = nil, name = nil} -self.GAMEPAD_CONSOLE = '' --Valid button icons for Xbox, Playstation and Nintendo controllers - ---If we need an emulated gamepad for keyboard controls -self.keyboard_controller = { - getGamepadMappingString = function() return 'balatro_kbm' end, - getGamepadAxis = function() return 0 end -} - -self.is_cursor_down = false -end - ---Sets the gamepad to be the updated gamepad, searches for the console type and sets the art button pips accordingly ---Some code here is from github.com/idbrii/love-gamepadguesser (MIT License) -function Controller:set_gamepad(_gamepad) - if self.GAMEPAD.object ~= _gamepad then - self.GAMEPAD.object = _gamepad - self.GAMEPAD.mapping = _gamepad:getGamepadMappingString() or '' - self.GAMEPAD.name = self.GAMEPAD.mapping:match("^%x*,(.-),") or '' - self.GAMEPAD.temp_console = self:get_console_from_gamepad(self.GAMEPAD.name) - if self.GAMEPAD_CONSOLE ~= self.GAMEPAD.temp_console then - self.GAMEPAD_CONSOLE = self.GAMEPAD.temp_console - for k, v in pairs(G.I.SPRITE) do - if v.atlas == G.ASSET_ATLAS["gamepad_ui"] then - v.sprite_pos.y = G.CONTROLLER.GAMEPAD_CONSOLE == 'Nintendo' and 2 or G.CONTROLLER.GAMEPAD_CONSOLE == 'Playstation' and (G.F_PS4_PLAYSTATION_GLYPHS and 3 or 1) or 0 - v:set_sprite_pos(v.sprite_pos) - end - end - end - self.GAMEPAD.temp_console = nil - end -end - ---Some code here is from github.com/idbrii/love-gamepadguesser (MIT License) -function Controller:get_console_from_gamepad(_gamepad) - G.ARGS.gamepad_patterns = G.ARGS.gamepad_patterns or - { - Playstation = {"%f[%w]PS%d%f[%D]", "Sony%f[%W]", "Play[Ss]tation"}, - Nintendo = {"Wii%f[%L]", "%f[%u]S?NES%f[%U]", "%f[%l]s?nes%f[%L]", "%f[%u]Switch%f[%L]", "Joy[- ]Cons?%f[%L]",}, - --Keyboard = {'balatro_kbm'} - } - - for k, v in pairs(G.ARGS.gamepad_patterns) do - for kk, vv in ipairs(v) do - if _gamepad:match(vv) then - return k - end - end - end - return 'Xbox' -end - ---The universal controller for what type of HID Device the player is using to interact with the game. The Game should be able to handle switching ---to any viable HID at any time -function Controller:set_HID_flags(HID_type, button) - --we need to determine it the axis input will be handled like a button or pointer - --if button and self.HID.controller and not string.find(button, 'dp') then return end - if HID_type == 'axis' then - self.HID.controller = true - self.HID.last_type = 'axis' - elseif HID_type and HID_type ~= self.HID.last_type then - self.HID.dpad = HID_type == 'button' - self.HID.pointer = HID_type == 'mouse' or HID_type == 'axis_cursor' or HID_type == 'touch' - self.HID.controller = HID_type == 'button' or HID_type == 'axis_cursor' - self.HID.mouse = HID_type == 'mouse' - self.HID.touch = HID_type == 'touch' - self.HID.axis_cursor = HID_type == 'axis_cursor' - self.HID.last_type = HID_type - - if self.HID.mouse then - love.mouse.setVisible(true) - else - love.mouse.setVisible(false) - end - end - if not self.HID.controller then - self.GAMEPAD_CONSOLE = '' - self.GAMEPAD.object = nil - self.GAMEPAD.mapping = nil - self.GAMEPAD.name = nil - end -end - ---Sets the current position of the cursor -function Controller:set_cursor_position() - --If using a mouse for the cursor - if self.HID.mouse or self.HID.touch then - self.interrupt.focus = false - --Never focus if using the mouse - if self.focused.target then - self.focused.target.states.focus.is = false - self.focused.target= nil - end - - --Set the position of the cursor to the love position of the mouse, derive cursor transform from that - self.cursor_position.x, self.cursor_position.y = love.mouse.getPosition() - G.CURSOR.T.x = self.cursor_position.x/(G.TILESCALE*G.TILESIZE) - G.CURSOR.T.y = self.cursor_position.y/(G.TILESCALE*G.TILESIZE) - G.CURSOR.VT.x = G.CURSOR.T.x - G.CURSOR.VT.y = G.CURSOR.T.y - end -end - ---Called every game logic update frame -function Controller:update(dt) - - --parse all locks and set - self.locked = false - if G.screenwipe then self.locks.wipe = true else self.locks.wipe = false end - - for k, v in pairs(self.locks) do - if v then self.locked = true end - end - - if self.locks.frame_set then - self.locks.frame_set = nil - self.overlay_timer = 0 - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.1, - timer = 'UPTIME', - blocking = false, - blockable = false, - no_delete = true, - func = (function() - self.locks.frame = nil - return true - end) - })) - end - - self.overlay_timer = self.overlay_timer or 0 - if G.OVERLAY_MENU then - self.overlay_timer = self.overlay_timer + dt - else - self.overlay_timer = 0 - end - - if self.overlay_timer > 1.5 then self.locks.frame = nil end - - --Remove anything from the registry that is no longer in game - self:cull_registry() - - --Calculate the axis update and set the HID flags if there is any axis input - self:set_HID_flags(self:update_axis(dt)) - - --Set the cursor to be visible only if we are using a mouse or an axis to control the cursor position - if self.HID.pointer and not (self.HID.mouse or self.HID.touch) and not self.interrupt.focus then - G.CURSOR.states.visible = true - else - G.CURSOR.states.visible = false - end - - --For mouse input, reset any controller things and set the cursor to be where the mouse is - self:set_cursor_position() - - --Handle all the button updates and key updates, call the required functions - if not G.screenwipe then - --Key press and release handling - for k, v in pairs(self.pressed_keys) do - if v then self:key_press_update(k, dt) end - end - for k, v in pairs(self.held_keys) do - if v then self:key_hold_update(k, dt) end - end - for k, v in pairs(self.released_keys) do - if v then self:key_release_update(k, dt) end - end - - --Button press and release handling - for k, v in pairs(self.pressed_buttons) do - if v then self:button_press_update(k, dt) end - end - for k, v in pairs(self.held_buttons) do - if v then self:button_hold_update(k, dt) end - end - for k, v in pairs(self.released_buttons) do - if v then self:button_release_update(k, dt) end - end - end - - self.frame_buttonpress = false - - --reset press and release lists - self.pressed_keys = EMPTY(self.pressed_keys) - self.released_keys = EMPTY(self.released_keys) - self.pressed_buttons= EMPTY(self.pressed_buttons) - self.released_buttons = EMPTY(self.released_buttons) - - - --If using controller, update context and snap tos - if self.HID.controller then - --If there is a node/position to snap to from the cursor context layer - if self.cursor_context.stack[self.cursor_context.layer] then - local _context = self.cursor_context.stack[self.cursor_context.layer] - self:snap_to{node = (_context.node and not _context.node.REMOVED and _context.node), T = _context.cursor_pos} - self.interrupt.stack = _context.interrupt - self.cursor_context.stack[self.cursor_context.layer] = nil - end - --If there is a card the was being dragged but no longer is, snap to it - if self.dragging.prev_target and not self.dragging.target and getmetatable(self.dragging.prev_target) == Card and not self.dragging.prev_target.REMOVED then - --Overly complicated coyote time focus, so the user can quickly select cards without things going wonky - if not self.COYOTE_FOCUS then - self:snap_to{node = self.dragging.prev_target} - else - self.COYOTE_FOCUS = nil - end - end - --If the cursor should snap to a location - if self.snap_cursor_to then - self.interrupt.focus = self.interrupt.stack - self.interrupt.stack = false - if self.snap_cursor_to.type == 'node' and not self.snap_cursor_to.node.REMOVED then - self.focused.prev_target = self.focused.target - self.focused.target = self.snap_cursor_to.node - self:update_cursor() - elseif self.snap_cursor_to.type == 'transform' then - self:update_cursor(self.snap_cursor_to.T) - end - if self.focused.prev_target ~= self.focused.target and self.focused.prev_target then self.focused.prev_target.states.focus.is = false end - self.snap_cursor_to = nil - end - end - - --Reset all collision states, get every node that collides with the cursor, then update the focus and hover targets - self:get_cursor_collision(G.CURSOR.T) - self:update_focus() - self:set_cursor_hover() - if self.L_cursor_queue then - self:L_cursor_press(self.L_cursor_queue.x, self.L_cursor_queue.y) - self.L_cursor_queue = nil - end - - self.dragging.prev_target = self.dragging.target - self.released_on.prev_target = self.released_on.target - self.clicked.prev_target = self.clicked.target - self.hovering.prev_target = self.hovering.target - - --Cursor is currently down - if not self.cursor_down.handled then - if self.cursor_down.target.states.drag.can then - self.cursor_down.target.states.drag.is = true - self.cursor_down.target:set_offset(self.cursor_down.T, 'Click') - self.dragging.target = self.cursor_down.target - self.dragging.handled = false - end - self.cursor_down.handled = true - end - - if not self.cursor_up.handled then - --First, stop dragging - if self.dragging.target then - self.dragging.target:stop_drag() - self.dragging.target.states.drag.is = false - self.dragging.target = nil - end - --Now, handle the Cursor release - --Was the Cursor release in the same location as the Cursor press and within Cursor timeout? - if self.cursor_down.target then - if (not self.cursor_down.target.click_timeout or self.cursor_down.target.click_timeout*G.SPEEDFACTOR > self.cursor_up.time - self.cursor_down.time) then - if Vector_Dist(self.cursor_down.T, self.cursor_up.T) < G.MIN_CLICK_DIST then - if self.cursor_down.target.states.click.can then - self.clicked.target = self.cursor_down.target - self.clicked.handled = false - end - --if not, was the Cursor dragging some other thing? - elseif self.dragging.prev_target and self.cursor_up.target and self.cursor_up.target.states.release_on.can then - self.released_on.target = self.cursor_up.target - self.released_on.handled = false - end - end - end - self.cursor_up.handled = true - end - - --Cursor is currently hovering over something - if self.cursor_hover.target and self.cursor_hover.target.states.hover.can and (not self.HID.touch or self.is_cursor_down) then - self.hovering.target = self.cursor_hover.target - if self.hovering.prev_target and self.hovering.prev_target ~= self.hovering.target then self.hovering.prev_target.states.hover.is = false end - self.hovering.target.states.hover.is = true - self.hovering.target:set_offset(self.cursor_hover.T, 'Hover') - elseif (self.cursor_hover.target == nil or (self.HID.touch and not self.is_cursor_down)) and self.hovering.target then - self.hovering.target.states.hover.is = false - self.hovering.target = nil - end - - -------------------------------------------------------------------- - -- Sending all input updates to the game objects - -------------------------------------------------------------------- - --The clicked object - if not self.clicked.handled then - self.clicked.target:click() - self.clicked.handled = true - end - - --Process registry clicks - self:process_registry() - - --The object being dragged - if self.dragging.target then - self.dragging.target:drag() - end - - --The object released on - if not self.released_on.handled and self.dragging.prev_target then - if self.dragging.prev_target == self.hovering.target then self.hovering.target:stop_hover();self.hovering.target = nil end - self.released_on.target:release(self.dragging.prev_target) - self.released_on.handled = true - end - - --The object being hovered over - if self.hovering.target then - self.hovering.target:set_offset(self.cursor_hover.T, 'Hover') - if self.hovering.prev_target ~= self.hovering.target then - if self.hovering.target ~= self.dragging.target and not self.HID.touch then - self.hovering.target:hover() - elseif self.HID.touch then - local _ID = self.hovering.target.ID - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - blocking = false, - delay = G.MIN_HOVER_TIME, - func = function() - if self.hovering.target and _ID == self.hovering.target.ID then - self.hovering.target:hover() - end - return true - end - })) - if self.hovering.prev_target then - self.hovering.prev_target:stop_hover() - end - end - if self.hovering.prev_target then - self.hovering.prev_target:stop_hover() - end - end - elseif self.hovering.prev_target then - self.hovering.prev_target:stop_hover() - end - if self.hovering.target and self.hovering.target == self.dragging.target and not self.HID.touch then - self.hovering.target:stop_hover() - end -end - ---Brute force remove all registries that no longer have valid nodes -function Controller:cull_registry() - for k, registry in pairs(self.button_registry) do - for i=#registry, 1, -1 do - if registry[i].node.REMOVED then - table.remove(registry, i) - end - end - end -end - ---Adds a node to the controller registry. Supply the button that will be pressed in order to click this node --- ----@param node Node The node that will be clicked when the registry is pressed ----@param registry string The button to register, must be a valid gamepad input -function Controller:add_to_registry(node, registry) - --If the button doesn't have a registry list yet, add it - self.button_registry[registry] = self.button_registry[registry] or {} - - --There really should only ever be one entry per registered button, but that is hard sometimes with all the stuff on screen. - --If that does happen, the most recently registered one will be used and the old one will be kept in case we remove the new button and want to keep the old binding - table.insert(self.button_registry[registry], 1, {node = node, menu = (not not G.OVERLAY_MENU) or (not not G.SETTINGS.paused)}) -end - ---Process any click function of any nodes that have been clicked in the button registry -function Controller:process_registry() - for _, registry in pairs(self.button_registry) do - for i=1, #registry do - if registry[i].click and registry[i].node.click then - if registry[i].menu == not not G.OVERLAY_MENU and - registry[i].node.T.x > -2 and registry[i].node.T.x < G.ROOM.T.w + 2 and - registry[i].node.T.y > -2 and registry[i].node.T.y < G.ROOM.T.h + 2 then - registry[i].node:click() - end - registry[i].click = nil - end - end - end -end - ---Add or remove layers from the context for the cursor. This allows the cursor to 'snap' back to the previous layer when the current layer is removed\ ---in such cases where a menu on screen is removed or nested menus are being navigated --- ----@param delta number The direction to modify the cursor context, 1 to add a layer, -1 to remove a layer, -1000 to remove all layers except for the base -function Controller:mod_cursor_context_layer(delta) - --Add a layer to the context, reference the node but if that node has been removed also save the cursor position too - if delta == 1 then - local prev_cursor_context = {node = self.focused.target, cursor_pos = {x = G.CURSOR.T.x, y = G.CURSOR.T.y}, interrupt = self.interrupt.focus} - self.cursor_context.stack[self.cursor_context.layer] = prev_cursor_context - self.cursor_context.layer = self.cursor_context.layer + 1 - - --remove the top layer from the stack - elseif delta == -1 then - self.cursor_context.stack[self.cursor_context.layer] = nil - self.cursor_context.layer = self.cursor_context.layer - 1 - - --remove all but the base layer from the stack - elseif delta == -1000 then - self.cursor_context.layer = 1 - self.cursor_context.stack = {self.cursor_context.stack[1]} - - --remove all layers - elseif delta == -2000 then - self.cursor_context.layer = 1 - self.cursor_context.stack = {} - end - - --Navigate focus, will default to the top layer on the stack - self:navigate_focus() -end - ---Snap the cursor to a particular node or transform -function Controller:snap_to(args) - self.snap_cursor_to = {node = args.node, T = args.T, type = args.node and 'node' or 'transform'} -end - ---saves the focus context to be loaded in the future, for example if the shop is rerolled while a card is highlighted -function Controller:save_cardarea_focus(_cardarea) - if G[_cardarea] then - if self.focused.target and self.focused.target.area and self.focused.target.area == G[_cardarea] then - self.cardarea_context[_cardarea] = self.focused.target.rank - return true - else - self.cardarea_context[_cardarea] = nil - end - end -end - ---recalls the focus context for a particular cardarea -function Controller:recall_cardarea_focus(_cardarea) - local ca_string = nil - if type(_cardarea) == 'string' then ca_string = _cardarea; _cardarea = G[_cardarea] end - - if _cardarea and (not self.focused.target or - self.interrupt.focus or - (not self.interrupt.focus and self.focused.target.area and self.focused.target.area == _cardarea)) then - if ca_string and self.cardarea_context[ca_string] then - for i = self.cardarea_context[ca_string], 1, -1 do - if _cardarea.cards[i] then - self:snap_to({node = _cardarea.cards[i]}) - self.interrupt.focus = false - break - end - end - elseif _cardarea.cards and _cardarea.cards[1] then - self:snap_to({node = _cardarea.cards[1]}) - self.interrupt.focus = false - end - end - if ca_string then self.cardarea_context[ca_string] = nil end -end - ---Updated the location of the cursor, either with a specific T or if there is a Node target -function Controller:update_cursor(hard_set_T) - if hard_set_T then - G.CURSOR.T.x = hard_set_T.x - G.CURSOR.T.y = hard_set_T.y - self.cursor_position.x = G.CURSOR.T.x*(G.TILESCALE*G.TILESIZE) - self.cursor_position.y = G.CURSOR.T.y*(G.TILESCALE*G.TILESIZE) - G.CURSOR.VT.x = G.CURSOR.T.x - G.CURSOR.VT.y = G.CURSOR.T.y - return - end - if self.focused.target then - self.cursor_position.x, self.cursor_position.y = self.focused.target:put_focused_cursor() - G.CURSOR.T.x = self.cursor_position.x/(G.TILESCALE*G.TILESIZE) - G.CURSOR.T.y = self.cursor_position.y/(G.TILESCALE*G.TILESIZE) - G.CURSOR.VT.x = G.CURSOR.T.x - G.CURSOR.VT.y = G.CURSOR.T.y - end -end - ---Helper function to set the button presses/releases for the values determined in update_axis() -function Controller:handle_axis_buttons() - for _, v in pairs(G.CONTROLLER.axis_buttons) do - --Button is no longer being pressed - if v.previous ~= '' and (v.current == '' or v.previous ~= v.current) then - G.CONTROLLER:button_release(v.previous) - end - --New button is being pressed - if v.current ~= '' and v.previous ~= v.current then - G.CONTROLLER:button_press(v.current) - end - end -end - ---Handles all axis input for left stick, right stick and triggers. Treats them as buttons or cursors depending on context -function Controller:update_axis(dt) - --Keep track of if there is any cursor movement from the axis changes - local axis_interpretation = nil - - --Advance all the axis buttons to determine if there were any changes - self.axis_buttons.l_stick.previous = self.axis_buttons.l_stick.current; self.axis_buttons.l_stick.current = '' - self.axis_buttons.r_stick.previous = self.axis_buttons.r_stick.current; self.axis_buttons.r_stick.current = '' - self.axis_buttons.l_trig.previous = self.axis_buttons.l_trig.current; self.axis_buttons.l_trig.current = '' - self.axis_buttons.r_trig.previous = self.axis_buttons.r_trig.current; self.axis_buttons.r_trig.current = '' - - if self.HID.controller then - --------------------------------------------------------------- - -- Left Thumbstick - --------------------------------------------------------------- - local l_stick_x = self.GAMEPAD.object:getGamepadAxis('leftx') - local l_stick_y = self.GAMEPAD.object:getGamepadAxis('lefty') - --If there is something being dragged, we want to treat the left stick as a cursor input - if self.dragging.target and math.abs(l_stick_x) + math.abs(l_stick_y) > 0.1 then - axis_interpretation = 'axis_cursor' --There is some cursor movement - - --deadzone of 10% for each axis of l_stick - if math.abs(l_stick_x) < 0.1 then l_stick_x = 0 end - if math.abs(l_stick_y) < 0.1 then l_stick_y = 0 end - l_stick_x = l_stick_x + (l_stick_x>0 and -0.1 or 0) + (l_stick_x<0 and 0.1 or 0) - l_stick_y = l_stick_y + (l_stick_y>0 and -0.1 or 0) + (l_stick_y<0 and 0.1 or 0) - - --Modify the cursor position according to the l_stick axis values - G.CURSOR.T.x = G.CURSOR.T.x + dt*l_stick_x*self.axis_cursor_speed - G.CURSOR.T.y = G.CURSOR.T.y + dt*l_stick_y*self.axis_cursor_speed - G.CURSOR.VT.x = G.CURSOR.T.x - G.CURSOR.VT.y = G.CURSOR.T.y - - self.cursor_position.x = G.CURSOR.T.x*(G.TILESCALE*G.TILESIZE) - self.cursor_position.y = G.CURSOR.T.y*(G.TILESCALE*G.TILESIZE) - - --If nothing is being dragged, we want to treat the left stick as a dpad input - else - self.axis_buttons.l_stick.current = self.axis_buttons.l_stick.previous - if math.abs(l_stick_x) + math.abs(l_stick_y) > 0.5 then - axis_interpretation = 'button' --left stick is no longer a cursor, can be set below from the right stick though - - self.axis_buttons.l_stick.current = math.abs(l_stick_x) > math.abs(l_stick_y) and - (l_stick_x > 0 and 'dpright' or 'dpleft') or - (l_stick_y > 0 and 'dpdown' or 'dpup') - elseif math.abs(l_stick_x) + math.abs(l_stick_y) < 0.3 then - self.axis_buttons.l_stick.current = '' - end - end - - --------------------------------------------------------------- - -- Right Thumbstick - --------------------------------------------------------------- - local r_stick_x = self.GAMEPAD.object:getGamepadAxis('rightx') - local r_stick_y = self.GAMEPAD.object:getGamepadAxis('righty') - G.DEADZONE = 0.2 - local mag = math.sqrt(math.abs(r_stick_x)^2 + math.abs(r_stick_y)^2) - if mag > G.DEADZONE then - axis_interpretation = 'axis_cursor' --There is some cursor movement - - --deadzone of 20% for each axis of l_stick - if math.abs(r_stick_x) < G.DEADZONE then r_stick_x = 0 end - if math.abs(r_stick_y) < G.DEADZONE then r_stick_y = 0 end - r_stick_x = r_stick_x + (r_stick_x>0 and -G.DEADZONE or 0) + (r_stick_x<0 and G.DEADZONE or 0) - r_stick_y = r_stick_y + (r_stick_y>0 and -G.DEADZONE or 0) + (r_stick_y<0 and G.DEADZONE or 0) - - --Modify the cursor position according to the l_stick axis values - G.CURSOR.T.x = G.CURSOR.T.x + dt*r_stick_x*self.axis_cursor_speed - G.CURSOR.T.y = G.CURSOR.T.y + dt*r_stick_y*self.axis_cursor_speed - G.CURSOR.VT.x = G.CURSOR.T.x - G.CURSOR.VT.y = G.CURSOR.T.y - - self.cursor_position.x = G.CURSOR.T.x*(G.TILESCALE*G.TILESIZE) - self.cursor_position.y = G.CURSOR.T.y*(G.TILESCALE*G.TILESIZE) - end - - --------------------------------------------------------------- - -- Triggers - --------------------------------------------------------------- - --Triggers are just buttons - local l_trig = self.GAMEPAD.object:getGamepadAxis('triggerleft') - local r_trig = self.GAMEPAD.object:getGamepadAxis('triggerright') - - --Set the current to be the same as previous, only set to '' if the trigger value is low enough - self.axis_buttons.l_trig.current = self.axis_buttons.l_trig.previous - self.axis_buttons.r_trig.current = self.axis_buttons.r_trig.previous - - --Make a tilting effect when you press the triggers while hovering over a node that has tilt_var - if self.focused.target and self.focused.target.tilt_var then - --self.focused.target.tilt_var.dx = 0.1*(r_trig - l_trig) + 0.9*self.focused.target.tilt_var.dx - end - - if l_trig > 0.5 then - self.axis_buttons.l_trig.current = 'triggerleft' - elseif l_trig < 0.3 then - self.axis_buttons.l_trig.current = '' - end - if r_trig > 0.5 then - self.axis_buttons.r_trig.current = 'triggerright' - elseif r_trig < 0.3 then - self.axis_buttons.r_trig.current = '' - end - - --return 'button' if trigger is being used and axis is not - if self.axis_buttons.r_trig.current ~= '' or self.axis_buttons.l_trig.current ~= '' then - axis_interpretation = axis_interpretation or 'button' - end - - self:handle_axis_buttons() - end - - if axis_interpretation then self.interrupt.focus = false end - - return axis_interpretation -end - -function Controller:button_press_update(button, dt) - if self.locks.frame then return end - self.held_button_times[button] = 0 - self.interrupt.focus = false - - if not self:capture_focused_input(button, 'press', dt) then - if button == "dpup" then - self:navigate_focus('U') - end - if button == "dpdown" then - self:navigate_focus('D') - end - if button == "dpleft" then - self:navigate_focus('L') - end - if button == "dpright" then - self:navigate_focus('R') - end - end - - if ((self.locked) and not G.SETTINGS.paused) or (self.locks.frame) or (self.frame_buttonpress) then return end - self.frame_buttonpress = true - - if self.button_registry[button] and self.button_registry[button][1] and not self.button_registry[button][1].node.under_overlay then - self.button_registry[button][1].click = true - else - if button == 'start' then - if G.STATE == G.STATES.SPLASH then - G:delete_run() - G:main_menu() - end - end - if button == "a" then - if self.focused.target and - self.focused.target.config.focus_args and - self.focused.target.config.focus_args.type == 'slider' and - (not G.CONTROLLER.HID.mouse and not G.CONTROLLER.HID.axis_cursor) then - else - self:L_cursor_press() - end - end - if button == 'b' then - if G.hand and self.focused.target and - self.focused.target.area == G.hand then - self:queue_R_cursor_press() - else - self.interrupt.focus = true - end - end - end -end - -function Controller:button_hold_update(button, dt) - if ((self.locked) and not G.SETTINGS.paused) or (self.locks.frame) or (self.frame_buttonpress) then return end - self.frame_buttonpress = true - if self.held_button_times[button] then - self.held_button_times[button] = self.held_button_times[button] + dt - self:capture_focused_input(button, 'hold', dt) - end - if (button == 'dpleft' or button == 'dpright' or button == 'dpup' or button == 'dpdown') and not self.no_holdcap then - self.repress_timer = self.repress_timer or 0.3 - if self.held_button_times[button] and (self.held_button_times[button] > self.repress_timer) then - self.repress_timer = 0.1 - self.held_button_times[button] = 0 - self:button_press_update(button, dt) - end - end -end - -function Controller:button_release_update(button, dt) - if not self.held_button_times[button] then return end - self.repress_timer = 0.3 - self.held_button_times[button] = nil - if button == 'a' then - self:L_cursor_release() - end -end - -function Controller:key_press_update(key, dt) - if key == "escape" and Cartomancer.INTERNAL_in_config then - Cartomancer.INTERNAL_in_config = false - if not Cartomancer.use_smods() then - Cartomancer.save_config() - end - end - if key == "escape" and G.ACTIVE_MOD_UI then - G.FUNCS.exit_mods() - end - if self.locks.frame then return end - if string.sub(key, 1, 2) == 'kp' then key = string.sub(key, 3) end - if key == 'enter' then key = 'return' end - - if self.text_input_hook then - if key == "escape" then - self.text_input_hook = nil - elseif key == "capslock" then - self.capslock = not self.capslock - else - G.FUNCS.text_input_key{ - e=self.text_input_hook, - key = key, - caps = self.held_keys["lshift"] or self.held_keys["rshift"] - } - end - return - end - - if key == "escape" then - if G.STATE == G.STATES.SPLASH then - G:delete_run() - G:main_menu() - else - if not G.OVERLAY_MENU then - G.FUNCS:options() - elseif not G.OVERLAY_MENU.config.no_esc then - G.FUNCS:exit_overlay_menu() - end - end - end - - if ((self.locked) and not G.SETTINGS.paused) or (self.locks.frame) or (self.frame_buttonpress) then return end - self.frame_buttonpress = true - self.held_key_times[key] = 0 - - - for _, keybind in pairs(SMODS.Keybinds) do - if keybind.action and keybind.key_pressed == key and keybind.event == 'pressed' then - local execute = true - for _, other_key in pairs(keybind.held_keys) do - if not self.held_keys[other_key] then - execute = false - break - end - end - if execute then - keybind:action() - end - end - end - if not _RELEASE_MODE and require("debugplus.core").isOkayToHandleDebugForKey(key) then - if key == 'tab' and not G.debug_tools then - G.debug_tools = UIBox{ - definition = create_UIBox_debug_tools(), - config = {align='cr', offset = {x=G.ROOM.T.x + 11,y=0},major = G.ROOM_ATTACH, bond = 'Weak'} - } - G.E_MANAGER:add_event(Event({ - blockable = false, - func = function() - G.debug_tools.alignment.offset.x = -4 - return true - end - })) - end - if self.hovering.target and self.hovering.target:is(Card) then - local _card = self.hovering.target - if G.OVERLAY_MENU then - if key == "1" then - unlock_card(_card.config.center) - _card:set_sprites(_card.config.center) - end - if key == "2" then - unlock_card(_card.config.center) - discover_card(_card.config.center) - _card:set_sprites(_card.config.center) - end - if key == "3" then - if _card.ability.set == 'Joker' and G.jokers and #G.jokers.cards < G.jokers.config.card_limit then - add_joker(_card.config.center.key) - _card:set_sprites(_card.config.center) - end - local debugplus = require("debugplus.core") - debugplus.handleSpawn(self, _card) - if _card.ability.consumeable and G.consumeables and #G.consumeables.cards < G.consumeables.config.card_limit then - add_joker(_card.config.center.key) - _card:set_sprites(_card.config.center) - end - end - end - if key == 'q' then - if (_card.ability.set == 'Joker' or _card.playing_card or _card.area) then - local found_index = 1 - if _card.edition then - for i, v in ipairs(G.P_CENTER_POOLS.Edition) do - if v.key == _card.edition.key then - found_index = i - break - end - end - end - found_index = found_index + 1 - if found_index > #G.P_CENTER_POOLS.Edition then found_index = found_index - #G.P_CENTER_POOLS.Edition end - local _edition = G.P_CENTER_POOLS.Edition[found_index].key - _card:set_edition(_edition, true, true) - end - end - end - if key == 'h' then - G.debug_UI_toggle = not G.debug_UI_toggle - end - if key == 'b' then - G:delete_run() - G:start_run({}) - end - if key == 'l' then - G:delete_run() - G.SAVED_GAME = get_compressed(G.SETTINGS.profile..'/'..'save.jkr') - if G.SAVED_GAME ~= nil then G.SAVED_GAME = STR_UNPACK(G.SAVED_GAME) end - G:start_run({savetext = G.SAVED_GAME}) - end - if key == 'j' then - G.debug_splash_size_toggle = not G.debug_splash_size_toggle - G:delete_run() - G:main_menu('splash') - end - if key == '8' then - love.mouse.setVisible( not love.mouse.isVisible() ) - end - if key == '9' then - G.debug_tooltip_toggle = not G.debug_tooltip_toggle - end - if key == "space" then - live_test() - end - local debugplus = require("debugplus.core") - debugplus.handleKeys(self, key, dt) - if key == 'v' then - if not G.prof then G.prof = require "engine/profile"; G.prof.start() - else G.prof:stop(); - print(G.prof.report()); G.prof = nil end - debugplus.profileMessage() - end - if key == "p" then - G.SETTINGS.perf_mode = not G.SETTINGS.perf_mode - debugplus.togglePerfUI() - end - end -end - -function Controller:key_hold_update(key, dt) - if ((self.locked) and not G.SETTINGS.paused) or (self.locks.frame) or (self.frame_buttonpress) then return end - --self.frame_buttonpress = true - if self.held_key_times[key] then - for _, keybind in pairs(SMODS.Keybinds) do - if keybind.key_pressed == key and keybind.event == 'held' and keybind.held_duration then - if self.held_key_times[key] > keybind.held_duration then - local execute = true - for _, other_key in pairs(keybind.held_keys) do - if not self.held_keys[other_key] then - execute = false - break - end - end - if execute then - keybind:action() - self.held_key_times[key] = nil - end - else - self.held_key_times[key] = self.held_key_times[key] + dt - end - end -end -if key == "r" and not G.SETTINGS.paused and not (G.GAME and G.GAME.USING_CODE) then - if self.held_key_times[key] > 0.7 then - if not G.GAME.won and not G.GAME.seeded and not G.GAME.challenge then - G.PROFILES[G.SETTINGS.profile].high_scores.current_streak.amt = 0 - end - G:save_settings() - self.held_key_times[key] = nil - G.SETTINGS.current_setup = 'New Run' - G.GAME.viewed_back = nil - G.run_setup_seed = G.GAME.seeded - G.challenge_tab = G.GAME and G.GAME.challenge and G.GAME.challenge_tab or nil - G.forced_seed, G.setup_seed = nil, nil - if G.GAME.seeded then G.forced_seed = G.GAME.pseudorandom.seed end - G.forced_stake = G.GAME.stake - if G.STAGE == G.STAGES.RUN then G.FUNCS.start_setup_run() end - G.forced_stake = nil - G.challenge_tab = nil - G.forced_seed = nil - else - self.held_key_times[key] = self.held_key_times[key] + dt - end - end - end -end - -function Controller:key_release_update(key, dt) -for _, keybind in pairs(SMODS.Keybinds) do - if keybind.action and keybind.key_pressed == key and keybind.event == 'released' then - local execute = true - for _, other_key in pairs(keybind.held_keys) do - if not self.held_keys[other_key] then - execute = false - break - end - end - if execute then - keybind:action() - end - end -end - if ((self.locked) and not G.SETTINGS.paused) or (self.locks.frame) or (self.frame_buttonpress) then return end - self.frame_buttonpress = true - if key == "a" and self.held_keys["g"] and not _RELEASE_MODE then - G.DEBUG = not(G.DEBUG) - end - if key == 'tab' and G.debug_tools then - G.debug_tools:remove() - G.debug_tools = nil - end -end - -function Controller:key_press(key) - self.pressed_keys[key] = true - self.held_keys[key] = true -end - -function Controller:key_release(key) - self.held_keys[key] = nil - self.released_keys[key] = true -end - -function Controller:button_press(button) - self.pressed_buttons[button] = true - self.held_buttons[button] = true -end - -function Controller:button_release(button) - self.held_buttons[button] = nil - self.released_buttons[button] = true -end - -function Controller:get_cursor_collision(cursor_trans) - self.collision_list = EMPTY(self.collision_list) - self.nodes_at_cursor = EMPTY(self.nodes_at_cursor) - - if self.COYOTE_FOCUS then return end - if self.dragging.target then - self.dragging.target.states.collide.is = true - self.nodes_at_cursor[#self.nodes_at_cursor+1] = self.dragging.target - self.collision_list[#self.collision_list+1] = self.dragging.target - end - - if not G.DRAW_HASH[1] or - cursor_trans.x-G.ROOM.T.x < -G.DRAW_HASH_BUFF or cursor_trans.x-G.ROOM.T.x > G.TILE_W + G.DRAW_HASH_BUFF or - cursor_trans.y-G.ROOM.T.y < -G.DRAW_HASH_BUFF or cursor_trans.y-G.ROOM.T.y > G.TILE_H + G.DRAW_HASH_BUFF then - return - end - - local DRAW_HASH_SQUARE = G.DRAW_HASH - for i = #DRAW_HASH_SQUARE, 1, -1 do - local v = DRAW_HASH_SQUARE[i] - if v:collides_with_point(cursor_trans) and not v.REMOVED then - self.nodes_at_cursor[#self.nodes_at_cursor+1] = v - if v.states.collide.can then - v.states.collide.is = true - self.collision_list[#self.collision_list+1] = v - end - end - end -end - -function Controller:set_cursor_hover() - self.cursor_hover.T = self.cursor_hover.T or {} - self.cursor_hover.T.x, self.cursor_hover.T.y =G.CURSOR.T.x, G.CURSOR.T.y - self.cursor_hover.time = G.TIMERS.TOTAL - - self.cursor_hover.prev_target = self.cursor_hover.target - self.cursor_hover.target = nil - - if self.interrupt.focus or ((self.locked) and (not G.SETTINGS.paused or G.screenwipe)) or self.locks.frame or self.COYOTE_FOCUS then self.cursor_hover.target = G.ROOM; return end - - if self.HID.controller and self.focused.target and self.focused.target.states.hover.can then - if (self.HID.dpad or self.HID.axis_cursor) and self.focused.target.states.collide.is then - self.cursor_hover.target = self.focused.target - else - for _, v in ipairs(self.collision_list) do - if v.states.hover.can then - self.cursor_hover.target = v - break - end - end - end - else - for _, v in ipairs(self.collision_list) do - if v.states.hover.can and (not v.states.drag.is or self.HID.touch) then - self.cursor_hover.target = v - break - end - end - end - - if not self.cursor_hover.target or (self.dragging.target and not self.HID.touch) then self.cursor_hover.target = G.ROOM end - if self.cursor_hover.target ~= self.cursor_hover.prev_target then self.cursor_hover.handled = false end -end - -function Controller:queue_L_cursor_press(x, y) - if self.locks.frame then return end - if G.STATE == G.STATES.SPLASH then - self:key_press('escape') - end - self.L_cursor_queue = {x = x, y = y} -end - -function Controller:queue_R_cursor_press(x, y) - if self.locks.frame then return end - if not G.SETTINGS.paused and G.hand and G.hand.highlighted[1] then - if (G.play and #G.play.cards > 0) or - (self.locked) or - (self.locks.frame) or - (G.GAME.STOP_USE and G.GAME.STOP_USE > 0) then return end - G.hand:unhighlight_all() - end -end - -function Controller:L_cursor_press(x, y) - x = x or self.cursor_position.x - y = y or self.cursor_position.y - - if ((self.locked) and (not G.SETTINGS.paused or G.screenwipe)) or (self.locks.frame) then return end - - self.cursor_down.T = {x = x/(G.TILESCALE*G.TILESIZE), y = y/(G.TILESCALE*G.TILESIZE)} - self.cursor_down.time = G.TIMERS.TOTAL - self.cursor_down.handled = false - self.cursor_down.target = nil - self.is_cursor_down = true - - local press_node = (self.HID.touch and self.cursor_hover.target) or self.hovering.target or self.focused.target - - if press_node then - self.cursor_down.target = press_node.states.click.can and press_node or press_node:can_drag() or nil - end - - if self.cursor_down.target == nil then - self.cursor_down.target = G.ROOM - end -end - -function Controller:L_cursor_release(x, y) - x = x or self.cursor_position.x - y = y or self.cursor_position.y - - if ((self.locked) and (not G.SETTINGS.paused or G.screenwipe)) or (self.locks.frame) then return end - - self.cursor_up.T = {x = x/(G.TILESCALE*G.TILESIZE), y = y/(G.TILESCALE*G.TILESIZE)} - self.cursor_up.time = G.TIMERS.TOTAL - self.cursor_up.handled = false - self.cursor_up.target = nil - self.is_cursor_down = false - - self.cursor_up.target = self.hovering.target or self.focused.target - - if self.cursor_up.target == nil then - self.cursor_up.target = G.ROOM - end -end - -function Controller:is_node_focusable(node) - local ret_val = false - if node.T.y > G.ROOM.T.h + 3 then return false end - if not node.REMOVED and not node.under_overlay and (node.states.hover.can and not self.dragging.target or self.dragging.target == node) and - (not not node.created_on_pause) == (not not G.SETTINGS.paused) and - (node.states.visible) and (not node.UIBox or node.UIBox.states.visible) then - if self.screen_keyboard then - if node.UIBox and node.UIBox == self.screen_keyboard and node.config.button then - ret_val = true - end - else - if node:is(Card) and (node.facing == 'front' or node.area == G.hand or node.area == G.jokers or (node == G.deck)) and - node.states.hover.can and not node.jimbo then - ret_val = true - end - if node.config and node.config.force_focus then ret_val = true end - if node.config and node.config.button then ret_val = true end - if node.config and node.config.focus_args then - if node.config.focus_args.type == 'none' or node.config.focus_args.funnel_from then - ret_val = false - else - ret_val = true - end - end - end - end - return ret_val -end - ---essentially works like 'hovering' with any nodes that are focusable, but ---the nodes can also be navigated to via controller key inputs. If no direction is supplied, ---this function focuses on any nodes that collide with this cursor. If a direction is ---supplied, focuses on the nearest node in that direction. -function Controller:update_focus(dir) - self.focused.prev_target = self.focused.target - - --Only needed when using a controller, hovering covers all KBM scenarios - if not self.HID.controller or self.interrupt.focus or (self.locked) and (not G.SETTINGS.paused or G.screenwipe) then - if self.focused.target then self.focused.target.states.focus.is = false end - self.focused.target = nil - return - end - - G.ARGS.focus_list = EMPTY(G.ARGS.focus_list) - G.ARGS.focusables = EMPTY(G.ARGS.focusables) - - ------------------------------------------------- - -- Find the focusable starting point - ------------------------------------------------- - --First, is there currently a focusable target that is still valid? - if self.focused.target then - self.focused.target.states.focus.is = false - - --If that node is no longer focusable or if the cursor no longer collides with the node, remove the target - if not self:is_node_focusable(self.focused.target) or not self.focused.target:collides_with_point(G.CURSOR.T) or self.HID.axis_cursor then - self.focused.target = nil - end - end - - --Now we check for 3 criteria: - --1: is there a current focused target and no dpad direction? if so, we simply add the currsnt focused target to the focusable list and set the state to true - --2: if not, and there is no dpad direction, iterate through the node list that the cursor intersects and check if any are focusable, only add the first one - --3: if there is a direction, add all focusable moveables to the focusable list to check later - if not dir and self.focused.target then - self.focused.target.states.focus.can = true - G.ARGS.focusables[#G.ARGS.focusables+1] = self.focused.target - else - if not dir then - for k, v in ipairs(self.nodes_at_cursor) do - v.states.focus.can = false - v.states.focus.is = false - if #G.ARGS.focusables == 0 and self:is_node_focusable(v) then - v.states.focus.can = true - G.ARGS.focusables[#G.ARGS.focusables+1] = v - end - end - else - for k, v in pairs(G.MOVEABLES) do - v.states.focus.can = false - v.states.focus.is = false - if self:is_node_focusable(v) then - v.states.focus.can = true - G.ARGS.focusables[#G.ARGS.focusables+1] = v - end - end - end - end - - --If there are any valid focusables - if #G.ARGS.focusables > 0 then - --If a direction control is supplied, set the target to be the closest node in that direction - if dir then - if (dir == 'L' or dir == 'R') and self.focused.target and self.focused.target:is(Card) and self.focused.target.area == G.hand and G.hand then - local nu_rank = self.focused.target.rank + (dir == 'L' and -1 or 1) - if nu_rank > #G.hand.cards then nu_rank = 1 end - if nu_rank == 0 then nu_rank = #G.hand.cards end - if nu_rank ~= self.focused.target.rank then G.ARGS.focus_list[1] = {node = G.hand.cards[nu_rank]} end - else - --set the cursor position to where it currently is on screen - G.ARGS.focus_cursor_pos = G.ARGS.focus_cursor_pos or {} - G.ARGS.focus_cursor_pos.x, G.ARGS.focus_cursor_pos.y = G.CURSOR.T.x - G.ROOM.T.x, G.CURSOR.T.y - G.ROOM.T.y - - --if there is a focused target, set the cursor to the midpoint - if self.focused.target then - _ft = self.focused.target - if self.focused.target.config.focus_args and self.focused.target.config.focus_args.funnel_to then - _ft = self.focused.target.config.focus_args.funnel_to - end - G.ARGS.focus_cursor_pos.x, G.ARGS.focus_cursor_pos.y = _ft.T.x + 0.5*_ft.T.w,_ft.T.y + 0.5*_ft.T.h - --if not but there is a focusable hovering target, put the cursor on it instead - elseif self.hovering.target and self.hovering.target.states.focus.can then - G.ARGS.focus_cursor_pos.x, G.ARGS.focus_cursor_pos.y = self.hovering.target:put_focused_cursor() - G.ARGS.focus_cursor_pos.x = G.ARGS.focus_cursor_pos.x / (G.TILESCALE*G.TILESIZE) - G.ROOM.T.x - G.ARGS.focus_cursor_pos.y = G.ARGS.focus_cursor_pos.y / (G.TILESCALE*G.TILESIZE) - G.ROOM.T.y - end - - --set the list to be all the nodes in that direction sorted by the closest node - for _, v in pairs(G.ARGS.focusables) do - if v ~= self.hovering.target and v ~= self.focused.target then - local eligible = false - - if v.config.focus_args and v.config.focus_args.funnel_to then - v = v.config.focus_args.funnel_to - end - - G.ARGS.focus_vec = G.ARGS.focus_vec or {} - G.ARGS.focus_vec.x = v.T.x + 0.5*v.T.w - (G.ARGS.focus_cursor_pos.x) - G.ARGS.focus_vec.y = v.T.y + 0.5*v.T.h - (G.ARGS.focus_cursor_pos.y) - - if v.config.focus_args and v.config.focus_args.nav then - if v.config.focus_args.nav == 'wide' then - if G.ARGS.focus_vec.y > 0.1 and dir == 'D' then eligible = true - elseif G.ARGS.focus_vec.y < -0.1 and dir == 'U' then eligible = true - elseif math.abs(G.ARGS.focus_vec.y) < v.T.h/2 then eligible = true end - elseif v.config.focus_args.nav == 'tall' then - if G.ARGS.focus_vec.x > 0.1 and dir == 'R' then eligible = true - elseif G.ARGS.focus_vec.x < -0.1 and dir == 'L' then eligible = true - elseif math.abs(G.ARGS.focus_vec.x) < v.T.w/2 then eligible = true end - end - elseif math.abs(G.ARGS.focus_vec.x) > math.abs(G.ARGS.focus_vec.y) then - if G.ARGS.focus_vec.x > 0 and dir == 'R' then eligible = true - elseif G.ARGS.focus_vec.x < 0 and dir == 'L' then eligible = true end - else - if G.ARGS.focus_vec.y > 0 and dir == 'D' then eligible = true - elseif G.ARGS.focus_vec.y < 0 and dir == 'U' then eligible = true end - end - - if eligible then - G.ARGS.focus_list[#G.ARGS.focus_list+1] = {node = v, dist = math.abs(G.ARGS.focus_vec.x) + math.abs(G.ARGS.focus_vec.y)} - end - end - end - if #G.ARGS.focus_list < 1 then - if self.focused.target then self.focused.target.states.focus.is = true end - return - end - table.sort(G.ARGS.focus_list, function (a, b) return a.dist < b.dist end) - end - else - if self.focused.target then - G.ARGS.focus_list[#G.ARGS.focus_list+1] = {node = self.focused.target, dist = 0} - else - --otherwise, get the focusable that collides - G.ARGS.focus_list[#G.ARGS.focus_list+1] = {node = G.ARGS.focusables[1], dist = 0} - end - end - end - - --now with the lists created, set the focused target to be the first node in the list - if G.ARGS.focus_list[1] then - if G.ARGS.focus_list[1].node.config and G.ARGS.focus_list[1].node.config.focus_args and G.ARGS.focus_list[1].node.config.focus_args.funnel_from then - self.focused.target = G.ARGS.focus_list[1].node.config.focus_args.funnel_from - else - self.focused.target = G.ARGS.focus_list[1].node - end - if self.focused.target ~= self.focused.prev_target then G.VIBRATION = G.VIBRATION + 0.7 end - else - self.focused.target = nil - end - - if self.focused.target then self.focused.target.states.focus.is = true end -end - -function Controller:capture_focused_input(button, input_type, dt) - local ret = false - local focused = self.focused.target - local extern_button = false - self.no_holdcap = nil - - --Implementing 'coyote time' type selection where a full button press isnt needed to select a card in hand. As long as a button down has been registered - --before a timer is up and the dpad is used to move to the next card it should register - if input_type == 'press' and (button == 'dpleft' or button == 'dpright') and - focused and self.dragging.target and - (self.held_button_times['a'] and self.held_button_times['a'] < 0.12) and - focused.area and focused.area:can_highlight(focused) then - self:L_cursor_release() - self:navigate_focus(button == 'dpleft' and 'L' or 'R') - self.held_button_times['a'] = nil - self.COYOTE_FOCUS = true - ret = true - elseif input_type == 'press' and focused and focused.area and focused == self.dragging.target then - focused.states.drag.is = false - if button == 'dpleft' and focused.rank > 1 then - focused.rank = focused.rank - 1 - focused.area.cards[focused.rank].rank = focused.rank + 1 - table.sort(focused.area.cards, function (a, b) return a.rank < b.rank end) - focused.area:align_cards() - self:update_cursor() - elseif button == 'dpright' and focused.rank < #focused.area.cards then - focused.rank = focused.rank + 1 - focused.area.cards[focused.rank].rank = focused.rank - 1 - table.sort(focused.area.cards, function (a, b) return a.rank < b.rank end) - focused.area:align_cards() - self:update_cursor() - end - focused.states.drag.is = true - ret = true - end - - if G.OVERLAY_MENU and not self.screen_keyboard and input_type == 'press' and G.OVERLAY_MENU:get_UIE_by_ID('tab_shoulders') and (button == 'leftshoulder' or button == 'rightshoulder') then - focused = G.OVERLAY_MENU:get_UIE_by_ID('tab_shoulders') - extern_button = true - end - if G.OVERLAY_MENU and not self.screen_keyboard and input_type == 'press' and G.OVERLAY_MENU:get_UIE_by_ID('cycle_shoulders') and (button == 'leftshoulder' or button == 'rightshoulder') then - focused = G.OVERLAY_MENU:get_UIE_by_ID('cycle_shoulders').children[1] - extern_button = true - end - if focused and focused.config.focus_args then - if focused.config.focus_args.type == 'cycle' and input_type == 'press' then - if ((extern_button and button == 'leftshoulder') or (not extern_button and button == 'dpleft')) then - focused.children[1]:click() - ret = true - end - if ((extern_button and button == 'rightshoulder') or (not extern_button and button == 'dpright')) then - focused.children[3]:click() - ret = true - end - end - if focused.config.focus_args.type == 'tab' and input_type == 'press' then - local proto_choices = focused.UIBox:get_group(nil, focused.children[1].children[1].config.group) - local choices = {} - for k, v in ipairs(proto_choices) do - if v.config.choice and v.config.button then choices[#choices+1] = v end - end - for k, v in ipairs(choices) do - if v.config.chosen then - if ((extern_button and button == 'leftshoulder') or (not extern_button and button == 'dpleft')) then - local next_i = k ~= 1 and (k-1) or (#choices) - if focused.config.focus_args.no_loop and next_i > k then ret = nil - else - choices[next_i]:click() - self:snap_to({node = choices[next_i]}) - self:update_cursor() - ret = true - end - elseif ((extern_button and button == 'rightshoulder') or (not extern_button and button == 'dpright')) then - local next_i = k ~= #choices and (k+1) or (1) - if focused.config.focus_args.no_loop and next_i < k then ret = nil - else - choices[next_i]:click() - self:snap_to({node = choices[next_i]}) - self:update_cursor() - ret = true - end - end - break - end - end - end - if focused.config.focus_args.type == 'slider' then - if button == 'dpleft' then - self.no_holdcap = true - if input_type == 'hold' and self.held_button_times[button] > 0.2 then - G.FUNCS.slider_descreet(focused.children[1], -dt*self.held_button_times[button]*0.6) - end - if input_type == 'press' then - G.FUNCS.slider_descreet(focused.children[1], -0.01) - end - ret = true - end - if button == 'dpright' then - self.no_holdcap = true - if input_type == 'hold' and self.held_button_times[button] > 0.2 then - G.FUNCS.slider_descreet(focused.children[1], dt*self.held_button_times[button]*0.6) - end - if input_type == 'press' then - G.FUNCS.slider_descreet(focused.children[1], 0.01) - end - ret = true - end - end - end - if ret == true then G.VIBRATION = G.VIBRATION +1 end - return ret -end - -function Controller:navigate_focus(dir) - --Get the corresponding focus target first, with or without a direction - self:update_focus(dir) - - --Set the cursor to be in the correct position for that target - self:update_cursor() -end - diff --git a/lovely/dump/engine/moveable.lua b/lovely/dump/engine/moveable.lua deleted file mode 100644 index 4ad58fa..0000000 --- a/lovely/dump/engine/moveable.lua +++ /dev/null @@ -1,520 +0,0 @@ -LOVELY_INTEGRITY = '2774a24114332371bc4208f854d32c6f93786326d6810fc4139b615d177277e3' - ----@class Moveable: Node -Moveable = Node:extend() - ---Moveable represents any game object that has the ability to move about the gamespace.\ ---All Moveables have a T (transform) that describes their desired transform in game units, as\ ---well as a VT (Visible Transform) that eases to T over time. This allows for simplified movement where\ ---we only need to set T.x, T.y, etc. to their final position and the engine will ensure the Moveable\ ---VT eases to that final location, regargless of any events or timing. --- ----@param args {T: table, container: Node} ---**T** The transform ititializer, with keys of x|1, y|2, w|3, h|4, r|5\ ---**container** optional container for this Node, defaults to G.ROOM -function Moveable:init(X,Y,W,H) - local args = (type(X) == 'table') and X or {T ={X or 0,Y or 0,W or 0,H or 0}} - Node.init(self, args) - - --The Visible transform is initally set to the same values as the transform T. - --Note that the VT has an extra 'scale' factor, this is used to manipulate the center-adjusted - --scale of any objects that need to be drawn larger or smaller - self.VT = { - x = self.T.x, - y = self.T.y, - w = self.T.w, - h = self.T.h, - r = self.T.r, - scale = self.T.scale - } - - --To determine location of VT, we need to keep track of the velocity of VT as it approaches T for the next frame - self.velocity = {x = 0, y = 0, r = 0, scale = 0, mag = 0} - - --For more robust drawing, attaching, movement and fewer redundant movement calculations, Moveables each have a 'role' - --that describes a heirarchy of move() calls. Any Moveables with 'Major' role type behave normally, essentially recalculating their - --VT every frame to ensure smooth movement. Moveables can be set to 'Minor' role and attached to some 'Major' moveable - --to weld the Minor moveable to the Major moveable. This makes the dependent moveable set their T and VT to be equal to - --the corresponding 'Major' T and VT, plus some defined offset. - --For finer control over what parts of T and VT are inherited, xy_bond, wh_bond, and r_bond can be set to one of - --'Strong' or 'Weak'. Strong simply copies the values, Weak allows the 'Minor' moveable to calculate their own. - self.role = { - role_type = 'Major', --Major dictates movement, Minor is welded to some major - offset = {x = 0, y = 0}, --Offset from Minor to Major - major = nil, - draw_major = self, - xy_bond = 'Strong', - wh_bond = 'Strong', - r_bond = 'Strong', - scale_bond = 'Strong' - } - - self.alignment = { - type = 'a', - offset = {x = 0, y = 0}, - prev_type = '', - prev_offset = {x = 0, y = 0}, - } - - --the pinch table is used to modify the VT.w and VT.h compared to T.w and T.h. If either x or y pinch is - --set to true, the VT width and or height will ease to 0. If pinch is false, they ease to T.w or T.h - self.pinch = {x = false, y = false} - - --Keep track of the last time this Moveable was moved via :move(dt). When it is successfully moved, set to equal - --the current G.TIMERS.REAL, and if it is called again this frame, doesn't recalculate move(dt) - self.last_moved = -1 - self.last_aligned = -1 - - self.static_rotation = false - - self.offset = {x=0, y=0} - self.Mid = self - - self.shadow_parrallax = {x = 0, y = -1.5} - self.layered_parallax = {x = 0, y = 0} - self.shadow_height = 0.2 - - self:calculate_parrallax() - - table.insert(G.MOVEABLES, self) - if getmetatable(self) == Moveable then - table.insert(G.I.MOVEABLE, self) - end -end -function Moveable:draw() - Node.draw(self) - self:draw_boundingrect() -end - ---Sets the alignment of moveable using roles --- ----@param args {major: Moveable, bond: string, offset: table, type: string} ---**major** The moveable this moveable will attach to\ ---**bond** The bond type, either 'Strong' or 'Weak'. Strong instantly adjusts VT, Weak manually calculates VT changes\ ---**offset** {x , y} offset from the alignment\ ---**type** the alignment type. Vertical options: c - center, t - top, b - bottom. Horizontal options: l - left, m - middle, r - right. i for inner -function Moveable:set_alignment(args) - args = args or {} - if args.major then - self:set_role({ - role_type = 'Minor', - major = args.major, - xy_bond = args.bond or args.xy_bond or 'Weak', - wh_bond = args.wh_bond or self.role.wh_bond, - r_bond = args.r_bond or self.role.r_bond, - scale_bond = args.scale_bond or self.role.scale_bond, - }) - end - self.alignment.type = args.type or self.alignment.type - if args.offset and (type(args.offset)=='table' and not (args.offset.y and args.offset.x)) or type(args.offset) ~= 'table' then - args.offset = nil - end - self.alignment.offset = args.offset or self.alignment.offset - self.alignment.lr_clamp = args.lr_clamp -end - -function Moveable:align_to_major() - if self.alignment.type ~= self.alignment.prev_type then - self.alignment.type_list = { - a = self.alignment.type == 'a', - m = string.find(self.alignment.type, "m"), - c = string.find(self.alignment.type, "c"), - b = string.find(self.alignment.type, "b"), - t = string.find(self.alignment.type, "t"), - l = string.find(self.alignment.type, "l"), - r = string.find(self.alignment.type, "r"), - i = string.find(self.alignment.type, "i"), - } - end - - if not self.alignment.type_list then return end - self.NEW_ALIGNMENT = true - - if self.alignment.type ~= self.alignment.prev_type then - self.alignment.prev_type = self.alignment.type - end - - if self.alignment.type_list.a or not self.role.major then return end - - if self.alignment.type_list.m then - self.role.offset.x = 0.5*self.role.major.T.w - (self.Mid.T.w)/2 + self.alignment.offset.x - self.Mid.T.x + self.T.x - end - - if self.alignment.type_list.c then - self.role.offset.y = 0.5*self.role.major.T.h - (self.Mid.T.h)/2 + self.alignment.offset.y - self.Mid.T.y + self.T.y - end - - if self.alignment.type_list.b then - if self.alignment.type_list.i then - self.role.offset.y = self.alignment.offset.y + self.role.major.T.h - self.T.h - else - self.role.offset.y = self.alignment.offset.y + self.role.major.T.h - end - end - - if self.alignment.type_list.r then - if self.alignment.type_list.i then - self.role.offset.x = self.alignment.offset.x + self.role.major.T.w - self.T.w - else - self.role.offset.x = self.alignment.offset.x + self.role.major.T.w - end - end - - if self.alignment.type_list.t then - if self.alignment.type_list.i then - self.role.offset.y = self.alignment.offset.y - else - self.role.offset.y = self.alignment.offset.y - self.T.h - end - end - - if self.alignment.type_list.l then - if self.alignment.type_list.i then - self.role.offset.x = self.alignment.offset.x - else - self.role.offset.x = self.alignment.offset.x - self.T.w - end - end - - self.role.offset.x = self.role.offset.x or 0 - self.role.offset.y = self.role.offset.y or 0 - - self.T.x = self.role.major.T.x + self.role.offset.x - self.T.y = self.role.major.T.y + self.role.offset.y - - self.alignment.prev_offset = self.alignment.prev_offset or {} - self.alignment.prev_offset.x, self.alignment.prev_offset.y = self.alignment.offset.x, self.alignment.offset.y -end - -function Moveable:hard_set_T(X, Y, W, H) - self.T.x = X - self.T.y = Y - self.T.w = W - self.T.h = H - - self.velocity.x = 0 - self.velocity.y = 0 - self.velocity.r = 0 - self.velocity.scale = 0 - - self.VT.x = X - self.VT.y = Y - self.VT.w = W - self.VT.h = H - self.VT.r = self.T.r - self.VT.scale = self.T.scale - self:calculate_parrallax() -end - -function Moveable:hard_set_VT() - self.VT.x = self.T.x - self.VT.y = self.T.y - self.VT.w = self.T.w - self.VT.h = self.T.h -end - -function Moveable:drag(offset) - if self.states.drag.can or offset then - self.ARGS.drag_cursor_trans = self.ARGS.drag_cursor_trans or {} - self.ARGS.drag_translation = self.ARGS.drag_translation or {} - local _p = self.ARGS.drag_cursor_trans - local _t = self.ARGS.drag_translation - _p.x = G.CONTROLLER.cursor_position.x/(G.TILESCALE*G.TILESIZE) - _p.y = G.CONTROLLER.cursor_position.y/(G.TILESCALE*G.TILESIZE) - - _t.x, _t.y = -self.container.T.w/2, -self.container.T.h/2 - point_translate(_p, _t) - - point_rotate(_p, self.container.T.r) - - _t.x, _t.y = self.container.T.w/2-self.container.T.x, self.container.T.h/2-self.container.T.y - point_translate(_p, _t) - - if not offset then - offset = self.click_offset - end - - self.T.x = _p.x - offset.x - self.T.y = _p.y - offset.y - self.NEW_ALIGNMENT = true - for k, v in pairs(self.children) do - v:drag(offset) - end - end - if self.states.drag.can then - Node.drag(self) - end -end - -function Moveable:juice_up(amount, rot_amt) - if G.SETTINGS.reduced_motion then return end - local amount = amount or 0.4 - - local end_time = G.TIMERS.REAL + 0.4 - local start_time = G.TIMERS.REAL - self.juice = { - scale = 0, - scale_amt = amount, - r = 0, - r_amt = ((rot_amt or pseudorandom_element({0.6*amount, -0.6*amount})) or 0), - start_time = start_time, - end_time = end_time - } - self.VT.scale = 1-0.6*amount -end - -function Moveable:move_juice(dt) - if self.juice and not self.juice.handled_elsewhere then - if self.juice.end_time < G.TIMERS.REAL then - self.juice = nil - else - self.juice.scale = self.juice.scale_amt*math.sin(50.8*(G.TIMERS.REAL-self.juice.start_time))*math.max(0, ((self.juice.end_time - G.TIMERS.REAL)/(self.juice.end_time - self.juice.start_time))^3) - self.juice.r = self.juice.r_amt*math.sin(40.8*(G.TIMERS.REAL-self.juice.start_time))*math.max(0, ((self.juice.end_time - G.TIMERS.REAL)/(self.juice.end_time - self.juice.start_time))^2) - end - end -end - -function Moveable:move(dt) - if self.FRAME.MOVE >= G.FRAMES.MOVE then return end - self.FRAME.OLD_MAJOR = self.FRAME.MAJOR - self.FRAME.MAJOR = nil - self.FRAME.MOVE = G.FRAMES.MOVE - if not self.created_on_pause and G.SETTINGS.paused then return end - - --WHY ON EARTH DOES THIS LINE MAKE IT RUN 2X AS FAST??? - ------------------------------------------------------- - --local timestart = love.timer.getTime() - ------------------------------------------------------- - - self:align_to_major() - - self.CALCING = nil - if self.role.role_type == 'Glued' then - if self.role.major then self:glue_to_major(self.role.major) end - elseif self.role.role_type == 'Minor' and self.role.major then - if self.role.major.FRAME.MOVE < G.FRAMES.MOVE then self.role.major:move(dt) end - self.STATIONARY = self.role.major.STATIONARY - if (not self.STATIONARY) or self.NEW_ALIGNMENT or - self.config.refresh_movement or - self.juice or - self.role.xy_bond == 'Weak' or - self.role.r_bond == 'Weak' then - self.CALCING = true - self:move_with_major(dt) - end - elseif self.role.role_type == 'Major' then - self.STATIONARY = true - self:move_juice(dt) - self:move_xy(dt) - self:move_r(dt, self.velocity) - self:move_scale(dt) - self:move_wh(dt) - self:calculate_parrallax() - end - if self.alignment and self.alignment.lr_clamp then - self:lr_clamp() - end - - self.NEW_ALIGNMENT = false -end - -function Moveable:lr_clamp() - if self.T.x < 0 then self.T.x = 0 end - if self.VT.x < 0 then self.VT.x = 0 end - if (self.T.x + self.T.w) > G.ROOM.T.w then self.T.x = G.ROOM.T.w - self.T.w end - if (self.VT.x + self.VT.w) > G.ROOM.T.w then self.VT.x = G.ROOM.T.w - self.VT.w end -end - -function Moveable:glue_to_major(major_tab) - self.T = major_tab.T - - self.VT.x = major_tab.VT.x + (0.5*(1 - major_tab.VT.w/(major_tab.T.w))*self.T.w) - self.VT.y = major_tab.VT.y - self.VT.w = major_tab.VT.w - self.VT.h = major_tab.VT.h - self.VT.r = major_tab.VT.r - self.VT.scale = major_tab.VT.scale - - self.pinch = major_tab.pinch - self.shadow_parrallax = major_tab.shadow_parrallax -end - -MWM = { - rotated_offset = {}, - angles = {}, - WH = {}, - offs = {}, -} - -function Moveable:move_with_major(dt) - if self.role.role_type ~= 'Minor' then return end - local major_tab = self.role.major:get_major() - - self:move_juice(dt) - - if self.role.r_bond == 'Weak' then - MWM.rotated_offset.x, MWM.rotated_offset.y = self.role.offset.x + major_tab.offset.x,self.role.offset.y+major_tab.offset.y - else - if major_tab.major.VT.r < 0.0001 and major_tab.major.VT.r > -0.0001 then - MWM.rotated_offset.x = self.role.offset.x + major_tab.offset.x - MWM.rotated_offset.y = self.role.offset.y + major_tab.offset.y - else - MWM.angles.cos, MWM.angles.sin = math.cos(major_tab.major.VT.r),math.sin(major_tab.major.VT.r) - MWM.WH.w, MWM.WH.h = -self.T.w/2 + major_tab.major.T.w/2,-self.T.h/2 + major_tab.major.T.h/2 - MWM.offs.x, MWM.offs.y = self.role.offset.x + major_tab.offset.x - MWM.WH.w,self.role.offset.y + major_tab.offset.y - MWM.WH.h - - MWM.rotated_offset.x = MWM.offs.x*MWM.angles.cos - MWM.offs.y*MWM.angles.sin + MWM.WH.w - MWM.rotated_offset.y = MWM.offs.x*MWM.angles.sin + MWM.offs.y*MWM.angles.cos + MWM.WH.h - end - end - - self.T.x = major_tab.major.T.x + MWM.rotated_offset.x - self.T.y = major_tab.major.T.y + MWM.rotated_offset.y - - if self.role.xy_bond == 'Strong' then - self.VT.x = major_tab.major.VT.x + MWM.rotated_offset.x - self.VT.y = major_tab.major.VT.y + MWM.rotated_offset.y - elseif self.role.xy_bond == 'Weak' then - self:move_xy(dt) - end - - if self.role.r_bond == 'Strong' then - self.VT.r = self.T.r + major_tab.major.VT.r + (self.juice and self.juice.r or 0) - elseif self.role.r_bond == 'Weak' then - self:move_r(dt, self.velocity) - end - - if self.role.scale_bond == 'Strong' then - self.VT.scale = self.T.scale*(major_tab.major.VT.scale/major_tab.major.T.scale) + (self.juice and self.juice.scale or 0) - elseif self.role.scale_bond == 'Weak' then - self:move_scale(dt) - end - - if self.role.wh_bond == 'Strong' then - self.VT.x = self.VT.x + (0.5*(1 - major_tab.major.VT.w/(major_tab.major.T.w))*self.T.w) - self.VT.w = (self.T.w)*(major_tab.major.VT.w/major_tab.major.T.w) - self.VT.h = (self.T.h)*(major_tab.major.VT.h/major_tab.major.T.h) - elseif self.role.wh_bond == 'Weak' then - self:move_wh(dt) - end - - self:calculate_parrallax() -end - -function Moveable:move_xy(dt) - if (self.T.x ~= self.VT.x or math.abs(self.velocity.x) > 0.01) or - (self.T.y ~= self.VT.y or math.abs(self.velocity.y) > 0.01) then - self.velocity.x = G.exp_times.xy*self.velocity.x + (1-G.exp_times.xy)*(self.T.x - self.VT.x)*35*dt - self.velocity.y = G.exp_times.xy*self.velocity.y + (1-G.exp_times.xy)*(self.T.y - self.VT.y)*35*dt - if self.velocity.x*self.velocity.x + self.velocity.y*self.velocity.y > G.exp_times.max_vel*G.exp_times.max_vel then - local actual_vel = math.sqrt(self.velocity.x*self.velocity.x + self.velocity.y*self.velocity.y) - self.velocity.x = G.exp_times.max_vel*self.velocity.x/actual_vel - self.velocity.y = G.exp_times.max_vel*self.velocity.y/actual_vel - end - self.STATIONARY = false - self.VT.x = self.VT.x + self.velocity.x - self.VT.y = self.VT.y + self.velocity.y - if math.abs(self.VT.x - self.T.x) < 0.01 and math.abs(self.velocity.x) < 0.01 then self.VT.x = self.T.x; self.velocity.x = 0 end - if math.abs(self.VT.y - self.T.y) < 0.01 and math.abs(self.velocity.y) < 0.01 then self.VT.y = self.T.y; self.velocity.y = 0 end - end -end - -function Moveable:move_scale(dt) - local des_scale = self.T.scale + (self.zoom and ((self.states.drag.is and 0.1 or 0) + (self.states.hover.is and 0.05 or 0)) or 0) + (self.juice and self.juice.scale or 0) - - if des_scale ~= self.VT.scale or - math.abs(self.velocity.scale) > 0.001 then - self.STATIONARY = false - self.velocity.scale = G.exp_times.scale*self.velocity.scale + (1-G.exp_times.scale)*(des_scale - self.VT.scale) - self.VT.scale = self.VT.scale + self.velocity.scale - end -end - -function Moveable:move_wh(dt) -if Big and G.STATE == G.STATES.MENU then self.T.w = to_big(self.T.w):to_number() -self.T.h = to_big(self.T.h):to_number() -self.VT.w = to_big(self.VT.w):to_number() -self.VT.h = to_big(self.VT.h):to_number() end - if (self.T.w ~= self.VT.w and not self.pinch.x) or - (self.T.h ~= self.VT.h and not self.pinch.y) or - (self.VT.w > 0 and self.pinch.x) or - (self.VT.h > 0 and self.pinch.y) then - self.STATIONARY = false - self.VT.w = self.VT.w + (8*dt)*(self.pinch.x and -1 or 1)*self.T.w - self.VT.h = self.VT.h + (8*dt)*(self.pinch.y and -1 or 1)*self.T.h - self.VT.w = math.max(math.min(self.VT.w, self.T.w), 0) - self.VT.h = math.max(math.min(self.VT.h, self.T.h), 0) - end -end - -function Moveable:move_r(dt, vel) - local des_r = self.T.r +0.015*vel.x/dt + (self.juice and self.juice.r*2 or 0) - - if des_r ~= self.VT.r or - math.abs(self.velocity.r) > 0.001 then - self.STATIONARY = false - self.velocity.r = G.exp_times.r*self.velocity.r + (1-G.exp_times.r)*(des_r - self.VT.r) - self.VT.r = self.VT.r + self.velocity.r - end - if math.abs(self.VT.r - self.T.r) < 0.001 and math.abs(self.velocity.r) < 0.001 then self.VT.r = self.T.r; self.velocity.r = 0 end -end - -function Moveable:calculate_parrallax() - if not G.ROOM then return end - self.shadow_parrallax.x = (self.T.x + self.T.w/2 - G.ROOM.T.w/2)/(G.ROOM.T.w/2)*1.5 -end - -function Moveable:set_role(args) - if args.major and not args.major.set_role then return end - if args.offset and (type(args.offset)=='table' and not (args.offset.y and args.offset.x)) or type(args.offset) ~= 'table' then - args.offset = nil - end - self.role = { - role_type = args.role_type or self.role.role_type, - offset = args.offset or self.role.offset, - major = args.major or self.role.major, - xy_bond = args.xy_bond or self.role.xy_bond, - wh_bond = args.wh_bond or self.role.wh_bond, - r_bond = args.r_bond or self.role.r_bond, - scale_bond = args.scale_bond or self.role.scale_bond, - draw_major = args.draw_major or self.role.draw_major, - } - if self.role.role_type == 'Major' then self.role.major = nil end -end - -function Moveable:get_major() - if ( self.role.role_type ~= 'Major' and self.role.major ~= self) and (self.role.xy_bond ~= 'Weak' and self.role.r_bond ~= 'Weak') then - --First, does the major already have their offset precalculated for this frame? - if not self.FRAME.MAJOR or (G.REFRESH_FRAME_MAJOR_CACHE) then - self.FRAME.MAJOR = self.FRAME.MAJOR or EMPTY(self.FRAME.OLD_MAJOR) - self.temp_offs = EMPTY(self.temp_offs) - local major = self.role.major:get_major() - self.FRAME.MAJOR.major = major.major - self.FRAME.MAJOR.offset = self.FRAME.MAJOR.offset or self.temp_offs - self.FRAME.MAJOR.offset.x, self.FRAME.MAJOR.offset.y = major.offset.x + self.role.offset.x + self.layered_parallax.x, major.offset.y + self.role.offset.y + self.layered_parallax.y - end - return self.FRAME.MAJOR - else - self.ARGS.get_major = self.ARGS.get_major or {} - self.ARGS.get_major.major = self - self.ARGS.get_major.offset = self.ARGS.get_major.offset or {} - self.ARGS.get_major.offset.x, self.ARGS.get_major.offset.y = 0,0 - return self.ARGS.get_major - end -end - -function Moveable:remove() - for k, v in pairs(G.MOVEABLES) do - if v == self then - table.remove(G.MOVEABLES, k) - break; - end - end - for k, v in pairs(G.I.MOVEABLE) do - if v == self then - table.remove(G.I.MOVEABLE, k) - break; - end - end - Node.remove(self) -end diff --git a/lovely/dump/engine/sound_manager.lua b/lovely/dump/engine/sound_manager.lua deleted file mode 100644 index 9447dcc..0000000 --- a/lovely/dump/engine/sound_manager.lua +++ /dev/null @@ -1,222 +0,0 @@ -LOVELY_INTEGRITY = 'a89ca7b9273fee523938c932a6467dfa383c8e44b527c8da74869b0ae75efe92' - -require "love.audio" -require "love.sound" -require "love.system" - -if (love.system.getOS() == 'OS X' )and (jit.arch == 'arm64' or jit.arch == 'arm') then jit.off() end - ---vars needed for sound manager thread -CHANNEL = love.thread.getChannel("sound_request") -LOAD_CHANNEL = love.thread.getChannel('load_channel') -LOAD_CHANNEL:push('audio thread start') -DISABLE_SFX = false -SMODS_Sounds = {} - ---create all sounds from resources and play one each to load into mem -SOURCES = {} -local sound_files = love.filesystem.getDirectoryItems("resources/sounds") - -for _, filename in ipairs(sound_files) do - local extension = string.sub(filename, -4) - for i = 1, 1 do - if extension == '.ogg' then - LOAD_CHANNEL:push('audio file - '..filename) - local sound_code = string.sub(filename, 1, -5) - local s = { - sound = love.audio.newSource("resources/sounds/"..filename,string.find(sound_code,'music') and "stream" or 'static'), - filepath = "resources/sounds/"..filename - } - SOURCES[sound_code] = {} - table.insert(SOURCES[sound_code], s) - s.sound_code = sound_code - s.sound:setVolume(0) - love.audio.play(s.sound) - s.sound:stop() - end - end -end - -function PLAY_SOUND(args) - args.per = args.per or 1 - args.vol = args.vol or 1 - SOURCES[args.sound_code] = SOURCES[args.sound_code] or {} - - for _, s in ipairs(SOURCES[args.sound_code]) do - if s.sound and not s.sound:isPlaying() then - s.original_pitch = args.per - s.original_volume = args.vol - s.created_on_pause = args.overlay_menu - s.created_on_state = args.state - s.sfx_handled = 0 - s.transition_timer = 0 - SET_SFX(s, args) - love.audio.play(s.sound) - return s - end - end - - local should_stream = (string.find(args.sound_code,'music') or string.find(args.sound_code,'ambient')) - local c = SMODS_Sounds[args.sound_code] - local s = c and - {sound = love.audio.newSource(love.sound.newDecoder(c.data), c.should_stream and 'stream' or 'static'), per = c.per, vol = c.vol } or - {sound = love.audio.newSource("resources/sounds/"..args.sound_code..'.ogg', should_stream and "stream" or 'static')} - table.insert(SOURCES[args.sound_code], s) - s.sound_code = args.sound_code - s.original_pitch = ((args.type ~= "sound") and s.per) or args.per or 1 - s.original_volume = ((args.type ~= "sound") and s.vol) or args.vol or 1 - s.created_on_pause = (args.overlay_menu and true or false) - s.created_on_state = args.state - s.sfx_handled = 0 - s.transition_timer = 0 - SET_SFX(s, args) - love.audio.play(s.sound) - return s -end - -function STOP_AUDIO() - for _, source in pairs(SOURCES) do - for _, s in pairs(source) do - if s.sound:isPlaying() then - s.sound:stop() - end - end - end -end - -function SET_SFX(s, args) - if string.find(s.sound_code,'music') then - if s.sound_code == args.desired_track then - s.current_volume = s.current_volume or 1 - s.current_volume = 1*(args.dt*3) + (1-(args.dt*3))*s.current_volume - else - s.current_volume = s.current_volume or 0 - s.current_volume = 0*(args.dt*3) + (1-(args.dt*3))*s.current_volume - end - s.sound:setVolume(s.current_volume*s.original_volume*(args.sound_settings.volume/100.0)*(args.sound_settings.music_volume/100.0)) - s.sound:setPitch(s.original_pitch*args.pitch_mod) - else - if s.temp_pitch ~= s.original_pitch then - s.sound:setPitch(s.original_pitch) - s.temp_pitch = s.original_pitch - end - local sound_vol = s.original_volume*(args.sound_settings.volume/100.0)*(args.sound_settings.game_sounds_volume/100.0) - if s.created_on_state == 13 then sound_vol = sound_vol*args.splash_vol end - if sound_vol <= 0 then - s.sound:stop() - else - s.sound:setVolume(sound_vol) - end - end - end - - function MODULATE(args) - if args.desired_track ~= '' then - local sound = ((SOURCES[current_track or {}] or {})[1] or {}).sound - if not sound or not sound:isPlaying() then - RESTART_MUSIC(args) - end - end - - for k, v in pairs(SOURCES) do - local i=1 - while i <= #v do - if not v[i].sound:isPlaying() then - v[i].sound:release() - table.remove(v, i) - else - i = i + 1 - end - end - - current_track = args.desired_track - for _, s in pairs(v) do - if s.sound and s.sound:isPlaying() and s.original_volume then - SET_SFX(s, args) - end - end - end - end - - function RESTART_MUSIC(args) - for k, v in pairs(SOURCES) do - if string.find(k,'music') then - for i, s in ipairs(v) do - s.sound:stop() - end - SOURCES[k] = {} - args.per = 0.7 - args.vol = 0.6 - args.sound_code = k - local s = PLAY_SOUND(args) - s.initialized = true - end - end - end - - function AMBIENT(args) - for k, v in pairs(SOURCES) do - if args.ambient_control[k] then - local start_ambient = args.ambient_control[k].vol*(args.sound_settings.volume/100.0)*(args.sound_settings.game_sounds_volume/100.0) > 0 - - for i, s in ipairs(v) do - if s.sound and s.sound:isPlaying() and s.original_volume then - s.original_volume = args.ambient_control[k].vol - SET_SFX(s, args) - start_ambient = false - end - end - - if start_ambient then - args.sound_code = k - args.vol = args.ambient_control[k].vol - args.per = args.ambient_control[k].per - PLAY_SOUND(args) - end - end - end - end - - function RESET_STATES(state) - for k, v in pairs(SOURCES) do - for i, s in ipairs(v) do - s.created_on_state = state - end - end - end - - LOAD_CHANNEL:push('finished') - - while true do - --Monitor the channel for any new requests - local request = CHANNEL:demand() -- Value from channel - if request then - if request.type == 'kill' then return end - --If the request is for an update to the music track, handle it here - if false then elseif request.type == 'sound' then - PLAY_SOUND(request) - elseif request.type == 'sound_source' then - SMODS_Sounds[request.sound_code] = { - sound_code = request.sound_code, - data = request.data, - sound = sound, - per = request.per, - vol = request.vol, - } - SOURCES[request.sound_code] = {} - elseif request.type == 'stop' then - STOP_AUDIO() - elseif request.type == 'modulate' then - MODULATE(request) - if request.ambient_control then AMBIENT(request) end - elseif request.type == 'restart_music' then - RESTART_MUSIC(request) - elseif request.type == 'reset_states' then - for k, v in pairs(SOURCES) do - for i, s in ipairs(v) do - s.created_on_state = request.state - end - end - end - end -end diff --git a/lovely/dump/engine/sprite.lua b/lovely/dump/engine/sprite.lua deleted file mode 100644 index 5d2878c..0000000 --- a/lovely/dump/engine/sprite.lua +++ /dev/null @@ -1,232 +0,0 @@ -LOVELY_INTEGRITY = '3d0395906e098682391897a81b05df12cd2dc6e39322ebd87a281c6c9d1caebc' - ---Class -Sprite = Moveable:extend() - ---Class Methods -function Sprite:init(X, Y, W, H, new_sprite_atlas, sprite_pos) - Moveable.init(self,X, Y, W, H) - self.CT = self.VT - self.atlas = new_sprite_atlas - self.scale = {x=self.atlas.px, y=self.atlas.py} - self.scale_mag = math.min(self.scale.x/W,self.scale.y/H) - self.zoom = true - - self:set_sprite_pos(sprite_pos) - - if getmetatable(self) == Sprite then - table.insert(G.I.SPRITE, self) - end -end - -function Sprite:reset() - self.atlas = G.ASSET_ATLAS[self.atlas.name] - self:set_sprite_pos(self.sprite_pos) -end - -function Sprite:set_sprite_pos(sprite_pos) - if sprite_pos and sprite_pos.v then - self.sprite_pos = {x = (math.random(sprite_pos.v)-1), y = sprite_pos.y} - else - self.sprite_pos = sprite_pos or {x=0,y=0} - end - self.sprite_pos_copy = {x = self.sprite_pos.x, y = self.sprite_pos.y} - - self.sprite = love.graphics.newQuad( - self.sprite_pos.x*self.atlas.px, - self.sprite_pos.y*self.atlas.py, - self.scale.x, - self.scale.y, self.atlas.image:getDimensions()) - - self.image_dims = {} - self.image_dims[1], self.image_dims[2] = self.atlas.image:getDimensions() -end - -function Sprite:get_pos_pixel() - self.RETS.get_pos_pixel = self.RETS.get_pos_pixel or {} - self.RETS.get_pos_pixel[1] = self.sprite_pos.x - self.RETS.get_pos_pixel[2] = self.sprite_pos.y - self.RETS.get_pos_pixel[3] = self.atlas.px --self.scale.x - self.RETS.get_pos_pixel[4] = self.atlas.py --self.scale.y - return self.RETS.get_pos_pixel -end - -function Sprite:get_image_dims() - return self.image_dims -end - -function Sprite:define_draw_steps(draw_step_definitions) - self.draw_steps = EMPTY(self.draw_steps) - for k, v in ipairs(draw_step_definitions) do - self.draw_steps[#self.draw_steps+1] = { - shader = v.shader or 'dissolve', - shadow_height = v.shadow_height or nil, - send = v.send or nil, - no_tilt = v.no_tilt or nil, - other_obj = v.other_obj or nil, - ms = v.ms or nil, - mr = v.mr or nil, - mx = v.mx or nil, - my = v.my or nil - } - end -end - -function Sprite:draw_shader(_shader, _shadow_height, _send, _no_tilt, other_obj, ms, mr, mx, my, custom_shader, tilt_shadow) - if G.SETTINGS.reduced_motion then _no_tilt = true end - local _draw_major = self.role.draw_major or self - if _shadow_height then - self.VT.y = self.VT.y - _draw_major.shadow_parrallax.y*_shadow_height - self.VT.x = self.VT.x - _draw_major.shadow_parrallax.x*_shadow_height - self.VT.scale = self.VT.scale*(1-0.2*_shadow_height) - end - - if custom_shader then - if _send then - for k, v in ipairs(_send) do - G.SHADERS[_shader]:send(v.name, v.val or (v.func and v.func()) or v.ref_table[v.ref_value]) - end - end - elseif _shader == 'vortex' then - G.SHADERS['vortex']:send('vortex_amt', G.TIMERS.REAL - (G.vortex_time or 0)) - else - self.ARGS.prep_shader = self.ARGS.prep_shader or {} - self.ARGS.prep_shader.cursor_pos = self.ARGS.prep_shader.cursor_pos or {} - self.ARGS.prep_shader.cursor_pos[1] = _draw_major.tilt_var and _draw_major.tilt_var.mx*G.CANV_SCALE or G.CONTROLLER.cursor_position.x*G.CANV_SCALE - self.ARGS.prep_shader.cursor_pos[2] = _draw_major.tilt_var and _draw_major.tilt_var.my*G.CANV_SCALE or G.CONTROLLER.cursor_position.y*G.CANV_SCALE - - G.SHADERS[_shader or 'dissolve']:send('mouse_screen_pos', self.ARGS.prep_shader.cursor_pos) - G.SHADERS[_shader or 'dissolve']:send('screen_scale', G.TILESCALE*G.TILESIZE*(_draw_major.mouse_damping or 1)*G.CANV_SCALE) - G.SHADERS[_shader or 'dissolve']:send('hovering',((_shadow_height and not tilt_shadow) or _no_tilt) and 0 or (_draw_major.hover_tilt or 0)*(tilt_shadow or 1)) - G.SHADERS[_shader or 'dissolve']:send("dissolve",math.abs(_draw_major.dissolve or 0)) - G.SHADERS[_shader or 'dissolve']:send("time",123.33412*(_draw_major.ID/1.14212 or 12.5123152)%3000) - G.SHADERS[_shader or 'dissolve']:send("texture_details",self:get_pos_pixel()) - G.SHADERS[_shader or 'dissolve']:send("image_details",self:get_image_dims()) - G.SHADERS[_shader or 'dissolve']:send("burn_colour_1",_draw_major.dissolve_colours and _draw_major.dissolve_colours[1] or G.C.CLEAR) - G.SHADERS[_shader or 'dissolve']:send("burn_colour_2",_draw_major.dissolve_colours and _draw_major.dissolve_colours[2] or G.C.CLEAR) - G.SHADERS[_shader or 'dissolve']:send("shadow",(not not _shadow_height)) - if _send then - G.SHADERS[_shader or 'dissolve']:send((SMODS.Shaders[_shader or 'dissolve'] and SMODS.Shaders[_shader or 'dissolve'].original_key) or _shader,_send) - end - end - - local p_shader = SMODS.Shader.obj_table[_shader or 'dissolve'] - if p_shader and type(p_shader.send_vars) == "function" then - local sh = G.SHADERS[_shader or 'dissolve'] - local parent_card = self.role.major and self.role.major:is(Card) and self.role.major - local send_vars = p_shader.send_vars(self, parent_card) - - if type(send_vars) == "table" then - for key, value in pairs(send_vars) do - sh:send(key, value) - end - end - end - love.graphics.setShader( G.SHADERS[_shader or 'dissolve'], G.SHADERS[_shader or 'dissolve']) - - if other_obj then - self:draw_from(other_obj, ms, mr, mx, my) - else - self:draw_self() - end - - love.graphics.setShader() - - if _shadow_height then - self.VT.y = self.VT.y + _draw_major.shadow_parrallax.y*_shadow_height - self.VT.x = self.VT.x + _draw_major.shadow_parrallax.x*_shadow_height - self.VT.scale = self.VT.scale/(1-0.2*_shadow_height) - end -end - -function Sprite:draw_self(overlay) - if not self.states.visible then return end - if self.sprite_pos.x ~= self.sprite_pos_copy.x or self.sprite_pos.y ~= self.sprite_pos_copy.y then - self:set_sprite_pos(self.sprite_pos) - end - prep_draw(self, 1) - love.graphics.scale(1/(self.scale.x/self.VT.w), 1/(self.scale.y/self.VT.h)) - love.graphics.setColor(overlay or G.BRUTE_OVERLAY or G.C.WHITE) - if self.video then - self.video_dims = self.video_dims or { - w = self.video:getWidth(), - h = self.video:getHeight(), - } - love.graphics.draw( - self.video, - 0 ,0, - 0, - self.VT.w/(self.T.w)/(self.video_dims.w/self.scale.x), - self.VT.h/(self.T.h)/(self.video_dims.h/self.scale.y) - ) - else - love.graphics.draw( - self.atlas.image, - self.sprite, - 0 ,0, - 0, - self.VT.w/(self.T.w), - self.VT.h/(self.T.h) - ) - end - love.graphics.pop() - add_to_drawhash(self) - self:draw_boundingrect() - if self.shader_tab then love.graphics.setShader() end -end - -function Sprite:draw(overlay) - if not self.states.visible then return end - if self.draw_steps then - for k, v in ipairs(self.draw_steps) do - self:draw_shader(v.shader, v.shadow_height, v.send, v.no_tilt, v.other_obj, v.ms, v.mr, v.mx, v.my, not not v.send) - end - else - self:draw_self(overlay) - end - - add_to_drawhash(self) - for k, v in pairs(self.children) do - if k ~= 'h_popup' then v:draw() end - end - add_to_drawhash(self) - self:draw_boundingrect() -end - -function Sprite:draw_from(other_obj, ms, mr, mx, my) - self.ARGS.draw_from_offset = self.ARGS.draw_from_offset or {} - self.ARGS.draw_from_offset.x = mx or 0 - self.ARGS.draw_from_offset.y = my or 0 - prep_draw(other_obj, (1 + (ms or 0)), (mr or 0), self.ARGS.draw_from_offset, true) - love.graphics.scale(1/(other_obj.scale_mag or other_obj.VT.scale)) - love.graphics.setColor(G.BRUTE_OVERLAY or G.C.WHITE) - love.graphics.draw( - self.atlas.image, - self.sprite, - -(other_obj.T.w/2 -other_obj.VT.w/2)*10, - 0, - 0, - other_obj.VT.w/(other_obj.T.w), - other_obj.VT.h/(other_obj.T.h) - ) - self:draw_boundingrect() - love.graphics.pop() -end - -function Sprite:remove() - if self.video then - self.video:release() - end - for k, v in pairs(G.ANIMATIONS) do - if v == self then - table.remove(G.ANIMATIONS, k) - end - end - for k, v in pairs(G.I.SPRITE) do - if v == self then - table.remove(G.I.SPRITE, k) - end - end - - Moveable.remove(self) -end diff --git a/lovely/dump/engine/string_packer.lua b/lovely/dump/engine/string_packer.lua deleted file mode 100644 index 2197a9b..0000000 --- a/lovely/dump/engine/string_packer.lua +++ /dev/null @@ -1,83 +0,0 @@ -LOVELY_INTEGRITY = '5d0771786fa792673ea7fd08a5f7ef9bfec9d89cc6a2d2f4ee8e7ff3faee05ec' - ---[[ -MIT License -Copyright (c) 2017 Robert Herlihy -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] - ---I modified this A LOT. Needed to make it quicker if it is being saved to file every few seconds during a game -function STR_PACK(data, recursive) - local ret_str = (recursive and "" or "return ").."{" - - for i, v in pairs(data) do - local type_i, type_v = type(i), type(v) - assert((type_i ~= "table"), "Data table cannot have an table as a key reference") - if type_i == "string" then - i = '['..string.format("%q",i)..']' - else - i = "["..i.."]" - end - if type_v == "table" then - if v.m and v.e then - v = "to_big("..v.m..","..v.e..")" - elseif v.array and v.sign then - local v0 = "to_big({" - for qi = 1,#v.array do - v0 = v0 .. v.array[qi] .. ", " - end - v0 = v0 .. "},"..v.sign..")" - v = v0 - elseif v.is and v:is(Object) then - v = [["]].."MANUAL_REPLACE"..[["]] - else - v = STR_PACK(v, true) - end - else - if type_v == "string" then v = string.format("%q", v) end - if type_v == "boolean" then v = v and "true" or "false" end - end - ret_str = ret_str..i.."="..v.."," - end - - return ret_str.."}" -end - -function STR_UNPACK(str) - return assert(loadstring(str))() -end - -function get_compressed(_file) - local file_data = love.filesystem.getInfo(_file) - if file_data ~= nil then - local file_string = love.filesystem.read(_file) - if file_string ~= '' then - if string.sub(file_string, 1, 6) ~= 'return' then - local success = nil - success, file_string = pcall(love.data.decompress, 'string', 'deflate', file_string) - if not success then return nil end - end - return file_string - end - end -end - -function compress_and_save(_file, _data) - local save_string = type(_data) == 'table' and STR_PACK(_data) or _data - save_string = love.data.compress('string', 'deflate', save_string, 1) - love.filesystem.write(_file,save_string) -end diff --git a/lovely/dump/engine/text.lua b/lovely/dump/engine/text.lua deleted file mode 100644 index 3c372fb..0000000 --- a/lovely/dump/engine/text.lua +++ /dev/null @@ -1,360 +0,0 @@ -LOVELY_INTEGRITY = '3f32eb39deebe597f05c1629610525603e46d33168f8992920aef2aab6c8d63a' - ---Class -DynaText = Moveable:extend() - ---Class Methods -function DynaText:init(config) - config = config or {} - self.config = config - self.shadow = config.shadow - self.scale = config.scale or 1 - self.pop_in_rate = config.pop_in_rate or 3 - self.bump_rate = config.bump_rate or 2.666 - self.bump_amount = config.bump_amount or 1 - self.font = config.font or G.LANG.font - if config.string and type(config.string) ~= 'table' then config.string = {config.string} end - self.string = (config.string and type(config.string) == 'table' and config.string[1]) or {'HELLO WORLD'} - self.text_offset = { - x = self.font.TEXT_OFFSET.x*self.scale + (self.config.x_offset or 0), - y = self.font.TEXT_OFFSET.y*self.scale + (self.config.y_offset or 0), - } - self.colours = config.colours or {G.C.RED} - self.created_time = G.TIMERS.REAL - self.silent = (config.silent) - - self.start_pop_in = self.config.pop_in - - config.W = 0 - config.H = 0 - - self.strings = {} - self.focused_string = 1 - - self:update_text(true) - if self.config.maxw and self.config.W > self.config.maxw then - self.start_pop_in = self.config.pop_in - self.scale = self.scale*(self.config.maxw/self.config.W) - self:update_text(true) - end - - if #self.strings > 1 then - self.pop_delay = self.config.pop_delay or 1.5 - self:pop_out(4) - end - - Moveable.init(self,config.X or 0, config.Y or 0, config.W, config.H) - - self.T.r = self.config.text_rot or 0 - - self.states.hover.can = false - self.states.click.can = false - self.states.collide.can = false - self.states.drag.can = false - self.states.release_on.can = false - - self:set_role{ - wh_bond = 'Weak', - scale_bond = 'Weak' - } - - if getmetatable(self) == DynaText then - table.insert(G.I.MOVEABLE, self) - end -end - -function DynaText:update(dt) - self:update_text() - self:align_letters() -end - -function DynaText:update_text(first_pass) - self.config.W = 0 - self.config.H = 0 - self.scale = self.config.scale_function and self.config.scale_function() or self.scale - - for k, v in ipairs(self.config.string) do - if (type(v) == 'table' and v.ref_table) or first_pass then - local part_a, part_b = 0,1000000 - local new_string = v - local outer_colour = nil - local inner_colour = nil - local part_scale = 1 - if type(v) == 'table' and (v.ref_table or v.string) then - new_string = (v.prefix or '')..format_ui_value(v.ref_table and v.ref_table[v.ref_value] or v.string)..(v.suffix or '') - part_a = #(v.prefix or '') - part_b = #new_string - #(v.suffix or '') - if v.scale then part_scale = v.scale end - if first_pass then - outer_colour = v.outer_colour or nil - inner_colour = v.colour or nil - end - v = new_string - end - - self.strings[k] = self.strings[k] or {} - local old_string = self.strings[k].string - if old_string ~= new_string or first_pass then - if self.start_pop_in then self.reset_pop_in = true end - self.reset_pop_in = self.reset_pop_in or self.config.reset_pop_in - if not self.reset_pop_in then - self.config.pop_out = nil - self.config.pop_in = nil - else - self.config.pop_in = self.config.pop_in or 0 - self.created_time = G.TIMERS.REAL - end - self.strings[k].string = v - local old_letters = self.strings[k].letters - local tempW = 0 - local tempH = 0 - local current_letter = 1 - self.strings[k].letters = {}--EMPTY(self.strings[k].letters) - - for _, c in utf8.chars(v) do - local old_letter = old_letters and old_letters[current_letter] or nil - local let_tab = {letter = love.graphics.newText(self.font.FONT, c), char = c, scale = old_letter and old_letter.scale or part_scale} - self.strings[k].letters[current_letter] = let_tab - local tx = self.font.FONT:getWidth(c)*self.scale*part_scale*G.TILESCALE*self.font.FONTSCALE + 2.7*(self.config.spacing or 0)*G.TILESCALE*self.font.FONTSCALE - local ty = self.font.FONT:getHeight(c)*self.scale*part_scale*G.TILESCALE*self.font.FONTSCALE*self.font.TEXT_HEIGHT_SCALE - let_tab.offset = old_letter and old_letter.offset or {x = 0, y = 0} - let_tab.dims = {x = tx/(self.font.FONTSCALE*G.TILESCALE), y = ty/(self.font.FONTSCALE*G.TILESCALE)} - let_tab.pop_in = first_pass and (old_letter and old_letter.pop_in or (self.config.pop_in and 0 or 1)) or 1 - let_tab.prefix = current_letter <= part_a and outer_colour or nil - let_tab.suffix = current_letter > part_b and outer_colour or nil - let_tab.colour = inner_colour or nil - if k > 1 then let_tab.pop_in = 0 end - tempW = tempW + tx/(G.TILESIZE*G.TILESCALE) - tempH = math.max(ty/(G.TILESIZE*G.TILESCALE), tempH) - current_letter = current_letter + 1 - end - - self.strings[k].W = tempW - self.strings[k].H = tempH - end - end - - if Big then - if type(self.strings[k].W) == 'table' then - self.strings[k].W = self.strings[k].W:to_number() - end - if type(self.strings[k].H) == 'table' then - self.strings[k].H = self.strings[k].H:to_number() - end - end - if self.strings[k].W > self.config.W then self.config.W = self.strings[k].W; self.strings[k].W_offset = 0 end - if self.strings[k].H > self.config.H then self.config.H = self.strings[k].H; self.strings[k].H_offset = 0 end - end - - if self.T then - if (self.T.w ~= self.config.W or self.T.h ~= self.config.H) and (not first_pass or self.reset_pop_in) then - self.ui_object_updated = true - self.non_recalc = self.config.non_recalc - end - self.T.w = self.config.W - self.T.h = self.config.H - end - - self.reset_pop_in = false - self.start_pop_in = false - - for k, v in ipairs(self.strings) do - v.W_offset = 0.5*(self.config.W - v.W) - v.H_offset = 0.5*(self.config.H - v.H + (self.config.offset_y or 0)) - end -end - -function DynaText:pop_out(pop_out_timer) - self.config.pop_out = pop_out_timer or 1 - self.pop_out_time = G.TIMERS.REAL + (self.pop_delay or 0) -end - -function DynaText:pop_in(pop_in_timer) - self.reset_pop_in = true - self.config.pop_out = nil - self.config.pop_in = pop_in_timer or 0 - self.created_time = G.TIMERS.REAL - - for k, letter in ipairs(self.strings[self.focused_string].letters) do - if Big then - letter.dims.x = to_big(letter.dims.x):to_number() - letter.dims.y = to_big(letter.dims.y):to_number() - letter.offset.x = to_big(letter.offset.x):to_number() - letter.offset.y = to_big(letter.offset.y):to_number() - end - letter.pop_in = 0 - end - - self:update_text() -end - -function DynaText:align_letters() - if self.pop_cycle then - self.focused_string = (self.config.random_element and math.random(1, #self.strings)) or self.focused_string == #self.strings and 1 or self.focused_string+1 - self.pop_cycle = false - for k, letter in ipairs(self.strings[self.focused_string].letters) do - if Big then - letter.dims.x = to_big(letter.dims.x):to_number() - letter.dims.y = to_big(letter.dims.y):to_number() - letter.offset.x = to_big(letter.offset.x):to_number() - letter.offset.y = to_big(letter.offset.y):to_number() - end - letter.pop_in = 0 - end - self.config.pop_in = 0.1 - self.config.pop_out = nil - self.created_time = G.TIMERS.REAL - end - self.string = self.strings[self.focused_string].string - for k, letter in ipairs(self.strings[self.focused_string].letters) do - if Big then - letter.dims.x = to_big(letter.dims.x):to_number() - letter.dims.y = to_big(letter.dims.y):to_number() - letter.offset.x = to_big(letter.offset.x):to_number() - letter.offset.y = to_big(letter.offset.y):to_number() - end - if self.config.pop_out then - letter.pop_in = math.min(1, math.max((self.config.min_cycle_time or 1)-(G.TIMERS.REAL - self.pop_out_time)*self.config.pop_out/(self.config.min_cycle_time or 1), 0)) - letter.pop_in = letter.pop_in*letter.pop_in - if k == #self.strings[self.focused_string].letters and letter.pop_in <= 0 and #self.strings > 1 then self.pop_cycle = true end - elseif self.config.pop_in then - local prev_pop_in = letter.pop_in - letter.pop_in = math.min(1, math.max((G.TIMERS.REAL - self.config.pop_in - self.created_time)*#self.string*self.pop_in_rate - k + 1, self.config.min_cycle_time == 0 and 1 or 0)) - letter.pop_in = letter.pop_in*letter.pop_in - if prev_pop_in <=0 and letter.pop_in > 0 and not self.silent and - (#self.string < 10 or k%2 == 0) then - if self.T.x > G.ROOM.T.w+2 or - self.T.y > G.ROOM.T.h+2 or - self.T.x <-2 or - self.T.y <-2 then else - play_sound('paper1', 0.45+0.05*math.random()+(0.3/#self.string)*k + (self.config.pitch_shift or 0)) - end - end - if k == #self.strings[self.focused_string].letters and letter.pop_in >= 1 then - if #self.strings > 1 then - self.pop_delay = (G.TIMERS.REAL - self.config.pop_in - self.created_time + (self.config.pop_delay or 1.5)) - self:pop_out(4) - else - self.config.pop_in = nil - end - end - end - letter.r = 0 - letter.scale = 1 - if self.config.rotate then letter.r = (self.config.rotate == 2 and -1 or 1)*(0.2*(-#self.strings[self.focused_string].letters/2 - 0.5 + k)/(#self.strings[self.focused_string].letters)+ (G.SETTINGS.reduced_motion and 0 or 1)*0.02*math.sin(2*G.TIMERS.REAL+k)) end - if self.config.pulse then - letter.scale = letter.scale + (G.SETTINGS.reduced_motion and 0 or 1)*(1/self.config.pulse.width)*self.config.pulse.amount*(math.max( - math.min((self.config.pulse.start - G.TIMERS.REAL)*self.config.pulse.speed + k + self.config.pulse.width, - (G.TIMERS.REAL - self.config.pulse.start)*self.config.pulse.speed - k + self.config.pulse.width+ 2), - 0)) - letter.r = letter.r + (G.SETTINGS.reduced_motion and 0 or 1)*(letter.scale - 1)*(0.02*(-#self.strings[self.focused_string].letters/2 - 0.5 + k)) - if self.config.pulse.start > G.TIMERS.REAL + 2*self.config.pulse.speed*#self.strings[self.focused_string].letters then - self.config.pulse = nil - end - end - if self.config.quiver then - letter.scale = letter.scale + (G.SETTINGS.reduced_motion and 0 or 1)*(0.1*self.config.quiver.amount) - letter.r = letter.r + (G.SETTINGS.reduced_motion and 0 or 1)*0.3*self.config.quiver.amount*( - math.sin(41.12342*G.TIMERS.REAL*self.config.quiver.speed + k*1223.2) + - math.cos(63.21231*G.TIMERS.REAL*self.config.quiver.speed + k*1112.2)*math.sin(36.1231*G.TIMERS.REAL*self.config.quiver.speed) + - math.cos(95.123*G.TIMERS.REAL*self.config.quiver.speed + k*1233.2) - - math.sin(30.133421*G.TIMERS.REAL*self.config.quiver.speed + k*123.2)) - end - if self.config.float then letter.offset.y = (G.SETTINGS.reduced_motion and 0 or 1)*math.sqrt(self.scale)*(2+(self.font.FONTSCALE/G.TILESIZE)*2000*math.sin(2.666*G.TIMERS.REAL+200*k)) + 60*(letter.scale-1) end - if self.config.bump then letter.offset.y = (G.SETTINGS.reduced_motion and 0 or 1)*self.bump_amount*math.sqrt(self.scale)*7*math.max(0, (5+self.bump_rate)*math.sin(self.bump_rate*G.TIMERS.REAL+200*k) - 3 - self.bump_rate) end - end -end - -function DynaText:set_quiver(amt) - self.config.quiver = { - speed = 0.5, - amount = amt or 0.7, - silent = false - } -end - -function DynaText:pulse(amt) - self.config.pulse = { - speed = 40, - width = 2.5, - start = G.TIMERS.REAL, - amount = amt or 0.2, - silent = false - } -end - -function DynaText:draw() -if Big then - self.scale = to_big(self.scale):to_number() - if self.shadow_parallax then self.shadow_parallax.x = to_big(self.shadow_parallax.x):to_number() end -end - if self.children.particle_effect then self.children.particle_effect:draw() end - - if self.shadow then - prep_draw(self, 1) - love.graphics.translate(self.strings[self.focused_string].W_offset + self.text_offset.x*self.font.FONTSCALE/G.TILESIZE, self.strings[self.focused_string].H_offset + self.text_offset.y*self.font.FONTSCALE/G.TILESIZE) - if self.config.spacing then love.graphics.translate(self.config.spacing*self.font.FONTSCALE/G.TILESIZE, 0) end - if self.config.shadow_colour then - love.graphics.setColor(self.config.shadow_colour) - else - love.graphics.setColor(0, 0, 0, 0.3*self.colours[1][4]) - end - for k, letter in ipairs(self.strings[self.focused_string].letters) do - if Big then - letter.dims.x = to_big(letter.dims.x):to_number() - letter.dims.y = to_big(letter.dims.y):to_number() - letter.offset.x = to_big(letter.offset.x):to_number() - letter.offset.y = to_big(letter.offset.y):to_number() - end - local real_pop_in = self.config.min_cycle_time == 0 and 1 or letter.pop_in - love.graphics.draw( - letter.letter, - 0.5*(letter.dims.x - letter.offset.x)*self.font.FONTSCALE/G.TILESIZE -self.shadow_parrallax.x*self.scale/(G.TILESIZE), - 0.5*(letter.dims.y)*self.font.FONTSCALE/G.TILESIZE -self.shadow_parrallax.y*self.scale/(G.TILESIZE), - letter.r or 0, - real_pop_in*self.scale*self.font.FONTSCALE/G.TILESIZE, - real_pop_in*self.scale*self.font.FONTSCALE/G.TILESIZE, - 0.5*letter.dims.x/self.scale, - 0.5*letter.dims.y/self.scale - ) - love.graphics.translate(letter.dims.x*self.font.FONTSCALE/G.TILESIZE, 0) - end - love.graphics.pop() - end - - prep_draw(self, 1) - love.graphics.translate(self.strings[self.focused_string].W_offset + self.text_offset.x*self.font.FONTSCALE/G.TILESIZE, self.strings[self.focused_string].H_offset + self.text_offset.y*self.font.FONTSCALE/G.TILESIZE) - if self.config.spacing then love.graphics.translate(self.config.spacing*self.font.FONTSCALE/G.TILESIZE, 0) end - self.ARGS.draw_shadow_norm = self.ARGS.draw_shadow_norm or {} - local _shadow_norm = self.ARGS.draw_shadow_norm - _shadow_norm.x, _shadow_norm.y = - self.shadow_parrallax.x/math.sqrt(self.shadow_parrallax.y*self.shadow_parrallax.y + self.shadow_parrallax.x*self.shadow_parrallax.x)*self.font.FONTSCALE/G.TILESIZE, - self.shadow_parrallax.y/math.sqrt(self.shadow_parrallax.y*self.shadow_parrallax.y + self.shadow_parrallax.x*self.shadow_parrallax.x)*self.font.FONTSCALE/G.TILESIZE - - for k, letter in ipairs(self.strings[self.focused_string].letters) do - if Big then - letter.dims.x = to_big(letter.dims.x):to_number() - letter.dims.y = to_big(letter.dims.y):to_number() - letter.offset.x = to_big(letter.offset.x):to_number() - letter.offset.y = to_big(letter.offset.y):to_number() - end - local real_pop_in = self.config.min_cycle_time == 0 and 1 or letter.pop_in - love.graphics.setColor(letter.prefix or letter.suffix or letter.colour or self.colours[k%#self.colours + 1]) - - love.graphics.draw( - letter.letter, - 0.5*(letter.dims.x - letter.offset.x)*self.font.FONTSCALE/G.TILESIZE + _shadow_norm.x, - 0.5*(letter.dims.y - letter.offset.y)*self.font.FONTSCALE/G.TILESIZE + _shadow_norm.y, - letter.r or 0, - real_pop_in*letter.scale*self.scale*self.font.FONTSCALE/G.TILESIZE, - real_pop_in*letter.scale*self.scale*self.font.FONTSCALE/G.TILESIZE, - 0.5*letter.dims.x/(self.scale), - 0.5*letter.dims.y/(self.scale) - ) - love.graphics.translate(letter.dims.x*self.font.FONTSCALE/G.TILESIZE, 0) - end - love.graphics.pop() - - add_to_drawhash(self) - self:draw_boundingrect() -end diff --git a/lovely/dump/engine/ui.lua b/lovely/dump/engine/ui.lua deleted file mode 100644 index fa684a8..0000000 --- a/lovely/dump/engine/ui.lua +++ /dev/null @@ -1,1066 +0,0 @@ -LOVELY_INTEGRITY = '435a9e8ef1b3d548ef4488606196332b7d61c0a33e2dd2225ca6c7f97e3ec32b' - ---Class -UIBox = Moveable:extend() - ---The base level and container of a graph of 1 or more UIElements. These UIEs are\ ---essentially a node based UI implementation. As the root node of the graph, this\ ---node is the first called for any movement, updates, or changes to ensure that all child\ ---nodes are updated and modified in the correct order.\\ ---The UI_definitions file houses the majority of the definition tables needed for UIBox initialization. --- ----@param args {T: table, definition: table, config: table} ---**T** A standard transform in game units describing the inital position and size of the object with x, y, w, h\ ---ex - {x = 1, y = 5, w = 2, h = 2, r = 0} --- ---**definition** A table containing a valid UIBox definition. These are mostly generated from UI_definitions --- ---**config** A configuration table for the UIBox ---ex - { align = 'cm', offset = {x = 1, y = 1}, parent_rect = A, attach_rect = B, can_collide = true } -function UIBox:init(args) - --First initialize the moveable - Moveable.init(self,{args.T}) - - --Initialization of fields - self.states.drag.can = false - self.draw_layers = {} --if we need to explicitly change the draw order of the UIEs - - --The definition table that contains the schematic of this UIBox - self.definition = args.definition - - if args.config then - self.config = args.config - args.config.major = args.config.major or args.config.parent or self - - self:set_alignment({ - major = args.config.major, - type = args.config.align or args.config.type or '', - bond = args.config.bond or 'Strong', - offset = args.config.offset or {x=0,y=0}, - lr_clamp = args.config.lr_clamp - }) - self:set_role{ - xy_bond = args.config.xy_bond, - r_bond = args.config.r_bond, - wh_bond = args.config.wh_bond or 'Weak', - scale_bond = args.config.scale_bond or 'Weak' - } - self.states.collide.can = true - - if args.config.can_collide == nil then - self.states.collide.can = true - else - self.states.collide.can = args.config.can_collide - end - - self.parent = self.config.parent - end - - --inherit the layered_parallax from the parent if there is any - --self.layered_parallax = self.role.major and self.role.major.layered_parallax or self.layered_parallax - - --Initialization of the UIBox from the definition - --First, set parent-child relationships to create the tree structure of the box - - self:set_parent_child(self.definition, nil) - --Set the midpoint for any future alignments to use - self.Mid = self.Mid or self.UIRoot - --Calculate the correct and width/height and offset for each node - self:calculate_xywh(self.UIRoot, self.T) - - --set the transform w/h to equal that of the calculated box - self.T.w = self.UIRoot.T.w - self.T.h = self.UIRoot.T.h - --Then, calculate the correct width and height for each container - self.UIRoot:set_wh() - --Then, set all of the correct alignments for the ui elements\ - - self.UIRoot:set_alignments() - - self:align_to_major() - self.VT.x, self.VT.y = self.T.x, self.T.y - self.VT.w, self.VT.h = self.T.w, self.T.h - - if self.Mid ~= self and self.Mid.parent and false then - self.VT.x = self.VT.x - self.Mid.role.offset.x + (self.Mid.parent.config.padding or 0) - self.VT.y = self.VT.y - self.Mid.role.offset.y + (self.Mid.parent.config.padding or 0) - end - - if self.alignment and self.alignment.lr_clamp then - self:lr_clamp() - end - - self.UIRoot:initialize_VT(true) - if getmetatable(self) == UIBox then - if args.config.instance_type then - table.insert(G.I[args.config.instance_type], self) - else - table.insert(G.I.UIBOX, self) - end - end -end - -function UIBox:get_UIE_by_ID(id, node) - if not node then node = self.UIRoot end - if node.config and node.config.id == id then return node end - for k, v in pairs(node.children) do - local res = self:get_UIE_by_ID(id, v) - if res then - return res - elseif v.config.object and v.config.object.get_UIE_by_ID then - res = v.config.object:get_UIE_by_ID(id, nil) - if res then - return res - end - end - end - return nil -end - -function UIBox:calculate_xywh(node, _T, recalculate, _scale) - node.ARGS.xywh_node_trans = node.ARGS.xywh_node_trans or {} - local _nt = node.ARGS.xywh_node_trans - local _ct = {} - - _ct.x, _ct.y, _ct.w, _ct.h = 0,0,0,0 - - local padding = node.config.padding or G.UIT.padding - --current node does not contain anything - if node.UIT == G.UIT.B or node.UIT == G.UIT.T or node.UIT == G.UIT.O then - _nt.x, _nt.y, _nt.w, _nt.h = - _T.x, - _T.y, - node.config.w or (node.config.object and node.config.object.T.w), - node.config.h or (node.config.object and node.config.object.T.h) - - if node.UIT == G.UIT.T then - node.config.text_drawable = nil - local scale = node.config.scale or 1 - if node.config.ref_table and node.config.ref_value then - node.config.text = tostring(node.config.ref_table[node.config.ref_value]) - if node.config.func and not recalculate then G.FUNCS[node.config.func](node) end - end - if not node.config.text then node.config.text = '[UI ERROR]' end - node.config.lang = node.config.lang or G.LANG - local tx = node.config.lang.font.FONT:getWidth(node.config.text)*node.config.lang.font.squish*scale*G.TILESCALE*node.config.lang.font.FONTSCALE - local ty = node.config.lang.font.FONT:getHeight()*scale*G.TILESCALE*node.config.lang.font.FONTSCALE*node.config.lang.font.TEXT_HEIGHT_SCALE - if node.config.vert then local thunk = tx; tx = ty; ty = thunk end - _nt.x, _nt.y, _nt.w, _nt.h = - _T.x, - _T.y, - tx/(G.TILESIZE*G.TILESCALE), - ty/(G.TILESIZE*G.TILESCALE) - - node.content_dimensions = node.content_dimensions or {} - node.content_dimensions.w = _T.w - node.content_dimensions.h = _T.h - node:set_values(_nt, recalculate) - elseif node.UIT == G.UIT.B or node.UIT == G.UIT.O then - node.content_dimensions = node.content_dimensions or {} - node.content_dimensions.w = _nt.w - node.content_dimensions.h = _nt.h - node:set_values(_nt, recalculate) - end - return _nt.w, _nt.h - else --For all other node containers, treat them explicitly like a column - for i = 1, 2 do - if i == 1 or (i == 2 and ((node.config.maxw and _ct.w > node.config.maxw) or (node.config.maxh and _ct.h > node.config.maxh))) then - local fac = _scale or 1 - if i == 2 then - local restriction = node.config.maxw or node.config.maxh - fac = fac*restriction/(node.config.maxw and _ct.w or _ct.h) - end - _nt.x, _nt.y, _nt.w, _nt.h = - _T.x, - _T.y, - node.config.minw or 0, - node.config.minh or 0 - - if node.UIT == G.UIT.ROOT then - _nt.x, _nt.y, _nt.w, _nt.h = 0, 0, node.config.minw or 0, node.config.minh or 0 - end - _ct.x, _ct.y, _ct.w, _ct.h = _nt.x+padding, _nt.y+padding, 0, 0 - local _tw, _th - for k, v in ipairs(node.children) do - if getmetatable(v) == UIElement then - if v.config and v.config.scale then v.config.scale = v.config.scale*fac end - _tw, _th = self:calculate_xywh(v, _ct, recalculate, fac) - if _th and _tw then - if Big then - _th = to_big(_th):to_number() - _tw = to_big(_tw):to_number() - end - if v.UIT == G.UIT.R then - _ct.h = _ct.h + _th + padding - _ct.y = _ct.y + _th + padding - if _tw + padding > _ct.w then _ct.w = _tw + padding end - if v.config and v.config.emboss then - _ct.h = _ct.h + v.config.emboss - _ct.y = _ct.y + v.config.emboss - end - else - _ct.w = _ct.w + _tw + padding - _ct.x = _ct.x + _tw + padding - if _th + padding > _ct.h then _ct.h = _th + padding end - if v.config and v.config.emboss then - _ct.h = _ct.h + v.config.emboss - end - end - end - end - end - end - end - - node.content_dimensions = node.content_dimensions or {} - node.content_dimensions.w = _ct.w + padding - node.content_dimensions.h = _ct.h + padding - _nt.w = math.max(_ct.w + padding, _nt.w) - _nt.h = math.max(_ct.h + padding, _nt.h)-- - node:set_values(_nt, recalculate) - return _nt.w, _nt.h - end -end - -function UIBox:remove_group(node, group) - node = node or self.UIRoot - for k, v in pairs(node.children) do - if self:remove_group(v, group) then node.children[k] = nil end - end - if node.config and node.config.group and node.config.group == group then node:remove(); return true end - - if not node.parent or true then self:calculate_xywh(self.UIRoot, self.T, true); self.UIRoot:set_wh(); self.UIRoot:set_alignment() end--self:recalculate() end -end - -function UIBox:get_group(node, group, ingroup) - node = node or self.UIRoot - ingroup = ingroup or {} - for k, v in pairs(node.children) do - self:get_group(v, group, ingroup) - end - if node.config and node.config.group and node.config.group == group then table.insert(ingroup, node); return ingroup end - return ingroup -end - -function UIBox:set_parent_child(node, parent) - local UIE = UIElement(parent, self, node.n, node.config) - - --set the group of the element - if parent and parent.config and parent.config.group then if UIE.config then UIE.config.group = parent.config.group else UIE.config = {group = parent.config.group} end end - - --set the button for the element - if parent and parent.config and parent.config.button then if UIE.config then UIE.config.button_UIE = parent else UIE.config = {button_UIE = parent} end end - if parent and parent.config and parent.config.button_UIE then if UIE.config then UIE.config.button_UIE = parent.config.button_UIE else UIE.config = {button = parent.config.button} end end - - if node.n and node.n == G.UIT.O and UIE.config.button then - UIE.config.object.states.click.can = false - end - - --current node is a container - if (node.n and node.n == G.UIT.C or node.n == G.UIT.R or node.n == G.UIT.ROOT) and node.nodes then - for k, v in pairs(node.nodes) do - self:set_parent_child(v, UIE) - end - end - - if not parent then - self.UIRoot = UIE - self.UIRoot.parent = self - else - table.insert(parent.children, UIE) - end - if node.config and node.config.mid then - self.Mid = UIE - end -end -function UIBox:remove() - if self == G.OVERLAY_MENU then G.REFRESH_ALERTS = true end - self.UIRoot:remove() - for k, v in pairs(G.I[self.config.instance_type or 'UIBOX']) do - if v == self then - table.remove(G.I[self.config.instance_type or 'UIBOX'], k) - break; - end - end - remove_all(self.children) - Moveable.remove(self) -end - -function UIBox:draw() - if self.FRAME.DRAW >= G.FRAMES.DRAW and not G.OVERLAY_TUTORIAL then return end - self.FRAME.DRAW = G.FRAMES.DRAW - - for k, v in pairs(self.children) do - if k ~= 'h_popup' and k ~= 'alert' then v:draw() end - end - - if self.states.visible then - add_to_drawhash(self) - self.UIRoot:draw_self() - self.UIRoot:draw_children() - for k, v in ipairs(self.draw_layers) do - if v.draw_self then v:draw_self() else v:draw() end - if v.draw_children then v:draw_children() end - end - end - - if self.children.alert then self.children.alert:draw() end - - self:draw_boundingrect() -end - -function UIBox:recalculate() - --Calculate the correct dimensions and width/height and offset for each node - self:calculate_xywh(self.UIRoot, self.T, true) - --Then, calculate the correct width and height for each container - self.UIRoot:set_wh() - --Then, set all of the correct alignments for the ui elements - self.UIRoot:set_alignments() - self.T.w = self.UIRoot.T.w - self.T.h = self.UIRoot.T.h - G.REFRESH_FRAME_MAJOR_CACHE = (G.REFRESH_FRAME_MAJOR_CACHE or 0) + 1 - self.UIRoot:initialize_VT() - G.REFRESH_FRAME_MAJOR_CACHE = (G.REFRESH_FRAME_MAJOR_CACHE > 1 and G.REFRESH_FRAME_MAJOR_CACHE - 1 or nil) -end - -function UIBox:move(dt) - Moveable.move(self, dt) - Moveable.move(self.UIRoot, dt) -end - -function UIBox:drag(offset) - Moveable.drag(self,offset) - Moveable.move(self.UIRoot, dt) -end - -function UIBox:add_child(node, parent) - self:set_parent_child(node, parent) - self:recalculate() -end - -function UIBox:set_container(container) - self.UIRoot:set_container(container) - Node.set_container(self, container) -end - -function UIBox:print_topology(indent) - local box_str = '| UIBox | - ID:'..self.ID..' w/h:'..self.T.w..'/'..self.T.h - local indent = indent or 0 - box_str = box_str..self.UIRoot:print_topology(indent) - return box_str -end - ---Class -UIElement = Moveable:extend() ---Class Methods -function UIElement:init(parent, new_UIBox, new_UIT, config) - self.parent = parent - self.UIT = new_UIT - self.UIBox = new_UIBox - self.config = config or {} - if self.config and self.config.object then self.config.object.parent = self end - self.children = {} - self.ARGS = self.ARGS or {} - self.content_dimensions = {w=0, h=0} -end -function UIElement:set_values(_T, recalculate) - if not recalculate or not self.T then - Moveable.init(self,{T = _T}) - self.states.click.can = false - self.states.drag.can = false - self.static_rotation = true - else - self.T.x = _T.x - self.T.y = _T.y - self.T.w = _T.w - self.T.h = _T.h - end - - if self.config.button_UIE then self.states.collide.can = true; self.states.hover.can = false; self.states.click.can = true end - if self.config.button then self.states.collide.can = true; self.states.click.can = true end - - if self.config.on_demand_tooltip or self.config.tooltip or self.config.detailed_tooltip then - self.states.collide.can = true - end - - self:set_role{role_type = 'Minor', major = self.UIBox, offset = {x = _T.x, y = _T.y}, wh_bond = 'Weak', scale_bond = 'Weak'} - - if self.config.draw_layer then - self.UIBox.draw_layers[self.config.draw_layer] = self - end - - if self.config.collideable then self.states.collide.can = true end - - if self.config.can_collide ~= nil then - self.states.collide.can = self.config.can_collide - if self.config.object then self.config.object.states.collide.can = self.states.collide.can end - end - - if self.UIT == G.UIT.O and not self.config.no_role then - self.config.object:set_role(self.config.role or {role_type = 'Minor', major = self, xy_bond = 'Strong', wh_bond = 'Weak', scale_bond = 'Weak'}) - end - - if self.config and self.config.ref_value and self.config.ref_table then - self.config.prev_value = self.config.ref_table[self.config.ref_value] - end - - if self.UIT == G.UIT.T then self.static_rotation = true end - - if self.config.juice then - if self.UIT == G.UIT.ROOT then self:juice_up() end - if self.UIT == G.UIT.T then self:juice_up() end - if self.UIT == G.UIT.O then self.config.object:juice_up(0.5) end - if self.UIT == G.UIT.B then self:juice_up() end - if self.UIT == G.UIT.C then self:juice_up() end - if self.UIT == G.UIT.R then self:juice_up() end - self.config.juice = false - end - - if not self.config.colour then - if self.UIT == G.UIT.ROOT then self.config.colour = G.C.UI.BACKGROUND_DARK end - if self.UIT == G.UIT.T then self.config.colour = G.C.UI.TEXT_LIGHT end - if self.UIT == G.UIT.O then self.config.colour = G.C.WHITE end - if self.UIT == G.UIT.B then self.config.colour = G.C.CLEAR end - if self.UIT == G.UIT.C then self.config.colour = G.C.CLEAR end - if self.UIT == G.UIT.R then self.config.colour = G.C.CLEAR end - end - if not self.config.outline_colour then - if self.UIT == G.UIT.ROOT then self.config.outline_colour = G.C.UI.OUTLINE_LIGHT end - if self.UIT == G.UIT.T then self.config.outline_colour = G.C.UI.OUTLINE_LIGHT end - if self.UIT == G.UIT.O then self.config.colour = G.C.UI.OUTLINE_LIGHT end - if self.UIT == G.UIT.B then self.config.outline_colour = G.C.UI.OUTLINE_LIGHT end - if self.UIT == G.UIT.C then self.config.outline_colour = G.C.UI.OUTLINE_LIGHT end - if self.UIT == G.UIT.R then self.config.outline_colour = G.C.UI.OUTLINE_LIGHT end - end - - if self.config.focus_args and not self.config.focus_args.registered then - if self.config.focus_args.button then - G.CONTROLLER:add_to_registry(self.config.button_UIE or self, self.config.focus_args.button) - end - - if self.config.focus_args.snap_to then - G.CONTROLLER:snap_to{node = self} - end - - if self.config.focus_args.funnel_to then - local _par = self.parent - while _par and _par:is(UIElement) do - if _par.config.focus_args and _par.config.focus_args.funnel_from then - _par.config.focus_args.funnel_from = self - self.config.focus_args.funnel_to = _par - break - end - _par = _par.parent - end - end - self.config.focus_args.registered = true - end - - if self.config.force_focus then self.states.collide.can = true end - - if self.config.button_delay and not self.config.button_delay_start then - self.config.button_delay_start = G.TIMERS.REAL - self.config.button_delay_end = G.TIMERS.REAL + self.config.button_delay - self.config.button_delay_progress = 0 - end - - self.layered_parallax = self.layered_parallax or {x=0, y=0} - - if self.config and self.config.func and (((self.config.button_UIE or self.config.button) and self.config.func ~= 'set_button_pip') or self.config.insta_func) then G.FUNCS[self.config.func](self) end -end - -function UIElement:print_topology(indent) - local UIT = '????' - for k, v in pairs(G.UIT) do - if v == self.UIT then UIT = ''..k end - end - local box_str = '\n'..(string.rep(" ", indent))..'| '..UIT..' | - ID:'..self.ID..' w/h:'..self.T.w..'/'..self.T.h - if UIT == 'O' then - box_str = box_str..' OBJ:'..( - getmetatable(self.config.object) == CardArea and 'CardArea' or - getmetatable(self.config.object) == Card and 'Card' or - getmetatable(self.config.object) == UIBox and 'UIBox' or - getmetatable(self.config.object) == Particles and 'Particles' or - getmetatable(self.config.object) == DynaText and 'DynaText' or - getmetatable(self.config.object) == Sprite and 'Sprite' or - getmetatable(self.config.object) == AnimatedSprite and 'AnimatedSprite' or - 'OTHER' - ) - elseif UIT == 'T' then - box_str = box_str..' TEXT:'..(self.config.text or 'REF') - end - - for k, v in ipairs(self.children) do - if v.print_topology then - box_str = box_str..v:print_topology(indent+1) - end - end - return box_str -end - -function UIElement:initialize_VT() - self:move_with_major(0) - self:calculate_parrallax() - - for _, v in pairs(self.children) do - if v.initialize_VT then v:initialize_VT() end - end - - self.VT.w, self.VT.h = self.T.w, self.T.h - - if self.UIT == G.UIT.T then self:update_text() end - if self.config.object then - if not self.config.no_role then - self.config.object:hard_set_T(self.T.x, self.T.y, self.T.w, self.T.h) - self.config.object:move_with_major(0) - self.config.object.alignment.prev_type = '' - self.config.object:align_to_major() - end - if self.config.object.recalculate then - self.config.object:recalculate() - end - end -end - -function UIElement:juice_up(amount, rot_amt) - if self.UIT == G.UIT.O then - if self.config.object then self.config.object:juice_up(amount, rot_amt) end - else - Moveable.juice_up(self, amount, rot_amt) - end -end - -function UIElement:can_drag() - if self.states.drag.can then return self end - return self.UIBox:can_drag() -end - -function UIElement:draw() -end - -function UIElement:draw_children(layer) - if self.states.visible then - for k, v in pairs(self.children) do - if not v.config.draw_layer and k ~= 'h_popup' and k~= 'alert' then - if v.draw_self and not v.config.draw_after then v:draw_self() else v:draw() end - if v.draw_children then v:draw_children() end - if v.draw_self and v.config.draw_after then v:draw_self() else v:draw() end - end - end - end -end - -function UIElement:set_wh() - --Iterate through all children of this node - local padding = (self.config and self.config.padding) or G.UIT.padding - - local _max_w, _max_h = 0,0 - - if next(self.children) == nil or self.config.no_fill then - return self.T.w, self.T.h - else - for k, w in pairs(self.children) do - if w.set_wh then - local _cw, _ch = w:set_wh() - if Big and G.STATE == G.STATES.MENU then _cw = to_big(_cw):to_number(); _ch = to_big(_ch):to_number() end - if _cw and _ch then - if _cw > _max_w then _max_w = _cw end - if _ch > _max_h then _max_h = _ch end - else - _max_w = padding - _max_h = padding - end - end - end - for k, w in pairs(self.children) do - if w.UIT == G.UIT.R then w.T.w = _max_w end - if w.UIT == G.UIT.C then w.T.h = _max_h end - end - end - return self.T.w, self.T.h -end - -function UIElement:align(x, y) - self.role.offset.y = self.role.offset.y + y - self.role.offset.x = self.role.offset.x + x - for _, v in pairs(self.children) do - if v.align then - v:align(x, y) - end - end -end - -function UIElement:set_alignments() - --vertically centered is c = centered - --horizontally centered is m = middle - --top and left are default - --bottom is b - --right is r - for k, v in pairs(self.children) do - if self.config and self.config.align and v.align then - - local padding = self.config.padding or G.UIT.padding - - if string.find(self.config.align, "c") then - if v.UIT == G.UIT.T or v.UIT == G.UIT.B or v.UIT == G.UIT.O then - v:align(0,0.5*(self.T.h - 2*padding - v.T.h)) - else - v:align(0,0.5*(self.T.h - self.content_dimensions.h)) - end - end - if string.find(self.config.align, "m") then - v:align(0.5*(self.T.w - self.content_dimensions.w),0) - end - if string.find(self.config.align, "b") then - v:align(0, self.T.h - self.content_dimensions.h) - end - if string.find(self.config.align, "r") then - v:align((self.T.w - self.content_dimensions.w), 0) - end - end - if v.set_alignments then v:set_alignments() end - end -end -function UIElement:update_text() - if self.config and self.config.text and not self.config.text_drawable then - self.config.lang = self.config.lang or G.LANG - self.config.text_drawable = love.graphics.newText(self.config.lang.font.FONT, {G.C.WHITE,self.config.text}) - end - - if self.config.ref_table and self.config.ref_table[self.config.ref_value] ~= self.config.prev_value then - self.config.text = tostring(self.config.ref_table[self.config.ref_value]) - self.config.text_drawable:set(self.config.text) - if not self.config.no_recalc and self.config.prev_value and string.len(self.config.prev_value) ~= string.len(self.config.text) then self.UIBox:recalculate() end - self.config.prev_value = self.config.ref_table[self.config.ref_value] - end -end - -function UIElement:update_object() - if self.config.ref_table and self.config.ref_value and self.config.ref_table[self.config.ref_value] ~= self.config.object then - self.config.object = self.config.ref_table[self.config.ref_value] - self.UIBox:recalculate() - end - - if self.config.object then - self.config.object.config.refresh_movement = true - if self.config.object.states.hover.is and not self.states.hover.is then - self:hover() - self.states.hover.is = true - end - if not self.config.object.states.hover.is and self.states.hover.is then - self:stop_hover() - self.states.hover.is = false - end - end - - if self.config.object and self.config.object.ui_object_updated then - self.config.object.ui_object_updated = nil - self.config.object.parent = self - self.config.object:set_role(self.config.role or {role_type = 'Minor', major = self}) - self.config.object:move_with_major(0) - if self.config.object.non_recalc then - self.parent.content_dimensions.w = self.config.object.T.w - self:align(self.parent.T.x - self.config.object.T.x, self.parent.T.y - self.config.object.T.y) - self.parent:set_alignments() - else - self.UIBox:recalculate() - end - end -end -function UIElement:draw_self() - if not self.states.visible then - if self.config.force_focus then add_to_drawhash(self) end - return - end - - if self.config.force_focus or self.config.force_collision or self.config.button_UIE or self.config.button or self.states.collide.can then - add_to_drawhash(self) - end - - local button_active = true - local parallax_dist = 1.5 - local button_being_pressed = false - - if (self.config.button or self.config.button_UIE) then - self.layered_parallax.x = ((self.parent and self.parent ~= self.UIBox and self.parent.layered_parallax.x or 0) + (self.config.shadow and 0.4*self.shadow_parrallax.x or 0)/G.TILESIZE) - self.layered_parallax.y = ((self.parent and self.parent ~= self.UIBox and self.parent.layered_parallax.y or 0) + (self.config.shadow and 0.4*self.shadow_parrallax.y or 0)/G.TILESIZE) - - if self.config.button and ((self.last_clicked and self.last_clicked > G.TIMERS.REAL - 0.1) or ((self.config.button and (self.states.hover.is or self.states.drag.is)) - and G.CONTROLLER.is_cursor_down)) then - self.layered_parallax.x = self.layered_parallax.x - parallax_dist*self.shadow_parrallax.x/G.TILESIZE*(self.config.button_dist or 1) - self.layered_parallax.y = self.layered_parallax.y - parallax_dist*self.shadow_parrallax.y/G.TILESIZE*(self.config.button_dist or 1) - parallax_dist = 0 - button_being_pressed = true - end - - if self.config.button_UIE and not self.config.button_UIE.config.button then button_active = false end - end - if self.config.colour[4] > 0.01 then - if self.UIT == G.UIT.T and self.config.scale then - self.ARGS.text_parallax = self.ARGS.text_parallax or {} - self.ARGS.text_parallax.sx = -self.shadow_parrallax.x*0.5/(self.config.scale*self.config.lang.font.FONTSCALE) - self.ARGS.text_parallax.sy = -self.shadow_parrallax.y*0.5/(self.config.scale*self.config.lang.font.FONTSCALE) - - if (self.config.button_UIE and button_active) or (not self.config.button_UIE and self.config.shadow and G.SETTINGS.GRAPHICS.shadows == 'On') then - prep_draw(self, 0.97) - if Big and G.STATE == G.STATES.MENU then self.config.scale = to_big(self.config.scale):to_number() end - if self.config.vert then love.graphics.translate(0,self.VT.h); love.graphics.rotate(-math.pi/2) end - if (self.config.shadow or (self.config.button_UIE and button_active)) and G.SETTINGS.GRAPHICS.shadows == 'On' then - love.graphics.setColor(0, 0, 0, 0.3*self.config.colour[4]) - love.graphics.draw( - self.config.text_drawable, - (self.config.lang.font.TEXT_OFFSET.x + (self.config.vert and -self.ARGS.text_parallax.sy or self.ARGS.text_parallax.sx))*(self.config.scale or 1)*self.config.lang.font.FONTSCALE/G.TILESIZE, - (self.config.lang.font.TEXT_OFFSET.y + (self.config.vert and self.ARGS.text_parallax.sx or self.ARGS.text_parallax.sy))*(self.config.scale or 1)*self.config.lang.font.FONTSCALE/G.TILESIZE, - 0, - (self.config.scale)*self.config.lang.font.squish*self.config.lang.font.FONTSCALE/G.TILESIZE, - (self.config.scale)*self.config.lang.font.FONTSCALE/G.TILESIZE - ) - end - love.graphics.pop() - end - - prep_draw(self, 1) - if Big and G.STATE == G.STATES.MENU then self.config.scale = to_big(self.config.scale):to_number() end - if self.config.vert then love.graphics.translate(0,self.VT.h); love.graphics.rotate(-math.pi/2) end - if not button_active then - love.graphics.setColor(G.C.UI.TEXT_INACTIVE) - else - love.graphics.setColor(self.config.colour) - end - love.graphics.draw( - self.config.text_drawable, - self.config.lang.font.TEXT_OFFSET.x*(self.config.scale)*self.config.lang.font.FONTSCALE/G.TILESIZE, - self.config.lang.font.TEXT_OFFSET.y*(self.config.scale)*self.config.lang.font.FONTSCALE/G.TILESIZE, - 0, - (self.config.scale)*self.config.lang.font.squish*self.config.lang.font.FONTSCALE/G.TILESIZE, - (self.config.scale)*self.config.lang.font.FONTSCALE/G.TILESIZE - ) - love.graphics.pop() - elseif self.UIT == G.UIT.B or self.UIT == G.UIT.C or self.UIT == G.UIT.R or self.UIT == G.UIT.ROOT then - prep_draw(self, 1) - love.graphics.scale(1/(G.TILESIZE)) - if self.config.shadow and G.SETTINGS.GRAPHICS.shadows == 'On' then - love.graphics.scale(0.98) - if self.config.shadow_colour then - love.graphics.setColor(self.config.shadow_colour) - else - love.graphics.setColor(0,0,0,0.3*self.config.colour[4]) - end - if self.config.r and self.VT.w > 0.01 then - self:draw_pixellated_rect('shadow', parallax_dist) - else - love.graphics.rectangle('fill', -self.shadow_parrallax.x*parallax_dist, -self.shadow_parrallax.y*parallax_dist, self.VT.w*G.TILESIZE, self.VT.h*G.TILESIZE) - end - love.graphics.scale(1/0.98) - end - - love.graphics.scale(button_being_pressed and 0.985 or 1) - if self.config.emboss then - love.graphics.setColor(darken(self.config.colour, self.states.hover.is and 0.5 or 0.3, true)) - self:draw_pixellated_rect('emboss', parallax_dist, self.config.emboss) - end - local collided_button = self.config.button_UIE or self - self.ARGS.button_colours = self.ARGS.button_colours or {} - self.ARGS.button_colours[1] = self.config.button_delay and mix_colours(self.config.colour, G.C.L_BLACK, 0.5) or self.config.colour - self.ARGS.button_colours[2] = (((collided_button.config.hover and collided_button.states.hover.is) or (collided_button.last_clicked and collided_button.last_clicked > G.TIMERS.REAL - 0.1)) and G.C.UI.HOVER or nil) - for k, v in ipairs(self.ARGS.button_colours) do - love.graphics.setColor(v) - if self.config.r and self.VT.w > 0.01 then - if self.config.button_delay then - love.graphics.setColor(G.C.GREY) - self:draw_pixellated_rect('fill', parallax_dist) - love.graphics.setColor(v) - self:draw_pixellated_rect('fill', parallax_dist, nil, self.config.button_delay_progress) - elseif self.config.progress_bar then - love.graphics.setColor(self.config.progress_bar.empty_col or G.C.GREY) - self:draw_pixellated_rect('fill', parallax_dist) - love.graphics.setColor(self.config.progress_bar.filled_col or G.C.BLUE) - self:draw_pixellated_rect('fill', parallax_dist, nil, self.config.progress_bar.ref_table[self.config.progress_bar.ref_value]/self.config.progress_bar.max) - else - self:draw_pixellated_rect('fill', parallax_dist) - end - else - love.graphics.rectangle('fill', 0,0, self.VT.w*G.TILESIZE, self.VT.h*G.TILESIZE) - end - end - love.graphics.pop() - elseif self.UIT == G.UIT.O and self.config.object then - --Draw the outline for highlighted objext - if self.config.focus_with_object and self.config.object.states.focus.is then - self.object_focus_timer = self.object_focus_timer or G.TIMERS.REAL - local lw = 50*math.max(0, self.object_focus_timer - G.TIMERS.REAL + 0.3)^2 - prep_draw(self, 1) - love.graphics.scale((1)/(G.TILESIZE)) - love.graphics.setLineWidth(lw + 1.5) - love.graphics.setColor(adjust_alpha(G.C.WHITE, 0.2*lw, true)) - self:draw_pixellated_rect('fill', parallax_dist) - love.graphics.setColor(self.config.colour[4] > 0 and mix_colours(G.C.WHITE, self.config.colour, 0.8) or G.C.WHITE) - self:draw_pixellated_rect('line', parallax_dist) - love.graphics.pop() - else - self.object_focus_timer = nil - end - self.config.object:draw() - end - end - - --Draw the outline of the object - if self.config.outline and self.config.outline_colour[4] > 0.01 then - if self.config.outline then - prep_draw(self, 1) - love.graphics.scale(1/(G.TILESIZE)) - love.graphics.setLineWidth(self.config.outline) - if self.config.line_emboss then - love.graphics.setColor(darken(self.config.outline_colour, self.states.hover.is and 0.5 or 0.3, true)) - self:draw_pixellated_rect('line_emboss', parallax_dist, self.config.line_emboss) - end - love.graphics.setColor(self.config.outline_colour) - if self.config.r and self.VT.w > 0.01 then - self:draw_pixellated_rect('line', parallax_dist) - else - love.graphics.rectangle('line', 0,0, self.VT.w*G.TILESIZE, self.VT.h*G.TILESIZE) - end - love.graphics.pop() - end - end - - --Draw the outline for highlighted buttons - if self.states.focus.is then - self.focus_timer = self.focus_timer or G.TIMERS.REAL - local lw = 50*math.max(0, self.focus_timer - G.TIMERS.REAL + 0.3)^2 - prep_draw(self, 1) - love.graphics.scale((1)/(G.TILESIZE)) - love.graphics.setLineWidth(lw + 1.5) - love.graphics.setColor(adjust_alpha(G.C.WHITE, 0.2*lw, true)) - self:draw_pixellated_rect('fill', parallax_dist) - love.graphics.setColor(self.config.colour[4] > 0 and mix_colours(G.C.WHITE, self.config.colour, 0.8) or G.C.WHITE) - self:draw_pixellated_rect('line', parallax_dist) - love.graphics.pop() - else - self.focus_timer = nil - end - - --Draw the 'chosen triangle' - if self.config.chosen then - prep_draw(self, 0.98) - love.graphics.scale(1/(G.TILESIZE)) - if self.config.shadow and G.SETTINGS.GRAPHICS.shadows == 'On' then - love.graphics.setColor(0,0,0,0.3*self.config.colour[4]) - love.graphics.polygon("fill", get_chosen_triangle_from_rect(self.layered_parallax.x - self.shadow_parrallax.x*parallax_dist*0.5, self.layered_parallax.y - self.shadow_parrallax.y*parallax_dist*0.5, self.VT.w*G.TILESIZE, self.VT.h*G.TILESIZE, self.config.chosen == 'vert')) - end - love.graphics.pop() - - prep_draw(self, 1) - love.graphics.scale(1/(G.TILESIZE)) - love.graphics.setColor(G.C.RED) - love.graphics.setColor(self.config.colour) - love.graphics.polygon("fill", get_chosen_triangle_from_rect(self.layered_parallax.x, self.layered_parallax.y, self.VT.w*G.TILESIZE, self.VT.h*G.TILESIZE, self.config.chosen == 'vert')) - love.graphics.pop() - end - self:draw_boundingrect() -end - -function UIElement:draw_pixellated_rect(_type, _parallax, _emboss, _progress) - if not self.pixellated_rect or - #self.pixellated_rect[_type].vertices < 1 or - _parallax ~= self.pixellated_rect.parallax or - self.pixellated_rect.w ~= self.VT.w or - self.pixellated_rect.h ~= self.VT.h or - self.pixellated_rect.sw ~= self.shadow_parrallax.x or - self.pixellated_rect.sh ~= self.shadow_parrallax.y or - self.pixellated_rect.progress ~= (_progress or 1) - then - self.pixellated_rect = { - w = self.VT.w, - h = self.VT.h, - sw = self.shadow_parrallax.x, - sh = self.shadow_parrallax.y, - progress = (_progress or 1), - fill = {vertices = {}}, - shadow = {vertices = {}}, - line = {vertices = {}}, - emboss = {vertices = {}}, - line_emboss = {vertices = {}}, - parallax = _parallax - } - local ext_up = self.config.ext_up and self.config.ext_up*G.TILESIZE or 0 - local res = self.config.res or math.min(self.VT.w, self.VT.h + math.abs(ext_up)/G.TILESIZE) > 3.5 and 0.8 or math.min(self.VT.w, self.VT.h + math.abs(ext_up)/G.TILESIZE) > 0.3 and 0.6 or 0.15 - local totw, toth, subw, subh = self.VT.w*G.TILESIZE, (self.VT.h + math.abs(ext_up)/G.TILESIZE)*G.TILESIZE, self.VT.w*G.TILESIZE-4*res, (self.VT.h + math.abs(ext_up)/G.TILESIZE)*G.TILESIZE-4*res - - local vertices = { - subw/2, subh/2-ext_up, - 0,4*res-ext_up, - 1*res,4*res-ext_up, - 1*res,2*res-ext_up, - 2*res,2*res-ext_up, - 2*res,1*res-ext_up, - 4*res,1*res-ext_up, - 4*res,0*res-ext_up, - subw,0*res-ext_up, - subw,1*res-ext_up, - subw+2*res,1*res-ext_up, - subw+2*res,2*res-ext_up, - subw+3*res,2*res-ext_up, - subw+3*res,4*res-ext_up, - totw,4*res-ext_up, - totw,subh-ext_up, - subw+3*res, subh-ext_up, - subw+3*res, subh+2*res-ext_up, - subw+2*res, subh+2*res-ext_up, - subw+2*res, subh+3*res-ext_up, - subw, subh+3*res-ext_up, - subw, toth-ext_up, - 4*res, toth-ext_up, - 4*res, subh+3*res-ext_up, - 2*res, subh+3*res-ext_up, - 2*res, subh+2*res-ext_up, - 1*res, subh+2*res-ext_up, - 1*res, subh-ext_up, - 0, subh-ext_up, - 0,4*res-ext_up, - } - for k, v in ipairs(vertices) do - if k%2 == 1 and v > totw*self.pixellated_rect.progress then v = totw*self.pixellated_rect.progress end - self.pixellated_rect.fill.vertices[k] = v - if k > 4 then - self.pixellated_rect.line.vertices[k-4] = v - if _emboss then - self.pixellated_rect.line_emboss.vertices[k-4] = v + (k%2 == 0 and -_emboss*self.shadow_parrallax.y or -0.7*_emboss*self.shadow_parrallax.x) - end - end - if k%2 == 0 then - self.pixellated_rect.shadow.vertices[k] = v -self.shadow_parrallax.y*_parallax - if _emboss then - self.pixellated_rect.emboss.vertices[k] = v + _emboss*G.TILESIZE - end - else - self.pixellated_rect.shadow.vertices[k] = v -self.shadow_parrallax.x*_parallax - if _emboss then - self.pixellated_rect.emboss.vertices[k] = v - end - end - end - end - - love.graphics.polygon((_type == 'line' or _type == 'line_emboss') and 'line' or "fill", self.pixellated_rect[_type].vertices) -end - -function UIElement:update(dt) - G.ARGS.FUNC_TRACKER = G.ARGS.FUNC_TRACKER or {} - if self.config.button_delay then - self.config.button_temp = self.config.button or self.config.button_temp - self.config.button = nil - self.config.button_delay_progress = (G.TIMERS.REAL - self.config.button_delay_start)/self.config.button_delay - if G.TIMERS.REAL >= self.config.button_delay_end then self.config.button_delay = nil end - end - if self.config.button_temp and not self.config.button_delay then self.config.button = self.config.button_temp end - if self.button_clicked then self.button_clicked = nil end - if self.config and self.config.func then - G.ARGS.FUNC_TRACKER[self.config.func] = (G.ARGS.FUNC_TRACKER[self.config.func] or 0) + 1 - G.FUNCS[self.config.func](self) - end - if self.UIT == G.UIT.T then self:update_text() end - if self.UIT == G.UIT.O then self:update_object() end - Node.update(self, dt) -end - -function UIElement:collides_with_point(cursor_trans) - if self.UIBox.states.collide.can then - return Node.collides_with_point(self, cursor_trans) - else - return false - end -end - -function UIElement:click() - if self.config.button and (not self.last_clicked or self.last_clicked + 0.1 < G.TIMERS.REAL) and self.states.visible and not self.under_overlay and not self.disable_button then - if self.config.one_press then self.disable_button = true end - self.last_clicked = G.TIMERS.REAL - - --Removes a layer from the overlay menu stack - if self.config.id == 'overlay_menu_back_button' then - G.CONTROLLER:mod_cursor_context_layer(-1) - G.NO_MOD_CURSOR_STACK = true - end - if G.OVERLAY_TUTORIAL and G.OVERLAY_TUTORIAL.button_listen == self.config.button then - G.FUNCS.tut_next() - end - G.FUNCS[self.config.button](self) - - G.NO_MOD_CURSOR_STACK = nil - - if self.config.choice then - local chosen_temp = self.config.chosen - local chosen_temp = self.config.chosen - local choices = self.UIBox:get_group(nil, self.config.group) - for k, v in pairs(choices) do - if v.config and v.config.choice then v.config.chosen = false end - end - self.config.chosen = chosen_temp or true - end - play_sound('button', 1, 0.3) - G.ROOM.jiggle = G.ROOM.jiggle + 0.5 - self.button_clicked = true - end - if self.config.button_UIE then - self.config.button_UIE:click() - end -end - -function UIElement:put_focused_cursor() - if self.config.focus_args and self.config.focus_args.type == 'tab' then - for k, v in pairs(self.children) do - if v.children[1].config.chosen then return v.children[1]:put_focused_cursor() end - end - else - return Node.put_focused_cursor(self) - end -end - -function UIElement:remove() - if self.config and self.config.object then - self.config.object:remove() - self.config.object = nil - end - - if self == G.CONTROLLER.text_input_hook then - G.CONTROLLER.text_input_hook = nil - end - remove_all(self.children) - - Moveable.remove(self) -end - -function UIElement:hover() - if self.config and self.config.on_demand_tooltip then - self.config.h_popup = create_popup_UIBox_tooltip(self.config.on_demand_tooltip) - self.config.h_popup_config ={align=self.T.y > G.ROOM.T.h/2 and 'tm' or 'bm', offset = {x=0,y=self.T.y > G.ROOM.T.h/2 and -0.1 or 0.1}, parent = self} - end - if self.config.tooltip then - self.config.h_popup = create_popup_UIBox_tooltip(self.config.tooltip) - self.config.h_popup_config ={align="tm", offset = {x=0,y=-0.1}, parent = self} - end - if self.config.detailed_tooltip and G.CONTROLLER.HID.pointer then - self.config.h_popup = create_UIBox_detailed_tooltip(self.config.detailed_tooltip) - self.config.h_popup_config ={align="tm", offset = {x=0,y=-0.1}, parent = self} - end - Node.hover(self) -end - -function UIElement:stop_hover() - Node.stop_hover(self) - if self.config and self.config.on_demand_tooltip then - self.config.h_popup = nil - end -end - -function UIElement:release(other) - if self.parent then self.parent:release(other) end -end - -function is_UI_containter(node) - if node.UIT ~= G.UIT.C and node.UIT ~= G.UIT.R and node.UIT ~= G.UIT.ROOT then - return false - end - return true -end diff --git a/lovely/dump/functions/UI_definitions.lua b/lovely/dump/functions/UI_definitions.lua deleted file mode 100644 index 5dacb9d..0000000 --- a/lovely/dump/functions/UI_definitions.lua +++ /dev/null @@ -1,6479 +0,0 @@ -LOVELY_INTEGRITY = '824fe1307b104cf5bc0a6245ef8c8e76db9af62d790ab2106537987e589dd59b' - ---Create a global UIDEF that contains all UI definition functions\ ---As a rule, these contain functions that return a table T representing the definition for a UIBox -G.UIDEF = {} - -function create_UIBox_debug_tools() -local debugplus = require("debugplus.core") -debugplus.registerButtons() - G.debug_tool_config = G.debug_tool_config or {} - G.FUNCS.DT_add_money = function() if G.STAGE == G.STAGES.RUN then ease_dollars(10) end end - G.FUNCS.DT_add_round = function() if G.STAGE == G.STAGES.RUN then ease_round(1) end end - G.FUNCS.DT_add_ante = function() if G.STAGE == G.STAGES.RUN then ease_ante(1) end end - G.FUNCS.DT_add_hand = function() if G.STAGE == G.STAGES.RUN then ease_hands_played(1) end end - G.FUNCS.DT_add_discard = function() if G.STAGE == G.STAGES.RUN then ease_discard(1) end end - G.FUNCS.DT_reroll_boss = function() if G.STAGE == G.STAGES.RUN and G.blind_select_opts then G.from_boss_tag = true; G.FUNCS.reroll_boss(); G.from_boss_tag = nil end end - G.FUNCS.DT_toggle_background = function() G.debug_background_toggle = not G.debug_background_toggle end - G.FUNCS.DT_add_chips = function() if G.STAGE == G.STAGES.RUN then update_hand_text({delay = 0}, {chips = 10 + G.GAME.current_round.current_hand.chips}); play_sound('chips1') end end - G.FUNCS.DT_add_mult = function() if G.STAGE == G.STAGES.RUN then update_hand_text({delay = 0}, {mult = 10 + G.GAME.current_round.current_hand.mult}); play_sound('multhit1') end end - G.FUNCS.DT_x_chips = function() if G.STAGE == G.STAGES.RUN then update_hand_text({delay = 0}, {chips = 2*G.GAME.current_round.current_hand.chips}); play_sound('chips1') end end - G.FUNCS.DT_x_mult = function() if G.STAGE == G.STAGES.RUN then update_hand_text({delay = 0}, {mult = 10*G.GAME.current_round.current_hand.mult}); play_sound('multhit2') end end - G.FUNCS.DT_chip_mult_reset = function() if G.STAGE == G.STAGES.RUN then update_hand_text({delay = 0}, {mult = 0, chips = 0}) end end - G.FUNCS.DT_win_game = function() if G.STAGE == G.STAGES.RUN then win_game() end end - G.FUNCS.DT_lose_game = function() if G.STAGE == G.STAGES.RUN then G.STATE = G.STATES.GAME_OVER; G.STATE_COMPLETE = false end end - G.FUNCS.DT_jimbo_toggle = function() - if G.DT_jimbo then - if G.DT_jimbo.children.particles.states.visible then - if G.DT_jimbo.children.card.states.visible then - G.DT_jimbo.children.card.states.visible = false - else - G.DT_jimbo.children.card.states.visible = true - G.DT_jimbo.children.particles.states.visible = false - end - else - G.DT_jimbo:remove() - G.DT_jimbo = nil - if G.SPLASH_LOGO then - G.SPLASH_LOGO.states.visible = true - if G.title_top and G.title_top.cards[1] then G.title_top.cards[1].states.visible = true end - end - end - else - if G.SPLASH_LOGO then - G.SPLASH_LOGO.states.visible = false - if G.title_top and G.title_top.cards[1] then G.title_top.cards[1].states.visible = false end - end - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.4, - blockable = false, - func = function() - G.DT_jimbo = Card_Character({x = G.ROOM.T.w/2,y = G.ROOM.T.h/2}) - - G.DT_jimbo:set_alignment{ - major = G.ROOM_ATTACH, - type = 'cm' - } - return true - end - })) - - end end - G.FUNCS.DT_jimbo_talk = function() - if G.DT_jimbo then - G.DT_jimbo:add_speech_bubble({ - " ", - " ", - " ", - }, 'cr') - G.DT_jimbo:say_stuff(4) end - end - - local t = {n=G.UIT.ROOT, config = {align = 'cm', r = 0.1}, nodes={ - UIBox_dyn_container({ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "While in collection, hover over a card", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "and press the following keys:", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, colour = G.C.BLUE, emboss = 0.05, r = 0.1}, nodes={ - {n=G.UIT.T, config={text = "[1] Unlock", scale = 0.25, colour = G.C.WHITE}} - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.05, colour = G.C.BLUE, emboss = 0.05, r = 0.1}, nodes={ - {n=G.UIT.T, config={text = "[2] Discover", scale = 0.25, colour = G.C.WHITE}} - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.05, colour = G.C.BLUE, emboss = 0.05, r = 0.1}, nodes={ - {n=G.UIT.T, config={text = "[3] Spawn", scale = 0.25, colour = G.C.WHITE}} - }} - }} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "Hover over any Joker/Playing card", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "hold [" .. require("debugplus.util").ctrlText .. "] (togglable in config)", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "and press [Q] to cycle Edition", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [W] to cycle Enhancement", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [E] to cycle Seal", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [A/S/D] to toggle Eternal/Perishable/Rental", scale = 0.2, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [F] to toggle Coupon (make free)", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [R/C] to destroy/copy card", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [M] to reload atlases", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [UP/DOWN] to cycle rank", scale = 0.2, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.00}, nodes={ - {n=G.UIT.T, config={text = "press [RIGHT/LEFT] to cycle suit", scale = 0.2, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [z] plus [1-3] to save a save state", scale = 0.2, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.00}, nodes={ - {n=G.UIT.T, config={text = "press [x] plus [1-3] to load a save state", scale = 0.2, colour = G.C.WHITE, shadow = true}} - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "Press [H] to isolate background", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "Press [J] to play splash animation", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "Press [8] to toggle cursor", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "Press [9] to toggle all tooltips", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.15}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes={ - UIBox_button{ label = {"$10"}, button = "DT_add_money", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"+1 Round"}, button = "DT_add_round", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"+1 Ante"}, button = "DT_add_ante", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"+1 Hand"}, button = "DT_add_hand", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"+1 Discard"}, button = "DT_add_discard", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"Boss Reroll"}, button = "DT_reroll_boss", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"Background"}, button = "DT_toggle_background", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"Win Blind"}, button = "DT_win_blind", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"Double Tag"}, button = "DT_double_tag", minw = 1.7, minh = 0.4, scale = 0.35}, - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes={ - UIBox_button{ label = {"+10 chips"}, button = "DT_add_chips", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"+10 mult"}, button = "DT_add_mult", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"X2 chips"}, button = "DT_x_chips", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"X10 mult"}, button = "DT_x_mult", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"Win this Run"}, button = "DT_win_game", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"Lose this Run"}, button = "DT_lose_game", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"Reset"}, button = "DT_chip_mult_reset", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"Jimbo"}, button = "DT_jimbo_toggle", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"Jimbo talk"}, button = "DT_jimbo_talk", minw = 1.7, minh = 0.4, scale = 0.35}, - }} - }} - }, true) - }} - return t -end - -function create_UIBox_notify_alert(_achievement, _type) - local _c, _atlas = G.P_CENTERS[_achievement], - _type == 'Joker' and G.ASSET_ATLAS["Joker"] or - _type == 'Voucher' and G.ASSET_ATLAS["Voucher"] or - _type == 'Back' and G.ASSET_ATLAS["centers"] or - G.ASSET_ATLAS["icons"] - local _smods_atlas = _c and ((G.SETTINGS.colourblind_option and _c.hc_atlas or _c.lc_atlas) or _c.atlas) - if _smods_atlas then - _atlas = G.ASSET_ATLAS[_smods_atlas] or _atlas - end - - if SMODS.Achievements[_achievement] then _c = SMODS.Achievements[_achievement]; _atlas = G.ASSET_ATLAS[_c.atlas] end - local t_s = Sprite(0,0,1.5*(_atlas.px/_atlas.py),1.5,_atlas, _c and _c.pos or {x=3, y=0}) - t_s.states.drag.can = false - t_s.states.hover.can = false - t_s.states.collide.can = false - - local subtext = _type == 'achievement' and localize(G.F_TROPHIES and 'k_trophy' or 'k_achievement') or - _type == 'Joker' and localize('k_joker') or - _type == 'Voucher' and localize('k_voucher') or - _type == 'Back' and localize('k_deck') or 'ERROR' - - if _achievement == 'b_challenge' then subtext = localize('k_challenges') end - local name = _type == 'achievement' and localize(_achievement, 'achievement_names') or 'ERROR' - - local t = {n=G.UIT.ROOT, config = {align = 'cl', r = 0.1, padding = 0.06, colour = G.C.UI.TRANSPARENT_DARK}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0.2, minw = 20, r = 0.1, colour = G.C.BLACK, outline = 1.5, outline_colour = G.C.GREY}, nodes={ - {n=G.UIT.R, config={align = "cm", r = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", r = 0.1}, nodes={ - {n=G.UIT.O, config={object = t_s}}, - }}, - _type ~= 'achievement' and {n=G.UIT.R, config={align = "cm", padding = 0.04}, nodes={ - {n=G.UIT.R, config={align = "cm", maxw = 3.4}, nodes={ - {n=G.UIT.T, config={text = subtext, scale = 0.5, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", maxw = 3.4}, nodes={ - {n=G.UIT.T, config={text = localize('k_unlocked_ex'), scale = 0.35, colour = G.C.FILTER, shadow = true}}, - }} - }} - or {n=G.UIT.R, config={align = "cm", padding = 0.04}, nodes={ - {n=G.UIT.R, config={align = "cm", maxw = 3.4, padding = 0.1}, nodes={ - {n=G.UIT.T, config={text = name, scale = 0.4, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", maxw = 3.4}, nodes={ - {n=G.UIT.T, config={text = subtext, scale = 0.3, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", maxw = 3.4}, nodes={ - {n=G.UIT.T, config={text = localize('k_unlocked_ex'), scale = 0.35, colour = G.C.FILTER, shadow = true}}, - }} - }} - }} - }} - }} - return t -end - -function create_UIBox_online_high_scores() - G.HTTP_MANAGER.out_channel:push({get_score = true}) - local padding, col, minw = 0.05, G.C.UI.TRANSPARENT_DARK, 0 - local t = {n=G.UIT.ROOT, config = {align = 'cm', minw=minw, r = 0.1, colour = col, padding = padding}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1, r = 0.1, colour = G.C.BLACK}, nodes={ - }} - }} - return t -end - -function create_UIBox_high_scores_filling(_resp) - local scores = {} - _resp = assert(loadstring(_resp))() - if not _resp then - return {n=G.UIT.ROOT, config = {align = 'cm', r = 0.1, colour = G.C.L_BLACK, padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1, minh = 1.3}, nodes={ - {n=G.UIT.T, config={text = 'ERROR', scale = 0.9, colour = G.C.RED, shadow = true}}, - }} - }} - end - for i = 1, 6 do - local v = _resp[i] or {username = '-'} - v.score = v.score and math.floor(v.score) or nil - local name_col = v.username == (G.SETTINGS.COMP and G.SETTINGS.COMP.name or nil) and G.C.FILTER or G.C.WHITE - scores[#scores+1] = {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cl", padding = 0, minw = 0.3}, nodes={ - {n=G.UIT.T, config={text = i..'.', scale = 0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.C, config={align = "cl", padding = 0, minw = 1.7, maxw = 1.6}, nodes={ - {n=G.UIT.T, config={text = (v.username), scale = math.min(0.6, 8*0.56/v.username:len()), colour = v.score and name_col or G.C.UI.TRANSPARENT_LIGHT, shadow = true}} - }}, - {n=G.UIT.C, config={align = "cl", minh = 0.8, r = 0.1, minw = 2.5, colour = G.C.BLACK, emboss = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, r = 0.1, minw = 2.6}, nodes={ - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {type(v.score) == 'number' and number_format(v.score) or ''}, colours = {G.C.RED},shadow = true, float = true,maxw = 2.5, scale = math.min(0.75, score_number_scale(1.5, v.score))})}}, - }}, - }}, - }}, - }} - end - return {n=G.UIT.ROOT, config = {align = 'cm', r = 0.1, colour = G.C.L_BLACK, padding = 0.05}, nodes=scores} -end - -function G.UIDEF.use_and_sell_buttons(card) - local sell = nil - local use = nil - if card.area and card.area.config.type == 'joker' then - sell = {n=G.UIT.C, config={align = "cr"}, nodes={ - {n=G.UIT.C, config={ref_table = card, align = "cr",padding = 0.1, r=0.08, minw = 1.25, hover = true, shadow = true, colour = G.C.UI.BACKGROUND_INACTIVE, one_press = true, button = 'sell_card', func = 'can_sell_card'}, nodes={ - {n=G.UIT.B, config = {w=0.1,h=0.6}}, - {n=G.UIT.C, config={align = "tm"}, nodes={ - {n=G.UIT.R, config={align = "cm", maxw = 1.25}, nodes={ - {n=G.UIT.T, config={text = localize('b_sell'),colour = G.C.UI.TEXT_LIGHT, scale = 0.4, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = localize('$'),colour = G.C.WHITE, scale = 0.4, shadow = true}}, - {n=G.UIT.T, config={ref_table = card, ref_value = 'sell_cost_label',colour = G.C.WHITE, scale = 0.55, shadow = true}} - }} - }} - }}, - }} - end - if card.ability.consumeable then - if (card.area == G.pack_cards and G.pack_cards) then - return { - n=G.UIT.ROOT, config = {padding = 0, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={mid = true}, nodes={ - }}, - {n=G.UIT.R, config={ref_table = card, r = 0.08, padding = 0.1, align = "bm", minw = 0.5*card.T.w - 0.15, minh = 0.8*card.T.h, maxw = 0.7*card.T.w - 0.15, hover = true, shadow = true, colour = G.C.UI.BACKGROUND_INACTIVE, one_press = true, button = 'use_card', func = 'can_use_consumeable'}, nodes={ - {n=G.UIT.T, config={text = localize('b_use'),colour = G.C.UI.TEXT_LIGHT, scale = 0.55, shadow = true}} - }}, - }} - end - use = - {n=G.UIT.C, config={align = "cr"}, nodes={ - - {n=G.UIT.C, config={ref_table = card, align = "cr",maxw = 1.25, padding = 0.1, r=0.08, minw = 1.25, minh = (card.area and card.area.config.type == 'joker') and 0 or 1, hover = true, shadow = true, colour = G.C.UI.BACKGROUND_INACTIVE, one_press = true, button = 'use_card', func = 'can_use_consumeable'}, nodes={ - {n=G.UIT.B, config = {w=0.1,h=0.6}}, - {n=G.UIT.T, config={text = localize('b_use'),colour = G.C.UI.TEXT_LIGHT, scale = 0.55, shadow = true}} - }} - }} - elseif card.area and card.area == G.pack_cards then - return { - n=G.UIT.ROOT, config = {padding = 0, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={ref_table = card, r = 0.08, padding = 0.1, align = "bm", minw = 0.5*card.T.w - 0.15, maxw = 0.9*card.T.w - 0.15, minh = 0.3*card.T.h, hover = true, shadow = true, colour = G.C.UI.BACKGROUND_INACTIVE, one_press = true, button = 'use_card', func = 'can_select_card'}, nodes={ - {n=G.UIT.T, config={text = localize('b_select'),colour = G.C.UI.TEXT_LIGHT, scale = 0.45, shadow = true}} - }}, - }} - end - local t = { - n=G.UIT.ROOT, config = {padding = 0, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.C, config={padding = 0.15, align = 'cl'}, nodes={ - {n=G.UIT.R, config={align = 'cl'}, nodes={ - sell - }}, - {n=G.UIT.R, config={align = 'cl'}, nodes={ - use - }}, - }}, - }} - return t -end - -function G.UIDEF.card_focus_ui(card) - local card_width = card.T.w + (card.ability.consumeable and -0.1 or card.ability.set == 'Voucher' and -0.16 or 0) - - local playing_card_colour = copy_table(G.C.WHITE) - playing_card_colour[4] = 1.5 - if G.hand and card.area == G.hand then ease_value(playing_card_colour, 4, -1.5, nil, 'REAL',nil, 0.2, 'quad') end - - local tcnx, tcny = card.T.x + card.T.w/2 - G.ROOM.T.w/2, card.T.y + card.T.h/2 - G.ROOM.T.h/2 - - local base_background = UIBox{ - T = {card.VT.x,card.VT.y,0,0}, - definition = - (not G.hand or card.area ~= G.hand) and {n=G.UIT.ROOT, config = {align = 'cm', minw = card_width + 0.3, minh = card.T.h + 0.3, r = 0.1, colour = adjust_alpha(G.C.BLACK, 0.7), outline_colour = lighten(G.C.JOKER_GREY, 0.5), outline = 1.5, line_emboss = 0.8}, nodes={ - {n=G.UIT.R, config={id = 'ATTACH_TO_ME'}, nodes={}} - }} or - {n=G.UIT.ROOT, config = {align = 'cm', minw = card_width, minh = card.T.h, r = 0.1, colour = playing_card_colour}, nodes={ - {n=G.UIT.R, config={id = 'ATTACH_TO_ME'}, nodes={}} - }}, - config = { - align = 'cm', - offset = {x= 0.007*tcnx*card.T.w, y = 0.007*tcny*card.T.h}, - parent = card, - r_bond = (not G.hand or card.area ~= G.hand) and 'Weak' or 'Strong' - } - } - - base_background.set_alignment = function() - local cnx, cny = card.T.x + card.T.w/2 - G.ROOM.T.w/2, card.T.y + card.T.h/2 - G.ROOM.T.h/2 - Moveable.set_alignment(card.children.focused_ui, {offset = {x= 0.007*cnx*card.T.w, y = 0.007*cny*card.T.h}}) - end - - local base_attach = base_background:get_UIE_by_ID('ATTACH_TO_ME') - - --The card UI can have BUY, REDEEM, USE, and SELL buttons depending on the context of the card - if card.area == G.shop_jokers and G.shop_jokers then --Add a buy button - local buy_and_use = nil - if card.ability.consumeable then - base_attach.children.buy_and_use = G.UIDEF.card_focus_button{ - card = card, parent = base_attach, type = 'buy_and_use', - func = 'can_buy_and_use', button = 'buy_from_shop', card_width = card_width - } - buy_and_use = true - end - base_attach.children.buy = G.UIDEF.card_focus_button{ - card = card, parent = base_attach, type = 'buy', - func = 'can_buy', button = 'buy_from_shop', card_width = card_width, buy_and_use = buy_and_use - } - end - if card.area == G.shop_vouchers and G.shop_vouchers then --Add a redeem button - base_attach.children.redeem = G.UIDEF.card_focus_button{ - card = card, parent = base_attach, type = 'buy', - func = 'can_redeem', button = 'redeem_from_shop', card_width = card_width - } - end - if card.area == G.shop_booster and G.shop_booster then --Add a redeem button - base_attach.children.redeem = G.UIDEF.card_focus_button{ - card = card, parent = base_attach, type = 'buy', - func = 'can_open', button = 'open_booster', card_width = card_width*0.85 - } - end - if ((card.area == G.consumeables and G.consumeables) or (card.area == G.pack_cards and G.pack_cards)) and - card.ability.consumeable then --Add a use button - base_attach.children.use = G.UIDEF.card_focus_button{ - card = card, parent = base_attach, type = 'use', - func = 'can_use_consumeable', button = 'use_card', card_width = card_width - } - end - if (card.area == G.pack_cards and G.pack_cards) and not card.ability.consumeable then --Add a use button - base_attach.children.use = G.UIDEF.card_focus_button{ - card = card, parent = base_attach, type = 'select', - func = 'can_select_card', button = 'use_card', card_width = card_width - } - end - if (card.area == G.jokers and G.jokers or card.area == G.consumeables and G.consumeables) and G.STATE ~= G.STATES.TUTORIAL then --Add a sell button - base_attach.children.sell = G.UIDEF.card_focus_button{ - card = card, parent = base_attach, type = 'sell', - func = 'can_sell_card', button = 'sell_card', card_width = card_width - } - end - - return base_background -end - -function G.UIDEF.card_focus_button(args) - if not args then return end - - local button_contents = {} - if args.type == 'sell' then - button_contents = - {n=G.UIT.C, config={align = "cl"}, nodes={ - {n=G.UIT.R, config={align = "cl", maxw = 1}, nodes={ - {n=G.UIT.T, config={text = localize('b_sell'),colour = G.C.UI.TEXT_LIGHT, scale = 0.4, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cl"}, nodes={ - {n=G.UIT.T, config={text = localize('$'),colour = G.C.WHITE, scale = 0.4, shadow = true}}, - {n=G.UIT.T, config={ref_table = args.card, ref_value = 'sell_cost_label',colour = G.C.WHITE, scale = 0.55, shadow = true}} - }} - }} - elseif args.type == 'buy' then - button_contents = {n=G.UIT.T, config={text = localize('b_buy'),colour = G.C.WHITE, scale = 0.5}} - elseif args.type == 'select' then - button_contents = {n=G.UIT.T, config={text = localize('b_select'),colour = G.C.WHITE, scale = 0.3}} - elseif args.type == 'redeem' then - button_contents = {n=G.UIT.T, config={text = localize('b_redeem'),colour = G.C.WHITE, scale = 0.5}} - elseif args.type == 'use' then - button_contents = {n=G.UIT.T, config={text = localize('b_use'),colour = G.C.WHITE, scale = 0.5}} - elseif args.type == 'buy_and_use' then - button_contents = - {n=G.UIT.C, config={align = "cr"}, nodes={ - {n=G.UIT.R, config={align = "cr", maxw = 1}, nodes={ - {n=G.UIT.T, config={text = localize('b_buy'),colour = G.C.UI.TEXT_LIGHT, scale = 0.4, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cr", maxw = 1}, nodes={ - {n=G.UIT.T, config={text = localize('b_and_use'),colour = G.C.WHITE, scale = 0.3, shadow = true}}, - }} - }} - end - - return UIBox{ - T = {args.card.VT.x,args.card.VT.y,0,0}, - definition = - {n=G.UIT.ROOT, config = {align = 'cm', colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={id = args.type == 'buy_and_use' and 'buy_and_use' or nil, ref_table = args.card, ref_parent = args.parent, align = args.type == 'sell' and 'cl' or 'cr', colour = G.C.BLACK, shadow = true, r = 0.08, func = args.func, one_press = true, button = args.button, focus_args = {type = 'none'}, hover = true}, nodes={ - {n=G.UIT.R, config={align = args.type == 'sell' and 'cl' or 'cr', minw = 1 + (args.type == 'select' and 0.1 or 0), minh = args.type == 'sell' and 1.5 or 1, padding = 0.08, - focus_args = {button = args.type == 'sell' and 'leftshoulder' or args.type == 'buy_and_use' and 'leftshoulder' or 'rightshoulder', scale = 0.55, orientation = args.type == 'sell' and 'tli' or 'tri', offset = {x = args.type == 'sell' and 0.1 or -0.1, y = 0}, type = 'none'}, - func = 'set_button_pip'}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.3}, nodes={}}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - args.type ~= 'sell' and {n=G.UIT.C, config={align = "cm",minw = 0.2, minh = 0.6}, nodes={}} or nil, - {n=G.UIT.C, config={align = "cm", maxw = 1}, nodes={ - button_contents - }}, - args.type == 'sell' and {n=G.UIT.C, config={align = "cm",minw = 0.2, minh = 0.6}, nodes={}} or nil, - }} - }} - }} - }}, - config = { - align = args.type == 'sell' and 'cl' or 'cr', - offset = {x=(args.type == 'sell' and -1 or 1)*((args.card_width or 0) - 0.17 - args.card.T.w/2),y=args.type == 'buy_and_use' and 0.6 or (args.buy_and_use) and -0.6 or 0}, - parent = args.parent, - } - } -end - -function G.UIDEF.speech_bubble(text_key, loc_vars) - local text = {} - if loc_vars and loc_vars.quip then - localize{type = 'quips', key = text_key or 'lq_1', vars = loc_vars or {}, nodes = text} - else - localize{type = 'tutorial', key = text_key or 'sb_1', vars = loc_vars or {}, nodes = text} - end - local row = {} - for k, v in ipairs(text) do - row[#row+1] = {n=G.UIT.R, config={align = "cl"}, nodes=v} - end - local t = {n=G.UIT.ROOT, config = {align = "cm", minh = 1,r = 0.3, padding = 0.07, minw = 1, colour = G.C.JOKER_GREY, shadow = true}, nodes={ - {n=G.UIT.C, config={align = "cm", minh = 1,r = 0.2, padding = 0.1, minw = 1, colour = G.C.WHITE}, nodes={ - {n=G.UIT.C, config={align = "cm", minh = 1,r = 0.2, padding = 0.03, minw = 1, colour = G.C.WHITE}, nodes=row}} - } - }} - return t -end - -function create_UIBox_highlight(rect) - local t = {n=G.UIT.ROOT, config = {align = "cm", minh = rect.T.h+0.1, minw = rect.T.w+0.15, r = 0.15, colour = G.C.DARK_EDITION}, nodes={ - }} -return t -end - -function G.UIDEF.deck_preview(args) - - local _minh, _minw = 0.35, 0.5 - local suit_labels = {} - local suit_counts = { - Spades = 0, - Hearts = 0, - Clubs = 0, - Diamonds = 0 - } - local mod_suit_counts = { - Spades = 0, - Hearts = 0, - Clubs = 0, - Diamonds = 0 - } - local mod_suit_diff = false - local wheel_flipped, wheel_flipped_text = 0, nil - local flip_col = G.C.WHITE - local rank_counts = {} - local deck_tables = {} - remove_nils(G.playing_cards) - table.sort(G.playing_cards, function (a, b) return a:get_nominal('suit') > b:get_nominal('suit') end ) - local SUITS = { - Spades = {}, - Hearts = {}, - Clubs = {}, - Diamonds = {}, - } - - for k, v in pairs(SUITS) do - for i = 1, 14 do - SUITS[k][#SUITS[k]+1] = {} - end - end - - local suit_map = {'Spades', 'Hearts', 'Clubs', 'Diamonds'} - local SUITS_SORTED = Cartomancer.tablecopy(SUITS) - local stones = nil - local rank_name_mapping = {'A','K','Q','J','10',9,8,7,6,5,4,3,2} - - for k, v in ipairs(G.playing_cards) do - if v.ability.effect == 'Stone Card' then - stones = stones or 0 - end - if (v.area and v.area == G.deck) or v.ability.wheel_flipped then - if v.ability.wheel_flipped then wheel_flipped = wheel_flipped + 1 end - if v.ability.effect == 'Stone Card' then - stones = stones + 1 - else - for kk, vv in pairs(suit_counts) do - if v.base.suit == kk then suit_counts[kk] = suit_counts[kk] + 1 end - if v:is_suit(kk) then mod_suit_counts[kk] = mod_suit_counts[kk] + 1 end - end - if SUITS[v.base.suit][v.base.id] then - table.insert(SUITS[v.base.suit][v.base.id], v) - end - rank_counts[v.base.id] = (rank_counts[v.base.id] or 0) + 1 - end - end - end - - wheel_flipped_text = (wheel_flipped > 0) and {n=G.UIT.T, config={text = '?',colour = G.C.FILTER, scale =0.25, shadow = true}} or nil - flip_col = wheel_flipped_text and mix_colours(G.C.FILTER, G.C.WHITE,0.7) or G.C.WHITE - - suit_labels[#suit_labels+1] = {n=G.UIT.R, config={align = "cm", r = 0.1, padding = 0.04, minw = _minw, minh = 2*_minh+0.25}, nodes={ - stones and {n=G.UIT.T, config={text = localize('ph_deck_preview_stones')..': ',colour = G.C.WHITE, scale =0.25, shadow = true}} - or nil, - stones and {n=G.UIT.T, config={text = ''..stones,colour = (stones > 0 and G.C.WHITE or G.C.UI.TRANSPARENT_LIGHT), scale =0.4, shadow = true}} - or nil, - }} - - local _row = {} - local _bg_col = G.C.JOKER_GREY - for k, v in ipairs(rank_name_mapping) do - local _tscale = 0.3 - local _colour = G.C.BLACK - local rank_col = v == 'A' and _bg_col or (v == 'K' or v == 'Q' or v == 'J') and G.C.WHITE or _bg_col - rank_col = mix_colours(rank_col, _bg_col, 0.8) - - local _col = {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", r = 0.1, minw = _minw, minh = _minh, colour = rank_col, emboss = 0.04, padding = 0.03}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = ''..v,colour = _colour, scale =1.6*_tscale}}, - }}, - {n=G.UIT.R, config={align = "cm", minw = _minw+0.04, minh = _minh, colour = G.C.L_BLACK, r = 0.1}, nodes={ - {n=G.UIT.T, config={text = ''..(rank_counts[15 - k] or 0),colour = flip_col, scale =_tscale, shadow = true}} - }} - }} - }} - table.insert(_row, _col) - end - table.insert(deck_tables, {n=G.UIT.R, config={align = "cm", padding = 0.04}, nodes=_row}) - - for j = 1, 4 do - _row = {} - _bg_col = mix_colours(G.C.SUITS[suit_map[j]], G.C.L_BLACK, 0.7) - for i = 14, 2, -1 do - local _tscale = #SUITS[suit_map[j]][i] > 0 and 0.3 or 0.25 - local _colour = #SUITS[suit_map[j]][i] > 0 and flip_col or G.C.UI.TRANSPARENT_LIGHT - - local _col = {n=G.UIT.C, config={align = "cm",padding = 0.05, minw = _minw+0.098, minh = _minh}, nodes={ - {n=G.UIT.T, config={text = ''..#SUITS[suit_map[j]][i],colour = _colour, scale =_tscale, shadow = true, lang = G.LANGUAGES['en-us']}}, - }} - table.insert(_row, _col) - end - table.insert(deck_tables, {n=G.UIT.R, config={align = "cm", r = 0.1, padding = 0.04, minh = 0.4, colour = _bg_col}, nodes=_row}) - end - - for k, v in ipairs(suit_map) do - local _x = (v == 'Spades' and 3) or (v == 'Hearts' and 0) or (v == 'Clubs' and 2) or (v == 'Diamonds' and 1) - local t_s = Sprite(0,0,0.3,0.3,G.ASSET_ATLAS["ui_"..(G.SETTINGS.colourblind_option and 2 or 1)], {x=_x, y=1}) - t_s.states.drag.can = false - t_s.states.hover.can = false - t_s.states.collide.can = false - - if mod_suit_counts[v] ~= suit_counts[v] then mod_suit_diff = true end - - suit_labels[#suit_labels+1] = - {n=G.UIT.R, config={align = "cm", r = 0.1, padding = 0.03, colour = G.C.JOKER_GREY}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = _minw, minh = _minh}, nodes={ - {n=G.UIT.O, config={can_collide = false, object = t_s}} - }}, - {n=G.UIT.C, config={align = "cm", minw = _minw*2.4, minh = _minh, colour = G.C.L_BLACK, r = 0.1}, nodes={ - {n=G.UIT.T, config={text = ''..suit_counts[v],colour = flip_col, scale =0.3, shadow = true, lang = G.LANGUAGES['en-us']}}, - mod_suit_counts[v] ~= suit_counts[v] and {n=G.UIT.T, config={text = ' ('..mod_suit_counts[v]..')',colour = mix_colours(G.C.BLUE, G.C.WHITE,0.7), scale =0.28, shadow = true, lang = G.LANGUAGES['en-us']}} or nil, - }} - }} - end - - - local t = - {n=G.UIT.ROOT, config={align = "cm", colour = G.C.JOKER_GREY, r = 0.1, emboss = 0.05, padding = 0.07}, nodes={ - {n=G.UIT.R, config={align = "cm", r = 0.1, emboss = 0.05, colour = G.C.BLACK, padding = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.04}, nodes=suit_labels}, - {n=G.UIT.C, config={align = "cm", padding = 0.02}, nodes=deck_tables} - }}, - mod_suit_diff and {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={padding = 0.3, r = 0.1, colour = mix_colours(G.C.BLUE, G.C.WHITE,0.7)}, nodes = {}}, - {n=G.UIT.T, config={text =' '..localize('ph_deck_preview_effective'),colour = G.C.WHITE, scale =0.3}}, - }} or nil, - wheel_flipped_text and {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={padding = 0.3, r = 0.1, colour = flip_col}, nodes = {}}, - {n=G.UIT.T, config={text =' '..(wheel_flipped > 1 and - localize{type = 'variable', key = 'deck_preview_wheel_plural', vars = {wheel_flipped}} or - localize{type = 'variable', key = 'deck_preview_wheel_singular', vars = {wheel_flipped}}),colour = G.C.WHITE, scale =0.3}}, - }} or nil, - }} - }} - return t -end - -function create_UIBox_character_button(args) - local button = args.button or "NONE" - local func = args.func or nil - local colour = args.colour or G.C.RED - local update_func = args.update_func or nil - - local t = {n=G.UIT.ROOT, config = {align = "cm", padding = 0.1, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.C, config={align = "tm", minw = 1.9, padding = 0.2, minh = 1.2, r = 0.1, hover = true, colour = colour, button = func, func = update_func, shadow = true, maxw = args.maxw}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = button, scale = 0.55, colour = G.C.UI.TEXT_LIGHT, focus_args = {button = 'x', orientation = 'bm'}, func = 'set_button_pip'}} - }} - }}, - }} - return t -end - -function G.UIDEF.shop() - G.shop_jokers = CardArea( - G.hand.T.x+0, - G.hand.T.y+G.ROOM.T.y + 9, - math.min(G.GAME.shop.joker_max,4)*1.02*G.CARD_W, - 1.05*G.CARD_H, - {card_limit = G.GAME.shop.joker_max, type = 'shop', highlight_limit = 1}) - - - G.shop_vouchers = CardArea( - G.hand.T.x+0, - G.hand.T.y+G.ROOM.T.y + 9, - 2.1*G.CARD_W, - 1.05*G.CARD_H, - {card_limit = 1, type = 'shop', highlight_limit = 1}) - - G.shop_booster = CardArea( - G.hand.T.x+0, - G.hand.T.y+G.ROOM.T.y + 9, - 2.4*G.CARD_W, - 1.15*G.CARD_H, - {card_limit = 2, type = 'shop', highlight_limit = 1, card_w = 1.27*G.CARD_W}) - - local shop_sign = AnimatedSprite(0,0, 4.4, 2.2, G.ANIMATION_ATLAS['shop_sign']) - shop_sign:define_draw_steps({ - {shader = 'dissolve', shadow_height = 0.05}, - {shader = 'dissolve'} - }) - G.SHOP_SIGN = UIBox{ - definition = - {n=G.UIT.ROOT, config = {colour = G.C.DYN_UI.MAIN, emboss = 0.05, align = 'cm', r = 0.1, padding = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1, minw = 4.72, minh = 3.1, colour = G.C.DYN_UI.DARK, r = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = shop_sign}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('ph_improve_run')}, colours = {lighten(G.C.GOLD, 0.3)},shadow = true, rotate = true, float = true, bump = true, scale = 0.5, spacing = 1, pop_in = 1.5, maxw = 4.3})}} - }}, - }}, - }}, - config = { - align="cm", - offset = {x=0,y=-15}, - major = G.HUD:get_UIE_by_ID('row_blind'), - bond = 'Weak' - } - } - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - G.SHOP_SIGN.alignment.offset.y = 0 - return true - end) - })) - local t = {n=G.UIT.ROOT, config = {align = 'cl', colour = G.C.CLEAR}, nodes={ - UIBox_dyn_container({ - {n=G.UIT.C, config={align = "cm", padding = 0.1, emboss = 0.05, r = 0.1, colour = G.C.DYN_UI.BOSS_MAIN}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.R,config={id = 'next_round_button', align = "cm", minw = 2.8, minh = 1.5, r=0.15,colour = G.C.RED, one_press = true, button = 'toggle_shop', hover = true,shadow = true}, nodes = { - {n=G.UIT.R, config={align = "cm", padding = 0.07, focus_args = {button = 'y', orientation = 'cr'}, func = 'set_button_pip'}, nodes={ - {n=G.UIT.R, config={align = "cm", maxw = 1.3}, nodes={ - {n=G.UIT.T, config={text = localize('b_next_round_1'), scale = 0.4, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", maxw = 1.3}, nodes={ - {n=G.UIT.T, config={text = localize('b_next_round_2'), scale = 0.4, colour = G.C.WHITE, shadow = true}} - }} - }}, - }}, - {n=G.UIT.R, config={align = "cm", minw = 2.8, minh = 1.6, r=0.15,colour = G.C.GREEN, button = 'reroll_shop', func = 'can_reroll', hover = true,shadow = true}, nodes = { - {n=G.UIT.R, config={align = "cm", padding = 0.07, focus_args = {button = 'x', orientation = 'cr'}, func = 'set_button_pip'}, nodes={ - {n=G.UIT.R, config={align = "cm", maxw = 1.3}, nodes={ - {n=G.UIT.T, config={text = localize('k_reroll'), scale = 0.4, colour = G.C.WHITE, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", maxw = 1.3, minw = 1}, nodes={ - {n=G.UIT.T, config={text = localize('$'), scale = 0.7, colour = G.C.WHITE, shadow = true}}, - {n=G.UIT.T, config={ref_table = G.GAME.current_round, ref_value = 'reroll_cost', scale = 0.75, colour = G.C.WHITE, shadow = true}}, - }} - }} - }}, - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.2, r=0.2, colour = G.C.L_BLACK, emboss = 0.05, minw = 8.2}, nodes={ - {n=G.UIT.O, config={object = G.shop_jokers}}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.2}, nodes={}}, - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.15, r=0.2, colour = G.C.L_BLACK, emboss = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.2, r=0.2, colour = G.C.BLACK, maxh = G.shop_vouchers.T.h+0.4}, nodes={ - {n=G.UIT.T, config={text = localize{type = 'variable', key = 'ante_x_voucher', vars = {G.GAME.round_resets.ante}}, scale = 0.45, colour = G.C.L_BLACK, vert = true}}, - {n=G.UIT.O, config={object = G.shop_vouchers}}, - }}, - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.15, r=0.2, colour = G.C.L_BLACK, emboss = 0.05}, nodes={ - {n=G.UIT.O, config={object = G.shop_booster}}, - }}, - }} - } - }, - - }, false) - }} - return t -end - - function create_card_for_shop(area) - if area == G.shop_jokers and G.SETTINGS.tutorial_progress and G.SETTINGS.tutorial_progress.forced_shop and G.SETTINGS.tutorial_progress.forced_shop[#G.SETTINGS.tutorial_progress.forced_shop] then - local t = G.SETTINGS.tutorial_progress.forced_shop - local _center = G.P_CENTERS[t[#t]] or G.P_CENTERS.c_empress - local card = Card(area.T.x + area.T.w/2, area.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, _center, {bypass_discovery_center = true, bypass_discovery_ui = true}) - t[#t] = nil - if not t[1] then G.SETTINGS.tutorial_progress.forced_shop = nil end - - create_shop_card_ui(card) - return card - else - local forced_tag = nil - for k, v in ipairs(G.GAME.tags) do - if not forced_tag then - forced_tag = v:apply_to_run({type = 'store_joker_create', area = area}) - if forced_tag then - for kk, vv in ipairs(G.GAME.tags) do - if vv:apply_to_run({type = 'store_joker_modify', card = forced_tag}) then break end - end - return forced_tag end - end - end - G.GAME.spectral_rate = G.GAME.spectral_rate or 0 - local total_rate = G.GAME.joker_rate + G.GAME.playing_card_rate - for _,v in ipairs(SMODS.ConsumableType.ctype_buffer) do - total_rate = total_rate + G.GAME[v:lower()..'_rate'] - end - local polled_rate = pseudorandom(pseudoseed('cdt'..G.GAME.round_resets.ante))*total_rate - local check_rate = 0 - -- need to preserve order to leave RNG unchanged - local rates = { - {type = 'Joker', val = G.GAME.joker_rate}, - {type = 'Tarot', val = G.GAME.tarot_rate}, - {type = 'Planet', val = G.GAME.planet_rate}, - {type = (G.GAME.used_vouchers["v_illusion"] and pseudorandom(pseudoseed('illusion')) > 0.6) and 'Enhanced' or 'Base', val = G.GAME.playing_card_rate}, - {type = 'Spectral', val = G.GAME.spectral_rate}, - } - for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do - if not (v == 'Tarot' or v == 'Planet' or v == 'Spectral') then - table.insert(rates, { type = v, val = G.GAME[v:lower()..'_rate'] }) - end - end - for _, v in ipairs(rates) do - if polled_rate > check_rate and polled_rate <= check_rate + v.val then - local card = create_card(v.type, area, nil, nil, nil, nil, nil, 'sho') - create_shop_card_ui(card, v.type, area) - G.E_MANAGER:add_event(Event({ - func = (function() - for k, v in ipairs(G.GAME.tags) do - if v:apply_to_run({type = 'store_joker_modify', card = card}) then break end - end - return true - end) - })) - if (v.type == 'Base' or v.type == 'Enhanced') and G.GAME.used_vouchers["v_illusion"] and pseudorandom(pseudoseed('illusion')) > 0.8 then - local edition_poll = pseudorandom(pseudoseed('illusion')) - local edition = {} - if edition_poll > 1 - 0.15 then edition.polychrome = true - elseif edition_poll > 0.5 then edition.holo = true - else edition.foil = true - end - card:set_edition(edition) - end - return card - end - check_rate = check_rate + v.val - end - end - end - - function create_shop_card_ui(card, type, area) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.43, - blocking = false, - blockable = false, - func = (function() - if card.opening then return true end - local t1 = { - n=G.UIT.ROOT, config = {minw = 0.6, align = 'tm', colour = darken(G.C.BLACK, 0.2), shadow = true, r = 0.05, padding = 0.05, minh = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", colour = lighten(G.C.BLACK, 0.1), r = 0.1, minw = 1, minh = 0.55, emboss = 0.05, padding = 0.03}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {{prefix = localize('$'), ref_table = card, ref_value = 'cost'}}, colours = {G.C.MONEY},shadow = true, silent = true, bump = true, pop_in = 0, scale = 0.5})}}, - }} - }} - local t2 = card.ability.set == 'Voucher' and { - n=G.UIT.ROOT, config = {ref_table = card, minw = 1.1, maxw = 1.3, padding = 0.1, align = 'bm', colour = G.C.GREEN, shadow = true, r = 0.08, minh = 0.94, func = 'can_redeem', one_press = true, button = 'redeem_from_shop', hover = true}, nodes={ - {n=G.UIT.T, config={text = localize('b_redeem'),colour = G.C.WHITE, scale = 0.4}} - }} or card.ability.set == 'Booster' and { - n=G.UIT.ROOT, config = {ref_table = card, minw = 1.1, maxw = 1.3, padding = 0.1, align = 'bm', colour = G.C.GREEN, shadow = true, r = 0.08, minh = 0.94, func = 'can_open', one_press = true, button = 'open_booster', hover = true}, nodes={ - {n=G.UIT.T, config={text = localize('b_open'),colour = G.C.WHITE, scale = 0.5}} - }} or { - n=G.UIT.ROOT, config = {ref_table = card, minw = 1.1, maxw = 1.3, padding = 0.1, align = 'bm', colour = G.C.GOLD, shadow = true, r = 0.08, minh = 0.94, func = 'can_buy', one_press = true, button = 'buy_from_shop', hover = true}, nodes={ - {n=G.UIT.T, config={text = localize('b_buy'),colour = G.C.WHITE, scale = 0.5}} - }} - local t3 = { - n=G.UIT.ROOT, config = {id = 'buy_and_use', ref_table = card, minh = 1.1, padding = 0.1, align = 'cr', colour = G.C.RED, shadow = true, r = 0.08, minw = 1.1, func = 'can_buy_and_use', one_press = true, button = 'buy_from_shop', hover = true, focus_args = {type = 'none'}}, nodes={ - {n=G.UIT.B, config = {w=0.1,h=0.6}}, - {n=G.UIT.C, config = {align = 'cm'}, nodes={ - {n=G.UIT.R, config = {align = 'cm', maxw = 1}, nodes={ - {n=G.UIT.T, config={text = localize('b_buy'),colour = G.C.WHITE, scale = 0.5}} - }}, - {n=G.UIT.R, config = {align = 'cm', maxw = 1}, nodes={ - {n=G.UIT.T, config={text = localize('b_and_use'),colour = G.C.WHITE, scale = 0.3}} - }}, - }} - }} - - - card.children.price = UIBox{ - definition = t1, - config = { - align="tm", - offset = {x=0,y=1.5}, - major = card, - bond = 'Weak', - parent = card - } - } - - card.children.buy_button = UIBox{ - definition = t2, - config = { - align="bm", - offset = {x=0,y=-0.3}, - major = card, - bond = 'Weak', - parent = card - } - } - - if card.ability.consumeable then --and card:can_use_consumeable(true, true) - card.children.buy_and_use_button = UIBox{ - definition = t3, - config = { - align="cr", - offset = {x=-0.3,y=0}, - major = card, - bond = 'Weak', - parent = card - } - } - end - - card.children.price.alignment.offset.y = card.ability.set == 'Booster' and 0.5 or 0.38 - - return true - end) - })) - end - - - function attention_text(args) - args = args or {} - args.text = args.text or 'test' - args.scale = args.scale or 1 - args.colour = copy_table(args.colour or G.C.WHITE) - args.hold = (args.hold or 0) + 0.1*(G.SPEEDFACTOR) - args.pos = args.pos or {x = 0, y = 0} - args.align = args.align or 'cm' - args.emboss = args.emboss or nil - - args.fade = 1 - - if args.cover then - args.cover_colour = copy_table(args.cover_colour or G.C.RED) - args.cover_colour_l = copy_table(lighten(args.cover_colour, 0.2)) - args.cover_colour_d = copy_table(darken(args.cover_colour, 0.2)) - else - args.cover_colour = copy_table(G.C.CLEAR) - end - - args.uibox_config = { - align = args.align or 'cm', - offset = args.offset or {x=0,y=0}, - major = args.cover or args.major or nil, - } - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0, - blockable = false, - blocking = false, - func = function() - args.AT = UIBox{ - T = {args.pos.x,args.pos.y,0,0}, - definition = - {n=G.UIT.ROOT, config = {align = args.cover_align or 'cm', minw = (args.cover and args.cover.T.w or 0.001) + (args.cover_padding or 0), minh = (args.cover and args.cover.T.h or 0.001) + (args.cover_padding or 0), padding = 0.03, r = 0.1, emboss = args.emboss, colour = args.cover_colour}, nodes={ - {n=G.UIT.O, config={draw_layer = 1, object = DynaText({scale = args.scale, string = args.text, maxw = args.maxw, colours = {args.colour},float = true, shadow = true, silent = not args.noisy, args.scale, pop_in = 0, pop_in_rate = 6, rotate = args.rotate or nil})}}, - }}, - config = args.uibox_config - } - args.AT.attention_text = true - - args.text = args.AT.UIRoot.children[1].config.object - args.text:pulse(0.5) - - if args.cover then - Particles(args.pos.x,args.pos.y, 0,0, { - timer_type = 'TOTAL', - timer = 0.01, - pulse_max = 15, - max = 0, - scale = 0.3, - vel_variation = 0.2, - padding = 0.1, - fill=true, - lifespan = 0.5, - speed = 2.5, - attach = args.AT.UIRoot, - colours = {args.cover_colour, args.cover_colour_l, args.cover_colour_d}, - }) - end - if args.backdrop_colour then - args.backdrop_colour = copy_table(args.backdrop_colour) - Particles(args.pos.x,args.pos.y,0,0,{ - timer_type = 'TOTAL', - timer = 5, - scale = 2.4*(args.backdrop_scale or 1), - lifespan = 5, - speed = 0, - attach = args.AT, - colours = {args.backdrop_colour} - }) - end - return true - end - })) - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = args.hold, - blockable = false, - blocking = false, - func = function() - if not args.start_time then - args.start_time = G.TIMERS.TOTAL - args.text:pop_out(3) - else - --args.AT:align_to_attach() - args.fade = math.max(0, 1 - 3*(G.TIMERS.TOTAL - args.start_time)) - if args.cover_colour then args.cover_colour[4] = math.min(args.cover_colour[4], 2*args.fade) end - if args.cover_colour_l then args.cover_colour_l[4] = math.min(args.cover_colour_l[4], args.fade) end - if args.cover_colour_d then args.cover_colour_d[4] = math.min(args.cover_colour_d[4], args.fade) end - if args.backdrop_colour then args.backdrop_colour[4] = math.min(args.backdrop_colour[4], args.fade) end - args.colour[4] = math.min(args.colour[4], args.fade) - if args.fade <= 0 then - args.AT:remove() - return true - end - end - end - })) - end - - function create_UIBox_buttons() - if G.hand and G.hand.cart_sorting == nil then G.hand.cart_sorting = true end - local text_scale = 0.45 - local button_height = 1.3 - local play_button = {n=G.UIT.C, config={id = 'play_button', align = "tm", minw = 2.5, padding = 0.3, r = 0.1, hover = true, colour = G.C.BLUE, button = "play_cards_from_highlighted", one_press = true, shadow = true, func = 'can_play'}, nodes={ - {n=G.UIT.R, config={align = "bcm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = localize('b_play_hand'), scale = text_scale, colour = G.C.UI.TEXT_LIGHT, focus_args = {button = 'x', orientation = 'bm'}, func = 'set_button_pip'}} - }}, - }} - - local discard_button = {n=G.UIT.C, config={id = 'discard_button',align = "tm", padding = 0.3, r = 0.1, minw = 2.5, minh = button_height, hover = true, colour = G.C.RED, button = "discard_cards_from_highlighted", one_press = true, shadow = true, func = 'can_discard'}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = localize('b_discard'), scale = text_scale, colour = G.C.UI.TEXT_LIGHT, focus_args = {button = 'y', orientation = 'bm'}, func = 'set_button_pip'}} - }} - }} - - local t = { - n=G.UIT.ROOT, config = {align = "cm", minw = 1, minh = 0.3,padding = 0.15, r = 0.1, colour = G.C.CLEAR}, nodes={ - G.SETTINGS.play_button_pos == 1 and discard_button or play_button, - - {n=G.UIT.C, config={align = "cm", padding = 0.1, r = 0.1, colour =G.C.UI.TRANSPARENT_DARK, outline = 1.5, outline_colour = mix_colours(G.C.WHITE,G.C.JOKER_GREY, 0.7), line_emboss = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - Cartomancer.SETTINGS.improved_hand_sorting and - create_toggle{ col = true, label = localize('b_sort_hand'), label_scale = text_scale*0.8, scale = 0.30, w = 0, shadow = true, ref_table = G.hand, ref_value = 'cart_sorting', callback = function () G.FUNCS.cartomancer_sort_hand_off() end } - or - {n=G.UIT.T, config={text = localize('b_sort_hand'), scale = text_scale*0.8, colour = G.C.UI.TEXT_LIGHT}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", minh = 0.7, minw = 0.9, padding = 0.1, r = 0.1, hover = true, colour =G.C.ORANGE, button = "sort_hand_value", shadow = true}, nodes={ - {n=G.UIT.T, config={text = localize('k_rank'), scale = text_scale*0.7, colour = G.C.UI.TEXT_LIGHT}} - }}, - {n=G.UIT.C, config={align = "cm", minh = 0.7, minw = 0.9, padding = 0.1, r = 0.1, hover = true, colour =G.C.ORANGE, button = "sort_hand_suit", shadow = true}, nodes={ - {n=G.UIT.T, config={text = localize('k_suit'), scale = text_scale*0.7, colour = G.C.UI.TEXT_LIGHT}} - }} - }} - }} - }}, - - G.SETTINGS.play_button_pos == 1 and play_button or discard_button, - } - } - return t - end - - function desc_from_rows(desc_nodes, empty, maxw) - local t = {} - for k, v in ipairs(desc_nodes) do - t[#t+1] = {n=G.UIT.R, config={align = "cm", maxw = maxw}, nodes=v} - end - return {n=G.UIT.R, config={align = "cm", colour = desc_nodes.background_colour or empty and G.C.CLEAR or G.C.UI.BACKGROUND_WHITE, r = 0.1, padding = 0.04, minw = 2, minh = 0.8, emboss = not empty and 0.05 or nil, filler = true}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.03}, nodes=t} - }} - end - - function transparent_multiline_text(desc_nodes) - local t = {} - for k, v in ipairs(desc_nodes) do - t[#t+1] = {n=G.UIT.R, config={align = "cm", maxw = maxw}, nodes=v} - end - return {n=G.UIT.R, config={align = "cm", padding = 0.03}, nodes=t} - end - - function info_tip_from_rows(desc_nodes, name) - local t = {} - for k, v in ipairs(desc_nodes) do - t[#t+1] = {n=G.UIT.R, config={align = "cm"}, nodes=v} - end - return {n=G.UIT.R, config={align = "cm", colour = lighten(G.C.GREY, 0.15), r = 0.1}, nodes={ - {n=G.UIT.R, config={align = "tm", minh = 0.36, padding = 0.03}, nodes={{n=G.UIT.T, config={text = name, scale = 0.32, colour = G.C.UI.TEXT_LIGHT}}}}, - {n=G.UIT.R, config={align = "cm", minw = 1.5, minh = 0.4, r = 0.1, padding = 0.05, colour = desc_nodes.background_colour or G.C.WHITE}, nodes={{n=G.UIT.R, config={align = "cm", padding = 0.03}, nodes=t}}} - }} - end - - function overlay_infotip(text_rows) - local t = {} - if type(text_rows) ~= 'table' then text_rows = {"ERROR"} end - for k, v in ipairs(text_rows) do - t[#t+1] = {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = v,colour = G.C.UI.TEXT_LIGHT, scale = 0.45, juice = true, shadow = true, lang = text_rows.lang}} - }} - end - return {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR, padding = 0.1}, nodes=t} - end - - function name_from_rows(name_nodes, background_colour) - if not name_nodes or (type(name_nodes) ~= 'table') or not next(name_nodes) then return end - return {n=G.UIT.R, config={align = "cm", padding = 0.05, r = 0.1, colour = background_colour, emboss = background_colour and 0.05 or nil}, nodes=name_nodes} - end - - function G.UIDEF.card_h_popup(card) - if card.ability_UIBox_table then - local AUT = card.ability_UIBox_table - local debuffed = card.debuff - local card_type_colour = get_type_colour(card.config.center or card.config, card) - local card_type_background = - (AUT.card_type == 'Locked' and G.C.BLACK) or - ((AUT.card_type == 'Undiscovered') and darken(G.C.JOKER_GREY, 0.3)) or - (AUT.card_type == 'Enhanced' or AUT.card_type == 'Default') and darken(G.C.BLACK, 0.1) or - (debuffed and darken(G.C.BLACK, 0.1)) or - (card_type_colour and darken(G.C.BLACK, 0.1)) or - G.C.SET[AUT.card_type] or - {0, 1, 1, 1} - - local outer_padding = 0.05 - local card_type = localize('k_'..string.lower(AUT.card_type)) - - if AUT.card_type == 'Joker' or (AUT.badges and AUT.badges.force_rarity) then card_type = SMODS.Rarity:get_rarity_badge(card.config.center.rarity) end - if AUT.card_type == 'Enhanced' then card_type = localize{type = 'name_text', key = card.config.center.key, set = 'Enhanced'} end - card_type = (debuffed and AUT.card_type ~= 'Enhanced') and localize('k_debuffed') or card_type - - local disp_type, is_playing_card = - (AUT.card_type ~= 'Locked' and AUT.card_type ~= 'Undiscovered' and AUT.card_type ~= 'Default') or debuffed, - AUT.card_type == 'Enhanced' or AUT.card_type == 'Default' - - local info_boxes = {} - local badges = {} - - local obj = card.config.center - if AUT.badges.card_type or AUT.badges.force_rarity then - if obj and (obj.set_card_type_badge or obj.type and obj.type.set_card_type_badge) then - if obj.type and type(obj.type.set_card_type_badge) == 'function' then - obj.type:set_card_type_badge(obj, card, badges) - end - if type(obj.set_card_type_badge) == 'function' then - obj:set_card_type_badge(card, badges) - end - else - badges[#badges + 1] = create_badge(((card.ability.name == 'Pluto' or card.ability.name == 'Ceres' or card.ability.name == 'Eris') and localize('k_dwarf_planet')) or (card.ability.name == 'Planet X' and localize('k_planet_q') or card_type),card_type_colour, nil, 1.2) - end - end - if obj and obj.set_badges and type(obj.set_badges) == 'function' then - obj:set_badges(card, badges) - end - local function is_bad_badge(string) - local bad_badges = {'cry_pinned_booster', 'cry_pinned_voucher', 'cry_pinned_consumeable'} - for i = 1, #bad_badges do - if string == bad_badges[i] then return true end - end - return false - end - if AUT.badges then - for k, v in ipairs(AUT.badges) do - if v == 'negative_consumable' or v == 'negative_playing_card' then v = 'negative' end - if not is_bad_badge(v) then badges[#badges + 1] = create_badge(localize(v, "labels"), get_badge_colour(v)) end - end - end if AUT.card_type ~= 'Locked' and AUT.card_type ~= 'Undiscovered' then - SMODS.create_mod_badges(card.config.center, badges) - if card.base then - SMODS.create_mod_badges(SMODS.Ranks[card.base.value], badges) - SMODS.create_mod_badges(SMODS.Suits[card.base.suit], badges) - end - if card.config and card.config.tag then - SMODS.create_mod_badges(SMODS.Tags[card.config.tag.key], badges) - end - badges.mod_set = nil - end - - -- if AUT.badges then - -- for k, v in ipairs(AUT.badges) do - -- local replaced = false - -- if v == 'cry_pinned_booster' or v == 'cry_pinned_voucher' or v == 'cry_pinned_consumeable' then replaced = true; v = 'pinned_left' end - -- if replaced == true then badges[#badges + 1] = create_badge(localize(v, "labels"), get_badge_colour(v)) end - -- end - --end - if AUT.info then - for k, v in ipairs(AUT.info) do - info_boxes[#info_boxes+1] = - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", colour = lighten(G.C.JOKER_GREY, 0.5), r = 0.1, padding = 0.05, emboss = 0.05}, nodes={ - info_tip_from_rows(v, v.name), - }} - }} - end - end - - local cols - if #info_boxes <= 3 then - cols = 1 - elseif #info_boxes <= 10 then - cols = 2 - elseif #info_boxes <= 24 then - cols = 3 - else - cols = 4 - end - local nodes_per_col = math.ceil(#info_boxes/cols) - local info_cols = {} - for i = 0, cols-1 do - local col = {} - for j = 1, nodes_per_col do - local info_box = info_boxes[i*nodes_per_col+j] - if info_box then - table.insert(col, info_box) - else break end - end - table.insert(info_cols, {n=G.UIT.C, config = {align="cm"}, nodes = col}) - end - info_boxes = {{n=G.UIT.R, config = {align="cm", padding = 0.05, card_pos = card.T.x }, nodes = info_cols}} - return {n=G.UIT.ROOT, config = {align = 'cm', colour = G.C.CLEAR}, nodes={ - {n=G.UIT.C, config={align = "cm", func = 'show_infotip',object = Moveable(),ref_table = next(info_boxes) and info_boxes or nil}, nodes={ - {n=G.UIT.R, config={padding = outer_padding, r = 0.12, colour = lighten(G.C.JOKER_GREY, 0.5), emboss = 0.07}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.07, r = 0.1, colour = adjust_alpha(card_type_background, 0.8)}, nodes={ - name_from_rows(AUT.name, is_playing_card and G.C.WHITE or nil), - desc_from_rows(AUT.main), - badges[1] and {n=G.UIT.R, config={align = "cm", padding = 0.03}, nodes=badges} or nil, - }} - }} - }}, - }} - end - end - - function get_badge_colour(key) - G.BADGE_COL = G.BADGE_COL or { - eternal = G.C.ETERNAL, - perishable = G.C.PERISHABLE, - rental = G.C.RENTAL, - foil = G.C.DARK_EDITION, - holographic = G.C.DARK_EDITION, - polychrome = G.C.DARK_EDITION, - negative = G.C.DARK_EDITION, - gold_seal = G.C.GOLD, - red_seal = G.C.RED, - blue_seal = G.C.BLUE, - purple_seal = G.C.PURPLE, - pinned_left = G.C.ORANGE, - } - for _, v in ipairs(G.P_CENTER_POOLS.Edition) do - G.BADGE_COL[v.key:sub(3)] = v.badge_colour - end - for k, v in pairs(SMODS.Rarity.obj_buffer) do - G.BADGE_COL[k] = G.C.RARITY[v] - end - for k, v in pairs(SMODS.Seals) do - G.BADGE_COL[k:lower()..'_seal'] = v.badge_colour - end - for k, v in pairs(SMODS.Stickers) do - G.BADGE_COL[k] = v.badge_colour - end - return G.BADGE_COL[key] or {1, 0, 0, 1} - end - - function create_badge(_string, _badge_col, _text_col, scaling) - scaling = scaling or 1 - return {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", colour = _badge_col or G.C.GREEN, r = 0.1, minw = 2, minh = 0.4*scaling, emboss = 0.05, padding = 0.03*scaling}, nodes={ - {n=G.UIT.B, config={h=0.1,w=0.03}}, - {n=G.UIT.O, config={object = DynaText({string = _string or 'ERROR', colours = {_text_col or G.C.WHITE},float = true, shadow = true, offset_y = -0.05, silent = true, spacing = 1, scale = 0.33*scaling})}}, - {n=G.UIT.B, config={h=0.1,w=0.03}}, - }} - }} - end - - function create_UIBox_detailed_tooltip(_center) - local full_UI_table = { - main = {}, - info = {}, - type = {}, - name = 'done', - badges = badges or {} - } - local desc = generate_card_ui(_center, full_UI_table, nil, _center.set, nil) - return {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", colour = lighten(G.C.JOKER_GREY, 0.5), r = 0.1, padding = 0.05, emboss = 0.05}, nodes={ - info_tip_from_rows(desc.info[1], desc.info[1].name), - }} - }} - end - - function create_popup_UIBox_tooltip(tooltip) - local title = tooltip.title or nil - local text = tooltip.text or {} - local rows = {} - if title then - local r = {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = title,colour = G.C.UI.TEXT_DARK, scale = 0.4}}}}}} - table.insert(rows, r) - end - for i = 1, #text do - if type(text[i]) == 'table' then - local r = {n=G.UIT.R, config={align = "cm", padding = 0.03}, nodes={ - {n=G.UIT.T, config={ref_table = text[i].ref_table, ref_value = text[i].ref_value,colour = G.C.UI.TEXT_DARK, scale = 0.4}}}} - table.insert(rows, r) - else - local r = {n=G.UIT.R, config={align = "cm", padding = 0.03}, nodes={ - {n=G.UIT.T, config={text = text[i],colour = G.C.UI.TEXT_DARK, scale = 0.4}}}} - table.insert(rows, r) - end - end - if tooltip.filler then - table.insert(rows, tooltip.filler.func(tooltip.filler.args)) - end - local t = { - n=G.UIT.ROOT, config = {align = "cm", padding = 0.05, r=0.1, colour = G.C.RED, emboss = 0.05}, nodes= - {{n=G.UIT.C, config={align = "cm", padding = 0.05, r = 0.1, colour = G.C.WHITE, emboss = 0.05}, nodes=rows}}} - return t - end - -function create_UIBox_HUD_blind() - local scale = 0.4 - local stake_sprite = get_stake_sprite(G.GAME.stake or 1, 0.5) - G.GAME.blind:change_dim(1.5,1.5) - - return {n=G.UIT.ROOT, config={align = "cm", minw = 4.5, r = 0.1, colour = G.C.BLACK, emboss = 0.05, padding = 0.05, func = 'HUD_blind_visible', id = 'HUD_blind'}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.7, r = 0.1, emboss = 0.05, colour = G.C.DYN_UI.MAIN}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = 3}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME.blind, ref_value = 'loc_name'}}, colours = {G.C.UI.TEXT_LIGHT},shadow = true, rotate = true, silent = true, float = true, scale = 1.6*scale, y_offset = -4}),id = 'HUD_blind_name'}}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", minh = 2.74, r = 0.1,colour = G.C.DYN_UI.DARK}, nodes={ - {n=G.UIT.R, config={align = "cm", id = 'HUD_blind_debuff', func = 'HUD_blind_debuff'}, nodes={}}, - {n=G.UIT.R, config={align = "cm",padding = 0.15}, nodes={ - {n=G.UIT.O, config={object = G.GAME.blind, draw_layer = 1}}, - {n=G.UIT.C, config={align = "cm",r = 0.1, padding = 0.05, emboss = 0.05, minw = 2.9, colour = G.C.BLACK}, nodes={ - {n=G.UIT.R, config={align = "cm", maxw = 2.8}, nodes={ - {n=G.UIT.T, config={text = localize('ph_blind_score_at_least'), scale = 0.3, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.6}, nodes={ - {n=G.UIT.O, config={w=0.5,h=0.5, colour = G.C.BLUE, object = stake_sprite, hover = true, can_collide = false}}, - {n=G.UIT.B, config={h=0.1,w=0.1}}, - {n=G.UIT.T, config={ref_table = G.GAME.blind, ref_value = 'chip_text', scale = 0.001, colour = G.C.RED, shadow = true, id = 'HUD_blind_count', func = 'blind_chip_UI_scale'}} - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.45, maxw = 2.8, func = 'HUD_blind_reward'}, nodes={ - {n=G.UIT.T, config={text = localize('ph_blind_reward'), scale = 0.3, colour = G.C.WHITE}}, - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME.current_round, ref_value = 'dollars_to_be_earned'}}, colours = {G.C.MONEY},shadow = true, rotate = true, bump = true, silent = true, scale = 0.45}),id = 'dollars_to_be_earned'}}, - }}, - }}, - }}, - }}, - }} -end - -function add_tag(_tag) - G.HUD_tags = G.HUD_tags or {} - local tag_sprite_ui = _tag:generate_UI() - G.HUD_tags[#G.HUD_tags+1] = UIBox{ - definition = {n=G.UIT.ROOT, config={align = "cm",padding = 0.05, colour = G.C.CLEAR}, nodes={ - tag_sprite_ui - }}, - config = { - align = G.HUD_tags[1] and 'tm' or 'bri', - offset = G.HUD_tags[1] and {x=0,y=0} or {x=0.7,y=0}, - major = G.HUD_tags[1] and G.HUD_tags[#G.HUD_tags] or G.ROOM_ATTACH} - } - discover_card(G.P_TAGS[_tag.key]) - - for i = 1, #G.GAME.tags do - G.GAME.tags[i]:apply_to_run({type = 'tag_add', tag = _tag}) - end - - G.GAME.tags[#G.GAME.tags+1] = _tag - _tag.HUD_tag = G.HUD_tags[#G.HUD_tags] -end - -function create_UIBox_HUD() - local scale = 0.4 - local stake_sprite = get_stake_sprite(G.GAME.stake or 1, 0.5) - - local contents = {} - - local spacing = 0.13 - local temp_col = G.C.DYN_UI.BOSS_MAIN - local temp_col2 = G.C.DYN_UI.BOSS_DARK - contents.round = { - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={id = 'hud_hands',align = "cm", padding = 0.05, minw = 1.45, colour = temp_col, emboss = 0.05, r = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.33, maxw = 1.35}, nodes={ - {n=G.UIT.T, config={text = localize('k_hud_hands'), scale = 0.85*scale, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", r = 0.1, minw = 1.2, colour = temp_col2}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME.current_round, ref_value = 'hands_left'}}, font = G.LANGUAGES['en-us'].font, colours = {G.C.BLUE},shadow = true, rotate = true, scale = 2*scale}),id = 'hand_UI_count'}}, - }} - }}, - {n=G.UIT.C, config={minw = spacing},nodes={}}, - {n=G.UIT.C, config={align = "cm", padding = 0.05, minw = 1.45, colour = temp_col, emboss = 0.05, r = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.33, maxw = 1.35}, nodes={ - {n=G.UIT.T, config={text = localize('k_hud_discards'), scale = 0.85*scale, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", r = 0.1, minw = 1.2, colour = temp_col2}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME.current_round, ref_value = 'discards_left'}}, font = G.LANGUAGES['en-us'].font, colours = {G.C.RED},shadow = true, rotate = true, scale = 2*scale}),id = 'discard_UI_count'}}, - }} - }}, - }}, - }}, - {n=G.UIT.R, config={minh = spacing},nodes={}}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, minw = 1.45*2 + spacing, minh = 1.15, colour = temp_col, emboss = 0.05, r = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", r = 0.1, minw = 1.28*2+spacing, minh = 1, colour = temp_col2}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME, ref_value = 'dollars', prefix = localize('$')}}, - scale_function = function () - return scale_number(G.GAME.dollars, 2.2 * scale, 99999, 1000000) - end, maxw = 1.35, colours = {G.C.MONEY}, font = G.LANGUAGES['en-us'].font, shadow = true,spacing = 2, bump = true, scale = 2.2*scale}), id = 'dollar_text_UI'}} - }}, - }}, - }}, - }}, - {n=G.UIT.R, config={minh = spacing},nodes={}}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={id = 'hud_ante',align = "cm", padding = 0.05, minw = 1.45, minh = 1, colour = temp_col, emboss = 0.05, r = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.33, maxw = 1.35}, nodes={ - {n=G.UIT.T, config={text = localize('k_ante'), scale = 0.85*scale, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", r = 0.1, minw = 1.2, colour = temp_col2}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME.round_resets, ref_value = 'ante_disp'}}, colours = {G.C.IMPORTANT},shadow = true, font = G.LANGUAGES['en-us'].font, scale = scale_number(G.GAME.round_resets.ante, 2*scale, 100)}),id = 'ante_UI_count'}},--{n=G.UIT.T, config={text = number_format(G.GAME.round_resets.ante), lang = G.LANGUAGES['en-us'], scale = scale_number(G.GAME.round_resets.ante, 2*scale, 100), colour = G.C.IMPORTANT, shadow = true,id = 'ante_UI_count'}}, - {n=G.UIT.T, config={text = " ", scale = 0.3*scale}}, - {n=G.UIT.T, config={text = "/ ", scale = 0.7*scale, colour = G.C.WHITE, shadow = true}}, - {n=G.UIT.T, config={ref_table = G.GAME, ref_value='win_ante', scale = scale, colour = G.C.WHITE, shadow = true}} - }}, - }}, - {n=G.UIT.C, config={minw = spacing},nodes={}}, - {n=G.UIT.C, config={align = "cm", padding = 0.05, minw = 1.45, minh = 1, colour = temp_col, emboss = 0.05, r = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", maxw = 1.35}, nodes={ - {n=G.UIT.T, config={text = localize('k_round'), minh = 0.33, scale = 0.85*scale, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", r = 0.1, minw = 1.2, colour = temp_col2, id = 'row_round_text'}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME, ref_value = 'round'}}, colours = {G.C.IMPORTANT},shadow = true, scale = 2*scale}),id = 'round_UI_count'}}, - }}, - }}, - }}, - } - - contents.hand = - {n=G.UIT.R, config={align = "cm", id = 'hand_text_area', colour = darken(G.C.BLACK, 0.1), r = 0.1, emboss = 0.05, padding = 0.03}, nodes={ - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 1.1}, nodes={ - {n=G.UIT.O, config={id = 'hand_name', func = 'hand_text_UI_set',object = DynaText({string = {{ref_table = G.GAME.current_round.current_hand, ref_value = "handname_text"}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, float = true, scale = scale*1.4})}}, - {n=G.UIT.O, config={id = 'cry_asc', func = 'cry_asc_UI_set',object = DynaText({string = {{ref_table = G.GAME.current_round.current_hand, ref_value = "cry_asc_num_text"}}, colours = {G.C.GOLD}, shadow = true, float = true, scale = scale*1})}}, - {n=G.UIT.O, config={id = 'hand_chip_total', func = 'hand_chip_total_UI_set',object = DynaText({string = {{ref_table = G.GAME.current_round.current_hand, ref_value = "chip_total_text"}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, float = true, scale = scale*1.4})}}, - {n=G.UIT.T, config={ref_table = G.GAME.current_round.current_hand, ref_value='hand_level', scale = scale, colour = G.C.UI.TEXT_LIGHT, id = 'hand_level', shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", minh = 1, padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cr", minw = 2, minh =1, r = 0.1,colour = G.C.UI_CHIPS, id = 'hand_chip_area', emboss = 0.05}, nodes={ - {n=G.UIT.O, config={func = 'flame_handler',no_role = true, id = 'flame_chips', object = Moveable(0,0,0,0), w = 0, h = 0}}, - {n=G.UIT.O, config={id = 'hand_chips', func = 'hand_chip_UI_set',object = DynaText({string = {{ref_table = G.GAME.current_round.current_hand, ref_value = "chip_text"}}, colours = {G.C.UI.TEXT_LIGHT}, font = G.LANGUAGES['en-us'].font, shadow = true, float = true, scale = scale*2.3})}}, - {n=G.UIT.B, config={w=0.1,h=0.1}}, - }}, - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = "X", lang = G.LANGUAGES['en-us'], scale = scale*2, colour = G.C.UI_MULT, shadow = true}}, - }}, - {n=G.UIT.C, config={align = "cl", minw = 2, minh=1, r = 0.1,colour = G.C.UI_MULT, id = 'hand_mult_area', emboss = 0.05}, nodes={ - {n=G.UIT.O, config={func = 'flame_handler',no_role = true, id = 'flame_mult', object = Moveable(0,0,0,0), w = 0, h = 0}}, - {n=G.UIT.B, config={w=0.1,h=0.1}}, - {n=G.UIT.O, config={id = 'hand_mult', func = 'hand_mult_UI_set',object = DynaText({string = {{ref_table = G.GAME.current_round.current_hand, ref_value = "mult_text"}}, colours = {G.C.UI.TEXT_LIGHT}, font = G.LANGUAGES['en-us'].font, shadow = true, float = true, scale = scale*2.3})}}, - }} - }} - }} - }} - contents.dollars_chips = {n=G.UIT.R, config={align = "cm",r=0.1, padding = 0,colour = G.C.DYN_UI.BOSS_MAIN, emboss = 0.05, id = 'row_dollars_chips'}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = 1.3}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0, maxw = 1.3}, nodes={ - {n=G.UIT.T, config={text = localize('k_round'), scale = 0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0, maxw = 1.3}, nodes={ - {n=G.UIT.T, config={text =localize('k_lower_score'), scale = 0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }} - }}, - {n=G.UIT.C, config={align = "cm", minw = 3.3, minh = 0.7, r = 0.1, colour = G.C.DYN_UI.BOSS_DARK}, nodes={ - {n=G.UIT.O, config={w=0.5,h=0.5 , object = stake_sprite, hover = true, can_collide = false}}, - {n=G.UIT.B, config={w=0.1,h=0.1}}, - {n=G.UIT.T, config={ref_table = G.GAME, ref_value = 'chips_text', lang = G.LANGUAGES['en-us'], scale = 0.85, colour = G.C.WHITE, id = 'chip_UI_count', func = 'chip_UI_set', shadow = true}} - }} - }} - }} - - contents.buttons = { - {n=G.UIT.C, config={align = "cm", r=0.1, colour = G.C.CLEAR, shadow = true, id = 'button_area', padding = 0.2}, nodes={ - {n=G.UIT.R, config={id = 'run_info_button', align = "cm", minh = 1.75, minw = 1.5,padding = 0.05, r = 0.1, hover = true, colour = G.C.RED, button = "run_info", shadow = true}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0, maxw = 1.4}, nodes={ - {n=G.UIT.T, config={text = localize('b_run_info_1'), scale = 1.2*scale, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0, maxw = 1.4}, nodes={ - {n=G.UIT.T, config={text = localize('b_run_info_2'), scale = 1*scale, colour = G.C.UI.TEXT_LIGHT, shadow = true, focus_args = {button = G.F_GUIDE and 'guide' or 'back', orientation = 'bm'}, func = 'set_button_pip'}} - }} - }}, - {n=G.UIT.R, config={align = "cm", minh = 1.75, minw = 1.5,padding = 0.05, r = 0.1, hover = true, colour = G.C.ORANGE, button = "options", shadow = true}, nodes={ - {n=G.UIT.C, config={align = "cm", maxw = 1.4, focus_args = {button = 'start', orientation = 'bm'}, func = 'set_button_pip'}, nodes={ - {n=G.UIT.T, config={text = localize('b_options'), scale = scale, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }}, - }} - }} - } - - return {n=G.UIT.ROOT, config = {align = "cm", padding = 0.03, colour = G.C.UI.TRANSPARENT_DARK}, nodes={ - {n=G.UIT.R, config = {align = "cm", padding= 0.05, colour = G.C.DYN_UI.MAIN, r=0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", colour = G.C.DYN_UI.BOSS_DARK, r=0.1, minh = 30, padding = 0.08}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.3}, nodes={}}, - {n=G.UIT.R, config={align = "cm", id = 'row_blind', minw = 1, minh = 3.75}, nodes={ - {n=G.UIT.B, config={w=0, h=3.64, id = 'row_blind_bottom'}, nodes={}} - }}, - contents.dollars_chips, - contents.hand, - {n=G.UIT.R, config={align = "cm", id = 'row_round'}, nodes={ - {n=G.UIT.C, config={align = "cm"}, nodes=contents.buttons}, - {n=G.UIT.C, config={align = "cm"}, nodes=contents.round} - }}, - }} - }} - }} -end - -function create_UIBox_blind_select() - G.blind_prompt_box = UIBox{ - definition = - {n=G.UIT.ROOT, config = {align = 'cm', colour = G.C.CLEAR, padding = 0.2}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = localize('ph_choose_blind_1'), colours = {G.C.WHITE}, shadow = true, bump = true, scale = 0.6, pop_in = 0.5, maxw = 5}), id = 'prompt_dynatext1'}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = localize('ph_choose_blind_2'), colours = {G.C.WHITE}, shadow = true, bump = true, scale = 0.7, pop_in = 0.5, maxw = 5, silent = true}), id = 'prompt_dynatext2'}} - }}, - (G.GAME.used_vouchers["v_retcon"] or G.GAME.used_vouchers["v_directors_cut"]) and - UIBox_button({label = {localize('b_reroll_boss'), localize('$')..cry_cheapest_boss_reroll()}, button = "reroll_boss", func = 'reroll_boss_button'}) or nil - }}, - config = {align="cm", offset = {x=0,y=-15},major = G.HUD:get_UIE_by_ID('row_blind'), bond = 'Weak'} - } - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - G.blind_prompt_box.alignment.offset.y = 0 - return true - end) - })) - - local width = G.hand.T.w - G.GAME.blind_on_deck = - not (G.GAME.round_resets.blind_states.Small == 'Defeated' or G.GAME.round_resets.blind_states.Small == 'Skipped' or G.GAME.round_resets.blind_states.Small == 'Hide') and 'Small' or - not (G.GAME.round_resets.blind_states.Big == 'Defeated' or G.GAME.round_resets.blind_states.Big == 'Skipped'or G.GAME.round_resets.blind_states.Big == 'Hide') and 'Big' or - 'Boss' - - G.blind_select_opts = {} - G.blind_select_opts.small = G.GAME.round_resets.blind_states['Small'] ~= 'Hide' and UIBox{definition = {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR}, nodes={UIBox_dyn_container({create_UIBox_blind_choice('Small')},false,get_blind_main_colour('Small'))}}, config = {align="bmi", offset = {x=0,y=0}}} or nil - G.blind_select_opts.big = G.GAME.round_resets.blind_states['Big'] ~= 'Hide' and UIBox{definition = {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR}, nodes={UIBox_dyn_container({create_UIBox_blind_choice('Big')},false,get_blind_main_colour('Big'))}}, config = {align="bmi", offset = {x=0,y=0}}} or nil - G.blind_select_opts.boss = G.GAME.round_resets.blind_states['Boss'] ~= 'Hide' and UIBox{definition = {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR}, nodes={UIBox_dyn_container({create_UIBox_blind_choice('Boss')},false,get_blind_main_colour('Boss'), mix_colours(G.C.BLACK, get_blind_main_colour('Boss'), 0.8))}}, config = {align="bmi", offset = {x=0,y=0}}} or nil - - local t = {n=G.UIT.ROOT, config = {align = 'tm',minw = width, r = 0.15, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.5}, nodes={ - G.GAME.round_resets.blind_states['Small'] ~= 'Hide' and {n=G.UIT.O, config={align = "cm", object = G.blind_select_opts.small}} or nil, - G.GAME.round_resets.blind_states['Big'] ~= 'Hide' and {n=G.UIT.O, config={align = "cm", object = G.blind_select_opts.big}} or nil, - G.GAME.round_resets.blind_states['Boss'] ~= 'Hide' and {n=G.UIT.O, config={align = "cm", object = G.blind_select_opts.boss}} or nil, - }} - }} - return t -end - -function create_UIBox_blind_tag(blind_choice, run_info) - G.GAME.round_resets.blind_tags = G.GAME.round_resets.blind_tags or {} - if not G.GAME.round_resets.blind_tags[blind_choice] then return nil end - local _tag = Tag(G.GAME.round_resets.blind_tags[blind_choice], nil, blind_choice) - local _tag_ui, _tag_sprite = _tag:generate_UI() - _tag_sprite.states.collide.can = not not run_info - return - {n=G.UIT.R, config={id = 'tag_container', ref_table = _tag, align = "cm"}, nodes={ - {n=G.UIT.R, config={align = 'tm', minh = 0.65}, nodes={ - {n=G.UIT.T, config={text = localize('k_or'), scale = 0.55, colour = disabled and G.C.UI.TEXT_INACTIVE or G.C.WHITE, shadow = not disabled}}, - }}, - {n=G.UIT.R, config={id = 'tag_'..blind_choice, align = "cm", r = 0.1, padding = 0.1, minw = 1, can_collide = true, ref_table = _tag_sprite}, nodes={ - {n=G.UIT.C, config={id = 'tag_desc', align = "cm", minh = 1}, nodes={ - _tag_ui - }}, - not run_info and {n=G.UIT.C, config={align = "cm", colour = G.C.UI.BACKGROUND_INACTIVE, minh = 0.6, minw = 2, maxw = 2, padding = 0.07, r = 0.1, shadow = true, hover = true, one_press = true, button = 'skip_blind', func = 'hover_tag_proxy', ref_table = _tag}, nodes={ - {n=G.UIT.T, config={text = localize('b_skip_blind'), scale = 0.4, colour = G.C.UI.TEXT_INACTIVE}} - }} or {n=G.UIT.C, config={align = "cm", padding = 0.1, emboss = 0.05, colour = mix_colours(G.C.BLUE, G.C.BLACK, 0.4), r = 0.1, maxw = 2}, nodes={ - {n=G.UIT.T, config={text = localize('b_skip_reward'), scale = 0.35, colour = G.C.WHITE}}, - }}, - }} - }} -end - -function create_UIBox_blind_choice(type, run_info) - if not G.GAME.blind_on_deck then - G.GAME.blind_on_deck = G.GAME.modifiers.cry_no_small_blind and 'Big' or 'Small' - end - if not run_info then G.GAME.round_resets.blind_states[G.GAME.blind_on_deck] = 'Select' end - - local disabled = false - type = type or 'Small' - - local blind_choice = { - config = G.P_BLINDS[G.GAME.round_resets.blind_choices[type]], - } - - blind_choice.animation = AnimatedSprite(0,0, 1.4, 1.4, G.ANIMATION_ATLAS[blind_choice.config.atlas] or G.ANIMATION_ATLAS['blind_chips'], blind_choice.config.pos) - blind_choice.animation:define_draw_steps({ - {shader = 'dissolve', shadow_height = 0.05}, - {shader = 'dissolve'} - }) - local extras = nil - local stake_sprite = get_stake_sprite(G.GAME.stake or 1, 0.5) - - G.GAME.orbital_choices = G.GAME.orbital_choices or {} - G.GAME.orbital_choices[G.GAME.round_resets.ante] = G.GAME.orbital_choices[G.GAME.round_resets.ante] or {} - - if not G.GAME.orbital_choices[G.GAME.round_resets.ante][type] 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 - - G.GAME.orbital_choices[G.GAME.round_resets.ante][type] = pseudorandom_element(_poker_hands, pseudoseed('orbital')) - end - - - - if type == 'Small' and not G.GAME.modifiers.cry_no_tags then - extras = create_UIBox_blind_tag(type, run_info) - elseif type == 'Big' and not G.GAME.modifiers.cry_no_tags then - extras = create_UIBox_blind_tag(type, run_info) - elseif type == 'Boss' and not run_info then - local dt1 = DynaText({string = {{string = localize('ph_up_ante_1'), colour = G.C.FILTER}}, colours = {G.C.BLACK}, scale = 0.55, silent = true, pop_delay = 4.5, shadow = true, bump = true, maxw = 3}) - local dt2 = DynaText({string = {{string = localize('ph_up_ante_2'), colour = G.C.WHITE}},colours = {G.C.CHANCE}, scale = 0.35, silent = true, pop_delay = 4.5, shadow = true, maxw = 3}) - local dt3 = DynaText({string = {{string = localize('ph_up_ante_3'), colour = G.C.WHITE}},colours = {G.C.CHANCE}, scale = 0.35, silent = true, pop_delay = 4.5, shadow = true, maxw = 3}) - extras = - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.07, r = 0.1, colour = {0,0,0,0.12}, minw = 2.9}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = dt1}}, - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = dt2}}, - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = dt3}}, - }}, - }}, - }} - end - G.GAME.round_resets.blind_ante = G.GAME.round_resets.blind_ante or G.GAME.round_resets.ante - local target = {type = 'raw_descriptions', key = blind_choice.config.key, set = 'Blind', vars = {}} - if blind_choice.config.name == 'The Ox' then - target.vars = {localize(G.GAME.current_round.most_played_poker_hand, 'poker_hands')} - end - local obj = blind_choice.config - if obj.loc_vars and _G['type'](obj.loc_vars) == 'function' then - local res = obj:loc_vars() or {} - target.vars = res.vars or target.vars - target.key = res.key or target.key - end - local loc_target = localize(target) - local loc_name = localize{type = 'name_text', key = blind_choice.config.key, set = 'Blind'} - local text_table = loc_target - local blind_col = get_blind_main_colour(type) - local blind_amt = get_blind_amount(G.GAME.round_resets.blind_ante)*blind_choice.config.mult*G.GAME.starting_params.ante_scaling - - local blind_state = G.GAME.round_resets.blind_states[type] - local _reward = true - if G.GAME.modifiers.no_blind_reward and G.GAME.modifiers.no_blind_reward[type] then _reward = nil end - if blind_state == 'Select' then blind_state = 'Current' end - local blind_desc_nodes = {} - for k, v in ipairs(text_table) do - blind_desc_nodes[#blind_desc_nodes+1] = {n=G.UIT.R, config={align = "cm", maxw = 2.8}, nodes={ - {n=G.UIT.T, config={text = v or '-', scale = 0.32, colour = disabled and G.C.UI.TEXT_INACTIVE or G.C.WHITE, shadow = not disabled}} - }} - end - local run_info_colour = run_info and (blind_state == 'Defeated' and G.C.GREY or blind_state == 'Skipped' and G.C.BLUE or blind_state == 'Upcoming' and G.C.ORANGE or blind_state == 'Current' and G.C.RED or G.C.GOLD) - local t = - {n=G.UIT.R, config={id = type, align = "tm", func = 'blind_choice_handler', minh = not run_info and 10 or nil, ref_table = {deck = nil, run_info = run_info}, r = 0.1, padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", colour = mix_colours(G.C.BLACK, G.C.L_BLACK, 0.5), r = 0.1, outline = 1, outline_colour = G.C.L_BLACK}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.2}, nodes={ - not run_info and {n=G.UIT.R, config={id = 'select_blind_button', align = "cm", ref_table = blind_choice.config, colour = disabled and G.C.UI.BACKGROUND_INACTIVE or G.C.ORANGE, minh = 0.6, minw = 2.7, padding = 0.07, r = 0.1, shadow = true, hover = true, one_press = true, button = 'select_blind'}, nodes={ - {n=G.UIT.T, config={ref_table = G.GAME.round_resets.loc_blind_states, ref_value = type, scale = 0.45, colour = disabled and G.C.UI.TEXT_INACTIVE or G.C.UI.TEXT_LIGHT, shadow = not disabled}} - }} or - {n=G.UIT.R, config={id = 'select_blind_button', align = "cm", ref_table = blind_choice.config, colour = run_info_colour, minh = 0.6, minw = 2.7, padding = 0.07, r = 0.1, emboss = 0.08}, nodes={ - {n=G.UIT.T, config={text = localize(blind_state, 'blind_states'), scale = 0.45, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }} - }}, - {n=G.UIT.R, config={id = 'blind_name',align = "cm", padding = 0.07}, nodes={ - {n=G.UIT.R, config={align = "cm", r = 0.1, outline = 1, outline_colour = blind_col, colour = darken(blind_col, 0.3), minw = 2.9, emboss = 0.1, padding = 0.07, line_emboss = 1}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = loc_name, colours = {disabled and G.C.UI.TEXT_INACTIVE or G.C.WHITE}, shadow = not disabled, float = not disabled, y_offset = -4, scale = 0.45, maxw =2.8})}}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.R, config={id = 'blind_desc', align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 1.5}, nodes={ - {n=G.UIT.O, config={object = blind_choice.animation}}, - }}, - text_table[1] and {n=G.UIT.R, config={align = "cm", minh = 0.7, padding = 0.05, minw = 2.9}, nodes = blind_desc_nodes} or nil, - }}, - {n=G.UIT.R, config={align = "cm",r = 0.1, padding = 0.05, minw = 3.1, colour = G.C.BLACK, emboss = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", maxw = 3}, nodes={ - {n=G.UIT.T, config={text = localize('ph_blind_score_at_least'), scale = 0.3, colour = disabled and G.C.UI.TEXT_INACTIVE or G.C.WHITE, shadow = not disabled}} - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.6}, nodes={ - {n=G.UIT.O, config={w=0.5,h=0.5, colour = G.C.BLUE, object = stake_sprite, hover = true, can_collide = false}}, - {n=G.UIT.B, config={h=0.1,w=0.1}}, - {n=G.UIT.T, config={text = number_format(blind_amt), scale = score_number_scale(0.9, blind_amt), colour = disabled and G.C.UI.TEXT_INACTIVE or G.C.RED, shadow = not disabled}} - }}, - _reward and {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = localize('ph_blind_reward'), scale = 0.35, colour = disabled and G.C.UI.TEXT_INACTIVE or G.C.WHITE, shadow = not disabled}}, - {n=G.UIT.T, config={text = string.rep(localize("$"), blind_choice.config.dollars)..'+', scale = 0.35, colour = disabled and G.C.UI.TEXT_INACTIVE or G.C.MONEY, shadow = not disabled}} - }} or nil, - }}, - }}, - }}, - }}, - {n=G.UIT.R, config={id = 'blind_extras', align = "cm"}, nodes={ - extras, - }} - - }} - return t -end - -function create_UIBox_round_evaluation() - local width = G.hand.T.w-2 - local t = {n=G.UIT.ROOT, config = {align = 'tm',colour = G.C.CLEAR}, nodes={ - UIBox_dyn_container( - { - {n=G.UIT.R, config={align = "tm", minw = width, minh = 3, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", minw = width, minh = 1.4}, nodes={}}, - {n=G.UIT.R, config={align = "cm", minw = width, id = 'base_round_eval'}, nodes={}}, - {n=G.UIT.R, config={align = "cm", minw = width, id = 'bonus_round_eval'}, nodes={}} - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={}}, - {n=G.UIT.R, config={align = "cm", minw = width, id = 'eval_bottom'}, nodes={}} - },false) - }} -return t -end - -function create_UIBox_arcana_pack() - local _size = G.GAME.pack_size - G.pack_cards = CardArea( - G.ROOM.T.x + 9 + G.hand.T.x, G.hand.T.y, - math.max(1,math.min(_size,5))*G.CARD_W, - 1.05*G.CARD_H, - {card_limit = _size, type = 'consumeable', highlight_limit = 1}) - - local t = {n=G.UIT.ROOT, config = {align = 'tm', r = 0.15, colour = G.C.CLEAR, padding = 0.15}, nodes={ - {n=G.UIT.R, config={align = "cl", colour = G.C.CLEAR,r=0.15, padding = 0.1, minh = 2, shadow = true}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", r=0.2, colour = G.C.CLEAR, shadow = true}, nodes={ - {n=G.UIT.O, config={object = G.pack_cards}}, - }} - }} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - }}, - {n=G.UIT.R, config={align = "tm"}, nodes={ - {n=G.UIT.C,config={align = "tm", padding = 0.05, minw = 2.4}, nodes={}}, - {n=G.UIT.C,config={align = "tm", padding = 0.05}, nodes={ - UIBox_dyn_container({ - {n=G.UIT.C, config={align = "cm", padding = 0.05, minw = 4}, nodes={ - {n=G.UIT.R,config={align = "bm", padding = 0.05}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = localize('k_arcana_pack'), colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.7, maxw = 4, pop_in = 0.5})}} - }}, - {n=G.UIT.R,config={align = "bm", padding = 0.05}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('k_choose')..' '}, colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.5, pop_in = 0.7})}}, - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME, ref_value = 'pack_choices'}}, colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.5, pop_in = 0.7})}} - }}, - }} - }), - }}, - {n=G.UIT.C,config={align = "tm", padding = 0.05, minw = 2.4}, nodes={ - {n=G.UIT.R,config={minh =0.2}, nodes={}}, - {n=G.UIT.R,config={align = "tm",padding = 0.2, minh = 1.2, minw = 1.8, r=0.15,colour = G.C.GREY, one_press = true, button = 'skip_booster', hover = true,shadow = true, func = 'can_skip_booster'}, nodes = { - {n=G.UIT.T, config={text = localize('b_skip'), scale = 0.5, colour = G.C.WHITE, shadow = true, focus_args = {button = 'y', orientation = 'bm'}, func = 'set_button_pip'}} - }} - }} - }} - }} - }} - return t -end - -function create_UIBox_spectral_pack() - local _size = G.GAME.pack_size - G.pack_cards = CardArea( - G.ROOM.T.x + 9 + G.hand.T.x, G.hand.T.y, - math.max(1,math.min(_size,5))*G.CARD_W, - 1.05*G.CARD_H, - {card_limit = _size, type = 'consumeable', highlight_limit = 1}) - - local t = {n=G.UIT.ROOT, config = {align = 'tm', r = 0.15, colour = G.C.CLEAR, padding = 0.15}, nodes={ - {n=G.UIT.R, config={align = "cl", colour = G.C.CLEAR,r=0.15, padding = 0.1, minh = 2, shadow = true}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", r=0.2, colour = G.C.CLEAR, shadow = true}, nodes={ - {n=G.UIT.O, config={object = G.pack_cards}}, - }} - }} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - }}, - {n=G.UIT.R, config={align = "tm"}, nodes={ - {n=G.UIT.C,config={align = "tm", padding = 0.05, minw = 2.4}, nodes={}}, - {n=G.UIT.C,config={align = "tm", padding = 0.05}, nodes={ - UIBox_dyn_container({ - {n=G.UIT.C, config={align = "cm", padding = 0.05, minw = 4}, nodes={ - {n=G.UIT.R,config={align = "bm", padding = 0.05}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = localize('k_spectral_pack'), colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.7, maxw = 4, pop_in = 0.5})}} - }}, - {n=G.UIT.R,config={align = "bm", padding = 0.05}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('k_choose')..' '}, colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.5, pop_in = 0.7})}}, - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME, ref_value = 'pack_choices'}}, colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.5, pop_in = 0.7})}} - }}, - }} - }), - }}, - {n=G.UIT.C,config={align = "tm", padding = 0.05, minw = 2.4}, nodes={ - {n=G.UIT.R,config={minh =0.2}, nodes={}}, - {n=G.UIT.R,config={align = "tm",padding = 0.2, minh = 1.2, minw = 1.8, r=0.15,colour = G.C.GREY, one_press = true, button = 'skip_booster', hover = true,shadow = true, func = 'can_skip_booster'}, nodes = { - {n=G.UIT.T, config={text = localize('b_skip'), scale = 0.5, colour = G.C.WHITE, shadow = true, focus_args = {button = 'y', orientation = 'bm'}, func = 'set_button_pip'}} - }} - }} - }} - }} - }} - return t -end - -function create_UIBox_standard_pack() - local _size = G.GAME.pack_size - G.pack_cards = CardArea( - G.ROOM.T.x + 9 + G.hand.T.x, G.hand.T.y, - math.max(1,math.min(_size,5))*G.CARD_W*1.1, - 1.05*G.CARD_H, - {card_limit = _size, type = 'consumeable', highlight_limit = 1}) - - local t = {n=G.UIT.ROOT, config = {align = 'tm', r = 0.15, colour = G.C.CLEAR, padding = 0.15}, nodes={ - {n=G.UIT.R, config={align = "cl", colour = G.C.CLEAR,r=0.15, padding = 0.1, minh = 2, shadow = true}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", r=0.2, colour = G.C.CLEAR, shadow = true}, nodes={ - {n=G.UIT.O, config={object = G.pack_cards}}, - }} - }} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - }}, - {n=G.UIT.R, config={align = "tm"}, nodes={ - {n=G.UIT.C,config={align = "tm", padding = 0.05, minw = 2.4}, nodes={}}, - {n=G.UIT.C,config={align = "tm", padding = 0.05}, nodes={ - UIBox_dyn_container({ - {n=G.UIT.C, config={align = "cm", padding = 0.05, minw = 4}, nodes={ - {n=G.UIT.R,config={align = "bm", padding = 0.05}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = localize('k_standard_pack'), colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.7, maxw = 4, pop_in = 0.5})}} - }}, - {n=G.UIT.R,config={align = "bm", padding = 0.05}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('k_choose')..' '}, colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.5, pop_in = 0.7})}}, - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME, ref_value = 'pack_choices'}}, colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.5, pop_in = 0.7})}} - }}, - }} - }), - }}, - {n=G.UIT.C,config={align = "tm", padding = 0.05, minw = 2.4}, nodes={ - {n=G.UIT.R,config={minh =0.2}, nodes={}}, - {n=G.UIT.R,config={align = "tm",padding = 0.2, minh = 1.2, minw = 1.8, r=0.15,colour = G.C.GREY, one_press = true, button = 'skip_booster', hover = true,shadow = true, func = 'can_skip_booster'}, nodes = { - {n=G.UIT.T, config={text = localize('b_skip'), scale = 0.5, colour = G.C.WHITE, shadow = true, focus_args = {button = 'y', orientation = 'bm'}, func = 'set_button_pip'}} - }} - }} - }} - }} - }} - return t -end - -function create_UIBox_buffoon_pack() - local _size = G.GAME.pack_size - G.pack_cards = CardArea( - G.ROOM.T.x + 9 + G.hand.T.x, G.hand.T.y, - math.max(1,math.min(_size,5))*G.CARD_W*1.1, - 1.05*G.CARD_H, - {card_limit = _size, type = 'consumeable', highlight_limit = 1}) - - local t = {n=G.UIT.ROOT, config = {align = 'tm', r = 0.15, colour = G.C.CLEAR, padding = 0.15}, nodes={ - {n=G.UIT.R, config={align = "cl", colour = G.C.CLEAR,r=0.15, padding = 0.1, minh = 2, shadow = true}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", r=0.2, colour = G.C.CLEAR, shadow = true}, nodes={ - {n=G.UIT.O, config={object = G.pack_cards}}, - }} - }} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - }}, - {n=G.UIT.R, config={align = "tm"}, nodes={ - {n=G.UIT.C,config={align = "tm", padding = 0.05, minw = 2.4}, nodes={}}, - {n=G.UIT.C,config={align = "tm", padding = 0.05}, nodes={ - UIBox_dyn_container({ - {n=G.UIT.C, config={align = "cm", padding = 0.05, minw = 4}, nodes={ - {n=G.UIT.R,config={align = "bm", padding = 0.05}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = localize('k_buffoon_pack'), colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.7, maxw = 4, pop_in = 0.5})}} - }}, - {n=G.UIT.R,config={align = "bm", padding = 0.05}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('k_choose')..' '}, colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.5, pop_in = 0.7})}}, - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME, ref_value = 'pack_choices'}}, colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.5, pop_in = 0.7})}} - }}, - }} - }), - }}, - {n=G.UIT.C,config={align = "tm", padding = 0.05, minw = 2.4}, nodes={ - {n=G.UIT.R,config={minh =0.2}, nodes={}}, - {n=G.UIT.R,config={align = "tm",padding = 0.2, minh = 1.2, minw = 1.8, r=0.15,colour = G.C.GREY, one_press = true, button = 'skip_booster', hover = true,shadow = true, func = 'can_skip_booster'}, nodes = { - {n=G.UIT.T, config={text = localize('b_skip'), scale = 0.5, colour = G.C.WHITE, shadow = true, focus_args = {button = 'y', orientation = 'bm'}, func = 'set_button_pip'}} - }} - }} - }} - }} - }} - return t -end - -function create_UIBox_celestial_pack() - local _size = G.GAME.pack_size - G.pack_cards = CardArea( - G.ROOM.T.x + 9 + G.hand.T.x, G.hand.T.y, - math.max(1,math.min(_size,5))*G.CARD_W*1.1 + 0.5, - 1.05*G.CARD_H, - {card_limit = _size, type = 'consumeable', highlight_limit = 1}) - - local t = {n=G.UIT.ROOT, config = {align = 'tm', r = 0.15, colour = G.C.CLEAR, padding = 0.15}, nodes={ - {n=G.UIT.R, config={align = "cl", colour = G.C.CLEAR,r=0.15, padding = 0.1, minh = 2, shadow = true}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", r=0.2, colour = G.C.CLEAR, shadow = true}, nodes={ - {n=G.UIT.O, config={object = G.pack_cards}}, - }} - }} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - }}, - {n=G.UIT.R, config={align = "tm"}, nodes={ - {n=G.UIT.C,config={align = "tm", padding = 0.05, minw = 2.4}, nodes={}}, - {n=G.UIT.C,config={align = "tm", padding = 0.05}, nodes={ - UIBox_dyn_container({ - {n=G.UIT.C, config={align = "cm", padding = 0.05, minw = 4}, nodes={ - {n=G.UIT.R,config={align = "bm", padding = 0.05}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = localize('k_celestial_pack'), colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.7, maxw = 4, pop_in = 0.5})}} - }}, - {n=G.UIT.R,config={align = "bm", padding = 0.05}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('k_choose')..' '}, colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.5, pop_in = 0.7})}}, - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME, ref_value = 'pack_choices'}}, colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.5, pop_in = 0.7})}} - }}, - }} - }), - }}, - {n=G.UIT.C,config={align = "tm", padding = 0.05, minw = 2.4}, nodes={ - {n=G.UIT.R,config={minh =0.2}, nodes={}}, - {n=G.UIT.R,config={align = "tm",padding = 0.2, minh = 1.2, minw = 1.8, r=0.15,colour = G.C.GREY, one_press = true, button = 'skip_booster', hover = true,shadow = true, func = 'can_skip_booster'}, nodes = { - {n=G.UIT.T, config={text = localize('b_skip'), scale = 0.5, colour = G.C.WHITE, shadow = true, focus_args = {button = 'y', orientation = 'bm'}, func = 'set_button_pip'}} - }} - }} - }} - }} - }} - return t -end - -function create_UIBox_card_alert(args) - args = args or {} - return {n=G.UIT.ROOT, config = {align = 'cm', colour = G.C.CLEAR, refresh_movement = true}, nodes={ - {n=G.UIT.R, config={align = "cm", r = 0.15, minw = 0.42, minh = 0.42, colour = args.no_bg and G.C.CLEAR or args.bg_col or (args.red_bad and darken(G.C.RED, 0.1) or G.C.RED), draw_layer = 1, emboss = 0.05, refresh_movement = true}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = args.text or '!', colours = {G.C.WHITE},shadow = true, rotate = true,H_offset = args.y_offset or 0,bump_rate = args.text and 3 or 7, bump_amount = args.bump_amount or 3, bump = true,maxw = args.maxw, text_rot = args.text_rot or 0.2, spacing = 3*(args.scale or 1), scale = args.scale or 0.48})}} - }}, - }} -end - -function create_slider(args) - args = args or {} - args.colour = args.colour or G.C.RED - args.w = args.w or 1 - args.h = args.h or 0.5 - args.label_scale = args.label_scale or 0.5 - args.text_scale = args.text_scale or 0.3 - args.min = args.min or 0 - args.max = args.max or 1 - args.decimal_places = args.decimal_places or 0 - args.text = string.format("%."..tostring(args.decimal_places).."f", args.ref_table[args.ref_value]) - local startval = args.w * (args.ref_table[args.ref_value] - args.min)/(args.max - args.min) - - local t = - {n=G.UIT.C, config={align = "cm", minw = args.w, min_h = args.h, padding = 0.1, r = 0.1, colour = G.C.CLEAR, focus_args = {type = 'slider'}}, nodes={ - {n=G.UIT.C, config={align = "cl", minw = args.w, r = 0.1,min_h = args.h,collideable = true, hover = true, colour = G.C.BLACK,emboss = 0.05,func = 'slider', refresh_movement = true}, nodes={ - {n=G.UIT.B, config={id = args.id, w=startval,h=args.h, r = 0.1, colour = args.colour, ref_table = args, refresh_movement = true}}, - }}, - not args.hide_val and {n=G.UIT.C, config={align = "cm", minh = args.h,r = 0.1, minw = 0.8, colour = args.colour,shadow = true}, nodes={ - {n=G.UIT.T, config={ref_table = args, ref_value = 'text', scale = args.text_scale, colour = G.C.UI.TEXT_LIGHT, decimal_places = args.decimal_places}} - }} or nil - }} - if args.label then - t = {n=G.UIT.R, config={align = "cm", minh = 1, minw = 1, padding = 0.1*args.label_scale, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = args.label, scale = args.label_scale, colour = G.C.UI.TEXT_LIGHT}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - t - }} - }} - end - return t -end - -function create_toggle(args) - args = args or {} - args.active_colour = args.active_colour or G.C.RED - args.inactive_colour = args.inactive_colour or G.C.BLACK - args.w = args.w or 3 - args.h = args.h or 0.5 - args.scale = args.scale or 1 - args.label = args.label or 'TEST?' - args.label_scale = args.label_scale or 0.4 - args.ref_table = args.ref_table or {} - args.ref_value = args.ref_value or 'test' - - local check = Sprite(0,0,0.5*args.scale,0.5*args.scale,G.ASSET_ATLAS["icons"], {x=1, y=0}) - check.states.drag.can = false - check.states.visible = false - - local info = nil - if args.info then - info = {} - for k, v in ipairs(args.info) do - table.insert(info, {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ - {n=G.UIT.T, config={text = v, scale = 0.25, colour = G.C.UI.TEXT_LIGHT}} - }}) - end - info = {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes=info} - end - - local t = - {n=args.col and G.UIT.C or G.UIT.R, config={align = "cm", padding = 0.1, r = 0.1, colour = G.C.CLEAR, focus_args = {funnel_from = true}}, nodes={ - {n=G.UIT.C, config={align = "cr", minw = args.w}, nodes={ - {n=G.UIT.T, config={text = args.label, scale = args.label_scale, colour = G.C.UI.TEXT_LIGHT}}, - {n=G.UIT.B, config={w = 0.1, h = 0.1}}, - }}, - {n=G.UIT.C, config={align = "cl", minw = 0.3*args.w}, nodes={ - {n=G.UIT.C, config={align = "cm", r = 0.1, colour = G.C.BLACK}, nodes={ - {n=G.UIT.C, config={align = "cm", r = 0.1, padding = 0.03, minw = 0.4*args.scale, minh = 0.4*args.scale, outline_colour = G.C.WHITE, outline = 1.2*args.scale, line_emboss = 0.5*args.scale, ref_table = args, - colour = args.inactive_colour, - button = 'toggle_button', button_dist = 0.2, hover = true, toggle_callback = args.callback, func = 'toggle', focus_args = {funnel_to = true}}, nodes={ - {n=G.UIT.O, config={object = check}}, - }}, - }} - }}, - }} - if args.info then - t = {n=args.col and G.UIT.C or G.UIT.R, config={align = "cm"}, nodes={ - t, - info, - }} - end - return t -end - -function create_option_cycle(args) - args = args or {} - args.colour = args.colour or G.C.RED - args.options = args.options or { - 'Option 1', - 'Option 2' - } - args.current_option = args.current_option or 1 - args.current_option_val = args.options[args.current_option] - args.opt_callback = args.opt_callback or nil - args.scale = args.scale or 1 - args.ref_table = args.ref_table or nil - args.ref_value = args.ref_value or nil - args.w = (args.w or 2.5)*args.scale - args.h = (args.h or 0.8)*args.scale - args.text_scale = (args.text_scale or 0.5)*args.scale - args.l = '<' - args.r = '>' - args.focus_args = args.focus_args or {} - args.focus_args.type = 'cycle' - - local info = nil - if args.info then - info = {} - for k, v in ipairs(args.info) do - table.insert(info, {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ - {n=G.UIT.T, config={text = v, scale = 0.3*args.scale, colour = G.C.UI.TEXT_LIGHT}} - }}) - end - info = {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes=info} - end - - local disabled = #args.options < 2 - local pips = {} - for i = 1, #args.options do - pips[#pips+1] = {n=G.UIT.B, config={w = 0.1*args.scale, h = 0.1*args.scale, r = 0.05, id = 'pip_'..i, colour = args.current_option == i and G.C.WHITE or G.C.BLACK}} - end - - local choice_pips = not args.no_pips and {n=G.UIT.R, config={align = "cm", padding = (0.05 - (#args.options > 15 and 0.03 or 0))*args.scale}, nodes=pips} or nil - - local t = - {n=G.UIT.C, config={align = "cm", padding = 0.1, r = 0.1, colour = G.C.CLEAR, id = args.id and (not args.label and args.id or nil) or nil, focus_args = args.focus_args}, nodes={ - {n=G.UIT.C, config={align = "cm",r = 0.1, minw = 0.6*args.scale, hover = not disabled, colour = not disabled and args.colour or G.C.BLACK,shadow = not disabled, button = not disabled and 'option_cycle' or nil, ref_table = args, ref_value = 'l', focus_args = {type = 'none'}}, nodes={ - {n=G.UIT.T, config={ref_table = args, ref_value = 'l', scale = args.text_scale, colour = not disabled and G.C.UI.TEXT_LIGHT or G.C.UI.TEXT_INACTIVE}} - }}, - args.mid and - {n=G.UIT.C, config={id = 'cycle_main'}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ - args.mid - }}, - not disabled and choice_pips or nil - }} - or {n=G.UIT.C, config={id = 'cycle_main', align = "cm", minw = args.w, minh = args.h, r = 0.1, padding = 0.05, colour = args.colour,emboss = 0.1, hover = true, can_collide = true, on_demand_tooltip = args.on_demand_tooltip}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = args, ref_value = "current_option_val"}}, colours = {G.C.UI.TEXT_LIGHT},pop_in = 0, pop_in_rate = 8, reset_pop_in = true,shadow = true, float = true, silent = true, bump = true, scale = args.text_scale, non_recalc = true})}}, - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ - }}, - not disabled and choice_pips or nil - }} - }}, - {n=G.UIT.C, config={align = "cm",r = 0.1, minw = 0.6*args.scale, hover = not disabled, colour = not disabled and args.colour or G.C.BLACK,shadow = not disabled, button = not disabled and 'option_cycle' or nil, ref_table = args, ref_value = 'r', focus_args = {type = 'none'}}, nodes={ - {n=G.UIT.T, config={ref_table = args, ref_value = 'r', scale = args.text_scale, colour = not disabled and G.C.UI.TEXT_LIGHT or G.C.UI.TEXT_INACTIVE}} - }}, - }} - - if args.cycle_shoulders then - t = - {n=G.UIT.R, config={align = "cm", colour = G.C.CLEAR}, nodes = { - {n=G.UIT.C, config={minw = 0.7,align = "cm", colour = G.C.CLEAR,func = 'set_button_pip', focus_args = {button = 'leftshoulder', type = 'none', orientation = 'cm', scale = 0.7, offset = {x = -0.1, y = 0}}}, nodes = {}}, - {n=G.UIT.C, config={id = 'cycle_shoulders', padding = 0.1}, nodes={t}}, - {n=G.UIT.C, config={minw = 0.7,align = "cm", colour = G.C.CLEAR,func = 'set_button_pip', focus_args = {button = 'rightshoulder', type = 'none', orientation = 'cm', scale = 0.7, offset = {x = 0.1, y = 0}}}, nodes = {}}, - }} - else - t = - {n=G.UIT.R, config={align = "cm", colour = G.C.CLEAR, padding = 0.0}, nodes = { - t - }} - end - if args.label or args.info then - t = {n=G.UIT.R, config={align = "cm", padding = 0.05, id = args.id or nil}, nodes={ - args.label and {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = args.label, scale = 0.5*args.scale, colour = G.C.UI.TEXT_LIGHT}} - }} or nil, - t, - info, - }} - end - return t -end - -function create_tabs(args) - args = args or {} - args.colour = args.colour or G.C.RED - args.tab_alignment = args.tab_alignment or 'cm' - args.opt_callback = args.opt_callback or nil - args.scale = args.scale or 1 - args.tab_w = args.tab_w or 0 - args.tab_h = args.tab_h or 0 - args.text_scale = (args.text_scale or 0.5) - args.tabs = args.tabs or { - { - label = 'tab 1', - chosen = true, - func = nil, - tab_definition_function = function() return {n=G.UIT.ROOT, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = 'A', scale = 1, colour = G.C.UI.TEXT_LIGHT}} - }} end - }, - { - label = 'tab 2', - chosen = false, - tab_definition_function = function() return {n=G.UIT.ROOT, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = 'B', scale = 1, colour = G.C.UI.TEXT_LIGHT}} - }} end - }, - { - label = 'tab 3', - chosen = false, - tab_definition_function = function() return {n=G.UIT.ROOT, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = 'C', scale = 1, colour = G.C.UI.TEXT_LIGHT}} - }} end - } - } - - local tab_buttons = {} - - for k, v in ipairs(args.tabs) do - if v.chosen then args.current = {k = k, v = v} end - tab_buttons[#tab_buttons+1] = UIBox_button({id = 'tab_but_'..(v.label or ''), ref_table = v, button = 'change_tab', label = {v.label}, minh = 0.8*args.scale, minw = 2.5*args.scale, col = true, choice = true, scale = args.text_scale, chosen = v.chosen, func = v.func, colour = args.colour, focus_args = {type = 'none'}}) - end - - local t = - {n=G.UIT.R, config={padding = 0.0, align = "cm", colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", colour = G.C.CLEAR}, nodes = { - (#args.tabs > 1 and not args.no_shoulders) and {n=G.UIT.C, config={minw = 0.7,align = "cm", colour = G.C.CLEAR,func = 'set_button_pip', focus_args = {button = 'leftshoulder', type = 'none', orientation = 'cm', scale = 0.7, offset = {x = -0.1, y = 0}}}, nodes = {}} or nil, - {n=G.UIT.C, config={id = args.no_shoulders and 'no_shoulders' or 'tab_shoulders', ref_table = args, align = "cm", padding = 0.15, group = 1, collideable = true, focus_args = #args.tabs > 1 and {type = 'tab', nav = 'wide',snap_to = args.snap_to_nav, no_loop = args.no_loop} or nil}, nodes=tab_buttons}, - (#args.tabs > 1 and not args.no_shoulders) and {n=G.UIT.C, config={minw = 0.7,align = "cm", colour = G.C.CLEAR,func = 'set_button_pip', focus_args = {button = 'rightshoulder', type = 'none', orientation = 'cm', scale = 0.7, offset = {x = 0.1, y = 0}}}, nodes = {}} or nil, - }}, - {n=G.UIT.R, config={align = args.tab_alignment, padding = args.padding or 0.1, no_fill = true, minh = args.tab_h, minw = args.tab_w}, nodes={ - {n=G.UIT.O, config={id = 'tab_contents', object = UIBox{definition = args.current.v.tab_definition_function(args.current.v.tab_definition_function_args), config = {offset = {x=0,y=0}}}}} - }}, - }} - - return t -end - -function create_text_input(args) - args = args or {} - args.colour = copy_table(args.colour) or copy_table(G.C.BLUE) - args.hooked_colour = copy_table(args.hooked_colour) or darken(copy_table(G.C.BLUE), 0.3) - args.w = args.w or 2.5 - args.h = args.h or 0.7 - args.text_scale = args.text_scale or 0.4 - args.max_length = args.max_length or 16 - args.all_caps = args.all_caps or false - args.prompt_text = args.prompt_text or localize('k_enter_text') - args.current_prompt_text = '' - args.id = args.id or "text_input" - - local text = {ref_table = args.ref_table, ref_value = args.ref_value, letters = {}, current_position = string.len(args.ref_table[args.ref_value])} - local ui_letters = {} - for i = 1, args.max_length do - text.letters[i] = (args.ref_table[args.ref_value] and (string.sub(args.ref_table[args.ref_value], i, i) or '')) or '' - ui_letters[i] = {n=G.UIT.T, config={ref_table = text.letters, ref_value = i, scale = args.text_scale, colour = G.C.UI.TEXT_LIGHT, id = args.id..'_letter_'..i}} - end - args.text = text - - local position_text_colour = lighten(copy_table(G.C.BLUE), 0.4) - - ui_letters[#ui_letters+1] = {n=G.UIT.T, config={ref_table = args, ref_value = 'current_prompt_text', scale = args.text_scale, colour = lighten(copy_table(args.colour), 0.4), id = args.id..'_prompt'}} - ui_letters[#ui_letters+1] = {n=G.UIT.B, config={r = 0.03,w=0.1, h=0.4, colour = position_text_colour, id = args.id..'_position', func = 'flash'}} - - local t = - {n=G.UIT.C, config={align = "cm", colour = G.C.CLEAR}, nodes = { - {n=G.UIT.C, config={id = args.id, align = "cm", padding = 0.05, r = 0.1, hover = true, colour = args.colour,minw = args.w, min_h = args.h, button = 'select_text_input', shadow = true}, nodes={ - {n=G.UIT.R, config={ref_table = args, padding = 0.05, align = "cm", r = 0.1, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={ref_table = args, align = "cm", r = 0.1, colour = G.C.CLEAR, func = 'text_input'}, nodes= - ui_letters - } - }} - }} - }} - return t -end - -function create_keyboard_input(args) - local keyboard_rows = { - '1234567890', - 'QWERTYUIOP', - 'ASDFGHJKL', - 'ZXCVBNM', - args.space_key and ' ' or nil - } - local keyboard_button_rows = { - {},{},{},{},{} - } - for k, v in ipairs(keyboard_rows) do - for i = 1, #v do - local c = v:sub(i,i) - keyboard_button_rows[k][#keyboard_button_rows[k] +1] = create_keyboard_button(c, c == ' ' and 'y' or nil) - end - end - return {n=G.UIT.ROOT, config={align = "cm", padding = 15, r = 0.1, colour = {G.C.GREY[1], G.C.GREY[2], G.C.GREY[3],0.7}}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, colour = G.C.CLEAR}, nodes = { - {n=G.UIT.C, config={align = "cm", padding = 0.05, colour = G.C.BLACK, emboss = 0.05, r = 0.1, mid = true}, nodes = { - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes = { - {n=G.UIT.C, config={align = "cm", padding = 0.05, colour = G.C.CLEAR}, nodes = { - {n=G.UIT.R, config={align = "cm", padding = 0.07, colour = G.C.CLEAR}, nodes=keyboard_button_rows[1]}, - {n=G.UIT.R, config={align = "cm", padding = 0.07, colour = G.C.CLEAR}, nodes=keyboard_button_rows[2]}, - {n=G.UIT.R, config={align = "cm", padding = 0.07, colour = G.C.CLEAR}, nodes=keyboard_button_rows[3]}, - {n=G.UIT.R, config={align = "cm", padding = 0.07, colour = G.C.CLEAR}, nodes=keyboard_button_rows[4]}, - {n=G.UIT.R, config={align = "cm", padding = 0.07, colour = G.C.CLEAR}, nodes=keyboard_button_rows[5]} - }}, - (args.backspace_key or args.return_key) and {n=G.UIT.C, config={align = "cm", padding = 0.05, colour = G.C.CLEAR}, nodes = { - args.backspace_key and {n=G.UIT.R, config={align = "cm", padding = 0.05, colour = G.C.CLEAR}, nodes={create_keyboard_button('backspace', 'x')}} or nil, - args.return_key and {n=G.UIT.R, config={align = "cm", padding = 0.05, colour = G.C.CLEAR}, nodes={create_keyboard_button('return', 'start')}} or nil, - {n=G.UIT.R, config={align = "cm", padding = 0.05, colour = G.C.CLEAR}, nodes={create_keyboard_button('back', 'b')}} - }} or nil - }}, - }} - }}, - - }} -end - -function create_keyboard_button(key, binding) - local key_label = (key == 'backspace' and 'Backspace') or (key == ' ' and 'Space') or (key == 'back' and 'Back') or (key == 'return' and 'Enter') or key - return UIBox_button{ label = {key_label}, button = "key_button", ref_table = {key = key == 'back' and 'return' or key}, - minw = key == ' ' and 6 or key == 'return' and 2.5 or key == 'backspace' and 2.5 or key == 'back' and 2.5 or 0.8, - minh = key == 'return' and 1.5 or key == 'backspace' and 1.5 or key == 'back' and 0.8 or 0.7, - col = true, colour = G.C.GREY, focus_args = binding and {button = binding, orientation = (key == ' ' or key == 'back') and 'cr' or 'bm', set_button_pip= true} or nil} -end - -function create_dynatext_pips(args) - args = args or {} - - args.active_colour = copy_table(args.colour) or G.C.RED - args.inactive_colour = copy_table(args.inactive_colour) or {0,0,0,0.08} - args.w = args.w or 0.07 - args.h = args.h or 0.07 - - if not (args.dynatext) or not (#args.dynatext.strings > 1) then return end - - local pips = {} - - for i = 1, #args.dynatext.strings do - pips[i] = {n=G.UIT.C, config={ref_table = args.dynatext, minw = args.w, minh = args.h, colour = G.C.UI.TEXT_INACTIVE, r = 0.1, id = 'pip_'..i, pipcol1 = args.active_colour, pipcol2 = args.inactive_colour, func = 'pip_dynatext'}} - end - - return {n=G.UIT.R, config={padding = 0.05, align = "cm"}, nodes=pips} -end - -function create_UIBox_options() - local current_seed = nil - local restart = nil - local main_menu = nil - local mods = nil - local your_collection = nil - local credits = nil - local customize = nil - - G.E_MANAGER:add_event(Event({ - blockable = false, - func = function() - G.REFRESH_ALERTS = true - return true - end - })) - - if G.STAGE == G.STAGES.RUN then - restart = UIBox_button{id = 'restart_button', label = {localize('b_start_new_run')}, button = "setup_run", minw = 5} - main_menu = UIBox_button{ label = {localize('b_main_menu')}, button = "go_to_menu", minw = 5} - mods = UIBox_button{ id = "mods_button", label = {localize('b_mods')}, button = "mods_button", minw = 5} - your_collection = UIBox_button{ label = {localize('b_collection')}, button = "your_collection", minw = 5, id = 'your_collection'} - current_seed = {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = localize('b_seed')..": ", scale = 0.4, colour = G.C.WHITE}} - }}, - {n=G.UIT.C, config={align = "cm", padding = 0, minh = 0.8}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0, minh = 0.8}, nodes={ - {n=G.UIT.R, config={align = "cm", r = 0.1, colour = G.GAME.seeded and G.C.RED or G.C.BLACK, minw = 1.8, minh = 0.5, padding = 0.1, emboss = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={ text = tostring(G.GAME.pseudorandom.seed), scale = 0.43, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }} - }} - }} - }}, - UIBox_button({col = true, button = 'copy_seed', label = {localize('b_copy')}, colour = G.C.BLUE, scale = 0.3, minw = 1.3, minh = 0.5,}), - }} - end - if G.STAGE == G.STAGES.MAIN_MENU then - credits = UIBox_button{ label = {localize('b_credits')}, button = "show_credits", minw = 5} - end - - local settings = UIBox_button({button = 'settings', label = {localize('b_settings')}, minw = 5, focus_args = {snap_to = true}}) - local high_scores = UIBox_button{ label = {localize('b_stats')}, button = "high_scores", minw = 5} - local customize = UIBox_button{ label = {localize('b_customize_deck')}, button = "customize_deck", minw = 5} - - local t = create_UIBox_generic_options({ contents = { - settings, - G.GAME.seeded and current_seed or nil, - restart, - main_menu, - mods, - high_scores, - your_collection, - customize, - credits - }}) - return t -end - -function create_UIBox_settings() - local tabs = {} - tabs[#tabs+1] = { - label = localize('b_set_game'), - chosen = true, - tab_definition_function = G.UIDEF.settings_tab, - tab_definition_function_args = 'Game' - } - if G.F_VIDEO_SETTINGS then tabs[#tabs+1] = { - label = localize('b_set_video'), - tab_definition_function = G.UIDEF.settings_tab, - tab_definition_function_args = 'Video' - } - end - tabs[#tabs+1] = { - label = localize('b_set_graphics'), - tab_definition_function = G.UIDEF.settings_tab, - tab_definition_function_args = 'Graphics' - } - tabs[#tabs+1] = { - label = localize('b_set_audio'), - tab_definition_function = G.UIDEF.settings_tab, - tab_definition_function_args = 'Audio' - } - - if not require("debugplus.config").SMODSLoaded then - tabs[#tabs+1] = { - label = "DebugPlus", - tab_definition_function = require("debugplus.config").fakeConfigTab, - } - end - local settings_icon = Cartomancer.add_settings_icon() - if settings_icon then - tabs[#tabs+1] = { - colour = G.C.MONEY, - custom_button = {settings_icon}, - tab_definition_function = Cartomancer.config_tab, - tab_definition_function_args = '' - } - end - local t = create_UIBox_generic_options({back_func = 'options',contents = {create_tabs( - {tabs = tabs, - tab_h = 7.05, - tab_alignment = 'tm', - snap_to_nav = true} - )}}) -return t -end - -function G.UIDEF.settings_tab(tab) - if tab == 'Game' then - return {n=G.UIT.ROOT, config={align = "cm", padding = 0.05, colour = G.C.CLEAR}, nodes={ - create_option_cycle({label = localize('b_set_gamespeed'),scale = 0.8, options = {0.5, 1, 2, 4}, opt_callback = 'change_gamespeed', current_option = (G.SETTINGS.GAMESPEED == 0.5 and 1 or G.SETTINGS.GAMESPEED == 4 and 4 or G.SETTINGS.GAMESPEED + 1)}), - create_option_cycle({w = 5, label = localize('b_set_play_discard_pos'),scale = 0.8, options = localize('ml_play_discard_pos_opt'), opt_callback = 'change_play_discard_position', current_option = (G.SETTINGS.play_button_pos)}), - G.F_RUMBLE and create_toggle({label = localize('b_set_rumble'), ref_table = G.SETTINGS, ref_value = 'rumble'}) or nil, - create_slider({label = localize('b_set_screenshake'),w = 4, h = 0.4, ref_table = G.SETTINGS, ref_value = 'screenshake', min = 0, max = 100}), - create_toggle({label = localize('ph_display_stickers'), ref_table = G.SETTINGS, ref_value = 'run_stake_stickers'}), - --create_toggle({label = localize('b_high_contrast_cards'), ref_table = G.SETTINGS, ref_value = 'colourblind_option', callback = G.FUNCS.refresh_contrast_mode}), - create_toggle({label = localize('b_reduced_motion'), ref_table = G.SETTINGS, ref_value = 'reduced_motion'}), - G.F_CRASH_REPORTS and create_toggle({label = localize('b_set_crash_reports'), ref_table = G.SETTINGS, ref_value = 'crashreports', info = localize('ml_crash_report_info')}) or nil, - }} - elseif tab == 'Video' then - --Reset the queue so there are no pending changes - G.SETTINGS.QUEUED_CHANGE = {} - - --Refresh the display information for all displays based on the screenmode selected - local res_option = GET_DISPLAYINFO(G.SETTINGS.WINDOW.screenmode, G.SETTINGS.WINDOW.selected_display) - - return - {n=G.UIT.ROOT, config={align = "cm", padding = 0.05, colour = G.C.CLEAR}, nodes={ - create_option_cycle({w = 4,scale = 0.8, label = localize('b_set_monitor'), options = G.SETTINGS.WINDOW.display_names, opt_callback = 'change_display', current_option = (G.SETTINGS.WINDOW.selected_display)}), - create_option_cycle({w = 4,scale = 0.8, label = localize('b_set_windowmode'), options = localize('ml_windowmode_opt'), opt_callback = 'change_screenmode', current_option = (({Windowed = 1, Fullscreen = 2, Borderless = 3})[G.SETTINGS.WINDOW.screenmode] or 1)}), - {n=G.UIT.R, config={align = "cm", id = 'resolution_cycle'}, nodes={create_option_cycle({w = 4,scale = 0.8, options = G.SETTINGS.WINDOW.DISPLAYS[G.SETTINGS.WINDOW.selected_display].screen_resolutions.strings, opt_callback = 'change_screen_resolution',current_option = res_option or 1})}}, - {n=G.UIT.R, config={align = "cm"}, nodes={create_option_cycle({w = 4,scale = 0.8, options = localize('ml_vsync_opt'), opt_callback = 'change_vsync',current_option = G.SETTINGS.WINDOW.vsync == 0 and 2 or 1})}}, - UIBox_button({button = 'apply_window_changes', label = {localize('b_set_apply')}, minw = 3, func = 'can_apply_window_changes'}), - }} - elseif tab == 'Audio' then - return {n=G.UIT.ROOT, config={align = "cm", padding = 0.05, colour = G.C.CLEAR}, nodes={ - create_slider({label = localize('b_set_master_vol'), w = 5, h = 0.4, ref_table = G.SETTINGS.SOUND, ref_value = 'volume', min = 0, max = 100}), - create_slider({label = localize('b_set_music_vol'), w = 5, h = 0.4, ref_table = G.SETTINGS.SOUND, ref_value = 'music_volume', min = 0, max = 100}), - create_slider({label = localize('b_set_game_vol'), w = 5, h = 0.4, ref_table = G.SETTINGS.SOUND, ref_value = 'game_sounds_volume', min = 0, max = 100}), - }} - elseif tab == 'Graphics' then - return {n=G.UIT.ROOT, config={align = "cm", padding = 0.05, colour = G.C.CLEAR}, nodes={ - create_option_cycle({w = 4,scale = 0.8, label = localize("b_set_shadows"),options = localize('ml_shadow_opt'), opt_callback = 'change_shadows', current_option = (G.SETTINGS.GRAPHICS.shadows == 'On' and 1 or 2)}), - create_option_cycle({w = 4,scale = 0.8, label = localize("b_set_pixel_smoothing"),options = localize('ml_smoothing_opt'), opt_callback = 'change_pixel_smoothing', current_option = G.SETTINGS.GRAPHICS.texture_scaling}), - create_slider({label = localize('b_set_CRT'),w = 4, h = 0.4, ref_table = G.SETTINGS.GRAPHICS, ref_value = 'crt', min = 0, max = 100}), - create_option_cycle({w = 4,scale = 0.8, label = localize("b_set_CRT_bloom"),options = localize('ml_bloom_opt'), opt_callback = 'change_crt_bloom', current_option = G.SETTINGS.GRAPHICS.bloom}), - create_option_cycle({label = localize('b_graphics_mipmap_level'),scale = 0.8, options = SMODS.config.graphics_mipmap_level_options, opt_callback = 'SMODS_change_mipmap', current_option = SMODS.config.graphics_mipmap_level}), - }} - end - - return {n=G.UIT.ROOT, config={align = "cm", padding = 0.05, colour = G.C.CLEAR, minh = 5, minw = 5}, nodes={}} -end - -function create_UIBox_test_framework(variables) - variables = variables or {}; - local nodes = {} - for k, v in pairs(variables) do - if v.type == 'cycle' then - table.insert(nodes, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = v.label or '', scale = 0.5, colour = G.C.UI.TEXT_DARK}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - create_option_cycle({options = v.options, opt_callback = 'test_framework_cycle_callback', ref_table = v.ref_table, ref_value = v.ref_value}) - }}, - }}) - elseif v.type == 'slider' then - table.insert(nodes, - {n=G.UIT.R, config={align = "cm", minh = 1, minw = 1, padding = 0.05, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = v.label, scale = 0.5, colour = G.C.UI.TEXT_DARK}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - create_slider({w = 5, h = 0.4, ref_table = v.ref_table, ref_value = v.ref_value, min = v.min or 0, max = v.max or 1}), - }}, - }}) - elseif v.type == 'text_input' then - table.insert(nodes, - {n=G.UIT.R, config={align = "cm", minh = 1, minw = 1, padding = 0.05, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = v.label, scale = 0.5, colour = G.C.UI.TEXT_DARK}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - create_text_input(v.options), - }}, - }}) - end - end - local t = {n=G.UIT.ROOT, config = {align = "cm", minw = G.ROOM.T.w*5, minh = G.ROOM.T.h*5,padding = 0.15, r = 0.1, colour = {G.C.BLACK[1], G.C.BLACK[2], G.C.BLACK[3],0.6}}, nodes={ - {n=G.UIT.C, config={align = "cm", minh = 1,r = 0.3, padding = 0.1, minw = 1, colour = G.C.WHITE, shadow = true}, nodes={ - {n=G.UIT.C, config={align = "cm", minh = 1,r = 0.2, padding = 0.2, minw = 1, colour = G.C.CLEAR, outline = 1, outline_colour = G.C.BLACK}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes= - nodes - }, - {n=G.UIT.R, config={align = "cm", minw = 2.5, padding = 0.1, r = 0.1, hover = true, colour = G.C.ORANGE, button = "exit_overlay_menu", shadow = true}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes={ - {n=G.UIT.T, config={text = "Back", scale = 0.5, colour = G.C.UI.TEXT_LIGHT}} - }} - }}, - }} - }} - }} -return t -end - -function G.UIDEF.usage_tabs() - return create_UIBox_generic_options({back_func = 'high_scores', contents ={create_tabs( - {tabs = { - { - label = localize('b_stat_jokers'), - chosen = true, - tab_definition_function = create_UIBox_usage, - tab_definition_function_args = {'joker_usage'}, - }, - { - label = localize('b_stat_consumables'), - tab_definition_function = create_UIBox_usage, - tab_definition_function_args = {'consumeable_usage'}, - }, - { - label = localize('b_stat_tarots'), - tab_definition_function = create_UIBox_usage, - tab_definition_function_args = {'consumeable_usage', 'Tarot'}, - }, - { - label = localize('b_stat_planets'), - tab_definition_function = create_UIBox_usage, - tab_definition_function_args = {'consumeable_usage', 'Planet'}, - }, - { - label = localize('b_stat_spectrals'), - tab_definition_function = create_UIBox_usage, - tab_definition_function_args = {'consumeable_usage', 'Spectral'}, - }, - { - label = localize('b_stat_vouchers'), - tab_definition_function = create_UIBox_usage, - tab_definition_function_args = {'voucher_usage', 'Voucher'}, - }, - }, - tab_h = 8, - snap_to_nav = true})}}) -end - -function create_UIBox_usage(args) - args = args or {} - _type, _set = args[1], args[2] - local used_cards = {} - local max_amt = 0 - for k, v in pairs(G.PROFILES[G.SETTINGS.profile][_type]) do - if G.P_CENTERS[k] and (not _set or G.P_CENTERS[k].set == _set) and G.P_CENTERS[k].discovered then - used_cards[#used_cards + 1] = {count = v.count, key = k} - if v.count > max_amt then max_amt = v.count end - end - end - - local _col = G.C.SECONDARY_SET[_set] or G.C.RED - - table.sort(used_cards, function (a, b) return a.count > b.count end ) - - local histograms = {} - - for i = 1, 10 do - local v = used_cards[i] - if v then - local card = Card(0,0, 0.7*G.CARD_W, 0.7*G.CARD_H, nil, G.P_CENTERS[v.key]) - card.ambient_tilt = 0.8 - local cardarea = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - G.CARD_W*0.7, - G.CARD_H*0.7, - {card_limit = 2, type = 'title', highlight_limit = 0}) - cardarea:emplace(card) - - histograms[#histograms +1] = - {n=G.UIT.C, config={align = "bm",minh = 6.2, colour = G.C.UI.TRANSPARENT_DARK, r = 0.1}, nodes={ - - {n=G.UIT.R, config={align = "bm"}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.7*G.CARD_H+0.1} , nodes={ - {n=G.UIT.O, config={object = cardarea}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.T, config={text = v.count, scale = 0.35, colour = mix_colours(G.C.FILTER, G.C.WHITE, 0.8), shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = v.count/max_amt*3.6, minw = 0.8, colour = G.C.SECONDARY_SET[G.P_CENTERS[v.key].set] or G.C.RED, res = 0.15, r = 0.001}, nodes={}}, - }}, - }}, - }} - else - histograms[#histograms +1] = - {n=G.UIT.C, config={align = "bm",minh = 6.2, colour = G.C.UI.TRANSPARENT_DARK, r = 0.1}, nodes={ - {n=G.UIT.R, config={align = "bm"}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.7*G.CARD_H+0.1, minw = 0.7*G.CARD_W} , nodes={ - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.T, config={text = '-', scale = 0.35, colour = mix_colours(G.C.FILTER, G.C.WHITE, 0.8), shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.2, minw = 0.8, colour = G.C.UI.TRANSPARENT_LIGHT, res = 0.15, r = 0.001}, nodes={}}, - }}, - }}, - }} - end - end - - local t = {n=G.UIT.ROOT, config={align = "cm", minw = 3, padding = 0.1, r = 0.1, colour = G.C.UI.TRANSPARENT_DARK}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.B, config={w=0.2,h=0.2,r =0.1,colour = G.C.FILTER}}, - {n=G.UIT.T, config={text = - _type == 'joker_usage' and localize('ph_stat_joker') or - _type == 'consumeable_usage' and localize('ph_stat_consumable') or - _type == 'voucher_usage' and localize('ph_stat_voucher'), - scale = 0.35, colour = G.C.WHITE}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes=histograms}, - }} - - return t -end - -function create_UIBox_customize_deck() - local suitTabs = {} - - local index = 1 - for i, suit in ipairs(SMODS.Suit:obj_list(true)) do - if G.COLLABS.options[suit.key] then - suitTabs[index] = { - label = localize(suit.key, 'suits_plural'), - tab_definition_function = G.UIDEF.custom_deck_tab, - tab_definition_function_args = suit.key - } - index = index + 1 - end - end - - if suitTabs[1] then - suitTabs[1].chosen = true - end - - local t = create_UIBox_generic_options({ back_func = 'options', snap_back = nil, contents = { - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - create_tabs( - {tabs = suitTabs, snap_to_nav = true, no_shoulders = true} - )}}} - }) - - return t -end - - -function G.UIDEF.custom_deck_tab(_suit) - local t = {} - - local rankCount = 0 -local lookup = {} -local options = G.COLLABS.options[_suit] -for i = 2, #options do - local skin = SMODS.DeckSkins[options[i]] - for j = 1, #skin.ranks do - if not lookup[skin.ranks[j]] then - lookup[skin.ranks[j]] = true - rankCount = rankCount + 1 - end - end -end - -local face_cards = CardArea( - 0,0, - math.min(math.max(rankCount*G.CARD_W*0.6, 4*G.CARD_W), 10*G.CARD_W), - 1.4*G.CARD_H, - {card_limit = rankCount, type = 'title', highlight_limit = 0}) - - - table.insert(t, - {n=G.UIT.R, config={align = "cm", colour = G.C.BLACK, r = 0.1, padding = 0.07, no_fill = true}, nodes={ - {n=G.UIT.O, config={object = face_cards}} - }} - ) - - local loc_options = localize(_suit, 'collabs') - local conv_loc_options = {} - for k, v in pairs(loc_options) do - conv_loc_options[tonumber(k)] = v - end - - loc_options = conv_loc_options - - local current_option = 1 - for k, v in pairs(G.COLLABS.options[_suit]) do - if G.SETTINGS.CUSTOM_DECK.Collabs[_suit] == v then current_option = k end - end - - table.insert(t, - {n=G.UIT.R, config={align = "cm"}, nodes={ - create_option_cycle({options = loc_options, w = 5.5, cycle_shoulders = true, curr_suit = _suit, opt_callback = 'change_collab', current_option = current_option, colour = G.C.RED, focus_args = {snap_to = true, nav = 'wide'}}), - }} - ) - table.insert(t, create_toggle({label = localize('b_high_contrast_cards'), ref_table = G.SETTINGS, ref_value = 'colourblind_option', callback = G.FUNCS.refresh_contrast_mode})) - - local faces = {'K','Q','J'} - local rank = SMODS.Ranks['2'] -local cards = {} -local smodSuit = SMODS.Suits[_suit] -repeat - if lookup[rank.key] then - local card_code = smodSuit.card_key .. '_' .. rank.card_key - local card = Card(0,0, G.CARD_W*1.2, G.CARD_H*1.2, G.P_CARDS[card_code], G.P_CENTERS.c_base) - card.no_ui = true - - cards[#cards + 1] = card - end - rank = SMODS.Ranks[rank.next[1]] -until rank == SMODS.Ranks['2'] - -for i = #cards, 1, -1 do - face_cards:emplace(cards[i]) -end - - - return {n=G.UIT.ROOT, config={align = "cm", padding = 0, colour = G.C.CLEAR, r = 0.1, minw = 7, minh = 4.2}, nodes=t} -end - -function create_UIBox_high_scores() - fetch_achievements() - set_profile_progress() - set_discover_tallies() - - local scores = { - create_UIBox_high_scores_row("hand"), - create_UIBox_high_scores_row("furthest_round"), - create_UIBox_high_scores_row("furthest_ante"), - create_UIBox_high_scores_row("poker_hand"), - create_UIBox_high_scores_row("most_money"), - create_UIBox_high_scores_row("win_streak"), - } - G.focused_profile = G.SETTINGS.profile - local cheevs = {} - - local t = create_UIBox_generic_options({ back_func = 'options', snap_back = true, contents = { - {n=G.UIT.C, config={align = "cm", minw = 3, padding = 0.2, r = 0.1, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes= - scores - }, - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.1, r = 0.1, colour = G.C.CLEAR}, nodes={ - create_progress_box(), - UIBox_button({button = 'usage', label = {localize('k_card_stats')}, minw = 7.5, minh =1, focus_args = {nav = 'wide'}}), - }}, - not G.F_NO_ACHIEVEMENTS and {n=G.UIT.C, config={align = "cm", r = 0.1, colour = G.C.CLEAR}, nodes=cheevs} or nil - }}) - - return t -end - -function create_progress_box(_profile_progress, smaller) - local rows, protos = {}, {'collection', 'challenges', 'joker_stickers', 'deck_stake_wins'} - _profile_progress = _profile_progress or G.PROFILES[G.SETTINGS.profile].progress - - - _profile_progress.overall_tally, _profile_progress.overall_of = - _profile_progress.discovered.tally/_profile_progress.discovered.of + - _profile_progress.deck_stakes.tally/_profile_progress.deck_stakes.of + - _profile_progress.joker_stickers.tally/_profile_progress.joker_stickers.of + - _profile_progress.challenges.tally/_profile_progress.challenges.of, - 4 - - local text_scale = smaller and 0.7 or 1 - local bar_colour = G.PROFILES[G.focused_profile].all_unlocked and G.C.RED or G.C.BLUE - - for _, v in ipairs(protos) do - local tab, val, max = nil,nil,nil - if v == 'collection' then - tab, val, max = _profile_progress.discovered, 'tally', _profile_progress.discovered.of - elseif v == 'deck_stake_wins' then - tab, val, max = _profile_progress.deck_stakes, 'tally', _profile_progress.deck_stakes.of - elseif v == 'joker_stickers' then - tab, val, max = _profile_progress.joker_stickers, 'tally', _profile_progress.joker_stickers.of - elseif v == 'challenges' then - tab, val, max = _profile_progress.challenges, 'tally', _profile_progress.challenges.of - end - local filling = v == 'collection' and { - {n=G.UIT.O, config={object = DynaText({string = {math.floor(0.01+100*_profile_progress.discovered.tally/_profile_progress.discovered.of)..'%'}, colours = {G.C.WHITE},shadow = true, float = true, scale = 0.55*text_scale})}}, - {n=G.UIT.T, config={text = " (".._profile_progress.discovered.tally..'/'.._profile_progress.discovered.of..")", scale = 0.35, colour = G.C.JOKER_GREY}} - } or v == 'deck_stake_wins' and { - {n=G.UIT.O, config={object = DynaText({string = {math.floor(0.01+100*_profile_progress.deck_stakes.tally/_profile_progress.deck_stakes.of)..'%'}, colours = {G.C.WHITE},shadow = true, float = true, scale = 0.55*text_scale})}}, - {n=G.UIT.T, config={text = " (".._profile_progress.deck_stakes.tally..'/'.._profile_progress.deck_stakes.of..")", scale = 0.35, colour = G.C.JOKER_GREY}} - } or v == 'joker_stickers' and { - {n=G.UIT.O, config={object = DynaText({string = {math.floor(0.01+100*_profile_progress.joker_stickers.tally/_profile_progress.joker_stickers.of)..'%'}, colours = {G.C.WHITE},shadow = true, float = true, scale = 0.55*text_scale})}}, - {n=G.UIT.T, config={text = " (".._profile_progress.joker_stickers.tally..'/'.._profile_progress.joker_stickers.of..")", scale = 0.35, colour = G.C.JOKER_GREY}} - } or v == 'challenges' and { - {n=G.UIT.O, config={object = DynaText({string = {math.floor(0.01+100*_profile_progress.challenges.tally/_profile_progress.challenges.of)..'%'}, colours = {G.C.WHITE},shadow = true, float = true, scale = 0.55*text_scale})}}, - {n=G.UIT.T, config={text = " (".._profile_progress.challenges.tally..'/'.._profile_progress.challenges.of..")", scale = 0.35, colour = G.C.JOKER_GREY}} - } - - rows[#rows+1] = {n=G.UIT.R, config={align = "cm", padding = 0.05, r = 0.1, colour = darken(G.C.JOKER_GREY, 0.1), emboss = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, minw = 3.5*text_scale, maxw = 3.5*text_scale}, nodes={ - {n=G.UIT.T, config={text = localize('k_'..v), scale = 0.5*text_scale, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.C, config={align = "cl", minh =smaller and 0.5 or 0.8, r = 0.1, minw = 3.5*text_scale, colour = G.C.BLACK, emboss = 0.05, - progress_bar = { - max = max, ref_table = tab, ref_value = val, empty_col = G.C.BLACK, filled_col = adjust_alpha(bar_colour, 0.5) - }}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, r = 0.1, minw = 3.5*text_scale}, nodes=filling}, - }}, - }} - end - - return {n=G.UIT.R, config={align = "cm", padding = 0.05, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, minw = 3.5*text_scale, maxw = 3.5*text_scale}, nodes={ - {n=G.UIT.T, config={text = localize('k_progress'), scale = 0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.C, config={align = "cl", minh = 0.6, r = 0.1, minw = 3.5*text_scale, colour = G.C.BLACK, emboss = 0.05, - progress_bar = { - max = _profile_progress.overall_of, ref_table = _profile_progress, ref_value = 'overall_tally', empty_col = G.C.BLACK, filled_col = adjust_alpha(bar_colour, 0.5) - }}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, r = 0.1, minw = 3.5*text_scale}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {math.floor(0.01+100*_profile_progress.overall_tally/_profile_progress.overall_of)..'%'}, colours = {G.C.WHITE},shadow = true, float = true, scale = 0.55})}}, - }}, - }} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes=rows}, - }} -end - -function create_UIBox_high_scores_row(score) - if not G.PROFILES[G.SETTINGS.profile].high_scores[score] then return nil end - local label_scale = 0.65 - 0.025*math.max(string.len(G.PROFILES[G.SETTINGS.profile].high_scores[score].label)-8, 0) - local label_w, score_w, h = 3.5, 4, 0.8 - local score_tab = {} - - if score == 'poker_hand' then - local handname, amount = localize('k_none'), 0 - for k, v in pairs(G.PROFILES[G.SETTINGS.profile].hand_usage) do if v.count > amount then handname = v.order; amount = v.count end end - score_tab = { - {n=G.UIT.O, config={object = DynaText({string = {amount < 1 and handname or localize(handname,'poker_hands')}, colours = {G.C.WHITE},shadow = true, float = true, scale = 0.55})}}, - {n=G.UIT.T, config={text = " ("..amount..")", scale = 0.45, colour = G.C.JOKER_GREY}} - } - elseif score == 'most_money' then - score_tab = { - {n=G.UIT.O, config={object = DynaText({string = {localize('$')..number_format(G.PROFILES[G.SETTINGS.profile].high_scores[score].amt)}, colours = {G.C.MONEY},shadow = true, float = true, scale = score_number_scale(0.85, G.PROFILES[G.SETTINGS.profile].high_scores[score].amt)})}}, - } - elseif score == 'win_streak' then - score_tab = { - {n=G.UIT.O, config={object = DynaText({string = {number_format(G.PROFILES[G.SETTINGS.profile].high_scores[score].amt)}, colours = {G.C.WHITE},shadow = true, float = true, scale = score_number_scale(0.85, G.PROFILES[G.SETTINGS.profile].high_scores[score].amt)})}}, - {n=G.UIT.T, config={text = " ("..G.PROFILES[G.SETTINGS.profile].high_scores["current_streak"].amt..")", scale = 0.45, colour = G.C.JOKER_GREY}} - } - elseif score == 'hand' then - local chip_sprite = Sprite(0,0,0.4,0.4,G.ASSET_ATLAS["ui_"..(G.SETTINGS.colourblind_option and 2 or 1)], {x=0, y=0}) - chip_sprite.states.drag.can = false - score_tab = { - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={w=0.4,h=0.4 , object = chip_sprite}} - }}, - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {number_format(G.PROFILES[G.SETTINGS.profile].high_scores[score].amt)}, colours = {G.C.RED},shadow = true, float = true, scale = math.min(0.75, score_number_scale(1.5, G.PROFILES[G.SETTINGS.profile].high_scores[score].amt))})}}, - }}, - } - elseif score == 'collection' then - score_tab = { - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {'%'..math.floor(0.01+100*G.PROFILES[G.SETTINGS.profile].high_scores[score].amt/G.PROFILES[G.SETTINGS.profile].high_scores[score].tot)}, colours = {G.C.WHITE},shadow = true, float = true, scale = math.min(0.75, score_number_scale(1.5, G.PROFILES[G.SETTINGS.profile].high_scores[score].amt))})}}, - {n=G.UIT.T, config={text = " ("..G.PROFILES[G.SETTINGS.profile].high_scores[score].amt..'/'..G.PROFILES[G.SETTINGS.profile].high_scores[score].tot..")", scale = 0.45, colour = G.C.JOKER_GREY}} - }}, - } - else - score_tab = { - {n=G.UIT.O, config={object = DynaText({string = {number_format(G.PROFILES[G.SETTINGS.profile].high_scores[score].amt)}, colours = {G.C.FILTER},shadow = true, float = true, scale = score_number_scale(0.85, G.PROFILES[G.SETTINGS.profile].high_scores[score].amt)})}}, - } - end - return {n=G.UIT.R, config={align = "cm", padding = 0.05, r = 0.1, colour = darken(G.C.JOKER_GREY, 0.1), emboss = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, minw = label_w, maxw = label_w}, nodes={ - {n=G.UIT.T, config={text = localize(score, 'high_scores'), scale = label_scale, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.C, config={align = "cl", minh = h, r = 0.1, minw = score_w, colour = G.C.BLACK, emboss = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, r = 0.1, minw = score_w, maxw = score_w}, nodes=score_tab}, - }}, - }} -end - -function create_UIBox_win() - local show_lose_cta = false - local eased_green = copy_table(G.C.GREEN) - eased_green[4] = 0 - ease_value(eased_green, 4, 0.5, nil, nil, true) - local t = create_UIBox_generic_options({ padding = 0, bg_colour = eased_green , colour = G.C.BLACK, outline_colour = G.C.EDITION, no_back = true, no_esc = true, contents = { - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('ph_you_win')}, colours = {G.C.EDITION},shadow = true, float = true, spacing = 10, rotate = true, scale = 1.5, pop_in = 0.4, maxw = 6.5})}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.15}, nodes={ - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.08}, nodes={ - create_UIBox_round_scores_row('hand'), - create_UIBox_round_scores_row('poker_hand'), - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.08}, nodes={ - create_UIBox_round_scores_row('cards_played', G.C.BLUE), - create_UIBox_round_scores_row('cards_discarded', G.C.RED), - create_UIBox_round_scores_row('cards_purchased', G.C.MONEY), - create_UIBox_round_scores_row('times_rerolled', G.C.GREEN), - create_UIBox_round_scores_row('new_collection', G.C.WHITE), - create_UIBox_round_scores_row('seed', G.C.WHITE), - UIBox_button({button = 'copy_seed', label = {localize('b_copy')}, colour = G.C.BLUE, scale = 0.3, minw = 2.3, minh = 0.4,}), - }}, - {n=G.UIT.C, config={align = "tr", padding = 0.08}, nodes={ - create_UIBox_round_scores_row('furthest_ante', G.C.FILTER), - create_UIBox_round_scores_row('furthest_round', G.C.FILTER), - {n=G.UIT.R, config={align = "cm", minh = 0.4, minw = 0.1}, nodes={}}, - show_win_cta and UIBox_button({id = 'win_cta', button = 'show_main_cta', label = {localize('b_next')}, colour = G.C.GREEN, scale = 0.8, minw = 2.5, minh = 2.5, focus_args = {nav = 'wide', snap_to = true}}) or nil, - not show_win_cta and UIBox_button({id = 'from_game_won', button = 'notify_then_setup_run', label = {localize('b_start_new_run')}, minw = 2.5, maxw = 2.5, minh = 1, focus_args = {nav = 'wide', snap_to = true}}) or nil, - not show_win_cta and {n=G.UIT.R, config={align = "cm", minh = 0.2, minw = 0.1}, nodes={}} or nil, - not show_win_cta and UIBox_button({button = 'go_to_menu', label = {localize('b_main_menu')}, minw = 2.5, maxw = 2.5, minh = 1, focus_args = {nav = 'wide'}}) or nil, - }} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.08}, nodes={ - UIBox_button({button = 'exit_overlay_menu', label = {localize('b_endless')}, minw = 6.5, maxw = 5, minh = 1.2, scale = 0.7, shadow = true, colour = G.C.BLUE, focus_args = {nav = 'wide', button = 'x',set_button_pip = true}}), - }}, - }} - }} - }}) - t.nodes[1] = {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 2}, nodes={ - {n=G.UIT.O, config={padding = 0, id = 'jimbo_spot', object = Moveable(0,0,G.CARD_W*1.1, G.CARD_H*1.1)}}, - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={t.nodes[1]} - }} - } - --t.nodes[1].config.mid = true - t.config.id = 'you_win_UI' - return t -end - -function create_UIBox_exit_CTA() - - local t = create_UIBox_generic_options({ back_label = 'Quit Game', back_func = 'quit' , colour = G.C.BLACK, back_colour = G.C.RED, padding = 0, contents = { - {n=G.UIT.C, config={align = "tm", padding = 0.15}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('ph_demo_thanks_1')}, colours = {G.C.WHITE},shadow = true, float = true, scale = 0.9})}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('ph_demo_thanks_2')}, colours = {G.C.WHITE},shadow = true, bump = true, rotate = true, pop_in = 0.2, scale = 1.4})}}, - }}, - {n=G.UIT.R, config={align = "tm", padding = 0.12, emboss = 0.1, colour = G.C.L_BLACK, r = 0.1}, nodes={ - simple_text_container('ml_demo_thanks_message',{colour = G.C.UI.TEXT_LIGHT, scale = 0.55, shadow = true}), - {n=G.UIT.R, config={align = "cm", padding = 0.2}, nodes={ - UIBox_button({button = 'wishlist_steam', label = {localize('b_wishlist')}, minw = 5.9, minh = 1.1, scale = 0.5, shadow = true, colour = G.C.GREEN, focus_args = {nav = 'wide', button = 'x',set_button_pip = true, snap_to = true}}), - UIBox_button({button = 'go_to_playbalatro', label = {localize('b_playbalatro')}, minw = 4.9, minh = 0.8, scale = 0.4, shadow = true, colour = G.C.BLUE, focus_args = {nav = 'wide', button = 'y',set_button_pip = true}}), - }}, - }}, - }} - }}) - t.nodes[2] = t.nodes[1] - t.nodes[1] = {n=G.UIT.C, config={align = "cm", padding = 2}, nodes={ - {n=G.UIT.O, config={padding = 0, id = 'jimbo_spot', object = Moveable(0,0,G.CARD_W*1.1, G.CARD_H*1.1)}}, - }} - --t.nodes[1].config.mid = true - return t -end - -function create_UIBox_small_cta() - return {n=G.UIT.ROOT, config={align = "cm", minw = 4, minh = 3}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('ph_demo_thanks_1')}, colours = {G.C.WHITE},shadow = true, float = true, scale = 0.3})}}, - }} -end - -function create_UIBox_demo_video_CTA() - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 21.7, - blockable = false, - blocking = false, - func = (function() - G.exception_queue = 'other' - G.FUNCS.go_to_demo_cta() - G.exception_queue = nil - return true - end)}), 'other') - - RESTART_MUSIC() - - local video_file = love.graphics.newVideo('resources/democta.ogv') - local vid_sprite = Sprite(0,0,11*16/9,11,G.ASSET_ATLAS["ui_"..(G.SETTINGS.colourblind_option and 2 or 1)], {x=0, y=0}) - video_file:getSource():setVolume(G.SETTINGS.SOUND.volume*G.SETTINGS.SOUND.game_sounds_volume/(100*100)) - vid_sprite.video = video_file - video_file:play() - - local t = create_UIBox_generic_options({ back_delay = 7, back_label = localize('b_skip'), back_func = 'go_to_demo_cta' , colour = G.C.BLACK, padding = 0, contents = { - {n=G.UIT.O, config={object = vid_sprite}}, - }}) - return t -end - -function create_UIBox_game_over() - local show_lose_cta = false - - - local eased_red = copy_table(G.GAME.round_resets.ante <= G.GAME.win_ante and G.C.RED or G.C.BLUE) - eased_red[4] = 0 - ease_value(eased_red, 4, 0.8, nil, nil, true) - local t = create_UIBox_generic_options({ bg_colour = eased_red ,no_back = true, padding = 0, contents = { - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('ph_game_over')}, colours = {G.C.RED},shadow = true, float = true, scale = 1.5, pop_in = 0.4, maxw = 6.5})}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.15}, nodes={ - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05, colour = G.C.BLACK, emboss = 0.05, r = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.08}, nodes={ - create_UIBox_round_scores_row('hand'), - create_UIBox_round_scores_row('poker_hand'), - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.08}, nodes={ - create_UIBox_round_scores_row('cards_played', G.C.BLUE), - create_UIBox_round_scores_row('cards_discarded', G.C.RED), - create_UIBox_round_scores_row('cards_purchased', G.C.MONEY), - create_UIBox_round_scores_row('times_rerolled', G.C.GREEN), - create_UIBox_round_scores_row('new_collection', G.C.WHITE), - create_UIBox_round_scores_row('seed', G.C.WHITE), - UIBox_button({button = 'copy_seed', label = {localize('b_copy')}, colour = G.C.BLUE, scale = 0.3, minw = 2.3, minh = 0.4, focus_args = {nav = 'wide'}}), - }}, - {n=G.UIT.C, config={align = "tr", padding = 0.08}, nodes={ - create_UIBox_round_scores_row('furthest_ante', G.C.FILTER), - create_UIBox_round_scores_row('furthest_round', G.C.FILTER), - create_UIBox_round_scores_row('defeated_by'), - }} - }} - }}, - show_lose_cta and - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={id = 'lose_cta', align = "cm", minw = 5, padding = 0.1, r = 0.1, hover = true, colour = G.C.GREEN, button = "show_main_cta", shadow = true}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes={ - {n=G.UIT.T, config={text = localize('b_next'), scale = 0.5, colour = G.C.UI.TEXT_LIGHT, focus_args = {nav = 'wide', snap_to = true}}} - }} - }} - }} or - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.R, config={id = 'from_game_over', align = "cm", minw = 5, padding = 0.1, r = 0.1, hover = true, colour = G.C.RED, button = "notify_then_setup_run", shadow = true, focus_args = {nav = 'wide', snap_to = true}}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true, maxw = 4.8}, nodes={ - {n=G.UIT.T, config={text = localize('b_start_new_run'), scale = 0.5, colour = G.C.UI.TEXT_LIGHT}} - }} - }}, - {n=G.UIT.R, config={align = "cm", minw = 5, padding = 0.1, r = 0.1, hover = true, colour = G.C.RED, button = "go_to_menu", shadow = true, focus_args = {nav = 'wide'}}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true, maxw = 4.8}, nodes={ - {n=G.UIT.T, config={text = localize('b_main_menu'), scale = 0.5, colour = G.C.UI.TEXT_LIGHT}} - }} - }} - }} - }}, - }} -}}) - t.nodes[1] = {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 2}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={padding = 0, id = 'jimbo_spot', object = Moveable(0,0,G.CARD_W*1.1, G.CARD_H*1.1)}}, - }}, - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={t.nodes[1]}}} -} - - --t.nodes[1].config.mid = true - return t -end - -function create_UIBox_round_scores_row(score, text_colour) - local label = G.GAME.round_scores[score] and localize('ph_score_'..score) or '' - local check_high_score = false - local score_tab = {} - local label_w, score_w, h = ({hand=true,poker_hand=true})[score] and 3.5 or 2.9, ({hand=true,poker_hand=true})[score] and 3.5 or 1, 0.5 - - if score == 'furthest_ante' then - label_w = 1.9 - check_high_score = true - label = localize('k_ante') - score_tab = { - {n=G.UIT.O, config={object = DynaText({string = {number_format(G.GAME.round_resets.ante)}, colours = {text_colour or G.C.FILTER},shadow = true, float = true, scale = 0.45})}}, - } - end - if score == 'furthest_round' then - label_w = 1.9 - check_high_score = true - label = localize('k_round') - score_tab = { - {n=G.UIT.O, config={object = DynaText({string = {number_format(G.GAME.round)}, colours = {text_colour or G.C.FILTER},shadow = true, float = true, scale = 0.45})}}, - } - end - if score == 'seed' then - label_w = 1.9 - score_w = 1.9 - label = localize('k_seed') - score_tab = { - {n=G.UIT.O, config={object = DynaText({string = {G.GAME.pseudorandom.seed}, colours = {text_colour or G.C.WHITE},shadow = true, float = true, scale = 0.45})}}, - } - end - if score == 'defeated_by' then - label = localize('k_defeated_by') - local blind_choice = {config = G.GAME.blind.config.blind or G.P_BLINDS.bl_small} - blind_choice.animation = AnimatedSprite(0,0, 1.4, 1.4, G.ANIMATION_ATLAS[blind_choice.config.atlas] or G.ANIMATION_ATLAS['blind_chips'], blind_choice.config.pos) - blind_choice.animation:define_draw_steps({ - {shader = 'dissolve', shadow_height = 0.05}, - {shader = 'dissolve'} - }) - - score_tab = { - {n=G.UIT.R, config={align = "cm", minh = 0.6}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = localize{type ='name_text', key = blind_choice.config.key, set = 'Blind'}, colours = {G.C.WHITE},shadow = true, float = true,maxw = 2.2, scale = 0.45})}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.O, config={object = blind_choice.animation}} - }}, - } - end - - local label_scale = 0.5 - - if score == 'poker_hand' then - local handname, amount = localize('k_none'), 0 - for k, v in pairs(G.GAME.hand_usage) do if v.count > amount then handname = v.order; amount = v.count end end - score_tab = { - {n=G.UIT.O, config={object = DynaText({string = {amount <1 and handname or localize(handname,'poker_hands')}, colours = {text_colour or G.C.WHITE},shadow = true, float = true, scale = 0.45, maxw = 2.5})}}, - {n=G.UIT.T, config={text = " ("..amount..")", scale = 0.35, colour = G.C.JOKER_GREY}} - } - elseif score == 'hand' then - check_high_score = true - local chip_sprite = Sprite(0,0,0.3,0.3,G.ASSET_ATLAS["ui_"..(G.SETTINGS.colourblind_option and 2 or 1)], {x=0, y=0}) - chip_sprite.states.drag.can = false - score_tab = { - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={w=0.3,h=0.3 , object = chip_sprite}} - }}, - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {number_format(G.GAME.round_scores[score].amt)}, colours = {text_colour or G.C.RED},shadow = true, float = true, scale = math.min(0.6, score_number_scale(1.2, G.GAME.round_scores[score].amt))})}}, - }}, - } - elseif G.GAME.round_scores[score] and not score_tab[1] then - score_tab = { - {n=G.UIT.O, config={object = DynaText({string = {number_format(G.GAME.round_scores[score].amt)}, colours = {text_colour or G.C.FILTER},shadow = true, float = true, scale = score_number_scale(0.6, G.GAME.round_scores[score].amt)})}}, - } - end - return {n=G.UIT.R, config={align = "cm", padding = 0.05, r = 0.1, colour = darken(G.C.JOKER_GREY, 0.1), emboss = 0.05, func = check_high_score and 'high_score_alert' or nil, id = score}, nodes={ - {n=score=='defeated_by' and G.UIT.R or G.UIT.C, config={align = "cm", padding = 0.02, minw = label_w, maxw = label_w}, nodes={ - {n=G.UIT.T, config={text = label, scale = label_scale, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=score=='defeated_by' and G.UIT.R or G.UIT.C, config={align = "cr"}, nodes={ - {n=G.UIT.C, config={align = "cm", minh = h, r = 0.1, minw = score=='defeated_by' and label_w or score_w, colour = (score == 'seed' and G.GAME.seeded) and G.C.RED or G.C.BLACK, emboss = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, r = 0.1, minw = score_w}, nodes=score_tab}, - }} - }}, - }} -end - -function create_UIBox_hand_tip(handname) - if not G.GAME.hands[handname].example then return {n=G.UIT.R, config={align = "cm"},nodes = {}} end - local cardarea = CardArea( - 2,2, - 3.5*G.CARD_W, - 0.75*G.CARD_H, - {card_limit = 5, type = 'title', highlight_limit = 0}) - for k, v in ipairs(G.GAME.hands[handname].example) do - local card = Card(0,0, 0.5*G.CARD_W, 0.5*G.CARD_H, G.P_CARDS[v[1]], G.P_CENTERS[v[3] or 'c_base']) - if v[2] then card:juice_up(0.3, 0.2) end - if k == 1 then play_sound('paper1',0.95 + math.random()*0.1, 0.3) end - ease_value(card.T, 'scale',v[2] and 0.25 or -0.15,nil,'REAL',true,0.2) - cardarea:emplace(card) - end - - return {n=G.UIT.R, config={align = "cm", colour = G.C.WHITE, r = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = cardarea}} - }} - }} -end - -function create_UIBox_current_hand_row(handname, simple) - return (G.GAME.hands[handname].visible) and - (not simple and - {n=G.UIT.R, config={align = "cm", padding = 0.05, r = 0.1, colour = darken(G.C.JOKER_GREY, 0.1), emboss = 0.05, hover = true, force_focus = true, on_demand_tooltip = {text = localize(handname, 'poker_hand_descriptions'), filler = {func = create_UIBox_hand_tip, args = handname}}}, nodes={ - {n=G.UIT.C, config={align = "cl", padding = 0, minw = 5}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.01, r = 0.1, colour = G.C.HAND_LEVELS[math.min(7, G.GAME.hands[handname].level)], minw = 1.5, outline = 0.8, outline_colour = G.C.WHITE}, nodes={ - {n=G.UIT.T, config={text = localize('k_level_prefix')..G.GAME.hands[handname].level, scale = 0.5, colour = G.C.UI.TEXT_DARK}} - }}, - {n=G.UIT.C, config={align = "cm", minw = 4.5, maxw = 4.5}, nodes={ - {n=G.UIT.T, config={text = ' '..localize(handname,'poker_hands'), scale = 0.45, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }} - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.05, colour = G.C.BLACK,r = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cr", padding = 0.01, r = 0.1, colour = G.C.CHIPS, minw = 1.1}, nodes={ - {n=G.UIT.T, config={text = number_format(G.GAME.hands[handname].chips, 1000000), scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}, - {n=G.UIT.B, config={w = 0.08, h = 0.01}} - }}, - {n=G.UIT.T, config={text = "X", scale = 0.45, colour = G.C.MULT}}, - {n=G.UIT.C, config={align = "cl", padding = 0.01, r = 0.1, colour = G.C.MULT, minw = 1.1}, nodes={ - {n=G.UIT.B, config={w = 0.08,h = 0.01}}, - {n=G.UIT.T, config={text = number_format(G.GAME.hands[handname].mult, 1000000), scale = 0.45, colour = G.C.UI.TEXT_LIGHT}} - }} - }}, - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = ' #', scale = 0.45, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.05, colour = G.C.L_BLACK,r = 0.1, minw = 0.9}, nodes={ - {n=G.UIT.T, config={text = G.GAME.hands[handname].played, scale = 0.45, colour = G.C.FILTER, shadow = true}}, - }} - }} - or {n=G.UIT.R, config={align = "cm", padding = 0.05, r = 0.1, colour = darken(G.C.JOKER_GREY, 0.1), force_focus = true, emboss = 0.05, hover = true, on_demand_tooltip = {text = localize(handname, 'poker_hand_descriptions'), filler = {func = create_UIBox_hand_tip, args = handname}}, focus_args = {snap_to = (simple and handname == 'Straight Flush')}}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0, minw = 5}, nodes={ - {n=G.UIT.T, config={text = localize(handname,'poker_hands'), scale = 0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }} - }}) - or nil -end - -function create_UIBox_current_hands(simple) - local hands = { - create_UIBox_current_hand_row("Flush Five", simple), - create_UIBox_current_hand_row("Flush House", simple), - create_UIBox_current_hand_row("Five of a Kind", simple), - create_UIBox_current_hand_row("Straight Flush", simple), - create_UIBox_current_hand_row("Four of a Kind", simple), - create_UIBox_current_hand_row("Full House", simple), - create_UIBox_current_hand_row("Flush", simple), - create_UIBox_current_hand_row("Straight", simple), - create_UIBox_current_hand_row("Three of a Kind", simple), - create_UIBox_current_hand_row("Two Pair", simple), - create_UIBox_current_hand_row("Pair", simple), - create_UIBox_current_hand_row("High Card", simple) - } - - local t = {n=G.UIT.ROOT, config={align = "cm", minw = 3, padding = 0.1, r = 0.1, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.04}, nodes= - hands - }, - }} - - return t -end - -function G.UIDEF.deck_info(_show_remaining) - return create_UIBox_generic_options({contents ={create_tabs( - {tabs = _show_remaining and { - { - label = localize('b_remaining'), - chosen = true, - tab_definition_function = G.UIDEF.view_deck, - tab_definition_function_args = true, - }, - { - label = localize('b_full_deck'), - tab_definition_function = G.UIDEF.view_deck - }, - } or { - { - label = localize('b_full_deck'), - chosen = true, - tab_definition_function = G.UIDEF.view_deck - }, - }, - tab_h = 8, - snap_to_nav = true})}}) -end - -function G.UIDEF.run_info() - return create_UIBox_generic_options({contents ={create_tabs( - {tabs = { - { - label = localize('b_poker_hands'), - chosen = true, - tab_definition_function = create_UIBox_current_hands, - }, - { - label = localize('b_blinds'), - tab_definition_function = G.UIDEF.current_blinds, - }, - { - label = localize('b_vouchers'), - tab_definition_function = G.UIDEF.used_vouchers, - }, - G.GAME.stake > 1 and { - label = localize('b_stake'), - tab_definition_function = G.UIDEF.current_stake, - } or nil, - }, - tab_h = 8, - snap_to_nav = true})}}) -end - -function G.UIDEF.current_blinds() - return {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR, padding = 0.2}, nodes={ - G.GAME.round_resets.blind_states['Small'] ~= 'Hide' and {n=G.UIT.C, config={align = "tm", padding = 0.1, outline = 2, r = 0.1, line_emboss = 0.2, outline_colour = G.C.BLACK}, nodes={ - create_UIBox_blind_choice('Small', true) - }} or nil, - G.GAME.round_resets.blind_states['Big'] ~= 'Hide' and {n=G.UIT.C, config={align = "tm", padding = 0.1, outline = 2, r = 0.1, line_emboss = 0.2, outline_colour = G.C.BLACK}, nodes={ - create_UIBox_blind_choice('Big', true) - }} or nil, - G.GAME.round_resets.blind_states['Boss'] ~= 'Hide' and {n=G.UIT.C, config={align = "tm", padding = 0.1, outline = 2, r = 0.1, line_emboss = 0.2, outline_colour = G.C.BLACK}, nodes={ - create_UIBox_blind_choice('Boss', true) - }} or nil - }} -end - -function G.UIDEF.deck_stake_column(_deck_key) - local deck_usage = G.PROFILES[G.SETTINGS.profile].deck_usage[_deck_key] - local stake_col = {} - local valid_option = nil - for i = #G.P_CENTER_POOLS['Stake'], 1, -1 do - local _wins = deck_usage and deck_usage.wins[i] or 0 - if (deck_usage and deck_usage.wins[i-1]) or i == 1 or G.PROFILES[G.SETTINGS.profile].all_unlocked then valid_option = true end - stake_col[#stake_col+1] = {n=G.UIT.R, config={id = i, align = "cm", colour = _wins > 0 and G.C.GREY or G.C.CLEAR, outline = 0, outline_colour = G.C.WHITE, r = 0.1, minh = 0.25, minw = valid_option and 0.45 or 0.25, func = 'RUN_SETUP_check_back_stake_highlight'}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = valid_option and 0.17 or 0.13, minw = valid_option and 0.37 or 0.13, colour = _wins > 0 and get_stake_col(i) or G.C.UI.TRANSPARENT_LIGHT, r = 0.1},nodes={}} - }} - if i > 1 then stake_col[#stake_col+1] = {n=G.UIT.R, config={align = "cm", minh = 0.1, minw = 0.04},nodes={}} end - end - return {n=G.UIT.ROOT, config={align = 'cm', colour = G.C.CLEAR}, nodes =stake_col} -end - -function G.UIDEF.current_stake() - local other_col = nil - if G.GAME.stake > 2 then - local stake_desc_rows = {{n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = localize('k_also_applied'), scale = 0.4, colour = G.C.WHITE}} - }} - } - if false then - for i = G.GAME.stake-1, 2, -1 do - local _stake_desc = {} - local _stake_center = G.P_CENTER_POOLS.Stake[i] - localize{type = 'descriptions', key = _stake_center.key, set = _stake_center.set, nodes = _stake_desc} - local _full_desc = {} - for k, v in ipairs(_stake_desc) do - _full_desc[#_full_desc+1] = {n=G.UIT.R, config={align = "cm"}, nodes=v} - end - _full_desc[#_full_desc] = nil - stake_desc_rows[#stake_desc_rows+1] = {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = 'cm'}, nodes ={{n=G.UIT.C, config={align = "cm", colour = get_stake_col(i), r = 0.1, minh = 0.35, minw = 0.35, emboss = 0.05}, nodes={}}, {n=G.UIT.B, config={w=0.1,h=0.1}}}}, - {n=G.UIT.C, config={align = "cm", padding = 0.03, colour = G.C.WHITE, r = 0.1, minh = 0.7, minw = 4.8}, nodes=_full_desc}, - }} - end - end SMODS.applied_stakes_UI(G.GAME.stake, stake_desc_rows) - other_col = {n=G.UIT.R, config={align = "cm", padding = 0.05, r = 0.1, colour = G.C.L_BLACK}, nodes=stake_desc_rows} - end - - local stake_sprite = get_stake_sprite(G.GAME.stake, 0.8) - local _stake_desc = {} - local _stake_center = G.P_CENTER_POOLS.Stake[G.GAME.stake] - localize{type = 'descriptions', key = _stake_center.key, set = _stake_center.set, nodes = _stake_desc} - local _full_desc = {} - for k, v in ipairs(_stake_desc) do - _full_desc[#_full_desc+1] = {n=G.UIT.R, config={align = "cm"}, nodes=v} - end - _full_desc[#_full_desc] = nil - local current_col = {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1, minw = 4}, nodes={ - {n=G.UIT.O, config={colour = G.C.BLUE, object = stake_sprite, hover = true, can_collide = false}}, - {n=G.UIT.T, config={text = localize{type = 'name_text', key = G.P_CENTER_POOLS.Stake[G.GAME.stake].key, set = 'Stake'}, scale = 0.45, colour = G.C.WHITE}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05, colour = get_stake_col(G.GAME.stake), r = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05, colour = G.C.WHITE, r = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.03, minh = 0.7, minw = 3.8}, nodes=_full_desc} - }} - }} - }} - - return {n=G.UIT.ROOT, config={align = "cm", colour = G.C.BLACK, r = 0.1, padding = 0.1}, nodes={ - current_col,other_col - }} -end - -function G.UIDEF.view_deck(unplayed_only) - local deck_tables = {} - remove_nils(G.playing_cards) - G.VIEWING_DECK = true - table.sort(G.playing_cards, function (a, b) return a:get_nominal('suit') > b:get_nominal('suit') end ) - local SUITS = { - Spades = {}, - Hearts = {}, - Clubs = {}, - Diamonds = {}, - } - local suit_map = {'Spades', 'Hearts', 'Clubs', 'Diamonds'} - local SUITS_SORTED = Cartomancer.tablecopy(SUITS) - for k, v in ipairs(G.playing_cards) do - local greyed - if unplayed_only and not ((v.area and v.area == G.deck) or v.ability.wheel_flipped) then - greyed = true - end - local card_string = v:cart_to_string() - if greyed then - card_string = card_string .. "Greyed" - end - if greyed and Cartomancer.SETTINGS.deck_view_hide_drawn_cards then - -- Ignore this card. - elseif not SUITS[v.base.suit][card_string] then - table.insert(SUITS_SORTED[v.base.suit], card_string) - - local _scale = 0.7 - local copy = copy_card(v, nil, _scale) - - copy.greyed = greyed - copy.stacked_quantity = 1 - - SUITS[v.base.suit][card_string] = copy - else - local stacked_card = SUITS[v.base.suit][card_string] - stacked_card.stacked_quantity = stacked_card.stacked_quantity + 1 - end - end - for j = 1, 4 do - if SUITS_SORTED[suit_map[j]][1] then - local view_deck = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - 6.5*G.CARD_W, - 0.6*G.CARD_H, - {card_limit = #SUITS_SORTED[suit_map[j]], type = 'title', view_deck = true, highlight_limit = 0, card_w = G.CARD_W*0.7, draw_layers = {'card'}}) - table.insert(deck_tables, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={object = view_deck}} - }} - ) - - for i = 1, #SUITS_SORTED[suit_map[j]] do - local card_string = SUITS_SORTED[suit_map[j]][i] - local card = SUITS[suit_map[j]][card_string] - - card.T.x = view_deck.T.x + view_deck.T.w/2 - card.T.y = view_deck.T.y - card:create_quantity_display() - - card:hard_set_T() - view_deck:emplace(card) - - end - - end - end - - local flip_col = G.C.WHITE - - local suit_tallies = {['Spades'] = 0, ['Hearts'] = 0, ['Clubs'] = 0, ['Diamonds'] = 0} - local mod_suit_tallies = {['Spades'] = 0, ['Hearts'] = 0, ['Clubs'] = 0, ['Diamonds'] = 0} - local rank_tallies = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - local mod_rank_tallies = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - local rank_name_mapping = {2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A'} - local face_tally = 0 - local mod_face_tally = 0 - local num_tally = 0 - local mod_num_tally = 0 - local ace_tally = 0 - local mod_ace_tally = 0 - local wheel_flipped = 0 - - for k, v in ipairs(G.playing_cards) do - if v.ability.name ~= 'Stone Card' and (not unplayed_only or ((v.area and v.area == G.deck) or v.ability.wheel_flipped)) then - if v.ability.wheel_flipped and unplayed_only then wheel_flipped = wheel_flipped + 1 end - --For the suits - suit_tallies[v.base.suit] = (suit_tallies[v.base.suit] or 0) + 1 - mod_suit_tallies['Spades'] = (mod_suit_tallies['Spades'] or 0) + (v:is_suit('Spades') and 1 or 0) - mod_suit_tallies['Hearts'] = (mod_suit_tallies['Hearts'] or 0) + (v:is_suit('Hearts') and 1 or 0) - mod_suit_tallies['Clubs'] = (mod_suit_tallies['Clubs'] or 0) + (v:is_suit('Clubs') and 1 or 0) - mod_suit_tallies['Diamonds'] = (mod_suit_tallies['Diamonds'] or 0) + (v:is_suit('Diamonds') and 1 or 0) - - --for face cards/numbered cards/aces - local card_id = v:get_id() - face_tally = face_tally + ((card_id ==11 or card_id ==12 or card_id ==13) and 1 or 0) - mod_face_tally = mod_face_tally + (v:is_face() and 1 or 0) - if card_id > 1 and card_id < 11 then - num_tally = num_tally + 1 - if not v.debuff then mod_num_tally = mod_num_tally + 1 end - end - if card_id == 14 then - ace_tally = ace_tally + 1 - if not v.debuff then mod_ace_tally = mod_ace_tally + 1 end - end - - --ranks - rank_tallies[card_id - 1] = rank_tallies[card_id - 1] + 1 - if not v.debuff then mod_rank_tallies[card_id - 1] = mod_rank_tallies[card_id - 1] + 1 end - end - end - - local modded = (face_tally ~= mod_face_tally) or - (mod_suit_tallies['Spades'] ~= suit_tallies['Spades']) or - (mod_suit_tallies['Hearts'] ~= suit_tallies['Hearts']) or - (mod_suit_tallies['Clubs'] ~= suit_tallies['Clubs']) or - (mod_suit_tallies['Diamonds'] ~= suit_tallies['Diamonds']) - - if wheel_flipped > 0 then flip_col = mix_colours(G.C.FILTER, G.C.WHITE,0.7) end - - local rank_cols = {} - for i = 13, 1, -1 do - local mod_delta = mod_rank_tallies[i] ~= rank_tallies[i] - rank_cols[#rank_cols+1] = {n=G.UIT.R, config={align = "cm", padding = 0.07}, nodes={ - {n=G.UIT.C, config={align = "cm", r = 0.1, padding = 0.04, emboss = 0.04, minw = 0.5, colour = G.C.L_BLACK}, nodes={ - {n=G.UIT.T, config={text = rank_name_mapping[i],colour = G.C.JOKER_GREY, scale = 0.35, shadow = true}}, - }}, - {n=G.UIT.C, config={align = "cr", minw = 0.4}, nodes={ - mod_delta and {n=G.UIT.O, config={object = DynaText({string = {{string = ''..rank_tallies[i], colour = flip_col},{string =''..mod_rank_tallies[i], colour = G.C.BLUE}}, colours = {G.C.RED}, scale = 0.4, y_offset = -2, silent = true, shadow = true, pop_in_rate = 10, pop_delay = 4})}} or - {n=G.UIT.T, config={text = rank_tallies[i] or 'NIL',colour = flip_col, scale = 0.45, shadow = true}}, - }} - }} - end - - - local t = - {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={}}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = 1.5, minh = 2, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", r = 0.1, colour = G.C.L_BLACK, emboss = 0.05, padding = 0.15}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = G.GAME.selected_back.loc_name, colours = {G.C.WHITE}, bump = true, rotate = true, shadow = true, scale = 0.6 - string.len(G.GAME.selected_back.loc_name)*0.01})}}, - }}, - {n=G.UIT.R, config={align = "cm", r = 0.1, padding = 0.1, minw = 2.5, minh = 1.3, colour = G.C.WHITE, emboss = 0.05}, nodes={ - {n=G.UIT.O, config={object = UIBox{ - definition = G.GAME.selected_back:generate_UI(nil,0.7, 0.5, G.GAME.challenge), - config = {offset = {x=0,y=0}} - }}} - }} - }}, - {n=G.UIT.R, config={align = "cm", r = 0.1, outline_colour = G.C.L_BLACK, line_emboss = 0.05, outline = 1.5}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.05, padding = 0.07}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {{string = localize('k_base_cards'), colour = G.C.RED}, modded and {string = localize('k_effective'), colour = G.C.BLUE} or nil}, colours = {G.C.RED}, silent = true,scale = 0.4,pop_in_rate = 10, pop_delay = 4})}} - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.05, padding = 0.1}, nodes={ - tally_sprite({x=1,y=0},{{string = ''..ace_tally, colour = flip_col},{string =''..mod_ace_tally, colour = G.C.BLUE}}, {localize('k_aces')}),--Aces - tally_sprite({x=2,y=0},{{string = ''..face_tally, colour = flip_col},{string =''..mod_face_tally, colour = G.C.BLUE}}, {localize('k_face_cards')}),--Face - tally_sprite({x=3,y=0},{{string = ''..num_tally, colour = flip_col},{string =''..mod_num_tally, colour = G.C.BLUE}}, {localize('k_numbered_cards')}),--Numbers - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.05, padding = 0.1}, nodes={ - tally_sprite({x=3,y=1}, {{string = ''..suit_tallies['Spades'], colour = flip_col},{string =''..mod_suit_tallies['Spades'], colour = G.C.BLUE}}, {localize('Spades', 'suits_plural')}), - tally_sprite({x=0,y=1}, {{string = ''..suit_tallies['Hearts'], colour = flip_col},{string =''..mod_suit_tallies['Hearts'], colour = G.C.BLUE}}, {localize('Hearts', 'suits_plural')}), - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.05, padding = 0.1}, nodes={ - tally_sprite({x=2,y=1}, {{string = ''..suit_tallies['Clubs'], colour = flip_col},{string =''..mod_suit_tallies['Clubs'], colour = G.C.BLUE}}, {localize('Clubs', 'suits_plural')}), - tally_sprite({x=1,y=1}, {{string = ''..suit_tallies['Diamonds'], colour = flip_col},{string =''..mod_suit_tallies['Diamonds'], colour = G.C.BLUE}}, {localize('Diamonds', 'suits_plural')}), - }}, - }} - }}, - {n=G.UIT.C, config={align = "cm"}, nodes=rank_cols}, - {n=G.UIT.B, config={w = 0.1, h = 0.1}}, - }}, - {n=G.UIT.B, config={w = 0.2, h = 0.1}}, - {n=G.UIT.C, config={align = "cm", padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables} - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.8, padding = 0.05}, nodes={ - not unplayed_only and Cartomancer.add_unique_count() or nil, - modded and {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={padding = 0.3, r = 0.1, colour = mix_colours(G.C.BLUE, G.C.WHITE,0.7)}, nodes = {}}, - {n=G.UIT.T, config={text =' '..localize('ph_deck_preview_effective'),colour = G.C.WHITE, scale =0.3}}, - }} or nil, - wheel_flipped > 0 and {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={padding = 0.3, r = 0.1, colour = flip_col}, nodes = {}}, - {n=G.UIT.T, config={text =' '..(wheel_flipped > 1 and - localize{type = 'variable', key = 'deck_preview_wheel_plural', vars = {wheel_flipped}} or - localize{type = 'variable', key = 'deck_preview_wheel_singular', vars = {wheel_flipped}}),colour = G.C.WHITE, scale =0.3}}, - }} or nil, - }} - }} - return t -end - -function tally_sprite(pos, value, tooltip, suit) - local text_colour = G.C.BLACK - if type(value) == "table" and value[1].string==value[2].string then - text_colour = value[1].colour or G.C.WHITE - value = value[1].string - end - local t_s = Sprite(0,0,0.5,0.5, G.ASSET_ATLAS[suit and SMODS.Suits[suit][G.SETTINGS.colourblind_option and "hc_ui_atlas" or "lc_ui_atlas"]] or G.ASSET_ATLAS[("ui_"..(G.SETTINGS.colourblind_option and "2" or "1"))], {x=pos.x or 0, y=pos.y or 0}) - t_s.states.drag.can = false - t_s.states.hover.can = false - t_s.states.collide.can = false - return - {n=G.UIT.C, config={align = "cm", padding = 0.07,force_focus = true, focus_args = {type = 'tally_sprite'}, tooltip = {text = tooltip}}, nodes={ - {n=G.UIT.R, config={align = "cm", r = 0.1, padding = 0.04, emboss = 0.05, colour = G.C.JOKER_GREY}, nodes={ - {n=G.UIT.O, config={w=0.5,h=0.5 ,can_collide = false, object = t_s, tooltip = {text = tooltip}}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - type(value) == "table" and {n=G.UIT.O, config={object = DynaText({string = value, colours = {G.C.RED}, scale = 0.4, silent = true, shadow = true, pop_in_rate = 10, pop_delay = 4})}} or - {n=G.UIT.T, config={text = value or 'NIL',colour = text_colour, scale = 0.4, shadow = true}}, - }}, - }} -end - -function G.UIDEF.used_vouchers() - - local silent = false - local keys_used = {} - local area_count = 0 - local voucher_areas = {} - local voucher_tables = {} - local voucher_table_rows = {} - for k, v in ipairs(G.P_CENTER_POOLS["Voucher"]) do - local key = 1 + math.floor((k-0.1)/2) - keys_used[key] = keys_used[key] or {} - if G.GAME.used_vouchers[v.key] then - if not G.GAME.cry_owned_vouchers[v.key] then - G.GAME.cry_owned_vouchers[v.key] = G.GAME.used_vouchers[v.key] - end - end - if G.GAME.cry_owned_vouchers[v.key] then - keys_used[key][#keys_used[key]+1] = v - end - end - for k, v in ipairs(keys_used) do - if next(v) then - area_count = area_count + 1 - end - end - for k, v in ipairs(keys_used) do - if next(v) then - if #voucher_areas == 5 or #voucher_areas == 10 then - table.insert(voucher_table_rows, - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes=voucher_tables} - ) - voucher_tables = {} - end - voucher_areas[#voucher_areas + 1] = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - (#v == 1 and 1 or 1.33)*G.CARD_W, - (area_count >=10 and 0.75 or 1.07)*G.CARD_H, - {card_limit = 2, type = 'voucher', highlight_limit = 0}) - for kk, vv in ipairs(v) do - local center = G.P_CENTERS[vv.key] - local card = Card(voucher_areas[#voucher_areas].T.x + voucher_areas[#voucher_areas].T.w/2, voucher_areas[#voucher_areas].T.y, G.CARD_W, G.CARD_H, nil, center, {bypass_discovery_center=true,bypass_discovery_ui=true,bypass_lock=true}) - card.ability.order = vv.order - card:start_materialize(nil, silent) - silent = true - if not G.GAME.voucher_edition_index then G.GAME.voucher_edition_index = {} end - if G.GAME.voucher_edition_index[card.ability.name] then -- i just made it a function so i can look at it less - local edition = cry_edition_to_table(G.GAME.voucher_edition_index[card.ability.name]) - if edition then - card:set_edition(edition, true, true) - end - end - - if G.GAME.voucher_sticker_index.eternal[card.ability.name] then - card:set_eternal(true) - card.ability.eternal = true - end - if G.GAME.voucher_sticker_index.perishable[card.ability.name] then - card:set_perishable(true) - card.ability.perish_tally = G.GAME.voucher_sticker_index.perishable[card.ability.name] - card.ability.perishable = true - if G.GAME.voucher_sticker_index.perishable[card.ability.name] == 0 then - card.debuff = true - end - end - if G.GAME.voucher_sticker_index.rental[card.ability.name] then - card:set_rental(true) - card.ability.rental = true - end - if G.GAME.voucher_sticker_index.pinned[card.ability.name] then - card.pinned = true - end - if G.GAME.voucher_sticker_index.banana[card.ability.name] then - card.ability.banana = true - end - card.ability.extra = G.GAME.cry_voucher_centers[card.config.center_key].config.extra - if card.ability.extra_disp then card.ability.extra_disp = G.GAME.cry_voucher_centers[card.config.center_key].config.extra_disp end - voucher_areas[#voucher_areas]:emplace(card) - end - table.insert(voucher_tables, - {n=G.UIT.C, config={align = "cm", padding = 0, no_fill = true}, nodes={ - {n=G.UIT.O, config={object = voucher_areas[#voucher_areas]}} - }} - ) - end - end - table.insert(voucher_table_rows, - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes=voucher_tables} - ) - - - local t = silent and {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('ph_vouchers_redeemed')}, colours = {G.C.UI.TEXT_LIGHT}, bump = true, scale = 0.6})}} - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.5}, nodes={ - }}, - {n=G.UIT.R, config={align = "cm", colour = G.C.BLACK, r = 1, padding = 0.15, emboss = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes=voucher_table_rows}, - }} - }} or - {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('ph_no_vouchers')}, colours = {G.C.UI.TEXT_LIGHT}, bump = true, scale = 0.6})}} - }} - return t -end - - - -function create_UIBox_your_collection() - set_discover_tallies() - G.E_MANAGER:add_event(Event({ - blockable = false, - func = function() - G.REFRESH_ALERTS = true - return true - end - })) - local consumable_nodes = {} - if #SMODS.ConsumableType.ctype_buffer <= 3 then - for _, key in ipairs(SMODS.ConsumableType.ctype_buffer) do - local id = 'your_collection_'..key:lower()..'s' - consumable_nodes[#consumable_nodes+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = G.DISCOVER_TALLIES[key:lower()..'s'], minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) - end - else - consumable_nodes[#consumable_nodes+1] = UIBox_button({ button = 'your_collection_consumables', label = {localize('b_stat_consumables'), localize{ type = 'variable', key = 'c_types', vars = {#SMODS.ConsumableType.ctype_buffer} } }, count = G.DISCOVER_TALLIES['consumeables'], minw = 4, minh = 4, id = 'your_collection_consumables', colour = G.C.FILTER }) - end - local t = create_UIBox_generic_options({ back_func = G.STAGE == G.STAGES.RUN and 'options' or 'exit_overlay_menu', contents = { - {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes={ - UIBox_button({button = 'your_collection_jokers', label = {localize('b_jokers')}, count = G.DISCOVER_TALLIES.jokers, minw = 5, minh = 1.7, scale = 0.6, id = 'your_collection_jokers'}), - UIBox_button({button = 'your_collection_decks', label = {localize('b_decks')}, count = G.DISCOVER_TALLIES.backs, minw = 5}), - UIBox_button({button = 'your_collection_vouchers', label = {localize('b_vouchers')}, count = G.DISCOVER_TALLIES.vouchers, minw = 5, id = 'your_collection_vouchers'}), - {n=G.UIT.R, config={align = "cm", padding = 0.1, r=0.2, colour = G.C.BLACK}, nodes={ - {n=G.UIT.C, config={align = "cm", maxh=2.9}, nodes={ - {n=G.UIT.T, config={text = localize('k_cap_consumables'), scale = 0.45, colour = G.C.L_BLACK, vert = true, maxh=2.2}}, - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes = consumable_nodes} - }}, - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes={ - UIBox_button({button = 'your_collection_enhancements', label = {localize('b_enhanced_cards')}, minw = 5}), - UIBox_button({button = 'your_collection_seals', label = {localize('b_seals')}, minw = 5, id = 'your_collection_seals'}), - UIBox_button({button = 'your_collection_editions', label = {localize('b_editions')}, count = G.DISCOVER_TALLIES.editions, minw = 5, id = 'your_collection_editions'}), - UIBox_button({button = 'your_collection_boosters', label = {localize('b_booster_packs')}, count = G.DISCOVER_TALLIES.boosters, minw = 5, id = 'your_collection_boosters'}), - UIBox_button({button = 'your_collection_tags', label = {localize('b_tags')}, count = G.DISCOVER_TALLIES.tags, minw = 5, id = 'your_collection_tags'}), - UIBox_button({button = 'your_collection_blinds', label = {localize('b_blinds')}, count = G.DISCOVER_TALLIES.blinds, minw = 5, minh = 2.0, id = 'your_collection_blinds', focus_args = {snap_to = true}}),UIBox_button({button = 'your_collection_other_gameobjects', label = {localize('k_other')}, minw = 5, id = 'your_collection_other_gameobjects', focus_args = {snap_to = true}}), - }}, - - }}) - return t -end - -function create_UIBox_your_collection_jokers() - local deck_tables = {} - - G.your_collection = {} - for j = 1, 3 do - G.your_collection[j] = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - 5*G.CARD_W, - 0.95*G.CARD_H, - {card_limit = 5, type = 'title', highlight_limit = 0, collection = true}) - table.insert(deck_tables, - {n=G.UIT.R, config={align = "cm", padding = 0.07, no_fill = true}, nodes={ - {n=G.UIT.O, config={object = G.your_collection[j]}} - }} - ) - end - - local joker_options = {} - for i = 1, math.ceil(#G.P_CENTER_POOLS.Joker/(5*#G.your_collection)) do - table.insert(joker_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#G.P_CENTER_POOLS.Joker/(5*#G.your_collection)))) - end - - for i = 1, 5 do - for j = 1, #G.your_collection do - local center = G.P_CENTER_POOLS["Joker"][i+(j-1)*5] - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W, G.CARD_H, nil, center) - card.sticker = get_joker_win_sticker(center) - G.your_collection[j]:emplace(card) - end - end - - INIT_COLLECTION_CARD_ALERTS() - - local t = create_UIBox_generic_options({ back_func = 'your_collection', contents = { - {n=G.UIT.R, config={align = "cm", r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - create_option_cycle({options = joker_options, w = 4.5, cycle_shoulders = true, opt_callback = 'your_collection_joker_page', current_option = 1, colour = G.C.RED, no_pips = true, focus_args = {snap_to = true, nav = 'wide'}}) - }} - }}) - return t -end - -function create_UIBox_your_collection_tarots() - local deck_tables = {} - - G.your_collection = {} - for j = 1, 2 do - G.your_collection[j] = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - (4.25+j)*G.CARD_W, - 1*G.CARD_H, - {card_limit = 4 + j, type = 'title', highlight_limit = 0, collection = true}) - table.insert(deck_tables, - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes={ - {n=G.UIT.O, config={object = G.your_collection[j]}} - }} - ) - end - - local tarot_options = {} - for i = 1, math.floor(#G.P_CENTER_POOLS.Tarot/11) do - table.insert(tarot_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.floor(#G.P_CENTER_POOLS.Tarot/11))) - end - - for j = 1, #G.your_collection do - for i = 1, 4+j do - local center = G.P_CENTER_POOLS["Tarot"][i+(j-1)*(5)] - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W, G.CARD_H, nil, center) - card:start_materialize(nil, i>1 or j>1) - G.your_collection[j]:emplace(card) - end - end - - INIT_COLLECTION_CARD_ALERTS() - - local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = { - {n=G.UIT.R, config={align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - create_option_cycle({options = tarot_options, w = 4.5, cycle_shoulders = true, opt_callback = 'your_collection_tarot_page', focus_args = {snap_to = true, nav = 'wide'},current_option = 1, colour = G.C.RED, no_pips = true}) - }} - }}) - return t -end - -function create_UIBox_your_collection_boosters() - local deck_tables = {} - - G.your_collection = {} - for j = 1, 2 do - G.your_collection[j] = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - (5.25)*G.CARD_W, - 1.3*G.CARD_H, - {card_limit = 4, type = 'title', highlight_limit = 0, collection = true}) - table.insert(deck_tables, - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes={ - {n=G.UIT.O, config={object = G.your_collection[j]}} - }} - ) - end - - local booster_options = {} - for i = 1, math.ceil(#G.P_CENTER_POOLS.Booster/8) do - table.insert(booster_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#G.P_CENTER_POOLS.Booster/8))) - end - - for j = 1, #G.your_collection do - for i = 1, 4 do - local center = G.P_CENTER_POOLS["Booster"][i+(j-1)*4] - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W*1.27, G.CARD_H*1.27, nil, center) - card:start_materialize(nil, i>1 or j>1) - G.your_collection[j]:emplace(card) - end - end - - INIT_COLLECTION_CARD_ALERTS() - - local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = { - {n=G.UIT.R, config={align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - create_option_cycle({options = booster_options, w = 4.5, cycle_shoulders = true, opt_callback = 'your_collection_booster_page', focus_args = {snap_to = true, nav = 'wide'},current_option = 1, colour = G.C.RED, no_pips = true}) - }} - }}) - return t -end - -function create_UIBox_your_collection_planets() - local deck_tables = {} - - G.your_collection = {} - for j = 1, 2 do - G.your_collection[j] = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - (6.25)*G.CARD_W, - 1*G.CARD_H, - {card_limit = 6, type = 'title', highlight_limit = 0, collection = true}) - table.insert(deck_tables, - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes={ - {n=G.UIT.O, config={object = G.your_collection[j]}} - }} - ) - end - - for j = 1, #G.your_collection do - for i = 1, 6 do - local center = G.P_CENTER_POOLS["Planet"][i+(j-1)*(6)] - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W, G.CARD_H, nil, center) - card:start_materialize(nil, i>1 or j>1) - G.your_collection[j]:emplace(card) - end - end - - INIT_COLLECTION_CARD_ALERTS() - - local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = { - {n=G.UIT.R, config={align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables}, - {n=G.UIT.R, config={align = "cm", padding = 0.7}, nodes={}}, - }}) - return t -end - -function create_UIBox_your_collection_spectrals() - local deck_tables = {} - - G.your_collection = {} - for j = 1, 2 do - G.your_collection[j] = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - (3.25+j)*G.CARD_W, - 1*G.CARD_H, - {card_limit = 3+j, type = 'title', highlight_limit = 0, collection = true}) - table.insert(deck_tables, - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes={ - {n=G.UIT.O, config={object = G.your_collection[j]}} - }} - ) - end - - for j = 1, #G.your_collection do - for i = 1, 3+j do - local center = G.P_CENTER_POOLS["Spectral"][i+(j-1)*3 + j - 1] - - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W, G.CARD_H, nil, center) - card:start_materialize(nil, i>1 or j>1) - G.your_collection[j]:emplace(card) - end - end - - local spectral_options = {} - for i = 1, math.floor(#G.P_CENTER_POOLS.Tarot/9) do - table.insert(spectral_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.floor(#G.P_CENTER_POOLS.Spectral/9))) - end - - INIT_COLLECTION_CARD_ALERTS() - - local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = { - {n=G.UIT.R, config={align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - create_option_cycle({options = spectral_options, w = 4.5, cycle_shoulders = true, opt_callback = 'your_collection_spectral_page', focus_args = {snap_to = true, nav = 'wide'},current_option = 1, colour = G.C.RED, no_pips = true}) - }}, - }}) - return t -end - -function create_UIBox_your_collection_vouchers(exit) - local deck_tables = {} - - G.your_collection = {} - for j = 1, 2 do - G.your_collection[j] = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - 4.25*G.CARD_W, - 1*G.CARD_H, - {card_limit = 4, type = 'voucher', highlight_limit = 0, collection = true}) - table.insert(deck_tables, - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes={ - {n=G.UIT.O, config={object = G.your_collection[j]}} - }} - ) - end - - local voucher_options = {} - for i = 1, math.ceil(#G.P_CENTER_POOLS.Voucher/(4*#G.your_collection)) do - table.insert(voucher_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#G.P_CENTER_POOLS.Voucher/(4*#G.your_collection)))) - end - - for i = 1, 4 do - for j = 1, #G.your_collection do - local center = G.P_CENTER_POOLS["Voucher"][i+(j-1)*4] - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W, G.CARD_H, nil, center) - card.ability.order = i+(j-1)*4 - card:start_materialize(nil, i>1 or j>1) - G.your_collection[j]:emplace(card) - end - end - - INIT_COLLECTION_CARD_ALERTS() - - local t = create_UIBox_generic_options({ back_func = exit or 'your_collection', contents = { - {n=G.UIT.R, config={align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - create_option_cycle({options = voucher_options, w = 4.5, cycle_shoulders = true, opt_callback = 'your_collection_voucher_page', focus_args = {snap_to = true, nav = 'wide'}, current_option = 1, colour = G.C.RED, no_pips = true}) - }} - }}) - return t -end - -function create_UIBox_your_collection_seals(exit) - local deck_tables = {} - - G.your_collection = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - 4.25*G.CARD_W, - 1.03*G.CARD_H, - {card_limit = 4, type = 'title', highlight_limit = 0, collection = true}) - table.insert(deck_tables, - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes={ - {n=G.UIT.O, config={object = G.your_collection}} - }} - ) - - for k, v in ipairs(G.P_CENTER_POOLS['Seal']) do - local center = G.P_CENTERS.c_base - local card = Card(G.your_collection.T.x + G.your_collection.T.w/2, G.your_collection.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, center) - card:set_seal(v.key, true) - G.your_collection:emplace(card) - end - - local t = create_UIBox_generic_options({ infotip = localize('ml_edition_seal_enhancement_explanation'), back_func = exit or 'your_collection', snap_back = true, contents = { - {n=G.UIT.R, config={align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables}, - }}) - return t -end - -function create_UIBox_your_collection_enhancements(exit) - local deck_tables = {} - - G.your_collection = {} - for j = 1, 2 do - G.your_collection[j] = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - 4.25*G.CARD_W, - 1.03*G.CARD_H, - {card_limit = 4, type = 'title', highlight_limit = 0, collection = true}) - table.insert(deck_tables, - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes={ - {n=G.UIT.O, config={object = G.your_collection[j]}} - }} - ) - end - - for i = 1, 4 do - for j = 1, #G.your_collection do - local center = G.P_CENTER_POOLS["Enhanced"][i+(j-1)*4] - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, center) - G.your_collection[j]:emplace(card) - end - end - - local t = create_UIBox_generic_options({ infotip = localize('ml_edition_seal_enhancement_explanation'), back_func = exit or 'your_collection', snap_back = true, contents = { - {n=G.UIT.R, config={align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables}, - }}) - return t -end - -function create_UIBox_your_collection_editions() - G.your_collection = {} - G.your_collection[1] = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - 5.3*G.CARD_W, - 1.03*G.CARD_H, - {card_limit = 5, type = 'title', highlight_limit = 0, collection = true}) - local deck_tables = - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes={ - {n=G.UIT.O, config={object = G.your_collection[1]}} - }} - - local editions = {'base', 'foil','holo','polychrome','negative'} - - for i = 1, 5 do - local card = Card(G.your_collection[1].T.x + G.your_collection[1].T.w/2, G.your_collection[1].T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS['e_'..editions[i]]) - card:start_materialize() - if G.P_CENTERS['e_'..editions[i]].discovered then card:set_edition({[editions[i]] = true}, true, true) end - G.your_collection[1]:emplace(card) - end - - INIT_COLLECTION_CARD_ALERTS() - - local t = create_UIBox_generic_options({ infotip = localize('ml_edition_seal_enhancement_explanation'), back_func = 'your_collection', snap_back = true, contents = { - {n=G.UIT.R, config={align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes={deck_tables}}, - }}) - return t -end - -function create_UIBox_your_collection_decks() - local deck_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Back) - G.GAME.viewed_back = Back(G.ACTIVE_MOD_UI and deck_pool[1] or G.P_CENTERS.b_red) - - local area = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - 1.2*G.CARD_W, - 1.2*G.CARD_H, - {card_limit = 52, type = 'deck', highlight_limit = 0}) - - for i = 1, 52 do - local card = Card(G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, G.CARD_W*1.2, G.CARD_H*1.2, pseudorandom_element(G.P_CARDS), G.P_CENTERS.c_base, {playing_card = i, viewed_back = true}) - card.sprite_facing = 'back' - card.facing = 'back' - area:emplace(card) - if i == 52 then G.sticker_card = card; card.sticker = get_deck_win_sticker(G.GAME.viewed_back.effect.center) end - end - - local ordered_names = {} - for k, v in ipairs(deck_pool) do - ordered_names[#ordered_names+1] = v.key - end - - local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = { - create_option_cycle({options = ordered_names, opt_callback = 'change_viewed_back', current_option = 1, colour = G.C.RED, w = 4.5, focus_args = {snap_to = true}, mid = - {n=G.UIT.R, config={align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.2, colour = G.C.BLACK, r = 0.2}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={object = area}} - }}, - {n=G.UIT.C, config={align = "tm", minw = 3.7, minh = 2.1, r = 0.1, colour = G.C.L_BLACK, padding = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", emboss = 0.1, r = 0.1, minw = 4, maxw = 4, minh = 0.6}, nodes={ - {n=G.UIT.O, config={id = nil, func = 'RUN_SETUP_check_back_name', object = Moveable()}}, - }}, - {n=G.UIT.R, config={align = "cm", colour = G.C.WHITE, emboss = 0.1, minh = 2.2, r = 0.1}, nodes={ - {n=G.UIT.O, config={id = G.GAME.viewed_back.name, func = 'RUN_SETUP_check_back', object = UIBox{definition = G.GAME.viewed_back:generate_UI(), config = {offset = {x=0,y=0}}}}} - }} - }}, - }}, - }}}), - }}) - return t -end - -function create_UIBox_your_collection_tags() - local tag_matrix = {} - local counter = 0 - local tag_tab = {} - local tag_pool = {} - if G.ACTIVE_MOD_UI then - for k, v in pairs(G.P_TAGS) do - if v.mod and G.ACTIVE_MOD_UI.id == v.mod.id then tag_pool[k] = v end - end - else - tag_pool = G.P_TAGS - end - for k, v in pairs(tag_pool) do - counter = counter + 1 - tag_tab[#tag_tab+1] = v - end - for i = 1, math.ceil(counter / 6) do - table.insert(tag_matrix, {}) - end - - table.sort(tag_tab, function (a, b) return a.order < b.order end) - - local tags_to_be_alerted = {} - for k, v in ipairs(tag_tab) do - local discovered = v.discovered - local temp_tag = Tag(v.key, true) - if not v.discovered then temp_tag.hide_ability = true end - local temp_tag_ui, temp_tag_sprite = temp_tag:generate_UI() - tag_matrix[math.ceil((k-1)/6+0.001)][1+((k-1)%6)] = {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={ - temp_tag_ui, - }} - if discovered and not v.alerted then - tags_to_be_alerted[#tags_to_be_alerted+1] = temp_tag_sprite - end - end - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - for _, v in ipairs(tags_to_be_alerted) do - v.children.alert = UIBox{ - definition = create_UIBox_card_alert(), - config = { align="tri", offset = {x = 0.1, y = 0.1}, parent = v} - } - v.children.alert.states.collide.can = false - end - return true - end) - })) - - - local table_nodes = {} - for i = 1, math.ceil(counter / 6) do - table.insert(table_nodes, {n=G.UIT.R, config={align = "cm"}, nodes=tag_matrix[i]}) - end local t = create_UIBox_generic_options({ back_func = 'your_collection', contents = { - {n=G.UIT.C, config={align = "cm", r = 0.1, colour = G.C.BLACK, padding = 0.1, emboss = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes=table_nodes} - }} - }} - }}) - return t -end - -function create_UIBox_your_collection_blinds(exit) - local blind_matrix = { - {},{},{}, {}, {}, {} - } - local blind_tab = {} - for k, v in pairs(G.P_BLINDS) do - blind_tab[#blind_tab+1] = v - end - - table.sort(blind_tab, function(a, b) return a.order + (a.boss and a.boss.showdown and 1000 or 0) < b.order + (b.boss and b.boss.showdown and 1000 or 0) end) - - local blinds_to_be_alerted = {} - for k, v in ipairs(blind_tab) do - local discovered = v.discovered - - local s = 1.3 - if math.ceil(#blind_tab/6) > 6 then - s = s * 6/math.ceil(#blind_tab/6) - end - local temp_blind = AnimatedSprite(0,0,s,s, G.ANIMATION_ATLAS[discovered and v.atlas or 'blind_chips'], discovered and v.pos or G.b_undiscovered.pos) - temp_blind:define_draw_steps({ - {shader = 'dissolve', shadow_height = 0.05}, - {shader = 'dissolve'} - }) - if k == 1 then - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - G.CONTROLLER:snap_to{node = temp_blind} - return true - end) - })) - end - temp_blind.float = true - temp_blind.states.hover.can = true - temp_blind.states.drag.can = false - temp_blind.states.collide.can = true - temp_blind.config = {blind = v, force_focus = true} - if discovered and not v.alerted then - blinds_to_be_alerted[#blinds_to_be_alerted+1] = temp_blind - end - temp_blind.hover = function() - if not G.CONTROLLER.dragging.target or G.CONTROLLER.using_touch then - if not temp_blind.hovering and temp_blind.states.visible then - temp_blind.hovering = true - temp_blind.hover_tilt = 3 - temp_blind:juice_up(0.05, 0.02) - play_sound('chips1', math.random()*0.1 + 0.55, 0.12) - temp_blind.config.h_popup = create_UIBox_blind_popup(v, discovered) - temp_blind.config.h_popup_config ={align = 'cl', offset = {x=-0.1,y=0},parent = temp_blind} - Node.hover(temp_blind) - if temp_blind.children.alert then - temp_blind.children.alert:remove() - temp_blind.children.alert = nil - temp_blind.config.blind.alerted = true - G:save_progress() - end - end - end - temp_blind.stop_hover = function() temp_blind.hovering = false; Node.stop_hover(temp_blind); temp_blind.hover_tilt = 0 end - end - local blinds_per_row = math.ceil(#blind_tab / 6) - local row = math.ceil((k - 1) / blinds_per_row + 0.001) - table.insert(blind_matrix[row], { - n = G.UIT.C, - config = { align = "cm", padding = 0.1 }, - nodes = { - ((k - blinds_per_row) % (2 * blinds_per_row) == 1) and { n = G.UIT.B, config = { h = 0.2, w = 0.5 } } or nil, - { n = G.UIT.O, config = { object = temp_blind, focus_with_object = true } }, - ((k - blinds_per_row) % (2 * blinds_per_row) == 0) and { n = G.UIT.B, config = { h = 0.2, w = 0.5 } } or nil, - } - }) - - end - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - for _, v in ipairs(blinds_to_be_alerted) do - v.children.alert = UIBox{ - definition = create_UIBox_card_alert(), - config = { align="tri", offset = {x = 0.1, y = 0.1}, parent = v} - } - v.children.alert.states.collide.can = false - end - return true - end) - })) - - local min_ante = 1 - local max_ante = 16 - local spacing = 1 - 15*0.06 - if G.GAME and G.GAME.round_resets and G.GAME.round_resets.ante then - local current_ante = G.GAME.round_resets.ante - - if current_ante > 8 then - min_ante = current_ante - 8 + 1 - max_ante = current_ante + 8 - end - end - local ante_amounts = {} - for i = min_ante, max_ante do - -- :3 - if spacing > 0 and i > 1 then - ante_amounts[#ante_amounts+1] = {n=G.UIT.R, config={minh = spacing}, nodes={}} - end - local blind_chip = Sprite(0,0,0.2,0.2,G.ASSET_ATLAS["ui_"..(G.SETTINGS.colourblind_option and 2 or 1)], {x=0, y=0}) - blind_chip.states.drag.can = false - ante_amounts[#ante_amounts+1] = {n=G.UIT.R, config={align = "cm", padding = 0.03}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = 0.7}, nodes={ - {n=G.UIT.T, config={text = i, scale = 0.4, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.C, config={align = "cr", minw = 2.8}, nodes={ - {n=G.UIT.O, config={object = blind_chip}}, - {n=G.UIT.C, config={align = "cm", minw = 0.03, minh = 0.01}, nodes={}}, - {n=G.UIT.T, config={text =number_format(get_blind_amount(i)), scale = 0.4, colour = i <= G.PROFILES[G.SETTINGS.profile].high_scores.furthest_ante.amt and G.C.RED or G.C.JOKER_GREY, shadow = true}}, - }} - }} - end - - local extras = nil - local t = create_UIBox_generic_options({ back_func = exit or 'your_collection', contents = { - {n=G.UIT.C, config={align = "cm", r = 0.1, colour = G.C.BLACK, padding = 0.1, emboss = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", r = 0.1, colour = G.C.L_BLACK, padding = 0.1, force_focus = true, focus_args = {nav = 'tall'}}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = 0.7}, nodes={ - {n=G.UIT.T, config={text = localize('k_ante_cap'), scale = 0.4, colour = lighten(G.C.FILTER, 0.2), shadow = true}}, - }}, - {n=G.UIT.C, config={align = "cr", minw = 2.8}, nodes={ - {n=G.UIT.T, config={text = localize('k_base_cap'), scale = 0.4, colour = lighten(G.C.RED, 0.2), shadow = true}}, - }} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes=ante_amounts} - }}, - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes=blind_matrix[1]}, - {n=G.UIT.R, config={align = "cm"}, nodes=blind_matrix[2]}, - {n=G.UIT.R, config={align = "cm"}, nodes=blind_matrix[3]}, - {n=G.UIT.R, config={align = "cm"}, nodes=blind_matrix[4]}, - {n=G.UIT.R, config={align = "cm"}, nodes=blind_matrix[5]}, - {n=G.UIT.R, config={align = "cm"}, nodes=blind_matrix[6]}, - }} - }} - }} - }}) - return t -end - -function create_UIBox_blind_popup(blind, discovered, vars) - local blind_text = {} - - local _dollars = blind.dollars - local target = {type = 'raw_descriptions', key = blind.key, set = 'Blind', vars = vars or blind.vars} - if blind.collection_loc_vars and type(blind.collection_loc_vars) == 'function' then - local res = blind:collection_loc_vars() or {} - target.vars = res.vars or target.vars - target.key = res.key or target.key - end - local loc_target = localize(target) - local loc_name = localize{type = 'name_text', key = blind.key, set = 'Blind'} - - if discovered then - local ability_text = {} - if loc_target then - for k, v in ipairs(loc_target) do - ability_text[#ability_text + 1] = {n=G.UIT.R, config={align = "cm"}, nodes={{n=G.UIT.T, config={text = v, scale = 0.35, shadow = true, colour = G.C.WHITE}}}} - end - end - local stake_sprite = get_stake_sprite(G.GAME.stake or 1, 0.4) - blind_text[#blind_text + 1] = - {n=G.UIT.R, config={align = "cm", emboss = 0.05, r = 0.1, minw = 2.5, padding = 0.07, colour = G.C.WHITE}, nodes={ - {n=G.UIT.R, config={align = "cm", maxw = 2.4}, nodes={ - {n=G.UIT.T, config={text = localize('ph_blind_score_at_least'), scale = 0.35, colour = G.C.UI.TEXT_DARK}}, - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = stake_sprite}}, - {n=G.UIT.T, config={text = blind.mult..localize('k_x_base'), scale = 0.4, colour = G.C.RED}}, - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = localize('ph_blind_reward'), scale = 0.35, colour = G.C.UI.TEXT_DARK}}, - {n=G.UIT.O, config={object = DynaText({string = {_dollars and string.rep(localize('$'),_dollars) or '-'}, colours = {G.C.MONEY}, rotate = true, bump = true, silent = true, scale = 0.45})}}, - }}, - ability_text[1] and {n=G.UIT.R, config={align = "cm", padding = 0.08, colour = mix_colours(blind.boss_colour, G.C.GREY, 0.4), r = 0.1, emboss = 0.05, minw = 2.5, minh = 0.9}, nodes=ability_text} or nil - }} - else - blind_text[#blind_text + 1] = - {n=G.UIT.R, config={align = "cm", emboss = 0.05, r = 0.1, minw = 2.5, padding = 0.1, colour = G.C.WHITE}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = localize('ph_defeat_this_blind_1'), scale = 0.4, colour = G.C.UI.TEXT_DARK}}, - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = localize('ph_defeat_this_blind_2'), scale = 0.4, colour = G.C.UI.TEXT_DARK}}, - }}, - }} - end - return {n=G.UIT.ROOT, config={align = "cm", padding = 0.05, colour = lighten(G.C.JOKER_GREY, 0.5), r = 0.1, emboss = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cm", emboss = 0.05, r = 0.1, minw = 2.5, padding = 0.1, colour = not discovered and G.C.JOKER_GREY or blind.boss_colour or G.C.GREY}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = discovered and loc_name or localize('k_not_discovered'), colours = {G.C.UI.TEXT_LIGHT}, shadow = true, rotate = not discovered, spacing = discovered and 2 or 0, bump = true, scale = 0.4})}}, - }}, - {n=G.UIT.R, config={align = "cm"}, nodes=blind_text}, - }} -end - - -function create_UIBox_card_unlock(card_center) - G.your_collection = CardArea( - G.ROOM.T.x + G.ROOM.T.w/2,G.ROOM.T.h, - 1*G.CARD_W, - 1*G.CARD_H, - {card_limit = 2, type = 'consumeable', highlight_limit = 0}) - - local card = Card(G.your_collection.T.x + G.your_collection.T.w/2 - G.CARD_W/2, G.your_collection.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, card_center, {bypass_discovery_center = true, bypass_discovery_ui = true}) - local locked_card = Card(G.your_collection.T.x + G.your_collection.T.w/2 - G.CARD_W/2, G.your_collection.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, card_center.set == 'Voucher' and G.v_locked or G.j_locked) - locked_card:remove_UI() - locked_card.ID = card.ID - card.states.click.can = false - locked_card.states.click.can = false - card.states.visible = false - card.no_ui = true - - G.E_MANAGER:add_event(Event({timer = 'REAL',blockable = false,blocking = false, - func = (function() G.OVERLAY_MENU.joker_unlock_table = card.ID return true end) })) - G.E_MANAGER:add_event(Event({timer = 'REAL',blockable = false,blocking = false, trigger = 'after', delay = 0.6, - func = (function() if G.OVERLAY_MENU and G.OVERLAY_MENU.joker_unlock_table == card.ID then locked_card:juice_up(0.3, 0.2); play_sound('cancel', 0.8) end; return true end) })) - G.E_MANAGER:add_event(Event({timer = 'REAL',blockable = false,blocking = false, trigger = 'after', delay = 1.15, - func = (function() if G.OVERLAY_MENU and G.OVERLAY_MENU.joker_unlock_table == card.ID then locked_card:juice_up(0.45, 0.3); play_sound('cancel', 0.92) end; return true end) })) - G.E_MANAGER:add_event(Event({timer = 'REAL',blockable = false,blocking = false, trigger = 'after', delay = 1.8, - func = (function() if G.OVERLAY_MENU and G.OVERLAY_MENU.joker_unlock_table == card.ID then locked_card:juice_up(0.6, 0.4); play_sound('cancel', 1.03) end; return true end) })) - - G.E_MANAGER:add_event(Event({ - timer = 'REAL', - blockable = false, - blocking = false, - trigger = 'after', - delay = 2.3, - func = (function() - if G.OVERLAY_MENU and G.OVERLAY_MENU.joker_unlock_table == card.ID then locked_card:start_dissolve({G.C.BLACK}) end - return true end) - })) - G.E_MANAGER:add_event(Event({ - timer = 'REAL', - blockable = false, - blocking = false, - trigger = 'after', - delay = 2.7, - func = (function() - if G.OVERLAY_MENU and G.OVERLAY_MENU.joker_unlock_table == card.ID then - card:start_materialize({G.C.BLUE}, true) - play_sound('crumple1', 0.8, 1); - end - return true end) - })) - G.E_MANAGER:add_event(Event({timer = 'REAL',blockable = false,blocking = false, trigger = 'after', delay = 2.78, - func = (function() if G.OVERLAY_MENU and G.OVERLAY_MENU.joker_unlock_table == card.ID then card.no_ui = nil; play_sound('timpani', 0.8, 1.8) end return true end) })) - G.E_MANAGER:add_event(Event({timer = 'REAL',blockable = false,blocking = false, trigger = 'after', delay = 2.95, - func = (function() if G.OVERLAY_MENU and G.OVERLAY_MENU.joker_unlock_table == card.ID then play_sound('timpani', 1, 1.8) end return true end) })) - - G.your_collection:emplace(card) - G.your_collection:emplace(locked_card) - - local t = create_UIBox_generic_options({padding = 0,back_label = localize('b_continue'), no_pip = true, snap_back = true, back_func = 'continue_unlock', minw = 4.5, contents = { - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {card_center.set == 'Voucher' and localize('k_voucher') or localize('k_joker')}, colours = {G.C.BLUE},shadow = true, rotate = true, bump = true, pop_in = 0.3, pop_in_rate = 2, scale = 1.2})}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('k_unlocked_ex')}, colours = {G.C.RED},shadow = true, rotate = true, bump = true, pop_in = 0.6, pop_in_rate = 2, scale = 0.8})}} - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0, draw_layer = 1}, nodes={ - {n=G.UIT.O, config={object = G.your_collection}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.2}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05, emboss = 0.05, colour = G.C.WHITE, r = 0.1}, nodes={ - desc_from_rows(card:generate_UIBox_unlock_table(true).main) - }} - }} - }} - }} - }}) - return t -end - -function create_UIBox_deck_unlock(deck_center) - G.GAME.viewed_back = Back(deck_center) - local area = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - 1.2*G.CARD_W, - 1.2*G.CARD_H, - {card_limit = 52, type = 'deck', highlight_limit = 0}) - - for i = 1, 52 do - local card = Card(G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, G.CARD_W*1.2, G.CARD_H*1.2, pseudorandom_element(G.P_CARDS), G.P_CENTERS.c_base, {bypass_back = deck_center.pos, playing_card = i, viewed_back = true}) - area:emplace(card) - card[deck_center.key] = true - card.sprite_facing = 'back' - card.facing = 'back' - end - local deck_criteria = {} - if deck_center.unlock_condition.type == 'win_deck' then - local other_name = localize{type = 'name_text', set = 'Back', key = deck_center.unlock_condition.deck} - localize{type = 'descriptions', key = 'deck_locked_win', set = "Other", nodes = deck_criteria, vars = {other_name}, default_col = G.C.WHITE, shadow = true} - elseif deck_center.unlock_condition.type == 'win_stake' then - local other_name = localize{type = 'name_text', set = 'Stake', key = G.P_CENTER_POOLS.Stake[deck_center.unlock_condition.stake].key} - localize{type = 'descriptions', key = 'deck_locked_stake', set = "Other", nodes = deck_criteria, vars = {other_name, colours = {get_stake_col(deck_center.unlock_condition.stake)}}, default_col = G.C.WHITE, shadow = true} - elseif deck_center.unlock_condition.type == 'discover_amount' then - localize{type = 'descriptions', key = 'deck_locked_discover', set = "Other", nodes = deck_criteria, vars = {deck_center.unlock_condition.amount}, default_col = G.C.WHITE, shadow = true} - end - - local deck_criteria_cols = {} - for k, v in ipairs(deck_criteria) do - if k > 1 then deck_criteria_cols[#deck_criteria_cols+1] = {n=G.UIT.C, config={align = "cm", padding = 0, minw = 0.1}, nodes={}} end - deck_criteria_cols[#deck_criteria_cols+1] = {n=G.UIT.C, config={align = "cm", padding = 0}, nodes=v} - end - - local t = create_UIBox_generic_options({ back_label = localize('b_continue'), no_pip = true, snap_back = true, back_func = 'continue_unlock', minw = 7, contents = { - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {{string = localize{type = 'name_text', set = 'Back', key = deck_center.key}, suffix = ' '..localize('k_unlocked_ex'), outer_colour = G.C.UI.TEXT_LIGHT}}, colours = {G.C.BLUE},shadow = true, rotate = true, float = true, scale = 0.7, pop_in = 0.1})}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes=deck_criteria_cols}, - {n=G.UIT.R, config={align = "cm", padding = 0.2, colour = G.C.BLACK, r = 0.2}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={object = area}} - }}, - {n=G.UIT.C, config={align = "cm", r = 0.2, colour = G.C.WHITE, emboss = 0.05, padding = 0.2, minw = 4}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes=G.GAME.viewed_back:generate_UI(deck_center).nodes} - }} - }} - }}) - return t -end - -function G.UIDEF.credits() - local text_scale = 0.75 - local t = create_UIBox_generic_options({contents ={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - create_tabs( - {tabs = { - { - label = "Music", - chosen = true, - tab_definition_function = function() return - {n=G.UIT.ROOT, config={align = "cm", padding = 0.2, colour = G.C.BLACK, r = 0.1, emboss = 0.05, minh = 6, minw = 6}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "Original Soundtrack", scale = text_scale*0.8, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "composed by ", scale = text_scale*0.8, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - {n=G.UIT.T, config={text = "LouisF", scale = text_scale*0.8, colour = G.C.BLUE, shadow = true}} - }}, - G.F_EXTERNAL_LINKS and {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - UIBox_button({label = {'Instagram'}, button = 'louisf_insta'}) - }} or nil, - {n=G.UIT.R, config={align = "cm", padding = 0.2}, nodes={ - {n=G.UIT.T, config={text = "Modified with their permission", scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }} - end, - }, - { - label = "Publishing", - tab_definition_function = function() return - {n=G.UIT.ROOT, config={align = "cm", padding = 0.2, colour = G.C.BLACK, r = 0.1, emboss = 0.05, minh = 6, minw = 10}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "Playstack", scale = text_scale*0.6, colour = G.C.RED, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "tm", padding = 0}, nodes={ - {n=G.UIT.C, config={align = "tl", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Harvey Elliott', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Kevin Shrapnell', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Rob Crossley', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Liz Cheng-Moore', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Will Newell', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Charlotte Riley', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Alexander Saunders', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Naman Budhwar', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Tomasz Wisniowski', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Patrick Johnson', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Tom Verney', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Wouter van Halderen', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Shawn Cotter', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - {n=G.UIT.C, config={align = "tl", padding = 0.093}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'CEO', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'COO', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'VP of Publishing', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Lead Marketing Manager', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Producer', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Producer', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Producer', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Lead Visual Marketing Manager', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Producer', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Senior Discovery Scout', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Discovery Scout', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'PR Manager', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Marketing Manager', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - }}, - {n=G.UIT.B, config={align = "tl", w=0.25, h=0}, nodes={}}, - {n=G.UIT.C, config={align = "tl", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Marta Matyjewicz', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Rebecca Bell', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Alex Flynn', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Justas Pugaciauskas', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Jessica Chu', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Millicent Su', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Carla Malavasi', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Pawel Kwietniak', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Ela Müller', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Edgar Khoo', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Dami Ajiboye', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Aaron Ludlow', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Jenny Quintero', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - {n=G.UIT.C, config={align = "tl", padding = 0.093}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Marketing Manager', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Finance', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Creative Director', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Graphic Designer', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Lead Video Artist', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Senior User Acquisition Manager', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Director of Publishing Services', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Front-end Developer', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Graphic Designer', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Video Editor', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Data Analyst', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Product Director', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Senior Partnerships Manager', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - }}, - {n=G.UIT.B, config={align = "tl", w=0.25, h=0}, nodes={}}, - {n=G.UIT.C, config={align = "tl", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Stephanie Marti', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Emma Smith-Bodie', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Moe Abrams', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Piotr Kowalik', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Carmen Martino', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Rong Lin', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Bea Gomez', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Jose Olivares', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Joanna Kieronska', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Zuzanna Dawidowska', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Jean-Claude Vidanes ', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'AJ Purnell', scale = text_scale*0.42, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - {n=G.UIT.C, config={align = "tl", padding = 0.093}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Senior Video Artist', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Community Manager', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Customer Support', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Software Engineer', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'HR & Office Manager', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Finance Manager', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Video Editor', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'QA & Localisation Manager', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'QA Tester', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'QA Tester', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'QA Tester', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'QA Tester', scale = text_scale*0.35, colour = G.C.GOLD, shadow = true}}, - }}, - }}, - }}, - }} - }} - end, - }, - { - label = "Production", - tab_definition_function = function() return - {n=G.UIT.ROOT, config={align = "cm", padding = 0.2, colour = G.C.BLACK, r = 0.1, emboss = 0.05, minh = 6, minw = 10}, nodes={ - {n=G.UIT.C, config={align = "tm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "Porting", scale = text_scale*0.6, colour = G.C.WHITE, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "PlayStation", scale = text_scale*0.45, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "tm", padding = 0}, nodes={ - {n=G.UIT.C, config={align = "tl", padding = 0.03}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Maarten De Meyer', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "Xbox", scale = text_scale*0.45, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "tm", padding = 0}, nodes={ - {n=G.UIT.C, config={align = "tl", padding = 0.03}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Maarten De Meyer', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "Android", scale = text_scale*0.45, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "tm", padding = 0}, nodes={ - {n=G.UIT.C, config={align = "tl", padding = 0.03}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Maarten De Meyer', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "Apple Platforms", scale = text_scale*0.45, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "tm", padding = 0}, nodes={ - {n=G.UIT.C, config={align = "tl", padding = 0.03}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Maarten De Meyer', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "Mac (Steam)", scale = text_scale*0.45, colour = G.C.GOLD, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "tm", padding = 0}, nodes={ - {n=G.UIT.C, config={align = "tl", padding = 0.03}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'william341', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - }}, - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "Localization", scale = text_scale*0.6, colour = G.C.WHITE, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "Universally Speaking", scale = text_scale*0.6, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "tm", padding = 0}, nodes={ - {n=G.UIT.C, config={align = "tl", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'German', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Spanish Latam', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'French', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Indonesian', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Italian', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Japanese', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Korean', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Dutch', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Polish', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Portuguese Brasilian', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Russian', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Simplified Chinese', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Traditional Chinese', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Project managers', scale = text_scale*0.35, colour = G.C.FILTER, shadow = true}}, - }}, - }}, - {n=G.UIT.C, config={align = "tl", padding = 0.05}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Dominik May, Lisa-Marie Beck', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Román René Orozco, Javier Gómez', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Romain Vervaecke, Claire Gérard', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Yopi Jalu Paksi, Sutarto Mohammad', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Oliver Cozzio, Giulia Benassi', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Takashi Fujimoto, Ai Parlow', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Haejung Lee, Sanghyun Bae', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Ellis Jongsma, Erik Nusselder', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Mariusz Wlodarczyk, Bartosz Klofik', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Samuel Modesto, R. Cali', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Yuliia Tatsenko, Natalia Rudane', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Shuai Fang, Liqi Ye', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Pauline Lin, AngelRabbitBB', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Ruoyang Yuan, Tania Carè', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - }}, - }}, - {n=G.UIT.C, config={align = "tm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "Testing/QA", scale = text_scale*0.6, colour = G.C.WHITE, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "tm", padding = 0}, nodes={ - {n=G.UIT.C, config={align = "tl", padding = 0.03}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Vishwak Kondapalli', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Basha Syed', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'CampfireCollective', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'drspectred', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'TheRealEvab', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Brightqwerty', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'MrWizzrd', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'mcpower', scale = text_scale*0.35, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - - }}, - }}, - - }} - end, - }, - { - label = "Sounds", - tab_definition_function = function() return - {n=G.UIT.ROOT, config={align = "cm", padding = 0.2, colour = G.C.BLACK, r = 0.1, emboss = 0.05, minh = 6, minw = 10}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "All sounds not listed here fall under ", scale = text_scale*0.6, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - {n=G.UIT.T, config={text = "Creative Commons - CC0", scale = text_scale*0.6, colour = G.C.BLUE, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = '"chamber_choir_chord_o.wav" (Used for Polychrome sound) by uair01 (https://freesound.org/people/uair01/sounds/65195/)', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'is licensed under ', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - {n=G.UIT.T, config={text = "Attribution 3.0 License", scale = text_scale*0.5, colour = G.C.GOLD, shadow = true}}, - {n=G.UIT.T, config={text = '. This work has been modified from its original state', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = '"Coffee1.wav" (Used for Tarot card sound) by Nathan Gibson (https://nathangibson.myportfolio.com)', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'is licensed under ', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - {n=G.UIT.T, config={text = "Attribution 4.0 License", scale = text_scale*0.5, colour = G.C.ORANGE, shadow = true}}, - {n=G.UIT.T, config={text = '.', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = '"Wood Block1.wav" (Used for Tarot card sound) by Nathan Gibson (https://nathangibson.myportfolio.com)', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'is licensed under ', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - {n=G.UIT.T, config={text = "Attribution 4.0 License", scale = text_scale*0.5, colour = G.C.ORANGE, shadow = true}}, - {n=G.UIT.T, config={text = '.', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = '"Toy records#06-E3-02.wav" (Used for Mult sounds) by poissonmort (https://freesound.org/people/poissonmort/sounds/253249/)', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'is licensed under ', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - {n=G.UIT.T, config={text = "Attribution 4.0 License", scale = text_scale*0.5, colour = G.C.ORANGE, shadow = true}}, - {n=G.UIT.T, config={text = '. This work has been modified from its original state', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - }} - end, - }, - { - label = "Imagery", - tab_definition_function = function() return - {n=G.UIT.ROOT, config={align = "cm", padding = 0.2, colour = G.C.BLACK, r = 0.1, emboss = 0.05, minh = 6, minw = 10}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'The font "m6x11.ttf" by Daniel Linssen (https://managore.itch.io/m6x11)', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'is licensed under an ', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - {n=G.UIT.T, config={text = "Attribution License", scale = text_scale*0.5, colour = G.C.GOLD, shadow = true}}, - {n=G.UIT.T, config={text = '.', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - not G.F_BASIC_CREDITS and - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Check out his itch.io profile, he has made an incredible catalogue of games.', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }} or nil, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'The Joker "Vagabond" was created by Lumpy Touch', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'The Collab art for Slay the Spire and The Binding of Isaac was', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'created by ', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - {n=G.UIT.T, config={text = "Neato", scale = text_scale*0.5, colour = G.C.GOLD, shadow = true}}, - {n=G.UIT.T, config={text = ' (twitch.tv/neato)', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "All sprites, shaders, and any other visual assets", scale = text_scale*0.6, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "not listed here were created by LocalThunk.", scale = text_scale*0.6, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "©2024 - All rights reserved", scale = text_scale*0.6, colour = G.C.BLUE, shadow = true}}, - }}, - }} - end, - }, - { - label = "Misc", - tab_definition_function = function() return - {n=G.UIT.ROOT, config={align = "cm", padding = 0.2, colour = G.C.BLACK, r = 0.1, emboss = 0.05, minh = 6, minw = 6}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "For Marshal", scale = text_scale*0.6, colour = G.C.WHITE, shadow = true}}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1,outline_colour = G.C.JOKER_GREY, r = 0.1, outline = 1}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = "Special Thanks", scale = text_scale*0.6, colour = G.C.GREEN, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "tm", padding = 0}, nodes={ - {n=G.UIT.C, config={align = "tl", padding = 0.05, minw = 2.5}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Nicole', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Josh', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Jeremy', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Dylan', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Justin', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Daniel', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Colby', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Thomas', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Mom & Dad', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Luc & Donna', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - {n=G.UIT.C, config={align = "tl", padding = 0.05, minw = 2.5}, nodes={ - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'GothicLordUK', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Big Simple', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'MALF', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Northernlion', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Purple Moss Collectors', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Dan Gheesling', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Fabian Fischer', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'newobject', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'MurphyObv', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", padding = 0}, nodes={ - {n=G.UIT.T, config={text = 'Love2D', scale = text_scale*0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - }}, - }}, - }} - }} - end, - }, - }, - snap_to_nav = true}), - }} - }}) - return t -end - -function G.UIDEF.challenges(from_game_over) - - if G.PROFILES[G.SETTINGS.profile].all_unlocked then G.PROFILES[G.SETTINGS.profile].challenges_unlocked = #G.CHALLENGES end - - if not G.PROFILES[G.SETTINGS.profile].challenges_unlocked then - local deck_wins = 0 - for k, v in pairs(G.PROFILES[G.SETTINGS.profile].deck_usage) do - if v.wins and v.wins[1] then - deck_wins = deck_wins + 1 - end - end - local loc_nodes = {} - localize{type = 'descriptions', key = 'challenge_locked', set = 'Other', nodes = loc_nodes, vars = {G.CHALLENGE_WINS, deck_wins}, default_col = G.C.WHITE} - - return {n=G.UIT.ROOT, config={align = "cm", padding = 0.1, colour = G.C.CLEAR, minh = 8.02, minw = 7}, nodes={ - transparent_multiline_text(loc_nodes) - }} - end - - G.run_setup_seed = nil - if G.OVERLAY_MENU then - local seed_toggle = G.OVERLAY_MENU:get_UIE_by_ID('run_setup_seed') - if seed_toggle then seed_toggle.states.visible = false end - end - - - local _ch_comp, _ch_tot = 0,#G.CHALLENGES - for k, v in ipairs(G.CHALLENGES) do - if v.id and G.PROFILES[G.SETTINGS.profile].challenge_progress.completed[v.id or ''] then - _ch_comp = _ch_comp + 1 - end - end - - local _ch_tab = {comp = _ch_comp, unlocked = G.PROFILES[G.SETTINGS.profile].challenges_unlocked} - - return {n=G.UIT.ROOT, config={align = "cm", padding = 0.1, colour = G.C.CLEAR, minh = 8, minw = 7}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1, r = 0.1 ,colour = G.C.BLACK}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.T, config={text = localize('k_challenge_mode'), scale = 0.4, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", minw = 8.5, minh = 1.5, padding = 0.2}, nodes={ - UIBox_button({id = from_game_over and 'from_game_over' or nil, label = {localize('b_new_challenge')}, button = 'challenge_list', minw = 4, scale = 0.4, minh = 0.6}), - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.8, r = 0.1, minw = 4.5, colour = G.C.L_BLACK, emboss = 0.05, - progress_bar = { - max = _ch_tot, ref_table = _ch_tab, ref_value = 'unlocked', empty_col = G.C.L_BLACK, filled_col = G.C.FILTER - }}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, r = 0.1, minw = 4.5}, nodes={ - {n=G.UIT.T, config={text = localize{type = 'variable', key = 'unlocked', vars = {_ch_tab.unlocked, _ch_tot}}, scale = 0.3, colour = G.C.WHITE, shadow =true}}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.8, r = 0.1, minw = 4.5, colour = G.C.L_BLACK, emboss = 0.05, - progress_bar = { - max = _ch_tot, ref_table = _ch_tab, ref_value = 'comp', empty_col = G.C.L_BLACK, filled_col = adjust_alpha(G.C.GREEN, 0.5) - }}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.05, r = 0.1, minw = 4.5}, nodes={ - {n=G.UIT.T, config={text = localize{type = 'variable', key = 'completed', vars = {_ch_comp, _ch_tot}}, scale = 0.3, colour = G.C.WHITE, shadow = true}}, - }}, - }}, - }}, - G.F_DAILIES and {n=G.UIT.R, config={align = "cm", padding = 0.1, r = 0.1 ,colour = G.C.BLACK}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.T, config={text = localize('k_daily_run'), scale = 0.4, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cl", minw = 8.5, minh = 4}, nodes={ - G.UIDEF.daily_overview() - }} - }} or nil, - }} -end - -function G.UIDEF.daily_overview() - local hist_height, hist_width = 3, 3 - - local daily_results = { - score = { - me = {val = 20000, percentile = 75}, - hist = { - 0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.05,0.15,0.1,0.1,0.05,0.05,0.05,0.05,0.05 - } - } - } - local score_hist, max_score_hist = {}, 0 - for k, v in ipairs(daily_results.score.hist) do if max_score_hist < v then max_score_hist = v end end - for k, v in ipairs(daily_results.score.hist) do - score_hist[#score_hist+1] = {n=G.UIT.C, config={align = 'bm'}, nodes ={{n=G.UIT.C, config={colour = G.C.BLUE, minw = hist_width/#daily_results.score.hist, minh = (v + 0.05*math.random())/max_score_hist*hist_height}}}} - end - - return {n=G.UIT.R, config={align = "cm"}, nodes=score_hist} -end - -function G.UIDEF.run_setup(from_game_over) - G.run_setup_seed = nil - local _challenge_chosen = from_game_over == 'challenge_list' - from_game_over = from_game_over and not (from_game_over == 'challenge_list') - - local _can_continue = G.MAIN_MENU_UI and G.FUNCS.can_continue({config = {func = true}}) - G.FUNCS.false_ret = function() return false end - local t = create_UIBox_generic_options({no_back = from_game_over, no_esc = from_game_over, contents ={ - {n=G.UIT.R, config={align = "cm", padding = 0, draw_layer = 1}, nodes={ - create_tabs( - {tabs = { - { - label = localize('b_new_run'), - chosen = (not _challenge_chosen) and (not _can_continue), - tab_definition_function = G.UIDEF.run_setup_option, - tab_definition_function_args = 'New Run' - }, - G.STAGE == G.STAGES.MAIN_MENU and { - label = localize('b_continue'), - chosen = (not _challenge_chosen) and _can_continue, - tab_definition_function = G.UIDEF.run_setup_option, - tab_definition_function_args = 'Continue', - func = 'can_continue' - } or { - label = localize('b_challenges'), - tab_definition_function = G.UIDEF.challenges, - tab_definition_function_args = from_game_over, - chosen = _challenge_chosen - }, - G.STAGE == G.STAGES.MAIN_MENU and { - label = localize('b_challenges'), - tab_definition_function = G.UIDEF.challenges, - tab_definition_function_args = from_game_over, - chosen = _challenge_chosen - } or nil, - }, - snap_to_nav = true}), - }}, - }}) - return t -end - -function G.UIDEF.profile_select() - G.focused_profile = G.focused_profile or G.SETTINGS.profile or 1 - - local t = create_UIBox_generic_options({padding = 0,contents ={ - {n=G.UIT.R, config={align = "cm", padding = 0, draw_layer = 1, minw = 4}, nodes={ - create_tabs( - {tabs = { - { - label = 1, - chosen = G.focused_profile == 1, - tab_definition_function = G.UIDEF.profile_option, - tab_definition_function_args = 1 - }, - { - label = 2, - chosen = G.focused_profile == 2, - tab_definition_function = G.UIDEF.profile_option, - tab_definition_function_args = 2 - }, - { - label = 3, - chosen = G.focused_profile == 3, - tab_definition_function = G.UIDEF.profile_option, - tab_definition_function_args = 3 - } - }, - snap_to_nav = true}), - }}, - }}) - return t -end - -function G.UIDEF.profile_option(_profile) - set_discover_tallies() - G.focused_profile = _profile - local profile_data = get_compressed(G.focused_profile..'/'..'profile.jkr') - if profile_data ~= nil then - profile_data = STR_UNPACK(profile_data) - profile_data.name = profile_data.name or ("P".._profile) - end - G.PROFILES[_profile].name = profile_data and profile_data.name or '' - - local lwidth, rwidth, scale = 1, 1, 1 - G.CHECK_PROFILE_DATA = nil - local t = {n=G.UIT.ROOT, config={align = 'cm', colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = 'cm',padding = 0.1, minh = 0.8}, nodes={ - ((_profile == G.SETTINGS.profile) or not profile_data) and {n=G.UIT.R, config={align = "cm"}, nodes={ - create_text_input({ - w = 4, max_length = 16, prompt_text = localize('k_enter_name'), - ref_table = G.PROFILES[_profile], ref_value = 'name',extended_corpus = true, keyboard_offset = 1, - callback = function() - G:save_settings() - G.FILE_HANDLER.force = true - end - }), - }} or {n=G.UIT.R, config={align = 'cm',padding = 0.1, minw = 4, r = 0.1, colour = G.C.BLACK, minh = 0.6}, nodes={ - {n=G.UIT.T, config={text = G.PROFILES[_profile].name, scale = 0.45, colour = G.C.WHITE}}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = 6}, nodes={ - (G.PROFILES[_profile].progress and G.PROFILES[_profile].progress.discovered) and create_progress_box(G.PROFILES[_profile].progress, 0.5) or - {n=G.UIT.C, config={align = "cm", minh = 4, minw = 5.2, colour = G.C.BLACK, r = 0.1}, nodes={ - {n=G.UIT.T, config={text = localize('k_empty_caps'), scale = 0.5, colour = G.C.UI.TRANSPARENT_LIGHT}} - }}, - }}, - {n=G.UIT.C, config={align = "cm", minh = 4}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 1}, nodes={ - profile_data and {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = lwidth}, nodes={{n=G.UIT.T, config={text = localize('k_wins'),colour = G.C.UI.TEXT_LIGHT, scale = scale*0.7}}}}, - {n=G.UIT.C, config={align = "cm"}, nodes={{n=G.UIT.T, config={text = ': ',colour = G.C.UI.TEXT_LIGHT, scale = scale*0.7}}}}, - {n=G.UIT.C, config={align = "cl", minw = rwidth}, nodes={{n=G.UIT.T, config={text = tostring(profile_data.career_stats.c_wins),colour = G.C.RED, shadow = true, scale = 1*scale}}}} - }} or nil, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.2}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.R, config={align = "cm", minw = 4, maxw = 4, minh = 0.8, padding = 0.2, r = 0.1, hover = true, colour = G.C.BLUE,func = 'can_load_profile', button = "load_profile", shadow = true, focus_args = {nav = 'wide'}}, nodes={ - {n=G.UIT.T, config={text = _profile == G.SETTINGS.profile and localize('b_current_profile') or profile_data and localize('b_load_profile') or localize('b_create_profile'), ref_value = 'load_button_text', scale = 0.5, colour = G.C.UI.TEXT_LIGHT}} - }} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0, minh = 0.7}, nodes={ - {n=G.UIT.R, config={align = "cm", minw = 3, maxw = 4, minh = 0.6, padding = 0.2, r = 0.1, hover = true, colour = G.C.RED,func = 'can_delete_profile', button = "delete_profile", shadow = true, focus_args = {nav = 'wide'}}, nodes={ - {n=G.UIT.T, config={text = _profile == G.SETTINGS.profile and localize('b_reset_profile') or localize('b_delete_profile'), scale = 0.3, colour = G.C.UI.TEXT_LIGHT}} - }} - }}, - (_profile == G.SETTINGS.profile and not G.PROFILES[G.SETTINGS.profile].all_unlocked) and {n=G.UIT.R, config={align = "cm", padding = 0, minh = 0.7}, nodes={ - {n=G.UIT.R, config={align = "cm", minw = 3, maxw = 4, minh = 0.6, padding = 0.2, r = 0.1, hover = true, colour = G.C.ORANGE,func = 'can_unlock_all', button = "unlock_all", shadow = true, focus_args = {nav = 'wide'}}, nodes={ - {n=G.UIT.T, config={text = localize('b_unlock_all'), scale = 0.3, colour = G.C.UI.TEXT_LIGHT}} - }} - }} or {n=G.UIT.R, config={align = "cm", minw = 3, maxw = 4, minh = 0.7}, nodes={ - G.PROFILES[_profile].all_unlocked and ((not G.F_NO_ACHIEVEMENTS) and {n=G.UIT.T, config={text = localize(G.F_TROPHIES and 'k_trophies_disabled' or 'k_achievements_disabled'), scale = 0.3, colour = G.C.UI.TEXT_LIGHT}} or - nil) or nil - }}, - }}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={id = 'warning_text', text = localize('ph_click_confirm'), scale = 0.4, colour = G.C.CLEAR}} - }} - }} - return t -end - -function G.UIDEF.stake_description(_stake) - local _stake_center = G.P_CENTER_POOLS.Stake[_stake] - local ret_nodes = {} - if _stake_center then localize{type = 'descriptions', key = _stake_center.key, set = _stake_center.set, nodes = ret_nodes} end - - local desc_t = {} - for k, v in ipairs(ret_nodes) do - desc_t[#desc_t+1] = {n=G.UIT.R, config={align = "cm", maxw = 5.3}, nodes=v} - end - - return {n=G.UIT.C, config={align = "cm", padding = 0.05, r = 0.1, colour = G.C.L_BLACK}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = localize{type = 'name_text', key = _stake_center.key, set = _stake_center.set}, scale = 0.35, colour = G.C.WHITE}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.03, colour = G.C.WHITE, r = 0.1, minh = 1, minw = 5.5}, nodes=desc_t} - }} -end - -function G.UIDEF.stake_option(_type) - local middle = {n=G.UIT.R, config={align = "cm", minh = 1.7, minw = 7.3}, nodes={ - {n=G.UIT.O, config={id = nil, func = 'RUN_SETUP_check_stake2', object = Moveable()}}, - }} - - local max_stake = get_deck_win_stake(G.GAME.viewed_back.effect.center.key) - if G.PROFILES[G.SETTINGS.profile].all_unlocked then max_stake = #G.P_CENTER_POOLS['Stake'] end - local stake_options = {} - for i = 1, math.min(max_stake+1, #G.P_CENTER_POOLS['Stake']) do - stake_options[i] = i - end - - return {n=G.UIT.ROOT, config={align = "tm", colour = G.C.CLEAR, minh = 2.03, minw = 8.3}, nodes={_type == 'Continue' and middle or create_option_cycle({options = - stake_options, - opt_callback = 'change_stake', current_option = G.viewed_stake, colour = G.C.RED, w = 6, mid = middle - }) -}} -end - -function G.UIDEF.viewed_stake_option() - G.viewed_stake = G.viewed_stake or 1 - local max_stake = get_deck_win_stake(G.GAME.viewed_back.effect.center.key) - if G.PROFILES[G.SETTINGS.profile].all_unlocked then max_stake = #G.P_CENTER_POOLS['Stake'] end - - G.viewed_stake = math.min(max_stake+1, G.viewed_stake) - if G.viewed_stake > #G.P_CENTER_POOLS.Stake then G.viewed_stake = #G.P_CENTER_POOLS.Stake end - if _type ~= 'Continue' then G.PROFILES[G.SETTINGS.profile].MEMORY.stake = G.viewed_stake end - - local stake_sprite = get_stake_sprite(G.viewed_stake) - - return {n=G.UIT.ROOT, config={align = "cm", colour = G.C.BLACK, r = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = localize('k_stake'), scale = 0.4, colour = G.C.L_BLACK, vert = true}} - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={colour = G.C.BLUE, object = stake_sprite, hover = true, can_collide = false}}, - }}, - G.UIDEF.stake_description(G.viewed_stake) - }} - }} -end - -function G.UIDEF.challenge_list(from_game_over) - G.CHALLENGE_PAGE_SIZE = 10 - local challenge_pages = {} - for i = 1, math.ceil(#G.CHALLENGES/G.CHALLENGE_PAGE_SIZE) do - table.insert(challenge_pages, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#G.CHALLENGES/G.CHALLENGE_PAGE_SIZE))) - end - G.E_MANAGER:add_event(Event({func = (function() - G.FUNCS.change_challenge_list_page{cycle_config = {current_option = 1}} - return true end)})) - - local _ch_comp, _ch_tot = 0,#G.CHALLENGES - for k, v in ipairs(G.CHALLENGES) do - if v.id and G.PROFILES[G.SETTINGS.profile].challenge_progress.completed[v.id or ''] then - _ch_comp = _ch_comp + 1 - end - end - - local t = create_UIBox_generic_options({ back_id = from_game_over and 'from_game_over' or nil, back_func = 'setup_run', back_id = 'challenge_list', contents = { - {n=G.UIT.C, config={align = "cm", padding = 0.0}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1, minh = 7, minw = 4.2}, nodes={ - {n=G.UIT.O, config={id = 'challenge_list', object = Moveable()}}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - create_option_cycle({id = 'challenge_page',scale = 0.9, h = 0.3, w = 3.5, options = challenge_pages, cycle_shoulders = true, opt_callback = 'change_challenge_list_page', current_option = 1, colour = G.C.RED, no_pips = true, focus_args = {snap_to = true}}) - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - {n=G.UIT.T, config={text = localize{type = 'variable', key = 'challenges_completed', vars = {_ch_comp, _ch_tot}}, scale = 0.4, colour = G.C.WHITE}}, - }}, - - }}, - {n=G.UIT.C, config={align = "cm", minh = 9, minw = 11.5}, nodes={ - {n=G.UIT.O, config={id = 'challenge_area', object = Moveable()}}, - }}, - }}) - return t -end - -function G.UIDEF.challenge_list_page(_page) - local snapped = false - local challenge_list = {} - for k, v in ipairs(G.CHALLENGES) do - if k > G.CHALLENGE_PAGE_SIZE*(_page or 0) and k <= G.CHALLENGE_PAGE_SIZE*((_page or 0) + 1) then - if G.CONTROLLER.focused.target and G.CONTROLLER.focused.target.config.id == 'challenge_page' then snapped = true end - local challenge_completed = G.PROFILES[G.SETTINGS.profile].challenge_progress.completed[v.id or ''] - local challenge_unlocked = G.PROFILES[G.SETTINGS.profile].challenges_unlocked and (G.PROFILES[G.SETTINGS.profile].challenges_unlocked >= k) - if v.unlocked and type(v.unlocked) == 'function' then - challenge_unlocked = v:unlocked() - elseif type(v.unlocked) == 'boolean' then - challenge_unlocked = v.unlocked - end - challenge_unlocked = challenge_unlocked or G.PROFILES[G.SETTINGS.profile].all_unlocked - - - challenge_list[#challenge_list+1] = - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = 'cl', minw = 0.8}, nodes = { - {n=G.UIT.T, config={text = k..'', scale = 0.4, colour = G.C.WHITE}}, - }}, - UIBox_button({id = k, col = true, label = {challenge_unlocked and localize(v.id, 'challenge_names') or localize('k_locked'),}, button = challenge_unlocked and 'change_challenge_description' or 'nil', colour = challenge_unlocked and G.C.RED or G.C.GREY, minw = 4, scale = 0.4, minh = 0.6, focus_args = {snap_to = not snapped}}), - {n=G.UIT.C, config={align = 'cm', padding = 0.05, minw = 0.6}, nodes = { - {n=G.UIT.C, config={minh = 0.4, minw = 0.4, emboss = 0.05, r = 0.1, colour = challenge_completed and G.C.GREEN or G.C.BLACK}, nodes = { - challenge_completed and {n=G.UIT.O, config={object = Sprite(0,0,0.4,0.4, G.ASSET_ATLAS["icons"], {x=1, y=0})}} or nil - }}, - }}, - }} - snapped = true - end - end - - return {n=G.UIT.ROOT, config={align = "cm", padding = 0.1, colour = G.C.CLEAR}, nodes=challenge_list} -end - -function G.UIDEF.challenge_description(_id, daily, is_row) - local challenge = G.CHALLENGES[_id] - if not challenge then return {n=G.UIT.ROOT, config={align = "cm", colour = G.C.BLACK, minh = 8.82, minw = 11.5, r = 0.1}, nodes={{n=G.UIT.T, config={text = localize('ph_select_challenge'), scale = 0.3, colour = G.C.UI.TEXT_LIGHT}}}} end - - local joker_size = 0.6 - local jokers = CardArea(0,0, - 10*joker_size, - 0.6*G.CARD_H, - {card_limit = get_challenge_rule(challenge, 'modifiers', 'joker_limit') or 5, - card_w = joker_size*G.CARD_W, type = 'title_2', highlight_limit = 0}) - - if challenge.jokers then - for k, v in ipairs(challenge.jokers) do - local card = Card(0,0, G.CARD_W*joker_size, G.CARD_H*joker_size, nil, G.P_CENTERS[v.id], {bypass_discovery_center = true,bypass_discovery_ui = true, bypass_lock=true}) - if v.edition then card:set_edition({[v.edition] = true}, true, true) end - if v.eternal then card:set_eternal(true) end - if v.pinned then card.pinned = true end - jokers:emplace(card) - end - end - - local joker_col = {n=G.UIT.C, config={align = "cm", padding = 0.05, colour = G.C.L_BLACK, r = 0.1, maxh = 1.8}, nodes={ - {n=G.UIT.T, config={text = localize('k_jokers_cap'), scale = 0.5, colour = G.C.UI.TEXT_LIGHT, vert = true, shadow = true}}, - {n=G.UIT.C, config={align = "cm", minh = 0.6*G.CARD_H, minw = 5, r = 0.1, colour = G.C.UI.TRANSPARENT_DARK}, nodes={ - jokers and {n=G.UIT.O, config={object = jokers}} or {n=G.UIT.T, config={text = localize('k_none'), scale = 0.5, colour = G.C.UI.TEXT_LIGHT}} - }} - }} - - local consumeables = CardArea(0,0, - 3*joker_size, - 0.6*G.CARD_H, - {card_limit = get_challenge_rule(challenge, 'modifiers', 'consumable_limit') or 2, - card_w = joker_size*G.CARD_W, type = 'title_2', spread = true, highlight_limit = 0}) - - if challenge.consumeables then - for k, v in ipairs(challenge.consumeables) do - local card = Card(0,0, G.CARD_W*joker_size, G.CARD_H*joker_size, nil, G.P_CENTERS[v.id], {bypass_discovery_center = true,bypass_discovery_ui = true, bypass_lock=true}) - if v.edition then card:set_edition({[v.edition] = true}, true, true) end - if v.eternal then card:set_eternal(true) end - consumeables:emplace(card) - end - end - - local consumable_col = {n=G.UIT.C, config={align = "cm", padding = 0.05, colour = G.C.L_BLACK, r = 0.1, maxh = 1.8}, nodes={ - {n=G.UIT.T, config={text = localize('k_cap_consumables'), scale = 0.3, colour = G.C.UI.TEXT_LIGHT, vert = true, shadow = true}}, - {n=G.UIT.C, config={align = "cm", minh = 0.6*G.CARD_H, r = 0.1, colour = G.C.UI.TRANSPARENT_DARK}, nodes={ - consumeables and {n=G.UIT.O, config={object = consumeables}} or {n=G.UIT.T, config={text = localize('k_none'), scale = 0.5, colour = G.C.UI.TEXT_LIGHT}}, - }} - }} - - local vouchers = CardArea(0,0, - 3*joker_size, - 0.6*G.CARD_H, - {card_limit = nil, - card_w = joker_size*G.CARD_W, type = 'title_2', spread = true, highlight_limit = 0}) - - if challenge.vouchers then - for k, v in ipairs(challenge.vouchers) do - local card = Card(0,0, G.CARD_W*joker_size, G.CARD_H*joker_size, nil, G.P_CENTERS[v.id], {bypass_discovery_center = true,bypass_discovery_ui = true, bypass_lock=true}) - if v.edition then card:set_edition({[v.edition] = true}, true, true) end - if v.eternal then card:set_eternal(true) end - vouchers:emplace(card) - end - end - - local voucher_col = {n=G.UIT.C, config={align = "cm", padding = 0.05, colour = G.C.L_BLACK, r = 0.1, maxh = 1.8}, nodes={ - {n=G.UIT.T, config={text = localize('k_vouchers_cap'), scale = 0.33, colour = G.C.UI.TEXT_LIGHT, vert = true, shadow = true}}, - {n=G.UIT.C, config={align = "cm", minh = 0.6*G.CARD_H, r = 0.1, colour = G.C.UI.TRANSPARENT_DARK}, nodes={ - vouchers and {n=G.UIT.O, config={object = vouchers}} or {n=G.UIT.T, config={text = localize('k_none'), scale = 0.5, colour = G.C.UI.TEXT_LIGHT}}, - }} - }} - - - - return {n=is_row and G.UIT.R or G.UIT.ROOT, config={align = "cm", r = 0.1, colour = G.C.BLACK}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ - joker_col, consumable_col, voucher_col - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - create_tabs( - {tabs = { - { - label = localize('b_rules'), - chosen = true, - tab_definition_function = G.UIDEF.challenge_description_tab, - tab_definition_function_args = {_id = _id, _tab = 'Rules'} - }, - { - label = localize('b_restrictions'), - tab_definition_function = G.UIDEF.challenge_description_tab, - tab_definition_function_args = {_id = _id, _tab = 'Restrictions'} - }, - { - label = localize('b_deck'), - tab_definition_function = G.UIDEF.challenge_description_tab, - tab_definition_function_args = {_id = _id, _tab = 'Deck'} - } - }, - tab_h = 5, - padding = 0, - text_scale = 0.36, - scale = 0.85, - no_shoulders = true, - no_loop = true} - )}}, - not is_row and {n=G.UIT.R, config={align = "cm", minh = 0.9}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1, minh = 0.7, minw = 9, r = 0.1, hover = true, colour = G.C.BLUE, button = "start_challenge_run", shadow = true, id = _id}, nodes={ - {n=G.UIT.T, config={text = localize('b_play_cap'), scale = 0.5, colour = G.C.UI.TEXT_LIGHT,func = 'set_button_pip', focus_args = {button = 'x',set_button_pip = true}}} - }} - }} or nil, - }} -end - -function G.UIDEF.challenge_description_tab(args) - args = args or {} - if args._tab == 'Rules' then - local challenge = G.CHALLENGES[args._id] - local start_rules = {} - local modded_starts = nil - local game_rules = {} - local starting_params = get_starting_params() - local base_modifiers = { - dollars = {value = starting_params.dollars, order = 6}, - discards = {value = starting_params.discards, order = 2}, - hands = {value = starting_params.hands, order = 1}, - reroll_cost = {value = starting_params.reroll_cost, order = 7}, - joker_slots = {value = starting_params.joker_slots, order = 4}, - consumable_slots = {value = starting_params.consumable_slots, order = 5}, - hand_size = {value = starting_params.hand_size, order = 3}, - } - local bonus_mods = 100 - if challenge.rules then - if challenge.rules.modifiers then - for k, v in ipairs(challenge.rules.modifiers) do - base_modifiers[v.id] = {value = v.value, order = base_modifiers[v.id] and base_modifiers[v.id].order or bonus_mods, custom = true, old_val = base_modifiers[v.id].value} - bonus_mods = bonus_mods + 1 - end - end - end - local nu_base_modifiers = {} - for k, v in pairs(base_modifiers) do - v.key = k - nu_base_modifiers[#nu_base_modifiers+1] = v - end - table.sort(nu_base_modifiers, function(a,b) return a.order < b.order end) - for k, v in ipairs(nu_base_modifiers) do - if v.old_val then - modded_starts = modded_starts or {} - modded_starts[#modded_starts+1] = {n=G.UIT.R, config={align = "cl", maxw = 3.5}, nodes= localize{type = 'text', key = 'ch_m_'..v.key, vars = {v.value}, default_col = G.C.L_BLACK}} - - else - start_rules[#start_rules+1] = {n=G.UIT.R, config={align = "cl", maxw =3.5}, nodes= localize{type = 'text', key = 'ch_m_'..v.key, vars = {v.value}, default_col = not v.custom and G.C.UI.TEXT_INACTIVE or nil}} - end - end - - if modded_starts then - start_rules = { - modded_starts and {n=G.UIT.R, config={align = "cl", padding = 0.05}, nodes=modded_starts} or nil, - {n=G.UIT.R, config={align = "cl", padding = 0.05, colour = G.C.GREY}, nodes={}}, - {n=G.UIT.R, config={align = "cl", padding = 0.05}, nodes=start_rules}, - } - end - - if challenge.rules then - if challenge.rules.custom then - for k, v in ipairs(challenge.rules.custom) do - game_rules[#game_rules+1] = {n=G.UIT.R, config={align = "cl"}, nodes= localize{type = 'text', key = 'ch_c_'..v.id, vars = {v.value}}} - end - end - end - if (not start_rules[1]) and (not modded_starts) then start_rules[#start_rules+1] = {n=G.UIT.R, config={align = "cl"}, nodes= localize{type = 'text', key = 'ch_m_none', vars = {}}} end - if not game_rules[1] then game_rules[#game_rules+1] = {n=G.UIT.R, config={align = "cl"}, nodes= localize{type = 'text', key = 'ch_c_none', vars = {}}} end - - local starting_rule_list = {n=G.UIT.C, config={align = "cm", minw = 3, r = 0.1, colour = G.C.BLUE}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.08, minh = 0.6}, nodes={ - {n=G.UIT.T, config={text = localize('k_game_modifiers'), scale = 0.4, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", minh = 4.1, minw = 4.2, padding = 0.05, r = 0.1, colour = G.C.WHITE}, nodes= start_rules} - }} - - local override_rule_list = {n=G.UIT.C, config={align = "cm", minw = 3, r = 0.1, colour = G.C.BLUE}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.08, minh = 0.6}, nodes={ - {n=G.UIT.T, config={text = localize('k_custom_rules'), scale = 0.4, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", minh = 4.1, minw = 6.8, maxw = 6.7, padding = 0.05, r = 0.1, colour = G.C.WHITE}, nodes= game_rules} - }} - - return {n=G.UIT.ROOT, config={align = "cm", padding = 0.05, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1, colour = G.C.L_BLACK, r = 0.1, minw = 3}, nodes={ - override_rule_list,starting_rule_list - }} - }} - elseif args._tab == 'Restrictions' then - local challenge = G.CHALLENGES[args._id] - - local banned_cards, banned_tags, banned_other = {}, {}, {} - - if challenge.restrictions then - if challenge.restrictions.banned_cards then - local row_cards = {} - local n_rows = math.max(1, math.floor(#challenge.restrictions.banned_cards/10) + 2 - math.floor(math.log(6, #challenge.restrictions.banned_cards))) - local max_width = 1 - for k, v in ipairs(challenge.restrictions.banned_cards) do - local _row = math.floor((k-1)*n_rows/(#challenge.restrictions.banned_cards)+1) - row_cards[_row] = row_cards[_row] or {} - row_cards[_row][#row_cards[_row]+1] = v - if #row_cards[_row] > max_width then max_width = #row_cards[_row] end - end - - local card_size = math.max(0.3, 0.75 - 0.01*(max_width*n_rows)) - - for _, row_card in ipairs(row_cards) do - local banned_card_area = CardArea( - 0,0, - 6.7, - 3.3/n_rows, - {card_limit = nil, type = 'title_2', view_deck = true, highlight_limit = 0, card_w = G.CARD_W*card_size}) - table.insert(banned_cards, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={object = banned_card_area}} - }} - ) - for k, v in ipairs(row_card) do - local card = Card(0,0, G.CARD_W*card_size, G.CARD_H*card_size, nil, G.P_CENTERS[v.id], {bypass_discovery_center = true,bypass_discovery_ui = true}) - banned_card_area:emplace(card) - end - end - end - if challenge.restrictions.banned_tags then - local tag_tab = {} - for k, v in pairs(challenge.restrictions.banned_tags) do - tag_tab[#tag_tab+1] = G.P_TAGS[v.id] - end - - table.sort(tag_tab, function (a, b) return a.order < b.order end) - - for k, v in ipairs(tag_tab) do - local temp_tag = Tag(v.key) - local temp_tag_ui = temp_tag:generate_UI(1.1 - 0.25*(math.sqrt(#challenge.restrictions.banned_tags))) - table.insert(banned_tags, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - temp_tag_ui - }} - ) - end - end - if challenge.restrictions.banned_other then - local other_tab = {} - for k, v in pairs(challenge.restrictions.banned_other) do - if v.type == 'blind' then - other_tab[#other_tab+1] = G.P_BLINDS[v.id] - end - end - - table.sort(other_tab, function (a, b) return a.order < b.order end) - - for k, v in ipairs(other_tab) do - local temp_blind = AnimatedSprite(0,0,1,1, G.ANIMATION_ATLAS[v.atlas or ''] or G.ANIMATION_ATLAS['blind_chips'], v.pos) - temp_blind:define_draw_steps({ - {shader = 'dissolve', shadow_height = 0.05}, - {shader = 'dissolve'} - }) - temp_blind.float = true - temp_blind.states.hover.can = true - temp_blind.states.drag.can = false - temp_blind.states.collide.can = true - temp_blind.config = {blind = v, force_focus = true} - temp_blind.hover = function() - if not G.CONTROLLER.dragging.target or G.CONTROLLER.using_touch then - if not temp_blind.hovering and temp_blind.states.visible then - temp_blind.hovering = true - temp_blind.hover_tilt = 3 - temp_blind:juice_up(0.05, 0.02) - play_sound('chips1', math.random()*0.1 + 0.55, 0.12) - temp_blind.config.h_popup = create_UIBox_blind_popup(v, true) - temp_blind.config.h_popup_config ={align = 'cl', offset = {x=-0.1,y=0},parent = temp_blind} - Node.hover(temp_blind) - end - end - end - temp_blind.stop_hover = function() temp_blind.hovering = false; Node.stop_hover(temp_blind); temp_blind.hover_tilt = 0 end - - table.insert(banned_other, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={object = temp_blind}} - }} - ) - end - end - end - if not banned_cards[1] then banned_cards[#banned_cards+1] = {n=G.UIT.R, config={align = "cl"}, nodes= localize{type = 'text', key = 'ch_m_none', vars = {}}} end - if not banned_tags[1] then banned_tags[#banned_tags+1] = {n=G.UIT.R, config={align = "cl"}, nodes= localize{type = 'text', key = 'ch_c_none', vars = {}}} end - if not banned_other[1] then banned_other[#banned_other+1] = {n=G.UIT.R, config={align = "cl"}, nodes= localize{type = 'text', key = 'ch_c_none', vars = {}}} end - - local banned_cards = {n=G.UIT.C, config={align = "cm", r = 0.1, colour = G.C.RED}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.08, minh = 0.6}, nodes={ - {n=G.UIT.T, config={text = localize('k_banned_cards'), scale = 0.4, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", minh = 4.1, minw =7.33, padding = 0.05, r = 0.1, colour = G.C.WHITE}, nodes= - banned_cards - } - }} - - local banned_tags = {n=G.UIT.C, config={align = "cm", r = 0.1, colour = G.C.RED}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.08, minh = 0.6, maxw = 1.48}, nodes={ - {n=G.UIT.T, config={text = localize('k_banned_tags'), scale = 0.3, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", minh = 4.1, minw = 1.48, padding = 0.05, r = 0.1, colour = G.C.WHITE}, nodes= - banned_tags} - }} - - local banned_other = {n=G.UIT.C, config={align = "cm", r = 0.1, colour = G.C.RED}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.08, minh = 0.6, maxw = 1.84}, nodes={ - {n=G.UIT.T, config={text = localize('k_other'), scale = 0.4, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - }}, - {n=G.UIT.R, config={align = "cm", minh = 4.1, minw = 2, padding = 0.05, r = 0.1, colour = G.C.WHITE}, nodes= - banned_other} - }} - - return {n=G.UIT.ROOT, config={align = "cm", padding = 0.05, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1, colour = G.C.L_BLACK, r = 0.1}, nodes={ - banned_cards, banned_tags, banned_other - }} - }} - elseif args._tab == 'Deck' then - local challenge = G.CHALLENGES[args._id] - local deck_tables = {} - local SUITS = {} - local suit_map = {} - for i = #SMODS.Suit.obj_buffer, 1, -1 do - local suit = SMODS.Suits[SMODS.Suit.obj_buffer[i]] - SUITS[suit.card_key] = {} - suit_map[#suit_map+1] = suit.card_key - end - local card_protos = nil - local _de = nil - if challenge then - _de = challenge.deck - end - - if _de and _de.cards then - card_protos = _de.cards - end - - if not card_protos then - card_protos = {} - for k, v in pairs(G.P_CARDS) do - local _r, _s = SMODS.Ranks[v.value].card_key, SMODS.Suits[v.suit].card_key - local keep, _e, _d, _g = true, nil, nil, nil - if type(SMODS.Ranks[v.value].in_pool) == 'function' and not SMODS.Ranks[v.value]:in_pool({initial_deck = true, suit = v.suit}) then - keep = false - end - if type(SMODS.Suits[v.suit].in_pool) == 'function' and not SMODS.Suits[v.suit]:in_pool({initial_deck = true, rank = v.value}) then - keep = false - end - if _de then - if _de.yes_ranks and not _de.yes_ranks[_r] then keep = false end - if _de.no_ranks and _de.no_ranks[_r] then keep = false end - if _de.yes_suits and not _de.yes_suits[_s] then keep = false end - if _de.no_suits and _de.no_suits[_s] then keep = false end - if _de.enhancement then _e = _de.enhancement end - if _de.edition then _d = _de.edition end - if _de.seal then _g = _de.seal end - end - - if keep then card_protos[#card_protos+1] = {s=_s,r=_r,e=_e,d=_d,g=_g} end - end - end - for k, v in ipairs(card_protos) do - local _card = Card(0,0, G.CARD_W*0.45, G.CARD_H*0.45, G.P_CARDS[v.s..'_'..v.r], G.P_CENTERS[v.e or 'c_base']) - if v.d then _card:set_edition({[v.d] = true}, true, true) end - if v.g then _card:set_seal(v.g, true, true) end - SUITS[v.s][#SUITS[v.s]+1] = _card - end - - local num_suits = 0 - for j = 1, #suit_map do - if SUITS[suit_map[j]][1] then num_suits = num_suits + 1 end - end - for j = 1, #suit_map do - if SUITS[suit_map[j]][1] then - table.sort(SUITS[suit_map[j]], function(a,b) return a:get_nominal() > b:get_nominal() end ) - local view_deck = CardArea( - 0,0, - 5.5*G.CARD_W, - (0.42 - (num_suits <= 4 and 0 or num_suits >= 8 and 0.28 or 0.07 * (num_suits - 4))) * G.CARD_H, - {card_limit = #SUITS[suit_map[j]], type = 'title_2', view_deck = true, highlight_limit = 0, card_w = G.CARD_W*0.5, draw_layers = {'card'}}) - table.insert(deck_tables, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={object = view_deck}} - }} - ) - - for i = 1, #SUITS[suit_map[j]] do - if SUITS[suit_map[j]][i] then - view_deck:emplace(SUITS[suit_map[j]][i]) - end - end - end - end - return {n=G.UIT.ROOT, config={align = "cm", padding = 0, colour = G.C.BLACK, r = 0.1, minw = 11.4, minh = 4.2}, nodes=deck_tables} - end -end - -function G.UIDEF.run_setup_option(type) - if not G.SAVED_GAME then - G.SAVED_GAME = get_compressed(G.SETTINGS.profile..'/'..'save.jkr') - if G.SAVED_GAME ~= nil then G.SAVED_GAME = STR_UNPACK(G.SAVED_GAME) end - end - - G.SETTINGS.current_setup = type - G.GAME.viewed_back = Back(get_deck_from_name(G.PROFILES[G.SETTINGS.profile].MEMORY.deck)) - - G.PROFILES[G.SETTINGS.profile].MEMORY.stake = G.PROFILES[G.SETTINGS.profile].MEMORY.stake or 1 - - if type == 'Continue' then - - G.viewed_stake = 1 - if G.SAVED_GAME ~= nil then - saved_game = G.SAVED_GAME - local viewed_deck = 'b_red' - for k, v in pairs(G.P_CENTERS) do - if v.name == saved_game.BACK.name then viewed_deck = k end - end - G.GAME.viewed_back:change_to(G.P_CENTERS[viewed_deck]) - G.viewed_stake = saved_game.GAME.stake or 1 - end - end - - if type == 'New Run' then - if G.OVERLAY_MENU then - local seed_toggle = G.OVERLAY_MENU:get_UIE_by_ID('run_setup_seed') - if seed_toggle then seed_toggle.states.visible = true end - end - G.viewed_stake = G.PROFILES[G.SETTINGS.profile].MEMORY.stake or 1 - G.FUNCS.change_stake({to_key = G.viewed_stake}) - else - G.run_setup_seed = nil - if G.OVERLAY_MENU then - local seed_toggle = G.OVERLAY_MENU:get_UIE_by_ID('run_setup_seed') - if seed_toggle then seed_toggle.states.visible = false end - end - end - - local area = CardArea( - G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, - G.CARD_W, - G.CARD_H, - {card_limit = 5, type = 'deck', highlight_limit = 0, deck_height = 0.75, thin_draw = 1}) - - for i = 1, 10 do - local card = Card(G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, G.CARD_W, G.CARD_H, pseudorandom_element(G.P_CARDS), G.P_CENTERS.c_base, {playing_card = i, viewed_back = true}) - card.sprite_facing = 'back' - card.facing = 'back' - area:emplace(card) - if i == 10 then G.sticker_card = card; card.sticker = get_deck_win_sticker(G.GAME.viewed_back.effect.center) end - end - - local ordered_names, viewed_deck = {}, 1 - for k, v in ipairs(G.P_CENTER_POOLS.Back) do - ordered_names[#ordered_names+1] = v.name - if v.name == G.GAME.viewed_back.name then viewed_deck = k end - end - - local lwidth, rwidth = 1.4, 1.8 - - local type_colour = G.C.BLUE - - local scale = 0.39 - G.setup_seed = '' - - local t = {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR, minh = 6.6, minw = 6}, nodes={ - type == 'Continue' and {n=G.UIT.R, config={align = "tm", minh = 3.8, padding = 0.15}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 3.3, minw = 6.8}, nodes={ - {n=G.UIT.C, config={align = "cm", colour = G.C.BLACK, padding = 0.15, r = 0.1, emboss = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", shadow = false}, nodes={ - {n=G.UIT.O, config={object = area}} - }}, - }},{n=G.UIT.C, config={align = "cm", minw = 4, maxw = 4, minh = 1.7, r = 0.1, colour = G.C.L_BLACK, padding = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", r = 0.1, minw = 4, maxw = 4, minh = 0.6}, nodes={ - {n=G.UIT.O, config={id = nil, func = 'RUN_SETUP_check_back_name', object = Moveable()}}, - }}, - {n=G.UIT.R, config={align = "cm", colour = G.C.WHITE,padding = 0.03, minh = 1.75, r = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = lwidth, maxw = lwidth}, nodes={{n=G.UIT.T, config={text = localize('k_round'),colour = G.C.UI.TEXT_DARK, scale = scale*0.8}}}}, - {n=G.UIT.C, config={align = "cm"}, nodes={{n=G.UIT.T, config={text = ': ',colour = G.C.UI.TEXT_DARK, scale = scale*0.8}}}}, - {n=G.UIT.C, config={align = "cl", minw = rwidth, maxw = lwidth}, nodes={{n=G.UIT.T, config={text = tostring(saved_game.GAME.round),colour = G.C.RED, scale = 0.8*scale}}}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = lwidth, maxw = lwidth}, nodes={{n=G.UIT.T, config={text = localize('k_ante'),colour = G.C.UI.TEXT_DARK, scale = scale*0.8}}}}, - {n=G.UIT.C, config={align = "cm"}, nodes={{n=G.UIT.T, config={text = ': ',colour = G.C.UI.TEXT_DARK, scale = scale*0.8}}}}, - {n=G.UIT.C, config={align = "cl", minw = rwidth, maxw = lwidth}, nodes={{n=G.UIT.T, config={text = tostring(saved_game.GAME.round_resets.ante),colour = G.C.BLUE, scale = 0.8*scale}}}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = lwidth, maxw = lwidth}, nodes={{n=G.UIT.T, config={text = localize('k_money'),colour = G.C.UI.TEXT_DARK, scale = scale*0.8}}}}, - {n=G.UIT.C, config={align = "cm"}, nodes={{n=G.UIT.T, config={text = ': ',colour = G.C.UI.TEXT_DARK, scale = scale*0.8}}}}, - {n=G.UIT.C, config={align = "cl", minw = rwidth, maxw = lwidth}, nodes={{n=G.UIT.T, config={text = localize('$')..format_ui_value(saved_game.GAME.dollars),colour = G.C.ORANGE, scale = 0.8*scale}}}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = lwidth, maxw = lwidth}, nodes={{n=G.UIT.T, config={text = localize('k_best_hand'),colour = G.C.UI.TEXT_DARK, scale = scale*0.8}}}}, - {n=G.UIT.C, config={align = "cm"}, nodes={{n=G.UIT.T, config={text = ': ',colour = G.C.UI.TEXT_DARK, scale = scale*0.8}}}}, - {n=G.UIT.C, config={align = "cl", minw = rwidth, maxw = lwidth}, nodes={{n=G.UIT.T, config={text = number_format(saved_game.GAME.round_scores.hand.amt),colour = G.C.RED, scale = scale_number(saved_game.GAME.round_scores.hand.amt, 0.8*scale, 100000000000)}}}} - }}, - saved_game.GAME.seeded and {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = lwidth, maxw = lwidth}, nodes={{n=G.UIT.T, config={text = localize('k_seed'),colour = G.C.UI.TEXT_DARK, scale = scale*0.8}}}}, - {n=G.UIT.C, config={align = "cm"}, nodes={{n=G.UIT.T, config={text = ': ',colour = G.C.UI.TEXT_DARK, scale = scale*0.8}}}}, - {n=G.UIT.C, config={align = "cl", minw = rwidth, maxw = lwidth}, nodes={{n=G.UIT.T, config={text = tostring(saved_game.GAME.pseudorandom.seed),colour = G.C.RED, scale = 0.8*scale}}}} - }} or nil, - }} - }}, - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={id = G.GAME.viewed_back.name, func = 'RUN_SETUP_check_back_stake_column', object = UIBox{definition = G.UIDEF.deck_stake_column(G.GAME.viewed_back.effect.center.key), config = {offset = {x=0,y=0}}}}} - }} - }} - }}}} or - {n=G.UIT.R, config={align = "cm", minh = 3.8}, nodes={ - create_option_cycle({options = ordered_names, opt_callback = 'change_viewed_back', current_option = viewed_deck, colour = G.C.RED, w = 3.5, mid = - {n=G.UIT.R, config={align = "cm", minh = 3.3, minw = 5}, nodes={ - {n=G.UIT.C, config={align = "cm", colour = G.C.BLACK, padding = 0.15, r = 0.1, emboss = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", shadow = false}, nodes={ - {n=G.UIT.O, config={object = area}} - }}, - }},{n=G.UIT.C, config={align = "cm", minh = 1.7, r = 0.1, colour = G.C.L_BLACK, padding = 0.1}, nodes={ - {n=G.UIT.R, config={align = "cm", r = 0.1, minw = 4, maxw = 4, minh = 0.6}, nodes={ - {n=G.UIT.O, config={id = nil, func = 'RUN_SETUP_check_back_name', object = Moveable()}}, - }}, - {n=G.UIT.R, config={align = "cm", colour = G.C.WHITE, minh = 1.7, r = 0.1}, nodes={ - {n=G.UIT.O, config={id = G.GAME.viewed_back.name, func = 'RUN_SETUP_check_back', object = UIBox{definition = G.GAME.viewed_back:generate_UI(), config = {offset = {x=0,y=0}}}}} - }} - }}, - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={id = G.GAME.viewed_back.name, func = 'RUN_SETUP_check_back_stake_column', object = UIBox{definition = G.UIDEF.deck_stake_column(G.GAME.viewed_back.effect.center.key), config = {offset = {x=0,y=0}}}}} - }} - }} - }} - }) - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - type == 'Continue' and {n=G.UIT.R, config={align = "cm", minh = 2.2, minw = 5}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.17}, nodes={}}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={id = nil, func = 'RUN_SETUP_check_stake', insta_func = true, object = Moveable()}}, - }} - }} - or {n=G.UIT.R, config={align = "cm", minh = 2.2, minw = 6.8}, nodes={ - {n=G.UIT.O, config={id = nil, func = 'RUN_SETUP_check_stake', insta_func = true, object = Moveable()}}, - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05, minh = 0.9}, nodes={ - {n=G.UIT.O, config={align = "cm", func = 'toggle_seeded_run', object = Moveable()}, nodes={ - }}, - }}, - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = 2.4, id = 'run_setup_seed'}, nodes={ - type == 'New Run' and create_toggle{col = true, label = localize('k_seeded_run'), label_scale = 0.25, w = 0, scale = 0.7, ref_table = G, ref_value = 'run_setup_seed'} or nil - }}, - {n=G.UIT.C, config={align = "cm", minw = 5, minh = 0.8, padding = 0.2, r = 0.1, hover = true, colour = G.C.BLUE, button = "start_setup_run", shadow = true, func = 'can_start_run'}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.T, config={text = localize('b_play_cap'), scale = 0.8, colour = G.C.UI.TEXT_LIGHT,func = 'set_button_pip', focus_args = {button = 'x',set_button_pip = true}}} - }} - }}, - {n=G.UIT.C, config={align = "cm", minw = 2.5}, nodes={}} - }} - }} - return t -end - -function create_button_binding_pip(args) - - local button_sprite_map = { - ['a'] = G.F_SWAP_AB_PIPS and 1 or 0, - ['b'] = G.F_SWAP_AB_PIPS and 0 or 1, - ['x'] = 2, - ['y'] = 3, - ['leftshoulder'] = 4, - ['rightshoulder'] = 5, - ['triggerleft'] = 6, - ['triggerright'] = 7, - ['start'] = 8, - ['back'] = 9, - ['dpadup'] = 10, - ['dpadright'] = 11, - ['dpaddown'] = 12, - ['dpadleft'] = 13, - ['left'] = 14, - ['right'] = 15, - ['leftstick'] = 16, - ['rightstick'] = 17, - ['guide'] = 19 - } - local BUTTON_SPRITE = Sprite(0,0,args.scale or 0.45,args.scale or 0.45,G.ASSET_ATLAS["gamepad_ui"], - {x=button_sprite_map[args.button], - y=G.CONTROLLER.GAMEPAD_CONSOLE == 'Nintendo' and 2 or G.CONTROLLER.GAMEPAD_CONSOLE == 'Playstation' and (G.F_PS4_PLAYSTATION_GLYPHS and 3 or 1) or 0}) - - return {n=G.UIT.ROOT, config = {align = 'cm', colour = G.C.CLEAR}, nodes={ - {n=G.UIT.O, config={object = BUTTON_SPRITE}}, - }} -end - -function create_UIBox_profile_button() - - local letters = {} - if G.F_DISP_USERNAME then - for _, c in utf8.chars(G.F_DISP_USERNAME) do - local _char = c - local leng = G.LANGUAGES['all1'].font.FONT:hasGlyphs(c) - letters[#letters+1] = {n=G.UIT.T, config={lang = G.LANGUAGES[leng and 'all1' or 'all2'],text = _char, scale = 0.3, colour = mix_colours(G.C.GREEN, G.C.WHITE, 0.7), shadow = true}} - end - end - - if not G.PROFILES[G.SETTINGS.profile].name then - G.PROFILES[G.SETTINGS.profile].name = "P"..G.SETTINGS.profile - end - - return {n=G.UIT.ROOT, config = {align = "cm", colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.2, r = 0.1, emboss = 0.1, colour = G.C.L_BLACK}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = localize('k_profile'), scale = 0.4, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.15, minw = 2, minh = 0.8, maxw = 2, r = 0.1, hover = true, colour = mix_colours(G.C.WHITE, G.C.GREY, 0.2), button = 'profile_select', shadow = true}, nodes={ - {n=G.UIT.T, config={ref_table = G.PROFILES[G.SETTINGS.profile], ref_value = 'name', scale = 0.4, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }}, - }} - }}, - G.F_DISP_USERNAME and {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = localize('k_playing_as'), scale = 0.3, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.12}, nodes={}}, - {n=G.UIT.R, config={align = "cm", maxw = 2}, nodes=letters} - }} or nil, - }} -end - -function create_UIBox_main_menu_buttons() - local text_scale = 0.45 - local language = nil - if not G.F_ENGLISH_ONLY then - language = Sprite(0,0,0.6,0.6,G.ASSET_ATLAS["icons"], {x=2, y=0}) - language.states.drag.can = false - end - local discord = nil - local twitter = nil - if G.F_DISCORD then - discord = Sprite(0,0,0.6,0.6,G.ASSET_ATLAS["icons"], {x=0, y=0}) - discord.states.drag.can = false - twitter = Sprite(0,0,0.6,0.6,G.ASSET_ATLAS["icons"], {x=0, y=1}) - twitter.states.drag.can = false - end - - local quit_func = 'quit' - - local t = { - n=G.UIT.ROOT, config = {align = "cm",colour = G.C.CLEAR}, nodes={ - {n=G.UIT.C, config={align = "bm"}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.2, r = 0.1, emboss = 0.1, colour = G.C.L_BLACK, mid = true}, nodes={ - UIBox_button{id = 'main_menu_play', button = not G.SETTINGS.tutorial_complete and "start_run" or "setup_run", colour = G.C.BLUE, minw = 3.65, minh = 1.55, label = {localize('b_play_cap')}, scale = text_scale*2, col = true}, - {n=G.UIT.C, config={align = "cm"}, nodes={ - UIBox_button{button = 'options', colour = G.C.ORANGE, minw = 2.65, minh = 1.35, label = {localize('b_options_cap')}, scale = text_scale * 1.2, col = true}, - G.F_QUIT_BUTTON and {n=G.UIT.C, config={align = "cm", minw = 0.2}, nodes={}} or nil, - G.F_QUIT_BUTTON and UIBox_button{button = quit_func, colour = G.C.RED, minw = 2.65, minh = 1.35, label = {localize('b_quit_cap')}, scale = text_scale * 1.2, col = true} or nil, - }}, - UIBox_button{id = 'collection_button', button = "your_collection", colour = G.C.PALE_GREEN, minw = 3.65, minh = 1.55, label = {localize('b_collection_cap')}, scale = text_scale*1.5, col = true}, - }}, - }}, - {n=G.UIT.C, config={align = "br", minw = 3.2, padding = 0.1}, nodes={ - G.F_DISCORD and {n=G.UIT.R, config = {align = "cm", padding = 0.2}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1, r = 0.1, hover = true, colour = mix_colours(G.C.BLUE, G.C.GREY, 0.4), button = 'go_to_discord', shadow = true}, nodes={ - {n=G.UIT.O, config={object = discord}}, - }}, - {n=G.UIT.C, config={align = "cm", padding = 0.1, r = 0.1, hover = true, colour = G.C.BLACK, button = 'go_to_twitter', shadow = true}, nodes={ - {n=G.UIT.O, config={object = twitter}}, - }} - }} or nil, - not G.F_ENGLISH_ONLY and {n=G.UIT.R, config = {align = "cm", padding = 0.2, r = 0.1, emboss = 0.1, colour = G.C.L_BLACK}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.15, minw = 1, r = 0.1, hover = true, colour = mix_colours(G.C.WHITE, G.C.GREY, 0.2), button = 'language_selection', shadow = true}, nodes={ - {n=G.UIT.O, config={object = language}}, - {n=G.UIT.T, config={text = G.LANG.label, scale = 0.4, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }} - }} or nil, - }}, - }} - return t -end - -function create_UIBox_main_menu_competittion_name() - G.SETTINGS.COMP.name = '' - local t = { - n=G.UIT.ROOT, config = {align = "cm",colour = G.C.CLEAR}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.2, r = 0.1, emboss = 0.1, colour = G.C.L_BLACK, mid = true}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - create_text_input({ - w = 4, max_length = 16,prompt_text = 'Enter Name', - ref_table = G.SETTINGS.COMP, ref_value = 'name' - }), - }}, - UIBox_button{button = "confirm_contest_name", colour = G.C.PALE_GREEN, minw = 2.65, minh = 1, label = {'Confirm'}, scale = 0.5}, - }}, - }} - return t -end - -function G.UIDEF.language_selector() - local rows = {} - local langs = {} - for k, v in pairs(G.LANGUAGES) do - if not v.omit then - langs[#langs+1] = v - end - end - table.sort(langs, (function(a, b) return a.label < b.label end)) - local _row = {} - for k, v in ipairs(langs) do - if not G.F_HIDE_BETA_LANGS or (not v.beta) then - _row[#_row+1] = {n=G.UIT.C, config={align = "cm", func = 'beta_lang_alert', padding = 0.05, r = 0.1, minh = 0.7, minw = 4.5, button = v.beta and 'warn_lang' or 'change_lang', ref_table = v, colour = v.beta and G.C.RED or G.C.BLUE, hover = true, shadow = true, focus_args = {snap_to = (k == 1)}}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = v.label, lang = v, scale = 0.45, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }} - }} - end - if _row[3] or (k == #langs) then - rows[#rows+1] = {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes=_row} - _row = {} - end - end - - local discord = nil - discord = Sprite(0,0,0.6,0.6,G.ASSET_ATLAS["icons"], {x=2, y=0}) - discord.states.drag.can = false - - local t = create_UIBox_generic_options({contents ={ - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes=rows}, - G.F_EXTERNAL_LINKS and {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.1, minw = 4, maxw = 4, r = 0.1, minh = 0.8, hover = true, colour = mix_colours(G.C.GREEN, G.C.GREY, 0.4), button = 'loc_survey', shadow = true}, nodes={ - {n=G.UIT.O, config={object = discord}}, - {n=G.UIT.T, config={text = G.LANG.button, scale = 0.45, colour = G.C.UI.TEXT_LIGHT, shadow = true}} - }}, - }} or nil - }}) - return t -end - -function create_UIBox_highlight(rect) - local t = {n=G.UIT.ROOT, config = {align = "cm", minh = rect.T.h+0.1, minw = rect.T.w+0.15, r = 0.15, colour = G.C.DARK_EDITION}, nodes={ - }} -return t -end - -function create_UIBox_generic_options(args) - args = args or {} - local back_func = args.back_func or "exit_overlay_menu" - local contents = args.contents or ({n=G.UIT.T, config={text = "EMPTY",colour = G.C.UI.RED, scale = 0.4}}) - if args.infotip then - G.E_MANAGER:add_event(Event({ - blocking = false, - blockable = false, - timer = 'REAL', - func = function() - if G.OVERLAY_MENU then - local _infotip_object = G.OVERLAY_MENU:get_UIE_by_ID('overlay_menu_infotip') - if _infotip_object then - _infotip_object.config.object:remove() - _infotip_object.config.object = UIBox{ - definition = overlay_infotip(args.infotip), - config = {offset = {x=0,y=0}, align = 'bm', parent = _infotip_object} - } - end - end - return true - end - })) - end - - return {n=G.UIT.ROOT, config = {align = "cm", minw = G.ROOM.T.w*5, minh = G.ROOM.T.h*5,padding = 0.1, r = 0.1, colour = args.bg_colour or {G.C.GREY[1], G.C.GREY[2], G.C.GREY[3],0.7}}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 1,r = 0.3, padding = 0.07, minw = 1, colour = args.outline_colour or G.C.JOKER_GREY, emboss = 0.1}, nodes={ - {n=G.UIT.C, config={align = "cm", minh = 1,r = 0.2, padding = 0.2, minw = 1, colour = args.colour or G.C.L_BLACK}, nodes={ - {n=G.UIT.R, config={align = "cm",padding = args.padding or 0.2, minw = args.minw or 7}, nodes= - contents - }, - not args.no_back and {n=G.UIT.R, config={id = args.back_id or 'overlay_menu_back_button', align = "cm", minw = 2.5, button_delay = args.back_delay, padding =0.1, r = 0.1, hover = true, colour = args.back_colour or G.C.ORANGE, button = back_func, shadow = true, focus_args = {nav = 'wide', button = 'b', snap_to = args.snap_back}}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0, no_fill = true}, nodes={ - {n=G.UIT.T, config={id = args.back_id or nil, text = args.back_label or localize('b_back'), scale = 0.5, colour = G.C.UI.TEXT_LIGHT, shadow = true, func = not args.no_pip and 'set_button_pip' or nil, focus_args = not args.no_pip and {button = args.back_button or 'b'} or nil}} - }} - }} or nil - }}, - }}, - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={id = 'overlay_menu_infotip', object = Moveable()}}, - }}, - }} -end - -function UIBox_dyn_container(inner_table, horizontal, colour_override, background_override, flipped, padding) - return {n=G.UIT.R, config = {align = "cm", padding= 0.03, colour = G.C.UI.TRANSPARENT_DARK, r=0.1}, nodes={ - {n=G.UIT.R, config = {align = "cm", padding= 0.05, colour = colour_override or G.C.DYN_UI.MAIN, r=0.1}, nodes={ - {n=G.UIT.R, config={align = horizontal and "cl" or (flipped and 'bm' or "tm"), colour = background_override or G.C.DYN_UI.BOSS_DARK, minw = horizontal and 100 or 0, minh = horizontal and 0 or 30, r=0.1, padding = padding or 0.08}, nodes= - inner_table - }}}}} -end - -function simple_text_container(_loc, args) - if not _loc then return nil end - args = args or {} - local container = {} - local loc_result = localize(_loc) - if loc_result and type(loc_result) == 'table' then - for k, v in ipairs(loc_result) do - container[#container+1] = - {n=G.UIT.R, config = {align = "cm", padding= 0}, nodes={ - {n=G.UIT.T, config={text = v, scale = args.scale or 0.35, colour = args.colour or G.C.UI.TEXT_DARK, shadow = args.shadow}} - }} - end - return {n=args.col and G.UIT.C or G.UIT.R, config = {align = "cm", padding= args.padding or 0.03}, nodes=container} - end -end - -function UIBox_button(args) - args = args or {} - args.button = args.button or "exit_overlay_menu" - args.func = args.func or nil - args.colour = args.colour or G.C.RED - args.choice = args.choice or nil - args.chosen = args.chosen or nil - args.label = args.label or {'LABEL'} - args.minw = args.minw or 2.7 - args.maxw = args.maxw or (args.minw - 0.2) - if args.minw < args.maxw then args.maxw = args.minw - 0.2 end - args.minh = args.minh or 0.9 - args.scale = args.scale or 0.5 - args.focus_args = args.focus_args or nil - args.text_colour = args.text_colour or G.C.UI.TEXT_LIGHT - local but_UIT = args.col == true and G.UIT.C or G.UIT.R - - local but_UI_label = {} - - local button_pip = nil - if args.dynamic_label then - but_UI_label = {} - - table.insert(but_UI_label, {n=G.UIT.R, config={align = "cm", padding = 0, minw = args.minw, maxw = args.maxw}, nodes={ - {n=G.UIT.T, config={ref_table = args.dynamic_label, ref_value = 'text', scale = args.scale, colour = args.text_colour, shadow = args.shadow, focus_args = button_pip and args.focus_args or nil, func = button_pip,}} - }}) - end - for k, v in ipairs(args.label) do - if k == #args.label and args.focus_args and args.focus_args.set_button_pip then - button_pip ='set_button_pip' - end - table.insert(but_UI_label, {n=G.UIT.R, config={align = "cm", padding = 0, minw = args.minw, maxw = args.maxw}, nodes={ - {n=G.UIT.T, config={text = v, scale = args.scale, colour = args.text_colour, shadow = args.shadow, focus_args = button_pip and args.focus_args or nil, func = button_pip, ref_table = args.ref_table}} - }}) - end - - if args.count then - table.insert(but_UI_label, - {n=G.UIT.R, config={align = "cm", minh = 0.4}, nodes={ - {n=G.UIT.T, config={scale = 0.35,text = args.count.tally..' / '..args.count.of, colour = {1,1,1,0.9}}} - }} - ) - end - - return - {n= but_UIT, config = {align = 'cm'}, nodes={ - {n= G.UIT.C, config={ - align = "cm", - padding = args.padding or 0, - r = 0.1, - hover = true, - colour = args.ref_table and args.ref_table.colour or args.colour, -- Cartomancer - one_press = args.one_press, - button = (args.button ~= 'nil') and args.button or nil, - choice = args.choice, - chosen = args.chosen, - focus_args = args.focus_args, - minh = args.minh - 0.3*(args.count and 1 or 0), - shadow = true, - func = args.func, - id = args.id, - back_func = args.back_func, - ref_table = args.ref_table, - mid = args.mid - }, nodes= - args.ref_table and args.ref_table.custom_button or but_UI_label -- Cartomancer - }}} -end diff --git a/lovely/dump/functions/button_callbacks.lua b/lovely/dump/functions/button_callbacks.lua deleted file mode 100644 index ca7e464..0000000 --- a/lovely/dump/functions/button_callbacks.lua +++ /dev/null @@ -1,3246 +0,0 @@ -LOVELY_INTEGRITY = '4a318253e70cba949d05bfb650e28bf79699539c4f0e57a07f3ad3d649a8688b' - ---Moves the tutorial to the next step in queue --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.tut_next = function(e) - if G.OVERLAY_TUTORIAL then - G.OVERLAY_TUTORIAL.Jimbo:remove_button() - G.OVERLAY_TUTORIAL.Jimbo:remove_speech_bubble() - G.OVERLAY_TUTORIAL.step_complete = false - G.OVERLAY_TUTORIAL.step = G.OVERLAY_TUTORIAL.step+1 - end -end - ---Ensures the compatibility indicator for the Blueprint and Brainstorm Jokers ---matches with any new changes of compatibility determined by the Joker --- ----@param e {} ---**e** Is the UIE that called this function\ ---**e.config.ref_table** points to the joker -G.FUNCS.blueprint_compat = function(e) - if e.config.ref_table.ability.blueprint_compat ~= e.config.ref_table.ability.blueprint_compat_check then - if e.config.ref_table.ability.blueprint_compat == 'compatible' then - e.config.colour = mix_colours(G.C.GREEN, G.C.JOKER_GREY, 0.8) - elseif e.config.ref_table.ability.blueprint_compat == 'incompatible' then - e.config.colour = mix_colours(G.C.RED, G.C.JOKER_GREY, 0.8) - end - e.config.ref_table.ability.blueprint_compat_ui = ' '..localize('k_'..e.config.ref_table.ability.blueprint_compat)..' ' - e.config.ref_table.ability.blueprint_compat_check = e.config.ref_table.ability.blueprint_compat - end -end - ---Sorts G.hand in descending order by suit (spades, hearts, clubs, diamonds, then rank) --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.sort_hand_suit = function(e) - G.hand:sort('suit desc') - play_sound('paper1') -end - ---Sorts G.hand in descending order by rank (rank, then spades, hearts, clubs, diamonds) --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.sort_hand_value = function(e) - G.hand:sort('desc') - play_sound('paper1') -end - ---Checks if the cost of a non voucher card is greater than what the player can afford and changes the ---buy button visuals accordingly --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.can_buy = function(e) - if (e.config.ref_table.cost > G.GAME.dollars - G.GAME.bankrupt_at) and (e.config.ref_table.cost > 0) then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - e.config.colour = G.C.ORANGE - e.config.button = 'buy_from_shop' - end - if e.config.ref_parent and e.config.ref_parent.children.buy_and_use then - if e.config.ref_parent.children.buy_and_use.states.visible then - e.UIBox.alignment.offset.y = -0.6 - else - e.UIBox.alignment.offset.y = 0 - end - end -end - ---Checks if the cost of a non voucher card is greater than what the player can afford and changes the ---buy button visuals accordingly --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.can_buy_and_use = function(e) - if (((e.config.ref_table.cost > G.GAME.dollars - G.GAME.bankrupt_at) and (e.config.ref_table.cost > 0)) or (not e.config.ref_table:can_use_consumeable())) then - e.UIBox.states.visible = false - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - if e.config.ref_table.highlighted then - e.UIBox.states.visible = true - end - e.config.colour = G.C.SECONDARY_SET.Voucher - e.config.button = 'buy_from_shop' - end -end - ---Checks if the cost of a voucher card is greater than what the player can afford and changes the ---redeem button visuals accordingly --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.can_redeem = function(e) - if e.config.ref_table.cost > G.GAME.dollars - G.GAME.bankrupt_at then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - e.config.colour = G.C.GREEN - e.config.button = 'use_card' - end -end - ---Checks if the cost of a booster pack is too much ---adjusts booster button visuals accordingly --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.can_open = function(e) - if (e.config.ref_table.cost) > 0 and (e.config.ref_table.cost > G.GAME.dollars - G.GAME.bankrupt_at) then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - e.config.colour = G.C.GREEN - e.config.button = 'use_card' - end -end - ---ensures that the HUD blind section is only visible when there is an active blind --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.HUD_blind_visible = function(e) - if G.GAME.blind and (G.GAME.blind.name ~= '' and G.GAME.blind.blind_set) then - G.GAME.blind.states.visible = true - elseif G.GAME.blind then - G.GAME.blind.states.visible = false - end -end - ---Expands or contracts the 'debuff text' area of the blind HUD when it changes, ---either bigger with a new boss or smaller when it is disabled, or for a smaller blind --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.HUD_blind_debuff = function(e) - if G.GAME.blind and G.GAME.blind.loc_debuff_text and G.GAME.blind.loc_debuff_text ~= '' then - if e.parent.config.minh == 0 or e.config.prev_loc ~= G.GAME.blind.loc_debuff_text then - e.parent.config.minh = 0.35 - e.config.scale = 0.36 - if G.GAME.blind.loc_debuff_lines[e.config.ref_value] == '' then e.config.scale = 0.0; e.parent.config.minh = 0.001 end - e.config.prev_loc = G.GAME.blind.loc_debuff_text - e.UIBox:recalculate(true) - end - else - if e.parent.config.minh > 0 then - e.parent.config.minh = 0 - e.config.scale = 0 - e.UIBox:recalculate(true) - end - end -end - ---Adds the prefix for the debuff text for the wheel blind --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.HUD_blind_debuff_prefix = function(e) - if (G.GAME.blind and G.GAME.blind.name == 'The Wheel' and not G.GAME.blind.disabled) or - e.config.id == 'bl_wheel' then - e.config.ref_table.val = ''..G.GAME.probabilities.normal - e.config.scale = 0.32 - else - e.config.ref_table.val = '' - e.config.scale = 0 - end -end - -G.FUNCS.HUD_blind_reward = function(e) - if G.GAME.modifiers.no_blind_reward and (G.GAME.blind and G.GAME.modifiers.no_blind_reward[G.GAME.blind:get_type()]) then - if e.config.minh > 0.44 then - e.config.minh = 0.4 - e.children[1].config.text = localize('k_no_reward') - --e.children[2].states.visible = false - e.UIBox:recalculate(true) - end - else - if e.config.minh < 0.45 then - e.config.minh = 0.45 - e.children[1].config.text = localize('k_reward')..': ' - e.children[2].states.visible = true - e.UIBox:recalculate(true) - end - end -end - ---Determines if there is a valid save file to load and continue from main menu --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.can_continue = function(e) - if e.config.func then --refers to this function, or 'can_continue', so this doesn't run repeatedly - local _can_continue = nil - local savefile = love.filesystem.getInfo(G.SETTINGS.profile..'/'..'save.jkr') - if savefile == nil then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - if not G.SAVED_GAME then - G.SAVED_GAME = get_compressed(G.SETTINGS.profile..'/'..'save.jkr') - if G.SAVED_GAME ~= nil then G.SAVED_GAME = STR_UNPACK(G.SAVED_GAME) end - if G.SAVED_GAME == nil then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - return _can_continue - end - end - if not G.SAVED_GAME or not G.SAVED_GAME.VERSION or G.SAVED_GAME.VERSION < '0.9.2' then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - _can_continue = true - end - end - e.config.func = nil - return _can_continue - end -end - -G.FUNCS.can_load_profile = function(e) - if G.SETTINGS.profile == G.focused_profile then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - e.config.colour = G.C.BLUE - e.config.button = 'load_profile' - end -end - -G.FUNCS.load_profile = function(delete_prof_data) - G.SAVED_GAME = nil - G.E_MANAGER:clear_queue() - G.FUNCS.wipe_on() - G.E_MANAGER:add_event(Event({ - no_delete = true, - func = function() - G:delete_run() - local _name = nil - if G.PROFILES[G.focused_profile].name and G.PROFILES[G.focused_profile].name ~= '' then - _name = G.PROFILES[G.focused_profile].name - end - if delete_prof_data then G.PROFILES[G.focused_profile] = {} end - G.DISCOVER_TALLIES = nil - G.PROGRESS = nil - G:load_profile(G.focused_profile) - G.PROFILES[G.focused_profile].name = _name - G:init_item_prototypes() - return true - end - })) - G.E_MANAGER:add_event(Event({ - no_delete = true, - blockable = true, - blocking = false, - func = function() - G:main_menu() - G.FILE_HANDLER.force = true - return true - end - })) - G.FUNCS.wipe_off() -end - -G.FUNCS.can_delete_profile = function(e) - G.CHECK_PROFILE_DATA = G.CHECK_PROFILE_DATA or love.filesystem.getInfo(G.focused_profile..'/'..'profile.jkr') - if (not G.CHECK_PROFILE_DATA) or e.config.disable_button then - G.CHECK_PROFILE_DATA = false - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - e.config.colour = G.C.RED - e.config.button = 'delete_profile' - end -end - -G.FUNCS.delete_profile = function(e) - local warning_text = e.UIBox:get_UIE_by_ID('warning_text') - if warning_text.config.colour ~= G.C.WHITE then - warning_text:juice_up() - warning_text.config.colour = G.C.WHITE - warning_text.config.shadow = true - e.config.disable_button = true - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.06, blockable = false, blocking = false, func = function() - play_sound('tarot2', 0.76, 0.4);return true end})) - - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.35, blockable = false, blocking = false, func = function() - e.config.disable_button = nil;return true end})) - - play_sound('tarot2', 1, 0.4) - else - love.filesystem.remove(G.focused_profile..'/'..'profile.jkr') - love.filesystem.remove(G.focused_profile..'/'..'save.jkr') - love.filesystem.remove(G.focused_profile..'/'..'meta.jkr') - love.filesystem.remove(G.focused_profile..'/'..'unlock_notify.jkr') - love.filesystem.remove(G.focused_profile..'') - G.SAVED_GAME = nil - G.DISCOVER_TALLIES = nil - G.PROGRESS = nil - G.PROFILES[G.focused_profile] = {} - if G.focused_profile == G.SETTINGS.profile then - G.FUNCS.load_profile(true) - else - local tab_but = G.OVERLAY_MENU:get_UIE_by_ID('tab_but_'..G.focused_profile) - G.FUNCS.change_tab(tab_but) - end - end -end - -G.FUNCS.can_unlock_all = function(e) - if G.PROFILES[G.SETTINGS.profile].all_unlocked or e.config.disable_button then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - e.config.colour = G.C.GREY - e.config.button = 'unlock_all' - end -end - -G.FUNCS.unlock_all = function(e) - local _infotip_object = G.OVERLAY_MENU:get_UIE_by_ID('overlay_menu_infotip') - - if (not _infotip_object.config.set) and (not G.F_NO_ACHIEVEMENTS) then - _infotip_object.config.object:remove() - _infotip_object.config.object = UIBox{ - definition = overlay_infotip(localize(G.F_TROPHIES and 'ml_unlock_all_trophies' or 'ml_unlock_all_explanation')), - config = {offset = {x=0,y=0}, align = 'bm', parent = _infotip_object} - } - _infotip_object.config.object.UIRoot:juice_up() - _infotip_object.config.set = true - e.config.disable_button = true - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.06, blockable = false, blocking = false, func = function() - play_sound('tarot2', 0.76, 0.4);return true end})) - - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.35, blockable = false, blocking = false, func = function() - e.config.disable_button = nil;return true end})) - - play_sound('tarot2', 1, 0.4) - else - G.PROFILES[G.SETTINGS.profile].all_unlocked = true - for k, v in pairs(G.P_CENTERS) do - if not v.demo and not v.wip then - v.alerted = true - v.discovered = true - v.unlocked = true - end - end - for k, v in pairs(G.P_BLINDS) do - if not v.demo and not v.wip then - v.alerted = true - v.discovered = true - v.unlocked = true - end - end - for k, v in pairs(G.P_TAGS) do - if not v.demo and not v.wip then - v.alerted = true - v.discovered = true - v.unlocked = true - end - end - set_profile_progress() - set_discover_tallies() - G:save_progress() - G.FILE_HANDLER.force = true - - local tab_but = G.OVERLAY_MENU:get_UIE_by_ID('tab_but_'..G.focused_profile) - G.FUNCS.change_tab(tab_but) - end -end - ---Creates an alert on this UIE if the round score for this id is a career high score --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.high_score_alert = function(e) - if e.config.id and not e.children.alert then - if G.GAME.round_scores[e.config.id] and G.GAME.round_scores[e.config.id].high_score then - e.children.alert = UIBox{ - definition = create_UIBox_card_alert({no_bg = true,text = localize('k_high_score_ex'), scale = 0.3}), - config = { - instance_type = 'ALERT', - align="tri", - offset = {x = 0.3, y = -0.18}, - major = e, parent = e} - } - e.children.alert.states.collide.can = false - end - end -end - -G.FUNCS.beta_lang_alert = function(e) - if not e.children.alert then - if e.config.ref_table and e.config.ref_table.beta then - e.children.alert = UIBox{ - definition = create_UIBox_card_alert({no_bg = true, text = 'BETA', scale = 0.35}), - config = { - instance_type = 'ALERT', - align="tri", - offset = {x = 0.07, y = -0.07}, - major = e, parent = e} - } - e.children.alert.states.collide.can = false - end - end -end - ---Creates a binding pip on this UIE if controller is being used --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.set_button_pip = function(e) - if G.CONTROLLER.HID.controller and e.config.focus_args and not e.children.button_pip then - e.children.button_pip = UIBox{ - definition = create_button_binding_pip{button = e.config.focus_args.button, scale = e.config.focus_args.scale}, - config = { - align= e.config.focus_args.orientation or 'cr', - offset = e.config.focus_args.offset or e.config.focus_args.orientation == 'bm' and {x = 0, y = 0.02} or {x = 0.1, y = 0.02}, - major = e, parent = e} - } - e.children.button_pip.states.collide.can = false - end - if not G.CONTROLLER.HID.controller and e.children.button_pip then - e.children.button_pip:remove() - e.children.button_pip = nil - end -end - ---Flashes text input cursor for the hooked text input, otherwise sets the width and alpha to 0 --- ----@param e {} ---**e** Is the UIE cursor that called this function -G.FUNCS.flash = function(e) - if G.CONTROLLER.text_input_hook and G.CONTROLLER.text_input_id == e.config.id:sub(1,string.len(G.CONTROLLER.text_input_id)) then - if (math.floor(G.TIMERS.REAL*2))%2 == 1 then - e.config.colour[4] = 0 - else - e.config.colour[4] = 1 - end - if e.config.w ~= 0.1 then e.config.w = 0.1; e.UIBox:recalculate(true) end - else - e.config.colour[4] = 0 - if e.config.w ~= 0 then e.config.w = 0; e.UIBox:recalculate(true) end - end -end - ---highlights/lowlights the pips for any dynatext with multiple values based on which one is displaying --- ----@param e {} ---**e** Is the dynatext that called this function -G.FUNCS.pip_dynatext = function(e) - if 'pip_'..tostring(e.config.ref_table.focused_string) == e.config.id then - if e.config.pip_state ~= 1 then - e.config.colour = e.config.pipcol1 - e.config.pip_state = 1 - end - elseif e.config.pip_state ~= 2 then - e.config.colour = e.config.pipcol2 - e.config.pip_state = 2 - end -end - ---for the toggle --- ----@param e {} ---**e** Is the slider UIE that called this function -function G.FUNCS.toggle_button(e) - e.config.ref_table.ref_table[e.config.ref_table.ref_value] = not e.config.ref_table.ref_table[e.config.ref_table.ref_value] - if e.config.toggle_callback then - e.config.toggle_callback(e.config.ref_table.ref_table[e.config.ref_table.ref_value]) - end -end - ---for the toggle --- ----@param e {} ---**e** Is the slider UIE that called this function -function G.FUNCS.toggle(e) - if not e.config.ref_table.ref_table[e.config.ref_table.ref_value] and e.config.toggle_active then - e.config.toggle_active = nil - e.config.colour = e.config.ref_table.inactive_colour - e.children[1].states.visible = false - e.children[1].config.object.states.visible = false - elseif e.config.ref_table.ref_table[e.config.ref_table.ref_value] and not e.config.toggle_active then - e.config.toggle_active = true - e.config.colour = e.config.ref_table.active_colour - e.children[1].states.visible = true - e.children[1].config.object.states.visible = true - end - -end - - ---Modifies the slider value if it is being dragged. e contains the 'container' for the bar and ---c contains the 'child' for the bar. either can be dragged. The value is lerped between the size ---of the child bar and the parent bar depending on any min/max values. Also changes the display text for the slider. --- ----@param e {} ---**e** Is the slider UIE that called this function -function G.FUNCS.slider(e) - local c = e.children[1] - e.states.drag.can = true - c.states.drag.can = true - if G.CONTROLLER and G.CONTROLLER.dragging.target and - (G.CONTROLLER.dragging.target == e or - G.CONTROLLER.dragging.target == c) then - local rt = c.config.ref_table - rt.ref_table[rt.ref_value] = math.min(rt.max,math.max(rt.min, rt.min + (rt.max - rt.min)*(G.CURSOR.T.x - e.parent.T.x - G.ROOM.T.x)/e.T.w)) - rt.text = string.format("%."..tostring(rt.decimal_places).."f", rt.ref_table[rt.ref_value]) - c.T.w = (rt.ref_table[rt.ref_value] - rt.min)/(rt.max - rt.min)*rt.w - c.config.w = c.T.w - if rt.callback then G.FUNCS[rt.callback](rt) end - end -end - ---Modifies the slider value descreetly by percentage ---c contains the 'child' for the bar. either can be dragged. The value is lerped between the size ---of the child bar and the parent bar depending on any min/max values. Also changes the display text for the slider. --- ----@param e {} ---**e** Is the slider UIE that called this function -function G.FUNCS.slider_descreet(e, per) - local c = e.children[1] - e.states.drag.can = true - c.states.drag.can = true - if per then - local rt = c.config.ref_table - rt.ref_table[rt.ref_value] = math.min(rt.max,math.max(rt.min, rt.ref_table[rt.ref_value] + per*(rt.max - rt.min))) - rt.text = string.format("%."..tostring(rt.decimal_places).."f", rt.ref_table[rt.ref_value]) - c.T.w = (rt.ref_table[rt.ref_value] - rt.min)/(rt.max - rt.min)*rt.w - c.config.w = c.T.w - end -end - ---When clicked, changes the selected option from an option cycle. Wraps around. ---Modifies any pips to show the currently selected option and resets last pip. ---Calls any functions from opt_callback defined in the option cycle when the value changes. --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.option_cycle = function(e) - local from_val = e.config.ref_table.options[e.config.ref_table.current_option] - local from_key = e.config.ref_table.current_option - local old_pip = e.UIBox:get_UIE_by_ID('pip_'..e.config.ref_table.current_option, e.parent.parent) - local cycle_main = e.UIBox:get_UIE_by_ID('cycle_main', e.parent.parent) - - if cycle_main and cycle_main.config.h_popup then - cycle_main:stop_hover() - G.E_MANAGER:add_event(Event({ - func = function() - cycle_main:hover() - return true - end - })) - end - - if e.config.ref_value == 'l' then - --cycle left - e.config.ref_table.current_option = e.config.ref_table.current_option - 1 - if e.config.ref_table.current_option <= 0 then e.config.ref_table.current_option = #e.config.ref_table.options end - else - --cycle right - e.config.ref_table.current_option = e.config.ref_table.current_option + 1 - if e.config.ref_table.current_option > #e.config.ref_table.options then e.config.ref_table.current_option = 1 end - end - local to_val = e.config.ref_table.options[e.config.ref_table.current_option] - local to_key = e.config.ref_table.current_option - e.config.ref_table.current_option_val = e.config.ref_table.options[e.config.ref_table.current_option] - - local new_pip = e.UIBox:get_UIE_by_ID('pip_'..e.config.ref_table.current_option, e.parent.parent) - - if old_pip then old_pip.config.colour = G.C.BLACK end - if new_pip then new_pip.config.colour = G.C.WHITE end - - if e.config.ref_table.opt_callback then - G.FUNCS[e.config.ref_table.opt_callback]{ - from_val = from_val, - to_val = to_val, - from_key = from_key, - to_key = to_key, - cycle_config = e.config.ref_table - } - end -end - ---|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| --- CYCLE CALLBACKS ---|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| - ---Generalized test framework callback for any testing option cycles --- ----@param args {cycle_config: table, to_val: value} ---**cycle_config** Is the config table from the original option cycle UIE\ ---**to_val** is the value the option is changing to -G.FUNCS.test_framework_cycle_callback = function(args) - args = args or {} - if args.cycle_config and args.cycle_config.ref_table and args.cycle_config.ref_value then - args.cycle_config.ref_table[args.cycle_config.ref_value] = args.to_val - end -end - ---Changing the current page being viewed for the Joker Collection --- ----@param args {cycle_config: table} ---**cycle_config** Is the config table from the original option cycle UIE -G.FUNCS.your_collection_joker_page = function(args) - if not args or not args.cycle_config then return end - for j = 1, #G.your_collection do - for i = #G.your_collection[j].cards,1, -1 do - local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) - c:remove() - c = nil - end - end - for i = 1, 5 do - for j = 1, #G.your_collection do - local center = G.P_CENTER_POOLS["Joker"][i+(j-1)*5 + (5*#G.your_collection*(args.cycle_config.current_option - 1))] - if not center then break end - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, center) - card.sticker = get_joker_win_sticker(center) - G.your_collection[j]:emplace(card) - end - end - INIT_COLLECTION_CARD_ALERTS() -end - ---Changing the current page being viewed for the tarot and planet card collection --- ----@param args {cycle_config: table} ---**cycle_config** Is the config table from the original option cycle UIE -G.FUNCS.your_collection_tarot_page = function(args) - if not args or not args.cycle_config then return end - for j = 1, #G.your_collection do - for i = #G.your_collection[j].cards,1, -1 do - local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) - c:remove() - c = nil - end - end - - for j = 1, #G.your_collection do - for i = 1, 4+j do - local center = G.P_CENTER_POOLS["Tarot"][i+(j-1)*(5) + (11*(args.cycle_config.current_option - 1))] - if not center then break end - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, center) - card:start_materialize(nil, i>1 or j>1) - G.your_collection[j]:emplace(card) - end - end - INIT_COLLECTION_CARD_ALERTS() -end - -G.FUNCS.your_collection_spectral_page = function(args) - if not args or not args.cycle_config then return end - for j = 1, #G.your_collection do - for i = #G.your_collection[j].cards,1, -1 do - local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) - c:remove() - c = nil - end - end - - for j = 1, #G.your_collection do - for i = 1, 3+j do - local center = G.P_CENTER_POOLS["Spectral"][i+(j-1)*(4) + (9*(args.cycle_config.current_option - 1))] - if not center then break end - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, center) - card:start_materialize(nil, i>1 or j>1) - G.your_collection[j]:emplace(card) - end - end - INIT_COLLECTION_CARD_ALERTS() -end - ---Changing the current page being viewed for the booster pack card collection --- ----@param args {cycle_config: table} ---**cycle_config** Is the config table from the original option cycle UIE -G.FUNCS.your_collection_booster_page = function(args) - if not args or not args.cycle_config then return end - for j = 1, #G.your_collection do - for i = #G.your_collection[j].cards,1, -1 do - local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) - c:remove() - c = nil - end - end - - for j = 1, #G.your_collection do - for i = 1, 4 do - local center = G.P_CENTER_POOLS["Booster"][i+(j-1)*4 + (8*(args.cycle_config.current_option - 1))] - if not center then break end - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W*1.27, G.CARD_H*1.27, nil, center) - card:start_materialize(nil, i>1 or j>1) - G.your_collection[j]:emplace(card) - end - end - INIT_COLLECTION_CARD_ALERTS() -end - ---Changing the current page being viewed for the voucher collection --- ----@param args {cycle_config: table} ---**cycle_config** Is the config table from the original option cycle UIE -G.FUNCS.your_collection_voucher_page = function(args) - if not args or not args.cycle_config then return end - for j = 1, #G.your_collection do - for i = #G.your_collection[j].cards,1, -1 do - local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) - c:remove() - c = nil - end - end - for i = 1, 4 do - for j = 1, #G.your_collection do - local center = G.P_CENTER_POOLS["Voucher"][i+(j-1)*4 + (8*(args.cycle_config.current_option - 1))] - if not center then break end - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, center) - card:start_materialize(nil, i>1 or j>1) - G.your_collection[j]:emplace(card) - end - end - INIT_COLLECTION_CARD_ALERTS() -end - ---Changing the selected card back --- ----@param args {to_val: value} ---**to_val** Deck back name being changed to -G.FUNCS.change_selected_back = function(args) - G.GAME.selected_back:change_to(G.P_CENTER_POOLS.Back[args.to_key]) -end - ---Changing the collection viewed card back --- ----@param args {to_val: value} ---**to_val** Deck back name being changed to -G.FUNCS.change_viewed_back = function(args) - G.viewed_stake = G.viewed_stake or 1 - local deck_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Back) - G.GAME.viewed_back:change_to(deck_pool[args.to_key]) - if G.sticker_card then G.sticker_card.sticker = get_deck_win_sticker(G.GAME.viewed_back.effect.center) end - local max_stake = get_deck_win_stake(G.GAME.viewed_back.effect.center.key) or 0 - G.viewed_stake = math.min(G.viewed_stake, max_stake + 1) - G.PROFILES[G.SETTINGS.profile].MEMORY.deck = args.to_val - for key, val in pairs(G.sticker_card.area.cards) do - val.children.back = false - val:set_ability(val.config.center, true) - end -end - -G.FUNCS.change_stake = function(args) - G.viewed_stake = args.to_key - G.PROFILES[G.SETTINGS.profile].MEMORY.stake = args.to_key -end - ---Switch VSync on or off - add the change to the settings change queue --- ----@param args {to_key: key} ---**to_key** new VSync key setting, 1 for On, 2 for Off -G.FUNCS.change_vsync = function(args) - G.SETTINGS.QUEUED_CHANGE.vsync = (G.SETTINGS.WINDOW.vsync == 0 and args.to_key == 1 and 1) or (G.SETTINGS.WINDOW.vsync == 1 and args.to_key == 2 and 0) or nil -end - ---Changes the screen resolution to the cycled resolution.\ ---Note - an issue with windows scaling above 100% means that these resolutions may not match the actual monitor resolution, ---they are more like render resolutions adjusted to fit the screen with scaling --- ----@param args {cycle_config: table, to_key: key} ---**cycle_config** Is the config table from the original option cycle UIE\ ---**to_key** The new resolution setting, refers to a resolution table generated with the option cycle -G.FUNCS.change_screen_resolution = function(args) - local curr_disp = G.SETTINGS.WINDOW.selected_display - local to_resolution = G.SETTINGS.WINDOW.DISPLAYS[curr_disp].screen_resolutions.values[args.to_key] - G.SETTINGS.QUEUED_CHANGE.screenres = {w = to_resolution.w, h = to_resolution.h} - -end - ---Changes the screen mode\ ---Options: Windowed, Fullscreen, Borderless --- ----@param args {cycle_config: table, to_val: value} ---**cycle_config** Is the config table from the original option cycle UIE\ ---**to_val** The new screenmode setting value -G.FUNCS.change_screenmode = function(args) - G.ARGS.screenmode_vals = G.ARGS.screenmode_vals or {"Windowed", "Fullscreen", "Borderless"} - G.SETTINGS.QUEUED_CHANGE.screenmode = G.ARGS.screenmode_vals[args.to_key] - G.FUNCS.change_window_cycle_UI() -end - ---Changes the displaying monitors --- ----@param args {cycle_config: table, to_key: key} ---**cycle_config** Is the config table from the original option cycle UIE\ ---**to_key** The new screenmode setting key -G.FUNCS.change_display = function(args) - G.SETTINGS.QUEUED_CHANGE.selected_display = args.to_key - G.FUNCS.change_window_cycle_UI() -end - ---Helper function to re-add the resolution cycle UIE with updated data -G.FUNCS.change_window_cycle_UI = function() - if G.OVERLAY_MENU then - local swap_node = G.OVERLAY_MENU:get_UIE_by_ID('resolution_cycle') - if swap_node then - local focused_display, focused_screenmode = G.SETTINGS.QUEUED_CHANGE.selected_display or G.SETTINGS.WINDOW.selected_display, G.SETTINGS.QUEUED_CHANGE.screenmode or G.SETTINGS.WINDOW.screenmode - - --Refresh the display information - local res_option = GET_DISPLAYINFO(focused_screenmode, focused_display) - - --Remove the old cycle, replace it with a new updated one reflecting any changes - swap_node.children[1]:remove() - swap_node.children[1] = nil - swap_node.UIBox:add_child( - create_option_cycle({w = 4,scale = 0.8, options = G.SETTINGS.WINDOW.DISPLAYS[focused_display].screen_resolutions.strings, opt_callback = 'change_screen_resolution',current_option = res_option or 1}), - swap_node) - end - end -end - ---Changes the speed that the game runs at, does not affect all timers, just G.TIMERS.TOTAL --- ----@param args {cycle_config: table, to_val: value} ---**cycle_config** Is the config table from the original option cycle UIE\ ---**to_val** The new screenmode setting key -G.FUNCS.change_gamespeed = function(args) - G.SETTINGS.GAMESPEED = args.to_val -end - ---Changes the relative position of play and discard buttons --- ----@param args {cycle_config: table, to_key: value} ---**cycle_config** Is the config table from the original option cycle UIE\ ---**to_val** The new screenmode setting key -G.FUNCS.change_play_discard_position = function(args) - G.SETTINGS.play_button_pos = args.to_key - if G.buttons then - G.buttons:remove() - G.buttons = UIBox{ - definition = create_UIBox_buttons(), - config = {align="bm", offset = {x=0,y=0.3},major = G.hand, bond = 'Weak'} - } - end -end - ---Changes the Shadow setting --- ----@param args {cycle_config: table, to_val: value} ---**cycle_config** Is the config table from the original option cycle UIE\ ---**to_val** The new value for shadows, 'On' or 'Off' -G.FUNCS.change_shadows = function(args) - G.SETTINGS.GRAPHICS.shadows = args.to_key == 1 and 'On' or 'Off' - G:save_settings() -end - ---Changes the Pixel smoothing, all sprites need to be realoaded when this changes\ --- ----@param args {cycle_config: table, to_key: key} ---**cycle_config** Is the config table from the original option cycle UIE\ ---**to_val** The new value for shadows, 'On' or 'Off' -G.FUNCS.change_pixel_smoothing = function(args) - G.SETTINGS.GRAPHICS.texture_scaling = args.to_key--^2 - SMODS.injectObjects(SMODS.Atlas) - G:save_settings() -end - ---Changes the Bloom amount for the CRT effect, number of samples to take for bloom\ --- ----@param args {cycle_config: table, to_key: key} ---**cycle_config** Is the config table from the original option cycle UIE\ ---**to_val** The new value for shadows, 'On' or 'Off' -G.FUNCS.change_crt_bloom = function(args) - G.SETTINGS.GRAPHICS.bloom = args.to_key - G:save_settings() -end - -G.FUNCS.change_collab = function(args) - G.SETTINGS.CUSTOM_DECK.Collabs[args.cycle_config.curr_suit] = G.COLLABS.options[args.cycle_config.curr_suit][args.to_key] or 'default' - for k, v in pairs(G.I.CARD) do - if v.config and v.config.card and v.children.front and v.ability.effect ~= 'Stone Card' then - v:set_sprites(nil, v.config.card) - end - end - G:save_settings() -end - ---|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| --- TEXT ENTRY ---|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| - ---passes a keyboard input to the controller when a key UI button is pressed --- ----@param e table --- ---[e is the UI Element that calls this update function, contains ARGS in e.config.ref_table] -G.FUNCS.key_button = function(e) - local args = e.config.ref_table - if args.key then G.CONTROLLER:key_press_update(args.key) end -end - ---Modifies the text input to show the current text value being modified. Shows the prompt text if\ ---the text input area is not hooked. Also modifies the UIE colour to show the hooked/non hooked colour\ ---If using a keyboard, pops it up here or removes it if using KBM --- ----@param e table --- ---[e is the UI Element that calls this update function, contains ARGS in e.config.ref_table] -G.FUNCS.text_input = function(e) - local args =e.config.ref_table - if G.CONTROLLER.text_input_hook == e then - e.parent.parent.config.colour = args.hooked_colour - args.current_prompt_text = '' - args.current_position_text = args.position_text - else - e.parent.parent.config.colour = args.colour - args.current_prompt_text = (args.text.ref_table[args.text.ref_value] == '' and args.prompt_text or '') - args.current_position_text = '' - end - - local OSkeyboard_e = e.parent.parent.parent - if G.CONTROLLER.text_input_hook == e and G.CONTROLLER.HID.controller then - if not OSkeyboard_e.children.controller_keyboard then - OSkeyboard_e.children.controller_keyboard = UIBox{ - definition = create_keyboard_input{backspace_key = true, return_key = true, space_key = false}, - config = { - align= 'cm', - offset = {x = 0, y = G.CONTROLLER.text_input_hook.config.ref_table.keyboard_offset or -4}, - major = e.UIBox, parent = OSkeyboard_e} - } - G.CONTROLLER.screen_keyboard = OSkeyboard_e.children.controller_keyboard - G.CONTROLLER:mod_cursor_context_layer(1) - end - elseif OSkeyboard_e.children.controller_keyboard then - OSkeyboard_e.children.controller_keyboard:remove() - OSkeyboard_e.children.controller_keyboard = nil - G.CONTROLLER.screen_keyboard = nil - G.CONTROLLER:mod_cursor_context_layer(-1) - end -end - -G.FUNCS.paste_seed = function(e) - G.CONTROLLER.text_input_hook = e.UIBox:get_UIE_by_ID('text_input').children[1].children[1] - G.CONTROLLER.text_input_id = 'text_input' - for i = 1, 8 do - G.FUNCS.text_input_key({key = 'right'}) - end - for i = 1, 8 do - G.FUNCS.text_input_key({key = 'backspace'}) - end - local clipboard = (G.F_LOCAL_CLIPBOARD and G.CLIPBOARD or love.system.getClipboardText()) or '' - for i = 1, #clipboard do - local c = clipboard:sub(i,i) - G.FUNCS.text_input_key({key = c}) - end - G.FUNCS.text_input_key({key = 'return'}) -end - ---When clicked, hooks the text input defined by e->1->1, which should be the text input UIE --- ----@param e table --- ---[e is the UI Element that calls this click function] -G.FUNCS.select_text_input = function(e) - G.CONTROLLER.text_input_hook = e.children[1].children[1] - G.CONTROLLER.text_input_id = e.config.id - - --Start by setting the cursor position to the correct location - TRANSPOSE_TEXT_INPUT(0) - e.UIBox:recalculate(true) -end - ---Handles all key inputs for the hooked text input. --- ----@param args {key: string, caps: boolean} ---**key** the key being pressed\ ---**caps** if the key should be capitalized -G.FUNCS.text_input_key = function(args) - args = args or {} - - if args.key == '[' or args.key == ']' then return end - if args.key == '0' then args.key = 'o' end - - --shortcut to hook config - local hook_config = G.CONTROLLER.text_input_hook.config.ref_table - hook_config.orig_colour = hook_config.orig_colour or copy_table(hook_config.colour) - - args.key = args.key or '%' - args.caps = args.caps or G.CONTROLLER.capslock or hook_config.all_caps --capitalize if caps lock or hook requires - - --Some special keys need to be mapped accordingly before passing through the corpus - local keymap = { - space = ' ', - backspace = 'BACKSPACE', - delete = 'DELETE', - ['return'] = 'RETURN', - right = 'RIGHT', - left = 'LEFT' - } - local hook = G.CONTROLLER.text_input_hook - local corpus = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'..(hook.config.ref_table.extended_corpus and " 0!$&()<>?:{}+-=,.[]_" or '') - - if hook.config.ref_table.extended_corpus then - local lower_ext = '1234567890-=;\',./' - local upper_ext = '!@#$%^&*()_+:"<>?' - if string.find(lower_ext, args.key) and args.caps then - args.key = string.sub(string.sub(upper_ext,string.find(lower_ext, args.key)), 0, 1) - end - end - local text = hook_config.text - - --set key to mapped key or upper if caps is true - args.key = keymap[args.key] or (args.caps and string.upper(args.key) or args.key) - - --Start by setting the cursor position to the correct location - TRANSPOSE_TEXT_INPUT(0) - - if string.len(text.ref_table[text.ref_value]) > 0 and args.key == 'BACKSPACE' then --If not at start, remove preceding letter - MODIFY_TEXT_INPUT{ - letter = '', - text_table = text, - pos = text.current_position, - delete = true - } - TRANSPOSE_TEXT_INPUT(-1) - elseif string.len(text.ref_table[text.ref_value]) > 0 and args.key == 'DELETE' then --if not at end, remove following letter - MODIFY_TEXT_INPUT{ - letter = '', - text_table = text, - pos = text.current_position+1, - delete = true - } - TRANSPOSE_TEXT_INPUT(0) - elseif args.key == 'RETURN' then --Release the hook - if hook.config.ref_table.callback then hook.config.ref_table.callback() end - hook.parent.parent.config.colour = hook_config.colour - local temp_colour = copy_table(hook_config.orig_colour) - hook_config.colour[1] = G.C.WHITE[1] - hook_config.colour[2] = G.C.WHITE[2] - hook_config.colour[3] = G.C.WHITE[3] - ease_colour(hook_config.colour, temp_colour) - G.CONTROLLER.text_input_hook = nil - elseif args.key == 'LEFT' then --Move cursor position to the left - TRANSPOSE_TEXT_INPUT(-1) - elseif args.key == 'RIGHT' then --Move cursor position to the right - TRANSPOSE_TEXT_INPUT(1) - elseif hook_config.max_length > string.len(text.ref_table[text.ref_value]) and - (string.len(args.key) == 1) and - string.find( corpus, args.key , 1, true) then --check to make sure the key is in the valid corpus, add it to the string - MODIFY_TEXT_INPUT{ - letter = args.key, - text_table = text, - pos = text.current_position+1 - } - TRANSPOSE_TEXT_INPUT(1) - end -end - ---Helper function for G.FUNCS.text_input_key -function GET_TEXT_FROM_INPUT() - local new_text = '' - local hook = G.CONTROLLER.text_input_hook - for i = 1, #hook.children do - if hook.children[i].config and hook.children[i].config.id:sub(1, 8+string.len(G.CONTROLLER.text_input_id)) == G.CONTROLLER.text_input_id..'_letter_' and hook.children[i].config.text ~= '' then - new_text = new_text..hook.children[i].config.text - end - end - return new_text -end - ---Helper function for G.FUNCS.text_input_key --- ----@param args {letter: string, text_table: table, pos: number, delete: boolean} ---**letter** the letter being pressed\ ---**text_table** the table full of letters from hook\ ---**pos** the current position of the iterator\ ---**delete** if the action is a deletion action -function MODIFY_TEXT_INPUT(args) - args = args or {} - - if args.delete and args.pos > 0 then - if args.pos >= #args.text_table.letters then - args.text_table.letters[args.pos] = '' - else - args.text_table.letters[args.pos] = args.text_table.letters[args.pos+1] - MODIFY_TEXT_INPUT{ - letter = args.letter, - text_table = args.text_table, - pos = args.pos+1, - delete = args.delete - } - end - return - end - local swapped_letter = args.text_table.letters[args.pos] - args.text_table.letters[args.pos] = args.letter - if swapped_letter and swapped_letter ~= '' then - MODIFY_TEXT_INPUT{ - letter = swapped_letter, - text_table = args.text_table, - pos = args.pos+1 - } - end -end - ---Helper function for G.FUNCS.text_input_key\ ---Moves the cursor left or right. Typing a key, deleting or backspacing also counts\ ---as a cursor move, since empty strings are used to fill the hook --- ----@param amount number -function TRANSPOSE_TEXT_INPUT(amount) - local position_child = nil - local hook = G.CONTROLLER.text_input_hook - local text = G.CONTROLLER.text_input_hook.config.ref_table.text - for i = 1, #hook.children do - if hook.children[i].config then - if hook.children[i].config.id == G.CONTROLLER.text_input_id..'_position' then - position_child = i; break - end - end - end - - local dir = (amount/math.abs(amount)) or 0 - - while amount ~= 0 do - if position_child + dir < 1 or position_child + dir >= #hook.children then break end - local real_letter = hook.children[position_child+dir].config.id:sub(1, 8+string.len(G.CONTROLLER.text_input_id)) == G.CONTROLLER.text_input_id..'_letter_' and hook.children[position_child+dir].config.text ~= '' - SWAP(hook.children, position_child, position_child + dir) - if real_letter then amount = amount - dir end - position_child = position_child + dir - end - - text.current_position = math.min(position_child-1, string.len(text.ref_table[text.ref_value])) - hook.UIBox:recalculate(true) - text.ref_table[text.ref_value] = GET_TEXT_FROM_INPUT() -end - ---Determines if there are any graphical changes in the queue that require window re-initialization, ---changes the button accordingly --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.can_apply_window_changes = function(e) - local can_apply = false - if G.SETTINGS.QUEUED_CHANGE then - if G.SETTINGS.QUEUED_CHANGE.screenmode and - G.SETTINGS.QUEUED_CHANGE.screenmode ~= G.SETTINGS.WINDOW.screenmode then - can_apply = true - elseif G.SETTINGS.QUEUED_CHANGE.screenres then - can_apply = true - elseif G.SETTINGS.QUEUED_CHANGE.vsync then - can_apply = true - elseif G.SETTINGS.QUEUED_CHANGE.selected_display and - G.SETTINGS.QUEUED_CHANGE.selected_display ~= G.SETTINGS.WINDOW.selected_display then - can_apply = true - end - end - - if can_apply then - e.config.button = 'apply_window_changes' - e.config.colour = G.C.RED - else - e.config.button = nil - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - end -end - ---Applies all window changes, including updates to the screenmode, selected display, resolution and vsync.\ ---These changes are all defined in the G.SETTINGS.QUEUED_CHANGE table. Any unchanged settings use the previous value -G.FUNCS.apply_window_changes = function(_initial) - --Set the screenmode setting from Windowed, Fullscreen or Borderless - G.SETTINGS.WINDOW.screenmode = (G.SETTINGS.QUEUED_CHANGE and G.SETTINGS.QUEUED_CHANGE.screenmode) or G.SETTINGS.WINDOW.screenmode or 'Windowed' - - --Set the monitor the window should be rendered to - G.SETTINGS.WINDOW.selected_display = (G.SETTINGS.QUEUED_CHANGE and G.SETTINGS.QUEUED_CHANGE.selected_display) or G.SETTINGS.WINDOW.selected_display or 1 - - --Set the screen resolution - G.SETTINGS.WINDOW.DISPLAYS[G.SETTINGS.WINDOW.selected_display].screen_res = { - w = (G.SETTINGS.QUEUED_CHANGE and G.SETTINGS.QUEUED_CHANGE.screenres and G.SETTINGS.QUEUED_CHANGE.screenres.w) or (G.SETTINGS.screen_res and G.SETTINGS.screen_res.w) or love.graphics.getWidth( ), - h = (G.SETTINGS.QUEUED_CHANGE and G.SETTINGS.QUEUED_CHANGE.screenres and G.SETTINGS.QUEUED_CHANGE.screenres.h) or (G.SETTINGS.screen_res and G.SETTINGS.screen_res.h) or love.graphics.getHeight( ) - } - - --Set the vsync value, 0 is off 1 is on - G.SETTINGS.WINDOW.vsync = (G.SETTINGS.QUEUED_CHANGE and G.SETTINGS.QUEUED_CHANGE.vsync) or G.SETTINGS.WINDOW.vsync or 1 - - love.window.updateMode( - (G.SETTINGS.QUEUED_CHANGE and G.SETTINGS.QUEUED_CHANGE.screenmode == 'Windowed') and love.graphics.getWidth()*0.8 or G.SETTINGS.WINDOW.DISPLAYS[G.SETTINGS.WINDOW.selected_display].screen_res.w, - (G.SETTINGS.QUEUED_CHANGE and G.SETTINGS.QUEUED_CHANGE.screenmode == 'Windowed') and love.graphics.getHeight()*0.8 or G.SETTINGS.WINDOW.DISPLAYS[G.SETTINGS.WINDOW.selected_display].screen_res.h, - {fullscreen = G.SETTINGS.WINDOW.screenmode ~= 'Windowed', - fullscreentype = (G.SETTINGS.WINDOW.screenmode == 'Borderless' and 'desktop') or (G.SETTINGS.WINDOW.screenmode == 'Fullscreen' and 'exclusive') or nil, - vsync = G.SETTINGS.WINDOW.vsync, - resizable = true, - display = G.SETTINGS.WINDOW.selected_display, - highdpi = (love.system.getOS() == 'OS X') - }) - G.SETTINGS.QUEUED_CHANGE = {} - if _initial ~= true then - love.resize(love.graphics.getWidth(),love.graphics.getHeight()) - G:save_settings() - end - if G.OVERLAY_MENU then - local tab_but = G.OVERLAY_MENU:get_UIE_by_ID('tab_but_Video') - G.FUNCS.change_tab(tab_but) - end -end - ---Iterates through any collection cardareas, applies the initial collection alert update.\ ---This update_alert function for each card is also called by the card in its own update function -function INIT_COLLECTION_CARD_ALERTS() - for j = 1, #G.your_collection do - for _, v in ipairs(G.your_collection[j].cards) do - v:update_alert() - end - end -end - ---|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| --- RUN SETUP ---|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| - ---Monitors the run option deck to determine if a new 'back' has been chosen from the option cycle\ ---if so, this function removes the old UI describing the ability of the back and replaces it with the new ability UI --- ----@param e {} ---**e** Is the UIE that called this function -G.FUNCS.RUN_SETUP_check_back = function(e) - if G.GAME.viewed_back.name ~= e.config.id then - --removes the UI from the previously selected back and adds the new one - - e.config.object:remove() - e.config.object = UIBox{ - definition = G.GAME.viewed_back:generate_UI(), - config = {offset = {x=0,y=0}, align = 'cm', parent = e} - } - e.config.id = G.GAME.viewed_back.name - end -end - -G.FUNCS.RUN_SETUP_check_back_name = function(e) - if e.config.object and G.GAME.viewed_back.name ~= e.config.id then - --removes the UI from the previously selected back and adds the new one - - e.config.object:remove() - e.config.object = UIBox{ - definition = {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR}, nodes={ - {n=G.UIT.O, config={id = G.GAME.viewed_back.name, func = 'RUN_SETUP_check_back_name', object = DynaText({string = G.GAME.viewed_back:get_name(),maxw = 4, colours = {G.C.WHITE}, shadow = true, bump = true, scale = 0.5, pop_in = 0, silent = true})}}, - }}, - config = {offset = {x=0,y=0}, align = 'cm', parent = e} - } - e.config.id = G.GAME.viewed_back.name - end -end - -G.FUNCS.RUN_SETUP_check_stake = function(e) - if (G.GAME.viewed_back.name ~= e.config.id) then - e.config.object:remove() - e.config.object = UIBox{ - definition = G.UIDEF.stake_option(G.SETTINGS.current_setup), - config = {offset = {x=0,y=0}, align = 'tmi', parent = e} - } - e.config.id = G.GAME.viewed_back.name - end -end - -G.FUNCS.RUN_SETUP_check_stake2 = function(e) - if (G.viewed_stake ~= e.config.id) then - e.config.object:remove() - e.config.object = UIBox{ - definition = G.UIDEF.viewed_stake_option(), - config = {offset = {x=0,y=0}, align = 'cm', parent = e} - } - e.config.id = G.viewed_stake - end -end - -G.FUNCS.RUN_SETUP_check_back_stake_column= function(e) - if G.GAME.viewed_back.name ~= e.config.id then - --removes the UI from the previously selected back and adds the new one - e.config.object:remove() - e.config.object = UIBox{ - definition = G.UIDEF.deck_stake_column(G.GAME.viewed_back.effect.center.key), - config = {offset = {x=0,y=0}, align = 'cm', parent = e} - } - e.config.id = G.GAME.viewed_back.name - end -end - -G.FUNCS.RUN_SETUP_check_back_stake_highlight= function(e) - if G.viewed_stake == e.config.id and e.config.outline < 0.1 then - e.config.outline = 0.8 - elseif G.viewed_stake ~= e.config.id and e.config.outline > 0.1 then - e.config.outline = 0 - end -end - -G.FUNCS.change_tab = function(e) - if not e then return end - local _infotip_object = G.OVERLAY_MENU:get_UIE_by_ID('overlay_menu_infotip') - if _infotip_object and _infotip_object.config.object then - _infotip_object.config.object:remove() - _infotip_object.config.object = Moveable() - end - - local tab_contents = e.UIBox:get_UIE_by_ID('tab_contents') - tab_contents.config.object:remove() - tab_contents.config.object = UIBox{ - definition = e.config.ref_table.tab_definition_function(e.config.ref_table.tab_definition_function_args), - config = {offset = {x=0,y=0}, parent = tab_contents, type = 'cm'} - } - tab_contents.UIBox:recalculate() -end - ---|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| --- OVERLAY MENUS ---|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| - ---The overlay menu is a full screen menu interface, and is usually called from button presses. The base Overlay menu function here\ ---creates a global G.OVERLAY_MENU that represents this full screen UIBox. The game may be paused at this time as well\ ---The generated UIBox is created below the visible screen area and eased up to the center of the screen --- ----@param args {definition: table, config: table, pause: boolean} ---**definition** The definition table for the UIBox\ ---**config** A configuration table for the UIBox\ ---**pause** Whether the game should be paused on creation of the UIBox -G.FUNCS.overlay_menu = function(args) - if not args then return end - --Remove any existing overlays if there is one - if G.OVERLAY_MENU then G.OVERLAY_MENU:remove() end - G.CONTROLLER.locks.frame_set = true - G.CONTROLLER.locks.frame = true - G.CONTROLLER.cursor_down.target = nil - G.CONTROLLER:mod_cursor_context_layer(G.NO_MOD_CURSOR_STACK and 0 or 1) - - args.config = args.config or {} - args.config = { - align = args.config.align or "cm", - offset = args.config.offset or {x=0,y=10}, - major = args.config.major or G.ROOM_ATTACH, - bond = 'Weak', - no_esc = args.config.no_esc - } - G.OVERLAY_MENU = true - --Generate the UIBox - G.OVERLAY_MENU = UIBox{ - definition = args.definition, - config = args.config - } - - --Set the offset and align. The menu overlay can be initially offset in the y direction and this will ensure it slides to middle - G.OVERLAY_MENU.alignment.offset.y = 0 - G.ROOM.jiggle = G.ROOM.jiggle + 1 - G.OVERLAY_MENU:align_to_major() -end - ---Removes the overlay menu if one exists, unpauses the game, and saves the settings to file -G.FUNCS.exit_overlay_menu = function() - if not G.OVERLAY_MENU then return end - G.CONTROLLER.locks.frame_set = true - G.CONTROLLER.locks.frame = true - G.CONTROLLER:mod_cursor_context_layer(-1000) - G.OVERLAY_MENU:remove() - G.OVERLAY_MENU = nil - G.VIEWING_DECK = nil - G.SETTINGS.paused = false - - --Save settings to file - G:save_settings() -end - ---Removes overlay menu and immediately generates the next unlock menu if there is one -G.FUNCS.continue_unlock = function() - G.FUNCS.exit_overlay_menu() - G.CONTROLLER:mod_cursor_context_layer(-2000) - G.E_MANAGER:update(0, true) -end - -G.FUNCS.test_framework = function(options) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_test_framework(options), - } -end - -G.FUNCS.options = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_options(), - } -end - -G.FUNCS.current_hands = function(e, simple) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_current_hands(simple), - } -end - -G.FUNCS.run_info = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = G.UIDEF.run_info(), - } -end - -G.FUNCS.deck_info = function(e) - G.SETTINGS.paused = true - if G.deck_preview then - G.deck_preview:remove() - G.deck_preview = nil - end - G.FUNCS.overlay_menu{ - definition = G.UIDEF.deck_info( - G.STATE == G.STATES.SELECTING_HAND or G.STATE == G.STATES.HAND_PLAYED or G.STATE == G.STATES.DRAW_TO_HAND - ), - } -end - -G.FUNCS.settings = function(e, instant) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_settings(), - config = {offset = {x=0,y=instant and 0 or 10}} -} -end - -G.FUNCS.show_credits = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = G.UIDEF.credits(), - } -end - -G.FUNCS.language_selection = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = G.UIDEF.language_selector(), - } -end - -G.FUNCS.your_collection = function(e) -if update_cry_member_count then update_cry_member_count() end - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection(), - } -end - -G.FUNCS.your_collection_blinds = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_blinds(), - } -end - -G.FUNCS.your_collection_jokers = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_jokers(), - } -end - -G.FUNCS.your_collection_tarots = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_tarots(), - } -end - -G.FUNCS.your_collection_planets = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_planets(), - } -end - -G.FUNCS.your_collection_spectrals = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_spectrals(), - } -end - -G.FUNCS.your_collection_vouchers = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_vouchers(), - } -end - -G.FUNCS.your_collection_enhancements_exit_overlay_menu = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_enhancements('exit_overlay_menu'), - } -end - -G.FUNCS.your_collection_enhancements = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_enhancements(), - } -end - -G.FUNCS.your_collection_decks = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_decks(), - } -end - -G.FUNCS.your_collection_editions = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_editions(), - } -end - -G.FUNCS.your_collection_tags = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_tags(), - } -end - -G.FUNCS.your_collection_seals = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_seals(), - } -end - -G.FUNCS.your_collection_boosters = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_boosters(), - } -end - -G.FUNCS.challenge_list = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = G.UIDEF.challenge_list((e.config.id == 'from_game_over')), - } - if (e.config.id == 'from_game_over') then G.OVERLAY_MENU.config.no_esc =true end -end - -G.FUNCS.high_scores = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_high_scores(), - } -end - -G.FUNCS.customize_deck = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_customize_deck(), - } -end - -G.FUNCS.usage = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = G.UIDEF.usage_tabs() - } -end - -G.FUNCS.setup_run = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = G.UIDEF.run_setup((e.config.id == 'from_game_over' or e.config.id == 'from_game_won' or e.config.id == 'challenge_list') and e.config.id), - } - if (e.config.id == 'from_game_over' or e.config.id == 'from_game_won') then G.OVERLAY_MENU.config.no_esc =true end -end - -G.FUNCS.wait_for_high_scores = function(e) - if G.ARGS.HIGH_SCORE_RESPONSE then - e.config.object:remove() - e.config.object = UIBox{ - definition = create_UIBox_high_scores_filling(G.ARGS.HIGH_SCORE_RESPONSE), - config = {offset = {x=0,y=0}, align = 'cm', parent = e} - } - G.ARGS.HIGH_SCORE_RESPONSE = nil - end -end - -G.FUNCS.notify_then_setup_run = function(e) - G.OVERLAY_MENU:remove() - G.OVERLAY_MENU = nil - - G.E_MANAGER:add_event(Event({ - blockable = false, - func = (function() - unlock_notify() - return true - end) - })) - - G.E_MANAGER:add_event(Event({ - blockable = false, - func = (function() - if #G.E_MANAGER.queues.unlock <= 0 and not G.OVERLAY_MENU then - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = G.UIDEF.run_setup((e.config.id == 'from_game_over' or e.config.id == 'from_game_won') and e.config.id), - } - if (e.config.id == 'from_game_over' or e.config.id == 'from_game_won') then G.OVERLAY_MENU.config.no_esc =true end - return true - end - end) - })) -end - -G.FUNCS.change_challenge_description = function(e) - if G.OVERLAY_MENU then - local desc_area = G.OVERLAY_MENU:get_UIE_by_ID('challenge_area') - if desc_area and desc_area.config.oid ~= e.config.id then - if desc_area.config.old_chosen then desc_area.config.old_chosen.config.chosen = nil end - e.config.chosen = 'vert' - if desc_area.config.object then - desc_area.config.object:remove() - end - desc_area.config.object = UIBox{ - definition = G.UIDEF.challenge_description(e.config.id), - config = {offset = {x=0,y=0}, align = 'cm', parent = desc_area} - } - desc_area.config.oid = e.config.id - desc_area.config.old_chosen = e - end - end -end - -G.FUNCS.change_challenge_list_page = function(args) - if not args or not args.cycle_config then return end - if G.OVERLAY_MENU then - local ch_list = G.OVERLAY_MENU:get_UIE_by_ID('challenge_list') - if ch_list then - if ch_list.config.object then - ch_list.config.object:remove() - end - ch_list.config.object = UIBox{ - definition = G.UIDEF.challenge_list_page(args.cycle_config.current_option-1), - config = {offset = {x=0,y=0}, align = 'cm', parent = ch_list} - } - G.FUNCS.change_challenge_description{config = {id = 'nil'}} - end - end -end - -G.FUNCS.deck_view_challenge = function(e) - G.FUNCS.overlay_menu{ - definition = create_UIBox_generic_options({back_func = 'deck_info', contents ={ - G.UIDEF.challenge_description(get_challenge_int_from_id(e.config.id.id or ''), nil, true) - } - }) - } -end - -G.FUNCS.profile_select = function(e) - G.SETTINGS.paused = true - G.focused_profile = G.SETTINGS.profile - - for i = 1, 3 do - if i ~= G.focused_profile and love.filesystem.getInfo(i..'/'..'profile.jkr') then G:load_profile(i) end - end - G:load_profile(G.focused_profile) - - G.FUNCS.overlay_menu{ - definition = G.UIDEF.profile_select(), - } -end - -G.FUNCS.quit = function(e) - love.event.quit() -end - -G.FUNCS.quit_cta = function(e) - G.SETTINGS.paused = true - G.SETTINGS.DEMO.quit_CTA_shown = true - - G:save_progress() - - G.FUNCS.overlay_menu{ - definition = create_UIBox_exit_CTA(), - config = {no_esc = true} - } - local Jimbo = nil - - if not G.jimboed then - G.jimboed = true - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = 2.5, - func = (function() - if G.OVERLAY_MENU and G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') then - Jimbo = Card_Character({x = 0, y = 5}) - local spot = G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') - spot.config.object:remove() - spot.config.object = Jimbo - Jimbo.ui_object_updated = true - Jimbo:add_speech_bubble( {"Having fun?", {{text = "Wishlist Balatro!", type = 'GREEN'}}}) - Jimbo:say_stuff(5) - end - return true - end) - })) - end -end - -G.FUNCS.demo_survey = function(e) - love.system.openURL( "https://forms.gle/WX26BHq1AwwV5xyH9")--"https://forms.gle/P8F4WzdCsccrm15T6" ) -end - -G.FUNCS.louisf_insta = function(e) - love.system.openURL( "https://www.instagram.com/louisfsoundtracks/" ) -end - -G.FUNCS.wishlist_steam = function(e) - love.system.openURL( "https://store.steampowered.com/app/2379780/Balatro/#game_area_purchase" ) -end - -G.FUNCS.go_to_playbalatro = function(e) - love.system.openURL( "https://www.playbalatro.com" ) -end - -G.FUNCS.go_to_discord = function(e) - love.system.openURL( "https://discord.gg/balatro" ) -end - -G.FUNCS.go_to_discord_loc = function(e) - love.system.openURL( "https://discord.com/channels/1116389027176787968/1207803392978853898" ) -end - -G.FUNCS.loc_survey = function(e) - love.system.openURL( "https://forms.gle/pL5tMh1oXLmv8czz9" ) -end - -G.FUNCS.go_to_twitter = function(e) - love.system.openURL( "https://twitter.com/LocalThunk" ) -end - -G.FUNCS.unlock_this = function(e) - unlock_achievement(e.config.id) -end - -G.FUNCS.reset_achievements = function(e) - G.ACHIEVEMENTS = nil - G.SETTINGS.ACHIEVEMENTS_EARNED = {} - G:save_progress() - G.FUNCS.exit_overlay_menu() -end - -G.FUNCS.refresh_contrast_mode = function() - local new_colour_proto = G.C["SO_"..(G.SETTINGS.colourblind_option and 2 or 1)] - G.C.SUITS.Hearts = new_colour_proto.Hearts - G.C.SUITS.Diamonds = new_colour_proto.Diamonds - G.C.SUITS.Spades = new_colour_proto.Spades - G.C.SUITS.Clubs = new_colour_proto.Clubs - for k, v in pairs(G.I.CARD) do - if v.config and v.config.card and v.children.front and v.ability.effect ~= 'Stone Card' then - v:set_sprites(nil, v.config.card) - end - end -end - -G.FUNCS.warn_lang = function(e) - local _infotip_object = G.OVERLAY_MENU:get_UIE_by_ID('overlay_menu_infotip') - if (_infotip_object.config.set ~= e.config.ref_table.label) then - _infotip_object.config.object:remove() - _infotip_object.config.object = UIBox{ - definition = overlay_infotip({e.config.ref_table.warning[1],e.config.ref_table.warning[2],e.config.ref_table.warning[3], lang = e.config.ref_table}), - config = {offset = {x=0,y=0}, align = 'bm', parent = _infotip_object} - } - _infotip_object.config.object.UIRoot:juice_up() - _infotip_object.config.set = e.config.ref_table.label - e.config.disable_button = true - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.06, blockable = false, blocking = false, func = function() - play_sound('tarot2', 0.76, 0.4);return true end})) - - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.35, blockable = false, blocking = false, func = function() - e.config.disable_button = nil;return true end})) - e.config.button = 'change_lang' - play_sound('tarot2', 1, 0.4) - end -end - - - -G.FUNCS.change_lang = function(e) - local lang = e.config.ref_table - if not lang or lang == G.LANG then - G.FUNCS.exit_overlay_menu() - else - G.SETTINGS.language = lang.loc_key or lang.key - G.SETTINGS.real_language = lang.key - G:set_language() - G.E_MANAGER:clear_queue() - G.FUNCS.wipe_on() - G.E_MANAGER:add_event(Event({ - no_delete = true, - blockable = true, - blocking = false, - func = function() - G:delete_run() - G:init_item_prototypes() - G:main_menu() - return true - end - })) - G.FUNCS.wipe_off() - end -end - -G.FUNCS.copy_seed = function(e) - if G.F_LOCAL_CLIPBOARD then - G.CLIPBOARD = G.GAME.pseudorandom.seed - else - love.system.setClipboardText(G.GAME.pseudorandom.seed) - end -end - -G.FUNCS.start_setup_run = function(e) - if G.OVERLAY_MENU then G.FUNCS.exit_overlay_menu() end - if G.SETTINGS.current_setup == 'New Run' then - if not G.GAME or (not G.GAME.won and not G.GAME.seeded) then - if G.SAVED_GAME ~= nil then - if not G.SAVED_GAME.GAME.won then - G.PROFILES[G.SETTINGS.profile].high_scores.current_streak.amt = 0 - end - G:save_settings() - end - end - local _seed = G.run_setup_seed and G.setup_seed or G.forced_seed or nil - local _challenge = G.challenge_tab or nil - local _stake = G.forced_stake or G.PROFILES[G.SETTINGS.profile].MEMORY.stake or 1 - G.FUNCS.start_run(e, {stake = _stake, seed = _seed, challenge = _challenge}) - - elseif G.SETTINGS.current_setup == 'Continue' then - if G.SAVED_GAME ~= nil then - G.FUNCS.start_run(nil, {savetext = G.SAVED_GAME}) - end - end -end - -G.FUNCS.start_challenge_run = function(e) - if G.OVERLAY_MENU then G.FUNCS.exit_overlay_menu() end - G.FUNCS.start_run(e, {stake = 1, challenge = G.CHALLENGES[e.config.id]}) -end - -function G.FUNCS.toggle_seeded_run(e) - if e.config.object and not G.run_setup_seed then - e.config.object:remove() - e.config.object = nil - elseif not e.config.object and G.run_setup_seed then - e.config.object = UIBox{ - definition = {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR}, nodes={ - {n=G.UIT.C, config={align = "cm", minw = 2.5, padding = 0.05}, nodes={ - simple_text_container('ml_disabled_seed',{colour = G.C.UI.TEXT_LIGHT, scale = 0.26, shadow = true}), - }}, - {n=G.UIT.C, config={align = "cm", minw = 0.1}, nodes={ - create_text_input({max_length = 8, all_caps = true, ref_table = G, ref_value = 'setup_seed', prompt_text = localize('k_enter_seed')}), - {n=G.UIT.C, config={align = "cm", minw = 0.1}, nodes={}}, - UIBox_button({label = localize('ml_paste_seed'),minw = 1, minh = 0.6, button = 'paste_seed', colour = G.C.BLUE, scale = 0.3, col = true}) - }}, - - {n=G.UIT.C, config={align = "cm", minw = 2.5}, nodes={ - }}, - }}, - config = {offset = {x=0,y=0}, parent = e, type = 'cm'} - } - e.config.object:recalculate() - end -end - -G.FUNCS.start_tutorial = function(e) - if G.OVERLAY_MENU then G.FUNCS.exit_overlay_menu() end - G.SETTINGS.tutorial_progress = - { - forced_shop = {'j_joker', 'c_empress'}, - forced_voucher = 'v_grabber', - forced_tags = {'tag_handy', 'tag_garbage'}, - hold_parts = {}, - completed_parts = {}, - } - G.SETTINGS.tutorial_complete = false - G.FUNCS.start_run(e) -end - -G.FUNCS.chip_UI_set = function(e) - local new_chips_text = number_format(G.GAME.chips) - if G.GAME.chips_text ~= new_chips_text then - e.config.scale = math.min(0.8, scale_number(G.GAME.chips, 1.1)) - G.GAME.chips_text = new_chips_text - end -end - -G.FUNCS.blind_chip_UI_scale = function(e) - if G.GAME.blind and G.GAME.blind.chips then - e.config.scale = scale_number(G.GAME.blind.chips, 0.7, 100000) - end -end - -function scale_number(number, scale, max, e_switch_point) - G.E_SWITCH_POINT = G.E_SWITCH_POINT or 100000000000 - if not number or type(number) ~= 'number' then return scale end - if not max then max = 10000 end - if math.abs(number) >= (e_switch_point or G.E_SWITCH_POINT) then - scale = scale*math.floor(math.log(max*10, 10))/math.floor(math.log(1000000*10, 10)) - elseif number >= max then - scale = scale*math.floor(math.log(max*10, 10))/math.floor(math.log(number*10, 10)) - end - return scale -end - -G.FUNCS.hand_mult_UI_set = function(e) - local new_mult_text = number_format(G.GAME.current_round.current_hand.mult) - if new_mult_text ~= G.GAME.current_round.current_hand.mult_text then - G.GAME.current_round.current_hand.mult_text = new_mult_text - e.config.object.scale = scale_number(G.GAME.current_round.current_hand.mult, 0.9, 1000) - e.config.object:update_text() - if not G.TAROT_INTERRUPT_PULSE then G.FUNCS.text_super_juice(e, math.min(2,math.max(0,math.floor(math.log10(is_number(G.GAME.current_round.current_hand.mult) and G.GAME.current_round.current_hand.mult or 1))))) end - end -end - -G.FUNCS.hand_chip_UI_set = function(e) - local new_chip_text = number_format(G.GAME.current_round.current_hand.chips) - if new_chip_text ~= G.GAME.current_round.current_hand.chip_text then - G.GAME.current_round.current_hand.chip_text = new_chip_text - e.config.object.scale = scale_number(G.GAME.current_round.current_hand.chips, 0.9, 1000) - e.config.object:update_text() - if not G.TAROT_INTERRUPT_PULSE then G.FUNCS.text_super_juice(e, math.min(2,math.max(0,math.floor(math.log10(is_number(G.GAME.current_round.current_hand.chips) and G.GAME.current_round.current_hand.chips or 1))))) end - end -end - -G.FUNCS.hand_chip_total_UI_set = function(e) - if to_big(G.GAME.current_round.current_hand.chip_total) < to_big(1) then - G.GAME.current_round.current_hand.chip_total_text = '' - else - local new_chip_total_text = number_format(G.GAME.current_round.current_hand.chip_total) - if new_chip_total_text ~= G.GAME.current_round.current_hand.chip_total_text then - e.config.object.scale = scale_number(G.GAME.current_round.current_hand.chip_total, 0.95, 100000000) - - G.GAME.current_round.current_hand.chip_total_text = new_chip_total_text - if not G.ARGS.hand_chip_total_UI_set or to_big(G.ARGS.hand_chip_total_UI_set) < to_big(G.GAME.current_round.current_hand.chip_total) then - G.FUNCS.text_super_juice(e, math.floor(math.log10(G.GAME.current_round.current_hand.chip_total))) - end - G.ARGS.hand_chip_total_UI_set = G.GAME.current_round.current_hand.chip_total - --e.UIBox:recalculate() - end - end -end - -function G.FUNCS.text_super_juice(e, _amount) - e.config.object:set_quiver(0.03*_amount) - e.config.object:pulse(0.3 + 0.08*_amount) - e.config.object:update_text() - e.config.object:align_letters() - e:update_object() -end - -G.FUNCS.flame_handler = function(e) - G.C.UI_CHIPLICK = G.C.UI_CHIPLICK or {1, 1, 1, 1} - G.C.UI_MULTLICK = G.C.UI_MULTLICK or {1, 1, 1, 1} - for i=1, 3 do - G.C.UI_CHIPLICK[i] = math.min(math.max(((G.C.UI_CHIPS[i]*0.5+G.C.YELLOW[i]*0.5) + 0.1)^2, 0.1), 1) - G.C.UI_MULTLICK[i] = math.min(math.max(((G.C.UI_MULT[i]*0.5+G.C.YELLOW[i]*0.5) + 0.1)^2, 0.1), 1) - end - - G.ARGS.flame_handler = G.ARGS.flame_handler or { - chips = { - id = 'flame_chips', - arg_tab = 'chip_flames', - colour = G.C.UI_CHIPS, - accent = G.C.UI_CHIPLICK - }, - mult = { - id = 'flame_mult', - arg_tab = 'mult_flames', - colour = G.C.UI_MULT, - accent = G.C.UI_MULTLICK - } - } - for k, v in pairs(G.ARGS.flame_handler) do - if e.config.id == v.id then - if not e.config.object:is(Sprite) or e.config.object.ID ~= v.ID then - e.config.object:remove() - e.config.object = Sprite(0, 0, 2.5, 2.5, G.ASSET_ATLAS["ui_1"], {x = 2, y = 0}) - v.ID = e.config.object.ID - G.ARGS[v.arg_tab] = { - intensity = 0, - real_intensity = 0, - intensity_vel = 0, - colour_1 = v.colour, - colour_2 = v.accent, - timer = G.TIMERS.REAL - } - e.config.object:set_alignment({ - major = e.parent, - type = 'bmi', - offset = {x=0,y=0}, - xy_bond = 'Weak' - }) - e.config.object:define_draw_steps({{ - shader = 'flame', - send = { - {name = 'time', ref_table = G.ARGS[v.arg_tab], ref_value = 'timer'}, - {name = 'amount', ref_table = G.ARGS[v.arg_tab], ref_value = 'real_intensity'}, - {name = 'image_details', ref_table = e.config.object, ref_value = 'image_dims'}, - {name = 'texture_details', ref_table = e.config.object.RETS, ref_value = 'get_pos_pixel'}, - {name = 'colour_1', ref_table = G.ARGS[v.arg_tab], ref_value = 'colour_1'}, - {name = 'colour_2', ref_table = G.ARGS[v.arg_tab], ref_value = 'colour_2'}, - {name = 'id', val = e.config.object.ID}, - }}}) - e.config.object:get_pos_pixel() - end - local _F = G.ARGS[v.arg_tab] - local exptime = math.exp(-0.4*G.real_dt) - - if to_big(G.ARGS.score_intensity.earned_score) >= to_big(G.ARGS.score_intensity.required_score) and to_big(G.ARGS.score_intensity.required_score) > to_big(0) then - _F.intensity = ((G.pack_cards and not G.pack_cards.REMOVED) or (G.TAROT_INTERRUPT)) and 0 or Cartomancer.get_flames_intensity() - else - _F.intensity = 0 - end - - _F.timer = Cartomancer.handle_flames_timer(_F.timer, _F.intensity) - if _F.intensity_vel < 0 then _F.intensity_vel = _F.intensity_vel*(1 - 10*G.real_dt) end - _F.intensity_vel = (1-exptime)*(_F.intensity - _F.real_intensity)*G.real_dt*25 + exptime*_F.intensity_vel - _F.real_intensity = math.max(0, _F.real_intensity + _F.intensity_vel) - - _F.real_intensity = (G.cry_flame_override and G.cry_flame_override['duration'] > 0) and ((_F.real_intensity + G.cry_flame_override['intensity'])/2) or _F.real_intensity - _F.change = (_F.change or 0)*(1 - 4.*G.real_dt) + ( 4.*G.real_dt)*(_F.real_intensity < _F.intensity - 0.0 and 1 or 0)*_F.real_intensity - _F.change = (G.cry_flame_override and G.cry_flame_override['duration'] > 0) and ((_F.change + G.cry_flame_override['intensity'])/2) or _F.change - end - end -end - -G.FUNCS.hand_text_UI_set = function(e) - if G.GAME.current_round.current_hand.handname ~= G.GAME.current_round.current_hand.handname_text then - G.GAME.current_round.current_hand.handname_text = G.GAME.current_round.current_hand.handname - if G.GAME.current_round.current_hand.handname:len() >= 13 then - e.config.object.scale = 12*0.56/G.GAME.current_round.current_hand.handname:len() - else - e.config.object.scale = 2.4/math.sqrt(G.GAME.current_round.current_hand.handname:len()+5) - end - e.config.object:update_text() - end -end - - G.FUNCS.can_play = function(e) - if #G.hand.highlighted <= (G.GAME.blind and G.GAME.blind.name == 'cry-Sapphire Stamp' and not G.GAME.blind.disabled and 1 or 0) or G.GAME.blind.block_play then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - e.config.colour = G.C.BLUE - e.config.button = 'play_cards_from_highlighted' - end - end - - G.FUNCS.can_start_run = function(e) - if not G.GAME.viewed_back.effect.center.unlocked then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - e.config.colour = G.C.BLUE - e.config.button = 'start_setup_run' - end - end - - G.FUNCS.visible_blind = function(e) - if next(G.GAME.blind.config.blind) then - e.states.visible = true - else - e.states.visible = false - end - end - - G.FUNCS.can_reroll = function(e) - if ((G.GAME.dollars-G.GAME.bankrupt_at) - G.GAME.current_round.reroll_cost < 0) and G.GAME.current_round.reroll_cost ~= 0 then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - --e.children[1].children[1].config.shadow = false - --e.children[2].children[1].config.shadow = false - --e.children[2].children[2].config.shadow = false - else - e.config.colour = G.C.GREEN - e.config.button = 'reroll_shop' - --e.children[1].children[1].config.shadow = true - --e.children[2].children[1].config.shadow = true - --e.children[2].children[2].config.shadow = true - end - end - - G.FUNCS.can_discard = function(e) - if G.GAME.current_round.discards_left <= 0 or #G.hand.highlighted <= 0 then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - e.config.colour = G.C.RED - e.config.button = 'discard_cards_from_highlighted' - end - end - - G.FUNCS.can_use_consumeable = function(e) - if e.config.ref_table:can_use_consumeable() then - e.config.colour = G.C.RED - e.config.button = 'use_card' - else - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - end - end - - G.FUNCS.can_select_card = function(e) - if e.config.ref_table.ability.set ~= 'Joker' or (e.config.ref_table.edition and e.config.ref_table.edition.negative) or #G.jokers.cards < G.jokers.config.card_limit then - e.config.colour = G.C.GREEN - e.config.button = 'use_card' - else - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - end - end - - G.FUNCS.can_sell_card = function(e) - if e.config.ref_table:can_sell_card() then - e.config.colour = G.C.GREEN - e.config.button = 'sell_card' - else - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - end - end - - G.FUNCS.can_skip_booster = function(e) - if G.pack_cards and (not (G.GAME.STOP_USE and G.GAME.STOP_USE > 0)) and -(G.STATE == G.STATES.SMODS_BOOSTER_OPENED or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.STANDARD_PACK or G.STATE == G.STATES.BUFFOON_PACK or (G.hand )) then - e.config.colour = G.C.GREY - e.config.button = 'skip_booster' - else - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - end - end - - G.FUNCS.show_infotip = function(e) - if e.config.ref_table then - e.children.info = UIBox{ - definition = {n=G.UIT.ROOT, config = {align = 'cm', colour = G.C.CLEAR, padding = 0.02}, nodes=e.config.ref_table}, - config = (not e.config.ref_table or not e.config.ref_table[1].config.card_pos or e.config.ref_table[1].config.card_pos > G.ROOM.T.w*0.4) and - {offset = {x=-0.03,y=0}, align = 'cl', parent = e} or - {offset = {x=0.03,y=0}, align = 'cr', parent = e} - } - e.children.info:align_to_major() - e.config.ref_table = nil - end - end - - - G.FUNCS.use_card = function(e, mute, nosave) - e.config.button = nil - local card = e.config.ref_table - local area = card.area - local prev_state = G.STATE - local dont_dissolve = nil - local delay_fac = 1 - - if card:check_use() then - G.E_MANAGER:add_event(Event({func = function() - e.disable_button = nil - e.config.button = 'use_card' - return true end })) - return - end - - if card.ability.set == 'Booster' and not nosave and G.STATE == G.STATES.SHOP then - save_with_action({ - type = 'use_card', - card = card.sort_id, - }) - end - - G.TAROT_INTERRUPT = G.STATE - if card.ability.set == 'Booster' then G.GAME.PACK_INTERRUPT = G.STATE end - G.STATE = (G.STATE == G.STATES.TAROT_PACK and G.STATES.TAROT_PACK) or - (G.STATE == G.STATES.PLANET_PACK and G.STATES.PLANET_PACK) or - (G.STATE == G.STATES.SPECTRAL_PACK and G.STATES.SPECTRAL_PACK) or - (G.STATE == G.STATES.STANDARD_PACK and G.STATES.STANDARD_PACK) or - (G.STATE == G.STATES.SMODS_BOOSTER_OPENED and G.STATES.SMODS_BOOSTER_OPENED) or - (G.STATE == G.STATES.BUFFOON_PACK and G.STATES.BUFFOON_PACK) or - G.STATES.PLAY_TAROT - - G.CONTROLLER.locks.use = true - if G.booster_pack and not G.booster_pack.alignment.offset.py and (card.ability.consumeable or not (G.GAME.pack_choices and G.GAME.pack_choices > 1)) then - G.booster_pack.alignment.offset.py = G.booster_pack.alignment.offset.y - G.booster_pack.alignment.offset.y = G.ROOM.T.y + 29 - end - if G.shop and not G.shop.alignment.offset.py then - G.shop.alignment.offset.py = G.shop.alignment.offset.y - G.shop.alignment.offset.y = G.ROOM.T.y + 29 - end - if G.blind_select and not G.blind_select.alignment.offset.py then - G.blind_select.alignment.offset.py = G.blind_select.alignment.offset.y - G.blind_select.alignment.offset.y = G.ROOM.T.y + 39 - end - if G.round_eval and not G.round_eval.alignment.offset.py then - G.round_eval.alignment.offset.py = G.round_eval.alignment.offset.y - G.round_eval.alignment.offset.y = G.ROOM.T.y + 29 - end - - if card.children.use_button then card.children.use_button:remove(); card.children.use_button = nil end - if card.children.sell_button then card.children.sell_button:remove(); card.children.sell_button = nil end - if card.children.price then card.children.price:remove(); card.children.price = nil end - - local nc - if card.ability.consumeable then - local obj = card.config.center - if obj.keep_on_use and type(obj.keep_on_use) == 'function' then - nc = obj:keep_on_use(card) - end - end - if not nc and card.area then card.area:remove_card(card) end - - if card.ability.consumeable then - if G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED then - card.T.x = G.hand.T.x + G.hand.T.w/2 - card.T.w/2 - card.T.y = G.hand.T.y + G.hand.T.h/2 - card.T.h/2 - 0.5 - discover_card(card.config.center) - elseif nc then - area:remove_from_highlighted(card) - play_sound('cardSlide2', nil, 0.3) - dont_dissolve = true - else draw_card(G.hand, G.play, 1, 'up', true, card, nil, mute) end - delay(0.2) - e.config.ref_table:use_consumeable(area) - if card.edition and card.edition.key then - local ed = SMODS.Centers[card.edition.key] - if ed.calculate and type(ed.calculate) == 'function' then - ed:calculate(card, {from_consumable = true}) - end - end - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({using_consumeable = true, consumeable = card}) - end - G.GAME.selected_back:trigger_effect({context = 'using_consumeable', consumeable = card}) - elseif card.ability.set == 'Enhanced' or card.ability.set == 'Default' then - G.playing_card = (G.playing_card and G.playing_card + 1) or 1 - G.deck:emplace(card) - play_sound('card1', 0.8, 0.6) - play_sound('generic1') - card.playing_card = G.playing_card - playing_card_joker_effects({card}) - card:add_to_deck() - table.insert(G.playing_cards, card) - dont_dissolve = true - delay_fac = 0.2 - elseif card.ability.set == 'Joker' then - card:add_to_deck() - G.jokers:emplace(card) - play_sound('card1', 0.8, 0.6) - play_sound('generic1') - dont_dissolve = true - delay_fac = 0.2 - elseif card.ability.set == 'Booster' then - delay(0.1) - if card.ability.booster_pos then G.GAME.current_round.used_packs[card.ability.booster_pos] = 'USED' end - draw_card(G.hand, G.play, 1, 'up', true, card, nil, true) - if not card.from_tag then - G.GAME.round_scores.cards_purchased.amt = G.GAME.round_scores.cards_purchased.amt + 1 - end - e.config.ref_table:open() - elseif card.ability.set == 'Voucher' then - delay(0.1) - draw_card(G.hand, G.play, 1, 'up', true, card, nil, true) - G.GAME.round_scores.cards_purchased.amt = G.GAME.round_scores.cards_purchased.amt + 1 - if area == G.pack_cards then e.config.ref_table.cost = 0 end - e.config.ref_table:redeem() - end - if card.ability.set == 'Booster' then - G.CONTROLLER.locks.use = false - G.TAROT_INTERRUPT = nil - else - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.2, - func = function() - if not dont_dissolve then card:start_dissolve() end - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.1, - func = function() - G.STATE = prev_state - G.TAROT_INTERRUPT=nil - G.CONTROLLER.locks.use = false - - if (prev_state == G.STATES.TAROT_PACK or prev_state == G.STATES.PLANET_PACK or - prev_state == G.STATES.SPECTRAL_PACK or prev_state == G.STATES.STANDARD_PACK or - prev_state == G.STATES.SMODS_BOOSTER_OPENED or - prev_state == G.STATES.BUFFOON_PACK) and G.booster_pack then - if area == G.consumeables or area == G.hand then - G.booster_pack.alignment.offset.y = G.booster_pack.alignment.offset.py - G.booster_pack.alignment.offset.py = nil - elseif G.GAME.pack_choices and G.GAME.pack_choices > 1 then - if G.booster_pack.alignment.offset.py then - G.booster_pack.alignment.offset.y = G.booster_pack.alignment.offset.py - G.booster_pack.alignment.offset.py = nil - end - G.GAME.pack_choices = G.GAME.pack_choices - 1 - else - G.CONTROLLER.interrupt.focus = true - if prev_state == G.STATES.TAROT_PACK then inc_career_stat('c_tarot_reading_used', 1) end - if prev_state == G.STATES.PLANET_PACK then inc_career_stat('c_planetarium_used', 1) end - G.FUNCS.end_consumeable(nil, delay_fac) - end - else - if G.shop then - G.shop.alignment.offset.y = G.shop.alignment.offset.py - G.shop.alignment.offset.py = nil - end - if G.blind_select then - G.blind_select.alignment.offset.y = G.blind_select.alignment.offset.py - G.blind_select.alignment.offset.py = nil - end - if G.round_eval then - G.round_eval.alignment.offset.y = G.round_eval.alignment.offset.py - G.round_eval.alignment.offset.py = nil - end - if area and area.cards and area.cards[1] then - G.E_MANAGER:add_event(Event({func = function() - G.E_MANAGER:add_event(Event({func = function() - G.CONTROLLER.interrupt.focus = nil - if card.ability.set == 'Voucher' then - G.CONTROLLER:snap_to({node = G.shop:get_UIE_by_ID('next_round_button')}) - elseif area then - G.CONTROLLER:recall_cardarea_focus(area) - end - return true end })) - return true end })) - end - end - return true - end})) - return true - end})) - end - end - - G.FUNCS.sell_card = function(e) - local card = e.config.ref_table - card:sell_card() - for i = 1, #G.jokers.cards do - if G.jokers.cards[i] ~= card then - G.jokers.cards[i]:calculate_joker({selling_card = true, card = card}) - end - end - G.GAME.selected_back:trigger_effect({context = 'selling_card', card = card}) - end - - G.FUNCS.can_confirm_contest_name = function(e) - if G.SETTINGS.COMP and G.SETTINGS.COMP.name ~= '' then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - else - e.config.colour = G.C.PALE_GREEN - e.config.button = 'confirm_contest_name' - end - end - - G.FUNCS.confirm_contest_name = function(e) - G.SETTINGS.COMP.submission_name = true - if G.MAIN_MENU_UI then G.MAIN_MENU_UI:remove() end - if G.PROFILE_BUTTON then G.PROFILE_BUTTON:remove() end - set_main_menu_UI() - G:save_progress() - G.FILE_HANDLER.force = true - end - - G.FUNCS.change_contest_name = function(e) - G.SETTINGS.COMP.name = '' - if G.MAIN_MENU_UI then G.MAIN_MENU_UI:remove() end - if G.PROFILE_BUTTON then G.PROFILE_BUTTON:remove() end - set_main_menu_UI() - end - - G.FUNCS.skip_tutorial_section = function(e) - G.OVERLAY_TUTORIAL.skip_steps = true - - if G.OVERLAY_TUTORIAL.Jimbo then G.OVERLAY_TUTORIAL.Jimbo:remove() end - if G.OVERLAY_TUTORIAL.content then G.OVERLAY_TUTORIAL.content:remove() end - G.OVERLAY_TUTORIAL:remove() - G.OVERLAY_TUTORIAL = nil - G.E_MANAGER:clear_queue('tutorial') - if G.SETTINGS.tutorial_progress.section == 'small_blind' then - G.SETTINGS.tutorial_progress.completed_parts['small_blind'] = true - elseif G.SETTINGS.tutorial_progress.section == 'big_blind' then - G.SETTINGS.tutorial_progress.completed_parts['big_blind'] = true - G.SETTINGS.tutorial_progress.forced_tags = nil - elseif G.SETTINGS.tutorial_progress.section == 'second_hand' then - G.SETTINGS.tutorial_progress.completed_parts['second_hand'] = true - G.SETTINGS.tutorial_progress.hold_parts['second_hand'] = true - elseif G.SETTINGS.tutorial_progress.section == 'first_hand' then - G.SETTINGS.tutorial_progress.completed_parts['first_hand'] = true - G.SETTINGS.tutorial_progress.completed_parts['first_hand_2'] = true - G.SETTINGS.tutorial_progress.completed_parts['first_hand_3'] = true - G.SETTINGS.tutorial_progress.completed_parts['first_hand_4'] = true - G.SETTINGS.tutorial_progress.completed_parts['first_hand_section'] = true - elseif G.SETTINGS.tutorial_progress.section == 'shop' then - G.SETTINGS.tutorial_progress.completed_parts['shop_1'] = true - G.SETTINGS.tutorial_progress.forced_voucher = nil - end - end - -G.FUNCS.shop_voucher_empty = function(e) - if (G.shop_vouchers and G.shop_vouchers.cards and (G.shop_vouchers.cards[1] or G.GAME.current_round.voucher)) then - e.states.visible = false - elseif G.SETTINGS.language ~= 'en-us' then - e.states.visible = false - else - e.states.visible = true - end -end - -G.FUNCS.check_for_buy_space = function(card) - if card.ability.set ~= 'Voucher' and - card.ability.set ~= 'Enhanced' and - card.ability.set ~= 'Default' and - not (card.ability.set == 'Joker' and #G.jokers.cards < G.jokers.config.card_limit + ((card.edition and card.edition.negative) and 1 or 0)) and - not (card.ability.consumeable and #G.consumeables.cards < G.consumeables.config.card_limit + ((card.edition and card.edition.negative) and 1 or 0)) then - alert_no_space(card, card.ability.consumeable and G.consumeables or G.jokers) - return false - end - return true -end - -G.FUNCS.buy_from_shop = function(e) - local c1 = e.config.ref_table - if c1 and c1:is(Card) then - if e.config.id ~= 'buy_and_use' then - if not G.FUNCS.check_for_buy_space(c1) then - e.disable_button = nil - return false - end - end - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.1, - func = function() - c1.area:remove_card(c1) - c1:add_to_deck() - if c1.children.price then c1.children.price:remove() end - c1.children.price = nil - if c1.children.buy_button then c1.children.buy_button:remove() end - c1.children.buy_button = nil - remove_nils(c1.children) - if c1.ability.set == 'Default' or c1.ability.set == 'Enhanced' then - inc_career_stat('c_playing_cards_bought', 1) - G.playing_card = (G.playing_card and G.playing_card + 1) or 1 - G.deck:emplace(c1) - c1.playing_card = G.playing_card - playing_card_joker_effects({c1}) - table.insert(G.playing_cards, c1) - elseif e.config.id ~= 'buy_and_use' then - if c1.ability.consumeable then - G.consumeables:emplace(c1) - else - G.jokers:emplace(c1) - end - G.E_MANAGER:add_event(Event({func = function() c1:calculate_joker({buying_card = true, card = c1}) return true end})) - end - --Tallies for unlocks - G.GAME.round_scores.cards_purchased.amt = G.GAME.round_scores.cards_purchased.amt + 1 - if c1.ability.consumeable then - if c1.config.center.set == 'Planet' then - inc_career_stat('c_planets_bought', 1) - elseif c1.config.center.set == 'Tarot' then - inc_career_stat('c_tarots_bought', 1) - end - elseif c1.ability.set == 'Joker' then - G.GAME.current_round.jokers_purchased = G.GAME.current_round.jokers_purchased + 1 - end - - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({buying_card = true, card = c1}) - end - G.GAME.selected_back:trigger_effect({context = 'buying_card', card = c1}) - - if G.GAME.modifiers.inflation then - G.GAME.inflation = G.GAME.inflation + 1 - G.E_MANAGER:add_event(Event({func = function() - for k, v in pairs(G.I.CARD) do - if v.set_cost then v:set_cost() end - end - return true end })) - end - - play_sound('card1') - inc_career_stat('c_shop_dollars_spent', c1.cost) - if c1.cost ~= 0 then - ease_dollars(-c1.cost) - end - G.CONTROLLER:save_cardarea_focus('jokers') - G.CONTROLLER:recall_cardarea_focus('jokers') - - if e.config.id == 'buy_and_use' then - G.FUNCS.use_card(e, true) - end - return true - end - })) - end -end - - G.FUNCS.toggle_shop = function(e) - stop_use() - G.CONTROLLER.locks.toggle_shop = true - if G.shop then - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({ending_shop = true}) - end - G.GAME.selected_back:trigger_effect({context = 'ending_shop'}) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.shop.alignment.offset.y = G.ROOM.T.y + 29 - G.SHOP_SIGN.alignment.offset.y = -15 - if G.GAME.oldbpfactor then G.GAME.oldbpfactor = math.max(G.GAME.oldbpfactor - G.GAME.oldbpfactor/8, 1) end - return true - end - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.5, - func = function() - G.shop:remove() - G.shop = nil - G.SHOP_SIGN:remove() - G.SHOP_SIGN = nil - G.STATE_COMPLETE = false - G.STATE = G.STATES.BLIND_SELECT - G.CONTROLLER.locks.toggle_shop = nil - return true - end - })) - end - end - - G.FUNCS.select_blind = function(e) - stop_use() - if G.blind_select then - G.GAME.facing_blind = true - G.blind_prompt_box:get_UIE_by_ID('prompt_dynatext1').config.object.pop_delay = 0 - G.blind_prompt_box:get_UIE_by_ID('prompt_dynatext1').config.object:pop_out(5) - G.blind_prompt_box:get_UIE_by_ID('prompt_dynatext2').config.object.pop_delay = 0 - G.blind_prompt_box:get_UIE_by_ID('prompt_dynatext2').config.object:pop_out(5) - - G.E_MANAGER:add_event(Event({ - trigger = 'before', delay = 0.2, - func = function() - G.blind_prompt_box.alignment.offset.y = -10 - G.blind_select.alignment.offset.y = 40 - G.blind_select.alignment.offset.x = 0 - return true - end})) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - ease_round(1) - inc_career_stat('c_rounds', 1) - if _DEMO then - G.SETTINGS.DEMO_ROUNDS = (G.SETTINGS.DEMO_ROUNDS or 0) + 1 - inc_steam_stat('demo_rounds') - G:save_settings() - end - G.GAME.round_resets.blind = e.config.ref_table - G.GAME.round_resets.blind_states[G.GAME.blind_on_deck] = 'Current' - G.blind_select:remove() - G.blind_prompt_box:remove() - G.blind_select = nil - delay(0.2) - return true - end})) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - new_round() - return true - end - })) - end - end - - G.FUNCS.skip_booster = function(e) - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({skipping_booster = true}) - end - G.GAME.selected_back:trigger_effect({context = 'skipping_booster'}) - G.FUNCS.end_consumeable(e) - end - - G.FUNCS.end_consumeable = function(e, delayfac) - delayfac = delayfac or 1 - stop_use() - if G.booster_pack then - if G.booster_pack_sparkles then G.booster_pack_sparkles:fade(1*delayfac) end - if G.booster_pack_stars then G.booster_pack_stars:fade(1*delayfac) end - if G.booster_pack_meteors then G.booster_pack_meteors:fade(1*delayfac) end - G.booster_pack.alignment.offset.y = G.ROOM.T.y + 9 - - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.2*delayfac,blocking = false, blockable = false, - func = function() - G.booster_pack:remove() - G.booster_pack = nil - return true - end})) - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 1*delayfac,blocking = false, blockable = false, - func = function() - if G.booster_pack_sparkles then G.booster_pack_sparkles:remove(); G.booster_pack_sparkles = nil end - if G.booster_pack_stars then G.booster_pack_stars:remove(); G.booster_pack_stars = nil end - if G.booster_pack_meteors then G.booster_pack_meteors:remove(); G.booster_pack_meteors = nil end - return true - end})) - end - - delay(0.2*delayfac) - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.2*delayfac, - func = function() - if not G.GAME.USING_RUN then - G.FUNCS.draw_from_hand_to_deck() - else - G.FUNCS.draw_from_hand_to_run() - end - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.2*delayfac, - func = function() - if G.shop and G.shop.alignment.offset.py then - G.shop.alignment.offset.y = G.shop.alignment.offset.py - G.shop.alignment.offset.py = nil - end - if G.blind_select and G.blind_select.alignment.offset.py then - G.blind_select.alignment.offset.y = G.blind_select.alignment.offset.py - G.blind_select.alignment.offset.py = nil - end - if G.round_eval and G.round_eval.alignment.offset.py then - G.round_eval.alignment.offset.y = G.round_eval.alignment.offset.py - G.round_eval.alignment.offset.py = nil - end - G.CONTROLLER.interrupt.focus = true - - G.E_MANAGER:add_event(Event({func = function() - if G.shop then G.CONTROLLER:snap_to({node = G.shop:get_UIE_by_ID('next_round_button')}) end - return true end })) - G.STATE = G.GAME.PACK_INTERRUPT - ease_background_colour_blind(G.GAME.PACK_INTERRUPT) - G.GAME.PACK_INTERRUPT = nil - Handy.insta_booster_skip.is_skipped = false - return true - end})) - for i = 1, #G.GAME.tags do - if G.GAME.tags[i]:apply_to_run({type = 'new_blind_choice'}) then break end - end - - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.2*delayfac, - func = function() - save_run() - return true - end})) - - return true - end})) - end - - G.FUNCS.blind_choice_handler = function(e) - if not e.config.ref_table.run_info and G.blind_select and G.blind_select.VT.y < 10 and e.config.id and G.blind_select_opts[string.lower(e.config.id)] then - if e.UIBox.role.xy_bond ~= 'Weak' then e.UIBox:set_role({xy_bond = 'Weak'}) end - if (e.config.ref_table.deck ~= 'on' and e.config.id == G.GAME.blind_on_deck) or - (e.config.ref_table.deck ~= 'off' and e.config.id ~= G.GAME.blind_on_deck) then - - local _blind_choice = G.blind_select_opts[string.lower(e.config.id)] - local _top_button = e.UIBox:get_UIE_by_ID('select_blind_button') - local _border = e.UIBox.UIRoot.children[1].children[1] - local _tag = e.UIBox:get_UIE_by_ID('tag_'..e.config.id) - local _tag_container = e.UIBox:get_UIE_by_ID('tag_container') - if _tag_container and not G.SETTINGS.tutorial_complete and not G.SETTINGS.tutorial_progress.completed_parts['shop_1'] then _tag_container.states.visible = false - elseif _tag_container then _tag_container.states.visible = true end - if e.config.id == G.GAME.blind_on_deck then - e.config.ref_table.deck = 'on' - e.config.draw_after = false - e.config.colour = G.C.CLEAR - _border.parent.config.outline = 2 - _border.parent.config.outline_colour = G.C.UI.TRANSPARENT_DARK - _border.config.outline_colour = _border.config.outline and _border.config.outline_colour or get_blind_main_colour(e.config.id) - _border.config.outline = 1.5 - _blind_choice.alignment.offset.y = -0.9 - if _tag and _tag_container then - _tag_container.children[2].config.draw_after = false - _tag_container.children[2].config.colour = G.C.BLACK - _tag.children[2].config.button = 'skip_blind' - _tag.config.outline_colour = adjust_alpha(G.C.BLUE, 0.5) - _tag.children[2].config.hover = true - _tag.children[2].config.colour = G.C.RED - _tag.children[2].children[1].config.colour = G.C.UI.TEXT_LIGHT - local _sprite = _tag.config.ref_table - _sprite.config.force_focus = nil - end - if _top_button then - G.E_MANAGER:add_event(Event({func = function() - G.CONTROLLER:snap_to({node = _top_button}) - return true end })) - _top_button.config.button = 'select_blind' - _top_button.config.colour = G.C.FILTER - _top_button.config.hover = true - _top_button.children[1].config.colour = G.C.WHITE - end - elseif e.config.id ~= G.GAME.blind_on_deck then - e.config.ref_table.deck = 'off' - e.config.draw_after = true - e.config.colour = adjust_alpha(G.GAME.round_resets.blind_states[e.config.id] == 'Skipped' and mix_colours(G.C.BLUE, G.C.L_BLACK, 0.1) or G.C.L_BLACK, 0.5) - _border.parent.config.outline = nil - _border.parent.config.outline_colour = nil - _border.config.outline_colour = nil - _border.config.outline = nil - _blind_choice.alignment.offset.y = -0.2 - if _tag and _tag_container then - if G.GAME.round_resets.blind_states[e.config.id] == 'Skipped' or - G.GAME.round_resets.blind_states[e.config.id] == 'Defeated' then - _tag_container.children[2]:set_role({xy_bond = 'Weak'}) - _tag_container.children[2]:align(0, 10) - _tag_container.children[1]:set_role({xy_bond = 'Weak'}) - _tag_container.children[1]:align(0, 10) - end - if G.GAME.round_resets.blind_states[e.config.id] == 'Skipped' then - _blind_choice.children.alert = UIBox{ - definition = create_UIBox_card_alert({text_rot = -0.35, no_bg = true,text = localize('k_skipped_cap'), bump_amount = 1, scale = 0.9, maxw = 3.4}), - config = { - align="tmi", - offset = {x = 0, y = 2.2}, - major = _blind_choice, parent = _blind_choice} - } - end - _tag.children[2].config.button = nil - _tag.config.outline_colour = G.C.UI.BACKGROUND_INACTIVE - _tag.children[2].config.hover = false - _tag.children[2].config.colour = G.C.UI.BACKGROUND_INACTIVE - _tag.children[2].children[1].config.colour = G.C.UI.TEXT_INACTIVE - local _sprite = _tag.config.ref_table - _sprite.config.force_focus = true - end - if _top_button then - _top_button.config.colour = G.C.UI.BACKGROUND_INACTIVE - _top_button.config.button = nil - _top_button.config.hover = false - _top_button.children[1].config.colour = G.C.UI.TEXT_INACTIVE - end - end - end - end - end - - G.FUNCS.hover_tag_proxy = function(e) - if not e.parent or not e.parent.states then return end - if (e.states.hover.is or e.parent.states.hover.is) and (e.created_on_pause == G.SETTINGS.paused) and - not e.parent.children.alert then - local _sprite = e.config.ref_table:get_uibox_table() - e.parent.children.alert = UIBox{ - definition = G.UIDEF.card_h_popup(_sprite), - config = {align="tm", offset = {x = 0, y = -0.1}, - major = e.parent, - instance_type = 'POPUP'}, - } - _sprite:juice_up(0.05, 0.02) - play_sound('paper1', math.random()*0.1 + 0.55, 0.42) - play_sound('tarot2', math.random()*0.1 + 0.55, 0.09) - e.parent.children.alert.states.collide.can = false - elseif e.parent.children.alert and - ((not e.states.collide.is and not e.parent.states.collide.is) or (e.created_on_pause ~= G.SETTINGS.paused)) then - e.parent.children.alert:remove() - e.parent.children.alert = nil - end - end - - G.FUNCS.skip_blind = function(e) - stop_use() - G.CONTROLLER.locks.skip_blind = true - G.E_MANAGER:add_event(Event({ - no_delete = true, - trigger = 'after', - blocking = false,blockable = false, - delay = 2.5, - timer = 'TOTAL', - func = function() - G.CONTROLLER.locks.skip_blind = nil - return true - end - })) - local _tag = e.UIBox:get_UIE_by_ID('tag_container') - G.GAME.skips = (G.GAME.skips or 0) + 1 - if _tag and not G.GAME.events.ev_cry_choco2 then - add_tag(_tag.config.ref_table, true) - local skipped, skip_to = G.GAME.blind_on_deck or 'Small', - G.GAME.blind_on_deck == 'Small' and 'Big' or G.GAME.blind_on_deck == 'Big' and 'Boss' or 'Boss' - G.GAME.round_resets.blind_states[skipped] = 'Skipped' - G.GAME.round_resets.blind_states[skip_to] = 'Select' - G.GAME.blind_on_deck = skip_to - play_sound('generic1') - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - delay(0.3) - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({skip_blind = true}) - end - G.GAME.selected_back:trigger_effect({context = 'skip_blind'}) - save_run() - for i = 1, #G.GAME.tags do - G.GAME.tags[i]:apply_to_run({type = 'immediate'}) - end - for i = 1, #G.GAME.tags do - if G.GAME.tags[i]:apply_to_run({type = 'new_blind_choice'}) then break end - end - return true - end - })) - end - end - - G.FUNCS.reroll_boss_button = function(e) - if ((to_big(G.GAME.dollars)-to_big(G.GAME.bankrupt_at)) - to_big(cry_cheapest_boss_reroll()) >= to_big(0)) and - (G.GAME.used_vouchers["v_retcon"] or - (G.GAME.used_vouchers["v_directors_cut"] and not G.GAME.round_resets.boss_rerolled)) then - e.config.colour = G.C.RED - e.config.button = 'reroll_boss' - e.children[1].children[1].config.shadow = true - if e.children[2] then e.children[2].children[1].config.shadow = true end - else - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - e.children[1].children[1].config.shadow = false - if e.children[2] then e.children[2].children[1].config.shadow = false end - end - end - - G.FUNCS.reroll_boss = function(e) - stop_use() - G.GAME.round_resets.boss_rerolled = true - if not G.from_boss_tag then ease_dollars(-cry_cheapest_boss_reroll()) end - G.from_boss_tag = nil - G.CONTROLLER.locks.boss_reroll = true - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - play_sound('other1') - G.blind_select_opts.boss:set_role({xy_bond = 'Weak'}) - G.blind_select_opts.boss.alignment.offset.y = 20 - return true - end - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.3, - func = (function() - local par = G.blind_select_opts.boss.parent - G.GAME.round_resets.blind_choices.Boss = get_new_boss() - - G.blind_select_opts.boss:remove() - G.blind_select_opts.boss = UIBox{ - T = {par.T.x, 0, 0, 0, }, - definition = - {n=G.UIT.ROOT, config={align = "cm", colour = G.C.CLEAR}, nodes={ - UIBox_dyn_container({create_UIBox_blind_choice('Boss')},false,get_blind_main_colour('Boss'), mix_colours(G.C.BLACK, get_blind_main_colour('Boss'), 0.8)) - }}, - config = {align="bmi", - offset = {x=0,y=G.ROOM.T.y + 9}, - major = par, - xy_bond = 'Weak' - } - } - par.config.object = G.blind_select_opts.boss - par.config.object:recalculate() - G.blind_select_opts.boss.parent = par - G.blind_select_opts.boss.alignment.offset.y = 0 - - G.E_MANAGER:add_event(Event({blocking = false, trigger = 'after', delay = 0.5,func = function() - G.CONTROLLER.locks.boss_reroll = nil - return true - end - })) - - save_run() - for i = 1, #G.GAME.tags do - if G.GAME.tags[i]:apply_to_run({type = 'new_blind_choice'}) then break end - end - return true - end) - })) - end - - G.FUNCS.reroll_shop = function(e) - stop_use() - G.CONTROLLER.locks.shop_reroll = true - if G.CONTROLLER:save_cardarea_focus('shop_jokers') then G.CONTROLLER.interrupt.focus = true end - if G.GAME.current_round.reroll_cost > 0 then - inc_career_stat('c_shop_dollars_spent', G.GAME.current_round.reroll_cost) - inc_career_stat('c_shop_rerolls', 1) - ease_dollars(-G.GAME.current_round.reroll_cost) - end - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - local final_free = G.GAME.current_round.free_rerolls > 0 - G.GAME.current_round.free_rerolls = math.max(G.GAME.current_round.free_rerolls - 1, 0) - G.GAME.round_scores.times_rerolled.amt = G.GAME.round_scores.times_rerolled.amt + 1 - - calculate_reroll_cost(final_free) - for i = #G.shop_jokers.cards,1, -1 do - local c = G.shop_jokers:remove_card(G.shop_jokers.cards[i]) - c:remove() - c = nil - end - - --save_run() - - play_sound('coin2') - play_sound('other1') - - for i = 1, G.GAME.shop.joker_max - #G.shop_jokers.cards do - local new_shop_card = create_card_for_shop(G.shop_jokers) - G.shop_jokers:emplace(new_shop_card) - new_shop_card:juice_up() - end - return true - end - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.3, - func = function() - G.E_MANAGER:add_event(Event({ - func = function() - G.CONTROLLER.interrupt.focus = false - G.CONTROLLER.locks.shop_reroll = false - G.CONTROLLER:recall_cardarea_focus('shop_jokers') - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({reroll_shop = true}) - end - G.GAME.selected_back:trigger_effect({context = 'reroll_shop'}) - return true - end - })) - return true - end - })) - G.E_MANAGER:add_event(Event({ func = function() save_run(); return true end})) - end - -G.FUNCS.cash_out = function(e) -if Handy.insta_cash_out.is_skipped and e.config.button then return end - stop_use() - if G.round_eval then - e.config.button = nil - G.round_eval.alignment.offset.y = G.ROOM.T.y + 15 - G.round_eval.alignment.offset.x = 0 - Handy.insta_cash_out.is_button_created = false - G.deck:shuffle('cashout'..G.GAME.round_resets.ante) - G.deck:hard_set_T() - delay(0.3) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - if G.round_eval then - G.round_eval:remove() - G.round_eval = nil - end - G.GAME.current_round.jokers_purchased = 0 - G.GAME.current_round.discards_left = math.max(0, G.GAME.round_resets.discards + G.GAME.round_bonus.discards) - G.GAME.current_round.hands_left = (math.max(1, G.GAME.round_resets.hands + G.GAME.round_bonus.next_hands)) - G.STATE = G.STATES.SHOP - Handy.insta_cash_out.is_skipped = false - G.GAME.shop_free = nil - G.GAME.shop_d6ed = nil - G.STATE_COMPLETE = false - return true - end - })) - ease_dollars(G.GAME.current_round.dollars) - G.E_MANAGER:add_event(Event({ - func = function() - G.GAME.previous_round.dollars = G.GAME.dollars - return true - end - })) - play_sound("coin7") - G.VIBRATION = G.VIBRATION + 1 - end - ease_chips(to_big(0)) - if G.GAME.round_resets.blind_states.Boss == 'Defeated' then - G.GAME.round_resets.blind_ante = G.GAME.round_resets.ante - G.GAME.round_resets.blind_tags.Small = get_next_tag_key() - G.GAME.round_resets.blind_tags.Big = get_next_tag_key() - end - reset_blinds() - delay(0.6) -end - -G.FUNCS.start_run = function(e, args) -args = args or {} - G.SETTINGS.paused = true - if e and e.config.id == 'restart_button' then G.GAME.viewed_back = nil end - G.E_MANAGER:clear_queue() - G.FUNCS.wipe_on() - G.E_MANAGER:add_event(Event({ - no_delete = true, - func = function() - G:delete_run() - return true - end - })) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - no_delete = true, - func = function() - G:start_run(args) - return true - end - })) - G.FUNCS.wipe_off() -end - -G.FUNCS.go_to_menu = function(e) - G.SETTINGS.paused = true - G.E_MANAGER:clear_queue() - G.FUNCS.wipe_on() - G.E_MANAGER:add_event(Event({ - no_delete = true, - func = function() - G:delete_run() - return true - end - })) - G.E_MANAGER:add_event(Event({ - no_delete = true, - blockable = true, - blocking = false, - func = function() - G:main_menu('game') - return true - end - })) - G.FUNCS.wipe_off() -end - -G.FUNCS.go_to_demo_cta = function(e) - G.SETTINGS.paused = true - G.E_MANAGER:clear_queue(nil, G.exception_queue) - play_sound('explosion_buildup1', nil, 0.3) - play_sound('whoosh1', 0.7, 0.8) - play_sound('introPad1', 0.704, 0.8) - G.video_organ = 0.6 - G.FUNCS.wipe_on(nil, true, nil, G.C.WHITE) - G.E_MANAGER:add_event(Event({ - no_delete = true, - func = function() - G:delete_run() - return true - end - })) - G.E_MANAGER:add_event(Event({ - no_delete = true, - blockable = true, - blocking = false, - func = function() - G:demo_cta() - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, - no_delete = true, - blockable = false, - blocking = false, - func = function() - G.video_organ = nil - G.normal_music_speed = nil - return true - end })) - return true - end - })) - G.FUNCS.wipe_off() -end - -G.FUNCS.show_main_cta = function(e) - if e then - if e.config.id == 'lose_cta' and not G.SETTINGS.DEMO.lose_CTA_shown then - G.SETTINGS.DEMO.lose_CTA_shown = true - end - if e.config.id == 'win_cta' and not G.SETTINGS.DEMO.win_CTA_shown then - G.SETTINGS.DEMO.win_CTA_shown = true - end - end - - G:save_progress() - - G.SETTINGS.paused = true - G.normal_music_speed = true - - G.FUNCS.overlay_menu{ - definition = create_UIBox_demo_video_CTA(), - config = {no_esc = true} - } -end - -G.FUNCS.wipe_on = function(message, no_card, timefac, alt_colour) - timefac = timefac or 1 - if G.screenwipe then return end - G.CONTROLLER.locks.wipe = true - G.STAGE_OBJECT_INTERRUPT = true - local colours = { - black = HEX("4f6367FF"), - white = {1, 1, 1, 1} - } - if not no_card then - G.screenwipecard = Card(1, 1, G.CARD_W, G.CARD_H, pseudorandom_element(G.P_CARDS), G.P_CENTERS.c_base) - G.screenwipecard.sprite_facing = 'back' - G.screenwipecard.facing = 'back' - G.screenwipecard.states.hover.can = false - G.screenwipecard:juice_up(0.5, 1) - end - local message_t = nil - if message then - message_t = {} - for k, v in ipairs(message) do - table.insert(message_t, {n=G.UIT.R, config={align = "cm"}, nodes={{n=G.UIT.O, config={object = DynaText({string = v or '', colours = {math.min(G.C.BACKGROUND.C[1], G.C.BACKGROUND.C[2]) > 0.5 and G.C.BLACK or G.C.WHITE},shadow = true, silent = k ~= 1, float = true, scale = 1.3, pop_in = 0, pop_in_rate = 2, rotate = 1})}}}}) - end - end - - G.screenwipe = UIBox{ - definition = - {n=G.UIT.ROOT, config = {align = "cm", minw =0, minh =0 ,padding = 0.15, r = 0.1, colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - message and {n=G.UIT.R, config={id = 'text', align = "cm", padding = 0.7}, nodes=message_t} or nil, - not no_card and {n=G.UIT.O, config={object = G.screenwipecard, role = {role_type = 'Major'}}} or nil - }}, - }}, - config = {align="cm", offset = {x=0,y=0}, major = G.ROOM_ATTACH} - } - G.screenwipe.colours = colours - G.screenwipe.children.particles = Particles(0, 0, 0,0, { - timer = 0, - max = 1, - scale = 40, - speed = 0, - lifespan = 1.7*timefac, - attach = G.screenwipe, - colours = {alt_colour or G.C.BACKGROUND.C} - }) - G.STAGE_OBJECT_INTERRUPT = nil - G.screenwipe.alignment.offset.y = 0 - if message then - for k, v in ipairs(G.screenwipe:get_UIE_by_ID('text').children) do - v.children[1].config.object:pulse() - end - end - - - G.E_MANAGER:add_event(Event({ - trigger = 'before', - delay = 0.7, - no_delete = true, - blockable = false, - func = function() - if not no_card then - G.screenwipecard:flip() - play_sound('cardFan2') - end - return true - end - })) -end - -G.FUNCS.wipe_off = function() - G.E_MANAGER:add_event(Event({ - no_delete = true, - func = function() - delay(0.3) - G.screenwipe.children.particles.max = 0 - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - no_delete = true, - blockable = false, - blocking = false, - timer = 'REAL', - ref_table = G.screenwipe.colours.black, - ref_value = 4, - ease_to = 0, - delay = 0.3, - func = (function(t) return t end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - no_delete = true, - blockable = false, - blocking = false, - timer = 'REAL', - ref_table = G.screenwipe.colours.white, - ref_value = 4, - ease_to = 0, - delay = 0.3, - func = (function(t) return t end) - })) - return true - end - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.55, - no_delete = true, - blocking = false, - timer = 'REAL', - func = function() - if G.screenwipecard then G.screenwipecard:start_dissolve({G.C.BLACK, G.C.ORANGE,G.C.GOLD, G.C.RED}) end - if G.screenwipe:get_UIE_by_ID('text') then - for k, v in ipairs(G.screenwipe:get_UIE_by_ID('text').children) do - v.children[1].config.object:pop_out(4) - end - end - return true - end - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 1.1, - no_delete = true, - blocking = false, - timer = 'REAL', - func = function() - G.screenwipe.children.particles:remove() - G.screenwipe:remove() - G.screenwipe.children.particles = nil - G.screenwipe = nil - G.screenwipecard = nil - return true - end - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 1.2, - no_delete = true, - blocking = true, - timer = 'REAL', - func = function() - return true - end - })) -end diff --git a/lovely/dump/functions/common_events.lua b/lovely/dump/functions/common_events.lua deleted file mode 100644 index a4d23a6..0000000 --- a/lovely/dump/functions/common_events.lua +++ /dev/null @@ -1,3169 +0,0 @@ -LOVELY_INTEGRITY = 'ab88a2edb6834f9903a71e4d3886fdab11953bd163c30e4b5640c2bb3712b019' - -function set_screen_positions() - if G.STAGE == G.STAGES.RUN then - G.hand.T.x = G.TILE_W - G.hand.T.w - 2.85 - G.hand.T.y = G.TILE_H - G.hand.T.h - - G.play.T.x = G.hand.T.x + (G.hand.T.w - G.play.T.w)/2 - G.play.T.y = G.hand.T.y - 3.6 - - G.jokers.T.x = G.hand.T.x - 0.1 - G.jokers.T.y = 0 - - G.consumeables.T.x = G.jokers.T.x + G.jokers.T.w + 0.2 - G.consumeables.T.y = 0 - G.jokers.T.x = G.hand.T.x - 0.1 - G.jokers.T.y = 0 - - G.deck.T.x = G.TILE_W - G.deck.T.w - 0.5 - G.deck.T.y = G.TILE_H - G.deck.T.h - - G.discard.T.x = G.jokers.T.x + G.jokers.T.w/2 + 0.3 + 15 - G.discard.T.y = 4.2 - - G.hand:hard_set_VT() - G.play:hard_set_VT() - G.jokers:hard_set_VT() - G.consumeables:hard_set_VT() - G.deck:hard_set_VT() - G.discard:hard_set_VT() - end - if G.STAGE == G.STAGES.MAIN_MENU then - if G.STATE == G.STATES.DEMO_CTA then - G.title_top.T.x = G.TILE_W/2 - G.title_top.T.w/2 - G.title_top.T.y = G.TILE_H/2 - G.title_top.T.h/2 - 2 - else - G.title_top.T.x = G.TILE_W/2 - G.title_top.T.w/2 - G.title_top.T.y = G.TILE_H/2 - G.title_top.T.h/2 -(G.debug_splash_size_toggle and 2 or 1.2)--||||||||||||||||| - end - - G.title_top:hard_set_VT() - end -end - -function ease_chips(mod) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - local chip_UI = G.HUD:get_UIE_by_ID('chip_UI_count') - - mod = mod or 0 - - --Ease from current chips to the new number of chips - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - blockable = false, - ref_table = G.GAME, - ref_value = 'chips', - ease_to = mod, - delay = 0.3, - func = (function(t) return math.floor(t) end) - })) - --Popup text next to the chips in UI showing number of chips gained/lost - chip_UI:juice_up() - --Play a chip sound - play_sound('chips2') - return true - end - })) -end - -function ease_dollars(mod, instant) - local function _mod(mod) - local dollar_UI = G.HUD:get_UIE_by_ID('dollar_text_UI') - mod = mod or 0 - local text = '+'..localize('$') - local col = G.C.MONEY - if mod < 0 then - text = '-'..localize('$') - col = G.C.RED - else - inc_career_stat('c_dollars_earned', mod) - end - --Ease from current chips to the new number of chips - G.GAME.dollars = G.GAME.dollars + mod - check_and_set_high_score('most_money', G.GAME.dollars) - check_for_unlock({type = 'money'}) - dollar_UI.config.object:update() - G.HUD:recalculate() - --Popup text next to the chips in UI showing number of chips gained/lost - attention_text({ - text = text..tostring(math.abs(mod)), - scale = 0.8, - hold = 0.7, - cover = dollar_UI.parent, - cover_colour = col, - align = 'cm', - }) - --Play a chip sound - play_sound('coin1') - end - if instant then - _mod(mod) - else - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - _mod(mod) - return true - end - })) - end -end - -function ease_discard(mod, instant, silent) - local _mod = function(mod) - if math.abs(math.max(G.GAME.current_round.discards_left, mod)) == 0 then return end - local discard_UI = G.HUD:get_UIE_by_ID('discard_UI_count') - mod = mod or 0 - mod = math.max(-G.GAME.current_round.discards_left, mod) - local text = '+' - local col = G.C.GREEN - if mod < 0 then - text = '' - col = G.C.RED - end - --Ease from current chips to the new number of chips - G.GAME.current_round.discards_left = G.GAME.current_round.discards_left + mod - --Popup text next to the chips in UI showing number of chips gained/lost - discard_UI.config.object:update() - G.HUD:recalculate() - attention_text({ - text = text..mod, - scale = 0.8, - hold = 0.7, - cover = discard_UI.parent, - cover_colour = col, - align = 'cm', - }) - --Play a chip sound - if not silent then play_sound('chips2') end - end - if instant then - _mod(mod) - else - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - _mod(mod) - return true - end - })) - end -end - -function ease_hands_played(mod, instant) - local _mod = function(mod) - local hand_UI = G.HUD:get_UIE_by_ID('hand_UI_count') - mod = mod or 0 - local text = '+' - local col = G.C.GREEN - if mod < 0 then - text = '' - col = G.C.RED - end - --Ease from current chips to the new number of chips - G.GAME.current_round.hands_left = G.GAME.current_round.hands_left + mod - hand_UI.config.object:update() - G.HUD:recalculate() - --Popup text next to the chips in UI showing number of chips gained/lost - attention_text({ - text = text..mod, - scale = 0.8, - hold = 0.7, - cover = hand_UI.parent, - cover_colour = col, - align = 'cm', - }) - --Play a chip sound - play_sound('chips2') - end - if instant then - _mod(mod) - else - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - _mod(mod) - return true - end - })) - end -end - -function ease_ante(mod) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - local ante_UI = G.hand_text_area.ante - mod = mod or 0 - local text = '+' - local col = G.C.IMPORTANT - if mod < 0 then - text = '-' - col = G.C.RED - end - G.GAME.round_resets.ante = G.GAME.round_resets.ante + mod - G.GAME.round_resets.ante_disp = number_format(G.GAME.round_resets.ante) - G.GAME.round_resets.ante = Big and (to_number(math.floor(to_big(G.GAME.round_resets.ante)))) or math.floor(G.GAME.round_resets.ante) - check_and_set_high_score('furthest_ante', G.GAME.round_resets.ante) - ante_UI.config.object:update() - G.HUD:recalculate() - --Popup text next to the chips in UI showing number of chips gained/lost - attention_text({ - text = text..tostring(math.abs(mod)), - scale = 1, - hold = 0.7, - cover = ante_UI.parent, - cover_colour = col, - align = 'cm', - }) - --Play a chip sound - play_sound('highlight2', 0.685, 0.2) - play_sound('generic1') - return true - end - })) -end - -function ease_round(mod) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - local round_UI = G.hand_text_area.round - mod = mod or 0 - local text = '+' - local col = G.C.IMPORTANT - if mod < 0 then - text = '' - col = G.C.RED - end - G.GAME.round = G.GAME.round + mod - check_and_set_high_score('furthest_round', G.GAME.round) - check_and_set_high_score('furthest_ante', G.GAME.round_resets.ante) - round_UI.config.object:update() - G.HUD:recalculate() - --Popup text next to the chips in UI showing number of chips gained/lost - attention_text({ - text = text..tostring(math.abs(mod)), - scale = 1, - hold = 0.7, - cover = round_UI.parent, - cover_colour = col, - align = 'cm', - }) - --Play a chip sound - play_sound('timpani', 0.8) - play_sound('generic1') - return true - end - })) -end - -function ease_value(ref_table, ref_value, mod, floored, timer_type, not_blockable, delay, ease_type) - mod = mod or 0 - - --Ease from current chips to the new number of chips - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - blockable = (not_blockable == false), - blocking = false, - ref_table = ref_table, - ref_value = ref_value, - ease_to = ref_table[ref_value] + mod, - timer = timer_type, - delay = delay or 0.3, - type = ease_type or nil, - func = (function(t) if floored then return math.floor(t) else return t end end) - })) -end - -function ease_background_colour(args) - for k, v in pairs(G.C.BACKGROUND) do - if args.new_colour and (k == 'C' or k == 'L' or k == 'D') then - if args.special_colour and args.tertiary_colour then - local col_key = k == 'L' and 'new_colour' or k == 'C' and 'special_colour' or k == 'D' and 'tertiary_colour' - ease_value(v, 1, args[col_key][1] - v[1], false, nil, true, 0.6) - ease_value(v, 2, args[col_key][2] - v[2], false, nil, true, 0.6) - ease_value(v, 3, args[col_key][3] - v[3], false, nil, true, 0.6) - else - local brightness = k == 'L' and 1.3 or k == 'D' and (args.special_colour and 0.4 or 0.7) or 0.9 - if k == 'C' and args.special_colour then - ease_value(v, 1, args.special_colour[1] - v[1], false, nil, true, 0.6) - ease_value(v, 2, args.special_colour[2] - v[2], false, nil, true, 0.6) - ease_value(v, 3, args.special_colour[3] - v[3], false, nil, true, 0.6) - else - ease_value(v, 1, args.new_colour[1]*brightness - v[1], false, nil, true, 0.6) - ease_value(v, 2, args.new_colour[2]*brightness - v[2], false, nil, true, 0.6) - ease_value(v, 3, args.new_colour[3]*brightness - v[3], false, nil, true, 0.6) - end - end - end - end - if args.contrast then - ease_value(G.C.BACKGROUND, 'contrast', args.contrast - G.C.BACKGROUND.contrast, false, nil, true, 0.6) - end -end - -function ease_colour(old_colour, new_colour, delay) - ease_value(old_colour, 1, new_colour[1] - old_colour[1], false, 'REAL', nil, delay) - ease_value(old_colour, 2, new_colour[2] - old_colour[2], false, 'REAL', nil, delay) - ease_value(old_colour, 3, new_colour[3] - old_colour[3], false, 'REAL', nil, delay) - ease_value(old_colour, 4, new_colour[4] - old_colour[4], false, 'REAL', nil, delay) -end - - -function ease_background_colour_blind(state, blind_override) - local blindname = ((blind_override or (G.GAME.blind and G.GAME.blind.name ~= '' and G.GAME.blind.name)) or 'Small Blind') - local blindname = (blindname == '' and 'Small Blind' or blindname) - - --For the blind related colours - if state == G.STATES.SHOP then - ease_colour(G.C.DYN_UI.MAIN, mix_colours(G.C.RED, G.C.BLACK, 0.9)) - elseif state == G.STATES.TAROT_PACK then - ease_colour(G.C.DYN_UI.MAIN, mix_colours(G.C.WHITE, G.C.BLACK, 0.9)) - elseif state == G.STATES.SPECTRAL_PACK then - ease_colour(G.C.DYN_UI.MAIN, mix_colours(G.C.SECONDARY_SET.Spectral, G.C.BLACK, 0.9)) - elseif state == G.STATES.STANDARD_PACK then - ease_colour(G.C.DYN_UI.MAIN, G.C.RED) - elseif state == G.STATES.BUFFOON_PACK then - ease_colour(G.C.DYN_UI.MAIN, G.C.FILTER) - elseif state == G.STATES.PLANET_PACK then - ease_colour(G.C.DYN_UI.MAIN, mix_colours(G.C.SECONDARY_SET.Planet, G.C.BLACK, 0.9)) - elseif G.GAME.blind then - G.GAME.blind:change_colour() - end - --For the actual background colour - if state == G.STATES.TAROT_PACK then - ease_background_colour{new_colour = G.C.PURPLE, special_colour = darken(G.C.BLACK, 0.2), contrast = 1.5} - elseif state == G.STATES.SPECTRAL_PACK then - ease_background_colour{new_colour = G.C.SECONDARY_SET.Spectral, special_colour = darken(G.C.BLACK, 0.2), contrast = 2} - elseif state == G.STATES.STANDARD_PACK then - ease_background_colour{new_colour = darken(G.C.BLACK, 0.2), special_colour = G.C.RED, contrast = 3} - elseif state == G.STATES.BUFFOON_PACK then - ease_background_colour{new_colour = G.C.FILTER, special_colour = G.C.BLACK, contrast = 2} - elseif state == G.STATES.PLANET_PACK then - ease_background_colour{new_colour = G.C.BLACK, contrast = 3} - elseif G.GAME.won then - ease_background_colour{new_colour = G.C.BLIND.won, contrast = 1} - elseif blindname == 'Small Blind' or blindname == 'Big Blind' or blindname == '' then - ease_background_colour{new_colour = G.C.BLIND['Small'], contrast = 1} - else - - local boss_col = G.C.BLACK - for k, v in pairs(G.P_BLINDS) do - if v.name == blindname then - if v.boss.showdown then - ease_background_colour{new_colour = G.C.BLUE, special_colour = G.C.RED, tertiary_colour = darken(G.C.BLACK, 0.4), contrast = 3} - return - end - boss_col = v.boss_colour or G.C.BLACK - end - end - ease_background_colour{new_colour = lighten(mix_colours(boss_col, G.C.BLACK, 0.3), 0.1), special_colour = boss_col, contrast = 2} - end -end - -function delay(time, queue) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = time or 1, - func = function() - return true - end - }), queue) -end - -function add_joker(joker, edition, silent, eternal) - local _area = G.P_CENTERS[joker].consumeable and G.consumeables or G.jokers - local _T = _area and _area.T or {x = G.ROOM.T.w/2 - G.CARD_W/2, y = G.ROOM.T.h/2 - G.CARD_H/2} - local card = Card(_T.x, _T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS[joker],{discover = true, bypass_discovery_center = true, bypass_discovery_ui = true, bypass_back = G.GAME.selected_back.pos }) - card:start_materialize(nil, silent) - if _area then card:add_to_deck() end - if edition then card:set_edition{[edition] = true} end - if eternal then card:set_eternal(true) end - if _area and card.ability.set == 'Joker' then _area:emplace(card) - elseif G.consumeables then G.consumeables:emplace(card) end - card.created_on_pause = nil - return card -end - -function draw_card(from, to, percent, dir, sort, card, delay, mute, stay_flipped, vol, discarded_only) - percent = percent or 50 - delay = delay or 0.1 - if dir == 'down' then - percent = 1-percent - end - sort = sort or false - local drawn = nil - - G.E_MANAGER:add_event(Event({ - trigger = 'before', - delay = delay, - func = function() - if card then - if from then card = from:remove_card(card) end - if card then drawn = true end - if card and to == G.hand and not card.states.visible then - card.states.visible = true - end - local stay_flipped = G.GAME and G.GAME.blind and G.GAME.blind:stay_flipped(to, card) - if G.GAME.modifiers.flipped_cards and to == G.hand then - if pseudorandom(pseudoseed('flipped_card')) < 1/G.GAME.modifiers.flipped_cards then - stay_flipped = true - end - end - to:emplace(card, nil, stay_flipped) - else - if to:draw_card_from(from, stay_flipped, discarded_only) then drawn = true end - end - if not mute and drawn then - if from == G.deck or from == G.hand or from == G.play or from == G.jokers or from == G.consumeables or from == G.discard then - G.VIBRATION = G.VIBRATION + 0.6 - end - play_sound('card1', 0.85 + percent*0.2/100, 0.6*(vol or 1)) - end - if sort then - to:sort() - end - return true - end - })) -end - -function highlight_card(card, percent, dir) - percent = percent or 0.5 - local highlight = true - if dir == 'down' then - percent = 1-percent - highlight = false - end - - G.E_MANAGER:add_event(Event({ - trigger = 'before', - delay = 0.1, - func = function() - card:highlight(highlight) - play_sound('cardSlide1', 0.85 + percent*0.2) - return true - end - })) -end - -function play_area_status_text(text, silent, delay) - local delay = delay or 0.6 - G.E_MANAGER:add_event(Event({ - trigger = (delay==0 and 'immediate' or 'before'), - delay = delay, - func = function() - attention_text({ - scale = 0.9, text = text, hold = 0.9, align = 'tm', - major = G.play, offset = {x = 0, y = -1} - }) - if not silent then - G.ROOM.jiggle = G.ROOM.jiggle + 2 - play_sound('cardFan2') - end - return true - end - })) -end - -function level_up_hand(card, hand, instant, amount) - amount = amount or 1 - if not next(find_joker('cry-Universum')) then - G.GAME.hands[hand].level = math.max(0, G.GAME.hands[hand].level + amount) - G.GAME.hands[hand].mult = math.max(G.GAME.hands[hand].mult + G.GAME.hands[hand].l_mult*amount, 1) - G.GAME.hands[hand].chips = math.max(G.GAME.hands[hand].chips + G.GAME.hands[hand].l_chips*amount, 1) - else - universum_mod = 1 - for i = 1, #G.jokers.cards do - local effects = G.jokers.cards[i]:calculate_joker({cry_universum = true, callback = function(card, effects) - universum_mod = universum_mod * (effects and effects.mod or 1) - end}) - end - G.GAME.hands[hand].level = math.max(0, G.GAME.hands[hand].level + amount) - G.GAME.hands[hand].mult = math.max(G.GAME.hands[hand].mult * (universum_mod)^amount, 1) - G.GAME.hands[hand].chips = math.max(G.GAME.hands[hand].chips * (universum_mod)^amount, 1) - end - if not instant then - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function() - play_sound('tarot1') - if card and card.juice_up then card:juice_up(0.8, 0.5) end - G.TAROT_INTERRUPT_PULSE = true - return true end })) - update_hand_text({delay = 0}, {mult = cry_ascend(G.GAME.hands[hand].mult), StatusText = true}) - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.9, func = function() - play_sound('tarot1') - if card and card.juice_up then card:juice_up(0.8, 0.5) end - return true end })) - update_hand_text({delay = 0}, {chips = cry_ascend(G.GAME.hands[hand].chips), StatusText = true}) - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.9, func = function() - play_sound('tarot1') - if card and card.juice_up then card:juice_up(0.8, 0.5) end - G.TAROT_INTERRUPT_PULSE = nil - return true end })) - update_hand_text({sound = 'button', volume = 0.7, pitch = 0.9, delay = 0}, {level=G.GAME.hands[hand].level}) - delay(1.3) - end - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() check_for_unlock{type = 'upgrade_hand', hand = hand, level = G.GAME.hands[hand].level} return true end) - })) -end - -function update_hand_text(config, vals) - G.E_MANAGER:add_event(Event({--This is the Hand name text for the poker hand - trigger = 'before', - blockable = not config.immediate, - delay = config.delay or 0.8, - func = function() - local col = G.C.GREEN - if vals.chips and G.GAME.current_round.current_hand.chips ~= vals.chips then - local delta = (is_number(vals.chips) and is_number(G.GAME.current_round.current_hand.chips)) and (vals.chips - G.GAME.current_round.current_hand.chips) or 0 - if to_big(delta) < to_big(0) then delta = number_format(delta); col = G.C.RED - elseif to_big(delta) > to_big(0) then delta = '+'..number_format(delta) - else delta = number_format(delta) - end - if type(vals.chips) == 'string' then delta = vals.chips end - G.GAME.current_round.current_hand.chips = vals.chips - G.hand_text_area.chips:update(0) - if vals.StatusText then - attention_text({ - text =delta, - scale = 0.8, - hold = 1, - cover = G.hand_text_area.chips.parent, - cover_colour = mix_colours(G.C.CHIPS, col, 0.1), - emboss = 0.05, - align = 'cm', - cover_align = 'cr' - }) - end - end - if vals.mult and G.GAME.current_round.current_hand.mult ~= vals.mult then - local delta = (is_number(vals.mult) and is_number(G.GAME.current_round.current_hand.mult))and (vals.mult - G.GAME.current_round.current_hand.mult) or 0 - if to_big(delta) < to_big(0) then delta = number_format(delta); col = G.C.RED - elseif to_big(delta) > to_big(0) then delta = '+'..number_format(delta) - else delta = number_format(delta) - end - if type(vals.mult) == 'string' then delta = vals.mult end - G.GAME.current_round.current_hand.mult = vals.mult - G.hand_text_area.mult:update(0) - if vals.StatusText then - attention_text({ - text =delta, - scale = 0.8, - hold = 1, - cover = G.hand_text_area.mult.parent, - cover_colour = mix_colours(G.C.MULT, col, 0.1), - emboss = 0.05, - align = 'cm', - cover_align = 'cl' - }) - end - if not G.TAROT_INTERRUPT then G.hand_text_area.mult:juice_up() end - end - if vals.handname and G.GAME.current_round.current_hand.handname ~= vals.handname then - G.GAME.current_round.current_hand.handname = vals.handname - if not config.nopulse then - G.hand_text_area.handname.config.object:pulse(0.2) - end - end - if vals.chip_total then G.GAME.current_round.current_hand.chip_total = vals.chip_total;G.hand_text_area.chip_total.config.object:pulse(0.5) end - if vals.level and G.GAME.current_round.current_hand.hand_level ~= ' '..localize('k_lvl')..tostring(vals.level) then - if vals.level == '' then - G.GAME.current_round.current_hand.hand_level = vals.level - else - G.GAME.current_round.current_hand.hand_level = ' '..localize('k_lvl')..tostring(vals.level) - if type(vals.level) == 'number' then - G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[math.min(vals.level, 7)] - else - G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[1] - end - G.hand_text_area.hand_level:juice_up() - end - end - if config.sound and not config.modded then play_sound(config.sound, config.pitch or 1, config.volume or 1) end - if config.modded then - SMODS.juice_up_blind() - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.06*G.SETTINGS.GAMESPEED, blockable = false, blocking = false, func = function() - play_sound('tarot2', 0.76, 0.4);return true end})) - play_sound('tarot2', 1, 0.4) - end - return true - end})) -end - -function eval_card(card, context) - local enhancement_calculated = false - local center = card.config.center - context = context or {} - local ret = {} - - if context.repetition_only then - if card.ability.set == 'Enhanced' and center.calculate and type(center.calculate) == 'function' then - center:calculate(card, context, ret) - enhancement_calculated = true - end - local seals = card:calculate_seal(context) - if seals then - ret.seals = seals - end - return ret - end - - if context.cardarea == G.play then - local chips = card:get_chip_bonus() - if chips > 0 then - ret.chips = chips - end - - local mult = card:get_chip_mult() - if mult > 0 then - ret.mult = mult - end - - local x_mult = card:get_chip_x_mult(context) - if x_mult > 0 then - ret.x_mult = x_mult - end - - local x_chips = card:get_chip_x_bonus() - if x_chips > 0 then - ret.x_chips = x_chips - end - - local e_chips = card:get_chip_e_bonus() - if e_chips > 0 then - ret.e_chips = e_chips - end - - local ee_chips = card:get_chip_ee_bonus() - if ee_chips > 0 then - ret.ee_chips = ee_chips - end - - local eee_chips = card:get_chip_eee_bonus() - if eee_chips > 0 then - ret.eee_chips = eee_chips - end - - local hyper_chips = card:get_chip_hyper_bonus() - if type(hyper_chips) == 'table' and hyper_chips[1] > 0 and hyper_chips[2] > 0 then - ret.hyper_chips = hyper_chips - end - - local e_mult = card:get_chip_e_mult() - if e_mult > 0 then - ret.e_mult = e_mult - end - - local ee_mult = card:get_chip_ee_mult() - if ee_mult > 0 then - ret.ee_mult = ee_mult - end - - local eee_mult = card:get_chip_eee_mult() - if eee_mult > 0 then - ret.eee_mult = eee_mult - end - - local hyper_mult = card:get_chip_hyper_mult() - if type(hyper_mult) == 'table' and hyper_mult[1] > 0 and hyper_mult[2] > 0 then - ret.hyper_mult = hyper_mult - end - local p_dollars = card:get_p_dollars() - if p_dollars > 0 then - ret.p_dollars = p_dollars - end - - if card.ability.set == 'Enhanced' and center.calculate and type(center.calculate) == 'function' then - center:calculate(card, context, ret) - enhancement_calculated = true - end - local jokers = card:calculate_joker(context) - if jokers then - ret.jokers = jokers - end - - local edition = card:get_edition(context) - if edition then - ret.edition = edition - end - end - - if context.cardarea == G.hand then - local h_mult = card:get_chip_h_mult() - if h_mult > 0 then - ret.h_mult = h_mult - end - - local h_x_mult = card:get_chip_h_x_mult() - if h_x_mult > 0 then - ret.x_mult = h_x_mult - end - - if card.ability.set == 'Enhanced' and center.calculate and type(center.calculate) == 'function' then - center:calculate(card, context, ret) - enhancement_calculated = true - end - local jokers = card:calculate_joker(context) - if jokers then - ret.jokers = jokers - end - end - - if not card.ability.extra_enhancement and card.edition and card.edition.key then - local ed = SMODS.Centers[card.edition.key] - if ed.calculate and type(ed.calculate) == 'function' then - context.from_playing_card = true - ed:calculate(card, context) - context.from_playing_card = nil - end - end - if not enhancement_calculated and card.ability.set == 'Enhanced' and center.calculate and type(center.calculate) == 'function' then - center:calculate(card, context, ret) - enhancement_calculated = true - end - local seals = not card.ability.extra_enhancement and card:calculate_seal(context) - if seals then - ret.seals = seals - end - if context.cardarea == G.jokers or context.card == G.consumeables then - local jokers = nil - if context.edition then - jokers = card:get_edition(context) - elseif context.other_joker then - jokers = context.other_joker:calculate_joker(context) - else - jokers = card:calculate_joker(context) - end - if jokers then - ret.jokers = jokers - end - end - - return ret -end - -function set_alerts() - if G.REFRESH_ALERTS then - G.REFRESH_ALERTS = nil - local alert_joker, alert_voucher, alert_tarot, alert_planet, alert_spectral, alert_blind, alert_edition, alert_tag, alert_seal, alert_booster = false,false,false,false,false,false,false,false,false,false - for k, v in pairs(G.P_CENTERS) do - if v.discovered and not v.alerted and not v.no_collection then - if v.set == 'Voucher' then alert_voucher = true end - if v.set == 'Tarot' then alert_tarot = true end - if v.set == 'Planet' then alert_planet = true end - if v.set == 'Spectral' then alert_spectral = true end - if v.set == 'Joker' then alert_joker = true end - if v.set == 'Edition' then alert_edition = true end - if v.set == 'Booster' then alert_booster = true end - end - end - for k, v in pairs(G.P_BLINDS) do - if v.discovered and not v.alerted and not v.no_collection then - alert_blind = true - end - end - for k, v in pairs(G.P_TAGS) do - if v.discovered and not v.alerted and not v.no_collection then - alert_tag = true - end - end - for k, v in pairs(G.P_SEALS) do - if v.discovered and not v.alerted and not v.no_collection then - alert_seal = true - end - end - - local alert_any = alert_voucher or alert_joker or alert_tarot or alert_planet or alert_spectral or alert_blind or alert_edition or alert_seal or alert_tag - - G.ARGS.set_alerts_alertables = G.ARGS.set_alerts_alertables or { - {id = 'your_collection', alert_uibox_name = 'your_collection_alert'}, - {id = 'your_collection_jokers', alert_uibox_name = 'your_collection_jokers_alert'}, - {id = 'your_collection_tarots', alert_uibox_name = 'your_collection_tarots_alert'}, - {id = 'your_collection_planets', alert_uibox_name = 'your_collection_planets_alert'}, - {id = 'your_collection_spectrals', alert_uibox_name = 'your_collection_spectrals_alert'}, - {id = 'your_collection_vouchers', alert_uibox_name = 'your_collection_vouchers_alert'}, - {id = 'your_collection_editions', alert_uibox_name = 'your_collection_editions_alert'}, - {id = 'your_collection_blinds', alert_uibox_name = 'your_collection_blinds_alert'}, - {id = 'your_collection_tags', alert_uibox_name = 'your_collection_tags_alert'}, - {id = 'your_collection_seals', alert_uibox_name = 'your_collection_seals_alert'}, - {id = 'your_collection_boosters', alert_uibox_name = 'your_collection_boosters_alert'}, - } - G.ARGS.set_alerts_alertables[1].should_alert = alert_any - G.ARGS.set_alerts_alertables[2].should_alert = alert_joker - G.ARGS.set_alerts_alertables[3].should_alert = alert_tarot - G.ARGS.set_alerts_alertables[4].should_alert = alert_planet - G.ARGS.set_alerts_alertables[5].should_alert = alert_spectral - G.ARGS.set_alerts_alertables[6].should_alert = alert_voucher - G.ARGS.set_alerts_alertables[7].should_alert = alert_edition - G.ARGS.set_alerts_alertables[8].should_alert = alert_blind - G.ARGS.set_alerts_alertables[9].should_alert = alert_tag - G.ARGS.set_alerts_alertables[10].should_alert = alert_seal - G.ARGS.set_alerts_alertables[11].should_alert = alert_booster - table.insert(G.ARGS.set_alerts_alertables, {id = 'mods_button', alert_uibox_name = 'mods_button_alert', should_alert = SMODS.mod_button_alert}) - - for k, v in ipairs(G.ARGS.set_alerts_alertables) do - if G.OVERLAY_MENU and G.OVERLAY_MENU:get_UIE_by_ID(v.id) then - if v.should_alert then - if not G[v.alert_uibox_name] then - G[v.alert_uibox_name] = UIBox{ - definition = create_UIBox_card_alert({red_bad = true}), - config = {align="tri", offset = {x = 0.05, y = -0.05}, major = G.OVERLAY_MENU:get_UIE_by_ID(v.id), instance_type = 'ALERT'} - } - G[v.alert_uibox_name].states.collide.can = false - end - elseif G[v.alert_uibox_name] then - G[v.alert_uibox_name]:remove() - G[v.alert_uibox_name] = nil - end - elseif G[v.alert_uibox_name] then - G[v.alert_uibox_name]:remove() - G[v.alert_uibox_name] = nil - end - end - - if G.MAIN_MENU_UI then - if alert_any then - if not G.collection_alert then - G.collection_alert = UIBox{definition = create_UIBox_card_alert(), config = {align="tri", offset = {x = 0.05, y = -0.05}, major = G.MAIN_MENU_UI:get_UIE_by_ID('collection_button')}} - G.collection_alert.states.collide.can = false - end - elseif G.collection_alert then - G.collection_alert:remove() - G.collection_alert = nil - end - elseif G.collection_alert then - G.collection_alert:remove() - G.collection_alert = nil - end - end -end - -function set_main_menu_UI() - G.MAIN_MENU_UI = UIBox{ - definition = create_UIBox_main_menu_buttons(), - config = {align="bmi", offset = {x=0,y=10}, major = G.ROOM_ATTACH, bond = 'Weak'} - } - G.MAIN_MENU_UI.alignment.offset.y = 0 - G.MAIN_MENU_UI:align_to_major() - G.E_MANAGER:add_event(Event({ - blockable = false, - blocking = false, - func = (function() - if (not G.F_DISP_USERNAME) or (type(G.F_DISP_USERNAME) == 'string') then - G.PROFILE_BUTTON = UIBox{ - definition = create_UIBox_profile_button(), - config = {align="bli", offset = {x=-10,y=0}, major = G.ROOM_ATTACH, bond = 'Weak'}} - G.PROFILE_BUTTON.alignment.offset.x = 0 - G.PROFILE_BUTTON:align_to_major() - return true - end - end) - })) - - - G.CONTROLLER:snap_to{node = G.MAIN_MENU_UI:get_UIE_by_ID('main_menu_play')} -end - -function card_eval_status_text(card, eval_type, amt, percent, dir, extra) - percent = percent or (0.9 + 0.2*math.random()) - if dir == 'down' then - percent = 1-percent - end - - if extra and extra.focus then card = extra.focus end - - local text = '' - local sound = nil - local volume = 1 - local card_aligned = 'bm' - local y_off = 0.15*G.CARD_H - if card.area == G.jokers or card.area == G.consumeables then - y_off = 0.05*card.T.h - elseif card.area == G.hand then - y_off = -0.05*G.CARD_H - card_aligned = 'tm' - elseif card.area == G.play then - y_off = -0.05*G.CARD_H - card_aligned = 'tm' - elseif card.jimbo then - y_off = -0.05*G.CARD_H - card_aligned = 'tm' - end - local config = {} - local delay = 0.65 - local colour = config.colour or (extra and extra.colour) or ( G.C.FILTER ) - local extrafunc = nil - - if eval_type == 'debuff' then - sound = 'cancel' - amt = 1 - colour = G.C.RED - config.scale = 0.6 - text = localize('k_debuffed') - elseif eval_type == 'chips' then - sound = 'chips1' - amt = amt - colour = G.C.CHIPS - text = localize{type='variable',key='a_chips',vars={amt}} - delay = 0.6 - elseif eval_type == 'mult' then - sound = 'multhit1'--'other1' - amt = amt - text = localize{type='variable',key='a_mult',vars={amt}} - colour = G.C.MULT - config.type = 'fade' - config.scale = 0.7 - elseif (eval_type == 'x_mult') or (eval_type == 'h_x_mult') then - sound = 'multhit2' - volume = 0.7 - amt = amt - text = localize{type='variable',key='a_xmult',vars={amt}} - colour = G.C.XMULT - config.type = 'fade' - config.scale = 0.7 - elseif eval_type == 'h_mult' then - sound = 'multhit1' - amt = amt - text = localize{type='variable',key='a_mult',vars={amt}} - colour = G.C.MULT - config.type = 'fade' - config.scale = 0.7 - elseif eval_type == 'x_chips' then - sound = 'talisman_xchip' - amt = amt - text = 'X' .. amt - colour = G.C.CHIPS - config.type = 'fade' - config.scale = 0.7 - elseif eval_type == 'e_chips' then - sound = 'talisman_echip' - amt = amt - text = '^' .. amt - colour = G.C.CHIPS - config.type = 'fade' - config.scale = 0.7 - elseif eval_type == 'ee_chips' then - sound = 'talisman_eechip' - amt = amt - text = '^^' .. amt - colour = G.C.CHIPS - config.type = 'fade' - config.scale = 0.7 - elseif eval_type == 'eee_chips' then - sound = 'talisman_eeechip' - amt = amt - text = '^^^' .. amt - colour = G.C.CHIPS - config.type = 'fade' - config.scale = 0.7 - elseif eval_type == 'hyper_chips' then - sound = 'talisman_eeechip' - text = (amt[1] > 5 and ('{' .. tostring(amt[1]) .. '}') or string.rep('^', amt[1])) .. tostring(amt[2]) - amt = amt[2] - colour = G.C.CHIPS - config.type = 'fade' - config.scale = 0.7 - elseif eval_type == 'e_mult' then - sound = 'talisman_emult' - amt = amt - text = '^' .. amt .. ' Mult' - colour = G.C.MULT - config.type = 'fade' - config.scale = 0.7 - elseif eval_type == 'ee_mult' then - sound = 'talisman_eemult' - amt = amt - text = '^^' .. amt .. ' Mult' - colour = G.C.MULT - config.type = 'fade' - config.scale = 0.7 - elseif eval_type == 'eee_mult' then - sound = 'talisman_eeemult' - amt = amt - text = '^^^' .. amt .. ' Mult' - colour = G.C.MULT - config.type = 'fade' - config.scale = 0.7 - elseif eval_type == 'hyper_mult' then - sound = 'talisman_eeemult' - text = (amt[1] > 5 and ('{' .. tostring(amt[1]) .. '}') or string.rep('^', amt[1])) .. tostring(amt[2]) .. ' Mult' - amt = amt[2] - colour = G.C.MULT - config.type = 'fade' - config.scale = 0.7 - elseif eval_type == 'dollars' then - sound = 'coin3' - amt = amt - text = (amt <-0.01 and '-' or '')..localize("$")..tostring(math.abs(amt)) - colour = amt <-0.01 and G.C.RED or G.C.MONEY - elseif eval_type == 'swap' then - sound = 'generic1' - amt = amt - text = localize('k_swapped_ex') - colour = G.C.PURPLE - elseif eval_type == 'extra' or eval_type == 'jokers' then - sound = extra.edition and 'foil2' or extra.mult_mod and 'multhit1' or extra.Xmult_mod and 'multhit2' or extra.Xchip_mod and 'talisman_xchip' or extra.Echip_mod and 'talisman_echip' or extra.Emult_mod and 'talisman_emult' or extra.EEchip_mod and 'talisman_eechip' or extra.EEmult_mod and 'talisman_eemult' or (extra.EEEchip_mod or extra.hyperchip_mod) and 'talisman_eeechip' or (extra.EEEmult_mod or extra.hypermult_mod) and 'talisman_eeemult' or 'generic1' - if extra.edition then - colour = G.C.DARK_EDITION - end - volume = extra.edition and 0.3 or sound == 'multhit2' and 0.7 or 1 - delay = extra.delay or 0.75 - amt = 1 - text = extra.message or text - if not text or text == '' then return end - if not extra.edition and (extra.mult_mod or extra.Xmult_mod) then - colour = G.C.MULT - end - if extra.chip_mod then - config.type = 'fall' - colour = G.C.CHIPS - config.scale = 0.7 - elseif extra.swap then - config.type = 'fall' - colour = G.C.PURPLE - config.scale = 0.7 - else - config.type = 'fall' - config.scale = 0.7 - end - end - delay = delay*1.25 - - if amt > 0 or amt < 0 then - if extra and extra.instant then - if extrafunc then extrafunc() end - attention_text({ - text = text, - scale = config.scale or 1, - hold = delay - 0.2, - backdrop_colour = colour, - align = card_aligned, - major = card, - offset = {x = 0, y = y_off} - }) - play_sound(sound, 0.8+percent*0.2, volume) - if not extra or not extra.no_juice then - if card and card.juice_up then card:juice_up(0.6, 0.1) end - G.ROOM.jiggle = G.ROOM.jiggle + 0.7 - end - else - G.E_MANAGER:add_event(Event({ --Add bonus chips from this card - trigger = 'before', - delay = delay, - func = function() - if extrafunc then extrafunc() end - attention_text({ - text = text, - scale = config.scale or 1, - hold = delay - 0.2, - backdrop_colour = colour, - align = card_aligned, - major = card, - offset = {x = 0, y = y_off} - }) - play_sound(sound, 0.8+percent*0.2, volume) - if not extra or not extra.no_juice then - if card and card.juice_up then card:juice_up(0.6, 0.1) end - G.ROOM.jiggle = G.ROOM.jiggle + 0.7 - end - return true - end - })) - end - end - if extra and extra.playing_cards_created then - playing_card_joker_effects(extra.playing_cards_created) - end -end - -function add_round_eval_row(config) - local config = config or {} - local width = G.round_eval.T.w - 0.51 - local num_dollars = config.dollars or 1 - Handy.insta_cash_out.dollars = config.dollars or 1 - local scale = 0.9 - - if config.name ~= 'bottom' then - total_cashout_rows = (total_cashout_rows or 0) + 1 - if total_cashout_rows > 7 then - return - end - if config.name ~= 'blind1' then - if not G.round_eval.divider_added then - G.E_MANAGER:add_event(Event({ - trigger = 'after',delay = 0.25, - func = function() - local spacer = {n=G.UIT.R, config={align = "cm", minw = width}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {'......................................'}, colours = {G.C.WHITE},shadow = true, float = true, y_offset = -30, scale = 0.45, spacing = 13.5, font = G.LANGUAGES['en-us'].font, pop_in = 0})}} - }} - G.round_eval:add_child(spacer,G.round_eval:get_UIE_by_ID(config.bonus and 'bonus_round_eval' or 'base_round_eval')) - return true - end - })) - delay(0.6) - G.round_eval.divider_added = true - end - else - delay(0.2) - end - - delay(0.2) - - G.E_MANAGER:add_event(Event({ - trigger = 'before',delay = 0.5, - func = function() - --Add the far left text and context first: - local left_text = {} - if config.name == 'blind1' then - local stake_sprite = get_stake_sprite(G.GAME.stake or 1, 0.5) - local obj = G.GAME.blind.config.blind - local blind_sprite = AnimatedSprite(0, 0, 1.2, 1.2, G.ANIMATION_ATLAS[obj.atlas] or G.ANIMATION_ATLAS['blind_chips'], copy_table(G.GAME.blind.pos)) - blind_sprite:define_draw_steps({ - {shader = 'dissolve', shadow_height = 0.05}, - {shader = 'dissolve'} - }) - table.insert(left_text, {n=G.UIT.O, config={w=1.2,h=1.2 , object = blind_sprite, hover = true, can_collide = false}}) - - table.insert(left_text, - config.saved and - {n=G.UIT.C, config={padding = 0.05, align = 'cm'}, nodes={ - {n=G.UIT.R, config={align = 'cm'}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {' '..(G.GAME.current_round.semicolon and ";" or localize('ph_mr_bones'))..' '}, colours = {(G.GAME.current_round.semicolon and G.C.SET.Code or G.C.FILTER)}, shadow = true, pop_in = 0, scale = 0.5*scale, silent = true})}} - }} - }} - or {n=G.UIT.C, config={padding = 0.05, align = 'cm'}, nodes={ - {n=G.UIT.R, config={align = 'cm'}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {' '..localize('ph_score_at_least')..' '}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4*scale, silent = true})}} - }}, - {n=G.UIT.R, config={align = 'cm', minh = 0.8}, nodes={ - {n=G.UIT.O, config={w=0.5,h=0.5 , object = stake_sprite, hover = true, can_collide = false}}, - {n=G.UIT.T, config={text = G.GAME.blind.chip_text, scale = scale_number(G.GAME.blind.chips, scale, 100000), colour = G.C.RED, shadow = true}} - }} - }}) - elseif string.find(config.name, 'tag') then - local blind_sprite = Sprite(0, 0, 0.7,0.7, G.ASSET_ATLAS['tags'], copy_table(config.pos)) - blind_sprite:define_draw_steps({ - {shader = 'dissolve', shadow_height = 0.05}, - {shader = 'dissolve'} - }) - blind_sprite:juice_up() - table.insert(left_text, {n=G.UIT.O, config={w=0.7,h=0.7 , object = blind_sprite, hover = true, can_collide = false}}) - table.insert(left_text, {n=G.UIT.O, config={object = DynaText({string = {config.condition}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4*scale, silent = true})}}) - elseif config.name == 'hands' then - table.insert(left_text, {n=G.UIT.T, config={text = config.disp or config.dollars, scale = 0.8*scale, colour = G.C.BLUE, shadow = true, juice = true}}) - table.insert(left_text, {n=G.UIT.O, config={object = DynaText({string = {" "..localize{type = 'variable', key = 'remaining_hand_money', vars = {G.GAME.modifiers.money_per_hand or 1}}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4*scale, silent = true})}}) - elseif config.name == 'discards' then - table.insert(left_text, {n=G.UIT.T, config={text = config.disp or config.dollars, scale = 0.8*scale, colour = G.C.RED, shadow = true, juice = true}}) - table.insert(left_text, {n=G.UIT.O, config={object = DynaText({string = {" "..localize{type = 'variable', key = 'remaining_discard_money', vars = {G.GAME.modifiers.money_per_discard or 0}}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4*scale, silent = true})}}) - elseif string.find(config.name, 'joker') then - table.insert(left_text, {n=G.UIT.O, config={object = DynaText({string = localize{type = 'name_text', set = config.card.config.center.set, key = config.card.config.center.key}, colours = {G.C.FILTER}, shadow = true, pop_in = 0, scale = 0.6*scale, silent = true})}}) - elseif config.name == 'interest_payload' then - table.insert(left_text, {n=G.UIT.T, config={text = num_dollars, scale = 0.8*scale, colour = G.C.SECONDARY_SET.Code, shadow = true, juice = true}}) - table.insert(left_text,{n=G.UIT.O, config={object = DynaText({string = {" "..localize{type = 'variable', key = 'interest', vars = {G.GAME.interest_amount*config.payload, 5, G.GAME.interest_amount*config.payload*G.GAME.interest_cap/5}}}, colours = {G.C.SECONDARY_SET.Code}, shadow = true, pop_in = 0, scale = 0.4*scale, silent = true})}}) - elseif config.name == 'interest' then - table.insert(left_text, {n=G.UIT.T, config={text = num_dollars, scale = 0.8*scale, colour = G.C.MONEY, shadow = true, juice = true}}) - table.insert(left_text,{n=G.UIT.O, config={object = DynaText({string = {" "..localize{type = 'variable', key = 'interest', vars = {G.GAME.interest_amount, 5, G.GAME.interest_amount*G.GAME.interest_cap/5}}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4*scale, silent = true})}}) - end - local full_row = {n=G.UIT.R, config={align = "cm", minw = 5}, nodes={ - {n=G.UIT.C, config={padding = 0.05, minw = width*0.55, minh = 0.61, align = "cl"}, nodes=left_text}, - {n=G.UIT.C, config={padding = 0.05,minw = width*0.45, align = "cr"}, nodes={{n=G.UIT.C, config={align = "cm", id = 'dollar_'..config.name},nodes={}}}} - }} - - if config.name == 'blind1' then - G.GAME.blind:juice_up() - end - G.round_eval:add_child(full_row,G.round_eval:get_UIE_by_ID(config.bonus and 'bonus_round_eval' or 'base_round_eval')) - play_sound('cancel', config.pitch or 1) - play_sound('highlight1',( 1.5*config.pitch) or 1, 0.2) - if config.card then config.card:juice_up(0.7, 0.46) end - return true - end - })) - local dollar_row = 0 - if num_dollars > 60 or num_dollars < -60 then - local dollar_string - if num_dollars < 0 then --if negative - dollar_string = '-'..localize('$')..(num_dollars*-1) - G.E_MANAGER:add_event(Event({ - trigger = 'before',delay = 0.38, - func = function() - G.round_eval:add_child( - {n=G.UIT.R, config={align = "cm", id = 'dollar_row_'..(dollar_row+1)..'_'..config.name}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('$')..(num_dollars*-1)}, colours = {G.C.MONEY}, shadow = true, pop_in = 0, scale = 0.65, float = true})}} - }}, - G.round_eval:get_UIE_by_ID('dollar_'..config.name)) - play_sound('coin3', 0.9+0.2*math.random(), 0.7) - play_sound('coin6', 1.3, 0.8) - return true - end - })) - else --if positive - dollar_string = localize('$')..num_dollars - G.E_MANAGER:add_event(Event({ - trigger = 'before',delay = 0.38, - func = function() - G.round_eval:add_child( - {n=G.UIT.R, config={align = "cm", id = 'dollar_row_'..(dollar_row+1)..'_'..config.name}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {localize('$')..format_ui_value(num_dollars)}, colours = {G.C.MONEY}, shadow = true, pop_in = 0, scale = 0.65, float = true})}} - }}, - G.round_eval:get_UIE_by_ID('dollar_'..config.name)) - - play_sound('coin3', 0.9+0.2*math.random(), 0.7) - play_sound('coin6', 1.3, 0.8) - return true - end - })) - --asdf - end else - local dollars_to_loop - if num_dollars < 0 then dollars_to_loop = (num_dollars*-1)+1 else dollars_to_loop = num_dollars end - for i = 1, dollars_to_loop do - G.E_MANAGER:add_event(Event({ - trigger = 'before',delay = 0.18 - ((num_dollars > 20 and 0.13) or (num_dollars > 9 and 0.1) or 0), - func = function() - if i%30 == 1 then - G.round_eval:add_child( - {n=G.UIT.R, config={align = "cm", id = 'dollar_row_'..(dollar_row+1)..'_'..config.name}, nodes={}}, - G.round_eval:get_UIE_by_ID('dollar_'..config.name)) - dollar_row = dollar_row+1 - end - - local r - if i == 1 and num_dollars < 0 then - r = {n=G.UIT.T, config={text = '-', colour = G.C.RED, scale = ((num_dollars < -20 and 0.28) or (num_dollars < -9 and 0.43) or 0.58), shadow = true, hover = true, can_collide = false, juice = true}} - play_sound('coin3', 0.9+0.2*math.random(), 0.7 - (num_dollars < -20 and 0.2 or 0)) - else - if num_dollars < 0 then r = {n=G.UIT.T, config={text = localize('$'), colour = G.C.RED, scale = ((num_dollars > 20 and 0.28) or (num_dollars > 9 and 0.43) or 0.58), shadow = true, hover = true, can_collide = false, juice = true}} - else r = {n=G.UIT.T, config={text = localize('$'), colour = G.C.MONEY, scale = ((num_dollars > 20 and 0.28) or (num_dollars > 9 and 0.43) or 0.58), shadow = true, hover = true, can_collide = false, juice = true}} end - end - play_sound('coin3', 0.9+0.2*math.random(), 0.7 - (num_dollars > 20 and 0.2 or 0)) - - if config.name == 'blind1' then - G.GAME.current_round.dollars_to_be_earned = G.GAME.current_round.dollars_to_be_earned:sub(2) - end - - G.round_eval:add_child(r,G.round_eval:get_UIE_by_ID('dollar_row_'..(dollar_row)..'_'..config.name)) - G.VIBRATION = G.VIBRATION + 0.4 - return true - end - })) - end - end - else - delay(0.4) - G.E_MANAGER:add_event(Event({ - trigger = 'before',delay = 0.5, - func = function() - UIBox{ - definition = {n=G.UIT.ROOT, config={align = 'cm', colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={id = 'cash_out_button', align = "cm", padding = 0.1, minw = 7, r = 0.15, colour = G.GAME.current_round.semicolon and G.C.SET.Code or G.C.ORANGE, shadow = true, hover = true, one_press = true, button = 'cash_out', focus_args = {snap_to = true}}, nodes={ - {n=G.UIT.T, config={text = G.GAME.current_round.semicolon and localize('k_end_blind') or (localize('b_cash_out')..": "), scale = 1, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - {n=G.UIT.T, config={text = localize('$')..format_ui_value(config.dollars), scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}} - }},}}, - config = { - align = 'tmi', - offset ={x=0,y=0.4}, - major = G.round_eval} - } - - --local left_text = {n=G.UIT.R, config={id = 'cash_out_button', align = "cm", padding = 0.1, minw = 2, r = 0.15, colour = G.C.ORANGE, shadow = true, hover = true, one_press = true, button = 'cash_out', focus_args = {snap_to = true}}, nodes={ - -- {n=G.UIT.T, config={text = localize('b_cash_out')..": ", scale = 1, colour = G.C.UI.TEXT_LIGHT, shadow = true}}, - -- {n=G.UIT.T, config={text = localize('$')..format_ui_value(config.dollars), scale = 1.3*scale, colour = G.C.WHITE, shadow = true, juice = true}} - --}} - --G.round_eval:add_child(left_text,G.round_eval:get_UIE_by_ID('eval_bottom')) - - Handy.insta_cash_out.is_button_created = true - G.GAME.current_round.dollars = config.dollars - - play_sound('coin6', config.pitch or 1) - G.VIBRATION = G.VIBRATION + 1 - return true - end - })) - end -end - -function change_shop_size(mod) - if not G.GAME.shop then return end - G.GAME.shop.joker_max = G.GAME.shop.joker_max + mod - if G.shop_jokers and G.shop_jokers.cards then - if mod < 0 then - --Remove jokers in shop - for i = #G.shop_jokers.cards, G.GAME.shop.joker_max+1, -1 do - if G.shop_jokers.cards[i] then - G.shop_jokers.cards[i]:remove() - end - end - end - G.shop_jokers.config.card_limit = G.GAME.shop.joker_max - G.shop_jokers.T.w = math.min(G.GAME.shop.joker_max,4)*1.02*G.CARD_W - G.shop:recalculate() - if mod > 0 then - for i = 1, G.GAME.shop.joker_max - #G.shop_jokers.cards do - G.shop_jokers:emplace(create_card_for_shop(G.shop_jokers)) - end - end - end -end - -function juice_card(card) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() if card and card.juice_up then card:juice_up(0.7) end;return true end) - })) -end - -function update_canvas_juice(dt) - G.JIGGLE_VIBRATION = G.ROOM.jiggle or 0 - if not G.SETTINGS.screenshake or (type(G.SETTINGS.screenshake) ~= 'number') then - G.SETTINGS.screenshake = G.SETTINGS.reduced_motion and 0 or 50 - end - local shake_amt = (G.SETTINGS.reduced_motion and 0 or 1)*math.max(0,G.SETTINGS.screenshake-30)/100 - G.ARGS.eased_cursor_pos = G.ARGS.eased_cursor_pos or {x=G.CURSOR.T.x,y=G.CURSOR.T.y, sx = G.CONTROLLER.cursor_position.x, sy = G.CONTROLLER.cursor_position.y} - G.ARGS.eased_cursor_pos.x = G.ARGS.eased_cursor_pos.x*(1-3*dt) + 3*dt*(shake_amt*G.CURSOR.T.x + (1-shake_amt)*G.ROOM.T.w/2) - G.ARGS.eased_cursor_pos.y = G.ARGS.eased_cursor_pos.y*(1-3*dt) + 3*dt*(shake_amt*G.CURSOR.T.y + (1-shake_amt)*G.ROOM.T.h/2) - G.ARGS.eased_cursor_pos.sx = G.ARGS.eased_cursor_pos.sx*(1-3*dt) + 3*dt*(shake_amt*G.CONTROLLER.cursor_position.x + (1-shake_amt)*G.WINDOWTRANS.real_window_w/2) - G.ARGS.eased_cursor_pos.sy = G.ARGS.eased_cursor_pos.sy*(1-3*dt) + 3*dt*(shake_amt*G.CONTROLLER.cursor_position.y + (1-shake_amt)*G.WINDOWTRANS.real_window_h/2) - - shake_amt = (G.SETTINGS.reduced_motion and 0 or 1)*G.SETTINGS.screenshake/100*3 - if shake_amt < 0.05 then shake_amt = 0 end - - G.ROOM.jiggle = (G.ROOM.jiggle or 0)*(1-5*dt)*(shake_amt > 0.05 and 1 or 0) - G.ROOM.T.r = (0.001*math.sin(0.3*G.TIMERS.REAL)+ 0.002*(G.ROOM.jiggle)*math.sin(39.913*G.TIMERS.REAL))*shake_amt - G.ROOM.T.x = G.ROOM_ORIG.x + (shake_amt)*(0.015*math.sin(0.913*G.TIMERS.REAL) + 0.01*(G.ROOM.jiggle*shake_amt)*math.sin(19.913*G.TIMERS.REAL) + (G.ARGS.eased_cursor_pos.x - 0.5*(G.ROOM.T.w + G.ROOM_ORIG.x))*0.01) - G.ROOM.T.y = G.ROOM_ORIG.y + (shake_amt)*(0.015*math.sin(0.952*G.TIMERS.REAL) + 0.01*(G.ROOM.jiggle*shake_amt)*math.sin(21.913*G.TIMERS.REAL) + (G.ARGS.eased_cursor_pos.y - 0.5*(G.ROOM.T.h + G.ROOM_ORIG.y))*0.01) - - G.JIGGLE_VIBRATION = G.JIGGLE_VIBRATION*(1-5*dt) - G.CURR_VIBRATION = G.CURR_VIBRATION or 0 - G.CURR_VIBRATION = math.min(1, G.CURR_VIBRATION + G.VIBRATION + G.JIGGLE_VIBRATION*0.2) - G.VIBRATION = 0 - G.CURR_VIBRATION = (1-15*dt)*G.CURR_VIBRATION - if not G.SETTINGS.rumble then G.CURR_VIBRATION = 0 end - if G.CONTROLLER.GAMEPAD.object and G.F_RUMBLE then G.CONTROLLER.GAMEPAD.object:setVibration(G.CURR_VIBRATION*0.4*G.F_RUMBLE, G.CURR_VIBRATION*0.4*G.F_RUMBLE) end -end - -function juice_card_until(card, eval_func, first, delay) - G.E_MANAGER:add_event(Event({ - trigger = 'after',delay = delay or 0.1, blocking = false, blockable = false, timer = 'REAL', - func = (function() if eval_func(card) then if card and card.juice_up then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end) - })) -end - -function check_for_unlock(args) - if not next(args) then return end - if false then return end - if args.type == 'win_challenge' then - unlock_achievement('rule_bender') - local _c = true - for k, v in pairs(G.CHALLENGES) do - if not G.PROFILES[G.SETTINGS.profile].challenge_progress.completed[v.id] then - _c = false - end - end - if _c then - unlock_achievement('rule_breaker') - end - end - if false then return end - fetch_achievements() -- Refreshes achievements - for k, v in pairs(G.ACHIEVEMENTS) do - if (not v.earned) and (v.unlock_condition and type(v.unlock_condition) == 'function') and v:unlock_condition(args) then - unlock_achievement(k) - end - end - - --|-------------------------------------------- - --|Achievements - --|-------------------------------------------- - if args.type == 'career_stat' then - if args.statname == 'c_cards_played' and G.PROFILES[G.SETTINGS.profile].career_stats[args.statname] >= 2500 then - unlock_achievement('card_player') - end - if args.statname == 'c_cards_discarded' and G.PROFILES[G.SETTINGS.profile].career_stats[args.statname] >= 2500 then - unlock_achievement('card_discarder') - end - end - if args.type == 'ante_up' then - if args.ante >= 4 then - unlock_achievement('ante_up') - end - if args.ante >= 8 then - unlock_achievement('ante_upper') - end - end - if args.type == 'win' then - unlock_achievement('heads_up') - if G.GAME.round <= 12 then - unlock_achievement('speedrunner') - end - if G.GAME.round_scores.times_rerolled.amt <= 0 then - unlock_achievement('you_get_what_you_get') - end - end - if args.type == 'win_stake' then - local highest_win, lowest_win = get_deck_win_stake(nil) - if highest_win >= G.P_STAKES["stake_red"].stake_level then - unlock_achievement('low_stakes') - end - if highest_win >= G.P_STAKES["stake_black"].stake_level then - unlock_achievement('mid_stakes') - end - if highest_win >= G.P_STAKES["stake_gold"].stake_level then - unlock_achievement('high_stakes') - end - if G.PROGRESS and G.PROGRESS.deck_stakes.tally/G.PROGRESS.deck_stakes.of >=1 then - unlock_achievement('completionist_plus') - end - if G.PROGRESS and G.PROGRESS.joker_stickers.tally/G.PROGRESS.joker_stickers.of >=1 then - unlock_achievement('completionist_plus_plus') - end - end - if args.type == 'money' then - if G.GAME.dollars >= 400 then - unlock_achievement('nest_egg') - end - end - if args.type == 'hand' then - if args.handname == 'Flush' and args.scoring_hand then - local _w = 0 - for k, v in ipairs(args.scoring_hand) do - if v.ability.name == 'Wild Card' then - _w = _w + 1 - end - end - if _w == #args.scoring_hand then - unlock_achievement('flushed') - end - end - - if args.disp_text == 'Royal Flush' then - unlock_achievement('royale') - end - end - if args.type == 'shatter' then - if #args.shattered >= 2 then - unlock_achievement('shattered') - end - end - if args.type == 'run_redeem' then - local _v = 0 - _v = _v - (G.GAME.starting_voucher_count or 0) - for k, v in pairs(G.GAME.used_vouchers) do - _v = _v + 1 - end - if _v >= 5 and G.GAME.round_resets.ante <= 4 then - unlock_achievement('roi') - end - end - if args.type == 'upgrade_hand' then - if args.level >= 10 then - unlock_achievement('retrograde') - end - end - if args.type == 'chip_score' then - if to_big(args.chips) >= to_big(10000) then - unlock_achievement('_10k') - end - if to_big(args.chips) >= to_big(1000000) then - unlock_achievement('_1000k') - end - if to_big(args.chips) >= to_big(100000000) then - unlock_achievement('_100000k') - end - end - if args.type == 'modify_deck' then - if G.deck and G.deck.config.card_limit <= 20 then - unlock_achievement('tiny_hands') - end - if G.deck and G.deck.config.card_limit >= 80 then - unlock_achievement('big_hands') - end - end - if args.type == 'spawn_legendary' then - unlock_achievement('legendary') - end - if args.type == 'discover_amount' then - if G.DISCOVER_TALLIES.vouchers.tally/G.DISCOVER_TALLIES.vouchers.of >=1 then - unlock_achievement('extreme_couponer') - end - if G.DISCOVER_TALLIES.spectrals.tally/G.DISCOVER_TALLIES.spectrals.of >=1 then - unlock_achievement('clairvoyance') - end - if G.DISCOVER_TALLIES.tarots.tally/G.DISCOVER_TALLIES.tarots.of >=1 then - unlock_achievement('cartomancy') - end - if G.DISCOVER_TALLIES.planets.tally/G.DISCOVER_TALLIES.planets.of >=1 then - unlock_achievement('astronomy') - end - if G.DISCOVER_TALLIES.total.tally/G.DISCOVER_TALLIES.total.of >=1 then - unlock_achievement('completionist') - end - end - --------------------------------------------- - - local i=1 - while i <= #G.P_LOCKED do - local ret = false - local card = G.P_LOCKED[i] - - local custom_check - if not card.unlocked and card.check_for_unlock and type(card.check_for_unlock) == 'function' then - ret = card:check_for_unlock(args) - if ret then unlock_card(card) end - custom_check = true - end if not custom_check and not card.unlocked and card.unlock_condition and args.type == 'career_stat' then - if args.statname == card.unlock_condition.type and G.PROFILES[G.SETTINGS.profile].career_stats[args.statname] >= card.unlock_condition.extra then - ret = true - unlock_card(card) - end - end - - if not custom_check and not card.unlocked and card.unlock_condition and card.unlock_condition.type == args.type then - if args.type == 'hand' and args.handname == card.unlock_condition.extra then - ret = true - unlock_card(card) - end - if args.type == 'min_hand_size' and G.hand and G.hand.config.card_limit <= card.unlock_condition.extra then - ret = true - unlock_card(card) - end - if args.type == 'interest_streak' and card.unlock_condition.extra <= G.PROFILES[G.SETTINGS.profile].career_stats.c_round_interest_cap_streak then - ret = true - unlock_card(card) - end - if args.type == 'run_card_replays' then - for k, v in ipairs(G.playing_cards) do - if v.base.times_played >= card.unlock_condition.extra then - ret = true - unlock_card(card) - break - end - end - end - if args.type == 'play_all_hearts' then - local played = true - for k, v in ipairs(G.deck.cards) do - if not SMODS.has_no_suit(v) and v.base.suit == 'Hearts' then - played = false - end - end - for k, v in ipairs(G.hand.cards) do - if not SMODS.has_no_suit(v) and v.base.suit == 'Hearts' then - played = false - end - end - if played then - ret = true - unlock_card(card) - end - end - if args.type == 'run_redeem' then - local vouchers_redeemed = 0 - for k, v in pairs(G.GAME.used_vouchers) do - vouchers_redeemed = vouchers_redeemed + 1 - end - if vouchers_redeemed >= card.unlock_condition.extra then - ret = true - unlock_card(card) - end - end - if args.type == 'have_edition' then - local shiny_jokers = 0 - for k, v in ipairs(G.jokers.cards) do - if v.edition then shiny_jokers = shiny_jokers + 1 end - end - if shiny_jokers >= card.unlock_condition.extra then - ret = true - unlock_card(card) - end - end - if args.type == 'double_gold' then - ret = true - unlock_card(card) - end - if args.type == 'continue_game' then - ret = true - unlock_card(card) - end - if args.type == 'blank_redeems' then - if G.PROFILES[G.SETTINGS.profile].voucher_usage['v_blank'] and G.PROFILES[G.SETTINGS.profile].voucher_usage['v_blank'].count >= card.unlock_condition.extra then - unlock_card(card) - end - end - if args.type == 'modify_deck' then - if card.unlock_condition.extra and card.unlock_condition.extra.suit then - local count = 0 - for _, v in pairs(G.playing_cards) do - if v.base.suit == card.unlock_condition.extra.suit then count = count + 1 end - end - if count >= card.unlock_condition.extra.count then - ret = true - unlock_card(card) - end - end - if card.unlock_condition.extra and card.unlock_condition.extra.enhancement then - local count = 0 - for _, v in pairs(G.playing_cards) do - if v.ability.name == card.unlock_condition.extra.enhancement then count = count + 1 end - end - if count >= card.unlock_condition.extra.count then - ret = true - unlock_card(card) - end - end - if card.unlock_condition.extra and card.unlock_condition.extra.tally then - local count = 0 - for _, v in pairs(G.playing_cards) do - if v.ability.set == 'Enhanced' then count = count + 1 end - end - if count >= card.unlock_condition.extra.count then - ret = true - unlock_card(card) - end - end - end - if args.type == 'discover_amount' then - if card.unlock_condition.amount then - if card.unlock_condition.amount <= args.amount then - ret = true - unlock_card(card) - end - end - if card.unlock_condition.tarot_count then - if #G.P_CENTER_POOLS.Tarot <= args.tarot_count then - ret = true - unlock_card(card) - end - end - if card.unlock_condition.planet_count then - if #G.P_CENTER_POOLS.Planet <= args.planet_count then - ret = true - unlock_card(card) - end - end - end - if args.type == 'win_deck' then - if card.unlock_condition.deck then - if get_deck_win_stake(card.unlock_condition.deck) > 0 then - ret = true - unlock_card(card) - end - end - end - if args.type == 'win_stake' then - if card.unlock_condition.stake then - if get_deck_win_stake() >= card.unlock_condition.stake then - ret = true - unlock_card(card) - end - end - end - if args.type == 'discover_planets' then - local count = 0 - for k, v in pairs(G.P_CENTERS) do - if v.set == 'Planet' and v.discovered then count = count + 1 end - end - if count >= 9 then - ret = true - unlock_card(card) - end - end - if args.type == 'blind_discoveries' then - local discovered_blinds = 0 - for k, v in pairs(G.P_BLINDS) do - if v.discovered then - discovered_blinds = discovered_blinds + 1 - end - end - if discovered_blinds >= card.unlock_condition.extra then - ret = true - unlock_card(card) - end - end - if args.type == 'modify_jokers' and G.jokers then - if card.unlock_condition.extra.count then - local count = 0 - for _, v in pairs(G.jokers.cards) do - if v.ability.set == 'Joker' and v.edition and v.edition.polychrome and card.unlock_condition.extra.polychrome then count = count + 1 end - end - if count >= card.unlock_condition.extra.count then - ret = true - unlock_card(card) - end - end - end - if args.type == 'money' then - if card.unlock_condition.extra <= G.GAME.dollars then - ret = true - unlock_card(card) - end - end - if args.type == 'round_win' then - if card.name == 'Matador' then - if G.GAME.current_round.hands_played == 1 and - G.GAME.current_round.discards_left == G.GAME.round_resets.discards and - G.GAME.blind:get_type() == 'Boss' then - ret = true - unlock_card(card) - end - end - if card.name == 'Troubadour' then - if G.PROFILES[G.SETTINGS.profile].career_stats.c_single_hand_round_streak >= card.unlock_condition.extra then - ret = true - unlock_card(card) - end - end - if card.name == 'Hanging Chad' then - if G.GAME.last_hand_played == card.unlock_condition.extra and G.GAME.blind:get_type() == 'Boss' then - ret = true - unlock_card(card) - end - end - end - if args.type == 'ante_up' then - if card.unlock_condition.ante then - if args.ante == card.unlock_condition.ante then - ret = true - unlock_card(card) - end - end - end - if args.type == 'hand_contents' then - if card.name == 'Seeing Double' then - local tally = 0 - for j = 1, #args.cards do - if args.cards[j]:get_id() == 7 and args.cards[j]:is_suit('Clubs') then - tally = tally+1 - end - end - if tally >= 4 then - ret = true - unlock_card(card) - end - end - - if card.name == 'Golden Ticket' then - local tally = 0 - for j = 1, #args.cards do - if SMODS.has_enhancement(args.cards[j], 'm_gold') then - tally = tally+1 - end - end - if tally >= 5 then - ret = true - unlock_card(card) - end - end - end - if args.type == 'discard_custom' then - if card.name == 'Hit the Road' then - local tally = 0 - for j = 1, #args.cards do - if args.cards[j]:get_id() == 11 then - tally = tally+1 - end - end - if tally >= 5 then - ret = true - unlock_card(card) - end - end - if card.name == 'Brainstorm' then - local eval = evaluate_poker_hand(args.cards) - if next(eval['Straight Flush']) then - local min = 10 - for j = 1, #args.cards do - if args.cards[j]:get_id() < min then min = args.cards[j]:get_id() end - end - if min == 10 then - ret = true - unlock_card(card) - end - end - end - end - if args.type == 'win_no_hand' and G.GAME.hands[card.unlock_condition.extra].played == 0 then - ret = true - unlock_card(card) - end - if args.type == 'win_custom' then - if card.name == 'Invisible Joker' and - G.GAME.max_jokers <= 4 then - ret = true - unlock_card(card) - end - if card.name == 'Blueprint' then - ret = true - unlock_card(card) - end - end - if args.type == 'win' then - if card.unlock_condition.n_rounds >= G.GAME.round then - ret = true - unlock_card(card) - end - end - if args.type == 'chip_score' then - if to_big(card.unlock_condition.chips) <= to_big(args.chips) then - ret = true - G.E_MANAGER:add_event(Event({ - func = function() - G.E_MANAGER:add_event(Event({ - func = function() - unlock_card(card) - return true end - })) - return true end - })) - end - end - end - if ret == true then - table.remove(G.P_LOCKED, i) - else - i = i + 1 - end - end -end - -function unlock_card(card) - if card.unlocked == false then - if not SMODS.config.seeded_unlocks and (G.GAME.seeded or G.GAME.challenge) then return end - if card.unlocked or card.wip then return end - G:save_notify(card) - card.unlocked = true - if card.set == 'Back' then discover_card(card) end - table.sort(G.P_CENTER_POOLS["Back"], function (a, b) return (a.order - (a.unlocked and 100 or 0)) < (b.order - (b.unlocked and 100 or 0)) end) - G:save_progress() - G.FILE_HANDLER.force = true - notify_alert(card.key, card.set) - end -end - -function fetch_achievements() - G.ACHIEVEMENTS = G.ACHIEVEMENTS or { - ante_up = {order = 1, tier = 3, earned = false, steamid = "BAL_01"}, - ante_upper = {order = 2, tier = 3, earned = false, steamid = "BAL_02"}, - heads_up = {order = 3, tier = 2, earned = false, steamid = "BAL_03"}, - low_stakes = {order = 4, tier = 2, earned = false, steamid = "BAL_04"}, - mid_stakes = {order = 5, tier = 2, earned = false, steamid = "BAL_05"}, - high_stakes = {order = 6, tier = 2, earned = false, steamid = "BAL_06"}, - card_player = {order = 7, tier = 3, earned = false, steamid = "BAL_07"}, - card_discarder = {order = 8, tier = 3, earned = false, steamid = "BAL_08"}, - nest_egg = {order = 9, tier = 2, earned = false, steamid = "BAL_09"}, - flushed = {order = 10, tier = 3, earned = false, steamid = "BAL_10"}, - speedrunner = {order = 11, tier = 2, earned = false, steamid = "BAL_11"}, - roi = {order = 12, tier = 3, earned = false, steamid = "BAL_12"}, - shattered = {order = 13, tier = 3, earned = false, steamid = "BAL_13"}, - royale = {order = 14, tier = 3, earned = false, steamid = "BAL_14"}, - retrograde = {order = 15, tier = 2, earned = false, steamid = "BAL_15"}, - _10k = {order = 16, tier = 3, earned = false, steamid = "BAL_16"}, - _1000k = {order = 17, tier = 2, earned = false, steamid = "BAL_17"}, - _100000k = {order = 18, tier = 1, earned = false, steamid = "BAL_18"}, - tiny_hands = {order = 19, tier = 2, earned = false, steamid = "BAL_19"}, - big_hands = {order = 20, tier = 2, earned = false, steamid = "BAL_20"}, - you_get_what_you_get = {order = 21, tier = 3, earned = false, steamid = "BAL_21"}, - rule_bender = {order = 22, tier = 3, earned = false, steamid = "BAL_22"}, - rule_breaker = {order = 23, tier = 1, earned = false, steamid = "BAL_23"}, - legendary = {order = 24, tier = 3, earned = false, steamid = "BAL_24"}, - astronomy = {order = 25, tier = 3, earned = false, steamid = "BAL_25"}, - cartomancy = {order = 26, tier = 3, earned = false, steamid = "BAL_26"}, - clairvoyance = {order = 27, tier = 2, earned = false, steamid = "BAL_27"}, - extreme_couponer = {order = 28, tier = 1, earned = false, steamid = "BAL_28"}, - completionist = {order = 29, tier = 1, earned = false, steamid = "BAL_29"}, - completionist_plus = {order = 30, tier = 1, earned = false, steamid = "BAL_30"}, - completionist_plus_plus={order = 31, tier = 1, earned = false, steamid = "BAL_31"}, - } - - G.SETTINGS.ACHIEVEMENTS_EARNED = G.SETTINGS.ACHIEVEMENTS_EARNED or {} - for k, v in pairs(G.ACHIEVEMENTS) do - if not v.key then v.key = k end - for kk, vv in pairs(G.SETTINGS.ACHIEVEMENTS_EARNED) do - if G.ACHIEVEMENTS[kk] and G.ACHIEVEMENTS[kk].mod then - G.ACHIEVEMENTS[kk].earned = true - end - end - end if G.F_NO_ACHIEVEMENTS then return end - - --|FROM LOCAL SETTINGS FILE - --|------------------------------------------------------- - if not G.STEAM then --|set this to false if you get this information from elsewhere - G.SETTINGS.ACHIEVEMENTS_EARNED = G.SETTINGS.ACHIEVEMENTS_EARNED or {} - for k, v in pairs(G.SETTINGS.ACHIEVEMENTS_EARNED) do - if G.ACHIEVEMENTS[k] then - G.ACHIEVEMENTS[k].earned = true - end - end - end - --|------------------------------------------------------- - - --|STEAM ACHIEVEMENTS - --|------------------------------------------------------- - if G.STEAM and not G.STEAM.initial_fetch then - for k, v in pairs(G.ACHIEVEMENTS) do - local achievement_name = v.steamid - local success, achieved = G.STEAM.userStats.getAchievement(achievement_name) - if success then - v.earned = not not achieved - end - end - G.STEAM.initial_fetch = true - end - --|------------------------------------------------------- - - --|Other platforms - --|------------------------------------------------------- - - --|------------------------------------------------------- -end - -function unlock_achievement(achievement_name) - if G.PROFILES[G.SETTINGS.profile].all_unlocked and (G.ACHIEVEMENTS and G.ACHIEVEMENTS[achievement_name] and not G.ACHIEVEMENTS[achievement_name].bypass_all_unlocked and SMODS.config.achievements < 3) or (SMODS.config.achievements < 3 and (G.GAME.seeded or G.GAME.challenge)) then return end - G.E_MANAGER:add_event(Event({ - no_delete = true, - blockable = false, - blocking = false, - func = function() - if G.STATE ~= G.STATES.HAND_PLAYED then - if G.PROFILES[G.SETTINGS.profile].all_unlocked and (G.ACHIEVEMENTS and G.ACHIEVEMENTS[achievement_name] and not G.ACHIEVEMENTS[achievement_name].bypass_all_unlocked and SMODS.config.achievements < 3) or (SMODS.config.achievements < 3 and (G.GAME.seeded or G.GAME.challenge)) then return end - local achievement_set = false - if G.F_NO_ACHIEVEMENTS and not (G.ACHIEVEMENTS[achievement_name] or {}).mod then return true end - - --|LOCAL SETTINGS FILE - --|------------------------------------------------------- - if not G.ACHIEVEMENTS then fetch_achievements() end - - G.SETTINGS.ACHIEVEMENTS_EARNED[achievement_name] = true - G:save_progress() - if G.ACHIEVEMENTS[achievement_name] and not G.STEAM then - if not G.ACHIEVEMENTS[achievement_name].earned then - --|THIS IS THE FIRST TIME THIS ACHIEVEMENT HAS BEEN EARNED - achievement_set = true - G.FILE_HANDLER.force = true - end - G.ACHIEVEMENTS[achievement_name].earned = true - end - --|------------------------------------------------------- - - - --|STEAM ACHIEVEMENTS - --|------------------------------------------------------- - if G.STEAM then - if G.ACHIEVEMENTS[achievement_name] then - if not G.ACHIEVEMENTS[achievement_name].earned then - --|THIS IS THE FIRST TIME THIS ACHIEVEMENT HAS BEEN EARNED - achievement_set = true - G.FILE_HANDLER.force = true - local achievement_code = G.ACHIEVEMENTS[achievement_name].steamid - local success, achieved = G.STEAM.userStats.getAchievement(achievement_code) - if not success or not achieved then - G.STEAM.send_control.update_queued = true - G.STEAM.userStats.setAchievement(achievement_code) - end - end - G.ACHIEVEMENTS[achievement_name].earned = true - end - end - --|------------------------------------------------------- - - --|Other platforms - --|------------------------------------------------------- - - --|------------------------------------------------------- - - if achievement_set then notify_alert(achievement_name) end - return true - end - end - }), 'achievement') -end - -function notify_alert(_achievement, _type) - _type = _type or 'achievement' - G.E_MANAGER:add_event(Event({ - no_delete = true, - pause_force = true, - timer = 'UPTIME', - func = function() - if G.achievement_notification then - G.achievement_notification:remove() - G.achievement_notification = nil - end - G.achievement_notification = G.achievement_notification or UIBox{ - definition = create_UIBox_notify_alert(_achievement, _type), - config = {align='cr', offset = {x=20,y=0},major = G.ROOM_ATTACH, bond = 'Weak'} - } - return true - end - }), 'achievement') - G.E_MANAGER:add_event(Event({ - no_delete = true, - trigger = 'after', - pause_force = true, - timer = 'UPTIME', - delay = 0.1, - func = function() - G.achievement_notification.alignment.offset.x = G.ROOM.T.x - G.achievement_notification.UIRoot.children[1].children[1].T.w - 0.8 - return true - end - }), 'achievement') - G.E_MANAGER:add_event(Event({ - no_delete = true, - pause_force = true, - trigger = 'after', - timer = 'UPTIME', - delay = 0.1, - func = function() - play_sound('highlight1', nil, 0.5) - play_sound('foil2', 0.5, 0.4) - return true - end - }), 'achievement') - G.E_MANAGER:add_event(Event({ - no_delete = true, - pause_force = true, - trigger = 'after', - delay = 3, - timer = 'UPTIME', - func = function() - G.achievement_notification.alignment.offset.x = 20 - return true - end - }), 'achievement') - G.E_MANAGER:add_event(Event({ - no_delete = true, - pause_force = true, - trigger = 'after', - delay = 0.5, - timer = 'UPTIME', - func = function() - if G.achievement_notification then - G.achievement_notification:remove() - G.achievement_notification = nil - end - return true - end - }), 'achievement') -end - -function inc_steam_stat(stat_name) - if not G.STEAM then return end - local success, current_stat = G.STEAM.userStats.getStatInt(stat_name) - if success then - G.STEAM.userStats.setStatInt(stat_name, current_stat+1) - G.STEAM.send_control.update_queued = true - end -end - -function unlock_notify() - local _UN = get_compressed(G.SETTINGS.profile..'/'..'unlock_notify.jkr') - if _UN then - for key in string.gmatch(_UN .. "\n", "(.-)\n") do - create_unlock_overlay(key) - end - love.filesystem.remove(G.SETTINGS.profile..'/'..'unlock_notify.jkr') - end -end - -function create_unlock_overlay(key) - if G.P_CENTERS[key] then - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - no_delete = true, - func = (function() - if not G.OVERLAY_MENU then - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = G.P_CENTERS[key].set == 'Back' and create_UIBox_deck_unlock(G.P_CENTERS[key]) or create_UIBox_card_unlock(G.P_CENTERS[key]), - } - play_sound('foil1', 0.7, 0.3) - play_sound('gong', 1.4, 0.15) - return true - end - end) - }), 'unlock') - end -end - -function discover_card(card) - if not SMODS.config.seeded_unlocks and (G.GAME.seeded or G.GAME.challenge) then return end - card = card or {} - if card.discovered or card.wip then return end - if card and not card.discovered then - card.alert = true - G.GAME.round_scores.new_collection.amt = G.GAME.round_scores.new_collection.amt+1 - end - card.discovered = true - set_discover_tallies() - G.E_MANAGER:add_event(Event({ - func = (function() - G:save_progress() - return true end)})) -end - -function get_deck_from_name(_name) - for k, v in pairs(G.P_CENTERS) do - if v.name == _name then return v end - end -end - -function get_next_voucher_key(_from_tag) - local _pool, _pool_key = get_current_pool('Voucher') - if _from_tag then _pool_key = 'Voucher_fromtag' end - local center = pseudorandom_element(_pool, pseudoseed(_pool_key)) - local it = 1 - while center == 'UNAVAILABLE' do - it = it + 1 - center = pseudorandom_element(_pool, pseudoseed(_pool_key..'_resample'..it)) - end - - return center -end - -function get_next_tag_key(append) - if G.FORCE_TAG then return G.FORCE_TAG end - local _pool, _pool_key = get_current_pool('Tag', nil, nil, append) - local _tag = pseudorandom_element(_pool, pseudoseed(_pool_key)) - local it = 1 - while _tag == 'UNAVAILABLE' do - it = it + 1 - _tag = pseudorandom_element(_pool, pseudoseed(_pool_key..'_resample'..it)) - end - - return _tag -end - -function create_playing_card(card_init, area, skip_materialize, silent, colours) - card_init = card_init or {} - card_init.front = card_init.front or pseudorandom_element(G.P_CARDS, pseudoseed('front')) - card_init.center = card_init.center or G.P_CENTERS.c_base - - G.playing_card = (G.playing_card and G.playing_card + 1) or 1 - local _area = area or G.hand - local card = Card(_area.T.x, _area.T.y, G.CARD_W, G.CARD_H, card_init.front, card_init.center, {playing_card = G.playing_card}) - table.insert(G.playing_cards, card) - card.playing_card = G.playing_card - if G.GAME.modifiers.cry_force_suit then card:change_suit(G.GAME.modifiers.cry_force_suit) end - if G.GAME.modifiers.cry_force_enhancement then card:set_ability(G.P_CENTERS[G.GAME.modifiers.cry_force_enhancement]) end - if G.GAME.modifiers.cry_force_edition then card:set_edition({[G.GAME.modifiers.cry_force_edition]=true},true,true) end - if G.GAME.modifiers.cry_force_seal then card:set_seal(G.GAME.modifiers.cry_force_seal) end - - if area then area:emplace(card) end - if not skip_materialize then card:start_materialize(colours, silent) end - - return card -end - -function get_pack(_key, _type) - if not G.GAME.first_shop_buffoon and not G.GAME.banned_keys['p_buffoon_normal_1'] then - G.GAME.first_shop_buffoon = true - return G.P_CENTERS['p_buffoon_normal_'..(math.random(1, 2))] - end - 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) and not G.GAME.banned_keys[v.key] then cume = cume + (v.weight or 1 ) end - end - local poll = pseudorandom(pseudoseed((_key or 'pack_generic')..G.GAME.round_resets.ante))*cume - for k, v in ipairs(G.P_CENTER_POOLS['Booster']) do - if not G.GAME.banned_keys[v.key] then - if not _type or _type == v.kind then it = it + (v.weight or 1) end - if it >= poll and it - (v.weight or 1) <= poll then center = v; break end - end - end - if not center then center = G.P_CENTERS['p_buffoon_normal_1'] end return center -end - -function get_current_pool(_type, _rarity, _legendary, _append) - --create the pool - G.ARGS.TEMP_POOL = EMPTY(G.ARGS.TEMP_POOL) - local _pool, _starting_pool, _pool_key, _pool_size = G.ARGS.TEMP_POOL, nil, '', 0 - - if _type == 'Joker' then -_rarity = (_legendary and 4) or (type(_rarity) == "number" and ((_rarity > 0.95 and 3) or (_rarity > 0.7 and 2) or 1)) or _rarity -local rarity = _rarity or SMODS.poll_rarity("Joker", 'rarity'..G.GAME.round_resets.ante..(_append or '')) - - _starting_pool, _pool_key = G.P_JOKER_RARITY_POOLS[rarity], 'Joker'..rarity..((not _legendary and _append) or '') - elseif SMODS.ObjectTypes[_type] and SMODS.ObjectTypes[_type].rarities then - local rarities = SMODS.ObjectTypes[_type].rarities - local rarity - if _legendary and rarities.legendary then - rarity = rarities.legendary.key - else - rarity = _rarity or SMODS.poll_rarity(_type, 'rarity_'.._type..G.GAME.round_resets.ante..(_append or '')) - end - _starting_pool, _pool_key = SMODS.ObjectTypes[_type].rarity_pools[rarity], _type..rarity..(_append or '') - else _starting_pool, _pool_key = G.P_CENTER_POOLS[_type], _type..(_append or '') - end - - --cull the pool - for k, v in ipairs(_starting_pool) do - local add = nil - local in_pool, pool_opts - if v.in_pool and type(v.in_pool) == 'function' then - in_pool, pool_opts = v:in_pool({ source = _append }) - end - pool_opts = pool_opts or {} - if _type == 'Enhanced' then - add = true - elseif _type == 'Demo' then - if v.pos and v.config then add = true end - elseif _type == 'Tag' then - if (not v.requires or (G.P_CENTERS[v.requires] and G.P_CENTERS[v.requires].discovered)) and - (not v.min_ante or v.min_ante <= G.GAME.round_resets.ante) then - add = true - end - elseif not (G.GAME.used_jokers[v.key] and not pool_opts.allow_duplicates and not next(find_joker("Showman"))) and - (v.unlocked ~= false or v.rarity == 4) then - if v.set == 'Voucher' then - if not G.GAME.cry_owned_vouchers[v.key] then - local include = true - if v.requires then - for kk, vv in pairs(v.requires) do - if not G.GAME.cry_owned_vouchers[vv] then - include = false - end - end - end - if G.shop_vouchers and G.shop_vouchers.cards then - for kk, vv in ipairs(G.shop_vouchers.cards) do - if vv.config.center.key == v.key then include = false end - end - end - if include then - add = true - end - end - elseif v.set == 'Planet' then - local softlocked = true - if not v.config.softlock then - softlocked = false - elseif v.config.hand_type then - softlocked = G.GAME.hands[v.config.hand_type].played == 0 - elseif v.config.hand_types then - for _, h in pairs(v.config.hand_types) do - if G.GAME.hands[h].played > 0 then - softlocked = false - end - end - end - if not softlocked then - add = true - end - elseif v.source_gate then - if v.source_gate ~= _append then - add = nil - else - add = true - end - elseif v.joker_gate then - add = nil - for kk, vv in pairs(G.jokers.cards) do - if vv.ability.name == v.joker_gate then - add = true - end - end - elseif v.enhancement_gate then - add = nil - for kk, vv in pairs(G.playing_cards) do - if SMODS.has_enhancement(vv, v.enhancement_gate) then - add = true - end - end - else - add = true - end - if v.name == 'Black Hole' or v.name == 'The Soul' or v.hidden then - add = false - end - end - - if v.no_pool_flag and G.GAME.pool_flags[v.no_pool_flag] then add = nil end - if v.yes_pool_flag and not G.GAME.pool_flags[v.yes_pool_flag] then add = nil end - if v.key == 'j_cry_filler' and _append == 'rta' then add = nil end - - if v.in_pool and type(v.in_pool) == 'function' then - add = in_pool and (add or pool_opts.override_base_checks) - end - if add and not G.GAME.banned_keys[v.key] then - _pool[#_pool + 1] = v.key - _pool_size = _pool_size + 1 - else - _pool[#_pool + 1] = 'UNAVAILABLE' - end - end - - --if pool is empty - if G.GAME.oldbpfactor and G.GAME.oldbpfactor >= 2 then - if _type == 'Joker' and (_rarity == nil or type(_rarity) ~= "string") and not _legendary and not (G.GAME.used_jokers["j_blueprint"] and not next(find_joker("Showman"))) then - for i = 1, math.floor(G.GAME.oldbpfactor - 1) do - _pool[#_pool + 1] = "j_blueprint" - end - end - end - if _pool_size == 0 then - _pool = EMPTY(G.ARGS.TEMP_POOL) - if SMODS.ObjectTypes[_type] and SMODS.ObjectTypes[_type].default and G.P_CENTERS[SMODS.ObjectTypes[_type].default] then - _pool[#_pool+1] = SMODS.ObjectTypes[_type].default - elseif _type == 'Tarot' or _type == 'Tarot_Planet' then _pool[#_pool + 1] = "c_strength" - elseif _type == 'Planet' then _pool[#_pool + 1] = "c_pluto" - elseif _type == 'Spectral' then _pool[#_pool + 1] = "c_incantation" - elseif _type == 'Joker' then _pool[#_pool + 1] = "j_joker" - elseif _type == 'Demo' then _pool[#_pool + 1] = "j_joker" - elseif _type == 'Voucher' then _pool[#_pool + 1] = "v_blank" - elseif _type == 'Tag' then _pool[#_pool + 1] = "tag_handy" - elseif _type == 'Consumeables' then _pool[#_pool + 1] = "c_ceres" - else _pool[#_pool + 1] = "j_joker" - end - end - - return _pool, _pool_key..(not _legendary and G.GAME.round_resets.ante or '') -end - -function poll_edition(_key, _mod, _no_neg, _guaranteed) - _mod = _mod or 1 - local edition_poll = pseudorandom(pseudoseed(_key or 'edition_generic')) - if _guaranteed then - if edition_poll > 1 - 0.003*25 and not _no_neg then - return {negative = true} - elseif edition_poll > 1 - 0.006*25 then - return {polychrome = true} - elseif edition_poll > 1 - 0.02*25 then - return {holo = true} - elseif edition_poll > 1 - 0.04*25 then - return {foil = true} - end - else - if edition_poll > 1 - 0.003*_mod and not _no_neg then - return {negative = true} - elseif edition_poll > 1 - 0.006*G.GAME.edition_rate*_mod then - return {polychrome = true} - elseif edition_poll > 1 - 0.02*G.GAME.edition_rate*_mod then - return {holo = true} - elseif edition_poll > 1 - 0.04*G.GAME.edition_rate*_mod then - return {foil = true} - end - end - return nil -end - -function create_card(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append) - local area = area or G.jokers - local center = G.P_CENTERS.b_red - - - --should pool be skipped with a forced key - if not forced_key and soulable and (not G.GAME.banned_keys['c_soul']) then - for _, v in ipairs(SMODS.Consumable.legendaries) do - if (_type == v.type.key or _type == v.soul_set) and not (G.GAME.used_jokers[v.key] and not next(find_joker("Showman")) and not v.can_repeat_soul) and (not v.in_pool or (type(v.in_pool) ~= "function") or v:in_pool()) then - if pseudorandom('soul_'..v.key.._type..G.GAME.round_resets.ante) > (1 - v.soul_rate) then - forced_key = v.key - end - end - end - if (_type == 'Tarot' or _type == 'Spectral' or _type == 'Tarot_Planet') and - not (G.GAME.used_jokers['c_soul'] and not next(find_joker("Showman"))) then - if pseudorandom('soul_'.._type..G.GAME.round_resets.ante) > 0.997 then - forced_key = 'c_soul' - end - end - if (_type == 'Planet' or _type == 'Spectral') and - not (G.GAME.used_jokers['c_black_hole'] and not next(find_joker("Showman"))) then - if pseudorandom('soul_'.._type..G.GAME.round_resets.ante) > 0.997 then - forced_key = 'c_black_hole' - end - end - end - - if _type == 'Base' then - forced_key = 'c_base' - end - - - - if forced_key and not G.GAME.banned_keys[forced_key] then - center = G.P_CENTERS[forced_key] - _type = (center.set ~= 'Default' and center.set or _type) - else - local _pool, _pool_key = get_current_pool(_type, _rarity, legendary, key_append) - center = pseudorandom_element(_pool, pseudoseed(_pool_key)) - local it = 1 - while center == 'UNAVAILABLE' do - it = it + 1 - center = pseudorandom_element(_pool, pseudoseed(_pool_key..'_resample'..it)) - end - - center = G.P_CENTERS[center] - end - - local front = ((_type=='Base' or _type == 'Enhanced') and pseudorandom_element(G.P_CARDS, pseudoseed('front'..(key_append or '')..G.GAME.round_resets.ante))) or nil - - local card = Card(area.T.x + area.T.w/2, area.T.y, G.CARD_W, G.CARD_H, front, center, - {bypass_discovery_center = area==G.shop_jokers or area == G.pack_cards or area == G.shop_vouchers or (G.shop_demo and area==G.shop_demo) or area==G.jokers or area==G.consumeables, - bypass_discovery_ui = area==G.shop_jokers or area == G.pack_cards or area==G.shop_vouchers or (G.shop_demo and area==G.shop_demo), - discover = area==G.jokers or area==G.consumeables, - bypass_back = G.GAME.selected_back.pos}) - if card.ability.consumeable and not skip_materialize then card:start_materialize() end - for k, v in ipairs(SMODS.Sticker.obj_buffer) do - local sticker = SMODS.Stickers[v] - if sticker.should_apply and type(sticker.should_apply) == 'function' and sticker:should_apply(card, center, area) then - sticker:apply(card, true) - end - end - - if _type == 'Joker' then - if G.GAME.modifiers.all_eternal then - card:set_eternal(true) - end - if (area == G.shop_jokers) or (area == G.pack_cards) then - local eternal_perishable_poll = pseudorandom((area == G.pack_cards and 'packetper' or 'etperpoll')..G.GAME.round_resets.ante) - if G.GAME.modifiers.enable_eternals_in_shop and eternal_perishable_poll > 0.7 and not SMODS.Stickers["eternal"].should_apply then - card:set_eternal(true) - elseif G.GAME.modifiers.enable_perishables_in_shop and ((eternal_perishable_poll > 0.4) and (eternal_perishable_poll <= 0.7)) and not SMODS.Stickers["perishable"].should_apply then - card:set_perishable(true) - end - if G.GAME.modifiers.enable_rentals_in_shop and pseudorandom((area == G.pack_cards and 'packssjr' or 'ssjr')..G.GAME.round_resets.ante) > 0.7 and not SMODS.Stickers["rental"].should_apply then - card:set_rental(true) - end - end - - if not SMODS.bypass_create_card_edition then - local edition = poll_edition('edi'..(key_append or '')..G.GAME.round_resets.ante) - card:set_edition(edition) - check_for_unlock({type = 'have_edition'}) - end - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({cry_creating_card = true, card = card}) - end - end - return card -end - -function copy_card(other, new_card, card_scale, playing_card, strip_edition) - local new_card = new_card or Card(other.T.x, other.T.y, G.CARD_W*(card_scale or 1), G.CARD_H*(card_scale or 1), G.P_CARDS.empty, G.P_CENTERS.c_base, {playing_card = playing_card}) - new_card:set_ability(other.config.center) - new_card.ability.type = other.ability.type - new_card:set_base(other.config.card) - for k, v in pairs(other.ability) do - if type(v) == 'table' then - new_card.ability[k] = copy_table(v) - else - new_card.ability[k] = v - end - end - - new_card.checkmonster = true - if not strip_edition then - new_card.from_copy = true - new_card:set_edition(other.edition or {}, nil, true) - end - check_for_unlock({type = 'have_edition'}) - new_card:set_seal(other.seal, true) - if other.params then - new_card.params = other.params - new_card.params.playing_card = playing_card - end - new_card.debuff = other.debuff - new_card.pinned = other.pinned - return new_card -end - -function tutorial_info(args) - local overlay_colour = {0.32,0.36,0.41,0} - ease_value(overlay_colour, 4, 0.6, nil, 'REAL', true,0.4) - G.OVERLAY_TUTORIAL = G.OVERLAY_TUTORIAL or UIBox{ - definition = {n=G.UIT.ROOT, config = {align = "cm", padding = 32.05, r=0.1, colour = overlay_colour, emboss = 0.05}, nodes={ - {n=G.UIT.R, config={align = "tr", minh = G.ROOM.T.h, minw = G.ROOM.T.w}, nodes={ - UIBox_button{label = {localize('b_skip').." >"}, button = "skip_tutorial_section", minw = 1.3, scale = 0.45, colour = G.C.JOKER_GREY} - }} - }}, - config = { - align = "cm", - offset = {x=0,y=3.2}, - major = G.ROOM_ATTACH, - bond = 'Weak' - } - } - G.OVERLAY_TUTORIAL.step = G.OVERLAY_TUTORIAL.step or 1 - G.OVERLAY_TUTORIAL.step_complete = false - local row_dollars_chips = G.HUD:get_UIE_by_ID('row_dollars_chips') - local align = args.align or "tm" - local step = args.step or 1 - local attach = args.attach or {major = row_dollars_chips, type = 'tm', offset = {x=0, y=-0.5}} - local pos = args.pos or {x=attach.major.T.x + attach.major.T.w/2, y=attach.major.T.y + attach.major.T.h/2} - local button = args.button or {button = localize('b_next'), func = 'tut_next'} - args.highlight = args.highlight or {} - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.3, - func = function() - if G.OVERLAY_TUTORIAL and G.OVERLAY_TUTORIAL.step == step and - not G.OVERLAY_TUTORIAL.step_complete then - G.CONTROLLER.interrupt.focus = true - G.OVERLAY_TUTORIAL.Jimbo = G.OVERLAY_TUTORIAL.Jimbo or Card_Character(pos) - if type(args.highlight) == 'function' then args.highlight = args.highlight() end - args.highlight[#args.highlight+1] = G.OVERLAY_TUTORIAL.Jimbo - G.OVERLAY_TUTORIAL.Jimbo:add_speech_bubble(args.text_key, align, args.loc_vars) - G.OVERLAY_TUTORIAL.Jimbo:set_alignment(attach) - if args.hard_set then G.OVERLAY_TUTORIAL.Jimbo:hard_set_VT() end - G.OVERLAY_TUTORIAL.button_listen = nil - if G.OVERLAY_TUTORIAL.content then G.OVERLAY_TUTORIAL.content:remove() end - if args.content then - G.OVERLAY_TUTORIAL.content = UIBox{ - definition = args.content(), - config = { - align = args.content_config and args.content_config.align or "cm", - offset = args.content_config and args.content_config.offset or {x=0,y=0}, - major = args.content_config and args.content_config.major or G.OVERLAY_TUTORIAL.Jimbo, - bond = 'Weak' - } - } - args.highlight[#args.highlight+1] = G.OVERLAY_TUTORIAL.content - end - if args.button_listen then G.OVERLAY_TUTORIAL.button_listen = args.button_listen end - if not args.no_button then G.OVERLAY_TUTORIAL.Jimbo:add_button(button.button, button.func, button.colour, button.update_func, true) end - G.OVERLAY_TUTORIAL.Jimbo:say_stuff(2*(#(G.localization.misc.tutorial[args.text_key] or {}))+1) - if args.snap_to then - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - blocking = false, blockable = false, - func = function() - if G.OVERLAY_TUTORIAL and G.OVERLAY_TUTORIAL.Jimbo and not G.OVERLAY_TUTORIAL.Jimbo.talking then - local _snap_to = args.snap_to() - if _snap_to then - G.CONTROLLER.interrupt.focus = false - G.CONTROLLER:snap_to({node = args.snap_to()}) - end - return true - end - end - }), 'tutorial') - end - if args.highlight then G.OVERLAY_TUTORIAL.highlights = args.highlight end - G.OVERLAY_TUTORIAL.step_complete = true - end - return not G.OVERLAY_TUTORIAL or G.OVERLAY_TUTORIAL.step > step or G.OVERLAY_TUTORIAL.skip_steps - end - }), 'tutorial') - return step+1 -end - -function calculate_reroll_cost(skip_increment) - if G.GAME.current_round.free_rerolls < 0 then G.GAME.current_round.free_rerolls = 0 end - if G.GAME.current_round.free_rerolls > 0 then G.GAME.current_round.reroll_cost = 0; return end - G.GAME.current_round.reroll_cost_increase = G.GAME.current_round.reroll_cost_increase or 0 - if not skip_increment then G.GAME.current_round.reroll_cost_increase = G.GAME.current_round.reroll_cost_increase + 1 end - G.GAME.current_round.reroll_cost = (G.GAME.round_resets.temp_reroll_cost or G.GAME.round_resets.reroll_cost) + G.GAME.current_round.reroll_cost_increase -end - -function reset_idol_card() - G.GAME.current_round.idol_card.rank = 'Ace' - G.GAME.current_round.idol_card.suit = 'Spades' - local valid_idol_cards = {} - for k, v in ipairs(G.playing_cards) do - if v.ability.effect ~= 'Stone Card' then - if not SMODS.has_no_suit(v) and not SMODS.has_no_rank(v) then - valid_idol_cards[#valid_idol_cards+1] = v - end - end - end - if valid_idol_cards[1] then - local idol_card = pseudorandom_element(valid_idol_cards, pseudoseed('idol'..G.GAME.round_resets.ante)) - G.GAME.current_round.idol_card.rank = idol_card.base.value - G.GAME.current_round.idol_card.suit = idol_card.base.suit - G.GAME.current_round.idol_card.id = idol_card.base.id - end -end - -function reset_mail_rank() - G.GAME.current_round.mail_card.rank = 'Ace' - local valid_mail_cards = {} - for k, v in ipairs(G.playing_cards) do - if v.ability.effect ~= 'Stone Card' then - if not SMODS.has_no_rank(v) then - valid_mail_cards[#valid_mail_cards+1] = v - end - end - end - if valid_mail_cards[1] then - local mail_card = pseudorandom_element(valid_mail_cards, pseudoseed('mail'..G.GAME.round_resets.ante)) - G.GAME.current_round.mail_card.rank = mail_card.base.value - G.GAME.current_round.mail_card.id = mail_card.base.id - end -end - -function reset_ancient_card() - local ancient_suits = {} - for k, v in ipairs({'Spades','Hearts','Clubs','Diamonds'}) do - if v ~= G.GAME.current_round.ancient_card.suit then ancient_suits[#ancient_suits + 1] = v end - end - local ancient_card = pseudorandom_element(ancient_suits, pseudoseed('anc'..G.GAME.round_resets.ante)) - G.GAME.current_round.ancient_card.suit = ancient_card -end - -function reset_castle_card() - G.GAME.current_round.castle_card.suit = 'Spades' - local valid_castle_cards = {} - for k, v in ipairs(G.playing_cards) do - if v.ability.effect ~= 'Stone Card' then - if not SMODS.has_no_suit(v) then - valid_castle_cards[#valid_castle_cards+1] = v - end - end - end - if valid_castle_cards[1] then - local castle_card = pseudorandom_element(valid_castle_cards, pseudoseed('cas'..G.GAME.round_resets.ante)) - G.GAME.current_round.castle_card.suit = castle_card.base.suit - end -end - -function reset_blinds() - G.GAME.round_resets.blind_states = G.GAME.round_resets.blind_states or {Small = 'Select', Big = 'Upcoming', Boss = 'Upcoming'} - if G.GAME.round_resets.blind_states.Boss == 'Defeated' then - G.GAME.round_resets.blind_states.Small = G.GAME.modifiers.cry_no_small_blind and 'Hide' or 'Upcoming' - G.GAME.round_resets.blind_states.Big = 'Upcoming' - G.GAME.round_resets.blind_states.Boss = 'Upcoming' - G.GAME.blind_on_deck = G.GAME.modifiers.cry_no_small_blind and 'Big' or 'Small' - if G.GAME.modifiers.cry_big_boss_rate and pseudorandom('cry_big_boss') < G.GAME.modifiers.cry_big_boss_rate then - G.GAME.round_resets.blind_choices.Big = get_new_boss() - elseif G.GAME.modifiers.cry_rush_hour_ii then - G.GAME.round_resets.blind_choices.Small = get_new_boss() - G.GAME.round_resets.blind_choices.Big = get_new_boss() - else - G.GAME.round_resets.blind_choices.Big = 'bl_big' - end - G.GAME.round_resets.blind_choices.Boss = get_new_boss() - G.GAME.round_resets.boss_rerolled = false - end -end - -function get_new_boss() - G.GAME.perscribed_bosses = G.GAME.perscribed_bosses or { - } - if G.GAME.perscribed_bosses and G.GAME.perscribed_bosses[G.GAME.round_resets.ante] then - local ret_boss = G.GAME.perscribed_bosses[G.GAME.round_resets.ante] - G.GAME.perscribed_bosses[G.GAME.round_resets.ante] = nil - G.GAME.bosses_used[ret_boss] = G.GAME.bosses_used[ret_boss] + 1 - return ret_boss - end - if G.FORCE_BOSS then return G.FORCE_BOSS end - - local eligible_bosses = {} - for k, v in pairs(G.P_BLINDS) do - if not v.boss then - - elseif v.in_pool and type(v.in_pool) == 'function' then - local res, options = v:in_pool() - if - ( - ((G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2) == - (v.boss.showdown or false) - ) or - (options or {}).ignore_showdown_check - then - eligible_bosses[k] = res and true or nil - end - elseif not v.boss.showdown and (v.boss.min <= math.max(1, G.GAME.round_resets.ante) and ((math.max(1, G.GAME.round_resets.ante))%G.GAME.win_ante ~= 0 or G.GAME.round_resets.ante < 2)) then - eligible_bosses[k] = true - elseif v.boss.showdown and (((G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2) or G.GAME.modifiers.cry_big_showdown ) then - eligible_bosses[k] = true - end - end - for k, v in pairs(G.GAME.banned_keys) do - if eligible_bosses[k] then eligible_bosses[k] = nil end - end - - local min_use = 100 - for k, v in pairs(G.GAME.bosses_used) do - if eligible_bosses[k] then - eligible_bosses[k] = v - if eligible_bosses[k] <= min_use then - min_use = eligible_bosses[k] - end - end - end - for k, v in pairs(eligible_bosses) do - if eligible_bosses[k] then - if eligible_bosses[k] > min_use then - eligible_bosses[k] = nil - end - end - end - local _, boss = pseudorandom_element(eligible_bosses, pseudoseed('boss')) - G.GAME.bosses_used[boss] = G.GAME.bosses_used[boss] + 1 - - return boss -end - -function get_type_colour(_c, card) - return - ((_c.unlocked == false and not (card and card.bypass_lock)) and G.C.BLACK) or - ((_c.unlocked ~= false and (_c.set == 'Joker' or _c.consumeable or _c.set == 'Voucher') and not _c.discoveredand and not ((_c.area ~= G.jokers and _c.area ~= G.consumeables and _c.area) or not _c.area)) and G.C.JOKER_GREY) or - (card and card.debuff and mix_colours(G.C.RED, G.C.GREY, 0.7)) or - (_c.set == 'Joker' and G.C.RARITY[_c.rarity]) or - (_c.set == 'Edition' and G.C.DARK_EDITION) or - (_c.set == 'Booster' and G.C.BOOSTER) or - G.C.SECONDARY_SET[_c.set] or - {0, 1, 1, 1} -end - -function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, hide_desc, main_start, main_end, card) - if card == nil and card_type then - card = SMODS.compat_0_9_8.generate_UIBox_ability_table_card - end - - if _c.specific_vars then specific_vars = _c.specific_vars end - local first_pass = nil - if not full_UI_table then - first_pass = true - full_UI_table = { - main = {}, - info = {}, - type = {}, - name = nil, - badges = badges or {} - } - end - - local desc_nodes = (not full_UI_table.name and full_UI_table.main) or full_UI_table.info - local name_override = nil - local info_queue = {} - - if full_UI_table.name then - full_UI_table.info[#full_UI_table.info+1] = {} - desc_nodes = full_UI_table.info[#full_UI_table.info] - end - - if not full_UI_table.name then - if specific_vars and specific_vars.no_name then - full_UI_table.name = true - elseif card_type == 'Locked' then - full_UI_table.name = localize{type = 'name', set = 'Other', key = 'locked', nodes = {}} - elseif card_type == 'Undiscovered' then - full_UI_table.name = localize{type = 'name', set = 'Other', key = 'undiscovered_'..(string.lower(_c.set)), name_nodes = {}} - elseif specific_vars and (card_type == 'Default' or card_type == 'Enhanced') then - if _c.name == 'Stone Card' or _c.replace_base_card then full_UI_table.name = true - elseif specific_vars.playing_card then - full_UI_table.name = {} - localize{type = 'other', key = 'playing_card', set = 'Other', nodes = full_UI_table.name, vars = {localize(specific_vars.value, 'ranks'), localize(specific_vars.suit, 'suits_plural'), colours = {specific_vars.colour}}} - full_UI_table.name = full_UI_table.name[1] - end - elseif card_type == 'Booster' then - - else - if not _c.generate_ui or type(_c.generate_ui) ~= 'function' then - full_UI_table.name = localize{type = 'name', set = _c.set, key = _c.key, nodes = full_UI_table.name} - end - end - full_UI_table.card_type = card_type or _c.set - end - - local loc_vars = {} - if main_start then - desc_nodes[#desc_nodes+1] = main_start - end - - local cfg = (card and card.ability) or _c['config'] - if cfg and G.GAME.modifiers.cry_consumable_reduce and cfg.max_highlighted and (cfg.max_highlighted > 1) then - local new_table = {} - for i0, j0 in pairs(cfg) do - new_table[i0] = j0 - end - new_table.max_highlighted = new_table.max_highlighted - 1 - cfg = new_table - end - if _c.name == 'cry-membershipcard' or _c.name == 'cry-membershipcardtwo' then - if not Cryptid.enabled["HTTPS Module"] then - if G.localization.descriptions.Other.cry_https_disabled then - main_end = {} - localize{type = 'other', key = 'cry_https_disabled', nodes = main_end, vars = {}} - main_end = main_end[1] - end - end - end - if _c.name == 'cry-translucent Joker' then - if G.jokers and G.jokers.cards then - for k, v in ipairs(G.jokers.cards) do - if (v.edition and v.edition.negative) and (G.localization.descriptions.Other.remove_negative)then - main_end = {} - localize{type = 'other', key = 'remove_negative', nodes = main_end, vars = {}} - main_end = main_end[1] - break - end - end - end - end - if _c.name == 'cry-blurred Joker' then - if (SMODS.Mods["sdm0sstuff"] or {}).can_load then - if G.localization.descriptions.Other.blurred_sdm0 then - main_end = {} - localize{type = 'other', key = 'blurred_sdm0', nodes = main_end, vars = {}} - main_end = main_end[1] - end - end - end - if _c.set == 'Other' then - localize{type = 'other', key = _c.key, nodes = desc_nodes, vars = specific_vars or _c.vars} - elseif card_type == 'Locked' then - if _c.wip then localize{type = 'other', key = 'wip_locked', set = 'Other', nodes = desc_nodes, vars = loc_vars} - elseif _c.demo and specific_vars then localize{type = 'other', key = 'demo_shop_locked', nodes = desc_nodes, vars = loc_vars} - elseif _c.demo then localize{type = 'other', key = 'demo_locked', nodes = desc_nodes, vars = loc_vars} - else - local res = {} - if _c.locked_loc_vars and type(_c.locked_loc_vars) == 'function' then - res = _c:locked_loc_vars(info_queue) or {} - loc_vars = res.vars or {} - specific_vars = specific_vars or {} - specific_vars.not_hidden = res.not_hidden or specific_vars.not_hidden - elseif _c.name == 'Golden Ticket' then - elseif _c.name == 'Mr. Bones' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_losses} - elseif _c.name == 'Acrobat' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_hands_played} - elseif _c.name == 'Sock and Buskin' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_face_cards_played} - elseif _c.name == 'Swashbuckler' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_jokers_sold} - elseif _c.name == 'Troubadour' then loc_vars = {_c.unlock_condition.extra} - elseif _c.name == 'Certificate' then - elseif _c.name == 'Smeared Joker' then loc_vars = {_c.unlock_condition.extra.count,localize{type = 'name_text', key = _c.unlock_condition.extra.e_key, set = 'Enhanced'}} - elseif _c.name == 'Throwback' then - elseif _c.name == 'Hanging Chad' then loc_vars = {localize(_c.unlock_condition.extra, 'poker_hands')} - elseif _c.name == 'Rough Gem' then loc_vars = {_c.unlock_condition.extra.count, localize(_c.unlock_condition.extra.suit, 'suits_singular')} - elseif _c.name == 'Bloodstone' then loc_vars = {_c.unlock_condition.extra.count, localize(_c.unlock_condition.extra.suit, 'suits_singular')} - elseif _c.name == 'Arrowhead' then loc_vars = {_c.unlock_condition.extra.count, localize(_c.unlock_condition.extra.suit, 'suits_singular')} - elseif _c.name == 'Onyx Agate' then loc_vars = {_c.unlock_condition.extra.count, localize(_c.unlock_condition.extra.suit, 'suits_singular')} - elseif _c.name == 'Glass Joker' then loc_vars = {_c.unlock_condition.extra.count, localize{type = 'name_text', key = _c.unlock_condition.extra.e_key, set = 'Enhanced'}} - elseif _c.name == 'Showman' then loc_vars = {_c.unlock_condition.ante} - elseif _c.name == 'Flower Pot' then loc_vars = {_c.unlock_condition.ante} - elseif _c.name == 'Blueprint' then - elseif _c.name == 'Wee Joker' then loc_vars = {_c.unlock_condition.n_rounds} - elseif _c.name == 'Merry Andy' then loc_vars = {_c.unlock_condition.n_rounds} - elseif _c.name == 'Oops! All 6s' then loc_vars = {number_format(_c.unlock_condition.chips)} - elseif _c.name == 'The Idol' then loc_vars = {number_format(_c.unlock_condition.chips)} - elseif _c.name == 'Seeing Double' then loc_vars = {localize("ph_4_7_of_clubs")} - elseif _c.name == 'Matador' then - elseif _c.name == 'Hit the Road' then - elseif _c.name == 'The Duo' then loc_vars = {localize(_c.unlock_condition.extra, 'poker_hands')} - elseif _c.name == 'The Trio' then loc_vars = {localize(_c.unlock_condition.extra, 'poker_hands')} - elseif _c.name == 'The Family' then loc_vars = {localize(_c.unlock_condition.extra, 'poker_hands')} - elseif _c.name == 'The Order' then loc_vars = {localize(_c.unlock_condition.extra, 'poker_hands')} - elseif _c.name == 'The Tribe' then loc_vars = {localize(_c.unlock_condition.extra, 'poker_hands')} - elseif _c.name == 'Stuntman' then loc_vars = {number_format(_c.unlock_condition.chips)} - elseif _c.name == 'Invisible Joker' then - elseif _c.name == 'Brainstorm' then - elseif _c.name == 'Satellite' then loc_vars = {_c.unlock_condition.extra} - elseif _c.name == 'Shoot the Moon' then - elseif _c.name == "Driver's License" then loc_vars = {_c.unlock_condition.extra.count} - elseif _c.name == 'Cartomancer' then loc_vars = {_c.unlock_condition.tarot_count} - elseif _c.name == 'Astronomer' then - elseif _c.name == 'Burnt Joker' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_cards_sold} - elseif _c.name == 'Bootstraps' then loc_vars = {_c.unlock_condition.extra.count} - --Vouchers - elseif _c.name == 'Overstock Plus' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_shop_dollars_spent} - elseif _c.name == 'Liquidation' then loc_vars = {_c.unlock_condition.extra} - elseif _c.name == 'Tarot Tycoon' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_tarots_bought} - elseif _c.name == 'Planet Tycoon' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_planets_bought} - elseif _c.name == 'Glow Up' then loc_vars = {_c.unlock_condition.extra} - elseif _c.name == 'Reroll Glut' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_shop_rerolls} - elseif _c.name == 'Omen Globe' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_tarot_reading_used} - elseif _c.name == 'Observatory' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_planetarium_used} - elseif _c.name == 'Nacho Tong' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_cards_played} - elseif _c.name == 'Recyclomancy' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_cards_discarded} - elseif _c.name == 'Money Tree' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_round_interest_cap_streak} - elseif _c.name == 'Antimatter' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].voucher_usage.v_blank and G.PROFILES[G.SETTINGS.profile].voucher_usage.v_blank.count or 0} - elseif _c.name == 'Illusion' then loc_vars = {_c.unlock_condition.extra, G.PROFILES[G.SETTINGS.profile].career_stats.c_playing_cards_bought} - elseif _c.name == 'Petroglyph' then loc_vars = {_c.unlock_condition.extra} - elseif _c.name == 'Retcon' then loc_vars = {_c.unlock_condition.extra} - elseif _c.name == 'Palette' then loc_vars = {_c.unlock_condition.extra} - end - - if _c.rarity and _c.rarity == 4 and specific_vars and not specific_vars.not_hidden then - localize{type = 'unlocks', key = res.key or 'joker_locked_legendary', set = res.set or 'Other', nodes = desc_nodes, vars = loc_vars, text_colour = res.text_colour, scale = res.scale} - else - - localize{type = 'unlocks', key = res.key or _c.key, set = res.set or _c.set, nodes = desc_nodes, vars = loc_vars, text_colour = res.text_colour, scale = res.scale} - end - end - elseif hide_desc then - localize{type = 'other', key = 'undiscovered_'..(string.lower(_c.set)), set = _c.set, nodes = desc_nodes} - elseif _c.generate_ui and type(_c.generate_ui) == 'function' then - _c:generate_ui(info_queue, card, desc_nodes, specific_vars, full_UI_table) - if specific_vars and specific_vars.pinned then info_queue[#info_queue+1] = {key = 'pinned_left', set = 'Other'} end - if specific_vars and specific_vars.sticker then info_queue[#info_queue+1] = {key = string.lower(specific_vars.sticker)..'_sticker', set = 'Other'} end - elseif specific_vars and specific_vars.debuffed then - localize{type = 'other', key = 'debuffed_'..(specific_vars.playing_card and 'playing_card' or 'default'), nodes = desc_nodes} - elseif _c.set == 'Joker' then - if _c.name == 'Stone Joker' or _c.name == 'Marble Joker' then info_queue[#info_queue+1] = G.P_CENTERS.m_stone - elseif _c.name == 'Steel Joker' then info_queue[#info_queue+1] = G.P_CENTERS.m_steel - elseif _c.name == 'Glass Joker' then info_queue[#info_queue+1] = G.P_CENTERS.m_glass - elseif _c.name == 'Golden Ticket' then info_queue[#info_queue+1] = G.P_CENTERS.m_gold - elseif _c.name == 'Lucky Cat' then info_queue[#info_queue+1] = G.P_CENTERS.m_lucky - elseif _c.name == 'Midas Mask' then info_queue[#info_queue+1] = G.P_CENTERS.m_gold - elseif _c.name == 'Invisible Joker' then - if G.jokers and G.jokers.cards then - for k, v in ipairs(G.jokers.cards) do - if (v.edition and v.edition.negative) and (G.localization.descriptions.Other.remove_negative)then - main_end = {} - localize{type = 'other', key = 'remove_negative', nodes = main_end, vars = {}} - main_end = main_end[1] - break - end - end - end - elseif _c.name == 'Diet Cola' then info_queue[#info_queue+1] = {key = 'tag_double', set = 'Tag'} - elseif _c.name == 'Perkeo' then info_queue[#info_queue+1] = {key = 'e_negative_consumable', set = 'Edition', config = {extra = 1}} - end - if specific_vars and specific_vars.pinned then info_queue[#info_queue+1] = {key = 'pinned_left', set = 'Other'} end - if specific_vars and specific_vars.sticker then info_queue[#info_queue+1] = {key = string.lower(specific_vars.sticker)..'_sticker', set = 'Other'} end - localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = specific_vars or {}} - elseif _c.set == 'Tag' then - if _c.name == 'Negative Tag' then info_queue[#info_queue+1] = G.P_CENTERS.e_negative - elseif _c.name == 'Foil Tag' then info_queue[#info_queue+1] = G.P_CENTERS.e_foil - elseif _c.name == 'Holographic Tag' then info_queue[#info_queue+1] = G.P_CENTERS.e_holo - elseif _c.name == 'Polychrome Tag' then info_queue[#info_queue+1] = G.P_CENTERS.e_polychrome - elseif _c.name == 'Charm Tag' then info_queue[#info_queue+1] = G.P_CENTERS.p_arcana_mega_1 - elseif _c.name == 'Meteor Tag' then info_queue[#info_queue+1] = G.P_CENTERS.p_celestial_mega_1 - elseif _c.name == 'Ethereal Tag' then info_queue[#info_queue+1] = G.P_CENTERS.p_spectral_normal_1 - elseif _c.name == 'Standard Tag' then info_queue[#info_queue+1] = G.P_CENTERS.p_standard_mega_1 - elseif _c.name == 'Buffoon Tag' then info_queue[#info_queue+1] = G.P_CENTERS.p_buffoon_mega_1 - end - localize{type = 'descriptions', key = _c.key, set = 'Tag', nodes = desc_nodes, vars = specific_vars or {}} - elseif _c.set == 'Voucher' then - if _c.name == "Overstock" or _c.name == "Overstock Plus" then loc_vars = {_c.config.extra} - elseif _c.name == "Tarot Merchant" or _c.name == "Tarot Tycoon" then loc_vars = {cfg.extra_disp} - elseif _c.name == "Planet Merchant" or _c.name == "Planet Tycoon" then loc_vars = {cfg.extra_disp} - elseif _c.name == "Hone" or _c.name == "Glow Up" then loc_vars = {cfg.extra} - elseif _c.name == "Reroll Surplus" or _c.name == "Reroll Glut" then loc_vars = {cfg.extra} - elseif _c.name == "Grabber" or _c.name == "Nacho Tong" then loc_vars = {cfg.extra} - elseif _c.name == "Wasteful" or _c.name == "Recyclomancy" then loc_vars = {cfg.extra} - elseif _c.name == "Seed Money" or _c.name == "Money Tree" then loc_vars = {cfg.extra/5} - elseif _c.name == "Blank" or _c.name == "Antimatter" then loc_vars = {_c.config.extra} - elseif _c.name == "Hieroglyph" or _c.name == "Petroglyph" then loc_vars = {cfg.extra} - elseif _c.name == "Director's Cut" or _c.name == "Retcon" then loc_vars = {cfg.extra} - elseif _c.name == "Paint Brush" or _c.name == "Palette" then loc_vars = {cfg.extra} - elseif _c.name == "Telescope" or _c.name == "Observatory" then loc_vars = {cfg.extra} - elseif _c.name == "Clearance Sale" or _c.name == "Liquidation" then loc_vars = {cfg.extra} - end - localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = loc_vars} - elseif _c.set == 'Edition' then - loc_vars = {cfg.extra} - localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = loc_vars} - elseif _c.set == 'Default' and specific_vars then - if specific_vars.nominal_chips then - localize{type = 'other', key = 'card_chips', nodes = desc_nodes, vars = {specific_vars.nominal_chips}} - end - if specific_vars.bonus_chips then - localize{type = 'other', key = 'card_extra_chips', nodes = desc_nodes, vars = {specific_vars.bonus_chips}} - end - elseif _c.set == 'Enhanced' then - if specific_vars and _c.name ~= 'Stone Card' and specific_vars.nominal_chips then - localize{type = 'other', key = 'card_chips', nodes = desc_nodes, vars = {specific_vars.nominal_chips}} - end - if _c.effect == 'Mult Card' then loc_vars = {cfg.mult} - elseif _c.effect == 'Wild Card' then - elseif _c.effect == 'Glass Card' then loc_vars = {cfg.Xmult, cfg.cry_prob and cry_prob(cfg.cry_prob, cfg.extra, cfg.cry_rigged) or G.GAME.probabilities.normal, cfg.extra} - elseif _c.effect == 'Steel Card' then loc_vars = {cfg.h_x_mult} - elseif _c.effect == 'Stone Card' then loc_vars = {((specific_vars and specific_vars.bonus_chips) or cfg.bonus)} - elseif _c.effect == 'Gold Card' then loc_vars = {cfg.h_dollars} - elseif _c.effect == 'Lucky Card' then loc_vars = {cfg.cry_prob and cry_prob(cfg.cry_prob, 15, cfg.cry_rigged) or G.GAME.probabilities.normal, cfg.mult, 5, cfg.p_dollars, 15} - end - localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = loc_vars} - if _c.name ~= 'Stone Card' and ((specific_vars and specific_vars.bonus_chips) or (cfg.bonus ~= 0 and cfg.bonus)) then - localize{type = 'other', key = 'card_extra_chips', nodes = desc_nodes, vars = {((specific_vars and specific_vars.bonus_chips) or cfg.bonus)}} - end - elseif _c.set == 'Booster' then - local desc_override = 'p_arcana_normal' - if _c.name == 'Arcana Pack' then desc_override = 'p_arcana_normal'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Jumbo Arcana Pack' then desc_override = 'p_arcana_jumbo'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Mega Arcana Pack' then desc_override = 'p_arcana_mega'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Celestial Pack' then desc_override = 'p_celestial_normal'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Jumbo Celestial Pack' then desc_override = 'p_celestial_jumbo'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Mega Celestial Pack' then desc_override = 'p_celestial_mega'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Spectral Pack' then desc_override = 'p_spectral_normal'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Jumbo Spectral Pack' then desc_override = 'p_spectral_jumbo'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Mega Spectral Pack' then desc_override = 'p_spectral_mega'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Standard Pack' then desc_override = 'p_standard_normal'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Jumbo Standard Pack' then desc_override = 'p_standard_jumbo'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Mega Standard Pack' then desc_override = 'p_standard_mega'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Buffoon Pack' then desc_override = 'p_buffoon_normal'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Jumbo Buffoon Pack' then desc_override = 'p_buffoon_jumbo'; loc_vars = {cfg.choose, cfg.extra} - elseif _c.name == 'Mega Buffoon Pack' then desc_override = 'p_buffoon_mega'; loc_vars = {cfg.choose, cfg.extra} - end - name_override = desc_override - if not full_UI_table.name then full_UI_table.name = localize{type = 'name', set = 'Other', key = name_override, nodes = full_UI_table.name} end - localize{type = 'other', key = desc_override, nodes = desc_nodes, vars = loc_vars} - elseif _c.set == 'Spectral' then - if _c.name == 'Talisman' or _c.name == 'Medium' or _c.name == 'Trance' or _c.name == 'Deja Vu' then - loc_vars = {_c.config.max_highlighted} - end - - if _c.name == 'Familiar' or _c.name == 'Grim' or _c.name == 'Incantation' then loc_vars = {cfg.extra} - elseif _c.name == 'Immolate' then loc_vars = {cfg.extra.destroy, cfg.extra.dollars} - elseif _c.name == 'Hex' then info_queue[#info_queue+1] = G.P_CENTERS.e_polychrome - elseif _c.name == 'Talisman' then info_queue[#info_queue+1] = {key = 'gold_seal', set = 'Other'} - elseif _c.name == 'Deja Vu' then info_queue[#info_queue+1] = {key = 'red_seal', set = 'Other'} - elseif _c.name == 'Trance' then info_queue[#info_queue+1] = {key = 'blue_seal', set = 'Other'} - elseif _c.name == 'Medium' then info_queue[#info_queue+1] = {key = 'purple_seal', set = 'Other'} - elseif _c.name == 'Ankh' then - if G.jokers and G.jokers.cards then - for k, v in ipairs(G.jokers.cards) do - if (v.edition and v.edition.negative) and (G.localization.descriptions.Other.remove_negative)then - info_queue[#info_queue+1] = G.P_CENTERS.e_negative - main_end = {} - localize{type = 'other', key = 'remove_negative', nodes = main_end, vars = {}} - main_end = main_end[1] - break - end - end - end - elseif _c.name == 'Cryptid' then loc_vars = {cfg.extra} - end - if _c.name == 'Ectoplasm' then info_queue[#info_queue+1] = G.P_CENTERS.e_negative; loc_vars = {G.GAME.ecto_minus or 1} end - if _c.name == 'Aura' then - info_queue[#info_queue+1] = G.P_CENTERS.e_foil - info_queue[#info_queue+1] = G.P_CENTERS.e_holo - info_queue[#info_queue+1] = G.P_CENTERS.e_polychrome - end - localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = loc_vars} - elseif _c.set == 'Planet' then - loc_vars = { - G.GAME.hands[cfg.hand_type].level,localize(cfg.hand_type, 'poker_hands'), G.GAME.hands[cfg.hand_type].l_mult, G.GAME.hands[cfg.hand_type].l_chips, - colours = {(G.GAME.hands[cfg.hand_type].level==1 and G.C.UI.TEXT_DARK or G.C.HAND_LEVELS[math.min(7, G.GAME.hands[cfg.hand_type].level)])} - } - localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = loc_vars} - elseif _c.set == 'Tarot' then - if _c.name == "The Fool" then - local fool_c = G.GAME.last_tarot_planet and G.P_CENTERS[G.GAME.last_tarot_planet] or nil - local last_tarot_planet = fool_c and localize{type = 'name_text', key = fool_c.key, set = fool_c.set} or localize('k_none') - local colour = (not fool_c or fool_c.name == 'The Fool') and G.C.RED or G.C.GREEN - main_end = { - {n=G.UIT.C, config={align = "bm", padding = 0.02}, nodes={ - {n=G.UIT.C, config={align = "m", colour = colour, r = 0.05, padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = ' '..last_tarot_planet..' ', colour = G.C.UI.TEXT_LIGHT, scale = 0.3, shadow = true}}, - }} - }} - } - loc_vars = {last_tarot_planet} - if not (not fool_c or fool_c.name == 'The Fool') then - info_queue[#info_queue+1] = fool_c - end - elseif _c.name == "The Magician" then loc_vars = {cfg.max_highlighted, localize{type = 'name_text', set = 'Enhanced', key = cfg.mod_conv}}; info_queue[#info_queue+1] = G.P_CENTERS[cfg.mod_conv] - elseif _c.name == "The High Priestess" then loc_vars = {cfg.planets} - elseif _c.name == "The Empress" then loc_vars = {cfg.max_highlighted, localize{type = 'name_text', set = 'Enhanced', key = cfg.mod_conv}}; info_queue[#info_queue+1] = G.P_CENTERS[cfg.mod_conv] - elseif _c.name == "The Emperor" then loc_vars = {cfg.tarots} - elseif _c.name == "The Hierophant" then loc_vars = {cfg.max_highlighted, localize{type = 'name_text', set = 'Enhanced', key = cfg.mod_conv}}; info_queue[#info_queue+1] = G.P_CENTERS[cfg.mod_conv] - elseif _c.name == "The Lovers" then loc_vars = {cfg.max_highlighted, localize{type = 'name_text', set = 'Enhanced', key = cfg.mod_conv}}; info_queue[#info_queue+1] = G.P_CENTERS[cfg.mod_conv] - elseif _c.name == "The Chariot" then loc_vars = {cfg.max_highlighted, localize{type = 'name_text', set = 'Enhanced', key = cfg.mod_conv}}; info_queue[#info_queue+1] = G.P_CENTERS[cfg.mod_conv] - elseif _c.name == "Justice" then loc_vars = {cfg.max_highlighted, localize{type = 'name_text', set = 'Enhanced', key = cfg.mod_conv}}; info_queue[#info_queue+1] = G.P_CENTERS[cfg.mod_conv] - elseif _c.name == "The Hermit" then loc_vars = {cfg.extra} - elseif _c.name == "The Wheel of Fortune" then loc_vars = {cfg.cry_prob and cry_prob(cfg.cry_prob, cfg.extra, cfg.cry_rigged) or G.GAME.probabilities.normal, cfg.extra}; info_queue[#info_queue+1] = G.P_CENTERS.e_foil; info_queue[#info_queue+1] = G.P_CENTERS.e_holo; info_queue[#info_queue+1] = G.P_CENTERS.e_polychrome; - elseif _c.name == "Strength" then loc_vars = {cfg.max_highlighted} - elseif _c.name == "The Hanged Man" then loc_vars = {cfg.max_highlighted} - elseif _c.name == "Death" then loc_vars = {cfg.max_highlighted} - elseif _c.name == "Temperance" then - local _money = 0 - if G.jokers then - for i = 1, #G.jokers.cards do - if G.jokers.cards[i].ability.set == 'Joker' then - _money = _money + G.jokers.cards[i].sell_cost - end - end - end - loc_vars = {cfg.extra, math.min(cfg.extra, _money)} - elseif _c.name == "The Devil" then loc_vars = {cfg.max_highlighted, localize{type = 'name_text', set = 'Enhanced', key = cfg.mod_conv}}; info_queue[#info_queue+1] = G.P_CENTERS[cfg.mod_conv] - elseif _c.name == "The Tower" then loc_vars = {cfg.max_highlighted, localize{type = 'name_text', set = 'Enhanced', key = cfg.mod_conv}}; info_queue[#info_queue+1] = G.P_CENTERS[cfg.mod_conv] - elseif _c.name == "The Star" then loc_vars = {cfg.max_highlighted, localize(cfg.suit_conv, 'suits_plural'), colours = {G.C.SUITS[cfg.suit_conv]}} - elseif _c.name == "The Moon" then loc_vars = {cfg.max_highlighted, localize(cfg.suit_conv, 'suits_plural'), colours = {G.C.SUITS[cfg.suit_conv]}} - elseif _c.name == "The Sun" then loc_vars = {cfg.max_highlighted, localize(cfg.suit_conv, 'suits_plural'), colours = {G.C.SUITS[cfg.suit_conv]}} - elseif _c.name == "Judgement" then - elseif _c.name == "The World" then loc_vars = {cfg.max_highlighted, localize(cfg.suit_conv, 'suits_plural'), colours = {G.C.SUITS[cfg.suit_conv]}} - end - localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = loc_vars} - end - - if main_end then - desc_nodes[#desc_nodes+1] = main_end - end - - if card_type == 'Default' or card_type == 'Enhanced' and not _c.replace_base_card and card and card.base then - if not _c.no_suit then - local suit = SMODS.Suits[card.base.suit] or {} - if suit.loc_vars and type(suit.loc_vars) == 'function' then - suit:loc_vars(info_queue, card) - end - end - if not _c.no_rank then - local rank = SMODS.Ranks[card.base.value] or {} - if rank.loc_vars and type(rank.loc_vars) == 'function' then - rank:loc_vars(info_queue, card) - end - end - end - - --Fill all remaining info if this is the main desc - if not ((specific_vars and not specific_vars.sticker) and (card_type == 'Default' or card_type == 'Enhanced')) then - if desc_nodes == full_UI_table.main and not full_UI_table.name then - localize{type = 'name', key = _c.key, set = _c.set, nodes = full_UI_table.name} - if not full_UI_table.name then full_UI_table.name = {} end - elseif desc_nodes ~= full_UI_table.main and not desc_nodes.name then - desc_nodes.name = localize{type = 'name_text', key = name_override or _c.key, set = name_override and 'Other' or _c.set} - end - end - - if first_pass and not (_c.set == 'Edition') and badges then - for k, v in ipairs(badges) do - v = (v == 'holographic' and 'holo' or v) - if v:sub(1,9) == 'negative_' then - info_queue[#info_queue+1] = {key = 'e_'..v, set = 'Edition', config = {extra = G.P_CENTERS['e_negative'].config.card_limit}} - end - if G.P_CENTERS[v] and G.P_CENTERS[v].set == 'Edition' then - info_queue[#info_queue + 1] = G.P_CENTERS[v] - end - if G.P_CENTERS['e_'..v] and G.P_CENTERS['e_'..v].set == 'Edition' then - info_queue[#info_queue + 1] = G.P_CENTERS['e_'..v] - end - local seal = SMODS.Seals[v] or SMODS.Seal.badge_to_key[v] and SMODS.Seals[SMODS.Seal.badge_to_key[v]] - if seal and seal.generate_ui ~= 0 then - local t = { key = v, set = 'Other' } - info_queue[#info_queue+1] = t - if seal.loc_vars and type(seal.loc_vars) == 'function' then - local res = seal:loc_vars(info_queue, card) or {} - t.vars = res.vars - t.key = res.key or t.key - t.set = res.set or t.set - end - else - if v == 'gold_seal' then info_queue[#info_queue+1] = {key = 'gold_seal', set = 'Other'} end - if v == 'blue_seal' then info_queue[#info_queue+1] = {key = 'blue_seal', set = 'Other'} end - if v == 'red_seal' then info_queue[#info_queue+1] = {key = 'red_seal', set = 'Other'} end - if v == 'purple_seal' then info_queue[#info_queue+1] = {key = 'purple_seal', set = 'Other'} end - end - local sticker = SMODS.Stickers[v] - if sticker then - local t = { key = v, set = 'Other' } - local res = {} - if sticker.loc_vars and type(sticker.loc_vars) == 'function' then - res = sticker:loc_vars(info_queue, card) or {} - t.vars = res.vars or {} - t.key = res.key or t.key - t.set = res.set or t.set - end - info_queue[#info_queue+1] = t - else - if v == 'eternal' then info_queue[#info_queue+1] = {key = 'eternal', set = 'Other'} end - if v == 'perishable' then info_queue[#info_queue+1] = {key = 'perishable', set = 'Other', vars = {G.GAME.perishable_rounds or 1, specific_vars.perish_tally or G.GAME.perishable_rounds}} end - if v == 'rental' then info_queue[#info_queue+1] = {key = 'rental', set = 'Other', vars = {G.GAME.rental_rate or 1}} end - end - if v == 'pinned_left' then info_queue[#info_queue+1] = {key = 'pinned_left', set = 'Other'} end - end - end - - SMODS.compat_0_9_8.generate_UIBox_ability_table_card = nil - for _, v in ipairs(info_queue) do - generate_card_ui(v, full_UI_table) - end - - return full_UI_table -end diff --git a/lovely/dump/functions/misc_functions.lua b/lovely/dump/functions/misc_functions.lua deleted file mode 100644 index a283c96..0000000 --- a/lovely/dump/functions/misc_functions.lua +++ /dev/null @@ -1,2196 +0,0 @@ -LOVELY_INTEGRITY = '3062e877afa10107b5e3bbd8ec9b301a451c24f4ae132c36908811e861037ba4' - ---Updates all display information for all displays for a given screenmode. Returns the key for the resolution option cycle --- ----@param screenmode string optional arg for one of 'Windowed', 'Fullscreen', or 'Borderless' ----@param display number optional arg to match fullscreen resolution with only the current display -function GET_DISPLAYINFO(screenmode, display) - --default the display to the current display, otherwise we need to return all available modes for the selected display - display = display or G.SETTINGS.WINDOW.selcted_display or 1 - - --default to current mode/'windowed', otherwise return all available options for specified mode - screenmode = screenmode or G.SETTINGS.WINDOW.screenmode or 'Windowed' - - --Get a count of the connected displays and iterate through them to update our window setting options accordingly - local display_count = love.window.getDisplayCount() - local res_option = 1 --This is the mode that the fullscreen option will default to for resolution, if we can find it in the list for the current monitor - local realw, realh = love.window.getMode() --the actual render resolution the window is currently using - local current_res_values = {w = realw, h = realh} - - --reset names to populate for displays - G.SETTINGS.WINDOW.display_names = {} - - for i = 1, display_count do - --reset the screen resolution table for this display and set the name - G.SETTINGS.WINDOW.DISPLAYS[i] = {} - G.SETTINGS.WINDOW.DISPLAYS[i].screen_resolutions = { - strings = {}, - values = {}, - } - G.SETTINGS.WINDOW.display_names[i] = ''..i - - --Get the render resolution and desktop resolution, this is a workaround to a known OpenGL issue where windows doesn't supply the correct DPI scaling factor - local render_w, render_h = love.window.getDesktopDimensions(i) - local unscaled_dims = love.window.getFullscreenModes(i)[1] - - --determine the DPI scale here, this can be used to determine the actual render resolution per display - G.SETTINGS.WINDOW.DISPLAYS[i].DPI_scale = 1--math.floor((0.5*unscaled_dims.width/render_w + 0.5*unscaled_dims.height/render_h)*500 + 0.5)/500 - G.SETTINGS.WINDOW.DISPLAYS[i].MONITOR_DIMS = unscaled_dims - - if screenmode == 'Fullscreen' then --Iterate through all possible screenmodes and populate the screen_resolutions table - --if the real resolution of the window is found, make sure we return that value - for _, v in ipairs(love.window.getFullscreenModes(i)) do - local _w, _h = v.width*G.SETTINGS.WINDOW.DISPLAYS[i].DPI_scale, v.height*G.SETTINGS.WINDOW.DISPLAYS[i].DPI_scale - if _w <= G.SETTINGS.WINDOW.DISPLAYS[i].MONITOR_DIMS.width and _h <= G.SETTINGS.WINDOW.DISPLAYS[i].MONITOR_DIMS.height then - G.SETTINGS.WINDOW.DISPLAYS[i].screen_resolutions.strings[#G.SETTINGS.WINDOW.DISPLAYS[i].screen_resolutions.strings+1] = ''..v.width..' X '..v.height - G.SETTINGS.WINDOW.DISPLAYS[i].screen_resolutions.values[#G.SETTINGS.WINDOW.DISPLAYS[i].screen_resolutions.values+1] = {w = v.width, h = v.height} - if i == G.SETTINGS.WINDOW.selected_display and i == display and current_res_values.w == v.width and current_res_values.h == v.height then - res_option = #G.SETTINGS.WINDOW.DISPLAYS[i].screen_resolutions.values - end - end - end - elseif screenmode == 'Windowed' then - G.SETTINGS.WINDOW.DISPLAYS[i].screen_resolutions.strings[1] = '-' - G.SETTINGS.WINDOW.DISPLAYS[i].screen_resolutions.values[1] = {w = 1280, h = 720} - elseif screenmode == 'Borderless' then - G.SETTINGS.WINDOW.DISPLAYS[i].screen_resolutions.strings[1] = - ''..G.SETTINGS.WINDOW.DISPLAYS[i].MONITOR_DIMS.width/G.SETTINGS.WINDOW.DISPLAYS[i].DPI_scale..' X ' - ..G.SETTINGS.WINDOW.DISPLAYS[i].MONITOR_DIMS.height/G.SETTINGS.WINDOW.DISPLAYS[i].DPI_scale - G.SETTINGS.WINDOW.DISPLAYS[i].screen_resolutions.values[1] = current_res_values - end - end - return res_option -end - -function timer_checkpoint(label, type, reset) - G.PREV_GARB = G.PREV_GARB or 0 - if not G.F_ENABLE_PERF_OVERLAY then return end - G.check = G.check or { - draw = { - checkpoint_list = {}, - checkpoints = 0, - last_time = 0, - }, - update = { - checkpoint_list = {}, - checkpoints = 0, - last_time = 0, - } - } - local cp = G.check[type] - if reset then - cp.last_time = love.timer.getTime() - cp.checkpoints = 0 - return - end - - cp.checkpoint_list[cp.checkpoints+1] = cp.checkpoint_list[cp.checkpoints+1] or {} - cp.checkpoints = cp.checkpoints+1 - cp.checkpoint_list[cp.checkpoints].label = label..': '..(collectgarbage( "count" ) - G.PREV_GARB) - cp.checkpoint_list[cp.checkpoints].time = love.timer.getTime() - cp.checkpoint_list[cp.checkpoints].TTC = cp.checkpoint_list[cp.checkpoints].time - cp.last_time - cp.checkpoint_list[cp.checkpoints].trend = cp.checkpoint_list[cp.checkpoints].trend or {} - cp.checkpoint_list[cp.checkpoints].states = cp.checkpoint_list[cp.checkpoints].states or {} - table.insert(cp.checkpoint_list[cp.checkpoints].trend, 1, cp.checkpoint_list[cp.checkpoints].TTC) - table.insert(cp.checkpoint_list[cp.checkpoints].states, 1, G.STATE) - cp.checkpoint_list[cp.checkpoints].trend[401] = nil - cp.checkpoint_list[cp.checkpoints].states[401] = nil - cp.last_time = cp.checkpoint_list[cp.checkpoints].time - G.PREV_GARB = collectgarbage( "count" ) - local av = 0 - for k, v in ipairs(cp.checkpoint_list[cp.checkpoints].trend) do - av = av + v/#cp.checkpoint_list[cp.checkpoints].trend - end - cp.checkpoint_list[cp.checkpoints].average = av -end - -function boot_timer(_label, _next, progress) - progress = progress or 0 - G.LOADING = G.LOADING or { - font = love.graphics.setNewFont("resources/fonts/m6x11plus.ttf", 20), - love.graphics.dis - } - local realw, realh = love.window.getMode() - love.graphics.setCanvas() - love.graphics.push() - love.graphics.setShader() - love.graphics.clear(0,0,0,1) - love.graphics.setColor(0.6, 0.8, 0.9,1) - if progress > 0 then love.graphics.rectangle('fill', realw/2 - 150, realh/2 - 15, progress*300, 30, 5) end - love.graphics.setColor(1, 1, 1,1) - love.graphics.setLineWidth(3) - love.graphics.rectangle('line', realw/2 - 150, realh/2 - 15, 300, 30, 5) - if G.F_VERBOSE and not _RELEASE_MODE then love.graphics.print("LOADING: ".._next, realw/2 - 150, realh/2 +40) end - love.graphics.pop() - love.graphics.present() - - G.ARGS.bt = G.ARGS.bt or love.timer.getTime() - G.ARGS.bt = love.timer.getTime() -end - -function EMPTY(t) - if not t then return {} end - for k, v in pairs(t) do - t[k] = nil - end - return t -end - -function interp(per, max, min) -min = min or 0 - if per and max then - return per*(max - min) + min - end -end - -function remove_all(t) - for i=#t, 1, -1 do - local v=t[i] - table.remove(t, i) - if v and v.children then - remove_all(v.children) - end - if v then v:remove() end - v = nil - end - for _, v in pairs(t) do - if v.children then remove_all(v.children) end - v:remove() - v = nil - end -end - -function Vector_Dist(trans1, trans2, mid) - local x = trans1.x - trans2.x + (mid and 0.5*(trans1.w-trans2.w) or 0) - local y = trans1.y - trans2.y + (mid and 0.5*(trans1.h-trans2.h) or 0) - return math.sqrt((x)*(x) + (y)*(y)) -end - -function Vector_Len(trans1) - return math.sqrt((trans1.x)*(trans1.x) + (trans1.y)*(trans1.y)) -end - -function Vector_Sub(trans1, trans2) - return {x = trans1.x - trans2.x, y = trans1.y - trans2.y} -end - -function get_index(t, val) - local index = nil - for i, v in pairs(t) do - if v == val then - index = i - end - end - return index -end - -function table_length(t) - local count = 0 - for _ in pairs(t) do count = count + 1 end - return count -end - -function remove_nils(t) - local ans = {} - for _,v in pairs(t) do - ans[ #ans+1 ] = v - end - return ans - end - -function SWAP(t, i, j) - if not t or not i or not j then return end - local temp = t[i] - t[i] = t[j] - t[j] = temp -end - -function pseudoshuffle(list, seed) - if seed then math.randomseed(seed) end - - if list[1] and list[1].sort_id then - table.sort(list, function (a, b) return (a.sort_id or 1) < (b.sort_id or 2) end) - end - - for i = #list, 2, -1 do - local j = math.random(i) - list[i], list[j] = list[j], list[i] - end -end - -function generate_starting_seed() - if G.GAME.stake >= #G.P_CENTER_POOLS['Stake'] then - local r_leg, r_tally = {}, 0 - local g_leg, g_tally = {}, 0 - for k, v in pairs(G.P_JOKER_RARITY_POOLS[4]) do - local win_ante = get_joker_win_sticker(v, true) - if win_ante and (win_ante >= 8) or (v.in_pool and type(v.in_pool) == 'function' and not v:in_pool()) then - g_leg[v.key] = true - g_tally = g_tally + 1 - else - r_leg[v.key] = true - r_tally = r_tally + 1 - end - end - if r_tally > 0 and g_tally > 0 then - local seed_found = nil - local extra_num = 0 - while not seed_found do - extra_num = extra_num + 0.561892350821 - seed_found = random_string(8, extra_num + G.CONTROLLER.cursor_hover.T.x*0.33411983 + G.CONTROLLER.cursor_hover.T.y*0.874146 + 0.412311010*G.CONTROLLER.cursor_hover.time) - if not r_leg[get_first_legendary(seed_found)] then seed_found = nil end - end - return seed_found - end - end - - return random_string(8, G.CONTROLLER.cursor_hover.T.x*0.33411983 + G.CONTROLLER.cursor_hover.T.y*0.874146 + 0.412311010*G.CONTROLLER.cursor_hover.time) -end - -function get_first_legendary(_key) - local _t, key = pseudorandom_element(G.P_JOKER_RARITY_POOLS[4], pseudoseed('Joker4', _key)) - return _t.key -end - -function pseudorandom_element(_t, seed, args) - -- TODO special cases for now - -- Preserves reverse nominal order for Suits, nominal+face_nominal order for Ranks - -- for vanilla RNG - if _t == SMODS.Suits then - _t = SMODS.Suit:obj_list(true) - end - if _t == SMODS.Ranks then - _t = SMODS.Rank:obj_list() - end - if seed then math.randomseed(seed) end - local keys = {} - for k, v in pairs(_t) do - local keep = true - local in_pool_func = - args and args.in_pool - or type(v) == 'table' and type(v.in_pool) == 'function' and v.in_pool - or _t == G.P_CARDS and function(c) - --Handles special case for Erratic Deck - local initial_deck = args and args.starting_deck or false - - return not ( - type(SMODS.Ranks[c.value].in_pool) == 'function' and not SMODS.Ranks[c.value]:in_pool({initial_deck = initial_deck, suit = c.suit}) - or type(SMODS.Suits[c.suit].in_pool) == 'function' and not SMODS.Suits[c.suit]:in_pool({initial_deck = initial_deck, rank = c.value}) - ) - end - if in_pool_func then - keep = in_pool_func(v, args) - end - if keep then - keys[#keys+1] = {k = k,v = v} - end - end - - if keys[1] and keys[1].v and type(keys[1].v) == 'table' and keys[1].v.sort_id then - table.sort(keys, function (a, b) return a.v.sort_id < b.v.sort_id end) - else - table.sort(keys, function (a, b) return a.k < b.k end) - end - - if #keys == 0 then return nil, nil end - local key = keys[math.random(#keys)].k - return _t[key], key -end - -function random_string(length, seed) - if seed then math.randomseed(seed) end - local ret = '' - for i = 1, length do - ret = ret..string.char(math.random() > 0.7 and math.random(string.byte('1'),string.byte('9')) or (math.random() > 0.45 and math.random(string.byte('A'),string.byte('N')) or math.random(string.byte('P'),string.byte('Z')))) - end - return string.upper(ret) -end - -function pseudohash(str) - if true then - local num = 1 - for i=#str, 1, -1 do - num = ((1.1239285023/num)*string.byte(str, i)*math.pi + math.pi*i)%1 - end - return num - else - str = string.sub(string.format("%-16s",str), 1, 24) - - local h = 0 - - for i=#str, 1, -1 do - h = bit.bxor(h, bit.lshift(h, 7) + bit.rshift(h, 3) + string.byte(str, i)) - end - return tonumber(string.format("%.13f",math.sqrt(math.abs(h))%1)) - end -end - -function pseudoseed(key, predict_seed) - if key == 'seed' then return math.random() end - - if predict_seed then - local _pseed = pseudohash(key..(predict_seed or '')) - _pseed = math.abs(tonumber(string.format("%.13f", (2.134453429141+_pseed*1.72431234)%1))) - return (_pseed + (pseudohash(predict_seed) or 0))/2 - end - - if not G.GAME.pseudorandom[key] then - G.GAME.pseudorandom[key] = pseudohash(key..(G.GAME.pseudorandom.seed or '')) - end - - G.GAME.pseudorandom[key] = math.abs(tonumber(string.format("%.13f", (2.134453429141+G.GAME.pseudorandom[key]*1.72431234)%1))) - return (G.GAME.pseudorandom[key] + (G.GAME.pseudorandom.hashed_seed or 0))/2 -end - -function pseudorandom(seed, min, max) - if type(seed) == 'string' then seed = pseudoseed(seed) end - math.randomseed(seed) - if min and max then return math.random(min, max) - else return math.random() end -end - -function tprint(tbl, indent) - if not indent then indent = 0 end - local toprint = string.rep(" ", indent) .. "{\r\n" - indent = indent + 2 - for k, v in pairs(tbl) do - toprint = toprint .. string.rep(" ", indent) - if (type(k) == "number") then - toprint = toprint .. "[" .. k .. "] = " - elseif (type(k) == "string") then - toprint = toprint .. k .. "= " - end - if (type(v) == "number") then - toprint = toprint .. v .. ",\r\n" - elseif (type(v) == "string") then - toprint = toprint .. "\"" .. v .. "\",\r\n" - elseif (type(v) == "table") then - if indent>=10 then - toprint = toprint .. tostring(v) .. ",\r\n" - else - toprint = toprint .. tostring(v) .. tprint(v, indent + 1) .. ",\r\n" - end - else - toprint = toprint .. "\"" .. tostring(v) .. "\",\r\n" - end - end - toprint = toprint .. string.rep(" ", indent-2) .. "}" - return toprint -end - -function sortingFunction(e1, e2) - return e1.order < e2.order -end - -function HEX(hex) - if #hex <= 6 then hex = hex.."FF" end - local _,_,r,g,b,a = hex:find('(%x%x)(%x%x)(%x%x)(%x%x)') - local color = {tonumber(r,16)/255,tonumber(g,16)/255,tonumber(b,16)/255,tonumber(a,16)/255 or 255} - return color -end - -function get_blind_main_colour(blind) --either in the form of the blind key for the P_BLINDS table or type - local disabled = false - blind = blind or '' - if blind == 'Boss' or blind == 'Small' or blind == 'Big' then - G.GAME.round_resets.blind_states = G.GAME.round_resets.blind_states or {} - if G.GAME.round_resets.blind_states[blind] == 'Defeated' or G.GAME.round_resets.blind_states[blind] == 'Skipped' then disabled = true end - blind = G.GAME.round_resets.blind_choices[blind] - end - return (disabled or not G.P_BLINDS[blind]) and G.C.BLACK or - G.P_BLINDS[blind].boss_colour or - (blind == 'bl_small' and mix_colours(G.C.BLUE, G.C.BLACK, 0.6) or - blind == 'bl_big' and mix_colours(G.C.ORANGE, G.C.BLACK, 0.6)) or G.C.BLACK -end - -function evaluate_poker_hand(hand) - - local results = { - ["Flush Five"] = {}, - ["Flush House"] = {}, - ["Five of a Kind"] = {}, - ["Straight Flush"] = {}, - ["Four of a Kind"] = {}, - ["Full House"] = {}, - ["Flush"] = {}, - ["Straight"] = {}, - ["Three of a Kind"] = {}, - ["Two Pair"] = {}, - ["Pair"] = {}, - ["High Card"] = {}, - top = nil - } - - for _,v in ipairs(SMODS.PokerHand.obj_buffer) do - results[v] = {} - end - local parts = { - _5 = get_X_same(5,hand), - _4 = get_X_same(4,hand), - _3 = get_X_same(3,hand), - _2 = get_X_same(2,hand), - _flush = get_flush(hand), - _straight = get_straight(hand), - _highest = get_highest(hand) - } - - for _,_hand in pairs(SMODS.PokerHands) do - if _hand.atomic_part and type(_hand.atomic_part) == 'function' then - parts[_hand.key] = _hand.atomic_part(hand) - end - end - if next(parts._5) and next(parts._flush) then - results["Flush Five"] = parts._5 - if not results.top then results.top = results["Flush Five"] end - end - - if next(parts._3) and next(parts._2) and next(parts._flush) then - local fh_hand = {} - local fh_3 = parts._3[1] - local fh_2 = parts._2[1] - for i=1, #fh_3 do - fh_hand[#fh_hand+1] = fh_3[i] - end - for i=1, #fh_2 do - fh_hand[#fh_hand+1] = fh_2[i] - end - table.insert(results["Flush House"], fh_hand) - if not results.top then results.top = results["Flush House"] end - end - - if next(parts._5) then - results["Five of a Kind"] = parts._5 - if not results.top then results.top = results["Five of a Kind"] end - end - - if next(parts._flush) and next(parts._straight) then - local _s, _f, ret = parts._straight, parts._flush, {} - for _, v in ipairs(_f[1]) do - ret[#ret+1] = v - end - for _, v in ipairs(_s[1]) do - local in_straight = nil - for _, vv in ipairs(_f[1]) do - if vv == v then in_straight = true end - end - if not in_straight then ret[#ret+1] = v end - end - - results["Straight Flush"] = {ret} - if not results.top then results.top = results["Straight Flush"] end - end - - if next(parts._4) then - results["Four of a Kind"] = parts._4 - if not results.top then results.top = results["Four of a Kind"] end - end - - if next(parts._3) and next(parts._2) then - local fh_hand = {} - local fh_3 = parts._3[1] - local fh_2 = parts._2[1] - for i=1, #fh_3 do - fh_hand[#fh_hand+1] = fh_3[i] - end - for i=1, #fh_2 do - fh_hand[#fh_hand+1] = fh_2[i] - end - table.insert(results["Full House"], fh_hand) - if not results.top then results.top = results["Full House"] end - end - - if next(parts._flush) then - results["Flush"] = parts._flush - if not results.top then results.top = results["Flush"] end - end - - if next(parts._straight) then - results["Straight"] = parts._straight - if not results.top then results.top = results["Straight"] end - end - - if next(parts._3) then - results["Three of a Kind"] = parts._3 - if not results.top then results.top = results["Three of a Kind"] end - end - - if (#parts._2 == 2) or (#parts._3 == 1 and #parts._2 == 1) then - local fh_hand = {} - local r = parts._2 - local fh_2a = r[1] - local fh_2b = r[2] - if not fh_2b then - fh_2b = parts._3[1] - end - for i=1, #fh_2a do - fh_hand[#fh_hand+1] = fh_2a[i] - end - for i=1, #fh_2b do - fh_hand[#fh_hand+1] = fh_2b[i] - end - table.insert(results["Two Pair"], fh_hand) - if not results.top then results.top = results["Two Pair"] end - end - - if next(parts._2) then - results["Pair"] = parts._2 - if not results.top then results.top = results["Pair"] end - end - - if next(parts._highest) then - results["High Card"] = parts._highest - if not results.top then results.top = results["High Card"] end - end - - if results["Five of a Kind"][1] then - results["Four of a Kind"] = {results["Five of a Kind"][1], results["Five of a Kind"][2], results["Five of a Kind"][3], results["Five of a Kind"][4]} - end - - if results["Four of a Kind"][1] then - results["Three of a Kind"] = {results["Four of a Kind"][1], results["Four of a Kind"][2], results["Four of a Kind"][3]} - end - - if results["Three of a Kind"][1] then - results["Pair"] = {results["Three of a Kind"][1], results["Three of a Kind"][2]} - end - - for _,_hand in pairs(SMODS.PokerHands) do - if _hand.composite and type(_hand.composite) == 'function' then - local other_hands - results[_hand.key], other_hands = _hand.composite(parts) - results[_hand.key] = results[_hand.key] or {} - if other_hands and type(other_hands) == 'table' then - for k, v in pairs(other_hands) do - results[k] = v - end - end - else - results[_hand.key] = parts[_hand.key] - end - end - results.top = nil - for _, v in ipairs(G.handlist) do - if not results.top and results[v] then - results.top = results[v] - break - end - end - return results -end - -function get_flush(hand) - local ret = {} - local four_fingers = next(find_joker('Four Fingers')) - local suits = SMODS.Suit.obj_buffer - if #hand < (5 - (four_fingers and 1 or 0)) then return ret else - for j = 1, #suits do - local t = {} - local suit = suits[j] - local flush_count = 0 - for i=1, #hand do - if hand[i]:is_suit(suit, nil, true) then flush_count = flush_count + 1; t[#t+1] = hand[i] end - end - if flush_count >= (5 - (four_fingers and 1 or 0)) then - table.insert(ret, t) - return ret - end - end - return {} - end -end - -function get_straight(hand) - local ret = {} - local four_fingers = next(find_joker('Four Fingers')) - if #hand > 5 or #hand < (5 - (four_fingers and 1 or 0)) then return ret else - local t = {} - local IDS = {} - for i=1, #hand do - local id = hand[i]:get_id() - if id > 1 and id < 15 then - if IDS[id] then - IDS[id][#IDS[id]+1] = hand[i] - else - IDS[id] = {hand[i]} - end - end - end - - local straight_length = 0 - local straight = false - local can_skip = next(find_joker('Shortcut')) - local skipped_rank = false - for j = 1, 14 do - if IDS[j == 1 and 14 or j] then - straight_length = straight_length + 1 - skipped_rank = false - for k, v in ipairs(IDS[j == 1 and 14 or j]) do - t[#t+1] = v - end - elseif can_skip and not skipped_rank and j ~= 14 then - skipped_rank = true - else - straight_length = 0 - skipped_rank = false - if not straight then t = {} end - if straight then break end - end - if straight_length >= (5 - (four_fingers and 1 or 0)) then straight = true end - end - if not straight then return ret end - table.insert(ret, t) - return ret - end -end - -function get_X_same(num, hand, or_more) - local vals = {} - for i = 1, SMODS.Rank.max_id.value do - vals[i] = {} - end - for i=#hand, 1, -1 do - local curr = {} - table.insert(curr, hand[i]) - for j=1, #hand do - if hand[i]:get_id() == hand[j]:get_id() and i ~= j then - table.insert(curr, hand[j]) - end - end - if or_more and (#curr >= num) or (#curr == num) then - vals[curr[1]:get_id()] = curr - end - end - local ret = {} - for i=#vals, 1, -1 do - if next(vals[i]) then table.insert(ret, vals[i]) end - end - return ret -end - -function get_highest(hand) - local highest = nil - for k, v in ipairs(hand) do - if not highest or v:get_nominal() > highest:get_nominal() then - highest = v - end - end - if #hand > 0 then return {{highest}} else return {} end -end - -function reset_drawhash() - G.DRAW_HASH = EMPTY(G.DRAW_HASH) -end - ---Copyright 2021 Max Cahill (Zlib license) --- ---This software is provided 'as-is', without any express or implied ---warranty. In no event will the authors be held liable for any damages ---arising from the use of this software. --- ---Permission is granted to anyone to use this software for any purpose, ---including commercial applications, and to alter it and redistribute it ---freely, subject to the following restrictions: --- ---1. The origin of this software must not be misrepresented; you must not --- claim that you wrote the original software. If you use this software --- in a product, an acknowledgment in the product documentation would be --- appreciated but is not required. ---2. Altered source versions must be plainly marked as such, and must not be --- misrepresented as being the original software. ---3. This notice may not be removed or altered from any source distribution. ---This function was slightly modified from it's original state -function nuGC(time_budget, memory_ceiling, disable_otherwise) - time_budget = time_budget or 3e-4 - memory_ceiling = memory_ceiling or 300 - local max_steps = 1000 - local steps = 0 - local start_time = love.timer.getTime() - while - love.timer.getTime() - start_time < time_budget and - steps < max_steps - do - collectgarbage("step", 1) - steps = steps + 1 - end - --safety net - if collectgarbage("count") / 1024 > memory_ceiling then - collectgarbage("collect") - end - --don't collect gc outside this margin - if disable_otherwise then - collectgarbage("stop") - end -end - ---The drawhash is a hash table of all drawn nodes and all nodes that may be invisible but still collide with the cursor -function add_to_drawhash(obj) - if obj then - G.DRAW_HASH[#G.DRAW_HASH+1] = obj - end -end - -function mix_colours(C1, C2, proportionC1) - return { - (C1[1] or 0.5)*proportionC1 + (C2[1] or 0.5)*(1-proportionC1), - (C1[2] or 0.5)*proportionC1 + (C2[2] or 0.5)*(1-proportionC1), - (C1[3] or 0.5)*proportionC1 + (C2[3] or 0.5)*(1-proportionC1), - (C1[4] or 1)*proportionC1 + (C2[4] or 1)*(1-proportionC1), - } -end - -function mod_chips(_chips) - if G.GAME.modifiers.chips_dollar_cap then - _chips = math.min(_chips, math.max(G.GAME.dollars, 0)) - end - return _chips -end - -function mod_mult(_mult) - return _mult -end - -function play_sound(sound_code, per, vol) - if G.F_MUTE then return end - if sound_code and G.SETTINGS.SOUND.volume > 0.001 then - G.ARGS.play_sound = G.ARGS.play_sound or {} - G.ARGS.play_sound.type = 'sound' - G.ARGS.play_sound.time = G.TIMERS.REAL - G.ARGS.play_sound.crt = G.SETTINGS.GRAPHICS.crt - G.ARGS.play_sound.sound_code = sound_code - G.ARGS.play_sound.per = per - G.ARGS.play_sound.vol = vol - G.ARGS.play_sound.pitch_mod = G.PITCH_MOD - G.ARGS.play_sound.state = G.STATE - G.ARGS.play_sound.music_control = G.SETTINGS.music_control - G.ARGS.play_sound.sound_settings = G.SETTINGS.SOUND - G.ARGS.play_sound.splash_vol = G.SPLASH_VOL - G.ARGS.play_sound.overlay_menu = not (not G.OVERLAY_MENU) - if G.F_SOUND_THREAD then - G.SOUND_MANAGER.channel:push(G.ARGS.play_sound) - else - PLAY_SOUND(G.ARGS.play_sound) - end - end -end - -function modulate_sound(dt) - --volume of the splash screen is set here - G.SPLASH_VOL = 2*dt*(G.STATE == G.STATES.SPLASH and 1 or 0) + (G.SPLASH_VOL or 1)*(1-2*dt) - - --Control the music here - local desired_track = - G.video_soundtrack or - (G.STATE == G.STATES.SPLASH and '') or - SMODS.Sound:get_current_music() or - (G.booster_pack_sparkles and not G.booster_pack_sparkles.REMOVED and 'music2') or - (G.booster_pack_meteors and not G.booster_pack_meteors.REMOVED and 'music3') or - (G.booster_pack and not G.booster_pack.REMOVED and 'music2') or - (G.shop and not G.shop.REMOVED and 'music4') or - (G.GAME.blind and G.GAME.blind.boss and 'music5') or - ('music1') - - G.PITCH_MOD = (G.PITCH_MOD or 1)*(1 - dt) + dt*((not G.normal_music_speed and G.STATE == G.STATES.GAME_OVER) and 0.5 or 1) - - --For ambient sound control - G.SETTINGS.ambient_control = G.SETTINGS.ambient_control or {} - G.ARGS.score_intensity = G.ARGS.score_intensity or {} - if not is_number(G.GAME.current_round.current_hand.chips) or not is_number(G.GAME.current_round.current_hand.mult) then - G.ARGS.score_intensity.earned_score = 0 - else - G.ARGS.score_intensity.earned_score = G.GAME.current_round.current_hand.chips*G.GAME.current_round.current_hand.mult - end - G.ARGS.score_intensity.required_score = G.GAME.blind and G.GAME.blind.chips or 0 - if G.cry_flame_override and G.cry_flame_override['duration'] > 0 then - G.cry_flame_override['duration'] = math.max(0, G.cry_flame_override['duration'] - dt) - end - G.ARGS.score_intensity.flames = math.min(1, (G.STAGE == G.STAGES.RUN and 1 or 0)*( - (G.ARGS.chip_flames and (G.ARGS.chip_flames.real_intensity + G.ARGS.chip_flames.change) or 0))/10) - G.ARGS.score_intensity.organ = G.video_organ or to_big(G.ARGS.score_intensity.required_score) > to_big(0) and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0 - - local AC = G.SETTINGS.ambient_control - G.ARGS.ambient_sounds = G.ARGS.ambient_sounds or { - ambientFire2 = {volfunc = function(_prev_volume) return _prev_volume*(1 - dt) + dt*0.9*((G.ARGS.score_intensity.flames > 0.3) and 1 or G.ARGS.score_intensity.flames/0.3) end}, - ambientFire1 = {volfunc = function(_prev_volume) return _prev_volume*(1 - dt) + dt*0.8*((G.ARGS.score_intensity.flames > 0.3) and (G.ARGS.score_intensity.flames-0.3)/0.7 or 0) end}, - ambientFire3 = {volfunc = function(_prev_volume) return _prev_volume*(1 - dt) + dt*0.4*((G.ARGS.chip_flames and G.ARGS.chip_flames.change or 0) + (G.ARGS.mult_flames and G.ARGS.mult_flames.change or 0)) end}, - ambientOrgan1 = {volfunc = function(_prev_volume) return _prev_volume*(1 - dt) + dt*0.6*(G.SETTINGS.SOUND.music_volume + 100)/200*(G.ARGS.score_intensity.organ) end}, - } - - for k, v in pairs(G.ARGS.ambient_sounds) do - AC[k] = AC[k] or {} - AC[k].per = (k == 'ambientOrgan1') and 0.7 or (k == 'ambientFire1' and 1.1) or (k == 'ambientFire2' and 1.05) or 1 - AC[k].vol = Cartomancer.handle_flames_volume((not G.video_organ and G.STATE == G.STATES.SPLASH) and 0 or AC[k].vol and v.volfunc(AC[k].vol) or 0) - end - - G.ARGS.push = G.ARGS.push or {} - G.ARGS.push.type = 'modulate' - G.ARGS.push.pitch_mod = G.PITCH_MOD - G.ARGS.push.state = G.STATE - G.ARGS.push.time = G.TIMERS.REAL - G.ARGS.push.dt = dt - G.ARGS.push.desired_track = desired_track - G.ARGS.push.sound_settings = G.SETTINGS.SOUND - G.ARGS.push.splash_vol = G.SPLASH_VOL - G.ARGS.push.overlay_menu = not (not G.OVERLAY_MENU) - G.ARGS.push.ambient_control = G.SETTINGS.ambient_control - if SMODS.remove_replace_sound and SMODS.remove_replace_sound ~= desired_track then - SMODS.Sound.replace_sounds[SMODS.remove_replace_sound] = nil - SMODS.remove_replace_sound = nil - end - local replace_sound = SMODS.Sound.replace_sounds[desired_track] - if replace_sound then - local replaced_track = desired_track - desired_track = replace_sound.key - G.ARGS.push.desired_track = desired_track - if SMODS.previous_track ~= desired_track then - if replace_sound.times > 0 then replace_sound.times = replace_sound.times - 1 end - if replace_sound.times == 0 then SMODS.remove_replace_sound = replaced_track end - end - end - local stop_sound = SMODS.Sound.stop_sounds[desired_track] - if SMODS.Sound.stop_sounds[desired_track] then - if SMODS.previous_track ~= '' and stop_sound > 0 then stop_sound = stop_sound - 1 end - SMODS.Sound.stop_sounds[desired_track] = stop_sound ~= 0 and stop_sound or nil - SMODS.previous_track = '' - return - end - - if G.F_SOUND_THREAD then - G.SOUND_MANAGER.channel:push(G.ARGS.push) - SMODS.previous_track = SMODS.previous_track or '' - local in_sync = (SMODS.Sounds[desired_track] or {}).sync - local out_sync = (SMODS.Sounds[SMODS.previous_track] or {}).sync - local should_sync = true - if (type(in_sync) == 'table' and not in_sync[SMODS.previous_track]) or in_sync == false then should_sync = false end - if (type(out_sync) == 'table' and not out_sync[desired_track]) or out_sync == false then should_sync = false end - if - SMODS.previous_track and SMODS.previous_track ~= desired_track and - not should_sync - then - G.ARGS.push.type = 'restart_music' - G.SOUND_MANAGER.channel:push(G.ARGS.push) - end - SMODS.previous_track = desired_track - else - MODULATE(G.ARGS.push) - end -end - -function count_of_suit(area, suit) - local num = 0 - for _,c in pairs(area.cards) do - if c.base.suit == suit then - num = num +1 - end - end - return num -end - -function prep_draw(moveable, scale, rotate, offset) -if Big and G.STATE == G.STATES.MENU then moveable.VT.x = to_big(moveable.VT.x):to_number() -moveable.VT.y = to_big(moveable.VT.y):to_number() -moveable.VT.w = to_big(moveable.VT.w):to_number() -moveable.VT.h = to_big(moveable.VT.h):to_number() end - love.graphics.push() - love.graphics.scale(G.TILESCALE*G.TILESIZE) - love.graphics.translate( - moveable.VT.x+moveable.VT.w/2 + (offset and offset.x or 0) + ((moveable.layered_parallax and moveable.layered_parallax.x) or ((moveable.parent and moveable.parent.layered_parallax and moveable.parent.layered_parallax.x)) or 0), - moveable.VT.y+moveable.VT.h/2 + (offset and offset.y or 0) + ((moveable.layered_parallax and moveable.layered_parallax.y) or ((moveable.parent and moveable.parent.layered_parallax and moveable.parent.layered_parallax.y)) or 0)) - if moveable.VT.r ~= 0 or moveable.juice or rotate then love.graphics.rotate(moveable.VT.r + (rotate or 0)) end - love.graphics.translate( - -scale*moveable.VT.w*(moveable.VT.scale)/2, - -scale*moveable.VT.h*(moveable.VT.scale)/2) - love.graphics.scale(moveable.VT.scale*scale) -end - -function get_chosen_triangle_from_rect(x, y, w, h, vert) - local scale = 2 - if vert then - x = x + math.min(0.6*math.sin(G.TIMERS.REAL*9)*scale+0.2, 0) - return { - x-3.5*scale, y+h/2 - 1.5*scale, - x-0.5*scale, y+h/2 + 0, - x-3.5*scale,y+h/2 + 1.5*scale - } - else - y = y + math.min(0.6*math.sin(G.TIMERS.REAL*9)*scale+0.2, 0) - return { - x+w/2 - 1.5*scale, y-4*scale, - x+w/2 + 0, y-1.1*scale, - x+w/2 + 1.5*scale, y-4*scale - } - end -end - -function point_translate(_T, delta) - _T.x = (_T.x + delta.x) or 0 - _T.y = (_T.y + delta.y) or 0 -end - -function point_rotate(_T, angle) - local _cos, _sin, _ox, _oy = math.cos(angle+math.pi/2), math.sin(angle+math.pi/2), _T.x , _T.y - _T.x = -_oy*_cos + _ox*_sin - _T.y = _oy*_sin + _ox*_cos -end - -function lighten(colour, percent, no_tab) - if no_tab then - return - colour[1]*(1-percent)+percent, - colour[2]*(1-percent)+percent, - colour[3]*(1-percent)+percent, - colour[4] - end - return { - colour[1]*(1-percent)+percent, - colour[2]*(1-percent)+percent, - colour[3]*(1-percent)+percent, - colour[4] - } -end - -function darken(colour, percent, no_tab) - if no_tab then - return - colour[1]*(1-percent), - colour[2]*(1-percent), - colour[3]*(1-percent), - colour[4] - end - return { - colour[1]*(1-percent), - colour[2]*(1-percent), - colour[3]*(1-percent), - colour[4] - } -end - -function adjust_alpha(colour, new_alpha, no_tab) - if no_tab then - return - colour[1], - colour[2], - colour[3], - new_alpha - end - return { - colour[1], - colour[2], - colour[3], - new_alpha - } -end - -function alert_no_space(card, area) - G.CONTROLLER.locks.no_space = true - attention_text({ - scale = 0.9, text = localize('k_no_space_ex'), hold = 0.9, align = 'cm', - cover = area, cover_padding = 0.1, cover_colour = adjust_alpha(G.C.BLACK, 0.7) - }) - card:juice_up(0.3, 0.2) - for i = 1, #area.cards do - area.cards[i]:juice_up(0.15) - end - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.06*G.SETTINGS.GAMESPEED, blockable = false, blocking = false, func = function() - play_sound('tarot2', 0.76, 0.4);return true end})) - play_sound('tarot2', 1, 0.4) - - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.5*G.SETTINGS.GAMESPEED, blockable = false, blocking = false, - func = function() - G.CONTROLLER.locks.no_space = nil - return true end})) -end - -function find_joker(name, non_debuff) - local jokers = {} - if not G.jokers or not G.jokers.cards then return {} end - for k, v in pairs(G.jokers.cards) do - if v and type(v) == 'table' and v.ability.name == name and (non_debuff or not v.debuff) then - table.insert(jokers, v) - end - end - for k, v in pairs(G.consumeables.cards) do - if v and type(v) == 'table' and v.ability.name == name and (non_debuff or not v.debuff) then - table.insert(jokers, v) - end - end - return jokers -end - -function get_blind_amount(ante) -if G.GAME.modifiers.scaling and G.GAME.modifiers.scaling > 3 then return SMODS.get_blind_amount(ante) end - local k = 0.75 - if not G.GAME.modifiers.scaling or G.GAME.modifiers.scaling == 1 then - local amounts = { - 300, 800, 2000, 5000, 11000, 20000, 35000, 50000 - } - if ante < 1 then return 100 end - if ante <= 8 then return amounts[ante] end - local a, b, c, d = amounts[8],1.6,ante-8, 1 + 0.2*(ante-8) - local amount = math.floor(a*(b+(k*c)^d)^c) - amount = amount - amount%(10^math.floor(math.log10(amount)-1)) - return amount - elseif G.GAME.modifiers.scaling == 2 then - local amounts = { - 300, 900, 2600, 8000, 20000, 36000, 60000, 100000 - --300, 900, 2400, 7000, 18000, 32000, 56000, 90000 - } - if ante < 1 then return 100 end - if ante <= 8 then return amounts[ante] end - local a, b, c, d = amounts[8],1.6,ante-8, 1 + 0.2*(ante-8) - local amount = math.floor(a*(b+(k*c)^d)^c) - amount = amount - amount%(10^math.floor(math.log10(amount)-1)) - return amount - elseif G.GAME.modifiers.scaling == 3 then - local amounts = { - 300, 1000, 3200, 9000, 25000, 60000, 110000, 200000 - --300, 1000, 3000, 8000, 22000, 50000, 90000, 180000 - } - if ante < 1 then return 100 end - if ante <= 8 then return amounts[ante] end - local a, b, c, d = amounts[8],1.6,ante-8, 1 + 0.2*(ante-8) - local amount = math.floor(a*(b+(k*c)^d)^c) - amount = amount - amount%(10^math.floor(math.log10(amount)-1)) - return amount - end -end - -function number_format(num, e_switch_point) - if type(num) ~= 'number' then return num end - - local sign = (num >= 0 and "") or "-" - num = math.abs(num) - G.E_SWITCH_POINT = G.E_SWITCH_POINT or 100000000000 - if not num or type(num) ~= 'number' then return num or '' end - if num >= (e_switch_point or G.E_SWITCH_POINT) then - local x = string.format("%.4g",num) - local fac = math.floor(math.log(tonumber(x), 10)) - if num == math.huge then - return sign.."naneinf" - end - - local mantissa = round_number(x/(10^fac), 3) - if mantissa >= 10 then - mantissa = mantissa / 10 - fac = fac + 1 - end - return sign..(string.format(fac >= 100 and "%.1fe%i" or fac >= 10 and "%.2fe%i" or "%.3fe%i", mantissa, fac)) - end - local formatted - if num ~= math.floor(num) and num < 100 then - formatted = string.format(num >= 10 and "%.1f" or "%.2f", num) - if formatted:sub(-1) == "0" then - formatted = formatted:gsub("%.?0+$", "") - end - -- Return already to avoid comas being added - if num < 0.01 then return tostring(num) end - else - formatted = string.format("%.0f", num) - end - return sign..(formatted:reverse():gsub("(%d%d%d)", "%1,"):gsub(",$", ""):reverse()) -end - -function score_number_scale(scale, amt) - G.E_SWITCH_POINT = G.E_SWITCH_POINT or 100000000000 - if type(amt) ~= 'number' then return 0.7*(scale or 1) end - if amt >= G.E_SWITCH_POINT then - return 0.7*(scale or 1) - elseif amt >= 1000000 then - return 14*0.75/(math.floor(math.log(amt))+4)*(scale or 1) - else - return 0.75*(scale or 1) - end -end - -function copy_table(O) - local O_type = type(O) - local copy - if O_type == 'table' then - copy = {} - for k, v in next, O, nil do - copy[copy_table(k)] = copy_table(v) - end - setmetatable(copy, copy_table(getmetatable(O))) - else - copy = O - end - return copy -end - -function send_score(_score) - if G.F_HTTP_SCORES and G.SETTINGS.COMP and G.F_STREAMER_EVENT then - G.HTTP_MANAGER.out_channel:push({ - set_score = true, - score = _score, - username = G.SETTINGS.COMP.name, - uid = tostring(G.STEAM.user.getSteamID()), - version = G.VERSION - }) - end -end - -function send_name() - if G.F_HTTP_SCORES and G.SETTINGS.COMP and G.F_STREAMER_EVENT then - G.HTTP_MANAGER.out_channel:push({ - set_name = true, - username = G.SETTINGS.COMP.name, - uid = tostring(G.STEAM.user.getSteamID()), - version = G.VERSION - }) - end -end - -function check_and_set_high_score(score, amt) - if not amt or type(amt) ~= 'number' then return end - if G.GAME.round_scores[score] and math.floor(amt) > (G.GAME.round_scores[score].amt or 0) then - G.GAME.round_scores[score].amt = math.floor(amt) - end - if G.GAME.seeded then return end - if score == 'hand' and G.SETTINGS.COMP and ((not G.SETTINGS.COMP.score) or (G.SETTINGS.COMP.score < math.floor(amt))) then - G.SETTINGS.COMP.score = amt - send_score(math.floor(amt)) - end - if G.PROFILES[G.SETTINGS.profile].high_scores[score] and math.floor(amt) > G.PROFILES[G.SETTINGS.profile].high_scores[score].amt then - if G.GAME.round_scores[score] then G.GAME.round_scores[score].high_score = true end - G.PROFILES[G.SETTINGS.profile].high_scores[score].amt = math.floor(amt) - G:save_settings() - end -end - -function set_joker_usage() - for k, v in pairs(G.jokers.cards) do - if v.config.center_key and v.ability.set == 'Joker' then - if G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key] then - G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].count = G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].count + 1 - else - G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key] = {count = 1, order = v.config.center.order, wins = {}, losses = {}, wins_by_key = {}, losses_by_key = {}} - end - end - end - G:save_settings() -end - -function set_joker_win() - for k, v in pairs(G.jokers.cards) do - if v.config.center_key and v.ability.set == 'Joker' then - G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key] = G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key] or {count = 1, order = v.config.center.order, wins = {}, losses = {}, wins_by_key = {}, losses_by_key = {}} - if G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key] then - G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].wins = G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].wins or {} - G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].wins[G.GAME.stake] = (G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].wins[G.GAME.stake] or 0) + 1 - G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].wins_by_key[SMODS.stake_from_index(G.GAME.stake)] = (G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].wins_by_key[SMODS.stake_from_index(G.GAME.stake)] or 0) + 1 - end - end - end - G:save_settings() -end - -function get_joker_win_sticker(_center, index) - if G.PROFILES[G.SETTINGS.profile].joker_usage[_center.key] and - G.PROFILES[G.SETTINGS.profile].joker_usage[_center.key].wins then - local _w = 0 - for k, v in pairs(G.PROFILES[G.SETTINGS.profile].joker_usage[_center.key].wins) do - _w = math.max(k, _w) - end - if index then return _w end - if _w > 0 then return G.sticker_map[_w] end - end - if index then return 0 end -end - -function set_joker_loss() - for k, v in pairs(G.jokers.cards) do - if v.config.center_key and v.ability.set == 'Joker' then - if G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key] then - G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].losses = G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].losses or {} - G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].losses[G.GAME.stake] = (G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].losses[G.GAME.stake] or 0) + 1 - G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].losses_by_key[SMODS.stake_from_index(G.GAME.stake)] = (G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].losses_by_key[SMODS.stake_from_index(G.GAME.stake)] or 0) + 1 - end - end - end - G:save_settings() -end - -function set_deck_usage() - if G.GAME.selected_back and G.GAME.selected_back.effect and G.GAME.selected_back.effect.center and G.GAME.selected_back.effect.center.key then - local deck_key = G.GAME.selected_back.effect.center.key - if G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] then - G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key].count = G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key].count + 1 - else - G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] = {count = 1, order = G.GAME.selected_back.effect.center.order, wins = {}, losses = {}, wins_by_key = {}, losses_by_key = {}} - end - G:save_settings() - end -end - -function set_deck_win() - if G.GAME.selected_back and G.GAME.selected_back.effect and G.GAME.selected_back.effect.center and G.GAME.selected_back.effect.center.key then - local deck_key = G.GAME.selected_back.effect.center.key - if not G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] then G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] = {count = 1, order = G.GAME.selected_back.effect.center.order, wins = {}, losses = {}, wins_by_key = {}, losses_by_key = {}} end - if G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] then - G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key].wins[G.GAME.stake] = (G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key].wins[G.GAME.stake] or 0) + 1 - for i = 1, - (G.P_CENTER_POOLS["Stake"][G.GAME.stake].unlocked_stake) and - (G.P_STAKES[G.P_CENTER_POOLS["Stake"][G.GAME.stake].unlocked_stake].stake_level-1) or (G.GAME.stake-1) - do - G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key].wins[i] = (G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key].wins[i] or 1) - end - end - set_challenge_unlock() - G:save_settings() - end -end - -function set_challenge_unlock() - if G.PROFILES[G.SETTINGS.profile].all_unlocked then return end - if G.PROFILES[G.SETTINGS.profile].challenges_unlocked then - local _ch_comp, _ch_tot = 0,#G.CHALLENGES - for k, v in ipairs(G.CHALLENGES) do - if v.id and G.PROFILES[G.SETTINGS.profile].challenge_progress.completed[v.id or ''] then - _ch_comp = _ch_comp + 1 - end - end - G.PROFILES[G.SETTINGS.profile].challenges_unlocked = math.min(_ch_tot, _ch_comp+5) - else - local deck_wins = 0 - for k, v in pairs(G.PROFILES[G.SETTINGS.profile].deck_usage) do - if v.wins and v.wins[1] then - deck_wins = deck_wins + 1 - end - end - if deck_wins >= G.CHALLENGE_WINS and not G.PROFILES[G.SETTINGS.profile].challenges_unlocked then - G.PROFILES[G.SETTINGS.profile].challenges_unlocked = 5 - notify_alert('b_challenge', "Back") - end - end -end - -function get_deck_win_stake(_deck_key) - if not _deck_key then - local _w, _w_low = 0, nil - local deck_count = 0 - for _, deck in pairs(G.PROFILES[G.SETTINGS.profile].deck_usage) do - local deck_won_with = nil - for k, v in pairs(deck.wins) do - deck_won_with = true - _w = math.max(k, _w) - end - if deck_won_with then deck_count = deck_count + 1 end - _w_low = _w_low and (math.min(_w_low, _w)) or _w - end - return _w, ((deck_count >= #G.P_CENTER_POOLS.Back) and _w_low or 0) - end - if G.PROFILES[G.SETTINGS.profile].deck_usage[_deck_key] and - G.PROFILES[G.SETTINGS.profile].deck_usage[_deck_key].wins then - local _w = 0 - for k, v in pairs(G.PROFILES[G.SETTINGS.profile].deck_usage[_deck_key].wins) do - _w = math.max(k, _w) - end - return _w - end - return 0 -end - -function get_deck_win_sticker(_center) - if G.PROFILES[G.SETTINGS.profile].deck_usage[_center.key] and - G.PROFILES[G.SETTINGS.profile].deck_usage[_center.key].wins then - local _w = -1 - for k, v in pairs(G.PROFILES[G.SETTINGS.profile].deck_usage[_center.key].wins) do - _w = math.max(k, _w) - end - if _w > 0 then return G.sticker_map[_w] end - end -end - -function set_deck_loss() - if G.GAME.selected_back and G.GAME.selected_back.effect and G.GAME.selected_back.effect.center and G.GAME.selected_back.effect.center.key then - local deck_key = G.GAME.selected_back.effect.center.key - if not G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] then G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] = {count = 1, order = G.GAME.selected_back.effect.center.order, wins = {}, losses = {}, wins_by_key = {}, losses_by_key = {}} end - if G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] then - G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key].losses[G.GAME.stake] = (G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key].losses[G.GAME.stake] or 0) + 1 - end - G:save_settings() - end -end - -function set_consumeable_usage(card) - if card.config.center_key and card.ability.consumeable then - if G.PROFILES[G.SETTINGS.profile].consumeable_usage[card.config.center_key] then - G.PROFILES[G.SETTINGS.profile].consumeable_usage[card.config.center_key].count = G.PROFILES[G.SETTINGS.profile].consumeable_usage[card.config.center_key].count + 1 - else - G.PROFILES[G.SETTINGS.profile].consumeable_usage[card.config.center_key] = {count = 1, order = card.config.center.order} - end - if G.GAME.consumeable_usage[card.config.center_key] then - G.GAME.consumeable_usage[card.config.center_key].count = G.GAME.consumeable_usage[card.config.center_key].count + 1 - else - G.GAME.consumeable_usage[card.config.center_key] = {count = 1, order = card.config.center.order, set = card.ability.set} - end - G.GAME.consumeable_usage_total = G.GAME.consumeable_usage_total or {tarot = 0, planet = 0, spectral = 0, tarot_planet = 0, all = 0} - if card.config.center.set == 'Tarot' then - G.GAME.consumeable_usage_total.tarot = G.GAME.consumeable_usage_total.tarot + 1 - G.GAME.consumeable_usage_total.tarot_planet = G.GAME.consumeable_usage_total.tarot_planet + 1 - elseif card.config.center.set == 'Planet' then - G.GAME.consumeable_usage_total.planet = G.GAME.consumeable_usage_total.planet + 1 - G.GAME.consumeable_usage_total.tarot_planet = G.GAME.consumeable_usage_total.tarot_planet + 1 - elseif card.config.center.set == 'Spectral' then G.GAME.consumeable_usage_total.spectral = G.GAME.consumeable_usage_total.spectral + 1 - end - - G.GAME.consumeable_usage_total.all = G.GAME.consumeable_usage_total.all + 1 - - if not card.config.center.discovered then - discover_card(card) - end - - if card.config.center.set == 'Tarot' or card.config.center.set == 'Planet' then - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.GAME.last_tarot_planet = card.config.center_key - return true - end - })) - return true - end - })) - end - - end - G:save_settings() -end - -function set_voucher_usage(card) - if card.config.center_key and card.ability.set == 'Voucher' then - if G.PROFILES[G.SETTINGS.profile].voucher_usage[card.config.center_key] then - G.PROFILES[G.SETTINGS.profile].voucher_usage[card.config.center_key].count = G.PROFILES[G.SETTINGS.profile].voucher_usage[card.config.center_key].count + 1 - else - G.PROFILES[G.SETTINGS.profile].voucher_usage[card.config.center_key] = {count = 1, order = card.config.center.order} - end - end - G:save_settings() -end - -function set_hand_usage(hand) - local hand_label = hand - hand = hand:gsub("%s+", "") - if G.PROFILES[G.SETTINGS.profile].hand_usage[hand] then - G.PROFILES[G.SETTINGS.profile].hand_usage[hand].count = G.PROFILES[G.SETTINGS.profile].hand_usage[hand].count + 1 - else - G.PROFILES[G.SETTINGS.profile].hand_usage[hand] = {count = 1, order = hand_label} - end - if G.GAME.hand_usage[hand] then - G.GAME.hand_usage[hand].count = G.GAME.hand_usage[hand].count + 1 - else - G.GAME.hand_usage[hand] = {count = 1, order = hand_label} - end - G:save_settings() -end - -function set_profile_progress() - G.PROGRESS = G.PROGRESS or { - joker_stickers = {tally = 0, of = 0}, - deck_stakes = {tally = 0, of = 0}, - challenges = {tally = 0, of = 0}, - } - for _, v in pairs(G.PROGRESS) do - if type(v) == 'table' then - v.tally = 0 - v.of = 0 - end - end - - for _, v in pairs(G.P_CENTERS) do - if v.set == 'Back' and not v.omit then - G.PROGRESS.deck_stakes.of = G.PROGRESS.deck_stakes.of + #G.P_CENTER_POOLS.Stake - G.PROGRESS.deck_stakes.tally = G.PROGRESS.deck_stakes.tally + get_deck_win_stake(v.key) - end - if v.set == 'Joker' then - G.PROGRESS.joker_stickers.of = G.PROGRESS.joker_stickers.of + #G.P_CENTER_POOLS.Stake - G.PROGRESS.joker_stickers.tally = G.PROGRESS.joker_stickers.tally + get_joker_win_sticker(v, true) - end - end - - for _, v in pairs(G.CHALLENGES) do - G.PROGRESS.challenges.of = G.PROGRESS.challenges.of + 1 - if G.PROFILES[G.SETTINGS.profile].challenge_progress.completed[v.id] then - G.PROGRESS.challenges.tally = G.PROGRESS.challenges.tally + 1 - end - end - - G.PROFILES[G.SETTINGS.profile].progress.joker_stickers = copy_table(G.PROGRESS.joker_stickers) - G.PROFILES[G.SETTINGS.profile].progress.deck_stakes = copy_table(G.PROGRESS.deck_stakes) - G.PROFILES[G.SETTINGS.profile].progress.challenges = copy_table(G.PROGRESS.challenges) -end - -function set_discover_tallies() - G.DISCOVER_TALLIES = G.DISCOVER_TALLIES or { - blinds = {tally = 0, of = 0}, - tags = {tally = 0, of = 0}, - jokers = {tally = 0, of = 0}, - consumeables = {tally = 0, of = 0}, - vouchers = {tally = 0, of = 0}, - boosters = {tally = 0, of = 0}, - editions = {tally = 0, of = 0}, - backs = {tally = 0, of = 0}, - total = {tally = 0, of = 0}, - } - for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do - G.DISCOVER_TALLIES[v:lower()..'s'] = {tally = 0, of = 0} - end for _, v in pairs(G.DISCOVER_TALLIES) do - v.tally = 0 - v.of = 0 - end - - for _, v in pairs(G.P_CENTERS) do - if not v.omit and not v.no_collection then - if v.set and ((v.set == 'Joker') or v.consumeable or (v.set == 'Edition') or (v.set == 'Voucher') or (v.set == 'Back') or (v.set == 'Booster')) then - G.DISCOVER_TALLIES.total.of = G.DISCOVER_TALLIES.total.of+1 - if v.discovered then - G.DISCOVER_TALLIES.total.tally = G.DISCOVER_TALLIES.total.tally+1 - end - end - if v.set and v.set == 'Joker' then - G.DISCOVER_TALLIES.jokers.of = G.DISCOVER_TALLIES.jokers.of+1 - if v.discovered then - G.DISCOVER_TALLIES.jokers.tally = G.DISCOVER_TALLIES.jokers.tally+1 - end - end - if v.set and v.set == 'Back' then - G.DISCOVER_TALLIES.backs.of = G.DISCOVER_TALLIES.backs.of+1 - if v.unlocked then - G.DISCOVER_TALLIES.backs.tally = G.DISCOVER_TALLIES.backs.tally+1 - end - end - if v.set and v.consumeable then - G.DISCOVER_TALLIES.consumeables.of = G.DISCOVER_TALLIES.consumeables.of+1 - if v.discovered then - G.DISCOVER_TALLIES.consumeables.tally = G.DISCOVER_TALLIES.consumeables.tally+1 - end - local tally = G.DISCOVER_TALLIES[v.set:lower()..'s'] - if tally then - tally.of = tally.of + 1 - if v.discovered then - tally.tally = tally.tally + 1 - end - end - end - if v.set and v.set == 'Voucher' then - G.DISCOVER_TALLIES.vouchers.of = G.DISCOVER_TALLIES.vouchers.of+1 - if v.discovered then - G.DISCOVER_TALLIES.vouchers.tally = G.DISCOVER_TALLIES.vouchers.tally+1 - end - end - if v.set and v.set == 'Booster' then - G.DISCOVER_TALLIES.boosters.of = G.DISCOVER_TALLIES.boosters.of+1 - if v.discovered then - G.DISCOVER_TALLIES.boosters.tally = G.DISCOVER_TALLIES.boosters.tally+1 - end - end - if v.set and v.set == 'Edition' then - G.DISCOVER_TALLIES.editions.of = G.DISCOVER_TALLIES.editions.of+1 - if v.discovered then - G.DISCOVER_TALLIES.editions.tally = G.DISCOVER_TALLIES.editions.tally+1 - end - end - end - end - for _, v in pairs(G.P_BLINDS) do - if not v.no_collection then - - G.DISCOVER_TALLIES.total.of = G.DISCOVER_TALLIES.total.of+1 - G.DISCOVER_TALLIES.blinds.of = G.DISCOVER_TALLIES.blinds.of+1 - if v.discovered then - G.DISCOVER_TALLIES.blinds.tally = G.DISCOVER_TALLIES.blinds.tally+1 - G.DISCOVER_TALLIES.total.tally = G.DISCOVER_TALLIES.total.tally+1 - end - end - end - - for _, v in pairs(G.P_TAGS) do - if not v.no_collection then - - G.DISCOVER_TALLIES.total.of = G.DISCOVER_TALLIES.total.of+1 - G.DISCOVER_TALLIES.tags.of = G.DISCOVER_TALLIES.tags.of+1 - if v.discovered then - G.DISCOVER_TALLIES.tags.tally = G.DISCOVER_TALLIES.tags.tally+1 - G.DISCOVER_TALLIES.total.tally = G.DISCOVER_TALLIES.total.tally+1 - end - end - end - - G.PROFILES[G.SETTINGS.profile].high_scores.collection.amt = G.DISCOVER_TALLIES.total.tally - G.PROFILES[G.SETTINGS.profile].high_scores.collection.tot = G.DISCOVER_TALLIES.total.of - G.PROFILES[G.SETTINGS.profile].progress.discovered = copy_table(G.DISCOVER_TALLIES.total) - - if check_for_unlock then check_for_unlock({type = 'discover_amount', - amount = G.DISCOVER_TALLIES.total.tally, - planet_count = G.DISCOVER_TALLIES.planets.tally, - tarot_count = G.DISCOVER_TALLIES.tarots.tally}) - end -end - -function stop_use() - G.GAME.STOP_USE = (G.GAME.STOP_USE or 0) + 1 - dec_stop_use(6) -end - -function dec_stop_use(_depth) - if _depth > 0 then - G.E_MANAGER:add_event(Event({ - blocking = false, - no_delete = true, - func = (function() - dec_stop_use(_depth - 1) - return true end)})) - else - G.E_MANAGER:add_event(Event({ - blocking = false, - no_delete = true, - func = (function() - G.GAME.STOP_USE = math.max(G.GAME.STOP_USE - 1, 0) - return true end)})) - end -end - -function inc_career_stat(stat, mod) - if G.GAME.seeded or G.GAME.challenge then return end - if not G.PROFILES[G.SETTINGS.profile].career_stats[stat] then G.PROFILES[G.SETTINGS.profile].career_stats[stat] = 0 end - G.PROFILES[G.SETTINGS.profile].career_stats[stat] = G.PROFILES[G.SETTINGS.profile].career_stats[stat] + (mod or 0) - G:save_settings() -end - -function recursive_table_cull(t) - local ret_t = {} - for k, v in pairs(t) do - if type(v) == 'table' then - if v.is and v:is(Object) then ret_t[k] = [["]].."MANUAL_REPLACE"..[["]] - else ret_t[k] = recursive_table_cull(v) - end - else ret_t[k] = v end - end - return ret_t -end - -function save_with_action(action) - G.action = action - save_run() - G.action = nil -end - -function cry_prob(owned, den, rigged) - prob = G.GAME and G.GAME.probabilities.normal or 1 - if rigged then - return den - else - return prob*owned - end -end -function save_run() - if G.F_NO_SAVING == true then return end - local cardAreas = {} - for k, v in pairs(G) do - if (type(v) == "table") and v.is and v:is(CardArea) then - local cardAreaSer = v:save() - if cardAreaSer then cardAreas[k] = cardAreaSer end - end - end - - local tags = {} - for k, v in ipairs(G.GAME.tags) do - if (type(v) == "table") and v.is and v:is(Tag) then - local tagSer = v:save() - if tagSer then tags[k] = tagSer end - end - end - - G.culled_table = recursive_table_cull{ - cardAreas = cardAreas, - tags = tags, - GAME = G.GAME, - STATE = G.STATE, - ACTION = G.action or nil, - BLIND = G.GAME.blind:save(), - BACK = G.GAME.selected_back:save(), - VERSION = G.VERSION - } - G.ARGS.save_run = G.culled_table - - G.FILE_HANDLER = G.FILE_HANDLER or {} - G.FILE_HANDLER.run = true - G.FILE_HANDLER.update_queued = true -end - -function remove_save() - love.filesystem.remove(G.SETTINGS.profile..'/save.jkr') - G.SAVED_GAME = nil - G.FILE_HANDLER.run = nil -end - -function loc_colour(_c, _default) - G.ARGS.LOC_COLOURS = G.ARGS.LOC_COLOURS or { - red = G.C.RED, - mult = G.C.MULT, - blue = G.C.BLUE, - chips = G.C.CHIPS, - green = G.C.GREEN, - money = G.C.MONEY, - gold = G.C.GOLD, - attention = G.C.FILTER, - purple = G.C.PURPLE, - white = G.C.WHITE, - inactive = G.C.UI.TEXT_INACTIVE, - spades = G.C.SUITS.Spades, - hearts = G.C.SUITS.Hearts, - clubs = G.C.SUITS.Clubs, - diamonds = G.C.SUITS.Diamonds, - tarot = G.C.SECONDARY_SET.Tarot, - planet = G.C.SECONDARY_SET.Planet, - spectral = G.C.SECONDARY_SET.Spectral, - edition = G.C.EDITION, - dark_edition = G.C.DARK_EDITION, - legendary = G.C.RARITY[4], - enhanced = G.C.SECONDARY_SET.Enhanced - } - for _, v in ipairs(SMODS.Rarity.obj_buffer) do - G.ARGS.LOC_COLOURS[v:lower()] = G.C.RARITY[v] - end - for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do - G.ARGS.LOC_COLOURS[v:lower()] = G.C.SECONDARY_SET[v] - end - for _, v in ipairs(SMODS.Suit.obj_buffer) do - G.ARGS.LOC_COLOURS[v:lower()] = G.C.SUITS[v] - end - return G.ARGS.LOC_COLOURS[_c] or _default or G.C.UI.TEXT_DARK -end - -function init_localization() - G.localization.misc.v_dictionary_parsed = {} - for k, v in pairs(G.localization.misc.v_dictionary) do - if type(v) == 'table' then - G.localization.misc.v_dictionary_parsed[k] = {multi_line = true} - for kk, vv in ipairs(v) do - G.localization.misc.v_dictionary_parsed[k][kk] = loc_parse_string(vv) - end - else - G.localization.misc.v_dictionary_parsed[k] = loc_parse_string(v) - end - end - G.localization.misc.v_text_parsed = {} - for k, v in pairs(G.localization.misc.v_text) do - G.localization.misc.v_text_parsed[k] = {} - for kk, vv in ipairs(v) do - G.localization.misc.v_text_parsed[k][kk] = loc_parse_string(vv) - end - end - G.localization.tutorial_parsed = {} - for k, v in pairs(G.localization.misc.tutorial) do - G.localization.tutorial_parsed[k] = {multi_line = true} - for kk, vv in ipairs(v) do - G.localization.tutorial_parsed[k][kk] = loc_parse_string(vv) - end - end - G.localization.quips_parsed = {} - for k, v in pairs(G.localization.misc.quips or {}) do - G.localization.quips_parsed[k] = {multi_line = true} - for kk, vv in ipairs(v) do - G.localization.quips_parsed[k][kk] = loc_parse_string(vv) - end - end - for g_k, group in pairs(G.localization) do - if g_k == 'descriptions' then - for _, set in pairs(group) do - for _, center in pairs(set) do - center.text_parsed = {} - if not center.text then else - for _, line in ipairs(center.text) do - center.text_parsed[#center.text_parsed+1] = loc_parse_string(line) - end - center.name_parsed = {} - for _, line in ipairs(type(center.name) == 'table' and center.name or {center.name}) do - center.name_parsed[#center.name_parsed+1] = loc_parse_string(line) - end - if center.unlock then - center.unlock_parsed = {} - for _, line in ipairs(center.unlock) do - center.unlock_parsed[#center.unlock_parsed+1] = loc_parse_string(line) - end - end - end - end - end - end - end -end - -function playing_card_joker_effects(cards) - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({playing_card_added = true, cards = cards}) - end -end - -function convert_save_to_meta() - if love.filesystem.getInfo(G.SETTINGS.profile..'/'..'unlocked_jokers.jkr') then - local _meta = { - unlocked = {}, - alerted = {}, - discovered = {} - } - if love.filesystem.getInfo(G.SETTINGS.profile..'/'..'unlocked_jokers.jkr') then - for line in string.gmatch( (get_compressed(G.SETTINGS.profile..'/'..'unlocked_jokers.jkr') or '').. "\n", "([^\n]*)\n") do - local key = line:gsub("%s+", "") - if key and (key ~= '') then - _meta.unlocked[key] = true - end - end - end - if love.filesystem.getInfo(G.SETTINGS.profile..'/'..'discovered_jokers.jkr') then - for line in string.gmatch( (get_compressed(G.SETTINGS.profile..'/'..'discovered_jokers.jkr') or '').. "\n", "([^\n]*)\n") do - local key = line:gsub("%s+", "") - if key and (key ~= '') then - _meta.discovered[key] = true - end - end - end - if love.filesystem.getInfo(G.SETTINGS.profile..'/'..'alerted_jokers.jkr') then - for line in string.gmatch( (get_compressed(G.SETTINGS.profile..'/'..'alerted_jokers.jkr') or '').. "\n", "([^\n]*)\n") do - local key = line:gsub("%s+", "") - if key and (key ~= '') then - _meta.alerted[key] = true - end - end - end - love.filesystem.remove(G.SETTINGS.profile..'/'..'unlocked_jokers.jkr') - love.filesystem.remove(G.SETTINGS.profile..'/'..'discovered_jokers.jkr') - love.filesystem.remove(G.SETTINGS.profile..'/'..'alerted_jokers.jkr') - - compress_and_save( G.SETTINGS.profile..'/'..'meta.jkr', STR_PACK(_meta)) - end -end - -function card_from_control(control) - G.playing_card = (G.playing_card and G.playing_card + 1) or 1 - local _card = Card(G.deck.T.x, G.deck.T.y, G.CARD_W, G.CARD_H, G.P_CARDS[control.s..'_'..control.r], G.P_CENTERS[control.e or 'c_base'], {playing_card = G.playing_card}) - if control.d then _card:set_edition({[control.d] = true}, true, true) end - if control.g then _card:set_seal(control.g, true, true) end - G.deck:emplace(_card) - table.insert(G.playing_cards, _card) -end - -function loc_parse_string(line) - local parsed_line = {} - local control = {} - local _c, _c_name, _c_val, _c_gather = nil, nil, nil, nil - local _s_gather, _s_ref = nil, nil - local str_parts, str_it = {}, 1 - for i = 1, #line do - local char = line:sub(i,i) - if char == '{' then --Start of a control section, extract all controls - if str_parts[1] then parsed_line[#parsed_line+1] = {strings = str_parts, control = control or {}} end - str_parts, str_it = {}, 1 - control, _c, _c_name, _c_val, _c_gather = {}, nil, nil, nil, nil - _s_gather, _s_ref = nil, nil - _c = true - elseif _c and not (char == ':' or char == '}') and not _c_gather then _c_name = (_c_name or '')..char - elseif _c and char == ':' then _c_gather = true - elseif _c and not (char == ',' or char == '}') and _c_gather then _c_val = (_c_val or '')..char - elseif _c and (char == ',' or char == '}') then _c_gather = nil; if _c_name then control[_c_name] = _c_val end; _c_name = nil; _c_val = nil; if char == '}' then _c = nil end - - elseif not _c and char ~= '#' and not _s_gather then str_parts[str_it] = (str_parts[str_it] or '')..(control['X'] and char:gsub("%s+", "") or char) - elseif not _c and char == '#' and not _s_gather then _s_gather = true; if str_parts[str_it] then str_it = str_it + 1 end - elseif not _c and char == '#' and _s_gather then _s_gather = nil; if _s_ref then str_parts[str_it] = {_s_ref}; str_it = str_it + 1; _s_ref = nil end - elseif not _c and _s_gather then _s_ref = (_s_ref or '')..char - end - if i == #line then - if str_parts[1] then parsed_line[#parsed_line+1] = {strings = str_parts, control = control or {}} end - return parsed_line - end - end -end - ---UTF8 handler for special characters, from https://github.com/blitmap/lua-utf8-simple -utf8 = {pattern = '[%z\1-\127\194-\244][\128-\191]*'} -utf8.map = - function (s, f, no_subs) - local i = 0 - - if no_subs then - for b, e in s:gmatch('()' .. utf8.pattern .. '()') do - i = i + 1 - local c = e - b - f(i, c, b) - end - else - for b, c in s:gmatch('()(' .. utf8.pattern .. ')') do - i = i + 1 - f(i, c, b) - end - end - end -utf8.chars = - function (s, no_subs) - return coroutine.wrap(function () return utf8.map(s, coroutine.yield, no_subs) end) - end - -function localize(args, misc_cat) -if args and args.vars then - local reset = {} - for i, j in pairs(args.vars) do - if type(j) == 'table' then - if (j.new and type(j.new) == "function") and ((j.m and j.e) or (j.array and j.sign and (type(j.array) == "table"))) then - reset[i] = number_format(j) - end - end - end - for i, j in pairs(reset) do - args.vars[i] = j - end -end - if args and not (type(args) == 'table') then - if misc_cat and G.localization.misc[misc_cat] then return G.localization.misc[misc_cat][args] or 'ERROR' end - return G.localization.misc.dictionary[args] or 'ERROR' - end - - local loc_target = nil - local ret_string = nil - if args.type == 'other' then - loc_target = G.localization.descriptions.Other[args.key] - elseif args.type == 'descriptions' or args.type == 'unlocks' then - loc_target = G.localization.descriptions[args.set][args.key] - elseif args.type == 'tutorial' then - loc_target = G.localization.tutorial_parsed[args.key] - elseif args.type == 'quips' then - loc_target = G.localization.quips_parsed[args.key] - elseif args.type == 'raw_descriptions' then - loc_target = G.localization.descriptions[args.set][args.key] - local multi_line = {} - if loc_target then - for _, lines in ipairs(args.type == 'unlocks' and loc_target.unlock_parsed or args.type == 'name' and loc_target.name_parsed or args.type == 'text' and loc_target or loc_target.text_parsed) do - local final_line = '' - for _, part in ipairs(lines) do - local assembled_string = '' - for _, subpart in ipairs(part.strings) do - assembled_string = assembled_string..(type(subpart) == 'string' and subpart or format_ui_value(args.vars[tonumber(subpart[1])]) or 'ERROR') - end - final_line = final_line..assembled_string - end - multi_line[#multi_line+1] = final_line - end - end - return multi_line - elseif args.type == 'text' then - loc_target = G.localization.misc.v_text_parsed[args.key] - elseif args.type == 'variable' then - loc_target = G.localization.misc.v_dictionary_parsed[args.key] - if not loc_target then return 'ERROR' end - if loc_target.multi_line then - local assembled_strings = {} - for k, v in ipairs(loc_target) do - local assembled_string = '' - for _, subpart in ipairs(v[1].strings) do - assembled_string = assembled_string..(type(subpart) == 'string' and subpart or format_ui_value(args.vars[tonumber(subpart[1])])) - end - assembled_strings[k] = assembled_string - end - return assembled_strings or {'ERROR'} - else - local assembled_string = '' - for _, subpart in ipairs(loc_target[1].strings) do - assembled_string = assembled_string..(type(subpart) == 'string' and subpart or format_ui_value(args.vars[tonumber(subpart[1])])) - end - ret_string = assembled_string or 'ERROR' - end - elseif args.type == 'name_text' then - if pcall(function() ret_string = G.localization.descriptions[(args.set or args.node.config.center.set)][args.key or args.node.config.center.key].name end) then - else ret_string = "ERROR" end - elseif args.type == 'name' then - loc_target = G.localization.descriptions[(args.set or args.node.config.center.set)][args.key or args.node.config.center.key] - end - - if ret_string then return ret_string end - - if loc_target then - for _, lines in ipairs(args.type == 'unlocks' and loc_target.unlock_parsed or args.type == 'name' and loc_target.name_parsed or (args.type == 'text' or args.type == 'tutorial' or args.type == 'quips') and loc_target or loc_target.text_parsed) do - local final_line = {} - for _, part in ipairs(lines) do - local assembled_string = '' - for _, subpart in ipairs(part.strings) do - assembled_string = assembled_string..(type(subpart) == 'string' and subpart or format_ui_value(args.vars[tonumber(subpart[1])]) or 'ERROR') - end - local desc_scale = G.LANG.font.DESCSCALE - if G.F_MOBILE_UI then desc_scale = desc_scale*1.5 end - if args.type == 'name' then - final_line[#final_line+1] = {n=G.UIT.O, config={ - object = DynaText({string = {assembled_string}, - colours = {(part.control.V and args.vars.colours[tonumber(part.control.V)]) or (part.control.C and loc_colour(part.control.C)) or args.text_colour or G.C.UI.TEXT_LIGHT}, - bump = true, - silent = true, - pop_in = 0, - pop_in_rate = 4, - maxw = 5, - shadow = true, - y_offset = -0.6, - spacing = math.max(0, 0.32*(17 - #assembled_string)), - scale = (0.55 - 0.004*#assembled_string)*(part.control.s and tonumber(part.control.s) or args.scale or 1) - }) - }} - elseif part.control.E then - local _float, _silent, _pop_in, _bump, _spacing = nil, true, nil, nil, nil - if part.control.E == '1' then - _float = true; _silent = true; _pop_in = 0 - elseif part.control.E == '2' then - _bump = true; _spacing = 1 - end - final_line[#final_line+1] = {n=G.UIT.O, config={ - object = DynaText({string = {assembled_string}, colours = {part.control.V and args.vars.colours[tonumber(part.control.V)] or loc_colour(part.control.C or nil)}, - float = _float, - silent = _silent, - pop_in = _pop_in, - bump = _bump, - spacing = _spacing, - scale = 0.32*(part.control.s and tonumber(part.control.s) or args.scale or 1)*desc_scale}) - }} - elseif part.control.X then - final_line[#final_line+1] = {n=G.UIT.C, config={align = "m", colour = loc_colour(part.control.X), r = 0.05, padding = 0.03, res = 0.15}, nodes={ - {n=G.UIT.T, config={ - text = assembled_string, - colour = loc_colour(part.control.C or nil), - scale = 0.32*(part.control.s and tonumber(part.control.s) or args.scale or 1)*desc_scale}}, - }} - else - final_line[#final_line+1] = {n=G.UIT.T, config={ - detailed_tooltip = part.control.T and (G.P_CENTERS[part.control.T] or G.P_TAGS[part.control.T]) or nil, - text = assembled_string, - shadow = args.shadow, - colour = part.control.V and args.vars.colours[tonumber(part.control.V)] or not part.control.C and args.text_colour or loc_colour(part.control.C or nil, args.default_col), - scale = 0.32*(part.control.s and tonumber(part.control.s) or args.scale or 1)*desc_scale},} - end - end - if args.type == 'name' or args.type == 'text' then return final_line end - args.nodes[#args.nodes+1] = final_line - end - end -end - -function get_stake_sprite(_stake, _scale) - _stake = _stake or 1 - _scale = _scale or 1 - local stake_sprite = Sprite(0,0,_scale*1,_scale*1,G.ASSET_ATLAS[G.P_CENTER_POOLS.Stake[_stake].atlas], G.P_CENTER_POOLS.Stake[_stake].pos) - stake_sprite.states.drag.can = false - if G.P_CENTER_POOLS['Stake'][_stake].shiny then - stake_sprite.draw = function(_sprite) - _sprite.ARGS.send_to_shader = _sprite.ARGS.send_to_shader or {} - _sprite.ARGS.send_to_shader[1] = math.min(_sprite.VT.r*3, 1) + G.TIMERS.REAL/(18) + (_sprite.juice and _sprite.juice.r*20 or 0) + 1 - _sprite.ARGS.send_to_shader[2] = G.TIMERS.REAL - - Sprite.draw_shader(_sprite, 'dissolve') - Sprite.draw_shader(_sprite, 'voucher', nil, _sprite.ARGS.send_to_shader) - end - end - return stake_sprite -end - -function get_front_spriteinfo(_front) - if _front and _front.suit and G.SETTINGS.CUSTOM_DECK and G.SETTINGS.CUSTOM_DECK.Collabs then - local collab = G.SETTINGS.CUSTOM_DECK.Collabs[_front.suit] - if collab and collab ~= 'default' then - local deckSkin = SMODS.DeckSkins[collab] - if deckSkin then - local hasRank = false - for i = 1, #deckSkin.ranks do - if deckSkin.ranks[i] == _front.value then hasRank = true break end - end - if hasRank then - local atlas = G.ASSET_ATLAS[G.SETTINGS.colourblind_option and deckSkin.hc_atlas or deckSkin.lc_atlas] - if atlas then - if deckSkin.posStyle == 'collab' then - return atlas, G.COLLABS.pos[_front.value] - elseif deckSkin.posStyle == 'suit' then - return atlas, { x = _front.pos.x, y = 0} - elseif deckSkin.posStyle == 'deck' then - return atlas, _front.pos - end - end - end - end - end -end - - return G.ASSET_ATLAS[G.SETTINGS.colourblind_option and _front.hc_atlas or _front.lc_atlas or {}] or G.ASSET_ATLAS[_front.atlas] or G.ASSET_ATLAS["cards_"..(G.SETTINGS.colourblind_option and 2 or 1)], _front.pos -end - -function get_stake_col(_stake) - G.C.STAKES = G.C.STAKES or { - G.C.WHITE, - G.C.RED, - G.C.GREEN, - G.C.BLACK, - G.C.BLUE, - G.C.PURPLE, - G.C.ORANGE, - G.C.GOLD - } - return G.C.STAKES[_stake] -end - -function get_challenge_int_from_id(_id) - for k, v in pairs(G.CHALLENGES) do - if v.id == _id then return k end - end - return 0 -end - -function get_starting_params() -return { - dollars = 4, - hand_size = 8, - discards = 3, - hands = 4, - reroll_cost = 5, - joker_slots = 5, - ante_scaling = 1, - consumable_slots = 2, - no_faces = false, - erratic_suits_and_ranks = false, - } -end - -function get_challenge_rule(_challenge, _type, _id) - if _challenge and _challenge.rules and _challenge.rules[_type] then - for k, v in ipairs(_challenge.rules[_type]) do - if _id == v.id then return v.value end - end - end -end - ---SOUND -function PLAY_SOUND(args) - args.per = args.per or 1 - args.vol = args.vol or 1 - SOURCES[args.sound_code] = SOURCES[args.sound_code] or {} - - local should_stream = (string.find(args.sound_code,'music') or string.find(args.sound_code,'ambient')) - local s = {sound = love.audio.newSource("resources/sounds/"..args.sound_code..'.ogg', should_stream and "stream" or 'static')} - table.insert(SOURCES[args.sound_code], s) - s.sound_code = args.sound_code - s.original_pitch = args.per or 1 - s.original_volume = args.vol or 1 - s.created_on_pause = (args.overlay_menu and true or false) - s.created_on_state = args.state - s.sfx_handled = 0 - s.transition_timer = 0 - SET_SFX(s, args) - love.audio.play(s.sound) - return s -end - -function STOP_AUDIO() - for _, source in pairs(SOURCES) do - for _, s in pairs(source) do - if s.sound:isPlaying() then - s.sound:stop() - end - end - end -end - -function SET_SFX(s, args) - if string.find(s.sound_code,'music') then - if s.sound_code == args.desired_track then - s.current_volume = s.current_volume or 1 - s.current_volume = 1*(args.dt*3) + (1-(args.dt*3))*s.current_volume - else - s.current_volume = s.current_volume or 0 - s.current_volume = 0*(args.dt*3) + (1-(args.dt*3))*s.current_volume - end - s.sound:setVolume(s.current_volume*s.original_volume*(args.sound_settings.volume/100.0)*(args.sound_settings.music_volume/100.0)) - s.sound:setPitch(s.original_pitch*args.pitch_mod) - else - if s.temp_pitch ~= s.original_pitch then - s.sound:setPitch(s.original_pitch) - s.temp_pitch = s.original_pitch - end - local sound_vol = s.original_volume*(args.sound_settings.volume/100.0)*(args.sound_settings.game_sounds_volume/100.0) - if s.created_on_state == 13 then sound_vol = sound_vol*args.splash_vol end - if sound_vol <= 0 then - s.sound:stop() - else - s.sound:setVolume(sound_vol) - end - end -end - -function MODULATE(args) - for k, v in pairs(SOURCES) do - if (string.find(k,'music') and (args.desired_track ~= '')) then - if v[1] and v[1].sound and v[1].sound:isPlaying() then - else - RESTART_MUSIC(args) - break; - end - end - end - - for k, v in pairs(SOURCES) do - local i=1 - while i <= #v do - if not v[i].sound:isPlaying() then - table.remove(v, i) - else - i = i + 1 - end - end - - for i, s in ipairs(v) do - if s.sound and s.sound:isPlaying() and s.original_volume then - SET_SFX(s, args) - end - end - end -end - -function RESTART_MUSIC(args) - for k, v in pairs(SOURCES) do - if string.find(k,'music') then - for i, s in ipairs(v) do - s.sound:stop() - end - SOURCES[k] = {} - args.per = 0.7 - args.vol = 0.6 - args.sound_code = k - local s = PLAY_SOUND(args) - s.initialized = true - end - end -end - -function AMBIENT(args) - for k, v in pairs(SOURCES) do - if args.ambient_control[k] then - local start_ambient = args.ambient_control[k].vol > 0 - - for i, s in ipairs(v) do - if s.sound and s.sound:isPlaying() and s.original_volume then - s.original_volume = args.ambient_control[k].vol - SET_SFX(s, args) - start_ambient = false - end - end - - if start_ambient then - args.sound_code = k - args.vol = args.ambient_control[k].vol - args.per = args.ambient_control[k].per - PLAY_SOUND(args) - end - end - end -end - -function RESET_STATES(state) - for k, v in pairs(SOURCES) do - for i, s in ipairs(v) do - s.created_on_state = state - end - end -end diff --git a/lovely/dump/functions/state_events.lua b/lovely/dump/functions/state_events.lua deleted file mode 100644 index 1897130..0000000 --- a/lovely/dump/functions/state_events.lua +++ /dev/null @@ -1,2521 +0,0 @@ -LOVELY_INTEGRITY = 'cafd95906db3619524c557a8c0e342367b9d6be2cb63f6f88e533f34308391bc' - -function win_game() - if not G.GAME.seeded and not G.GAME.challenge then - set_joker_win() - set_deck_win() - - check_and_set_high_score('win_streak', G.PROFILES[G.SETTINGS.profile].high_scores.current_streak.amt+1) - check_and_set_high_score('current_streak', G.PROFILES[G.SETTINGS.profile].high_scores.current_streak.amt+1) - check_for_unlock({type = 'win_no_hand'}) - check_for_unlock({type = 'win_no'}) - check_for_unlock({type = 'win_custom'}) - check_for_unlock({type = 'win_deck'}) - check_for_unlock({type = 'win_stake'}) - check_for_unlock({type = 'win'}) - check_for_unlock({type = 'cry_win_with_hand', hand = G.GAME.last_hand_played}) - inc_career_stat('c_wins', 1) - end - - set_profile_progress() - - if G.GAME.challenge then - G.PROFILES[G.SETTINGS.profile].challenge_progress.completed[G.GAME.challenge] = true - set_challenge_unlock() - check_for_unlock({type = 'win_challenge'}) - G:save_settings() - end - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - for k, v in pairs(G.I.CARD) do - v.sticker_run = nil - end - - play_sound('win') - G.SETTINGS.paused = true - - G.FUNCS.overlay_menu{ - definition = create_UIBox_win(), - config = {no_esc = true} - } - local Jimbo = nil - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 2.5, - blocking = false, - func = (function() - if G.OVERLAY_MENU and G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') then - Jimbo = Card_Character({x = 0, y = 5}) - local spot = G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') - spot.config.object:remove() - spot.config.object = Jimbo - Jimbo.ui_object_updated = true - Jimbo:add_speech_bubble('wq_'..math.random(1,7), nil, {quip = true}) - Jimbo:say_stuff(5) - if G.F_JAN_CTA then - G.E_MANAGER:add_event(Event({ - func = function() - Jimbo:add_button(localize('b_wishlist'), 'wishlist_steam', G.C.DARK_EDITION, nil, true, 1.6) - return true - end})) - end - end - return true - end) - })) - - return true - end) - })) - - if not G.GAME.seeded and not G.GAME.challenge then - G.PROFILES[G.SETTINGS.profile].stake = math.max(G.PROFILES[G.SETTINGS.profile].stake or 1, (G.GAME.stake or 1)+1) - end - G:save_progress() - G.FILE_HANDLER.force = true - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - if not G.SETTINGS.paused then - G.GAME.current_round.round_text = 'Endless Round ' - return true - end - end) - })) -end - -function end_round() -G.GAME.cry_exploit_override = nil - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.2, - func = function() - G.GAME.blind.in_blind = false - local game_over = true - local game_won = false - G.RESET_BLIND_STATES = true - G.RESET_JIGGLES = true - if G.GAME.current_round.semicolon then - game_over = false - end - if to_big(G.GAME.chips) >= to_big(G.GAME.blind.chips) then - game_over = false - end - for i = 1, #G.playing_cards do - local CARD = G.playing_cards[i] - CARD.cry_debuff_immune = false - end - for i = 1, #G.jokers.cards do - local eval = nil - eval = G.jokers.cards[i]:calculate_joker({end_of_round = true, game_over = game_over, callback = function(card, eval) - if eval then - if eval.saved then - game_over = false - end - card_eval_status_text(card, 'jokers', nil, nil, nil, eval) - end - end}) - - G.jokers.cards[i]:calculate_rental() - G.jokers.cards[i]:calculate_perishable() - end - G.GAME.selected_back:trigger_effect({context = 'end_of_round', game_over = game_over}) - if G.GAME.voucher_sticker_index then - if G.GAME.voucher_sticker_index.perishable then - for k, v in pairs(G.GAME.voucher_sticker_index.perishable) do - if v > 1 then - G.GAME.voucher_sticker_index.perishable[k] = v - 1 - end - if v == 1 then - G.GAME.voucher_sticker_index.perishable[k] = v - 1 - for kk, vv in pairs(G.P_CENTERS) do - if k == vv.name then - cry_debuff_voucher(kk) - G.GAME.used_vouchers.vv = nil - G.GAME.used_vouchers[kk] = nil - break - end - end - end - end - end - if G.GAME.voucher_sticker_index.rental then - local cumulative_rental = 0 - for k, v in pairs(G.GAME.voucher_sticker_index.rental) do - cumulative_rental = cumulative_rental + G.GAME.cry_voucher_rental_rate - end - if cumulative_rental > 0 then - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - blocking = false, - blockable = false, - func = (function() - ease_dollars(-cumulative_rental) - return true - end)})) - end - end - if G.GAME.voucher_sticker_index.banana then -- i'm pretty sure unredeem breaks if spectrals are disabled? unsure though - local voucher_queue = {} - local current_round_voucher=G.GAME.current_round.voucher - for k, v in pairs(G.GAME.voucher_sticker_index.banana) do - if (pseudorandom('byebyevoucher') < G.GAME.probabilities.normal/G.GAME.cry_voucher_banana_odds) then - area = G.play - local unredeemed_voucher = '' - for kk, vv in pairs(G.P_CENTERS) do - if k == vv.name then - unredeemed_voucher = kk - break - end - end - local card = create_card('Voucher', area, nil, nil, nil, nil, unredeemed_voucher) - if G.GAME.voucher_edition_index[card.ability.name] then -- i made this bullshit a function - local edition = cry_edition_to_table(G.GAME.voucher_edition_index[card.ability.name]) - if edition then - card:set_edition(edition, true, true) - end - end - if G.GAME.voucher_sticker_index.eternal[card.ability.name] then - card:set_eternal(true) - card.ability.eternal = true - end - if G.GAME.voucher_sticker_index.perishable[card.ability.name] then - card:set_perishable(true) - card.ability.perish_tally = G.GAME.voucher_sticker_index.perishable[card.ability.name] - card.ability.perishable = true - if G.GAME.voucher_sticker_index.perishable[card.ability.name] == 0 then - card.debuff = true - end - end - if G.GAME.voucher_sticker_index.rental[card.ability.name] then - card:set_rental(true) - card.ability.rental = true - end - if G.GAME.voucher_sticker_index.pinned[card.ability.name] then - card.pinned = true - end - if G.GAME.voucher_sticker_index.banana[card.ability.name] then - card.ability.banana = true - end - card:start_materialize() - area:emplace(card) - card.cost=0 - card.shop_voucher=false - voucher_queue[#voucher_queue+1] = card - end - end - for k, v in pairs(voucher_queue) do - v:unredeem() - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0, - func = function() - v:start_dissolve() - return true - end})) - end - G.GAME.current_round.voucher=current_round_voucher - end - end - local i = 1 - while i <= #G.jokers.cards do - local gone = G.jokers.cards[i]:calculate_banana() - if not gone then i = i + 1 end - end - i = 1 - while i <= #G.consumeables.cards do - G.consumeables.cards[i]:cry_calculate_consumeable_rental() - G.consumeables.cards[i]:cry_calculate_consumeable_perishable() - local gone = nil - if not gone then i = i + 1 end - end - if G.GAME.round_resets.ante >= G.GAME.win_ante and G.GAME.blind_on_deck == 'Boss' then - game_won = true - G.GAME.won = true - end - if game_over then - G.STATE = G.STATES.GAME_OVER - if not G.GAME.won and not G.GAME.seeded and not G.GAME.challenge then - G.PROFILES[G.SETTINGS.profile].high_scores.current_streak.amt = 0 - end - G:save_settings() - G.FILE_HANDLER.force = true - G.STATE_COMPLETE = false - else - G.GAME.unused_discards = (G.GAME.unused_discards or 0) + G.GAME.current_round.discards_left - if G.GAME.blind and G.GAME.blind.config.blind then - discover_card(G.GAME.blind.config.blind) - end - - if G.GAME.blind_on_deck == 'Boss' then - local _handname, _played, _order = 'High Card', -1, 100 - for k, v in pairs(G.GAME.hands) do - if v.played > _played or (v.played == _played and _order > v.order) then - _played = v.played - _handname = k - end - end - G.GAME.current_round.most_played_poker_hand = _handname - end - - if G.GAME.blind:get_type() == 'Boss' and not G.GAME.seeded and not G.GAME.challenge then - G.GAME.current_boss_streak = G.GAME.current_boss_streak + 1 - check_and_set_high_score('boss_streak', G.GAME.current_boss_streak) - end - - if G.GAME.current_round.hands_played == 1 then - inc_career_stat('c_single_hand_round_streak', 1) - else - if not G.GAME.seeded and not G.GAME.challenge then - G.PROFILES[G.SETTINGS.profile].career_stats.c_single_hand_round_streak = 0 - G:save_settings() - end - end - - check_for_unlock({type = 'round_win'}) - set_joker_usage() - if game_won and not G.GAME.win_notified then - G.GAME.win_notified = true - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - blocking = false, - blockable = false, - func = (function() - if G.STATE == G.STATES.ROUND_EVAL then - win_game() - G.GAME.won = true - return true - end - end) - })) - end - if scoring_hand then - local unscoring_hand = {} - for i = 1, #G.play.cards do - local is_scoring = false - for j = 1, #scoring_hand do - if G.play.cards[i] == scoring_hand[j] then - is_scoring = true - end - end - if not is_scoring then - unscoring_hand[#unscoring_hand+1] = G.play.cards[i] - end - end - for i = 1, #unscoring_hand do - unscoring_hand[i]:calculate_seal{unscoring = true} - end - end - for i=1, #G.hand.cards do - --Check for hand doubling - local reps = {1} - local j = 1 - while j <= #reps do - local percent = (i-0.999)/(#G.hand.cards-0.998) + (j-1)*0.1 - if reps[j] ~= 1 then card_eval_status_text((reps[j].jokers or reps[j].seals).card, 'jokers', nil, nil, nil, (reps[j].jokers or reps[j].seals)) end - - --calculate the hand effects - local effects = {G.hand.cards[i]:get_end_of_round_effect()} - G.hand.cards[i]:calculate_rental() - G.hand.cards[i]:calculate_perishable() - local extra_enhancements = SMODS.get_enhancements(G.hand.cards[i], true) - local old_ability = copy_table(G.hand.cards[i].ability) - local old_center = G.hand.cards[i].config.center - local old_center_key = G.hand.cards[i].config.center_key - for k, _ in pairs(extra_enhancements) do - if G.P_CENTERS[k] then - G.hand.cards[i]:set_ability(G.P_CENTERS[k]) - G.hand.cards[i].ability.extra_enhancement = k - effects[#effects+1] = G.hand.cards[i]:get_end_of_round_effect() - end - end - G.hand.cards[i].ability = old_ability - G.hand.cards[i].config.center = old_center - G.hand.cards[i].config.center_key = old_center_key - G.hand.cards[i]:set_sprites(old_center) - for k=1, #G.jokers.cards do - --calculate the joker individual card effects - local eval = G.jokers.cards[k]:calculate_joker({cardarea = G.hand, other_card = G.hand.cards[i], individual = true, end_of_round = true, callback = function(card, eval, retrigger) - if eval then - table.insert(effects, eval) -effects[#effects].from_retrigger = retrigger -end end, no_retrigger_anim = true}) - - end - - if reps[j] == 1 then - --Check for hand doubling - --From Red seal - local eval = eval_card(G.hand.cards[i], {end_of_round = true,cardarea = G.hand, repetition = true, repetition_only = true}) - if next(eval) and (next(effects[1]) or #effects > 1) then - for h = 1, eval.seals.repetitions do - reps[#reps+1] = eval - end - end - - --from Jokers - for j=1, #G.jokers.cards do - --calculate the joker effects - local eval = eval_card(G.jokers.cards[j], {cardarea = G.hand, other_card = G.hand.cards[i], repetition = true, end_of_round = true, card_effects = effects, callback = function(card, ret) eval = {jokers = ret} - if next(eval) then - for h = 1, eval.jokers.repetitions do - reps[#reps+1] = eval - end - end end}) - end - end - - for ii = 1, #effects do - --if this effect came from a joker - if effects[ii].card and not Talisman.config_file.disable_anims then - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() effects[ii].card:juice_up(0.7);return true end) - })) - end - - --If dollars - if effects[ii].h_dollars then - ease_dollars(effects[ii].h_dollars) - card_eval_status_text(G.hand.cards[i], 'dollars', effects[ii].h_dollars, percent) - end - - --Any extras - if effects[ii].extra then - card_eval_status_text(G.hand.cards[i], 'extra', nil, percent, nil, effects[ii].extra) - end - end - j = j + 1 - end - end - delay(0.3) - - - local i = 1 - while i <= #G.hand.cards do - local gone = G.hand.cards[i]:calculate_banana() - if not gone then i = i + 1 end - end - for i = 1, #G.discard.cards do - G.discard.cards[i]:calculate_perishable() - end - i = 1 - while i <= #G.deck.cards do - G.deck.cards[i]:calculate_perishable() - local gone = G.deck.cards[i]:calculate_banana() - if not gone then i = i + 1 end - end - if G.GAME.used_vouchers.v_cry_double_down then - local function update_dbl(area) - for i = 1, #area.cards do - if area.cards[i].dbl_side then - --tweak to do deck effects with on the flip side - cry_misprintize(area.cards[i].dbl_side, {min = 1.5, max = 1.5}, nil, true) - card_eval_status_text(area.cards[i], "extra", nil, nil, nil, { message = localize("k_upgrade_ex") }) - end - end - end - update_dbl(G.jokers) - update_dbl(G.consumeables) - update_dbl(G.hand) - update_dbl(G.discard) - update_dbl(G.deck) - end - G.FUNCS.draw_from_hand_to_discard() - if G.GAME.blind_on_deck == 'Boss' then - G.GAME.voucher_restock = nil - if G.GAME.modifiers.set_eternal_ante and (G.GAME.round_resets.ante == G.GAME.modifiers.set_eternal_ante) then - for k, v in ipairs(G.jokers.cards) do - v:set_eternal(true) - end - end - if G.GAME.modifiers.set_joker_slots_ante and (G.GAME.round_resets.ante == G.GAME.modifiers.set_joker_slots_ante) then - G.jokers.config.card_limit = 0 - end - delay(0.4); ease_ante(G.GAME.blind and G.GAME.blind:cry_calc_ante_gain() or 1); cry_apply_ante_tax(); delay(0.4); check_for_unlock({type = 'ante_up', ante = G.GAME.round_resets.ante + 1}) - end - G.FUNCS.draw_from_discard_to_deck() - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.3, - func = function() - G.STATE = G.STATES.ROUND_EVAL - G.STATE_COMPLETE = false - - if G.GAME.blind_on_deck == 'Small' then - G.GAME.round_resets.blind_states.Small = 'Defeated' - elseif G.GAME.blind_on_deck == 'Big' then - G.GAME.round_resets.blind_states.Big = 'Defeated' - else - if G.GAME.current_round.cry_voucher_stickers.pinned == false then - if not G.GAME.modifiers.cry_no_vouchers then - if not G.GAME.modifiers.cry_voucher_restock_antes or G.GAME.round_resets.ante % G.GAME.modifiers.cry_voucher_restock_antes == 0 then - G.GAME.current_round.voucher = get_next_voucher_key() - G.GAME.current_round.cry_bonusvouchers = {} - G.GAME.cry_bonusvouchersused = {} -- i'm not sure why i'm putting these in two separate tables but it doesn't matter much - for i = 1, G.GAME.cry_bonusvouchercount do - G.GAME.current_round.cry_bonusvouchers[i] = get_next_voucher_key() - end - end - else - very_fair_quip = pseudorandom_element(G.localization.misc.very_fair_quips, pseudoseed("cry_very_fair")) - end - G.GAME.current_round.cry_voucher_edition = cry_get_next_voucher_edition() - G.GAME.current_round.cry_voucher_stickers = cry_get_next_voucher_stickers() - end - G.GAME.round_resets.blind_states.Boss = 'Defeated' - for k, v in ipairs(G.playing_cards) do - v.ability.played_this_ante = nil - end - end - - if G.GAME.round_resets.temp_handsize then G.hand:change_size(-G.GAME.round_resets.temp_handsize); G.GAME.round_resets.temp_handsize = nil end - if G.GAME.round_resets.temp_reroll_cost then G.GAME.round_resets.temp_reroll_cost = nil; calculate_reroll_cost(true) end - for _, v in pairs(find_joker("cry-loopy")) do - if v.ability.extra.retrigger ~= 0 then - v.ability.extra.retrigger = 0 - card_eval_status_text(v, 'extra', nil, nil, nil, {message = localize("k_reset"), colour = G.C.GREEN}) - end - end - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({end_of_round2 = true}) - end - - reset_idol_card() - reset_mail_rank() - reset_ancient_card() - reset_castle_card() for _, mod in ipairs(SMODS.mod_list) do - if mod.reset_game_globals and type(mod.reset_game_globals) == 'function' then - mod.reset_game_globals(false) - end - end - for k, v in ipairs(G.playing_cards) do - v.ability.discarded = nil - v.ability.forced_selection = nil - end - return true - end - })) - end - return true - end - })) - end - -function new_round() - G.RESET_JIGGLES = nil - delay(0.4) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.GAME.current_round.discards_left = math.max(0, G.GAME.round_resets.discards + G.GAME.round_bonus.discards) - G.GAME.current_round.hands_left = (math.max(1, G.GAME.round_resets.hands + G.GAME.round_bonus.next_hands)) - G.GAME.current_round.hands_played = 0 - G.GAME.current_round.discards_used = 0 - G.GAME.current_round.reroll_cost_increase = 0 - G.GAME.current_round.used_packs = {} - - for k, v in pairs(G.GAME.hands) do - v.played_this_round = 0 - end - - for k, v in pairs(G.playing_cards) do - v.ability.wheel_flipped = nil - end - - local chaos = find_joker('Chaos the Clown') - G.GAME.current_round.free_rerolls = #chaos - calculate_reroll_cost(true) - - G.GAME.round_bonus.next_hands = 0 - G.GAME.round_bonus.discards = 0 - - local blhash = '' - if G.GAME.blind_on_deck == 'Small' then - G.GAME.round_resets.blind_states.Small = 'Current' - G.GAME.current_boss_streak = 0 - blhash = 'S' - elseif G.GAME.blind_on_deck == 'Big' then - G.GAME.round_resets.blind_states.Big = 'Current' - G.GAME.current_boss_streak = 0 - blhash = 'B' - else - G.GAME.round_resets.blind_states.Boss = 'Current' - blhash = 'L' - end - G.GAME.subhash = (G.GAME.round_resets.ante)..(blhash) - - G.GAME.blind:set_blind(G.GAME.round_resets.blind) - if G.GAME.modifiers.cry_card_each_round then - G.E_MANAGER:add_event(Event({ - func = function() - local front = pseudorandom_element(G.P_CARDS, pseudoseed('cry_horizon')) - G.playing_card = (G.playing_card and G.playing_card + 1) or 1 - local edition = G.P_CENTERS.c_base - local card = Card(G.play.T.x + G.play.T.w/2, G.play.T.y, G.CARD_W, G.CARD_H, front, G.P_CENTERS.c_base, {playing_card = G.playing_card}) - card:start_materialize() - if G.GAME.selected_back.effect.config.cry_force_edition and G.GAME.selected_back.effect.config.cry_force_edition ~= "random" then - local edition = {} - edition[G.GAME.selected_back.effect.config.cry_force_edition] = true - card:set_edition(edition, true, true); - end - G.play:emplace(card) - table.insert(G.playing_cards, card) - playing_card_joker_effects({true}) - return true - end})) - G.E_MANAGER:add_event(Event({ - func = function() - G.deck.config.card_limit = G.deck.config.card_limit + 1 - return true - end})) - draw_card(G.play,G.deck, 90,'up', nil) - end - if G.GAME.modifiers.cry_conveyor and #G.jokers.cards>0 then - local duplicated_joker = copy_card(G.jokers.cards[#G.jokers.cards]) - duplicated_joker:add_to_deck() - G.jokers:emplace(duplicated_joker) - G.jokers.cards[1]:start_dissolve() - end - G.GAME.current_round.semicolon = false - - for i = 1, #G.playing_cards do - local CARD = G.playing_cards[i] - CARD.cry_debuff_immune = false - end - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({setting_blind = true, blind = G.GAME.round_resets.blind}) - end - G.GAME.selected_back:trigger_effect({context = 'setting_blind', blind = G.GAME.round_resets.blind}) - delay(0.4) - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.STATE = G.STATES.DRAW_TO_HAND - G.deck:shuffle('nr'..G.GAME.round_resets.ante) - G.deck:hard_set_T() -if G.SCORING_COROUTINE then return false end - G.STATE_COMPLETE = false - return true - end - })) - return true - end - })) -end - -G.FUNCS.draw_from_deck_to_hand = function(e) - if not (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) and - G.hand.config.card_limit <= 0 and #G.hand.cards == 0 then - G.STATE = G.STATES.GAME_OVER; G.STATE_COMPLETE = false - return true - end - - local hand_space = e - if not hand_space then - local limit = G.hand.config.card_limit - #G.hand.cards - local n = 0 - while n < #G.deck.cards do - local card = G.deck.cards[#G.deck.cards-n] - limit = limit - 1 + (card.edition and card.edition.card_limit or 0) - if limit < 0 then break end - n = n + 1 - end - hand_space = n - end - if G.GAME.blind.name == 'The Serpent' and - not G.GAME.blind.disabled and - (G.GAME.current_round.hands_played > 0 or - G.GAME.current_round.discards_used > 0) then - hand_space = math.min(#G.deck.cards, 3) - end - delay(0.3) - if not G.GAME.USING_RUN then - for i=1, hand_space do --draw cards from deckL - if G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK then - draw_card(G.deck,G.hand, i*100/hand_space,'up', true) - else - draw_card(G.deck,G.hand, i*100/hand_space,'up', true) - end - end -else - for i = 1, #G.cry_runarea.cards do - draw_card(G.cry_runarea,G.hand, i*100/#G.cry_runarea.cards,'up', true) - end -end - -G.FUNCS.draw_from_hand_to_run = function(e) -- might as well just slap this here - local hand_count = #G.hand.cards - for i=1, hand_count do --draw cards from deck - draw_card(G.hand, G.cry_runarea, i*100/hand_count,'down', nil, nil, 0.08) - end -end -end - -G.FUNCS.discard_cards_from_highlighted = function(e, hook) - stop_use() - G.CONTROLLER.interrupt.focus = true - G.CONTROLLER:save_cardarea_focus('hand') - - for k, v in ipairs(G.playing_cards) do - v.ability.forced_selection = nil - end - - if G.CONTROLLER.focused.target and G.CONTROLLER.focused.target.area == G.hand then G.card_area_focus_reset = {area = G.hand, rank = G.CONTROLLER.focused.target.rank} end - local highlighted_count = math.min(#G.hand.highlighted, G.discard.config.card_limit - #G.play.cards) - if highlighted_count > 0 then - update_hand_text({immediate = true, nopulse = true, delay = 0}, {mult = 0, chips = 0, level = '', handname = ''}) - table.sort(G.hand.highlighted, function(a,b) return a.T.x < b.T.x end) - inc_career_stat('c_cards_discarded', highlighted_count) - for i = 1, #G.hand.cards do - eval_card(G.hand.cards[i], {pre_discard = true, full_hand = G.hand.highlighted, hook = hook}) - end - for j = 1, #G.jokers.cards do - G.jokers.cards[j]:calculate_joker({pre_discard = true, full_hand = G.hand.highlighted, hook = hook}) - end - local cards = {} - local destroyed_cards = {} - for i=1, highlighted_count do - local removed = false - local eval = nil - eval = eval_card(G.hand.highlighted[i], {discard = true, full_hand = G.hand.highlighted}) - if eval and eval.remove then - removed = true - card_eval_status_text(G.hand.highlighted[i], 'jokers', nil, 1, nil, eval) - end - for j = 1, #G.jokers.cards do - local eval = nil - eval = G.jokers.cards[j]:calculate_joker({discard = true, other_card = G.hand.highlighted[i], full_hand = G.hand.highlighted, callback = function(card, eval) - if eval then - if eval.remove then removed = true end - card_eval_status_text(card, 'jokers', nil, 1, nil, eval) - end - end}) - - end - G.GAME.selected_back:trigger_effect({context = 'discard', other_card = G.hand.highlighted[i], full_hand = G.hand.highlighted}) - table.insert(cards, G.hand.highlighted[i]) - if removed then - destroyed_cards[#destroyed_cards + 1] = G.hand.highlighted[i] - if SMODS.has_enhancement(G.hand.highlighted[i], 'm_glass') then - G.hand.highlighted[i]:shatter() - else - G.hand.highlighted[i]:start_dissolve() - end - else - G.hand.highlighted[i].ability.discarded = true - draw_card(G.hand, G.discard, i*100/highlighted_count, 'down', false, G.hand.highlighted[i]) - end - end - - if destroyed_cards[1] then - for j=1, #G.jokers.cards do - eval_card(G.jokers.cards[j], {cardarea = G.jokers, remove_playing_cards = true, removed = destroyed_cards}) - end - end - - G.GAME.round_scores.cards_discarded.amt = G.GAME.round_scores.cards_discarded.amt + #cards - check_for_unlock({type = 'discard_custom', cards = cards}) - if not hook then - if G.GAME.modifiers.discard_cost then - ease_dollars(-G.GAME.modifiers.discard_cost) - end - ease_discard(-1) - G.GAME.current_round.discards_used = G.GAME.current_round.discards_used + 1 - G.STATE = G.STATES.DRAW_TO_HAND - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() -if G.SCORING_COROUTINE then return false end - G.STATE_COMPLETE = false - return true - end - })) - end - end -end - -G.FUNCS.play_cards_from_highlighted = function(e) - if G.play and G.play.cards[1] then return end - --check the hand first - - stop_use() - G.GAME.blind.triggered = false - G.CONTROLLER.interrupt.focus = true - G.CONTROLLER:save_cardarea_focus('hand') - - for k, v in ipairs(G.playing_cards) do - v.ability.forced_selection = nil - end - - table.sort(G.hand.highlighted, function(a,b) return a.T.x < b.T.x end) - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.STATE = G.STATES.HAND_PLAYED - G.STATE_COMPLETE = true - return true - end - })) - inc_career_stat('c_cards_played', #G.hand.highlighted) - inc_career_stat('c_hands_played', 1) - ease_hands_played(-1) - delay(0.4) - - for i=1, #G.hand.highlighted do - if G.hand.highlighted[i]:is_face() then inc_career_stat('c_face_cards_played', 1) end - G.hand.highlighted[i].base.times_played = G.hand.highlighted[i].base.times_played + 1 - G.hand.highlighted[i].ability.played_this_ante = true - G.GAME.round_scores.cards_played.amt = G.GAME.round_scores.cards_played.amt + 1 - draw_card(G.hand, G.play, i*100/#G.hand.highlighted, 'up', nil, G.hand.highlighted[i]) - end - - check_for_unlock({type = 'run_card_replays'}) - - if G.GAME.blind:press_play() then - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - SMODS.juice_up_blind() - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.06*G.SETTINGS.GAMESPEED, blockable = false, blocking = false, func = function() - play_sound('tarot2', 0.76, 0.4);return true end})) - play_sound('tarot2', 1, 0.4) - return true - end) - })) - delay(0.4) - end - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - check_for_unlock({type = 'hand_contents', cards = G.play.cards}) - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.FUNCS.evaluate_play() - return true - end - })) - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.1, - func = function() - if G.SCORING_COROUTINE then return false end - check_for_unlock({type = 'play_all_hearts'}) - G.FUNCS.draw_from_play_to_discard() - G.GAME.hands_played = G.GAME.hands_played + 1 - G.GAME.current_round.hands_played = G.GAME.current_round.hands_played + 1 - return true - end - })) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() -if G.SCORING_COROUTINE then return false end - G.STATE_COMPLETE = false - return true - end - })) - return true - end) - })) -end - -G.FUNCS.get_poker_hand_info = function(_cards) - local poker_hands = evaluate_poker_hand(_cards) - local scoring_hand = {} - local text,disp_text,loc_disp_text = 'NULL','NULL', 'NULL' - if next(poker_hands["Flush Five"]) then text = "Flush Five"; scoring_hand = poker_hands["Flush Five"][1] - elseif next(poker_hands["Flush House"]) then text = "Flush House"; scoring_hand = poker_hands["Flush House"][1] - elseif next(poker_hands["Five of a Kind"]) then text = "Five of a Kind"; scoring_hand = poker_hands["Five of a Kind"][1] - elseif next(poker_hands["Straight Flush"]) then text = "Straight Flush"; scoring_hand = poker_hands["Straight Flush"][1] - elseif next(poker_hands["Four of a Kind"]) then text = "Four of a Kind"; scoring_hand = poker_hands["Four of a Kind"][1] - elseif next(poker_hands["Full House"]) then text = "Full House"; scoring_hand = poker_hands["Full House"][1] - elseif next(poker_hands["Flush"]) then text = "Flush"; scoring_hand = poker_hands["Flush"][1] - elseif next(poker_hands["Straight"]) then text = "Straight"; scoring_hand = poker_hands["Straight"][1] - elseif next(poker_hands["Three of a Kind"]) then text = "Three of a Kind"; scoring_hand = poker_hands["Three of a Kind"][1] - elseif next(poker_hands["Two Pair"]) then text = "Two Pair"; scoring_hand = poker_hands["Two Pair"][1] - elseif next(poker_hands["Pair"]) then text = "Pair"; scoring_hand = poker_hands["Pair"][1] - elseif next(poker_hands["High Card"]) then text = "High Card"; scoring_hand = poker_hands["High Card"][1] end - - disp_text = text - if text =='Straight Flush' then - local min = 10 - for j = 1, #scoring_hand do - if scoring_hand[j]:get_id() < min then min =scoring_hand[j]:get_id() end - end - if min >= 10 then - disp_text = 'Royal Flush' - end - end - loc_disp_text = localize(disp_text, 'poker_hands') - return text, loc_disp_text, poker_hands, scoring_hand, disp_text -end - -G.FUNCS.evaluate_play = function(e) - local text,disp_text,poker_hands,scoring_hand,non_loc_disp_text = G.FUNCS.get_poker_hand_info(G.play.cards) - - G.GAME.hands[text].played = G.GAME.hands[text].played + 1 - if G.GAME.current_round.current_hand.cry_asc_num > 0 then G.GAME.cry_asc_played = G.GAME.cry_asc_played and G.GAME.cry_asc_played+1 or 1 end - G.GAME.hands[text].played_this_round = G.GAME.hands[text].played_this_round + 1 - G.GAME.last_hand_played = text - set_hand_usage(text) - G.GAME.hands[text].visible = true - - --Add all the pure bonus cards to the scoring hand - local pures = {} - for i=1, #G.play.cards do - if next(find_joker('Splash')) then - scoring_hand[i] = G.play.cards[i] - else - if SMODS.always_scores(G.play.cards[i]) then - local inside = false - for j=1, #scoring_hand do - if scoring_hand[j] == G.play.cards[i] then - inside = true - end - end - if not inside then table.insert(pures, G.play.cards[i]) end - end - end - end - for i=1, #pures do - table.insert(scoring_hand, pures[i]) - end - table.sort(scoring_hand, function (a, b) return a.T.x < b.T.x end ) - delay(0.2) - for i=1, #scoring_hand do - --Highlight all the cards used in scoring and play a sound indicating highlight - highlight_card(scoring_hand[i],(i-0.999)/5,'up') - end - - local percent = 0.3 - local percent_delta = 0.08 - - if G.GAME.current_round.current_hand.handname ~= disp_text then delay(0.3) end - update_hand_text({sound = G.GAME.current_round.current_hand.handname ~= disp_text and 'button' or nil, volume = 0.4, immediate = true, nopulse = nil, - delay = G.GAME.current_round.current_hand.handname ~= disp_text and 0.4 or 0}, {handname=disp_text, level=G.GAME.hands[text].level, mult = cry_ascend(G.GAME.hands[text].mult), chips = cry_ascend(G.GAME.hands[text].chips)}) - - if not G.GAME.blind:debuff_hand(G.play.cards, poker_hands, text) then - mult = mod_mult(cry_ascend(G.GAME.hands[text].mult)) - hand_chips = mod_chips(cry_ascend(G.GAME.hands[text].chips)) - - check_for_unlock({type = 'hand', handname = text, disp_text = non_loc_disp_text, scoring_hand = scoring_hand, full_hand = G.play.cards}) - - delay(0.4) - - if G.GAME.first_used_hand_level and G.GAME.first_used_hand_level > 0 then - level_up_hand(G.deck.cards[1], text, nil, G.GAME.first_used_hand_level) - G.GAME.first_used_hand_level = nil - end - - local hand_text_set = false - for i=1, #G.jokers.cards do - --calculate the joker effects - local effects = eval_card(G.jokers.cards[i], {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, before = true, callback = function(card, ret) effects = {jokers = ret} - if effects.jokers then - card_eval_status_text(card, 'jokers', nil, percent, nil, effects.jokers) - percent = percent + percent_delta - if effects.jokers.level_up then - level_up_hand(card, text) - end - end - end}) - end - G.GAME.selected_back:trigger_effect({context = 'before_hand', full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands}) - - mult = mod_mult(cry_ascend(G.GAME.hands[text].mult)) - hand_chips = mod_chips(cry_ascend(G.GAME.hands[text].chips)) - - local modded = false - - mult, hand_chips, modded = G.GAME.blind:modify_hand(G.play.cards, poker_hands, text, mult, hand_chips) - mult, hand_chips = mod_mult(mult), mod_chips(hand_chips) - if modded then update_hand_text({sound = 'chips2', modded = modded}, {chips = hand_chips, mult = mult}) end - for i=1, #scoring_hand do - --add cards played to list - if not SMODS.has_no_rank(scoring_hand[i]) then - G.GAME.cards_played[scoring_hand[i].base.value].total = G.GAME.cards_played[scoring_hand[i].base.value].total + 1 - if not SMODS.has_no_suit(scoring_hand[i]) then - G.GAME.cards_played[scoring_hand[i].base.value].suits[scoring_hand[i].base.suit] = true - end - end - --if card is debuffed - if scoring_hand[i].debuff then - G.GAME.blind.triggered = true - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() SMODS.juice_up_blind();return true end) - })) - card_eval_status_text(scoring_hand[i], 'debuff') - else - --Check for play doubling - local reps = {1} - - --From Red seal - local eval = eval_card(scoring_hand[i], {repetition_only = true,cardarea = G.play, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, repetition = true}) - if next(eval) then - for h = 1, eval.seals.repetitions do - reps[#reps+1] = eval - end - end - --From jokers - for j=1, #G.jokers.cards do - --calculate the joker effects - local eval = eval_card(G.jokers.cards[j], {cardarea = G.play, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, other_card = scoring_hand[i], repetition = true, callback = function(card, ret) eval = {jokers = ret} - if next(eval) and eval.jokers then - if not eval.jokers.repetitions then eval.jokers.repetitions = 0 end - for h = 1, eval.jokers.repetitions do - reps[#reps+1] = eval - end - end end}) - end - --From edition - if scoring_hand[i].edition and scoring_hand[i].edition.key then - local ed = SMODS.Centers[scoring_hand[i].edition.key] - if ed.config and ed.config.retriggers then - for h = 1, ed.config.retriggers do - reps[#reps+1] = {seals = { - message = localize("k_again_ex"), - card = scoring_hand[i] - }} - end - end - if ed.calculate and type(ed.calculate) == 'function' then - local check = ed:calculate(scoring_hand[i], {retrigger_edition_check = true, cardarea = G.play, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, other_card = scoring_hand[i], repetition = true}) - if check and type(check) == 'table' and next(check) then - for j = 1, check.repetitions do - reps[#reps+1] = {seals = check} - end - end - end - end - for j=1,#reps do - percent = percent + percent_delta - if reps[j] ~= 1 and (not scoring_hand or not scoring_hand[i] or not scoring_hand[i].will_shatter) then - card_eval_status_text((reps[j].jokers or reps[j].seals).card, 'jokers', nil, nil, nil, (reps[j].jokers or reps[j].seals)) - end - - --calculate the hand effects - local effects = {eval_card(scoring_hand[i], {cardarea = G.play, full_hand = G.play.cards, scoring_hand = scoring_hand, poker_hand = text})} - local post_effect = {seals = effects[1].seals, edition = effects[1].edition} - effects[1].seals = nil - effects[1].edition = nil - local extra_enhancements = SMODS.get_enhancements(scoring_hand[i], true) - local old_ability = copy_table(scoring_hand[i].ability) - local old_center = scoring_hand[i].config.center - local old_center_key = scoring_hand[i].config.center_key - for k, _ in pairs(extra_enhancements) do - if G.P_CENTERS[k] then - scoring_hand[i]:set_ability(G.P_CENTERS[k]) - scoring_hand[i].ability.extra_enhancement = k - effects[#effects+1] = eval_card(scoring_hand[i], {cardarea = G.play, full_hand = G.play.cards, scoring_hand = scoring_hand, poker_hand = text, extra_enhancement = true}) - end - end - effects[#effects+1] = post_effect - scoring_hand[i].ability = old_ability - scoring_hand[i].config.center = old_center - scoring_hand[i].config.center_key = old_center_key - scoring_hand[i]:set_sprites(old_center) - for k=1, #G.jokers.cards do - --calculate the joker individual card effects - local eval = G.jokers.cards[k]:calculate_joker({cardarea = G.play, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, other_card = scoring_hand[i], individual = true, callback = function(card, eval, retrigger) - if eval then - table.insert(effects, eval) -effects[#effects].from_retrigger = retrigger -end end, no_retrigger_anim = true}) - - end - scoring_hand[i].lucky_trigger = nil - - for ii = 1, #effects do - --If chips added, do chip add event and add the chips to the total - if effects[ii].chips then - if effects[ii].card then juice_card(effects[ii].card) end - hand_chips = mod_chips(hand_chips + effects[ii].chips) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(scoring_hand[i], 'chips', effects[ii].chips, percent) - end - - --If mult added, do mult add event and add the mult to the total - if effects[ii].mult then - if effects[ii].card then juice_card(effects[ii].card) end - mult = mod_mult(mult + effects[ii].mult) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(scoring_hand[i], 'mult', effects[ii].mult, percent) - end - - --If play dollars added, add dollars to total - if effects[ii].p_dollars then - if effects[ii].card then juice_card(effects[ii].card) end - ease_dollars(effects[ii].p_dollars) - card_eval_status_text(scoring_hand[i], 'dollars', effects[ii].p_dollars, percent) - end - - --If dollars added, add dollars to total - if effects[ii].dollars then - if effects[ii].card then juice_card(effects[ii].card) end - ease_dollars(effects[ii].dollars) - card_eval_status_text(scoring_hand[i], 'dollars', effects[ii].dollars, percent) - end - - --Any extra effects - if effects[ii].extra then - if effects[ii].card then juice_card(effects[ii].card) end - local extras = {mult = false, hand_chips = false} - if effects[ii].extra.mult_mod then mult =mod_mult( mult + effects[ii].extra.mult_mod);extras.mult = true end - if effects[ii].extra.chip_mod then hand_chips = mod_chips(hand_chips + effects[ii].extra.chip_mod);extras.hand_chips = true end - if effects[ii].extra.swap then - local old_mult = mult - mult = mod_mult(hand_chips) - hand_chips = mod_chips(old_mult) - extras.hand_chips = true; extras.mult = true - end - if effects[ii].extra.func then effects[ii].extra.func() end - update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult}) - card_eval_status_text(scoring_hand[i], 'extra', nil, percent, nil, effects[ii].extra) - end - - if effects[ii].seals then - if effects[ii].seals.chips then - if effects[ii].card then juice_card(effects[ii].card) end - hand_chips = mod_chips(hand_chips + effects[ii].seals.chips) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(scoring_hand[i], 'chips', effects[ii].seals.chips, percent) - end - - if effects[ii].seals.mult then - if effects[ii].card then juice_card(effects[ii].card) end - mult = mod_mult(mult + effects[ii].seals.mult) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(scoring_hand[i], 'mult', effects[ii].seals.mult, percent) - end - - if effects[ii].seals.p_dollars then - if effects[ii].card then juice_card(effects[ii].card) end - ease_dollars(effects[ii].seals.p_dollars) - card_eval_status_text(scoring_hand[i], 'dollars', effects[ii].seals.p_dollars, percent) - end - - if effects[ii].seals.dollars then - if effects[ii].card then juice_card(effects[ii].card) end - ease_dollars(effects[ii].seals.dollars) - card_eval_status_text(scoring_hand[i], 'dollars', effects[ii].seals.dollars, percent) - end - - if effects[ii].seals.x_mult then - if effects[ii].card then juice_card(effects[ii].card) end - mult = mod_mult(mult*effects[ii].seals.x_mult) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(scoring_hand[i], 'x_mult', effects[ii].seals.x_mult, percent) - end - - if effects[ii].seals.func then - effects[ii].seals.func() - end - end - - --If x_mult added, do mult add event and mult the mult to the total - if effects[ii].x_mult then - if effects[ii].card then juice_card(effects[ii].card) end - mult = mod_mult(mult*effects[ii].x_mult) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(scoring_hand[i], 'x_mult', effects[ii].x_mult, percent) - if next(find_joker("cry-Exponentia")) then - for _, v in pairs(find_joker("cry-Exponentia")) do - local old = v.ability.extra.Emult - v.ability.extra.Emult = v.ability.extra.Emult + v.ability.extra.Emult_mod - card_eval_status_text(v, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_powmult',vars={number_format(to_big(v.ability.extra.Emult))}}}) - exponentia_scale_mod(v, v.ability.extra.Emult_mod, old, v.ability.extra.Emult) - end - end - end - - if effects[ii].x_chips then - mod_percent = true - if effects[ii].card then juice_card(effects[ii].card) end - hand_chips = mod_chips(hand_chips*effects[ii].x_chips) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(scoring_hand[i], 'x_chips', effects[ii].x_chips, percent) - end - if effects[ii].e_chips then - mod_percent = true - if effects[ii].card then juice_card(effects[ii].card) end - hand_chips = mod_chips(hand_chips^effects[ii].e_chips) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(scoring_hand[i], 'e_chips', effects[ii].e_chips, percent) - end - if effects[ii].ee_chips then - mod_percent = true - if effects[ii].card then juice_card(effects[ii].card) end - hand_chips = mod_chips(hand_chips:arrow(2, effects[ii].ee_chips)) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(scoring_hand[i], 'ee_chips', effects[ii].ee_chips, percent) - end - if effects[ii].eee_chips then - mod_percent = true - if effects[ii].card then juice_card(effects[ii].card) end - hand_chips = mod_chips(hand_chips:arrow(3, effects[ii].eee_chips)) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(scoring_hand[i], 'eee_chips', effects[ii].eee_chips, percent) - end - if effects[ii].hyper_chips and type(effects[ii].hyper_chips) == 'table' then - mod_percent = true - if effects[ii].card then juice_card(effects[ii].card) end - hand_chips = mod_chips(hand_chips:arrow(effects[ii].hyper_chips[1], effects[ii].hyper_chips[2])) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(scoring_hand[i], 'hyper_chips', effects[ii].hyper_chips, percent) - end - if effects[ii].e_mult then - mod_percent = true - if effects[ii].card then juice_card(effects[ii].card) end - mult = mod_mult(mult^effects[ii].e_mult) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(scoring_hand[i], 'e_mult', effects[ii].e_mult, percent) - end - if effects[ii].ee_mult then - mod_percent = true - if effects[ii].card then juice_card(effects[ii].card) end - mult = mod_mult(mult:arrow(2, effects[ii].ee_mult)) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(scoring_hand[i], 'ee_mult', effects[ii].ee_mult, percent) - end - if effects[ii].eee_mult then - mod_percent = true - if effects[ii].card then juice_card(effects[ii].card) end - mult = mod_mult(mult:arrow(3, effects[ii].eee_mult)) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(scoring_hand[i], 'eee_mult', effects[ii].eee_mult, percent) - end - if effects[ii].hyper_mult and type(effects[ii].hyper_mult) == 'table' then - mod_percent = true - if effects[ii].card then juice_card(effects[ii].card) end - mult = mod_mult(mult:arrow(effects[ii].hyper_mult[1], effects[ii].hyper_mult[2])) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(scoring_hand[i], 'hyper_mult', effects[ii].hyper_mult, percent) - end - - --calculate the card edition effects - if effects[ii].edition then - if effects[ii].edition.chip_mod then - hand_chips = mod_chips(hand_chips + effects[ii].edition.chip_mod) - local key_switch = (effects[ii].edition.chip_mod > 0 and 'a_chips' or 'a_chips_minus') - card_eval_status_text(scoring_hand[i], 'extra', nil, percent, nil, { - message = localize{type='variable', key=key_switch, vars={math.abs(effects[ii].edition.chip_mod)}}, - chip_mod = true, - colour = G.C.DARK_EDITION, - edition = true - }) - update_hand_text({delay = 0}, {chips = hand_chips}) - end - if effects[ii].edition.mult_mod then - mult = mult + effects[ii].edition.mult_mod - card_eval_status_text(scoring_hand[i], 'extra', nil, percent, nil, { - message = localize{type='variable', key='a_mult', vars={effects[ii].edition.mult_mod}}, - mult_mod = true, - colour = G.C.DARK_EDITION, - edition = true - }) - update_hand_text({delay = 0}, {mult = mult}) - end - if effects[ii].edition.x_mult_mod then - mult = mult * effects[ii].edition.x_mult_mod - card_eval_status_text(scoring_hand[i], 'extra', nil, percent, nil, { - message = localize{type='variable', key='a_xmult', vars={effects[ii].edition.x_mult_mod}}, - x_mult_mod = true, - colour = G.C.DARK_EDITION, - edition = true - }) - update_hand_text({delay = 0}, {mult = mult}) - end - if scoring_hand and scoring_hand[i] and scoring_hand[i].edition then - local trg = scoring_hand[i] - local edi = trg.edition - if edi.x_chips then - hand_chips = mod_chips(hand_chips * edi.x_chips) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = 'X'.. edi.x_chips ..' Chips', - edition = true, - x_chips = true}) - end - if edi.e_chips then - hand_chips = mod_chips(hand_chips ^ edi.e_chips) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^'.. edi.e_chips ..' Chips', - edition = true, - e_chips = true}) - end - if edi.ee_chips then - hand_chips = mod_chips(hand_chips:arrow(2, edi.ee_chips)) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^^'.. edi.ee_chips ..' Chips', - edition = true, - ee_chips = true}) - end - if edi.eee_chips then - hand_chips = mod_chips(hand_chips:arrow(3, edi.eee_chips)) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^^^'.. edi.eee_chips ..' Chips', - edition = true, - eee_chips = true}) - end - if edi.hyper_chips and type(edi.hyper_chips) == 'table' then - hand_chips = mod_chips(hand_chips:arrow(edi.hyper_chips[1], edi.hyper_chips[2])) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = (edi.hyper_chips[1] > 5 and ('{' .. edi.hyper_chips[1] .. '}') or string.rep('^', edi.hyper_chips[1])) .. edi.hyper_chips[2] ..' Chips', - edition = true, - eee_chips = true}) - end - if edi.e_mult then - mult = mod_mult(mult ^ edi.e_mult) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^'.. edi.e_mult ..' Mult', - edition = true, - e_mult = true}) - end - if edi.ee_mult then - mult = mod_mult(mult:arrow(2, edi.ee_mult)) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^^'.. edi.ee_mult ..' Mult', - edition = true, - ee_mult = true}) - end - if edi.eee_mult then - mult = mod_mult(mult:arrow(3, edi.eee_mult)) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^^^'.. edi.eee_mult ..' Mult', - edition = true, - eee_mult = true}) - end - if edi.hyper_mult and type(edi.hyper_mult) == 'table' then - mult = mod_mult(mult:arrow(edi.hyper_mult[1], edi.hyper_mult[2])) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = (edi.hyper_mult[1] > 5 and ('{' .. edi.hyper_mult[1] .. '}') or string.rep('^', edi.hyper_mult[1])) .. edi.hyper_mult[2] ..' Mult', - edition = true, - hyper_mult = true}) - end - end - if effects[ii].edition.p_dollars_mod then - if effects[ii].card then juice_card(effects[ii].card) end - ease_dollars(effects[ii].edition.p_dollars_mod) - card_eval_status_text(scoring_hand[i], 'dollars', effects[ii].edition.p_dollars_mod, percent) - end - if not effects[ii].edition then - hand_chips = mod_chips(hand_chips + (effects[ii].edition.chip_mod or 0)) - mult = mult + (effects[ii].edition.mult_mod or 0) - mult = mod_mult(mult*(effects[ii].edition.x_mult_mod or 1)) - update_hand_text({delay = 0}, { - chips = effects[ii].edition.chip_mod and hand_chips or nil, - mult = (effects[ii].edition.mult_mod or effects[ii].edition.x_mult_mod) and mult or nil, - }) - card_eval_status_text(scoring_hand[i], 'extra', nil, percent, nil, { - message = (effects[ii].edition.chip_mod and localize{type='variable',key='a_chips',vars={effects[ii].edition.chip_mod}}) or - (effects[ii].edition.mult_mod and localize{type='variable',key='a_mult',vars={effects[ii].edition.mult_mod}}) or - (effects[ii].edition.x_mult_mod and localize{type='variable',key='a_xmult',vars={effects[ii].edition.x_mult_mod}}), - chip_mod = effects[ii].edition.chip_mod, - mult_mod = effects[ii].edition.mult_mod, - x_mult_mod = effects[ii].edition.x_mult_mod, - colour = G.C.DARK_EDITION, - edition = true})end - end - if effects[ii].from_retrigger then - card_eval_status_text(effects[ii].from_retrigger.card, 'jokers', nil, nil, nil, effects[ii].from_retrigger) - end - -end - end - end - end - - delay(0.3) - local mod_percent = false - if scoring_hand then - local unscoring_hand = {} - for i = 1, #G.play.cards do - local is_scoring = false - for j = 1, #scoring_hand do - if G.play.cards[i] == scoring_hand[j] then - is_scoring = true - end - end - if not is_scoring then - unscoring_hand[#unscoring_hand+1] = G.play.cards[i] - end - end - for i = 1, #unscoring_hand do - unscoring_hand[i]:calculate_seal{unscoring = true} - end - end - for i=1, #G.hand.cards do - if mod_percent then percent = percent + percent_delta end - mod_percent = false - - --Check for hand doubling - local reps = {1} - local j = 1 - while j <= #reps do - if reps[j] ~= 1 and (not scoring_hand or not scoring_hand[i] or not scoring_hand[i].will_shatter) then - card_eval_status_text((reps[j].jokers or reps[j].seals).card, 'jokers', nil, nil, nil, (reps[j].jokers or reps[j].seals)) - percent = percent + percent_delta - end - - --calculate the hand effects - local effects = {eval_card(G.hand.cards[i], {cardarea = G.hand, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands})} - local extra_enhancements = SMODS.get_enhancements(G.hand.cards[i], true) - local old_ability = copy_table(G.hand.cards[i].ability) - local old_center = G.hand.cards[i].config.center - local old_center_key = G.hand.cards[i].config.center_key - for k, _ in pairs(extra_enhancements) do - if G.P_CENTERS[k] then - G.hand.cards[i]:set_ability(G.P_CENTERS[k]) - G.hand.cards[i].ability.extra_enhancement = k - effects[#effects+1] = eval_card(G.hand.cards[i], {cardarea = G.hand, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, extra_enhancement = true}) - end - end - G.hand.cards[i].ability = old_ability - G.hand.cards[i].config.center = old_center - G.hand.cards[i].config.center_key = old_center_key - G.hand.cards[i]:set_sprites(old_center) - - for k=1, #G.jokers.cards do - --calculate the joker individual card effects - local eval = G.jokers.cards[k]:calculate_joker({cardarea = G.hand, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, other_card = G.hand.cards[i], individual = true, callback = function(card, eval, retrigger) - if eval then - mod_percent = true - table.insert(effects, eval) -effects[#effects].from_retrigger = retrigger -end end, no_retrigger_anim = true}) - - end - - if reps[j] == 1 then - --Check for hand doubling - - --From Red seal - local eval = eval_card(G.hand.cards[i], {repetition_only = true,cardarea = G.hand, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, repetition = true, card_effects = effects}) - if next(eval) and (next(effects[1]) or #effects > 1) then - for h = 1, eval.seals.repetitions do - reps[#reps+1] = eval - end - end - - --From Joker - for j=1, #G.jokers.cards do - --calculate the joker effects - local eval = eval_card(G.jokers.cards[j], {cardarea = G.hand, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, other_card = G.hand.cards[i], repetition = true, card_effects = effects, callback = function(card, ret) eval = {jokers = ret} - if next(eval) then - for h = 1, eval.jokers.repetitions do - reps[#reps+1] = eval - end - end end}) - end - end - - for ii = 1, #effects do - --if this effect came from a joker - if effects[ii].card and not Talisman.config_file.disable_anims then - mod_percent = true - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() effects[ii].card:juice_up(0.7);return true end) - })) - end - - --If hold mult added, do hold mult add event and add the mult to the total - - --If dollars added, add dollars to total - if effects[ii].dollars then - ease_dollars(effects[ii].dollars) - card_eval_status_text(G.hand.cards[i], 'dollars', effects[ii].dollars, percent) - end - - if effects[ii].h_mult then - mod_percent = true - mult = mod_mult(mult + effects[ii].h_mult) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(G.hand.cards[i], 'h_mult', effects[ii].h_mult, percent) - end - if effects[ii].h_chips then - if effects[ii].card then juice_card(effects[ii].card) end - hand_chips = mod_chips(hand_chips + effects[ii].h_chips) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(effects[ii].card, 'chips', effects[ii].h_chips, percent) - end - - if effects[ii].x_mult then - mod_percent = true - mult = mod_mult(mult*effects[ii].x_mult) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(G.hand.cards[i], 'x_mult', effects[ii].x_mult, percent) - if next(find_joker("cry-Exponentia")) then - for _, v in pairs(find_joker("cry-Exponentia")) do - local old = v.ability.extra.Emult - v.ability.extra.Emult = v.ability.extra.Emult + v.ability.extra.Emult_mod - card_eval_status_text(v, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_powmult',vars={number_format(to_big(v.ability.extra.Emult))}}}) - exponentia_scale_mod(v, v.ability.extra.Emult_mod, old, v.ability.extra.Emult) - end - end - end - - if effects[ii].x_chips then - mod_percent = true - hand_chips = mod_chips(hand_chips*effects[ii].x_chips) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(G.hand.cards[i], 'x_chips', effects[ii].x_chips, percent) - end - if effects[ii].e_chips then - mod_percent = true - hand_chips = mod_chips(hand_chips^effects[ii].e_chips) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(G.hand.cards[i], 'e_chips', effects[ii].e_chips, percent) - end - if effects[ii].ee_chips then - mod_percent = true - hand_chips = mod_chips(hand_chips:arrow(2, effects[ii].ee_chips)) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(G.hand.cards[i], 'ee_chips', effects[ii].ee_chips, percent) - end - if effects[ii].eee_chips then - mod_percent = true - hand_chips = mod_chips(hand_chips:arrow(3, effects[ii].eee_chips)) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(G.hand.cards[i], 'eee_chips', effects[ii].eee_chips, percent) - end - if effects[ii].hyper_chips and type(effects[ii].hyper_chips) == 'table' then - mod_percent = true - hand_chips = mod_chips(hand_chips:arrow(effects[ii].hyper_chips[1], effects[ii].hyper_chips[2])) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(G.hand.cards[i], 'hyper_chips', effects[ii].hyper_chips, percent) - end - if effects[ii].e_mult then - mod_percent = true - mult = mod_mult(mult^effects[ii].e_mult) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(G.hand.cards[i], 'e_mult', effects[ii].e_mult, percent) - end - if effects[ii].ee_mult then - mod_percent = true - mult = mod_mult(mult:arrow(2, effects[ii].ee_mult)) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(G.hand.cards[i], 'ee_mult', effects[ii].ee_mult, percent) - end - if effects[ii].eee_mult then - mod_percent = true - mult = mod_mult(mult:arrow(3, effects[ii].eee_mult)) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(G.hand.cards[i], 'eee_mult', effects[ii].eee_mult, percent) - end - if effects[ii].hyper_mult and type(effects[ii].hyper_mult) == 'table' then - mod_percent = true - mult = mod_mult(mult:arrow(effects[ii].hyper_mult[1], effects[ii].hyper_mult[2])) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(G.hand.cards[i], 'hyper_mult', effects[ii].hyper_mult, percent) - end - - if effects[ii].message then - mod_percent = true - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(G.hand.cards[i], 'extra', nil, percent, nil, effects[ii]) - end - if effects[ii].from_retrigger then - card_eval_status_text(effects[ii].from_retrigger.card, 'jokers', nil, nil, nil, effects[ii].from_retrigger) - end - -end - j = j +1 - end - end - --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- - --Joker Effects - --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- - percent = percent + percent_delta - local numcards = #G.jokers.cards + #G.consumeables.cards - if G.GAME.modifiers.cry_beta then numcards = #G.jokers.cards end - for i=1, numcards do - local _card = G.jokers.cards[i] or G.consumeables.cards[i - #G.jokers.cards] - --calculate the joker edition effects - local edition_effects = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, edition = true}) - if not edition_effects then edition_effects = {} end - if edition_effects.jokers then - edition_effects.jokers.edition = true - if edition_effects.jokers.p_dollars_mod then - ease_dollars(edition_effects.jokers.p_dollars_mod) - card_eval_status_text(_card, 'dollars', edition_effects.jokers.p_dollars_mod, percent) - end - if edition_effects.jokers.chip_mod then - hand_chips = mod_chips(hand_chips + edition_effects.jokers.chip_mod) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(_card, 'jokers', nil, percent, nil, { - message = localize{type='variable',key='a_chips',vars={edition_effects.jokers.chip_mod}}, - chip_mod = edition_effects.jokers.chip_mod, - colour = G.C.EDITION, - edition = true}) - if (effects and effects[ii] and effects[ii].edition and effects[ii].edition.x_mult_mod or edition_effects and edition_effects.jokers and edition_effects.jokers.x_mult_mod) and next(find_joker("cry-Exponentia")) then - for _, v in pairs(find_joker("cry-Exponentia")) do - local old = v.ability.extra.Emult - v.ability.extra.Emult = v.ability.extra.Emult + v.ability.extra.Emult_mod - card_eval_status_text(v, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_powmult',vars={number_format(to_big(v.ability.extra.Emult))}}}) - exponentia_scale_mod(v, v.ability.extra.Emult_mod, old, v.ability.extra.Emult) - end - end - end - if edition_effects.jokers.mult_mod then - mult = mod_mult(mult + edition_effects.jokers.mult_mod) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(_card, 'jokers', nil, percent, nil, { - message = localize{type='variable',key='a_mult',vars={edition_effects.jokers.mult_mod}}, - mult_mod = edition_effects.jokers.mult_mod, - colour = G.C.DARK_EDITION, - edition = true}) - if (effects and effects[ii] and effects[ii].edition and effects[ii].edition.x_mult_mod or edition_effects and edition_effects.jokers and edition_effects.jokers.x_mult_mod) and next(find_joker("cry-Exponentia")) then - for _, v in pairs(find_joker("cry-Exponentia")) do - local old = v.ability.extra.Emult - v.ability.extra.Emult = v.ability.extra.Emult + v.ability.extra.Emult_mod - card_eval_status_text(v, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_powmult',vars={number_format(to_big(v.ability.extra.Emult))}}}) - exponentia_scale_mod(v, v.ability.extra.Emult_mod, old, v.ability.extra.Emult) - end - end - end - percent = percent+percent_delta - end - - --calculate the joker effects - local effects = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, joker_main = true, callback = function(_card, ret) effects = {jokers = ret} - G.GAME.selected_back:trigger_effect({context = 'joker_main', joker = _card, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands}) - - --Any Joker effects - if effects.jokers then - local extras = {mult = false, hand_chips = false} - if effects.jokers.mult_mod then mult = mod_mult(mult + effects.jokers.mult_mod);extras.mult = true end - if effects.jokers.chip_mod then hand_chips = mod_chips(hand_chips + effects.jokers.chip_mod);extras.hand_chips = true end - if effects.jokers.Xmult_mod then mult = mod_mult(mult*effects.jokers.Xmult_mod);extras.mult = true end - if effects.jokers.Emult_mod then mult = mod_mult(mult^effects.jokers.Emult_mod);extras.mult = true end - if effects.jokers.EEmult_mod then mult = mod_mult(mult:arrow(2, effects.jokers.EEmult_mod));extras.mult = true end - if effects.jokers.EEEmult_mod then mult = mod_mult(mult:arrow(3, effects.jokers.EEEmult_mod));extras.mult = true end - if effects.jokers.hypermult_mod and type(effects.jokers.hypermult_mod) == 'table' then mult = mod_mult(mult:arrow(effects.jokers.hypermult_mod[1], effects.jokers.hypermult_mod[2]));extras.mult = true end - if effects.jokers.Xchip_mod then hand_chips = mod_chips(hand_chips*effects.jokers.Xchip_mod);extras.hand_chips = true end - if effects.jokers.Echip_mod then hand_chips = mod_chips(hand_chips^effects.jokers.Echip_mod);extras.hand_chips = true end - if effects.jokers.EEchip_mod then hand_chips = mod_chips(hand_chips:arrow(2, effects.jokers.EEchip_mod));extras.hand_chips = true end - if effects.jokers.EEEchip_mod then hand_chips = mod_chips(hand_chips:arrow(3, effects.jokers.EEEchip_mod));extras.hand_chips = true end - if effects.jokers.hyperchip_mod and type(effects.jokers.hyperchip_mod) == 'table' then hand_chips = mod_chips(hand_chips:arrow(effects.jokers.hyperchip_mod[1], effects.jokers.hyperchip_mod[2]));extras.hand_chips = true end - update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult}) - card_eval_status_text(_card, 'jokers', nil, percent, nil, effects.jokers) - if effects.jokers.Xmult_mod and effects.jokers.Xmult_mod ~= 1 and next(find_joker("cry-Exponentia")) then - for _, v in pairs(find_joker("cry-Exponentia")) do - local old = v.ability.extra.Emult - v.ability.extra.Emult = v.ability.extra.Emult + v.ability.extra.Emult_mod - card_eval_status_text(v, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_powmult',vars={number_format(to_big(v.ability.extra.Emult))}}}) - exponentia_scale_mod(v, v.ability.extra.Emult_mod, old, v.ability.extra.Emult) - end - end - percent = percent+percent_delta - end - - end}) - --Joker on Joker effects - for _, v in ipairs(G.jokers.cards) do - local effect = v:calculate_joker({full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, other_joker = _card, callback = function(v, effect) - if effect then - local extras = {mult = false, hand_chips = false} - if effect.mult_mod then mult = mod_mult(mult + effect.mult_mod);extras.mult = true end - if effect.chip_mod then hand_chips = mod_chips(hand_chips + effect.chip_mod);extras.hand_chips = true end - if effect.Xmult_mod then mult = mod_mult(mult*effect.Xmult_mod);extras.mult = true end - if effect.Emult_mod then mult = mod_mult(mult^effect.Emult_mod);extras.mult = true end - if effect.EEmult_mod then mult = mod_mult(mult:arrow(2, effect.EEmult_mod));extras.mult = true end - if effect.EEEmult_mod then mult = mod_mult(mult:arrow(3, effect.EEEmult_mod));extras.mult = true end - if effect.hypermult_mod and type(effect.hypermult_mod) == 'table' then mult = mod_mult(mult:arrow(effect.hypermult_mod[1], effect.hypermult_mod[2]));extras.mult = true end - if effect.Xchip_mod then hand_chips = mod_chips(hand_chips*effect.Xchip_mod);extras.hand_chips = true end - if effect.Echip_mod then hand_chips = mod_chips(hand_chips^effect.Echip_mod);extras.hand_chips = true end - if effect.EEchip_mod then hand_chips = mod_chips(hand_chips:arrow(2, effect.EEchip_mod));extras.hand_chips = true end - if effect.EEEchip_mod then hand_chips = mod_chips(hand_chips:arrow(3, effect.EEEchip_mod));extras.hand_chips = true end - if effect.hyperchip_mod and type(effect.hyperchip_mod) == 'table' then hand_chips = mod_chips(hand_chips:arrow(effect.hyperchip_mod[1], effect.hyperchip_mod[2]));extras.hand_chips = true end - if extras.mult or extras.hand_chips then update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult}) end - if extras.mult or extras.hand_chips then card_eval_status_text(v, 'jokers', nil, percent, nil, effect) end - if effects.Xmult_mod and next(find_joker("cry-Exponentia")) then - for _, v in pairs(find_joker("cry-Exponentia")) do - local old = v.ability.extra.Emult - v.ability.extra.Emult = v.ability.extra.Emult + v.ability.extra.Emult_mod - card_eval_status_text(v, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_powmult',vars={number_format(to_big(v.ability.extra.Emult))}}}) - exponentia_scale_mod(v, v.ability.extra.Emult_mod, old, v.ability.extra.Emult) - end - end - if effect.Xmult_mod and effect.Xmult_mod ~= 1 and next(find_joker("cry-Exponentia")) then - for _, v in pairs(find_joker("cry-Exponentia")) do - local old = v.ability.extra.Emult - v.ability.extra.Emult = v.ability.extra.Emult + v.ability.extra.Emult_mod - card_eval_status_text(v, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_powmult',vars={number_format(to_big(v.ability.extra.Emult))}}}) - exponentia_scale_mod(v, v.ability.extra.Emult_mod, old, v.ability.extra.Emult) - end - end - percent = percent+percent_delta - end end}) end if edition_effects.jokers then - if edition_effects.jokers.x_mult_mod then - mult = mod_mult(mult*edition_effects.jokers.x_mult_mod) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(_card, 'jokers', nil, percent, nil, { - message = localize{type='variable',key='a_xmult',vars={edition_effects.jokers.x_mult_mod}}, - x_mult_mod = edition_effects.jokers.x_mult_mod, - colour = G.C.EDITION, - edition = true}) - end - if G.jokers.cards and G.jokers.cards[i] and G.jokers.cards[i].edition then - local trg = G.jokers.cards[i] - local edi = trg.edition - if edi.x_chips then - hand_chips = mod_chips(hand_chips * edi.x_chips) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = 'X'.. edi.x_chips ..' Chips', - edition = true, - x_chips = true}) - end - if edi.e_chips then - hand_chips = mod_chips(hand_chips ^ edi.e_chips) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^'.. edi.e_chips ..' Chips', - edition = true, - e_chips = true}) - end - if edi.ee_chips then - hand_chips = mod_chips(hand_chips:arrow(2, edi.ee_chips)) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^^'.. edi.ee_chips ..' Chips', - edition = true, - ee_chips = true}) - end - if edi.eee_chips then - hand_chips = mod_chips(hand_chips:arrow(3, edi.eee_chips)) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^^^'.. edi.eee_chips ..' Chips', - edition = true, - eee_chips = true}) - end - if edi.hyper_chips and type(edi.hyper_chips) == 'table' then - hand_chips = mod_chips(hand_chips:arrow(edi.hyper_chips[1], edi.hyper_chips[2])) - update_hand_text({delay = 0}, {chips = hand_chips}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = (edi.hyper_chips[1] > 5 and ('{' .. edi.hyper_chips[1] .. '}') or string.rep('^', edi.hyper_chips[1])) .. edi.hyper_chips[2] ..' Chips', - edition = true, - eee_chips = true}) - end - if edi.e_mult then - mult = mod_mult(mult ^ edi.e_mult) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^'.. edi.e_mult ..' Mult', - edition = true, - e_mult = true}) - end - if edi.ee_mult then - mult = mod_mult(mult:arrow(2, edi.ee_mult)) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^^'.. edi.ee_mult ..' Mult', - edition = true, - ee_mult = true}) - end - if edi.eee_mult then - mult = mod_mult(mult:arrow(3, edi.eee_mult)) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^^^'.. edi.eee_mult ..' Mult', - edition = true, - eee_mult = true}) - end - if edi.hyper_mult and type(edi.hyper_mult) == 'table' then - mult = mod_mult(mult:arrow(edi.hyper_mult[1], edi.hyper_mult[2])) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = (edi.hyper_mult[1] > 5 and ('{' .. edi.hyper_mult[1] .. '}') or string.rep('^', edi.hyper_mult[1])) .. edi.hyper_mult[2] ..' Mult', - edition = true, - hyper_mult = true}) - end - end - edition_effects.jokers.x_mult_mod = nil - if edition_effects.jokers.x_mult_mod then - mult = mod_mult(mult*edition_effects.jokers.x_mult_mod) - update_hand_text({delay = 0}, {mult = mult}) - card_eval_status_text(_card, 'jokers', nil, percent, nil, { - message = localize{type='variable',key='a_xmult',vars={edition_effects.jokers.x_mult_mod}}, - x_mult_mod = edition_effects.jokers.x_mult_mod, - colour = G.C.EDITION, - edition = true}) - if (effects and effects[ii] and effects[ii].edition and effects[ii].edition.x_mult_mod or edition_effects and edition_effects.jokers and edition_effects.jokers.x_mult_mod) and next(find_joker("cry-Exponentia")) then - for _, v in pairs(find_joker("cry-Exponentia")) do - local old = v.ability.extra.Emult - v.ability.extra.Emult = v.ability.extra.Emult + v.ability.extra.Emult_mod - card_eval_status_text(v, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_powmult',vars={number_format(to_big(v.ability.extra.Emult))}}}) - exponentia_scale_mod(v, v.ability.extra.Emult_mod, old, v.ability.extra.Emult) - end - end - end - percent = percent+percent_delta - end - end - - local nu_chip, nu_mult = G.GAME.selected_back:trigger_effect{context = 'final_scoring_step', chips = hand_chips, mult = mult} - mult = mod_mult(nu_mult or mult) - hand_chips = mod_chips(nu_chip or hand_chips) - - local cards_destroyed = {} - for i=1, #scoring_hand do - local destroyed = nil - --un-highlight all cards - highlight_card(scoring_hand[i],(i-0.999)/(#scoring_hand-0.998),'down') - - for j = 1, #G.jokers.cards do - destroyed = G.jokers.cards[j]:calculate_joker({destroying_card = scoring_hand[i], full_hand = G.play.cards, callback = function(card, ret) if ret then destroyed=true end end}) - if destroyed then break end - end - - if SMODS.has_enhancement(scoring_hand[i], 'm_glass') and not scoring_hand[i].debuff and pseudorandom('glass') < cry_prob(scoring_hand[i].ability.cry_prob, scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra, scoring_hand[i].ability.cry_rigged)/(scoring_hand[i].ability.name == 'Glass Card' and scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) then - destroyed = true - end - - if scoring_hand[i].will_shatter then destroyed = true end - if scoring_hand[i]:calculate_seal({destroying_card = scoring_hand[i], full_hand = G.play.cards}) and not scoring_hand[i].ability.eternal then - destroyed = true - end - - if destroyed then - if SMODS.has_enhancement(scoring_hand[i], 'm_glass') then - scoring_hand[i].shattered = true - else - scoring_hand[i].destroyed = true - end - cards_destroyed[#cards_destroyed+1] = scoring_hand[i] - end - end - for j=1, #G.jokers.cards do - eval_card(G.jokers.cards[j], {cardarea = G.jokers, remove_playing_cards = true, removed = cards_destroyed}) - end - G.GAME.selected_back:trigger_effect({context = 'remove_playing_cards', removed = cards_destroyed}) - - local glass_shattered = {} - for k, v in ipairs(cards_destroyed) do - if v.shattered then glass_shattered[#glass_shattered+1] = v end - end - - check_for_unlock{type = 'shatter', shattered = glass_shattered} - - for i=1, #cards_destroyed do - G.E_MANAGER:add_event(Event({ - func = function() - if SMODS.has_enhancement(cards_destroyed[i], 'm_glass') then - cards_destroyed[i]:shatter() - else - cards_destroyed[i]:start_dissolve() - end - return true - end - })) - end - else - mult = mod_mult(0) - hand_chips = mod_chips(0) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - SMODS.juice_up_blind() - G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.06*G.SETTINGS.GAMESPEED, blockable = false, blocking = false, func = function() - play_sound('tarot2', 0.76, 0.4);return true end})) - play_sound('tarot2', 1, 0.4) - return true - end) - })) - - play_area_status_text("Not Allowed!")--localize('k_not_allowed_ex'), true) - --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- - --Joker Debuff Effects - --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- - for i=1, #G.jokers.cards do - - --calculate the joker effects - local effects = eval_card(G.jokers.cards[i], {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, debuffed_hand = true, callback = function(card, ret) effects = {jokers = ret} - - --Any Joker effects - if effects.jokers then - card_eval_status_text(card, 'jokers', nil, percent, nil, effects.jokers) - percent = percent+percent_delta - end - end}) end - end - G.E_MANAGER:add_event(Event({ - trigger = 'after',delay = 0.4, - func = (function() update_hand_text({delay = 0, immediate = true}, {mult = 0, chips = 0, chip_total = G.GAME.blind.cry_cap_score and G.GAME.blind:cry_cap_score(math.floor(hand_chips*mult)) or math.floor(hand_chips*mult), level = '', handname = ''});play_sound('button', 0.9, 0.6);return true end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() G.GAME.current_round.current_hand.cry_asc_num = 0;G.GAME.current_round.current_hand.cry_asc_num_text = '';return true end) - })) - check_and_set_high_score('hand', hand_chips*mult) - - check_for_unlock({type = 'chip_score', chips = math.floor(hand_chips*mult)}) - - if to_big(hand_chips)*mult > to_big(0) then - delay(0.8) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() play_sound('chips2');return true end) - })) - end - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - blocking = false, - ref_table = G.GAME, - ref_value = 'chips', - ease_to = G.GAME.chips + (G.GAME.blind.cry_cap_score and G.GAME.blind:cry_cap_score(math.floor(hand_chips*mult)) or math.floor(hand_chips*mult)), - delay = 0.5, - func = (function(t) return math.floor(t) end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'ease', - blocking = true, - ref_table = G.GAME.current_round.current_hand, - ref_value = 'chip_total', - ease_to = 0, - delay = 0.5, - func = (function(t) return math.floor(t) end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() G.GAME.current_round.current_hand.handname = '';return true end) - })) - delay(0.3) - - for i=1, #G.jokers.cards do - --calculate the joker after hand played effects - local effects = eval_card(G.jokers.cards[i], {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, after = true, callback = function(card, ret) effects = {jokers = ret} - if effects.jokers then - card_eval_status_text(card, 'jokers', nil, percent, nil, effects.jokers) - percent = percent + percent_delta - end - end - - }) end - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - if G.GAME.modifiers.debuff_played_cards then - for k, v in ipairs(scoring_hand) do v.ability.perma_debuff = true end - end - return true end) - })) - - end - - G.FUNCS.draw_from_play_to_discard = function(e) - local play_count = #G.play.cards - local it = 1 - for k, v in ipairs(G.play.cards) do - if (not v.shattered) and (not v.destroyed) then - draw_card(G.play,G.discard, it*100/play_count,'down', false, v) - it = it + 1 - end - end - end - - G.FUNCS.draw_from_play_to_hand = function(cards) - local gold_count = #cards - for i=1, gold_count do --draw cards from play - if not cards[i].shattered and not cards[i].destroyed then - draw_card(G.play,G.hand, i*100/gold_count,'up', true, cards[i]) - end - end - end - - G.FUNCS.draw_from_discard_to_deck = function(e) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - local discard_count = #G.discard.cards - for i=1, discard_count do --draw cards from deck - draw_card(G.discard, G.deck, i*100/discard_count,'up', nil ,nil, 0.005, i%2==0, nil, math.max((21-i)/20,0.7)) - end - return true - end - })) - end - - G.FUNCS.draw_from_hand_to_deck = function(e) - local hand_count = #G.hand.cards - for i=1, hand_count do --draw cards from deck - draw_card(G.hand, G.deck, i*100/hand_count,'down', nil, nil, 0.08) - end - end - - G.FUNCS.draw_from_hand_to_discard = function(e) - local hand_count = #G.hand.cards - for i=1, hand_count do - draw_card(G.hand,G.discard, i*100/hand_count,'down', nil, nil, 0.07) - end -end - -G.FUNCS.evaluate_round = function() - total_cashout_rows = 0 - local pitch = 0.95 - local dollars = 0 - - if to_big(G.GAME.chips) >= to_big(G.GAME.blind.chips) then - add_round_eval_row({dollars = G.GAME.blind.dollars, name='blind1', pitch = pitch}) - pitch = pitch + 0.06 - dollars = dollars + G.GAME.blind.dollars - else - add_round_eval_row({dollars = 0, name='blind1', pitch = pitch, saved = true}) - pitch = pitch + 0.06 - end - - G.E_MANAGER:add_event(Event({ - trigger = 'before', - delay = 1.3*math.min(G.GAME.blind.dollars+2, 7)/2*0.15 + 0.5, - func = function() - G.GAME.blind:defeat() - return true - end - })) - delay(0.2) - G.E_MANAGER:add_event(Event({ - func = function() - ease_background_colour_blind(G.STATES.ROUND_EVAL, '') - return true - end - })) - G.GAME.selected_back:trigger_effect({context = 'eval'}) - - if G.GAME.current_round.hands_left > 0 and not G.GAME.modifiers.no_extra_hand_money then - add_round_eval_row({dollars = G.GAME.current_round.hands_left*(G.GAME.modifiers.money_per_hand or 1), disp = G.GAME.current_round.hands_left, bonus = true, name='hands', pitch = pitch}) - pitch = pitch + 0.06 - dollars = dollars + G.GAME.current_round.hands_left*(G.GAME.modifiers.money_per_hand or 1) - end - if G.GAME.current_round.discards_left > 0 and G.GAME.modifiers.money_per_discard then - add_round_eval_row({dollars = G.GAME.current_round.discards_left*(G.GAME.modifiers.money_per_discard), disp = G.GAME.current_round.discards_left, bonus = true, name='discards', pitch = pitch}) - pitch = pitch + 0.06 - dollars = dollars + G.GAME.current_round.discards_left*(G.GAME.modifiers.money_per_discard) - end - for i = 1, #G.playing_cards do - local CARD = G.playing_cards[i] - CARD.cry_debuff_immune = false - end - for i = 1, #G.jokers.cards do - local ret = G.jokers.cards[i]:calculate_dollar_bonus() - if ret then - add_round_eval_row({dollars = ret, bonus = true, name='joker'..i, pitch = pitch, card = G.jokers.cards[i]}) - pitch = pitch + 0.06 - dollars = dollars + ret - end - end - for i = 1, #G.GAME.tags do - local ret = G.GAME.tags[i]:apply_to_run({type = 'eval'}) - if ret then - add_round_eval_row({dollars = ret.dollars, bonus = true, name='tag'..i, pitch = pitch, condition = ret.condition, pos = ret.pos, tag = ret.tag}) - pitch = pitch + 0.06 - dollars = dollars + ret.dollars - end - end - if G.GAME.dollars >= 5 and not G.GAME.modifiers.no_interest and G.GAME.cry_payload then - add_round_eval_row({bonus = true, payload = G.GAME.cry_payload, name='interest_payload', pitch = pitch, dollars = G.GAME.interest_amount*G.GAME.cry_payload*math.min(math.floor(G.GAME.dollars/5), G.GAME.interest_cap/5)}) - pitch = pitch + 0.06 - if not G.GAME.seeded and not G.GAME.challenge then - if G.GAME.interest_amount*math.min(math.floor(G.GAME.dollars/5), G.GAME.interest_cap/5) == G.GAME.interest_amount*G.GAME.interest_cap/5 then - G.PROFILES[G.SETTINGS.profile].career_stats.c_round_interest_cap_streak = G.PROFILES[G.SETTINGS.profile].career_stats.c_round_interest_cap_streak + 1 - else - G.PROFILES[G.SETTINGS.profile].career_stats.c_round_interest_cap_streak = 0 - end - end - check_for_unlock({type = 'interest_streak'}) - dollars = dollars + G.GAME.interest_amount*G.GAME.cry_payload*math.min(math.floor(G.GAME.dollars/5), G.GAME.interest_cap/5) - G.GAME.cry_payload = nil - elseif G.GAME.dollars >= 5 and not G.GAME.modifiers.no_interest then - add_round_eval_row({bonus = true, name='interest', pitch = pitch, dollars = G.GAME.interest_amount*math.min(math.floor(G.GAME.dollars/5), G.GAME.interest_cap/5)}) - pitch = pitch + 0.06 - if not G.GAME.seeded and not G.GAME.challenge then - if G.GAME.interest_amount*math.min(math.floor(G.GAME.dollars/5), G.GAME.interest_cap/5) == G.GAME.interest_amount*G.GAME.interest_cap/5 then - G.PROFILES[G.SETTINGS.profile].career_stats.c_round_interest_cap_streak = G.PROFILES[G.SETTINGS.profile].career_stats.c_round_interest_cap_streak + 1 - else - G.PROFILES[G.SETTINGS.profile].career_stats.c_round_interest_cap_streak = 0 - end - end - check_for_unlock({type = 'interest_streak'}) - dollars = dollars + G.GAME.interest_amount*math.min(math.floor(G.GAME.dollars/5), G.GAME.interest_cap/5) - end - - pitch = pitch + 0.06 - - if total_cashout_rows > 7 then - local total_hidden = total_cashout_rows - 7 - - G.E_MANAGER:add_event(Event({ - trigger = 'before',delay = 0.38, - func = function() - local hidden = {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({ - string = {localize{type = 'variable', key = 'cashout_hidden', vars = {total_hidden}}}, - colours = {G.C.WHITE}, shadow = true, float = false, - scale = 0.45, - font = G.LANGUAGES['en-us'].font, pop_in = 0 - })}} - }} - - G.round_eval:add_child(hidden, G.round_eval:get_UIE_by_ID('bonus_round_eval')) - return true - end - })) - end - add_round_eval_row({name = 'bottom', dollars = dollars}) - Talisman.dollars = dollars -end - -G.FUNCS.tutorial_controller = function() - if G.F_SKIP_TUTORIAL then - G.SETTINGS.tutorial_complete = true - G.SETTINGS.tutorial_progress = nil - return - end - G.SETTINGS.tutorial_progress = G.SETTINGS.tutorial_progress or - { - forced_shop = {'j_joker', 'c_empress'}, - forced_voucher = 'v_grabber', - forced_tags = {'tag_handy', 'tag_garbage'}, - hold_parts = {}, - completed_parts = {}, - } - if not G.SETTINGS.paused and (not G.SETTINGS.tutorial_complete) then - if G.STATE == G.STATES.BLIND_SELECT and G.blind_select and not G.SETTINGS.tutorial_progress.completed_parts['small_blind'] then - G.SETTINGS.tutorial_progress.section = 'small_blind' - G.FUNCS.tutorial_part('small_blind') - G.SETTINGS.tutorial_progress.completed_parts['small_blind'] = true - G:save_progress() - end - if G.STATE == G.STATES.BLIND_SELECT and G.blind_select and not G.SETTINGS.tutorial_progress.completed_parts['big_blind'] and G.GAME.round > 0 then - G.SETTINGS.tutorial_progress.section = 'big_blind' - G.FUNCS.tutorial_part('big_blind') - G.SETTINGS.tutorial_progress.completed_parts['big_blind'] = true - G.SETTINGS.tutorial_progress.forced_tags = nil - G:save_progress() - end - if G.STATE == G.STATES.SELECTING_HAND and not G.SETTINGS.tutorial_progress.completed_parts['second_hand'] and G.SETTINGS.tutorial_progress.hold_parts['big_blind'] then - G.SETTINGS.tutorial_progress.section = 'second_hand' - G.FUNCS.tutorial_part('second_hand') - G.SETTINGS.tutorial_progress.completed_parts['second_hand'] = true - G:save_progress() - end - if G.SETTINGS.tutorial_progress.hold_parts['second_hand'] then - G.SETTINGS.tutorial_complete = true - end - if not G.SETTINGS.tutorial_progress.completed_parts['first_hand_section'] then - if G.STATE == G.STATES.SELECTING_HAND and not G.SETTINGS.tutorial_progress.completed_parts['first_hand'] then - G.SETTINGS.tutorial_progress.section = 'first_hand' - G.FUNCS.tutorial_part('first_hand') - G.SETTINGS.tutorial_progress.completed_parts['first_hand'] = true - G:save_progress() - end - if G.STATE == G.STATES.SELECTING_HAND and not G.SETTINGS.tutorial_progress.completed_parts['first_hand_2'] and G.SETTINGS.tutorial_progress.hold_parts['first_hand'] then - G.FUNCS.tutorial_part('first_hand_2') - G.SETTINGS.tutorial_progress.completed_parts['first_hand_2'] = true - G:save_progress() - end - if G.STATE == G.STATES.SELECTING_HAND and not G.SETTINGS.tutorial_progress.completed_parts['first_hand_3'] and G.SETTINGS.tutorial_progress.hold_parts['first_hand_2'] then - G.FUNCS.tutorial_part('first_hand_3') - G.SETTINGS.tutorial_progress.completed_parts['first_hand_3'] = true - G:save_progress() - end - if G.STATE == G.STATES.SELECTING_HAND and not G.SETTINGS.tutorial_progress.completed_parts['first_hand_4'] and G.SETTINGS.tutorial_progress.hold_parts['first_hand_3'] then - G.FUNCS.tutorial_part('first_hand_4') - G.SETTINGS.tutorial_progress.completed_parts['first_hand_4'] = true - G.SETTINGS.tutorial_progress.completed_parts['first_hand_section'] = true - G:save_progress() - end - end - if G.STATE == G.STATES.SHOP and G.shop and G.shop.VT.y < 5 and not G.SETTINGS.tutorial_progress.completed_parts['shop_1'] then - G.SETTINGS.tutorial_progress.section = 'shop' - G.FUNCS.tutorial_part('shop_1') - G.SETTINGS.tutorial_progress.completed_parts['shop_1'] = true - G.SETTINGS.tutorial_progress.forced_voucher = nil - G:save_progress() - end - end -end - -G.FUNCS.tutorial_part = function(_part) - local step = 1 - G.SETTINGS.paused = true - if _part == 'small_blind' then - step = tutorial_info({ - text_key = 'sb_1', - attach = {major = G.ROOM_ATTACH, type = 'cm', offset = {x = 0, y = 0}}, - step = step, - }) - step = tutorial_info({ - text_key = 'sb_2', - attach = {major = G.ROOM_ATTACH, type = 'cm', offset = {x = 0, y = 0}}, - step = step, - }) - step = tutorial_info({ - text_key = 'sb_3', - highlight = { - G.blind_select.UIRoot.children[1].children[1].config.object:get_UIE_by_ID('blind_name'), - G.blind_select.UIRoot.children[1].children[1].config.object:get_UIE_by_ID('blind_desc'), - }, - attach = {major = G.blind_select.UIRoot.children[1].children[1], type = 'tr', offset = {x = 2, y = 4}}, - step = step, - }) - step = tutorial_info({ - text_key = 'sb_4', - highlight = { - G.blind_select.UIRoot.children[1].children[1] - }, - snap_to = function() - if G.blind_select and G.blind_select.UIRoot and G.blind_select.UIRoot.children[1] and G.blind_select.UIRoot.children[1].children[1] and G.blind_select.UIRoot.children[1].children[1].config.object then - return G.blind_select.UIRoot.children[1].children[1].config.object:get_UIE_by_ID('select_blind_button') end - end, - attach = {major = G.blind_select.UIRoot.children[1].children[1], type = 'tr', offset = {x = 2, y = 4}}, - step = step, - no_button = true, - button_listen = 'select_blind' - }) - elseif _part == 'big_blind' then - step = tutorial_info({ - text_key = 'bb_1', - highlight = { - G.blind_select.UIRoot.children[1].children[2].config.object:get_UIE_by_ID('blind_name'), - G.blind_select.UIRoot.children[1].children[2].config.object:get_UIE_by_ID('blind_desc'), - }, - hard_set = true, - attach = {major = G.HUD, type = 'cm', offset = {x = 0, y = -2}}, - step = step, - }) - step = tutorial_info({ - text_key = 'bb_2', - highlight = { - G.blind_select.UIRoot.children[1].children[2].config.object:get_UIE_by_ID('blind_name'), - G.blind_select.UIRoot.children[1].children[2].config.object:get_UIE_by_ID('tag_desc'), - }, - attach = {major = G.HUD, type = 'cm', offset = {x = 0, y = -2}}, - step = step, - }) - step = tutorial_info({ - text_key = 'bb_3', - highlight = { - G.blind_select.UIRoot.children[1].children[3].config.object:get_UIE_by_ID('blind_name'), - G.blind_select.UIRoot.children[1].children[3].config.object:get_UIE_by_ID('blind_desc'), - }, - attach = {major = G.HUD, type = 'cm', offset = {x = 0, y = -2}}, - step = step, - }) - step = tutorial_info({ - text_key = 'bb_4', - highlight = { - G.blind_select.UIRoot.children[1].children[3].config.object:get_UIE_by_ID('blind_name'), - G.blind_select.UIRoot.children[1].children[3].config.object:get_UIE_by_ID('blind_desc'), - G.blind_select.UIRoot.children[1].children[3].config.object:get_UIE_by_ID('blind_extras'), - G.HUD:get_UIE_by_ID('hud_ante') - }, - attach = {major = G.HUD, type = 'cm', offset = {x = 0, y = -2}}, - step = step, - }) - step = tutorial_info({ - text_key = 'bb_5', - loc_vars = {G.GAME.win_ante}, - highlight = { - G.blind_select, - G.HUD:get_UIE_by_ID('hud_ante') - }, - attach = {major = G.HUD, type = 'cm', offset = {x = 0, y = -2}}, - step = step, - no_button = true, - snap_to = function() - if G.blind_select and G.blind_select.UIRoot and G.blind_select.UIRoot.children[1] and G.blind_select.UIRoot.children[1].children[2] and - G.blind_select.UIRoot.children[1].children[2].config.object then - return G.blind_select.UIRoot.children[1].children[2].config.object:get_UIE_by_ID('select_blind_button') end - end, - button_listen = 'select_blind' - }) - elseif _part == 'first_hand' then - step = tutorial_info({ - text_key = 'fh_1', - attach = {major = G.ROOM_ATTACH, type = 'cm', offset = {x = 0, y = 0}}, - step = step, - }) - step = tutorial_info({ - text_key = 'fh_2', - highlight = { - G.HUD:get_UIE_by_ID('hand_text_area') - }, - attach = {major = G.ROOM_ATTACH, type = 'cm', offset = {x = 0, y = 0}}, - step = step, - }) - step = tutorial_info({ - text_key = 'fh_3', - attach = {major = G.ROOM_ATTACH, type = 'cm', offset = {x = 0, y = 0}}, - highlight = { - G.HUD:get_UIE_by_ID('run_info_button') - }, - no_button = true, - button_listen = 'run_info', - snap_to = function() return G.HUD:get_UIE_by_ID('run_info_button') end, - step = step, - }) - elseif _part == 'first_hand_2' then - step = tutorial_info({ - hard_set = true, - text_key = 'fh_4', - highlight = { - G.hand, - G.HUD:get_UIE_by_ID('run_info_button') - }, - attach = {major = G.hand, type = 'cl', offset = {x = -1.5, y = 0}}, - snap_to = function() return G.hand.cards[1] end, - step = step, - }) - step = tutorial_info({ - text_key = 'fh_5', - highlight = { - G.hand, - G.buttons:get_UIE_by_ID('play_button'), - G.HUD:get_UIE_by_ID('run_info_button') - }, - attach = {major = G.hand, type = 'cl', offset = {x = -1.5, y = 0}}, - no_button = true, - button_listen = 'play_cards_from_highlighted', - step = step, - }) - elseif _part == 'first_hand_3' then - step = tutorial_info({ - hard_set = true, - text_key = 'fh_6', - highlight = { - G.hand, - G.buttons:get_UIE_by_ID('discard_button'), - G.HUD:get_UIE_by_ID('run_info_button') - }, - attach = {major = G.hand, type = 'cl', offset = {x = -1.5, y = 0}}, - no_button = true, - button_listen = 'discard_cards_from_highlighted', - step = step, - }) - elseif _part == 'first_hand_4' then - step = tutorial_info({ - hard_set = true, - text_key = 'fh_7', - highlight = { - G.HUD:get_UIE_by_ID('hud_hands').parent, - }, - attach = {major = G.ROOM_ATTACH, type = 'cm', offset = {x = 0, y = 0}}, - step = step, - }) - step = tutorial_info({ - text_key = 'fh_8', - highlight = { - G.HUD:get_UIE_by_ID('hud_hands').parent, - G.HUD:get_UIE_by_ID('row_dollars_chips'), - G.HUD_blind - }, - attach = {major = G.ROOM_ATTACH, type = 'cm', offset = {x = 0, y = 0}}, - step = step, - }) - elseif _part == 'second_hand' then - step = tutorial_info({ - text_key = 'sh_1', - hard_set = true, - highlight = { - G.jokers - }, - attach = {major = G.HUD, type = 'cm', offset = {x = 0, y = -2}}, - step = step, - }) - local empress = find_joker('The Empress')[1] - if empress then - step = tutorial_info({ - text_key = 'sh_2', - highlight = { - empress - }, - attach = {major = G.HUD, type = 'cm', offset = {x = 0, y = -2}}, - step = step, - }) - step = tutorial_info({ - text_key = 'sh_3', - attach = {major = G.HUD, type = 'cm', offset = {x = 0, y = -2}}, - highlight = { - empress, - G.hand - }, - no_button = true, - button_listen = 'use_card', - snap_to = function() return G.hand.cards[1] end, - step = step, - }) - end - elseif _part == 'shop_1' then - step = tutorial_info({ - hard_set = true, - text_key = 's_1', - highlight = { - G.SHOP_SIGN, - G.HUD:get_UIE_by_ID('dollar_text_UI').parent.parent.parent - }, - attach = {major = G.shop, type = 'tm', offset = {x = 0, y = 4}}, - step = step, - }) - step = tutorial_info({ - text_key = 's_2', - highlight = { - G.SHOP_SIGN, - G.HUD:get_UIE_by_ID('dollar_text_UI').parent.parent.parent, - G.shop_jokers.cards[2], - }, - snap_to = function() return G.shop_jokers.cards[2] end, - attach = {major = G.shop, type = 'tr', offset = {x = -0.5, y = 6}}, - no_button = true, - button_listen = 'buy_from_shop', - step = step, - }) - step = tutorial_info({ - text_key = 's_3', - loc_vars = {#G.P_CENTER_POOLS.Joker}, - highlight = function() return { - G.SHOP_SIGN, - G.HUD:get_UIE_by_ID('dollar_text_UI').parent.parent.parent, - G.jokers.cards[1], - } end, - attach = {major = G.shop, type = 'tm', offset = {x = 0, y = 6}}, - step = step, - }) - step = tutorial_info({ - text_key = 's_4', - highlight = function() return { - G.SHOP_SIGN, - G.HUD:get_UIE_by_ID('dollar_text_UI').parent.parent.parent, - G.jokers.cards[1], - } end, - attach = {major = G.shop, type = 'tm', offset = {x = 0, y = 6}}, - step = step, - }) - step = tutorial_info({ - text_key = 's_5', - highlight = function() return { - G.SHOP_SIGN, - G.HUD:get_UIE_by_ID('dollar_text_UI').parent.parent.parent, - G.jokers, - } end, - attach = {major = G.shop, type = 'tm', offset = {x = 0, y = 6}}, - step = step, - }) - step = tutorial_info({ - text_key = 's_6', - highlight = function() return { - G.SHOP_SIGN, - G.HUD:get_UIE_by_ID('dollar_text_UI').parent.parent.parent, - G.shop_jokers.cards[1], - } end, - snap_to = function() return G.shop_jokers.cards[1] end, - no_button = true, - button_listen = 'buy_from_shop', - attach = {major = G.shop, type = 'tr', offset = {x = -0.5, y = 6}}, - step = step, - }) - step = tutorial_info({ - text_key = 's_7', - highlight = function() return { - G.SHOP_SIGN, - G.HUD:get_UIE_by_ID('dollar_text_UI').parent.parent.parent, - G.consumeables.cards[#G.consumeables.cards], - } end, - attach = {major = G.shop, type = 'tm', offset = {x = 0, y = 6}}, - step = step, - }) - step = tutorial_info({ - text_key = 's_8', - highlight = function() return { - G.SHOP_SIGN, - G.HUD:get_UIE_by_ID('dollar_text_UI').parent.parent.parent, - G.consumeables - } end, - attach = {major = G.shop, type = 'tm', offset = {x = 0, y = 6}}, - step = step, - }) - step = tutorial_info({ - text_key = 's_9', - highlight = function() return { - G.SHOP_SIGN, - G.HUD:get_UIE_by_ID('dollar_text_UI').parent.parent.parent, - G.shop_vouchers, - } end, - snap_to = function() return G.shop_vouchers.cards[1] end, - attach = {major = G.shop, type = 'tr', offset = {x = -4, y = 6}}, - step = step, - }) - step = tutorial_info({ - text_key = 's_10', - highlight = function() return { - G.SHOP_SIGN, - G.HUD:get_UIE_by_ID('dollar_text_UI').parent.parent.parent, - G.shop_vouchers, - } end, - attach = {major = G.shop, type = 'tr', offset = {x = -4, y = 6}}, - step = step, - }) - step = tutorial_info({ - text_key = 's_11', - highlight = function() return { - G.SHOP_SIGN, - G.HUD:get_UIE_by_ID('dollar_text_UI').parent.parent.parent, - G.shop_booster, - } end, - snap_to = function() return G.shop_booster.cards[1] end, - attach = {major = G.shop, type = 'tl', offset = {x = 3, y = 6}}, - step = step, - }) - step = tutorial_info({ - text_key = 's_12', - highlight = function() return { - G.shop:get_UIE_by_ID('next_round_button'), - } end, - snap_to = function() if G.shop then return G.shop:get_UIE_by_ID('next_round_button') end end, - no_button = true, - button_listen = 'toggle_shop', - attach = {major = G.shop, type = 'tm', offset = {x = 0, y = 6}}, - step = step, - }) - end - - - G.E_MANAGER:add_event(Event({ - blockable = false, - timer = 'REAL', - func = function() - if (G.OVERLAY_TUTORIAL.step == step and - not G.OVERLAY_TUTORIAL.step_complete) or G.OVERLAY_TUTORIAL.skip_steps then - if G.OVERLAY_TUTORIAL.Jimbo then G.OVERLAY_TUTORIAL.Jimbo:remove() end - if G.OVERLAY_TUTORIAL.content then G.OVERLAY_TUTORIAL.content:remove() end - G.OVERLAY_TUTORIAL:remove() - G.OVERLAY_TUTORIAL = nil - G.SETTINGS.tutorial_progress.hold_parts[_part]=true - return true - end - return G.OVERLAY_TUTORIAL.step > step or G.OVERLAY_TUTORIAL.skip_steps - end - }), 'tutorial') - G.SETTINGS.paused = false -end diff --git a/lovely/dump/game.lua b/lovely/dump/game.lua deleted file mode 100644 index d7f96cf..0000000 --- a/lovely/dump/game.lua +++ /dev/null @@ -1,4038 +0,0 @@ -LOVELY_INTEGRITY = '6ce2fb7d4e93be5cc027ce62976490e8adadb9539ab9eecba2f579bc9b8dc2e5' - ---Class -Game = Object:extend() - ---Class Methods -function Game:init() - G = self - - self:set_globals() -end - -function Game:start_up() - --Load the settings file - local settings = get_compressed('settings.jkr') - local settings_ver = nil - if settings then - local settings_file = STR_UNPACK(settings) - if G.VERSION >= '1.0.0' and (love.system.getOS() == 'NOPE') and ((not settings_file.version) or (settings_file.version < '1.0.0')) then - for i = 1, 3 do - love.filesystem.remove(i..'/'..'profile.jkr') - love.filesystem.remove(i..'/'..'save.jkr') - love.filesystem.remove(i..'/'..'meta.jkr') - love.filesystem.remove(i..'/'..'unlock_notify.jkr') - love.filesystem.remove(i..'') - end - for k, v in pairs(settings_file) do - self.SETTINGS[k] = v - end - self.SETTINGS.profile = 1 - self.SETTINGS.tutorial_progress = nil - else - if G.VERSION < '1.0.0' then - settings_ver = settings_file.version - end - for k, v in pairs(settings_file) do - self.SETTINGS[k] = v - end - end - end - self.SETTINGS.version = settings_ver or G.VERSION - self.SETTINGS.paused = nil - - local new_colour_proto = self.C["SO_"..(self.SETTINGS.colourblind_option and 2 or 1)] - self.C.SUITS.Hearts = new_colour_proto.Hearts - self.C.SUITS.Diamonds = new_colour_proto.Diamonds - self.C.SUITS.Spades = new_colour_proto.Spades - self.C.SUITS.Clubs = new_colour_proto.Clubs - - boot_timer('start', 'settings', 0.1) - - if self.SETTINGS.GRAPHICS.texture_scaling then - self.SETTINGS.GRAPHICS.texture_scaling = self.SETTINGS.GRAPHICS.texture_scaling > 1 and 2 or 1 - end - - if self.SETTINGS.DEMO and not self.F_CTA then - self.SETTINGS.DEMO = { - total_uptime = 0, - timed_CTA_shown = true, - win_CTA_shown = true, - quit_CTA_shown = true - } - end - - --create all sounds from resources and play one each to load into mem - SOURCES = {} - local sound_files = love.filesystem.getDirectoryItems("resources/sounds") - - for _, filename in ipairs(sound_files) do - local extension = string.sub(filename, -4) - if extension == '.ogg' then - local sound_code = string.sub(filename, 1, -5) - SOURCES[sound_code] = {} - end - end - - self.SETTINGS.language = self.SETTINGS.language or 'en-us' - boot_timer('settings', 'window init', 0.2) - self:init_window() - - if G.F_SOUND_THREAD then - boot_timer('window init', 'soundmanager2') - --call the sound manager to prepare the thread to play sounds - self.SOUND_MANAGER = { - thread = love.thread.newThread('engine/sound_manager.lua'), - channel = love.thread.getChannel('sound_request'), - load_channel = love.thread.getChannel('load_channel') - } - self.SOUND_MANAGER.thread:start(1) - - local sound_loaded, prev_file = false, 'none' - while not sound_loaded and false do - --Monitor the channel for any new requests - local request = self.SOUND_MANAGER.load_channel:pop() -- Value from channel - if request then - --If the request is for an update to the music track, handle it here - if request == 'finished' then sound_loaded = true - else - boot_timer(request, prev_file) - prev_file = request - end - end - love.timer.sleep(0.001) - end - - boot_timer('soundmanager2', 'savemanager',0.22) - end - - boot_timer('window init', 'savemanager') - --call the save manager to wait for any save requests - G.SAVE_MANAGER = { - thread = love.thread.newThread([[require "love.system" - - if (love.system.getOS() == 'OS X' ) and (jit.arch == 'arm64' or jit.arch == 'arm') then jit.off() end - - require "love.timer" - require "love.thread" - require 'love.filesystem' - require "engine/object" - require "engine/string_packer" - - --vars needed for sound manager thread - CHANNEL = love.thread.getChannel("save_request") - - talisman = "]] .. Talisman.config_file.break_infinity .. [[" - - --untested - function tal_compress_and_save(_file, _data) - local save_string = type(_data) == 'table' and STR_PACK(_data) or _data - local fallback_save = STR_PACK({GAME = {won = true}}) --just bare minimum to not crash, maybe eventually display some info? - if talisman == 'bignumber' then - fallback_save = "if not BigMeta then " .. fallback_save - elseif talisman == 'omeganum' then - fallback_save = "if not OmegaMeta then " .. fallback_save - else - fallback_save = "if BigMeta or OmegaMeta then " .. fallback_save - end - fallback_save = fallback_save .. " end" - save_string = fallback_save .. " " .. save_string - save_string = love.data.compress('string', 'deflate', save_string, 1) - love.filesystem.write(_file,save_string) - end - - while true do - --Monitor the channel for any new requests - local request = CHANNEL:demand() -- Value from channel - if request then - --Saves progress for settings, unlocks, alerts and discoveries - if request.type == 'save_progress' then - local prefix_profile = (request.save_progress.SETTINGS.profile or 1)..'' - if not love.filesystem.getInfo(prefix_profile) then love.filesystem.createDirectory( prefix_profile ) end - prefix_profile = prefix_profile..'/' - - if not love.filesystem.getInfo(prefix_profile..'meta.jkr') then - love.filesystem.append( prefix_profile..'meta.jkr', 'return {}' ) - end - - local meta = STR_UNPACK(get_compressed(prefix_profile..'meta.jkr') or 'return {}') - meta.unlocked = meta.unlocked or {} - meta.discovered = meta.discovered or {} - meta.alerted = meta.alerted or {} - - local _append = false - - for k, v in pairs(request.save_progress.UDA) do - if string.find(v, 'u') and not meta.unlocked[k] then - meta.unlocked[k] = true - _append = true - end - if string.find(v, 'd') and not meta.discovered[k] then - meta.discovered[k] = true - _append = true - end - if string.find(v, 'a') and not meta.alerted[k] then - meta.alerted[k] = true - _append = true - end - end - if _append then compress_and_save( prefix_profile..'meta.jkr', STR_PACK(meta)) end - - compress_and_save('settings.jkr', request.save_progress.SETTINGS) - compress_and_save(prefix_profile..'profile.jkr', request.save_progress.PROFILE) - - CHANNEL:push('done') - --Saves the settings file - elseif request.type == 'save_settings' then - compress_and_save('settings.jkr', request.save_settings) - compress_and_save(request.profile_num..'/profile.jkr', request.save_profile) - --Saves the metrics file - elseif request.type == 'save_metrics' then - compress_and_save('metrics.jkr', request.save_metrics) - --Saves any notifications - elseif request.type == 'save_notify' then - local prefix_profile = (request.profile_num or 1)..'' - if not love.filesystem.getInfo(prefix_profile) then love.filesystem.createDirectory( prefix_profile ) end - prefix_profile = prefix_profile..'/' - - if not love.filesystem.getInfo(prefix_profile..'unlock_notify.jkr') then love.filesystem.append( prefix_profile..'unlock_notify.jkr', '') end - local unlock_notify = get_compressed(prefix_profile..'unlock_notify.jkr') or '' - - if request.save_notify and not string.find(unlock_notify, request.save_notify) then - compress_and_save( prefix_profile..'unlock_notify.jkr', unlock_notify..request.save_notify..'\n') - end - - --Saves the run - elseif request.type == 'save_run' then - local prefix_profile = (request.profile_num or 1)..'' - if not love.filesystem.getInfo(prefix_profile) then love.filesystem.createDirectory( prefix_profile ) end - prefix_profile = prefix_profile..'/' - - tal_compress_and_save(prefix_profile..'save.jkr', request.save_table) - end - end - end]]), - channel = love.thread.getChannel('save_request') - } - G.SAVE_MANAGER.thread:start(2) - boot_timer('savemanager', 'shaders',0.4) - - --call the http manager - G.HTTP_MANAGER = { - thread = love.thread.newThread('engine/http_manager.lua'), - out_channel = love.thread.getChannel('http_request'), - in_channel = love.thread.getChannel('http_response') - } - if G.F_HTTP_SCORES then - G.HTTP_MANAGER.thread:start() - end - - --Load all shaders from resources - self.SHADERS = {} - local shader_files = love.filesystem.getDirectoryItems("resources/shaders") - for k, filename in ipairs(shader_files) do - local extension = string.sub(filename, -3) - if extension == '.fs' then - local shader_name = string.sub(filename, 1, -4) - self.SHADERS[shader_name] = love.graphics.newShader("resources/shaders/"..filename) - end - end - - boot_timer('shaders', 'controllers',0.7) - - --Input handler/controller for game objects - self.CONTROLLER = Controller() - love.joystick.loadGamepadMappings("resources/gamecontrollerdb.txt") - if self.F_RUMBLE then - local joysticks = love.joystick.getJoysticks() - if joysticks then - if joysticks[1] then - self.CONTROLLER:set_gamepad(joysticks[2] or joysticks[1]) - end - end - end - boot_timer('controllers', 'localization',0.8) - - if self.SETTINGS.GRAPHICS.texture_scaling then - self.SETTINGS.GRAPHICS.texture_scaling = self.SETTINGS.GRAPHICS.texture_scaling > 1 and 2 or 1 - end - - self:load_profile(G.SETTINGS.profile or 1) - - self.SETTINGS.QUEUED_CHANGE = {} - self.SETTINGS.music_control = {desired_track = '', current_track = '', lerp = 1} - - self:set_render_settings() - - self:set_language() - - self:init_item_prototypes() - boot_timer('protos', 'shared sprites',0.9) - - --For globally shared sprites - self.shared_debuff = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["centers"], {x=4, y = 0}) - - self.shared_soul = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["centers"], self.P_CENTERS.soul.pos) - self.shared_undiscovered_joker = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["centers"], self.P_CENTERS.undiscovered_joker.pos) - self.shared_undiscovered_tarot = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["centers"], self.P_CENTERS.undiscovered_tarot.pos) - - self.shared_sticker_eternal = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["stickers"], {x = 0,y = 0}) - self.shared_sticker_perishable = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["stickers"], {x = 0,y = 2}) - self.shared_sticker_rental = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["stickers"], {x = 1,y = 2}) - - self.shared_stickers = { - White = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["stickers"], {x = 1,y = 0}), - Red = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["stickers"], {x = 2,y = 0}), - Green = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["stickers"], {x = 3,y = 0}), - Black = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["stickers"], {x = 0,y = 1}), - Blue = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["stickers"], {x = 4,y = 0}), - Purple = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["stickers"], {x = 1,y = 1}), - Orange = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["stickers"], {x = 2,y = 1}), - Gold = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["stickers"], {x = 3,y = 1}) - } - self.shared_seals = { - Gold = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["centers"], {x = 2,y = 0}), - Purple = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["centers"], {x = 4,y = 4}), - Red = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["centers"], {x = 5,y = 4}), - Blue = Sprite(0, 0, self.CARD_W, self.CARD_H, self.ASSET_ATLAS["centers"], {x = 6,y = 4}), - } - self.sticker_map = { - 'White','Red','Green','Black','Blue','Purple','Orange','Gold' - } - boot_timer('shared sprites', 'prep stage',0.95) - - --For the visible cursor - G.STAGE_OBJECT_INTERRUPT =true - self.CURSOR = Sprite(0,0,0.3, 0.3, self.ASSET_ATLAS['gamepad_ui'], {x = 18, y = 0}) - self.CURSOR.states.collide.can = false - G.STAGE_OBJECT_INTERRUPT = false - - --Create the event manager for the game - self.E_MANAGER = EventManager() - self.SPEEDFACTOR = 1 - initSteamodded() - - for i = 1, #G.CHALLENGES do - if (G.CHALLENGES[i].id == 'c_cry_rush_hour' or G.CHALLENGES[i].id == 'c_cry_rush_hour_ii' or G.CHALLENGES[i].id == 'c_cry_rush_hour_iii') and #G.CHALLENGES[i].restrictions.banned_other == 0 then - for k, v in pairs(G.P_BLINDS) do - if k ~= "bl_cry_clock" and k ~= "bl_cry_lavender_loop" and v.boss then - G.CHALLENGES[i].restrictions.banned_other[#G.CHALLENGES[i].restrictions.banned_other+1] = {id = k, type = 'blind'} - end - end - end - end - set_profile_progress() - Cartomancer.load_mod_file('internal/localization.lua', 'localization') - boot_timer('prep stage', 'splash prep',1) - self:splash_screen() - boot_timer('splash prep', 'end',1) -end - -function Game:init_item_prototypes() - --Initialize all prototypes for units/items - self.P_SEALS = { - Red = {order = 1, discovered = false, set = "Seal"}, - Blue = {order = 2, discovered = false, set = "Seal"}, - Gold = {order = 3, discovered = false, set = "Seal"}, - Purple = {order = 4, discovered = false, set = "Seal"}, - } - - self.P_TAGS = { - tag_uncommon = {name = 'Uncommon Tag', set = 'Tag', discovered = false, min_ante = nil, order = 1, config = {type = 'store_joker_create'}, pos = {x = 0,y = 0}}, - tag_rare = {name = 'Rare Tag', set = 'Tag', discovered = false, min_ante = nil, order = 2, config = {type = 'store_joker_create', odds = 3}, requires = 'j_blueprint', pos = {x = 1,y = 0}}, - tag_negative = {name = 'Negative Tag', set = 'Tag', discovered = false, min_ante = 2, order = 3, config = {type = 'store_joker_modify', edition = 'negative', odds = 5}, requires = 'e_negative', pos = {x = 2, y = 0}}, - tag_foil = {name = 'Foil Tag', set = 'Tag', discovered = false, min_ante = nil, order = 4, config = {type = 'store_joker_modify', edition = 'foil', odds = 2}, requires = 'e_foil', pos = {x = 3,y = 0}}, - tag_holo = {name = 'Holographic Tag', set = 'Tag', discovered = false, min_ante = nil, order = 5, config = {type = 'store_joker_modify', edition = 'holo', odds = 3}, requires = 'e_holo', pos = {x = 0,y = 1}}, - tag_polychrome = {name = 'Polychrome Tag', set = 'Tag', discovered = false, min_ante = nil, order = 6, config = {type = 'store_joker_modify', edition = 'polychrome', odds = 4}, requires = 'e_polychrome', pos = {x = 1,y = 1}}, - tag_investment = {name = 'Investment Tag', set = 'Tag', discovered = false, min_ante = nil, order = 7, config = {type = 'eval', dollars = 25}, pos = {x = 2,y = 1}}, - tag_voucher = {name = 'Voucher Tag', set = 'Tag', discovered = false, min_ante = nil, order = 8, config = {type = 'voucher_add'}, pos = {x = 3,y = 1}}, - tag_boss = {name = 'Boss Tag', set = 'Tag', discovered = false, min_ante = nil, order = 9, config = {type = 'new_blind_choice', }, pos = {x = 0,y = 2}}, - tag_standard = {name = 'Standard Tag', set = 'Tag', discovered = false, min_ante = 2, order = 10, config = {type = 'new_blind_choice', }, pos = {x = 1,y = 2}}, - tag_charm = {name = 'Charm Tag', set = 'Tag', discovered = false, min_ante = nil, order = 11, config = {type = 'new_blind_choice', }, pos = {x = 2,y = 2}}, - tag_meteor = {name = 'Meteor Tag', set = 'Tag', discovered = false, min_ante = 2, order = 12, config = {type = 'new_blind_choice', }, pos = {x = 3,y = 2}}, - tag_buffoon = {name = 'Buffoon Tag', set = 'Tag', discovered = false, min_ante = 2, order = 13, config = {type = 'new_blind_choice', }, pos = {x = 4,y = 2}}, - tag_handy = {name = 'Handy Tag', set = 'Tag', discovered = false, min_ante = 2, order = 14, config = {type = 'immediate', dollars_per_hand = 1}, pos = {x = 1,y = 3}}, - tag_garbage = {name = 'Garbage Tag', set = 'Tag', discovered = false, min_ante = 2, order = 15, config = {type = 'immediate', dollars_per_discard = 1}, pos = {x = 2,y = 3}}, - tag_ethereal = {name = 'Ethereal Tag', set = 'Tag', discovered = false, min_ante = 2, order = 16, config = {type = 'new_blind_choice'}, pos = {x = 3,y = 3}}, - tag_coupon = {name = 'Coupon Tag', set = 'Tag', discovered = false, min_ante = nil, order = 17, config = {type = 'shop_final_pass', }, pos = {x = 4,y = 0}}, - tag_double = {name = 'Double Tag', set = 'Tag', discovered = false, min_ante = nil, order = 18, config = {type = 'tag_add', }, pos = {x = 5,y = 0}}, - tag_juggle = {name = 'Juggle Tag', set = 'Tag', discovered = false, min_ante = nil, order = 19, config = {type = 'round_start_bonus', h_size = 3}, pos = {x = 5,y = 1}}, - tag_d_six = {name = 'D6 Tag', set = 'Tag', discovered = false, min_ante = nil, order = 20, config = {type = 'shop_start', }, pos = {x = 5,y = 3}}, - tag_top_up = {name = 'Top-up Tag', set = 'Tag', discovered = false, min_ante = 2, order = 21, config = {type = 'immediate', spawn_jokers = 2}, pos = {x = 4,y = 1}}, - tag_skip = {name = 'Skip Tag', set = 'Tag', discovered = false, min_ante = nil, order = 22, config = {type = 'immediate', skip_bonus = 5}, pos = {x = 0,y = 3}}, - tag_orbital = {name = 'Orbital Tag', set = 'Tag', discovered = false, min_ante = 2, order = 23, config = {type = 'immediate', levels = 3}, pos = {x = 5,y = 2}}, - tag_economy = {name = 'Economy Tag', set = 'Tag', discovered = false, min_ante = nil, order = 24, config = {type = 'immediate', max = 40}, pos = {x = 4,y = 3}}, - } - self.tag_undiscovered = {name = 'Not Discovered', order = 1, config = {type = ''}, pos = {x=3,y=4}} - - self.P_STAKES = { - stake_white = {name = 'White Chip', unlocked = true, order = 1, pos = {x = 0,y = 0}, stake_level = 1, set = 'Stake'}, - stake_red = {name = 'Red Chip', unlocked = false, order = 2, pos = {x = 1,y = 0}, stake_level = 2, set = 'Stake'}, - stake_green = {name = 'Green Chip', unlocked = false, order = 3, pos = {x = 2,y = 0}, stake_level = 3, set = 'Stake'}, - stake_black = {name = 'Black Chip', unlocked = false, order = 4, pos = {x = 4,y = 0}, stake_level = 4, set = 'Stake'}, - stake_blue = {name = 'Blue Chip', unlocked = false, order = 5, pos = {x = 3,y = 0}, stake_level = 5, set = 'Stake'}, - stake_purple = {name = 'Purple Chip', unlocked = false, order = 6, pos = {x = 0,y = 1}, stake_level = 6, set = 'Stake'}, - stake_orange = {name = 'Orange Chip', unlocked = false, order = 7, pos = {x = 1,y = 1}, stake_level = 7, set = 'Stake'}, - stake_gold = {name = 'Gold Chip', unlocked = false, order = 8, pos = {x = 2,y = 1}, stake_level = 8, set = 'Stake'}, - } - - self.P_BLINDS = { - bl_small = {name = 'Small Blind', defeated = false, order = 1, dollars = 3, mult = 1, vars = {}, debuff_text = '', debuff = {}, pos = {x=0, y=0}}, - bl_big = {name = 'Big Blind', defeated = false, order = 2, dollars = 4, mult = 1.5,vars = {}, debuff_text = '', debuff = {}, pos = {x=0, y=1}}, - bl_ox = {name = 'The Ox', defeated = false, order = 4, dollars = 5, mult = 2, vars = {localize('ph_most_played')}, debuff = {}, pos = {x=0, y=2}, boss = {min = 6, max = 10}, boss_colour = HEX('b95b08')}, - bl_hook = {name = 'The Hook', defeated = false, order = 3, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=7}, boss = {min = 1, max = 10}, boss_colour = HEX('a84024')}, - bl_mouth = {name = 'The Mouth', defeated = false, order = 17, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=18}, boss = {min = 2, max = 10}, boss_colour = HEX('ae718e')}, - bl_fish = {name = 'The Fish', defeated = false, order = 10, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=5}, boss = {min = 2, max = 10}, boss_colour = HEX('3e85bd')}, - bl_club = {name = 'The Club', defeated = false, order = 9, dollars = 5, mult = 2, vars = {}, debuff = {suit = 'Clubs'}, pos = {x=0, y=4}, boss = {min = 1, max = 10}, boss_colour = HEX('b9cb92')}, - bl_manacle = {name = 'The Manacle', defeated = false, order = 15, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=8}, boss = {min = 1, max = 10}, boss_colour = HEX('575757')}, - bl_tooth = {name = 'The Tooth', defeated = false, order = 23, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=22}, boss = {min = 3, max = 10}, boss_colour = HEX('b52d2d')}, - bl_wall = {name = 'The Wall', defeated = false, order = 6, dollars = 5, mult = 4, vars = {}, debuff = {}, pos = {x=0, y=9}, boss = {min = 2, max = 10}, boss_colour = HEX('8a59a5')}, - bl_house = {name = 'The House', defeated = false, order = 5, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=3}, boss ={min = 2, max = 10}, boss_colour = HEX('5186a8')}, - bl_mark = {name = 'The Mark', defeated = false, order = 25, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=23}, boss = {min = 2, max = 10}, boss_colour = HEX('6a3847')}, - - bl_final_bell = {name = 'Cerulean Bell',defeated = false, order = 30, dollars = 8, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=26}, boss = {showdown = true, min = 10, max = 10}, boss_colour = HEX('009cfd')}, - bl_wheel = {name = 'The Wheel', defeated = false, order = 7, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=10}, boss = {min = 2, max = 10}, boss_colour = HEX('50bf7c')}, - bl_arm = {name = 'The Arm', defeated = false, order = 8, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=11}, boss = {min = 2, max = 10}, boss_colour = HEX('6865f3')}, - bl_psychic = {name = 'The Psychic', defeated = false, order = 11, dollars = 5, mult = 2, vars = {}, debuff = {h_size_ge = 5}, pos = {x=0, y=12}, boss = {min = 1, max = 10}, boss_colour = HEX('efc03c')}, - bl_goad = {name = 'The Goad', defeated = false, order = 12, dollars = 5, mult = 2, vars = {}, debuff = {suit = 'Spades'}, pos = {x=0, y=13}, boss = {min = 1, max = 10}, boss_colour = HEX('b95c96')}, - bl_water = {name = 'The Water', defeated = false, order = 13, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=14}, boss = {min = 2, max = 10}, boss_colour = HEX('c6e0eb')}, - bl_eye = {name = 'The Eye', defeated = false, order = 16, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=17}, boss = {min = 3, max = 10}, boss_colour = HEX('4b71e4')}, - bl_plant = {name = 'The Plant', defeated = false, order = 18, dollars = 5, mult = 2, vars = {}, debuff = {is_face = 'face'}, pos = {x=0, y=19}, boss = {min = 4, max = 10}, boss_colour = HEX('709284')}, - bl_needle = {name = 'The Needle', defeated = false, order = 21, dollars = 5, mult = 1, vars = {}, debuff = {}, pos = {x=0, y=20}, boss = {min = 2, max = 10}, boss_colour = HEX('5c6e31')}, - bl_head = {name = 'The Head', defeated = false, order = 22, dollars = 5, mult = 2, vars = {}, debuff = {suit = 'Hearts'}, pos = {x=0, y=21}, boss = {min = 1, max = 10}, boss_colour = HEX('ac9db4')}, - bl_final_leaf = {name = 'Verdant Leaf', defeated = false, order = 27, dollars = 8, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=28}, boss = {showdown = true, min = 10, max = 10}, boss_colour = HEX('56a786')}, - bl_final_vessel = {name = 'Violet Vessel',defeated = false, order = 28, dollars = 8, mult = 6, vars = {}, debuff = {}, pos = {x=0, y=29}, boss = {showdown = true, min = 10, max = 10}, boss_colour = HEX('8a71e1')}, - bl_window = {name = 'The Window', defeated = false, order = 14, dollars = 5, mult = 2, vars = {}, debuff = {suit = 'Diamonds'}, pos = {x=0, y=6}, boss = {min = 1, max = 10}, boss_colour = HEX('a9a295')}, - bl_serpent = {name = 'The Serpent', defeated = false, order = 19, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=15}, boss = {min = 5, max = 10}, boss_colour = HEX('439a4f')}, - bl_pillar = {name = 'The Pillar', defeated = false, order = 20, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=16}, boss = {min = 1, max = 10}, boss_colour = HEX('7e6752')}, - bl_flint = {name = 'The Flint', defeated = false, order = 24, dollars = 5, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=24}, boss = {min = 2, max = 10}, boss_colour = HEX('e56a2f')}, - bl_final_acorn = {name = 'Amber Acorn', defeated = false, order = 26, dollars = 8, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=27}, boss = {showdown = true, min = 10, max = 10}, boss_colour = HEX('fda200')}, - bl_final_heart = {name = 'Crimson Heart',defeated = false, order = 29, dollars = 8, mult = 2, vars = {}, debuff = {}, pos = {x=0, y=25}, boss = {showdown = true, min = 10, max = 10}, boss_colour = HEX('ac3232')}, - - } - self.b_undiscovered = {name = 'Undiscovered', debuff_text = 'Defeat this blind to discover', pos = {x=0,y=30}} - - self.P_CARDS = { - H_2={name = "2 of Hearts",value = '2', suit = 'Hearts', pos = {x=0,y=0}}, - H_3={name = "3 of Hearts",value = '3', suit = 'Hearts', pos = {x=1,y=0}}, - H_4={name = "4 of Hearts",value = '4', suit = 'Hearts', pos = {x=2,y=0}}, - H_5={name = "5 of Hearts",value = '5', suit = 'Hearts', pos = {x=3,y=0}}, - H_6={name = "6 of Hearts",value = '6', suit = 'Hearts', pos = {x=4,y=0}}, - H_7={name = "7 of Hearts",value = '7', suit = 'Hearts', pos = {x=5,y=0}}, - H_8={name = "8 of Hearts",value = '8', suit = 'Hearts', pos = {x=6,y=0}}, - H_9={name = "9 of Hearts",value = '9', suit = 'Hearts', pos = {x=7,y=0}}, - H_T={name = "10 of Hearts",value = '10', suit = 'Hearts', pos = {x=8,y=0}}, - H_J={name = "Jack of Hearts",value = 'Jack', suit = 'Hearts', pos = {x=9,y=0}}, - H_Q={name = "Queen of Hearts",value = 'Queen', suit = 'Hearts', pos = {x=10,y=0}}, - H_K={name = "King of Hearts",value = 'King', suit = 'Hearts', pos = {x=11,y=0}}, - H_A={name = "Ace of Hearts",value = 'Ace', suit = 'Hearts', pos = {x=12,y=0}}, - C_2={name = "2 of Clubs",value = '2', suit = 'Clubs', pos = {x=0,y=1}}, - C_3={name = "3 of Clubs",value = '3', suit = 'Clubs', pos = {x=1,y=1}}, - C_4={name = "4 of Clubs",value = '4', suit = 'Clubs', pos = {x=2,y=1}}, - C_5={name = "5 of Clubs",value = '5', suit = 'Clubs', pos = {x=3,y=1}}, - C_6={name = "6 of Clubs",value = '6', suit = 'Clubs', pos = {x=4,y=1}}, - C_7={name = "7 of Clubs",value = '7', suit = 'Clubs', pos = {x=5,y=1}}, - C_8={name = "8 of Clubs",value = '8', suit = 'Clubs', pos = {x=6,y=1}}, - C_9={name = "9 of Clubs",value = '9', suit = 'Clubs', pos = {x=7,y=1}}, - C_T={name = "10 of Clubs",value = '10', suit = 'Clubs', pos = {x=8,y=1}}, - C_J={name = "Jack of Clubs",value = 'Jack', suit = 'Clubs', pos = {x=9,y=1}}, - C_Q={name = "Queen of Clubs",value = 'Queen', suit = 'Clubs', pos = {x=10,y=1}}, - C_K={name = "King of Clubs",value = 'King', suit = 'Clubs', pos = {x=11,y=1}}, - C_A={name = "Ace of Clubs",value = 'Ace', suit = 'Clubs', pos = {x=12,y=1}}, - D_2={name = "2 of Diamonds",value = '2', suit = 'Diamonds', pos = {x=0,y=2}}, - D_3={name = "3 of Diamonds",value = '3', suit = 'Diamonds', pos = {x=1,y=2}}, - D_4={name = "4 of Diamonds",value = '4', suit = 'Diamonds', pos = {x=2,y=2}}, - D_5={name = "5 of Diamonds",value = '5', suit = 'Diamonds', pos = {x=3,y=2}}, - D_6={name = "6 of Diamonds",value = '6', suit = 'Diamonds', pos = {x=4,y=2}}, - D_7={name = "7 of Diamonds",value = '7', suit = 'Diamonds', pos = {x=5,y=2}}, - D_8={name = "8 of Diamonds",value = '8', suit = 'Diamonds', pos = {x=6,y=2}}, - D_9={name = "9 of Diamonds",value = '9', suit = 'Diamonds', pos = {x=7,y=2}}, - D_T={name = "10 of Diamonds",value = '10', suit = 'Diamonds', pos = {x=8,y=2}}, - D_J={name = "Jack of Diamonds",value = 'Jack', suit = 'Diamonds', pos = {x=9,y=2}}, - D_Q={name = "Queen of Diamonds",value = 'Queen', suit = 'Diamonds', pos = {x=10,y=2}}, - D_K={name = "King of Diamonds",value = 'King', suit = 'Diamonds', pos = {x=11,y=2}}, - D_A={name = "Ace of Diamonds",value = 'Ace', suit = 'Diamonds', pos = {x=12,y=2}}, - S_2={name = "2 of Spades",value = '2', suit = 'Spades', pos = {x=0,y=3}}, - S_3={name = "3 of Spades",value = '3', suit = 'Spades', pos = {x=1,y=3}}, - S_4={name = "4 of Spades",value = '4', suit = 'Spades', pos = {x=2,y=3}}, - S_5={name = "5 of Spades",value = '5', suit = 'Spades', pos = {x=3,y=3}}, - S_6={name = "6 of Spades",value = '6', suit = 'Spades', pos = {x=4,y=3}}, - S_7={name = "7 of Spades",value = '7', suit = 'Spades', pos = {x=5,y=3}}, - S_8={name = "8 of Spades",value = '8', suit = 'Spades', pos = {x=6,y=3}}, - S_9={name = "9 of Spades",value = '9', suit = 'Spades', pos = {x=7,y=3}}, - S_T={name = "10 of Spades",value = '10', suit = 'Spades', pos = {x=8,y=3}}, - S_J={name = "Jack of Spades",value = 'Jack', suit = 'Spades', pos = {x=9,y=3}}, - S_Q={name = "Queen of Spades",value = 'Queen', suit = 'Spades', pos = {x=10,y=3}}, - S_K={name = "King of Spades",value = 'King', suit = 'Spades', pos = {x=11,y=3}}, - S_A={name = "Ace of Spades",value = 'Ace', suit = 'Spades', pos = {x=12,y=3}}, - } - - self.j_locked = {unlocked = false, max = 1, name = "Locked", pos = {x=8,y=9}, set = "Joker", cost_mult = 1.0,config = {}} - self.v_locked = {unlocked = false, max = 1, name = "Locked", pos = {x=8,y=3}, set = "Voucher", cost_mult = 1.0,config = {}} - self.c_locked = {unlocked = false, max = 1, name = "Locked", pos = {x=4,y=2}, set = "Tarot", cost_mult = 1.0,config = {}} - self.j_undiscovered = {unlocked = false, max = 1, name = "Locked", pos = {x=9,y=9}, set = "Joker", cost_mult = 1.0,config = {}} - self.t_undiscovered = {unlocked = false, max = 1, name = "Locked", pos = {x=6,y=2}, set = "Tarot", cost_mult = 1.0,config = {}} - self.p_undiscovered = {unlocked = false, max = 1, name = "Locked", pos = {x=7,y=2}, set = "Planet", cost_mult = 1.0,config = {}} - self.s_undiscovered = {unlocked = false, max = 1, name = "Locked", pos = {x=5,y=2}, set = "Spectral", cost_mult = 1.0,config = {}} - self.v_undiscovered = {unlocked = false, max = 1, name = "Locked", pos = {x=8,y=2}, set = "Voucher", cost_mult = 1.0,config = {}} - self.booster_undiscovered = {unlocked = false, max = 1, name = "Locked", pos = {x=0,y=5}, set = "Booster", cost_mult = 1.0,config = {}} - - self.P_CENTERS = { - c_base={max = 500, freq = 1, line = 'base', name = "Default Base", pos = {x=1,y=0}, set = "Default", label = 'Base Card', effect = "Base", cost_mult = 1.0, config = {}}, - - --Jokers - j_joker= {order = 1, unlocked = true, start_alerted = true, discovered = true, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 2, name = "Joker", pos = {x=0,y=0}, set = "Joker", effect = "Mult", cost_mult = 1.0, config = {mult = 4}}, - j_greedy_joker= {order = 2, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "Greedy Joker", pos = {x=6,y=1}, set = "Joker", effect = "Suit Mult", cost_mult = 1.0, config = {extra = {s_mult = 3, suit = 'Diamonds'}}}, - j_lusty_joker= {order = 3, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "Lusty Joker", pos = {x=7,y=1}, set = "Joker", effect = "Suit Mult", cost_mult = 1.0, config = {extra = {s_mult = 3, suit = 'Hearts'}}}, - j_wrathful_joker= {order = 4, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "Wrathful Joker", pos = {x=8,y=1}, set = "Joker", effect = "Suit Mult", cost_mult = 1.0, config = {extra = {s_mult = 3, suit = 'Spades'}}}, - j_gluttenous_joker= {order = 5, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "Gluttonous Joker", pos = {x=9,y=1}, set = "Joker", effect = "Suit Mult", cost_mult = 1.0, config = {extra = {s_mult = 3, suit = 'Clubs'}}}, - j_jolly= {order = 6, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 3, name = "Jolly Joker", pos = {x=2,y=0}, set = "Joker", effect = "Type Mult", cost_mult = 1.0, config = {t_mult = 8, type = 'Pair'}}, - j_zany= {order = 7, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Zany Joker", pos = {x=3,y=0}, set = "Joker", effect = "Type Mult", cost_mult = 1.0, config = {t_mult = 12, type = 'Three of a Kind'}}, - j_mad= {order = 8, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Mad Joker", pos = {x=4,y=0}, set = "Joker", effect = "Type Mult", cost_mult = 1.0, config = {t_mult = 10, type = 'Two Pair'}}, - j_crazy= {order = 9, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Crazy Joker", pos = {x=5,y=0}, set = "Joker", effect = "Type Mult", cost_mult = 1.0, config = {t_mult = 12, type = 'Straight'}}, - j_droll= {order = 10, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Droll Joker", pos = {x=6,y=0}, set = "Joker", effect = "Type Mult", cost_mult = 1.0, config = {t_mult = 10, type = 'Flush'}}, - j_sly= {order = 11, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 3, name = "Sly Joker",set = "Joker", config = {t_chips = 50, type = 'Pair'}, pos = {x=0,y=14}}, - j_wily= {order = 12, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Wily Joker",set = "Joker", config = {t_chips = 100, type = 'Three of a Kind'}, pos = {x=1,y=14}}, - j_clever= {order = 13, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Clever Joker",set = "Joker", config = {t_chips = 80, type = 'Two Pair'}, pos = {x=2,y=14}}, - j_devious= {order = 14, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Devious Joker",set = "Joker", config = {t_chips = 100, type = 'Straight'}, pos = {x=3,y=14}}, - j_crafty= {order = 15, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Crafty Joker",set = "Joker", config = {t_chips = 80, type = 'Flush'}, pos = {x=4,y=14}}, - - j_half= {order = 16, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "Half Joker", pos = {x=7,y=0}, set = "Joker", effect = "Hand Size Mult", cost_mult = 1.0, config = {extra = {mult = 20, size = 3}}}, - j_stencil= {order = 17, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 8, name = "Joker Stencil", pos = {x=2,y=5}, set = "Joker", effect = "Hand Size Mult", cost_mult = 1.0, config = {}}, - j_four_fingers= {order = 18, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Four Fingers", pos = {x=6,y=6}, set = "Joker", effect = "", config = {}}, - j_mime= {order = 19, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 5, name = "Mime", pos = {x=4,y=1}, set = "Joker", effect = "Hand card double", cost_mult = 1.0, config = {extra = 1}}, - j_credit_card= {order = 20, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 1, name = "Credit Card", pos = {x=5,y=1}, set = "Joker", effect = "Credit", cost_mult = 1.0, config = {extra = 20}}, - j_ceremonial= {order = 21, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 2, cost = 6, name = "Ceremonial Dagger", pos = {x=5,y=5}, set = "Joker", effect = "", config = {mult = 0}}, - j_banner= {order = 22, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "Banner", pos = {x=1,y=2}, set = "Joker", effect = "Discard Chips", cost_mult = 1.0, config = {extra = 30}}, - j_mystic_summit= {order = 23, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "Mystic Summit", pos = {x=2,y=2}, set = "Joker", effect = "No Discard Mult", cost_mult = 1.0, config = {extra = {mult = 15, d_remaining = 0}}}, - j_marble= {order = 24, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Marble Joker", pos = {x=3,y=2}, set = "Joker", effect = "Stone card hands", cost_mult = 1.0, config = {extra = 1}}, - j_loyalty_card= {order = 25, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 5, name = "Loyalty Card", pos = {x=4,y=2}, set = "Joker", effect = "1 in 10 mult", cost_mult = 1.0, config = {extra = {Xmult = 4, every = 5, remaining = "5 remaining"}}}, - j_8_ball= {order = 26, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "8 Ball", pos = {x=0,y=5}, set = "Joker", effect = "Spawn Tarot", cost_mult = 1.0, config = {extra=4}}, - j_misprint= {order = 27, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Misprint", pos = {x=6,y=2}, set = "Joker", effect = "Random Mult", cost_mult = 1.0, config = {extra = {max = 23, min = 0}}}, - j_dusk= {order = 28, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 5, name = "Dusk", pos = {x=4,y=7}, set = "Joker", effect = "", config = {extra = 1}, unlock_condition = {type = '', extra = '', hidden = true}}, - j_raised_fist= {order = 29, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "Raised Fist", pos = {x=8,y=2}, set = "Joker", effect = "Socialized Mult", cost_mult = 1.0, config = {}}, - j_chaos= {order = 30, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Chaos the Clown", pos = {x=1,y=0}, set = "Joker", effect = "Bonus Rerolls", cost_mult = 1.0, config = {extra = 1}}, - - j_fibonacci= {order = 31, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 8, name = "Fibonacci", pos = {x=1,y=5}, set = "Joker", effect = "Card Mult", cost_mult = 1.0, config = {extra = 8}}, - j_steel_joker= {order = 32, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Steel Joker", pos = {x=7,y=2}, set = "Joker", effect = "Steel Card Buff", cost_mult = 1.0, config = {extra = 0.2}, enhancement_gate = 'm_steel'}, - j_scary_face= {order = 33, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Scary Face", pos = {x=2,y=3}, set = "Joker", effect = "Scary Face Cards", cost_mult = 1.0, config = {extra = 30}}, - j_abstract= {order = 34, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Abstract Joker", pos = {x=3,y=3}, set = "Joker", effect = "Joker Mult", cost_mult = 1.0, config = {extra = 3}}, - j_delayed_grat= {order = 35, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Delayed Gratification", pos = {x=4,y=3}, set = "Joker", effect = "Discard dollars", cost_mult = 1.0, config = {extra = 2}}, - j_hack= {order = 36, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Hack", pos = {x=5,y=2}, set = "Joker", effect = "Low Card double", cost_mult = 1.0, config = {extra = 1}}, - j_pareidolia= {order = 37, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 5, name = "Pareidolia", pos = {x=6,y=3}, set = "Joker", effect = "All face cards", cost_mult = 1.0, config = {}}, - j_gros_michel= {order = 38, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = false, rarity = 1, cost = 5, name = "Gros Michel", pos = {x=7,y=6}, set = "Joker", effect = "", config = {extra = {odds = 6, mult = 15}}, no_pool_flag = 'gros_michel_extinct'}, - j_even_steven= {order = 39, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Even Steven", pos = {x=8,y=3}, set = "Joker", effect = "Even Card Buff", cost_mult = 1.0, config = {extra = 4}}, - j_odd_todd= {order = 40, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Odd Todd", pos = {x=9,y=3}, set = "Joker", effect = "Odd Card Buff", cost_mult = 1.0, config = {extra = 31}}, - j_scholar= {order = 41, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Scholar", pos = {x=0,y=4}, set = "Joker", effect = "Ace Buff", cost_mult = 1.0, config = {extra = {mult = 4, chips = 20}}}, - j_business= {order = 42, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Business Card", pos = {x=1,y=4}, set = "Joker", effect = "Face Card dollar Chance", cost_mult = 1.0, config = {extra = 2}}, - j_supernova= {order = 43, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "Supernova", pos = {x=2,y=4}, set = "Joker", effect = "Hand played mult", cost_mult = 1.0, config = {extra = 1}}, - j_ride_the_bus= {order = 44, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 1, cost = 6, name = "Ride the Bus", pos = {x=1,y=6}, set = "Joker", effect = "", config = {extra = 1}, unlock_condition = {type = 'discard_custom'}}, - j_space= {order = 45, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 5, name = "Space Joker", pos = {x=3,y=5}, set = "Joker", effect = "Upgrade Hand chance", cost_mult = 1.0, config = {extra = 4}}, - - j_egg= {order = 46, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = 'Egg', pos = {x = 0, y = 10}, set = 'Joker', config = {extra = 3}}, - j_burglar= {order = 47, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = 'Burglar', pos = {x = 1, y = 10}, set = 'Joker', config = {extra = 3}}, - j_blackboard= {order = 48, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = 'Blackboard', pos = {x = 2, y = 10}, set = 'Joker', config = {extra = 3}}, - j_runner= {order = 49, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 1, cost = 5, name = 'Runner', pos = {x = 3, y = 10}, set = 'Joker', config = {extra = {chips = 0, chip_mod = 15}}}, - j_ice_cream= {order = 50, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = false, rarity = 1, cost = 5, name = 'Ice Cream', pos = {x = 4, y = 10}, set = 'Joker', config = {extra = {chips = 100, chip_mod = 5}}}, - j_dna= {order = 51, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 8, name = 'DNA', pos = {x = 5, y = 10}, set = 'Joker', config = {}}, - j_splash= {order = 52, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 3, name = 'Splash', pos = {x = 6, y = 10}, set = 'Joker', config = {}}, - j_blue_joker= {order = 53, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = 'Blue Joker', pos = {x = 7, y = 10}, set = 'Joker', config = {extra = 2}}, - j_sixth_sense= {order = 54, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = 'Sixth Sense', pos = {x = 8, y = 10}, set = 'Joker', config = {}}, - j_constellation= {order = 55, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 2, cost = 6, name = 'Constellation', pos = {x = 9, y = 10}, set = 'Joker', config = {extra = 0.1, Xmult = 1}}, - j_hiker= {order = 56, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 5, name = 'Hiker', pos = {x = 0, y = 11}, set = 'Joker', config = {extra = 5}}, - j_faceless= {order = 57, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = 'Faceless Joker', pos = {x = 1, y = 11}, set = 'Joker', config = {extra = {dollars = 5, faces = 3}}}, - j_green_joker= {order = 58, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 1, cost = 4, name = 'Green Joker', pos = {x = 2, y = 11}, set = 'Joker', config = {extra = {hand_add = 1, discard_sub = 1}}}, - j_superposition= {order = 59, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = 'Superposition', pos = {x = 3, y = 11}, set = 'Joker', config = {}}, - j_todo_list= {order = 60, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = 'To Do List', pos = {x = 4, y = 11}, set = 'Joker', config = {extra = {dollars = 4, poker_hand = 'High Card'}}}, - - j_cavendish= {order = 61, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = false, rarity = 1, cost = 4, name = "Cavendish", pos = {x=5,y=11}, set = "Joker", cost_mult = 1.0, config = {extra = {odds = 1000, Xmult = 3}}, yes_pool_flag = 'gros_michel_extinct'}, - j_card_sharp= {order = 62, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Card Sharp", pos = {x=6,y=11}, set = "Joker", cost_mult = 1.0, config = {extra = {Xmult = 3}}}, - j_red_card= {order = 63, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 1, cost = 5, name = "Red Card", pos = {x=7,y=11}, set = "Joker", cost_mult = 1.0, config = {extra = 3}}, - j_madness= {order = 64, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 2, cost = 7, name = "Madness", pos = {x=8,y=11}, set = "Joker", cost_mult = 1.0, config = {extra = 0.5}}, - j_square= {order = 65, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 1, cost = 4, name = "Square Joker", pos = {x=9,y=11}, set = "Joker", cost_mult = 1.0, config = {extra = {chips = 0, chip_mod = 4}}}, - j_seance= {order = 66, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Seance", pos = {x=0,y=12}, set = "Joker", cost_mult = 1.0, config = {extra = {poker_hand = 'Straight Flush'}}}, - j_riff_raff= {order = 67, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 6, name = "Riff-raff", pos = {x=1,y=12}, set = "Joker", cost_mult = 1.0, config = {extra = 2}}, - j_vampire= {order = 68, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 2, cost = 7, name = "Vampire",set = "Joker", config = {extra = 0.1, Xmult = 1}, pos = {x=2,y=12}}, - j_shortcut= {order = 69, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Shortcut",set = "Joker", config = {}, pos = {x=3,y=12}}, - j_hologram= {order = 70, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 2, cost = 7, name = "Hologram",set = "Joker", config = {extra = 0.25, Xmult = 1}, pos = {x=4,y=12}, soul_pos = {x=2, y=9},}, - j_vagabond= {order = 71, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 8, name = "Vagabond",set = "Joker", config = {extra = 4}, pos = {x=5,y=12}}, - j_baron= {order = 72, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 8, name = "Baron",set = "Joker", config = {extra = 1.5}, pos = {x=6,y=12}}, - j_cloud_9= {order = 73, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Cloud 9",set = "Joker", config = {extra = 1}, pos = {x=7,y=12}}, - j_rocket= {order = 74, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = false, eternal_compat = true, rarity = 2, cost = 6, name = "Rocket",set = "Joker", config = {extra = {dollars = 1, increase = 2}}, pos = {x=8,y=12}}, - j_obelisk= {order = 75, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 3, cost = 8, name = "Obelisk",set = "Joker", config = {extra = 0.2, Xmult = 1}, pos = {x=9,y=12}}, - - j_midas_mask= {order = 76, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Midas Mask",set = "Joker", config = {}, pos = {x=0,y=13}}, - j_luchador= {order = 77, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = false, rarity = 2, cost = 5, name = "Luchador",set = "Joker", config = {}, pos = {x=1,y=13}}, - j_photograph= {order = 78, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "Photograph",set = "Joker", config = {extra = 2}, pos = {x=2,y=13}}, - j_gift= {order = 79, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Gift Card",set = "Joker", config = {extra = 1}, pos = {x=3,y=13}}, - j_turtle_bean= {order = 80, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = false, rarity = 2, cost = 6, name = "Turtle Bean",set = "Joker", config = {extra = {h_size = 5, h_mod = 1}}, pos = {x=4,y=13}}, - j_erosion= {order = 81, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Erosion",set = "Joker", config = {extra = 4}, pos = {x=5,y=13}}, - j_reserved_parking= {order = 82, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 6, name = "Reserved Parking",set = "Joker", config = {extra = {odds = 2, dollars = 1}}, pos = {x=6,y=13}}, - j_mail= {order = 83, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Mail-In Rebate",set = "Joker", config = {extra = 5}, pos = {x=7,y=13}}, - j_to_the_moon= {order = 84, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 5, name = "To the Moon",set = "Joker", config = {extra = 1}, pos = {x=8,y=13}}, - j_hallucination= {order = 85, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Hallucination",set = "Joker", config = {extra = 2}, pos = {x=9,y=13}}, - j_fortune_teller= {order = 86, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 6, name = "Fortune Teller", pos = {x=7,y=5}, set = "Joker", effect = "", config = {extra = 1}}, - j_juggler= {order = 87, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Juggler", pos = {x=0,y=1}, set = "Joker", effect = "Hand Size", cost_mult = 1.0, config = {h_size = 1}}, - j_drunkard= {order = 88, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Drunkard", pos = {x=1,y=1}, set = "Joker", effect = "Discard Size", cost_mult = 1.0, config = {d_size = 1}}, - j_stone= {order = 89, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Stone Joker", pos = {x=9,y=0}, set = "Joker", effect = "Stone Card Buff", cost_mult = 1.0, config = {extra = 25}, enhancement_gate = 'm_stone'}, - j_golden= {order = 90, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 6, name = "Golden Joker", pos = {x=9,y=2}, set = "Joker", effect = "Bonus dollars", cost_mult = 1.0, config = {extra = 4}}, - - j_lucky_cat= {order = 91, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 2, cost = 6, name = "Lucky Cat",set = "Joker", config = {Xmult = 1, extra = 0.25}, pos = {x=5,y=14}, enhancement_gate = 'm_lucky'}, - j_baseball= {order = 92, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 8, name = "Baseball Card",set = "Joker", config = {extra = 1.5}, pos = {x=6,y=14}}, - j_bull= {order = 93, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Bull",set = "Joker", config = {extra = 2}, pos = {x=7,y=14}}, - j_diet_cola= {order = 94, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = false, rarity = 2, cost = 6, name = "Diet Cola",set = "Joker", config = {}, pos = {x=8,y=14}}, - j_trading= {order = 95, unlocked = true, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Trading Card",set = "Joker", config = {extra = 3}, pos = {x=9,y=14}}, - j_flash= {order = 96, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 2, cost = 5, name = "Flash Card",set = "Joker", config = {extra = 2, mult = 0}, pos = {x=0,y=15}}, - j_popcorn= {order = 97, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = false, rarity = 1, cost = 5, name = "Popcorn",set = "Joker", config = {mult = 20, extra = 4}, pos = {x=1,y=15}}, - j_trousers= {order = 98, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 2, cost = 6, name = "Spare Trousers",set = "Joker", config = {extra = 2}, pos = {x=4,y=15}}, - j_ancient= {order = 99, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 8, name = "Ancient Joker",set = "Joker", config = {extra = 1.5}, pos = {x=7,y=15}}, - j_ramen= {order = 100, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = false, rarity = 2, cost = 6, name = "Ramen",set = "Joker", config = {Xmult = 2, extra = 0.01}, pos = {x=2,y=15}}, - j_walkie_talkie= {order = 101, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Walkie Talkie",set = "Joker", config = {extra = {chips = 10, mult = 4}}, pos = {x=8,y=15}}, - j_selzer= {order = 102, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = false, rarity = 2, cost = 6, name = "Seltzer",set = "Joker", config = {extra = 10}, pos = {x=3,y=15}}, - j_castle= {order = 103, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 2, cost = 6, name = "Castle",set = "Joker", config = {extra = {chips = 0, chip_mod = 3}}, pos = {x=9,y=15}}, - j_smiley= {order = 104, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Smiley Face",set = "Joker", config = {extra = 5}, pos = {x=6,y=15}}, - j_campfire= {order = 105, unlocked = true, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 9, name = "Campfire",set = "Joker", config = {extra = 0.25}, pos = {x=5,y=15}}, - - j_ticket= {order = 106, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "Golden Ticket", pos = {x=5,y=3}, set = "Joker", effect = "dollars for Gold cards", cost_mult = 1.0, config = {extra = 4},unlock_condition = {type = 'hand_contents', extra = 'Gold'}, enhancement_gate = 'm_gold'}, - j_mr_bones= {order = 107, unlocked = false, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = false, rarity = 2, cost = 5, name = "Mr. Bones", pos = {x=3,y=4}, set = "Joker", effect = "Prevent Death", cost_mult = 1.0, config = {},unlock_condition = {type = 'c_losses', extra = 5}}, - j_acrobat= {order = 108, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Acrobat", pos = {x=2,y=1}, set = "Joker", effect = "Shop size", cost_mult = 1.0, config = {extra = 3},unlock_condition = {type = 'c_hands_played', extra = 200}}, - j_sock_and_buskin= {order = 109, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Sock and Buskin", pos = {x=3,y=1}, set = "Joker", effect = "Face card double", cost_mult = 1.0, config = {extra = 1},unlock_condition = {type = 'c_face_cards_played', extra = 300}}, - j_swashbuckler= {order = 110, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Swashbuckler", pos = {x=9,y=5}, set = "Joker", effect = "Set Mult", cost_mult = 1.0, config = {mult = 1},unlock_condition = {type = 'c_jokers_sold', extra = 20}}, - j_troubadour= {order = 111, unlocked = false, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Troubadour", pos = {x=0,y=2}, set = "Joker", effect = "Hand Size, Plays", cost_mult = 1.0, config = {extra = {h_size = 2, h_plays = -1}}, unlock_condition = {type = 'round_win', extra = 5}}, - j_certificate= {order = 112, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Certificate", pos = {x=8,y=8}, set = "Joker", effect = "", config = {}, unlock_condition = {type = 'double_gold'}}, - j_smeared= {order = 113, unlocked = false, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Smeared Joker", pos = {x=4,y=6}, set = "Joker", effect = "", config = {}, unlock_condition = {type = 'modify_deck', extra = {count = 3, enhancement = 'Wild Card', e_key = 'm_wild'}}}, - j_throwback= {order = 114, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Throwback", pos = {x=5,y=7}, set = "Joker", effect = "", config = {extra = 0.25}, unlock_condition = {type = 'continue_game'}}, - j_hanging_chad= {order = 115, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 4, name = "Hanging Chad", pos = {x=9,y=6}, set = "Joker", effect = "", config = {extra = 2}, unlock_condition = {type = 'round_win', extra = 'High Card'}}, - j_rough_gem= {order = 116, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Rough Gem", pos = {x=9,y=7}, set = "Joker", effect = "", config = {extra = 1}, unlock_condition = {type = 'modify_deck', extra = {count = 30, suit = 'Diamonds'}}}, - j_bloodstone= {order = 117, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Bloodstone", pos = {x=0,y=8}, set = "Joker", effect = "", config = {extra = {odds = 2, Xmult = 1.5}}, unlock_condition = {type = 'modify_deck', extra = {count = 30, suit = 'Hearts'}}}, - j_arrowhead= {order = 118, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Arrowhead", pos = {x=1,y=8}, set = "Joker", effect = "", config = {extra = 50}, unlock_condition = {type = 'modify_deck', extra = {count = 30, suit = 'Spades'}}}, - j_onyx_agate= {order = 119, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Onyx Agate", pos = {x=2,y=8}, set = "Joker", effect = "", config = {extra = 7}, unlock_condition = {type = 'modify_deck', extra = {count = 30, suit = 'Clubs'}}}, - j_glass= {order = 120, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 2, cost = 6, name = "Glass Joker", pos = {x=1,y=3}, set = "Joker", effect = "Glass Card", cost_mult = 1.0, config = {extra = 0.75, Xmult = 1}, unlock_condition = {type = 'modify_deck', extra = {count = 5, enhancement = 'Glass Card', e_key = 'm_glass'}}, enhancement_gate = 'm_glass'}, - - j_ring_master= {order = 121, unlocked = false, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 5, name = "Showman", pos = {x=6,y=5}, set = "Joker", effect = "", config = {}, unlock_condition = {type = 'ante_up', ante = 4}}, - j_flower_pot= {order = 122, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Flower Pot", pos = {x=0,y=6}, set = "Joker", effect = "", config = {extra = 3}, unlock_condition = {type = 'ante_up', ante = 8}}, - j_blueprint= {order = 123, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 10,name = "Blueprint", pos = {x=0,y=3}, set = "Joker", effect = "Copycat", cost_mult = 1.0, config = {},unlock_condition = {type = 'win_custom'}}, - j_wee= {order = 124, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = false, eternal_compat = true, rarity = 3, cost = 8, name = "Wee Joker", pos = {x=0,y=0}, set = "Joker", effect = "", config = {extra = {chips = 0, chip_mod = 8}}, unlock_condition = {type = 'win', n_rounds = 18}}, - j_merry_andy= {order = 125, unlocked = false, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Merry Andy", pos = {x=8,y=0}, set = "Joker", effect = "", cost_mult = 1.0, config = {d_size = 3, h_size = -1}, unlock_condition = {type = 'win', n_rounds = 12}}, - j_oops= {order = 126, unlocked = false, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 4, name = "Oops! All 6s", pos = {x=5,y=6}, set = "Joker", effect = "", config = {}, unlock_condition = {type = 'chip_score', chips = 10000}}, - j_idol= {order = 127, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "The Idol", pos = {x=6,y=7}, set = "Joker", effect = "", config = {extra = 2}, unlock_condition = {type = 'chip_score', chips = 1000000}}, - j_seeing_double= {order = 128, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Seeing Double", pos = {x=4,y=4}, set = "Joker", effect = "X1.5 Mult club 7", cost_mult = 1.0, config = {extra = 2},unlock_condition = {type = 'hand_contents', extra = 'four 7 of Clubs'}}, - j_matador= {order = 129, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Matador", pos = {x=4,y=5}, set = "Joker", effect = "", config = {extra = 8}, unlock_condition = {type = 'round_win'}}, - j_hit_the_road= {order = 130, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 8, name = "Hit the Road", pos = {x=8,y=5}, set = "Joker", effect = "Jack Discard Effect", cost_mult = 1.0, config = {extra = 0.5}, unlock_condition = {type = 'discard_custom'}}, - j_duo= {order = 131, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 8, name = "The Duo", pos = {x=5,y=4}, set = "Joker", effect = "X1.5 Mult", cost_mult = 1.0, config = {Xmult = 2, type = 'Pair'}, unlock_condition = {type = 'win_no_hand', extra = 'Pair'}}, - j_trio= {order = 132, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 8, name = "The Trio", pos = {x=6,y=4}, set = "Joker", effect = "X2 Mult", cost_mult = 1.0, config = {Xmult = 3, type = 'Three of a Kind'}, unlock_condition = {type = 'win_no_hand', extra = 'Three of a Kind'}}, - j_family= {order = 133, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 8, name = "The Family", pos = {x=7,y=4}, set = "Joker", effect = "X3 Mult", cost_mult = 1.0, config = {Xmult = 4, type = 'Four of a Kind'}, unlock_condition = {type = 'win_no_hand', extra = 'Four of a Kind'}}, - j_order= {order = 134, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 8, name = "The Order", pos = {x=8,y=4}, set = "Joker", effect = "X3 Mult", cost_mult = 1.0, config = {Xmult = 3, type = 'Straight'}, unlock_condition = {type = 'win_no_hand', extra = 'Straight'}}, - j_tribe= {order = 135, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 8, name = "The Tribe", pos = {x=9,y=4}, set = "Joker", effect = "X3 Mult", cost_mult = 1.0, config = {Xmult = 2, type = 'Flush'}, unlock_condition = {type = 'win_no_hand', extra = 'Flush'}}, - - j_stuntman= {order = 136, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 7, name = "Stuntman", pos = {x=8,y=6}, set = "Joker", effect = "", config = {extra = {h_size = 2, chip_mod = 250}}, unlock_condition = {type = 'chip_score', chips = 100000000}}, - j_invisible= {order = 137, unlocked = false, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = false, rarity = 3, cost = 8, name = "Invisible Joker", pos = {x=1,y=7}, set = "Joker", effect = "", config = {extra = 2}, unlock_condition = {type = 'win_custom'}}, - j_brainstorm= {order = 138, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 10, name = "Brainstorm", pos = {x=7,y=7}, set = "Joker", effect = "Copycat", config = {}, unlock_condition = {type = 'discard_custom'}}, - j_satellite= {order = 139, unlocked = false, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Satellite", pos = {x=8,y=7}, set = "Joker", effect = "", config = {extra = 1}, unlock_condition = {type = 'money', extra = 400}}, - j_shoot_the_moon= {order = 140, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 1, cost = 5, name = "Shoot the Moon", pos = {x=2,y=6}, set = "Joker", effect = "", config = {extra = 13}, unlock_condition = {type = 'play_all_hearts'}}, - j_drivers_license= {order = 141, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 7, name = "Driver's License", pos = {x=0,y=7}, set = "Joker", effect = "", config = {extra = 3}, unlock_condition = {type = 'modify_deck', extra = {count = 16, tally = 'total'}}}, - j_cartomancer= {order = 142, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 6, name = "Cartomancer", pos = {x=7,y=3}, set = "Joker", effect = "Tarot Buff", cost_mult = 1.0, config = {}, unlock_condition = {type = 'discover_amount', tarot_count = 22}}, - j_astronomer= {order = 143, unlocked = false, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 8, name = "Astronomer", pos = {x=2,y=7}, set = "Joker", effect = "", config = {}, unlock_condition = {type = 'discover_amount', planet_count = 12}}, - j_burnt= {order = 144, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 3, cost = 8, name = "Burnt Joker", pos = {x=3,y=7}, set = "Joker", effect = "", config = {h_size = 0, extra = 4}, unlock_condition = {type = 'c_cards_sold', extra = 50}}, - j_bootstraps= {order = 145, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 2, cost = 7, name = "Bootstraps", pos = {x=9,y=8}, set = "Joker", effect = "", config = {extra = {mult = 2, dollars = 5}}, unlock_condition = {type = 'modify_jokers', extra = {polychrome = true, count = 2}}}, - j_caino= {order = 146, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 4, cost = 20, name = "Caino", pos = {x=3,y=8}, soul_pos = {x=3, y=9}, set = "Joker", effect = "", config = {extra = 1}, unlock_condition = {type = '', extra = '', hidden = true}}, - j_triboulet= {order = 147, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 4, cost = 20, name = "Triboulet", pos = {x=4,y=8}, soul_pos = {x=4, y=9}, set = "Joker", effect = "", config = {extra = 2}, unlock_condition = {type = '', extra = '', hidden = true}}, - j_yorick= {order = 148, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 4, cost = 20, name = "Yorick", pos = {x=5,y=8}, soul_pos = {x=5, y=9}, set = "Joker", effect = "", config = {extra = {xmult = 1, discards = 23}}, unlock_condition = {type = '', extra = '', hidden = true}}, - j_chicot= {order = 149, unlocked = false, discovered = false, blueprint_compat = false, perishable_compat = true, eternal_compat = true, rarity = 4, cost = 20, name = "Chicot", pos = {x=6,y=8}, soul_pos = {x=6, y=9}, set = "Joker", effect = "", config = {}, unlock_condition = {type = '', extra = '', hidden = true}}, - j_perkeo= {order = 150, unlocked = false, discovered = false, blueprint_compat = true, perishable_compat = true, eternal_compat = true, rarity = 4, cost = 20, name = "Perkeo", pos = {x=7,y=8}, soul_pos = {x=7, y=9}, set = "Joker", effect = "", config = {}, unlock_condition = {type = '', extra = '', hidden = true}}, - - - - --All Consumeables - - --Tarots - c_fool= {order = 1, discovered = false, cost = 3, consumeable = true, name = "The Fool", pos = {x=0,y=0}, set = "Tarot", effect = "Disable Blind Effect", cost_mult = 1.0, config = {}}, - c_magician= {order = 2, discovered = false, cost = 3, consumeable = true, name = "The Magician", pos = {x=1,y=0}, set = "Tarot", effect = "Enhance", cost_mult = 1.0, config = {mod_conv = 'm_lucky', max_highlighted = 2}}, - c_high_priestess= {order = 3, discovered = false, cost = 3, consumeable = true, name = "The High Priestess", pos = {x=2,y=0}, set = "Tarot", effect = "Round Bonus", cost_mult = 1.0, config = {planets = 2}}, - c_empress= {order = 4, discovered = false, cost = 3, consumeable = true, name = "The Empress", pos = {x=3,y=0}, set = "Tarot", effect = "Enhance", cost_mult = 1.0, config = {mod_conv = 'm_mult', max_highlighted = 2}}, - c_emperor= {order = 5, discovered = false, cost = 3, consumeable = true, name = "The Emperor", pos = {x=4,y=0}, set = "Tarot", effect = "Round Bonus", cost_mult = 1.0, config = {tarots = 2}}, - c_heirophant= {order = 6, discovered = false, cost = 3, consumeable = true, name = "The Hierophant", pos = {x=5,y=0}, set = "Tarot", effect = "Enhance", cost_mult = 1.0, config = {mod_conv = 'm_bonus', max_highlighted = 2}}, - c_lovers= {order = 7, discovered = false, cost = 3, consumeable = true, name = "The Lovers", pos = {x=6,y=0}, set = "Tarot", effect = "Enhance", cost_mult = 1.0, config = {mod_conv = 'm_wild', max_highlighted = 1}}, - c_chariot= {order = 8, discovered = false, cost = 3, consumeable = true, name = "The Chariot", pos = {x=7,y=0}, set = "Tarot", effect = "Enhance", cost_mult = 1.0, config = {mod_conv = 'm_steel', max_highlighted = 1}}, - c_justice= {order = 9, discovered = false, cost = 3, consumeable = true, name = "Justice", pos = {x=8,y=0}, set = "Tarot", effect = "Enhance", cost_mult = 1.0, config = {mod_conv = 'm_glass', max_highlighted = 1}}, - c_hermit= {order = 10, discovered = false, cost = 3, consumeable = true, name = "The Hermit", pos = {x=9,y=0}, set = "Tarot", effect = "Dollar Doubler", cost_mult = 1.0, config = {extra = 20}}, - c_wheel_of_fortune= {order = 11, discovered = false, cost = 3, consumeable = true, name = "The Wheel of Fortune", pos = {x=0,y=1}, set = "Tarot", effect = "Round Bonus", cost_mult = 1.0, config = {extra = 4}}, - c_strength= {order = 12, discovered = false, cost = 3, consumeable = true, name = "Strength", pos = {x=1,y=1}, set = "Tarot", effect = "Round Bonus", cost_mult = 1.0, config = {mod_conv = 'up_rank', max_highlighted = 2}}, - c_hanged_man= {order = 13, discovered = false, cost = 3, consumeable = true, name = "The Hanged Man", pos = {x=2,y=1}, set = "Tarot", effect = "Card Removal", cost_mult = 1.0, config = {remove_card = true, max_highlighted = 2}}, - c_death= {order = 14, discovered = false, cost = 3, consumeable = true, name = "Death", pos = {x=3,y=1}, set = "Tarot", effect = "Card Conversion", cost_mult = 1.0, config = {mod_conv = 'card', max_highlighted = 2, min_highlighted = 2}}, - c_temperance= {order = 15, discovered = false, cost = 3, consumeable = true, name = "Temperance", pos = {x=4,y=1}, set = "Tarot", effect = "Joker Payout", cost_mult = 1.0, config = {extra = 50}}, - c_devil= {order = 16, discovered = false, cost = 3, consumeable = true, name = "The Devil", pos = {x=5,y=1}, set = "Tarot", effect = "Enhance", cost_mult = 1.0, config = {mod_conv = 'm_gold', max_highlighted = 1}}, - c_tower= {order = 17, discovered = false, cost = 3, consumeable = true, name = "The Tower", pos = {x=6,y=1}, set = "Tarot", effect = "Enhance", cost_mult = 1.0, config = {mod_conv = 'm_stone', max_highlighted = 1}}, - c_star= {order = 18, discovered = false, cost = 3, consumeable = true, name = "The Star", pos = {x=7,y=1}, set = "Tarot", effect = "Suit Conversion", cost_mult = 1.0, config = {suit_conv = 'Diamonds', max_highlighted = 3}}, - c_moon= {order = 19, discovered = false, cost = 3, consumeable = true, name = "The Moon", pos = {x=8,y=1}, set = "Tarot", effect = "Suit Conversion", cost_mult = 1.0, config = {suit_conv = 'Clubs', max_highlighted = 3}}, - c_sun= {order = 20, discovered = false, cost = 3, consumeable = true, name = "The Sun", pos = {x=9,y=1}, set = "Tarot", effect = "Suit Conversion", cost_mult = 1.0, config = {suit_conv = 'Hearts', max_highlighted = 3}}, - c_judgement= {order = 21, discovered = false, cost = 3, consumeable = true, name = "Judgement", pos = {x=0,y=2}, set = "Tarot", effect = "Random Joker", cost_mult = 1.0, config = {}}, - c_world= {order = 22, discovered = false, cost = 3, consumeable = true, name = "The World", pos = {x=1,y=2}, set = "Tarot", effect = "Suit Conversion", cost_mult = 1.0, config = {suit_conv = 'Spades', max_highlighted = 3}}, - - --Planets - c_mercury= {order = 1, discovered = false, cost = 3, consumeable = true, freq = 1, name = "Mercury", pos = {x=0,y=3}, set = "Planet", effect = "Hand Upgrade", cost_mult = 1.0, config = {hand_type = 'Pair'}}, - c_venus= {order = 2, discovered = false, cost = 3, consumeable = true, freq = 1, name = "Venus", pos = {x=1,y=3}, set = "Planet", effect = "Hand Upgrade", cost_mult = 1.0, config = {hand_type = 'Three of a Kind'}}, - c_earth= {order = 3, discovered = false, cost = 3, consumeable = true, freq = 1, name = "Earth", pos = {x=2,y=3}, set = "Planet", effect = "Hand Upgrade", cost_mult = 1.0, config = {hand_type = 'Full House'}}, - c_mars= {order = 4, discovered = false, cost = 3, consumeable = true, freq = 1, name = "Mars", pos = {x=3,y=3}, set = "Planet", effect = "Hand Upgrade", cost_mult = 1.0, config = {hand_type = 'Four of a Kind'}}, - c_jupiter= {order = 5, discovered = false, cost = 3, consumeable = true, freq = 1, name = "Jupiter", pos = {x=4,y=3}, set = "Planet", effect = "Hand Upgrade", cost_mult = 1.0, config = {hand_type = 'Flush'}}, - c_saturn= {order = 6, discovered = false, cost = 3, consumeable = true, freq = 1, name = "Saturn", pos = {x=5,y=3}, set = "Planet", effect = "Hand Upgrade", cost_mult = 1.0, config = {hand_type = 'Straight'}}, - c_uranus= {order = 7, discovered = false, cost = 3, consumeable = true, freq = 1, name = "Uranus", pos = {x=6,y=3}, set = "Planet", effect = "Hand Upgrade", cost_mult = 1.0, config = {hand_type = 'Two Pair'}}, - c_neptune= {order = 8, discovered = false, cost = 3, consumeable = true, freq = 1, name = "Neptune", pos = {x=7,y=3}, set = "Planet", effect = "Hand Upgrade", cost_mult = 1.0, config = {hand_type = 'Straight Flush'}}, - c_pluto= {order = 9, discovered = false, cost = 3, consumeable = true, freq = 1, name = "Pluto", pos = {x=8,y=3}, set = "Planet", effect = "Hand Upgrade", cost_mult = 1.0, config = {hand_type = 'High Card'}}, - c_planet_x= {order = 10, discovered = false, cost = 3, consumeable = true, freq = 1, name = "Planet X", pos = {x=9,y=2}, set = "Planet", effect = "Hand Upgrade", cost_mult = 1.0, config = {hand_type = 'Five of a Kind', softlock = true}}, - c_ceres= {order = 11, discovered = false, cost = 3, consumeable = true, freq = 1, name = "Ceres", pos = {x=8,y=2}, set = "Planet", effect = "Hand Upgrade", cost_mult = 1.0, config = {hand_type = 'Flush House', softlock = true}}, - c_eris= {order = 12, discovered = false, cost = 3, consumeable = true, freq = 1, name = "Eris", pos = {x=3,y=2}, set = "Planet", effect = "Hand Upgrade", cost_mult = 1.0, config = {hand_type = 'Flush Five', softlock = true}}, - - --Spectral - c_familiar= {order = 1, discovered = false, cost = 4, consumeable = true, name = "Familiar", pos = {x=0,y=4}, set = "Spectral", config = {remove_card = true, extra = 3}}, - c_grim= {order = 2, discovered = false, cost = 4, consumeable = true, name = "Grim", pos = {x=1,y=4}, set = "Spectral", config = {remove_card = true, extra = 2}}, - c_incantation= {order = 3, discovered = false, cost = 4, consumeable = true, name = "Incantation", pos = {x=2,y=4}, set = "Spectral", config = {remove_card = true, extra = 4}}, - c_talisman= {order = 4, discovered = false, cost = 4, consumeable = true, name = "Talisman", pos = {x=3,y=4}, set = "Spectral", config = {extra = 'Gold', max_highlighted = 1}}, - c_aura= {order = 5, discovered = false, cost = 4, consumeable = true, name = "Aura", pos = {x=4,y=4}, set = "Spectral", config = {}}, - c_wraith= {order = 6, discovered = false, cost = 4, consumeable = true, name = "Wraith", pos = {x=5,y=4}, set = "Spectral", config = {}}, - c_sigil= {order = 7, discovered = false, cost = 4, consumeable = true, name = "Sigil", pos = {x=6,y=4}, set = "Spectral", config = {}}, - c_ouija= {order = 8, discovered = false, cost = 4, consumeable = true, name = "Ouija", pos = {x=7,y=4}, set = "Spectral", config = {}}, - c_ectoplasm= {order = 9, discovered = false, cost = 4, consumeable = true, name = "Ectoplasm", pos = {x=8,y=4}, set = "Spectral", config = {}}, - c_immolate= {order = 10, discovered = false, cost = 4, consumeable = true, name = "Immolate", pos = {x=9,y=4}, set = "Spectral", config = {remove_card = true, extra = {destroy = 5, dollars = 20}}}, - c_ankh= {order = 11, discovered = false, cost = 4, consumeable = true, name = "Ankh", pos = {x=0,y=5}, set = "Spectral", config = {extra = 2}}, - c_deja_vu= {order = 12, discovered = false, cost = 4, consumeable = true, name = "Deja Vu", pos = {x=1,y=5}, set = "Spectral", config = {extra = 'Red', max_highlighted = 1}}, - c_hex= {order = 13, discovered = false, cost = 4, consumeable = true, name = "Hex", pos = {x=2,y=5}, set = "Spectral", config = {extra = 2}}, - c_trance= {order = 14, discovered = false, cost = 4, consumeable = true, name = "Trance", pos = {x=3,y=5}, set = "Spectral", config = {extra = 'Blue', max_highlighted = 1}}, - c_medium= {order = 15, discovered = false, cost = 4, consumeable = true, name = "Medium", pos = {x=4,y=5}, set = "Spectral", config = {extra = 'Purple', max_highlighted = 1}}, - c_cryptid= {order = 16, discovered = false, cost = 4, consumeable = true, name = "Cryptid", pos = {x=5,y=5}, set = "Spectral", config = {extra = 2, max_highlighted = 1}}, - c_soul= {order = 17, discovered = false, cost = 4, consumeable = true, name = "The Soul", pos = {x=2,y=2}, set = "Spectral", effect = "Unlocker", config = {}, hidden = true}, - c_black_hole= {order = 18, discovered = false, cost = 4, consumeable = true, name = "Black Hole", pos = {x=9,y=3}, set = "Spectral", config = {}, hidden = true}, - - --Vouchers - - v_overstock_norm = {order = 1, discovered = false, unlocked = true , available = true, cost = 10, name = "Overstock", pos = {x=0,y=0}, set = "Voucher", config = {extra = 1}}, - v_clearance_sale= {order = 3, discovered = false, unlocked = true , available = true, cost = 10, name = "Clearance Sale", pos = {x=3,y=0}, set = "Voucher", config = {extra = 25}}, - v_hone= {order = 5, discovered = false, unlocked = true , available = true, cost = 10, name = "Hone", pos = {x=4,y=0}, set = "Voucher", config = {extra = 2}}, - v_reroll_surplus= {order = 7, discovered = false, unlocked = true , available = true, cost = 10, name = "Reroll Surplus", pos = {x=0,y=2}, set = "Voucher", config = {extra = 2}}, - v_crystal_ball= {order = 9, discovered = false, unlocked = true , available = true, cost = 10, name = "Crystal Ball", pos = {x=2,y=2}, set = "Voucher", config = {extra = 1}}, - v_telescope= {order = 11, discovered = false, unlocked = true , available = true, cost = 10, name = "Telescope", pos = {x=3,y=2}, set = "Voucher", config = {extra = 3}}, - v_grabber= {order = 13, discovered = false, unlocked = true , available = true, cost = 10, name = "Grabber", pos = {x=5,y=0}, set = "Voucher", config = {extra = 1}}, - v_wasteful= {order = 15, discovered = false, unlocked = true , available = true, cost = 10, name = "Wasteful", pos = {x=6,y=0}, set = "Voucher", config = {extra = 1}}, - v_tarot_merchant= {order = 17, discovered = false, unlocked = true , available = true, cost = 10, name = "Tarot Merchant", pos = {x=1,y=0}, set = "Voucher", config = {extra = 9.6/4, extra_disp = 2}}, - v_planet_merchant= {order = 19, discovered = false, unlocked = true , available = true, cost = 10, name = "Planet Merchant", pos = {x=2,y=0}, set = "Voucher", config = {extra = 9.6/4, extra_disp = 2}}, - v_seed_money= {order = 21, discovered = false, unlocked = true , available = true, cost = 10, name = "Seed Money", pos = {x=1,y=2}, set = "Voucher", config = {extra = 50}}, - v_blank= {order = 23, discovered = false, unlocked = true , available = true, cost = 10, name = "Blank", pos = {x=7,y=0}, set = "Voucher", config = {extra = 5}}, - v_magic_trick= {order = 25, discovered = false, unlocked = true , available = true, cost = 10, name = "Magic Trick", pos = {x=4,y=2}, set = "Voucher", config = {extra = 4}}, - v_hieroglyph= {order = 27, discovered = false, unlocked = true , available = true, cost = 10, name = "Hieroglyph", pos = {x=5,y=2}, set = "Voucher", config = {extra = 1}}, - v_directors_cut= {order = 29, discovered = false, unlocked = true , available = true, cost = 10, name = "Director's Cut", pos = {x=6,y=2}, set = "Voucher", config = {extra = 10}}, - v_paint_brush= {order = 31, discovered = false, unlocked = true , available = true, cost = 10, name = "Paint Brush", pos = {x=7,y=2}, set = "Voucher", config = {extra = 1}}, - - v_overstock_plus= {order = 2, discovered = false, unlocked = false, available = true, cost = 10, name = "Overstock Plus", pos = {x=0,y=1}, set = "Voucher", config = {extra = 1}, requires = {'v_overstock_norm'},unlock_condition = {type = 'c_shop_dollars_spent', extra = 2500}}, - v_liquidation= {order = 4, discovered = false, unlocked = false, available = true, cost = 10, name = "Liquidation", pos = {x=3,y=1}, set = "Voucher", config = {extra = 50}, requires = {'v_clearance_sale'},unlock_condition = {type = 'run_redeem', extra = 10}}, - v_glow_up= {order = 6, discovered = false, unlocked = false, available = true, cost = 10, name = "Glow Up", pos = {x=4,y=1}, set = "Voucher", config = {extra = 4}, requires = {'v_hone'},unlock_condition = {type = 'have_edition', extra = 5}}, - v_reroll_glut= {order = 8, discovered = false, unlocked = false, available = true, cost = 10, name = "Reroll Glut", pos = {x=0,y=3}, set = "Voucher", config = {extra = 2}, requires = {'v_reroll_surplus'},unlock_condition = {type = 'c_shop_rerolls', extra = 100}}, - v_omen_globe= {order = 10, discovered = false, unlocked = false, available = true, cost = 10, name = "Omen Globe", pos = {x=2,y=3}, set = "Voucher", config = {extra = 4}, requires = {'v_crystal_ball'},unlock_condition = {type = 'c_tarot_reading_used', extra = 25}}, - v_observatory= {order = 12, discovered = false, unlocked = false, available = true, cost = 10, name = "Observatory", pos = {x=3,y=3}, set = "Voucher", config = {extra = 1.5}, requires = {'v_telescope'},unlock_condition = {type = 'c_planetarium_used', extra = 25}}, - v_nacho_tong= {order = 14, discovered = false, unlocked = false, available = true, cost = 10, name = "Nacho Tong", pos = {x=5,y=1}, set = "Voucher", config = {extra = 1}, requires = {'v_grabber'},unlock_condition = {type = 'c_cards_played', extra = 2500}}, - v_recyclomancy= {order = 16, discovered = false, unlocked = false, available = true, cost = 10, name = "Recyclomancy", pos = {x=6,y=1}, set = "Voucher", config = {extra = 1}, requires = {'v_wasteful'},unlock_condition = {type = 'c_cards_discarded', extra = 2500}}, - v_tarot_tycoon= {order = 18, discovered = false, unlocked = false, available = true,cost = 10, name = "Tarot Tycoon", pos = {x=1,y=1}, set = "Voucher", config = {extra = 32/4, extra_disp = 4}, requires = {'v_tarot_merchant'},unlock_condition = {type = 'c_tarots_bought', extra = 50}}, - v_planet_tycoon= {order = 20, discovered = false, unlocked = false, available = true,cost = 10, name = "Planet Tycoon", pos = {x=2,y=1}, set = "Voucher", config = {extra = 32/4, extra_disp = 4}, requires = {'v_planet_merchant'},unlock_condition = {type = 'c_planets_bought', extra = 50}}, - v_money_tree= {order = 22, discovered = false, unlocked = false, available = true, cost = 10, name = "Money Tree", pos = {x=1,y=3}, set = "Voucher", config = {extra = 100}, requires = {'v_seed_money'},unlock_condition = {type = 'interest_streak', extra = 10}}, - v_antimatter= {order = 24, discovered = false, unlocked = false, available = true, cost = 10, name = "Antimatter", pos = {x=7,y=1}, set = "Voucher", config = {extra = 1}, requires = {'v_blank'},unlock_condition = {type = 'blank_redeems', extra = 10}}, - v_illusion= {order = 26, discovered = false, unlocked = false, available = true, cost = 10, name = "Illusion", pos = {x=4,y=3}, set = "Voucher", config = {extra = 4}, requires = {'v_magic_trick'},unlock_condition = {type = 'c_playing_cards_bought', extra = 20}}, - v_petroglyph= {order = 28, discovered = false, unlocked = false, available = true, cost = 10, name = "Petroglyph", pos = {x=5,y=3}, set = "Voucher", config = {extra = 1}, requires = {'v_hieroglyph'},unlock_condition = {type = 'ante_up', ante = 12, extra = 12}}, - v_retcon= {order = 30, discovered = false, unlocked = false, available = true, cost = 10, name = "Retcon", pos = {x=6,y=3}, set = "Voucher", config = {extra = 10}, requires = {'v_directors_cut'},unlock_condition = {type = 'blind_discoveries', extra = 25}}, - v_palette= {order = 32, discovered = false, unlocked = false, available = true, cost = 10, name = "Palette", pos = {x=7,y=3}, set = "Voucher", config = {extra = 1}, requires = {'v_paint_brush'},unlock_condition = {type = 'min_hand_size', extra = 5}}, - - --Backs - - b_red= {name = "Red Deck", stake = 1, unlocked = true,order = 1, pos = {x=0,y=0}, set = "Back", config = {discards = 1}, discovered = true}, - b_blue= {name = "Blue Deck", stake = 1, unlocked = false,order = 2, pos = {x=0,y=2}, set = "Back", config = {hands = 1}, unlock_condition = {type = 'discover_amount', amount = 20}}, - b_yellow= {name = "Yellow Deck", stake = 1, unlocked = false,order = 3, pos = {x=1,y=2}, set = "Back", config = {dollars = 10}, unlock_condition = {type = 'discover_amount', amount = 50}}, - b_green= {name = "Green Deck", stake = 1, unlocked = false,order = 4, pos = {x=2,y=2}, set = "Back", config = {extra_hand_bonus = 2, extra_discard_bonus = 1, no_interest = true}, unlock_condition = {type = 'discover_amount', amount = 75}}, - b_black= {name = "Black Deck", stake = 1, unlocked = false,order = 5, pos = {x=3,y=2}, set = "Back", config = {hands = -1, joker_slot = 1}, unlock_condition = {type = 'discover_amount', amount = 100}}, - b_magic= {name = "Magic Deck", stake = 1, unlocked = false,order = 6, pos = {x=0,y=3}, set = "Back", config = {voucher = 'v_crystal_ball', consumables = {'c_fool', 'c_fool'}}, unlock_condition = {type = 'win_deck', deck = 'b_red'}}, - b_nebula= {name = "Nebula Deck", stake = 1, unlocked = false,order = 7, pos = {x=3,y=0}, set = "Back", config = {voucher = 'v_telescope', consumable_slot = -1}, unlock_condition = {type = 'win_deck', deck = 'b_blue'}}, - b_ghost= {name = "Ghost Deck", stake = 1, unlocked = false,order = 8, pos = {x=6,y=2}, set = "Back", config = {spectral_rate = 2, consumables = {'c_hex'}}, unlock_condition = {type = 'win_deck', deck = 'b_yellow'}}, - b_abandoned= {name = "Abandoned Deck", stake = 1, unlocked = false,order = 9, pos = {x=3,y=3}, set = "Back", config = {remove_faces = true}, unlock_condition = {type = 'win_deck', deck = 'b_green'}}, - b_checkered= {name = "Checkered Deck", stake = 1, unlocked = false,order = 10,pos = {x=1,y=3}, set = "Back", config = {}, unlock_condition = {type = 'win_deck', deck = 'b_black'}}, - b_zodiac= {name = "Zodiac Deck", stake = 1, unlocked = false,order = 11, pos = {x=3,y=4}, set = "Back", config = {vouchers = {'v_tarot_merchant','v_planet_merchant', 'v_overstock_norm'}}, unlock_condition = {type = 'win_stake', stake = 2}}, - b_painted= {name = "Painted Deck", stake = 1, unlocked = false,order = 12, pos = {x=4,y=3}, set = "Back", config = {hand_size = 2, joker_slot = -1}, unlock_condition = {type = 'win_stake', stake=3}}, - b_anaglyph= {name = "Anaglyph Deck", stake = 1, unlocked = false,order = 13, pos = {x=2,y=4}, set = "Back", config = {}, unlock_condition = {type = 'win_stake', stake = 4}}, - b_plasma= {name = "Plasma Deck", stake = 1, unlocked = false,order = 14, pos = {x=4,y=2}, set = "Back", config = {ante_scaling = 2}, unlock_condition = {type = 'win_stake', stake=5}}, - b_erratic= {name = "Erratic Deck", stake = 1, unlocked = false,order = 15, pos = {x=2,y=3}, set = "Back", config = {randomize_rank_suit = true}, unlock_condition = {type = 'win_stake', stake=7}}, - - b_challenge= {name = "Challenge Deck", stake = 1, unlocked = true,order = 16, pos = {x=0,y=4}, set = "Back", config = {}, omit = true}, - - - --All enhanced card types here - m_bonus = {max = 500, order = 2, name = "Bonus", set = "Enhanced", pos = {x=1,y=1}, effect = "Bonus Card", label = "Bonus Card", config = {bonus=30}}, - m_mult = {max = 500, order = 3, name = "Mult", set = "Enhanced", pos = {x=2,y=1}, effect = "Mult Card", label = "Mult Card", config = {mult = 4}}, - m_wild = {max = 500, order = 4, name = "Wild Card", set = "Enhanced", pos = {x=3,y=1}, effect = "Wild Card", label = "Wild Card", config = {}}, - m_glass = {max = 500, order = 5, name = "Glass Card", set = "Enhanced", pos = {x=5,y=1}, effect = "Glass Card", label = "Glass Card", config = {Xmult = 2, extra = 4}}, - m_steel = {max = 500, order = 6, name = "Steel Card", set = "Enhanced", pos = {x=6,y=1}, effect = "Steel Card", label = "Steel Card", config = {h_x_mult = 1.5}}, - m_stone = {max = 500, order = 7, name = "Stone Card", set = "Enhanced", pos = {x=5,y=0}, effect = "Stone Card", label = "Stone Card", config = {bonus = 50}}, - m_gold = {max = 500, order = 8, name = "Gold Card", set = "Enhanced", pos = {x=6,y=0}, effect = "Gold Card", label = "Gold Card", config = {h_dollars = 3}}, - m_lucky = {max = 500, order = 9, name = "Lucky Card", set = "Enhanced", pos = {x=4,y=1}, effect = "Lucky Card", label = "Lucky Card", config = {mult=20, p_dollars = 20}}, - - --editions - e_base = {order = 1, unlocked = true, discovered = false, name = "Base", pos = {x=0,y=0}, atlas = 'Joker', set = "Edition", config = {}}, - e_foil = {order = 2, unlocked = true, discovered = false, name = "Foil", pos = {x=0,y=0}, atlas = 'Joker', set = "Edition", config = {extra = 50}}, - e_holo = {order = 3, unlocked = true, discovered = false, name = "Holographic", pos = {x=0,y=0}, atlas = 'Joker', set = "Edition", config = {extra = 10}}, - e_polychrome = {order = 4, unlocked = true, discovered = false, name = "Polychrome", pos = {x=0,y=0}, atlas = 'Joker', set = "Edition", config = {extra = 1.5}}, - e_negative = {order = 5, unlocked = true, discovered = false, name = "Negative", pos = {x=0,y=0}, atlas = 'Joker', set = "Edition", config = {extra = 1}}, - - --booster packs - p_arcana_normal_1 = {order = 1, discovered = false, name = "Arcana Pack", weight = 1, kind = 'Arcana', cost = 4, pos = {x=0,y=0}, atlas = 'Booster', set = 'Booster', config = {extra = 3, choose = 1}}, - p_arcana_normal_2 = {order = 2, discovered = false, name = "Arcana Pack", weight = 1, kind = 'Arcana', cost = 4, pos = {x=1,y=0}, atlas = 'Booster', set = 'Booster', config = {extra = 3, choose = 1}}, - p_arcana_normal_3 = {order = 3, discovered = false, name = "Arcana Pack", weight = 1, kind = 'Arcana', cost = 4, pos = {x=2,y=0}, atlas = 'Booster', set = 'Booster', config = {extra = 3, choose = 1}}, - p_arcana_normal_4 = {order = 4, discovered = false, name = "Arcana Pack", weight = 1, kind = 'Arcana', cost = 4, pos = {x=3,y=0}, atlas = 'Booster', set = 'Booster', config = {extra = 3, choose = 1}}, - p_arcana_jumbo_1 = {order = 5, discovered = false, name = "Jumbo Arcana Pack", weight = 1, kind = 'Arcana', cost = 6, pos = {x=0,y=2}, atlas = 'Booster', set = 'Booster', config = {extra = 5, choose = 1}}, - p_arcana_jumbo_2 = {order = 6, discovered = false, name = "Jumbo Arcana Pack", weight = 1, kind = 'Arcana', cost = 6, pos = {x=1,y=2}, atlas = 'Booster', set = 'Booster', config = {extra = 5, choose = 1}}, - p_arcana_mega_1 = {order = 7, discovered = false, name = "Mega Arcana Pack", weight = 0.25, kind = 'Arcana', cost = 8, pos = {x=2,y=2}, atlas = 'Booster', set = 'Booster', config = {extra = 5, choose = 2}}, - p_arcana_mega_2 = {order = 8, discovered = false, name = "Mega Arcana Pack", weight = 0.25, kind = 'Arcana', cost = 8, pos = {x=3,y=2}, atlas = 'Booster', set = 'Booster', config = {extra = 5, choose = 2}}, - p_celestial_normal_1 = {order = 9, discovered = false, name = "Celestial Pack", weight = 1, kind = 'Celestial', cost = 4, pos = {x=0,y=1}, atlas = 'Booster', set = 'Booster', config = {extra = 3, choose = 1}}, - p_celestial_normal_2 = {order = 10, discovered = false, name = "Celestial Pack", weight = 1, kind = 'Celestial', cost = 4, pos = {x=1,y=1}, atlas = 'Booster', set = 'Booster', config = {extra = 3, choose = 1}}, - p_celestial_normal_3 = {order = 11, discovered = false, name = "Celestial Pack", weight = 1, kind = 'Celestial', cost = 4, pos = {x=2,y=1}, atlas = 'Booster', set = 'Booster', config = {extra = 3, choose = 1}}, - p_celestial_normal_4 = {order = 12, discovered = false, name = "Celestial Pack", weight = 1, kind = 'Celestial', cost = 4, pos = {x=3,y=1}, atlas = 'Booster', set = 'Booster', config = {extra = 3, choose = 1}}, - p_celestial_jumbo_1 = {order = 13, discovered = false, name = "Jumbo Celestial Pack", weight = 1, kind = 'Celestial', cost = 6, pos = {x=0,y=3}, atlas = 'Booster', set = 'Booster', config = {extra = 5, choose = 1}}, - p_celestial_jumbo_2 = {order = 14, discovered = false, name = "Jumbo Celestial Pack", weight = 1, kind = 'Celestial', cost = 6, pos = {x=1,y=3}, atlas = 'Booster', set = 'Booster', config = {extra = 5, choose = 1}}, - p_celestial_mega_1 = {order = 15, discovered = false, name = "Mega Celestial Pack", weight = 0.25, kind = 'Celestial', cost = 8, pos = {x=2,y=3}, atlas = 'Booster', set = 'Booster', config = {extra = 5, choose = 2}}, - p_celestial_mega_2 = {order = 16, discovered = false, name = "Mega Celestial Pack", weight = 0.25, kind = 'Celestial', cost = 8, pos = {x=3,y=3}, atlas = 'Booster', set = 'Booster', config = {extra = 5, choose = 2}}, - p_spectral_normal_1 = {order = 29, discovered = false, name = "Spectral Pack", weight = 0.3, kind = 'Spectral', cost = 4, pos = {x=0,y=4}, atlas = 'Booster', set = 'Booster', config = {extra = 2, choose = 1}}, - p_spectral_normal_2 = {order = 30, discovered = false, name = "Spectral Pack", weight = 0.3, kind = 'Spectral', cost = 4, pos = {x=1,y=4}, atlas = 'Booster', set = 'Booster', config = {extra = 2, choose = 1}}, - p_spectral_jumbo_1 = {order = 31, discovered = false, name = "Jumbo Spectral Pack", weight = 0.3, kind = 'Spectral', cost = 6, pos = {x=2,y=4}, atlas = 'Booster', set = 'Booster', config = {extra = 4, choose = 1}}, - p_spectral_mega_1 = {order = 32, discovered = false, name = "Mega Spectral Pack", weight = 0.07, kind = 'Spectral', cost = 8, pos = {x=3,y=4}, atlas = 'Booster', set = 'Booster', config = {extra = 4, choose = 2}}, - p_standard_normal_1 = {order = 17, discovered = false, name = "Standard Pack", weight = 1, kind = 'Standard', cost = 4, pos = {x=0,y=6}, atlas = 'Booster', set = 'Booster', config = {extra = 3, choose = 1}}, - p_standard_normal_2 = {order = 18, discovered = false, name = "Standard Pack", weight = 1, kind = 'Standard', cost = 4, pos = {x=1,y=6}, atlas = 'Booster', set = 'Booster', config = {extra = 3, choose = 1}}, - p_standard_normal_3 = {order = 19, discovered = false, name = "Standard Pack", weight = 1, kind = 'Standard', cost = 4, pos = {x=2,y=6}, atlas = 'Booster', set = 'Booster', config = {extra = 3, choose = 1}}, - p_standard_normal_4 = {order = 20, discovered = false, name = "Standard Pack", weight = 1, kind = 'Standard', cost = 4, pos = {x=3,y=6}, atlas = 'Booster', set = 'Booster', config = {extra = 3, choose = 1}}, - p_standard_jumbo_1 = {order = 21, discovered = false, name = "Jumbo Standard Pack", weight = 1, kind = 'Standard', cost = 6, pos = {x=0,y=7}, atlas = 'Booster', set = 'Booster', config = {extra = 5, choose = 1}}, - p_standard_jumbo_2 = {order = 22, discovered = false, name = "Jumbo Standard Pack", weight = 1, kind = 'Standard', cost = 6, pos = {x=1,y=7}, atlas = 'Booster', set = 'Booster', config = {extra = 5, choose = 1}}, - p_standard_mega_1 = {order = 23, discovered = false, name = "Mega Standard Pack", weight = 0.25, kind = 'Standard', cost = 8, pos = {x=2,y=7}, atlas = 'Booster', set = 'Booster', config = {extra = 5, choose = 2}}, - p_standard_mega_2 = {order = 24, discovered = false, name = "Mega Standard Pack", weight = 0.25, kind = 'Standard', cost = 8, pos = {x=3,y=7}, atlas = 'Booster', set = 'Booster', config = {extra = 5, choose = 2}}, - p_buffoon_normal_1 = {order = 25, discovered = false, name = "Buffoon Pack", weight = 0.6, kind = 'Buffoon', cost = 4, pos = {x=0,y=8}, atlas = 'Booster', set = 'Booster', config = {extra = 2, choose = 1}}, - p_buffoon_normal_2 = {order = 26, discovered = false, name = "Buffoon Pack", weight = 0.6, kind = 'Buffoon', cost = 4, pos = {x=1,y=8}, atlas = 'Booster', set = 'Booster', config = {extra = 2, choose = 1}}, - p_buffoon_jumbo_1 = {order = 27, discovered = false, name = "Jumbo Buffoon Pack", weight = 0.6, kind = 'Buffoon', cost = 6, pos = {x=2,y=8}, atlas = 'Booster', set = 'Booster', config = {extra = 4, choose = 1}}, - p_buffoon_mega_1 = {order = 28, discovered = false, name = "Mega Buffoon Pack", weight = 0.15, kind = 'Buffoon', cost = 8, pos = {x=3,y=8}, atlas = 'Booster', set = 'Booster', config = {extra = 4, choose = 2}}, - - --Extras - soul={pos = {x=0,y=1}}, - undiscovered_joker={pos = {x=5,y=3}}, - undiscovered_tarot={pos = {x=6,y=3}}, - } - - self.P_CENTER_POOLS = { - Booster = {}, - Default = {}, - Enhanced = {}, - Edition = {}, - Joker = {}, - Tarot = {}, - Planet = {}, - Tarot_Planet = {}, - Spectral = {}, - Consumeables = {}, - Voucher = {}, - Back = {}, - Tag = {}, - Seal = {}, - Stake = {}, - Demo = {} - } - - self.P_JOKER_RARITY_POOLS = { - {},{},{},{} - } - - self.P_LOCKED = {} - - self:save_progress() - - - ------------------------------------- - local TESTHELPER_unlocks = false and not _RELEASE_MODE - ------------------------------------- - if not love.filesystem.getInfo(G.SETTINGS.profile..'') then love.filesystem.createDirectory( G.SETTINGS.profile..'' ) end - if not love.filesystem.getInfo(G.SETTINGS.profile..'/'..'meta.jkr') then love.filesystem.append( G.SETTINGS.profile..'/'..'meta.jkr', 'return {}') end - - convert_save_to_meta() - - local meta = STR_UNPACK(get_compressed(G.SETTINGS.profile..'/'..'meta.jkr') or 'return {}') - meta.unlocked = meta.unlocked or {} - meta.discovered = meta.discovered or {} - meta.alerted = meta.alerted or {} - for _, t in ipairs{ - G.P_CENTERS, - G.P_BLINDS, - G.P_TAGS, - G.P_SEALS, - } do - for k, v in pairs(t) do - SMODS._save_d_u(v) - v._discovered_unlocked_overwritten = true - end - end - - for k, v in pairs(self.P_CENTERS) do - if not v.wip and not v.demo then - if TESTHELPER_unlocks then v.unlocked = true; v.discovered = true;v.alerted = true end --REMOVE THIS - if not v.unlocked and (string.find(k, '^j_') or string.find(k, '^b_') or string.find(k, '^v_')) and meta.unlocked[k] then - v.unlocked = true - end - if not v.unlocked and (string.find(k, '^j_') or string.find(k, '^b_') or string.find(k, '^v_')) then self.P_LOCKED[#self.P_LOCKED+1] = v end - if not v.discovered and (string.find(k, '^j_') or string.find(k, '^b_') or string.find(k, '^e_') or string.find(k, '^c_') or string.find(k, '^p_') or string.find(k, '^v_')) and meta.discovered[k] then - v.discovered = true - end - if v.discovered and meta.alerted[k] or v.set == 'Back' or v.start_alerted then - v.alerted = true - elseif v.discovered then - v.alerted = false - end - end - end - - table.sort(self.P_LOCKED, function (a, b) return not a.order or not b.order or a.order < b.order end) - - for k, v in pairs(self.P_BLINDS) do - v.key = k - if not v.wip and not v.demo then - if TESTHELPER_unlocks then v.discovered = true; v.alerted = true end --REMOVE THIS - if not v.discovered and meta.discovered[k] then - v.discovered = true - end - if v.discovered and meta.alerted[k] then - v.alerted = true - elseif v.discovered then - v.alerted = false - end - end - end - for k, v in pairs(self.P_TAGS) do - v.key = k - if not v.wip and not v.demo then - if TESTHELPER_unlocks then v.discovered = true; v.alerted = true end --REMOVE THIS - if not v.discovered and meta.discovered[k] then - v.discovered = true - end - if v.discovered and meta.alerted[k] then - v.alerted = true - elseif v.discovered then - v.alerted = false - end - table.insert(self.P_CENTER_POOLS['Tag'], v) - end - end - for k, v in pairs(self.P_SEALS) do - v.key = k - if not v.wip and not v.demo then - if TESTHELPER_unlocks then v.discovered = true; v.alerted = true end --REMOVE THIS - if not v.discovered and meta.discovered[k] then - v.discovered = true - end - if v.discovered and meta.alerted[k] then - v.alerted = true - elseif v.discovered then - v.alerted = false - end - table.insert(self.P_CENTER_POOLS['Seal'], v) - end - end - for k, v in pairs(self.P_STAKES) do - v.key = k - table.insert(self.P_CENTER_POOLS['Stake'], v) - end - - for k, v in pairs(self.P_CENTERS) do - v.key = k - if v.set == 'Joker' then table.insert(self.P_CENTER_POOLS['Joker'], v) end - if v.set and v.demo and v.pos then table.insert(self.P_CENTER_POOLS['Demo'], v) end - if not v.wip then - if v.set and v.set ~= 'Joker' and not v.skip_pool and not v.omit then table.insert(self.P_CENTER_POOLS[v.set], v) end - if v.set == 'Tarot' or v.set == 'Planet' then table.insert(self.P_CENTER_POOLS['Tarot_Planet'], v) end - if v.consumeable then table.insert(self.P_CENTER_POOLS['Consumeables'], v) end - if v.rarity and v.set == 'Joker' and not v.demo then table.insert(self.P_JOKER_RARITY_POOLS[v.rarity], v) end - end - end - - table.sort(self.P_CENTER_POOLS["Joker"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Tarot"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Planet"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Tarot_Planet"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Spectral"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Voucher"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Booster"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Consumeables"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Back"], function (a, b) return (a.order - (a.unlocked and 100 or 0)) < (b.order - (b.unlocked and 100 or 0)) end) - table.sort(self.P_CENTER_POOLS["Enhanced"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Edition"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Stake"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Tag"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Seal"], function (a, b) return a.order < b.order end) - table.sort(self.P_CENTER_POOLS["Demo"], function (a, b) return a.order + (a.set == 'Joker' and 1000 or 0) < b.order + (b.set == 'Joker' and 1000 or 0) end) - for i = 1, 4 do - table.sort(self.P_JOKER_RARITY_POOLS[i], function (a, b) return a.order < b.order end) - end -end - -function Game:load_profile(_profile) - if not G.PROFILES[_profile] then _profile = 1 end - G.SETTINGS.profile = _profile - - --Load the settings file - local info = get_compressed(_profile..'/profile.jkr') - if info ~= nil then - for k, v in pairs(STR_UNPACK(info)) do - G.PROFILES[G.SETTINGS.profile][k] = v - end - end - - local temp_profile = { - MEMORY = { - deck = 'Red Deck', - stake = 1, - }, - stake = 1, - - high_scores = { - hand = {label = 'Best Hand', amt = 0}, - furthest_round = {label = 'Highest Round', amt = 0}, - furthest_ante = {label = 'Highest Ante', amt = 0}, - most_money = {label = 'Most Money', amt = 0}, - boss_streak = {label = 'Most Bosses in a Row', amt = 0}, - collection = {label = 'Collection', amt = 0, tot = 1}, - win_streak = {label = 'Best Win Streak', amt = 0}, - current_streak = {label = '', amt = 0}, - poker_hand = {label = 'Most Played Hand', amt = 0} - }, - - career_stats = { - c_round_interest_cap_streak = 0, - c_dollars_earned = 0, - c_shop_dollars_spent = 0, - c_tarots_bought = 0, - c_planets_bought = 0, - c_playing_cards_bought = 0, - c_vouchers_bought = 0, - c_tarot_reading_used = 0, - c_planetarium_used = 0, - c_shop_rerolls = 0, - c_cards_played = 0, - c_cards_discarded = 0, - c_losses = 0, - c_wins = 0, - c_rounds = 0, - c_hands_played = 0, - c_face_cards_played = 0, - c_jokers_sold = 0, - c_cards_sold = 0, - c_single_hand_round_streak = 0, - }, - progress = { - - }, - joker_usage = {}, - consumeable_usage = {}, - voucher_usage = {}, - hand_usage = {}, - deck_usage = {}, - deck_stakes = {}, - challenges_unlocked = nil, - challenge_progress = { - completed = {}, - unlocked = {} - } - } - local recursive_init - recursive_init = function(t1, t2) - for k, v in pairs(t1) do - if not t2[k] then - t2[k] = v - elseif type(t2[k]) == 'table' and type(v) == 'table' then - recursive_init(v, t2[k]) - end - end - end - - recursive_init(temp_profile, G.PROFILES[G.SETTINGS.profile]) -end - -function Game:set_language() - if not self.LANGUAGES then - if false then - ------------------------------------------ - --SET LANGUAGE FOR FIRST TIME STARTUP HERE - - ------------------------------------------ - - G.SETTINGS.language = 'en-us' - end - ------------------------------------------------------- - --IF LANGUAGE NEEDS TO BE SET ON EVERY REBOOT, SET HERE - - ------------------------------------------------------- - - self.LANGUAGES = { - ['en-us'] = {font = 1, label = "English", key = 'en-us', button = "Language Feedback", warning = {'This language is still in Beta. To help us','improve it, please click on the feedback button.', 'Click again to confirm'}}, - ['de'] = {font = 1, label = "Deutsch", key = 'de', beta = nil, button = "Feedback zur Übersetzung", warning = {'Diese Übersetzung ist noch im Beta-Stadium. Willst du uns helfen,','sie zu verbessern? Dann klicke bitte auf die Feedback-Taste.', "Zum Bestätigen erneut klicken"}}, - ['es_419'] = {font = 1, label = "Español (México)", key = 'es_419', beta = nil, button = "Sugerencias de idioma", warning = {'Este idioma todavía está en Beta. Pulsa el botón','de sugerencias para ayudarnos a mejorarlo.', "Haz clic de nuevo para confirmar"}}, - ['es_ES'] = {font = 1, label = "Español (España)", key = 'es_ES', beta = nil, button = "Sugerencias de idioma", warning = {'Este idioma todavía está en Beta. Pulsa el botón','de sugerencias para ayudarnos a mejorarlo.', "Haz clic de nuevo para confirmar"}}, - ['fr'] = {font = 1, label = "Français", key = 'fr', beta = nil, button = "Partager votre avis", warning = {'La traduction française est encore en version bêta. ','Veuillez cliquer sur le bouton pour nous donner votre avis.', "Cliquez à nouveau pour confirmer"}}, - ['id'] = {font = 1, label = "Bahasa Indonesia", key = 'id', beta = true, button = "Umpan Balik Bahasa", warning = {'Bahasa ini masih dalam tahap Beta. Untuk membantu','kami meningkatkannya, silakan klik tombol umpan balik.', "Klik lagi untuk mengonfirmasi"}}, - ['it'] = {font = 1, label = "Italiano", key = 'it', beta = nil, button = "Feedback traduzione", warning = {'Questa traduzione è ancora in Beta. Per','aiutarci a migliorarla, clicca il tasto feedback', "Fai clic di nuovo per confermare"}}, - ['ja'] = {font = 5, label = "日本語", key = 'ja', beta = nil, button = "提案する", warning = {'この翻訳は現在ベータ版です。提案があった場合、','ボタンをクリックしてください。', "もう一度クリックして確認"}}, - ['ko'] = {font = 4, label = "한국어", key = 'ko', beta = nil, button = "번역 피드백", warning = {'이 언어는 아직 베타 단계에 있습니다. ','번역을 도와주시려면 피드백 버튼을 눌러주세요.', "다시 클릭해서 확인하세요"}}, - ['nl'] = {font = 1, label = "Nederlands", key = 'nl', beta = nil, button = "Taal suggesties", warning = {'Deze taal is nog in de Beta fase. Help ons het te ','verbeteren door op de suggestie knop te klikken.', "Klik opnieuw om te bevestigen"}}, - ['pl'] = {font = 1, label = "Polski", key = 'pl', beta = nil, button = "Wyślij uwagi do tłumaczenia", warning = {'Polska wersja językowa jest w fazie Beta. By pomóc nam poprawić',' jakość tłumaczenia, kliknij przycisk i podziel się swoją opinią i uwagami.', "Kliknij ponownie, aby potwierdzić"}}, - ['pt_BR'] = {font = 1, label = "Português", key = 'pt_BR', beta = nil, button = "Feedback de Tradução", warning = {'Esta tradução ainda está em Beta. Se quiser nos ajudar','a melhorá-la, clique no botão de feedback por favor', "Clique novamente para confirmar"}}, - ['ru'] = {font = 6, label = "Русский", key = 'ru', beta = true, button = "Отзыв о языке", warning = {'Этот язык все еще находится в Бета-версии. Чтобы помочь','нам его улучшить, пожалуйста, нажмите на кнопку обратной связи.', "Щелкните снова, чтобы подтвердить"}}, - ['zh_CN'] = {font = 2, label = "简体中文", key = 'zh_CN', beta = nil, button = "意见反馈", warning = {'这个语言目前尚为Beta版本。 请帮助我们改善翻译品质,','点击”意见反馈” 来提供你的意见。', "再次点击确认"}}, - ['zh_TW'] = {font = 3, label = "繁體中文", key = 'zh_TW', beta = nil, button = "意見回饋", warning = {'這個語言目前尚為Beta版本。請幫助我們改善翻譯品質,','點擊”意見回饋” 來提供你的意見。', "再按一下即可確認"}}, - ['all1'] = {font = 8, label = "English", key = 'all', omit = true}, - ['all2'] = {font = 9, label = "English", key = 'all', omit = true}, - } - --if G.F_ENGLISH_ONLY then - -- self.LANGUAGES = { - -- ['en-us'] = self.LANGUAGES['en-us'] - -- } - --end - - --load the font and set filter - self.FONTS = { - {file = "resources/fonts/m6x11plus.ttf", render_scale = self.TILESIZE*10, TEXT_HEIGHT_SCALE = 0.83, TEXT_OFFSET = {x=10,y=-20}, FONTSCALE = 0.1, squish = 1, DESCSCALE = 1}, - {file = "resources/fonts/NotoSansSC-Bold.ttf", render_scale = self.TILESIZE*7, TEXT_HEIGHT_SCALE = 0.7, TEXT_OFFSET = {x=0,y=-35}, FONTSCALE = 0.12, squish = 1, DESCSCALE = 1.1}, - {file = "resources/fonts/NotoSansTC-Bold.ttf", render_scale = self.TILESIZE*7, TEXT_HEIGHT_SCALE = 0.7, TEXT_OFFSET = {x=0,y=-35}, FONTSCALE = 0.12, squish = 1, DESCSCALE = 1.1}, - {file = "resources/fonts/NotoSansKR-Bold.ttf", render_scale = self.TILESIZE*7, TEXT_HEIGHT_SCALE = 0.8, TEXT_OFFSET = {x=0,y=-20}, FONTSCALE = 0.12, squish = 1, DESCSCALE = 1}, - {file = "resources/fonts/NotoSansJP-Bold.ttf", render_scale = self.TILESIZE*7, TEXT_HEIGHT_SCALE = 0.8, TEXT_OFFSET = {x=0,y=-20}, FONTSCALE = 0.12, squish = 1, DESCSCALE = 1}, - {file = "resources/fonts/NotoSans-Bold.ttf", render_scale = self.TILESIZE*7, TEXT_HEIGHT_SCALE = 0.65, TEXT_OFFSET = {x=0,y=-40}, FONTSCALE = 0.12, squish = 1, DESCSCALE = 1}, - {file = "resources/fonts/m6x11plus.ttf", render_scale = self.TILESIZE*10, TEXT_HEIGHT_SCALE = 0.9, TEXT_OFFSET = {x=10,y=15}, FONTSCALE = 0.1, squish = 1, DESCSCALE = 1}, - {file = "resources/fonts/GoNotoCurrent-Bold.ttf", render_scale = self.TILESIZE*10, TEXT_HEIGHT_SCALE = 0.8, TEXT_OFFSET = {x=10,y=-20}, FONTSCALE = 0.1, squish = 1, DESCSCALE = 1}, - {file = "resources/fonts/GoNotoCJKCore.ttf", render_scale = self.TILESIZE*10, TEXT_HEIGHT_SCALE = 0.8, TEXT_OFFSET = {x=10,y=-20}, FONTSCALE = 0.1, squish = 1, DESCSCALE = 1}, - } - for _, v in ipairs(self.FONTS) do - if love.filesystem.getInfo(v.file) then - v.FONT = love.graphics.newFont( v.file, v.render_scale) - end - end - for _, v in pairs(self.LANGUAGES) do - v.font = self.FONTS[v.font] - end - end - - self.LANG = self.LANGUAGES[self.SETTINGS.real_language or self.SETTINGS.language] or self.LANGUAGES['en-us'] - - local localization = love.filesystem.getInfo('localization/'..G.SETTINGS.language..'.lua') or love.filesystem.getInfo('localization/en-us.lua') - if localization ~= nil then - self.localization = assert(loadstring(love.filesystem.read('localization/'..G.SETTINGS.language..'.lua') or love.filesystem.read('localization/en-us.lua')))() - init_localization() - end -end - -function Game:set_render_settings() - self.SETTINGS.GRAPHICS.texture_scaling = self.SETTINGS.GRAPHICS.texture_scaling or 2 - - --Set fiter to linear interpolation and nearest, best for pixel art - love.graphics.setDefaultFilter( - self.SETTINGS.GRAPHICS.texture_scaling == 1 and 'nearest' or 'linear', - self.SETTINGS.GRAPHICS.texture_scaling == 1 and 'nearest' or 'linear', 1) - - love.graphics.setLineStyle("rough") - - --spritesheets - self.animation_atli = { - {name = "blind_chips", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/BlindChips.png",px=34,py=34, frames = 21}, - {name = "shop_sign", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/ShopSignAnimation.png",px=113,py=57, frames = 4} - } - self.asset_atli = { - {name = "cards_1", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/8BitDeck.png",px=71,py=95}, - {name = "cards_2", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/8BitDeck_opt2.png",px=71,py=95}, - {name = "centers", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/Enhancers.png",px=71,py=95}, - {name = "Joker", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/Jokers.png",px=71,py=95}, - {name = "Tarot", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/Tarots.png",px=71,py=95}, - {name = "Voucher", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/Vouchers.png",px=71,py=95}, - {name = "Booster", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/boosters.png",px=71,py=95}, - {name = "ui_1", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/ui_assets.png",px=18,py=18}, - {name = "ui_2", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/ui_assets_opt2.png",px=18,py=18}, - {name = "balatro", path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/balatro.png",px=333,py=216}, - {name = 'gamepad_ui', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/gamepad_ui.png",px=32,py=32}, - {name = 'icons', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/icons.png",px=66,py=66}, - {name = 'tags', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/tags.png",px=34,py=34}, - {name = 'stickers', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/stickers.png",px=71,py=95}, - {name = 'chips', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/chips.png",px=29,py=29}, - - {name = 'collab_AU_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_AU_1.png",px=71,py=95}, - {name = 'collab_AU_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_AU_2.png",px=71,py=95}, - {name = 'collab_TW_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_TW_1.png",px=71,py=95}, - {name = 'collab_TW_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_TW_2.png",px=71,py=95}, - {name = 'collab_VS_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_VS_1.png",px=71,py=95}, - {name = 'collab_VS_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_VS_2.png",px=71,py=95}, - {name = 'collab_DTD_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_DTD_1.png",px=71,py=95}, - {name = 'collab_DTD_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_DTD_2.png",px=71,py=95}, - {name = 'collab_CYP_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_CYP_1.png",px=71,py=95}, - {name = 'collab_CYP_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_CYP_2.png",px=71,py=95}, - {name = 'collab_STS_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_STS_1.png",px=71,py=95}, - {name = 'collab_STS_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_STS_2.png",px=71,py=95}, - {name = 'collab_TBoI_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_TBoI_1.png",px=71,py=95}, - {name = 'collab_TBoI_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_TBoI_2.png",px=71,py=95}, - {name = 'collab_SV_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_SV_1.png",px=71,py=95}, - {name = 'collab_SV_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_SV_2.png",px=71,py=95}, - - {name = 'collab_SK_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_SK_1.png",px=71,py=95}, - {name = 'collab_SK_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_SK_2.png",px=71,py=95}, - {name = 'collab_DS_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_DS_1.png",px=71,py=95}, - {name = 'collab_DS_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_DS_2.png",px=71,py=95}, - {name = 'collab_CL_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_CL_1.png",px=71,py=95}, - {name = 'collab_CL_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_CL_2.png",px=71,py=95}, - {name = 'collab_D2_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_D2_1.png",px=71,py=95}, - {name = 'collab_D2_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_D2_2.png",px=71,py=95}, - {name = 'collab_PC_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_PC_1.png",px=71,py=95}, - {name = 'collab_PC_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_PC_2.png",px=71,py=95}, - {name = 'collab_WF_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_WF_1.png",px=71,py=95}, - {name = 'collab_WF_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_WF_2.png",px=71,py=95}, - {name = 'collab_EG_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_EG_1.png",px=71,py=95}, - {name = 'collab_EG_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_EG_2.png",px=71,py=95}, - {name = 'collab_XR_1', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_XR_1.png",px=71,py=95}, - {name = 'collab_XR_2', path = "resources/textures/"..self.SETTINGS.GRAPHICS.texture_scaling.."x/collabs/collab_XR_2.png",px=71,py=95}, - } - self.asset_images = { - {name = "playstack_logo", path = "resources/textures/1x/playstack-logo.png", px=1417,py=1417}, - {name = "localthunk_logo", path = "resources/textures/1x/localthunk-logo.png", px=1390,py=560} - } - - --Load in all atli defined above - for i=1, #self.animation_atli do - self.ANIMATION_ATLAS[self.animation_atli[i].name] = {} - self.ANIMATION_ATLAS[self.animation_atli[i].name].name = self.animation_atli[i].name - self.ANIMATION_ATLAS[self.animation_atli[i].name].image = love.graphics.newImage(self.animation_atli[i].path, {mipmaps = true, dpiscale = self.SETTINGS.GRAPHICS.texture_scaling}) - self.ANIMATION_ATLAS[self.animation_atli[i].name].px = self.animation_atli[i].px - self.ANIMATION_ATLAS[self.animation_atli[i].name].py = self.animation_atli[i].py - self.ANIMATION_ATLAS[self.animation_atli[i].name].frames = self.animation_atli[i].frames - end - - for i=1, #self.asset_atli do - self.ASSET_ATLAS[self.asset_atli[i].name] = {} - self.ASSET_ATLAS[self.asset_atli[i].name].name = self.asset_atli[i].name - self.ASSET_ATLAS[self.asset_atli[i].name].image = love.graphics.newImage(self.asset_atli[i].path, {mipmaps = true, dpiscale = self.SETTINGS.GRAPHICS.texture_scaling}) - local mipmap_level = SMODS.config.graphics_mipmap_level_options[SMODS.config.graphics_mipmap_level] - if mipmap_level and mipmap_level > 0 then - self.ASSET_ATLAS[self.asset_atli[i].name].image:setMipmapFilter('linear', mipmap_level) - end - self.ASSET_ATLAS[self.asset_atli[i].name].type = self.asset_atli[i].type - self.ASSET_ATLAS[self.asset_atli[i].name].px = self.asset_atli[i].px - self.ASSET_ATLAS[self.asset_atli[i].name].py = self.asset_atli[i].py - end - for i=1, #self.asset_images do - self.ASSET_ATLAS[self.asset_images[i].name] = {} - self.ASSET_ATLAS[self.asset_images[i].name].name = self.asset_images[i].name - self.ASSET_ATLAS[self.asset_images[i].name].image = love.graphics.newImage(self.asset_images[i].path, {mipmaps = true, dpiscale = 1}) - self.ASSET_ATLAS[self.asset_images[i].name].type = self.asset_images[i].type - self.ASSET_ATLAS[self.asset_images[i].name].px = self.asset_images[i].px - self.ASSET_ATLAS[self.asset_images[i].name].py = self.asset_images[i].py - end - - for _, v in pairs(G.I.SPRITE) do - v:reset() - end - - self.ASSET_ATLAS.Planet = self.ASSET_ATLAS.Tarot - self.ASSET_ATLAS.Spectral = self.ASSET_ATLAS.Tarot -end - -function Game:init_window(reset) - --Initialize the window - self.ROOM_PADDING_H= 0.7 - self.ROOM_PADDING_W = 1 - self.WINDOWTRANS = { - x = 0, y = 0, - w = self.TILE_W+2*self.ROOM_PADDING_W, - h = self.TILE_H+2*self.ROOM_PADDING_H - } - self.window_prev = { - orig_scale = self.TILESCALE, - w=self.WINDOWTRANS.w*self.TILESIZE*self.TILESCALE, - h=self.WINDOWTRANS.h*self.TILESIZE*self.TILESCALE, - orig_ratio = self.WINDOWTRANS.w*self.TILESIZE*self.TILESCALE/(self.WINDOWTRANS.h*self.TILESIZE*self.TILESCALE)} - G.SETTINGS.QUEUED_CHANGE = G.SETTINGS.QUEUED_CHANGE or {} - G.SETTINGS.QUEUED_CHANGE.screenmode = G.SETTINGS.WINDOW.screenmode - - G.FUNCS.apply_window_changes(true) -end - -function Game:delete_run() - if self.ROOM then - remove_all(G.STAGE_OBJECTS[G.STAGE]) - self.load_shop_booster = nil - self.load_shop_jokers = nil - self.load_shop_vouchers = nil - if self.buttons then self.buttons:remove(); self.buttons = nil end - if self.deck_preview then self.deck_preview:remove(); self.deck_preview = nil end - if self.shop and not G.GAME.USING_CODE then self.shop:remove(); self.shop = nil end - if self.blind_select then self.blind_select:remove(); self.blind_select = nil end - if self.booster_pack then self.booster_pack:remove(); self.booster_pack = nil end - if self.MAIN_MENU_UI then self.MAIN_MENU_UI:remove(); self.MAIN_MENU_UI = nil end - if self.SPLASH_FRONT then self.SPLASH_FRONT:remove(); self.SPLASH_FRONT = nil end - if self.SPLASH_BACK then self.SPLASH_BACK:remove(); self.SPLASH_BACK = nil end - if self.SPLASH_LOGO then self.SPLASH_LOGO:remove(); self.SPLASH_LOGO = nil end - if self.GAME_OVER_UI then self.GAME_OVER_UI:remove(); self.GAME_OVER_UI = nil end - if self.collection_alert then self.collection_alert:remove(); self.collection_alert = nil end - if self.HUD then self.HUD:remove(); self.HUD = nil end - if self.HUD_blind then self.HUD_blind:remove(); self.HUD_blind = nil end - if self.HUD_tags then - for k, v in pairs(self.HUD_tags) do - v:remove() - end - self.HUD_tags = nil - end - if self.OVERLAY_MENU then self.OVERLAY_MENU:remove(); self.OVERLAY_MENU = nil end - if self.OVERLAY_TUTORIAL then - G.OVERLAY_TUTORIAL.Jimbo:remove() - if G.OVERLAY_TUTORIAL.content then G.OVERLAY_TUTORIAL.content:remove() end - G.OVERLAY_TUTORIAL:remove() - G.OVERLAY_TUTORIAL = nil - end - for k, v in pairs(G) do - if (type(v) == "table") and v.is and v:is(CardArea) then - G[k] = nil - end - end - G.I.CARD = {} - end - G.VIEWING_DECK = nil - G.E_MANAGER:clear_queue() - G.CONTROLLER:mod_cursor_context_layer(-1000) - G.CONTROLLER.focus_cursor_stack = {} - G.CONTROLLER.focus_cursor_stack_level = 1 - if G.GAME then G.GAME.won = false end - - G.STATE = -1 -end - - - -function Game:save_progress() - G.ARGS.save_progress = G.ARGS.save_progress or {} - G.ARGS.save_progress.UDA = EMPTY(G.ARGS.save_progress.UDA) - G.ARGS.save_progress.SETTINGS = G.SETTINGS - G.ARGS.save_progress.PROFILE = G.PROFILES[G.SETTINGS.profile] - - for k, v in pairs(self.P_CENTERS) do - G.ARGS.save_progress.UDA[k] = (v.unlocked and 'u' or '')..(v.discovered and 'd' or '')..(v.alerted and 'a' or '') - end - for k, v in pairs(self.P_BLINDS) do - G.ARGS.save_progress.UDA[k] = (v.unlocked and 'u' or '')..(v.discovered and 'd' or '')..(v.alerted and 'a' or '') - end - for k, v in pairs(self.P_TAGS) do - G.ARGS.save_progress.UDA[k] = (v.unlocked and 'u' or '')..(v.discovered and 'd' or '')..(v.alerted and 'a' or '') - end - for k, v in pairs(self.P_SEALS) do - G.ARGS.save_progress.UDA[k] = (v.unlocked and 'u' or '')..(v.discovered and 'd' or '')..(v.alerted and 'a' or '') - end - - G.FILE_HANDLER = G.FILE_HANDLER or {} - G.FILE_HANDLER.progress = true - G.FILE_HANDLER.update_queued = true -end - -function Game:save_notify(card) - G.SAVE_MANAGER.channel:push({ - type = 'save_notify', - save_notify = card.key, - profile_num = G.SETTINGS.profile - }) -end - -function Game:save_settings() - G.ARGS.save_settings = G.SETTINGS - G.FILE_HANDLER = G.FILE_HANDLER or {} - G.FILE_HANDLER.settings = true - G.FILE_HANDLER.update_queued = true -end - -function Game:save_metrics() - G.ARGS.save_metrics = G.METRICS - G.FILE_HANDLER = G.FILE_HANDLER or {} - G.FILE_HANDLER.settings = true - G.FILE_HANDLER.update_queued = true -end - -function Game:prep_stage(new_stage, new_state, new_game_obj) - for k, v in pairs(self.CONTROLLER.locks) do - self.CONTROLLER.locks[k] = nil - end - if new_game_obj then self.GAME = self:init_game_object() end - if new_game_obj and Talisman and Talisman.igo then self.GAME = Talisman.igo(self.GAME) end - self.STAGE = new_stage or self.STAGES.MAIN_MENU - self.STATE = new_state or self.STATES.MENU - self.STATE_COMPLETE = false - self.SETTINGS.paused = false - - self.ROOM = Node{T={ - x = self.ROOM_PADDING_W, - y = self.ROOM_PADDING_H, - w = self.TILE_W, - h = self.TILE_H} - } - self.ROOM.jiggle = 0 - self.ROOM.states.drag.can = false - self.ROOM:set_container(self.ROOM) - - self.ROOM_ATTACH = Moveable{T={ - x = 0, - y = 0, - w = self.TILE_W, - h = self.TILE_H} - } - self.ROOM_ATTACH.states.drag.can = false - self.ROOM_ATTACH:set_container(self.ROOM) - love.resize(love.graphics.getWidth( ),love.graphics.getHeight( )) -end - -function Game:sandbox() - G.TIMERS.REAL = 0 - G.TIMERS.TOTAL = 0 - - self:prep_stage(G.STAGES.SANDBOX, G.STATES.SANDBOX, true) - self.GAME.selected_back = Back(G.P_CENTERS.b_red) - - ease_background_colour{new_colour = G.C.BLACK, contrast = 1} - - G.SANDBOX = { - vort_time = 7, - vort_speed = 0, - col_op = {'RED','BLUE','GREEN','BLACK','L_BLACK','WHITE','EDITION','DARK_EDITION','ORANGE','PURPLE'}, - col1 = G.C.RED,col2 = G.C.BLUE, - mid_flash = 0, - joker_text = '', - edition = 'base', - tilt = 1, - card_size = 1, - base_size = {w = G.CARD_W, h = G.CARD_H}, - gamespeed = 0 - } - - if G.SPLASH_FRONT then G.SPLASH_FRONT:remove(); G.SPLASH_FRONT = nil end - if G.SPLASH_BACK then G.SPLASH_BACK:remove(); G.SPLASH_BACK = nil end - - G.SPLASH_BACK = Sprite(-30, -13, G.ROOM.T.w+60, G.ROOM.T.h+22, G.ASSET_ATLAS["ui_"..(G.SETTINGS.colourblind_option and 2 or 1)], {x = 2, y = 0}) - G.SPLASH_BACK:set_alignment({ - major = G.ROOM_ATTACH, - type = 'cm', - offset = {x=0,y=0} - }) - - G.SPLASH_BACK:define_draw_steps({{ - shader = 'splash', - send = { - {name = 'time', ref_table = G.SANDBOX, ref_value = 'vort_time'}, - {name = 'vort_speed', val = 0.4}, - {name = 'colour_1', ref_table = G.SANDBOX, ref_value = 'col1'}, - {name = 'colour_2', ref_table = G.SANDBOX, ref_value = 'col2'}, - {name = 'mid_flash', ref_table = G.SANDBOX, ref_value = 'mid_flash'}, - {name = 'vort_offset', val = 0}, - }}}) - - function create_UIBox_sandbox_controls() - G.FUNCS.col1change = function(args) - G.SANDBOX.col1 = G.C[args.to_val] - end - G.FUNCS.col2change = function(args) - G.SANDBOX.col2 = G.C[args.to_val] - end - G.FUNCS.edition_change = function(args) - G.SANDBOX.edition = args.to_val - if G.SANDBOX.joker then G.SANDBOX.joker:set_edition({[args.to_val] = true}, true, true) end - end - G.FUNCS.pulseme = function(e) - if math.random() > 0.998 then e.config.object:pulse(1) end - end - G.FUNCS.spawn_joker = function(e) G.FUNCS.rem_joker(); G.SANDBOX.joker = add_joker(G.SANDBOX.joker_text, G.SANDBOX.edition) end - G.FUNCS.rem_joker = function(e) if G.SANDBOX.joker then G.SANDBOX.joker:remove(); G.SANDBOX.joker = nil end end - G.FUNCS.do_time = function(args) if args.to_val == 'PLAY' then G.SANDBOX.gamespeed = 1 else G.SANDBOX.gamespeed = 0 end end - G.FUNCS.cb = function(rt) G.CARD_W = rt.ref_table[rt.ref_value]*G.SANDBOX.base_size.w; G.CARD_H = rt.ref_table[rt.ref_value]*G.SANDBOX.base_size.h end - G.E_MANAGER:add_event(Event({ - func = (function() - G.SANDBOX.file_reload_timer = (G.SANDBOX.file_reload_timer or 0) - if G.SANDBOX.file_reload_timer < G.TIMERS.REAL then - G.SANDBOX.file_reload_timer = G.SANDBOX.file_reload_timer+0.25 - end - if G.SANDBOX.joker then G.SANDBOX.joker.ambient_tilt = G.SANDBOX.tilt end - G.SANDBOX.vort_time = G.SANDBOX.vort_time + G.real_dt*G.SANDBOX.gamespeed - G.CONTROLLER.lock_input = false - end) - })) - - local t = { - n=G.UIT.ROOT, config = {align = "cm",colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.05, r = 0.1, emboss = 0.1, colour = G.C.L_BLACK}, nodes={ - create_slider({label = 'Time', w = 2, h = 0.3, text_scale = 0.2, label_scale = 0.3, ref_table = G.SANDBOX, ref_value = 'vort_time', min = 0, max = 30}), - create_option_cycle({options = {'PLAY','PAUSE'}, opt_callback = 'do_time', current_option = 1, colour = G.C.RED, w = 2, scale = 0.7}), - create_slider({label = 'tilt', w = 2, h = 0.3, text_scale = 0.2, label_scale = 0.3, ref_table = G.SANDBOX, ref_value = 'tilt', min = 0, max = 3, decimal_places = 2}), - create_slider({label = 'Card size', w = 2, h = 0.3, text_scale = 0.2, label_scale = 0.3, ref_table = G.SANDBOX, ref_value = 'card_size', min = 0.1, max = 3, callback = 'cb', decimal_places = 2}), - create_option_cycle({options = G.SANDBOX.col_op, opt_callback = 'col1change', current_option = 1, colour = G.C.RED, w = 2, scale = 0.7}), - create_option_cycle({options = G.SANDBOX.col_op, opt_callback = 'col2change', current_option = 2, colour = G.C.RED, w = 2, scale = 0.7}), - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes = { - UIBox_button{ label = {"+"}, button = "spawn_joker", minw = 0.7, col = true}, - create_text_input({prompt_text = 'Joker key', extended_corpus = true, ref_table = G.SANDBOX, ref_value = 'joker_text', text_scale = 0.3, w = 1.5, h = 0.6}), - UIBox_button{ label = {"-"}, button = "rem_joker", minw = 0.7, col = true}, - }}, - create_option_cycle({options = {'base', 'foil', 'holo', 'polychrome','negative'}, opt_callback = 'edition_change', current_option = 1, colour = G.C.RED, w = 2, scale = 0.7}), - }} - }} - return t - end - - - G.SANDBOX.UI = UIBox{ - definition = create_UIBox_sandbox_controls(), - config = {align="cli", offset = {x=0,y=0}, major = G.ROOM_ATTACH, bond = 'Weak'} - } - - G.SANDBOX.UI:recalculate(true) -end - -function Game:splash_screen() - --If the skip splash screen option is set, immediately go to the main menu here - if G.SETTINGS.skip_splash == 'Yes' then - G:main_menu() - return - end - - self:prep_stage(G.STAGES.MAIN_MENU, G.STATES.SPLASH, true) - G.E_MANAGER:add_event(Event({ - func = (function() - discover_card() - return true - end) - })) - - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - G.TIMERS.TOTAL = 0 - G.TIMERS.REAL = 0 - --Prep the splash screen shaders for both the background(colour swirl) and the foreground(white flash), starting at black - G.SPLASH_BACK = Sprite(-30, -13, G.ROOM.T.w+60, G.ROOM.T.h+22, G.ASSET_ATLAS["ui_1"], {x = 2, y = 0}) - G.SPLASH_BACK:define_draw_steps({{ - shader = 'splash', - send = { - {name = 'time', ref_table = G.TIMERS, ref_value = 'REAL'}, - {name = 'vort_speed', val = 1}, - {name = 'colour_1', ref_table = G.C, ref_value = 'BLUE'}, - {name = 'colour_2', ref_table = G.C, ref_value = 'WHITE'}, - {name = 'mid_flash', val = 0}, - {name = 'vort_offset', val = (2*90.15315131*os.time())%100000}, - }}}) - G.SPLASH_BACK:set_alignment({ - major = G.ROOM_ATTACH, - type = 'cm', - offset = {x=0,y=0} - }) - G.SPLASH_FRONT = Sprite(0,-20, G.ROOM.T.w*2, G.ROOM.T.h*4, G.ASSET_ATLAS["ui_1"], {x = 2, y = 0}) - G.SPLASH_FRONT:define_draw_steps({{ - shader = 'flash', - send = { - {name = 'time', ref_table = G.TIMERS, ref_value = 'REAL'}, - {name = 'mid_flash', val = 1} - }}}) - G.SPLASH_FRONT:set_alignment({ - major = G.ROOM_ATTACH, - type = 'cm', - offset = {x=0,y=0} - }) - - --spawn in splash card - local SC = nil - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.2,func = (function() - local SC_scale = 1.2 - SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS['j_joker']) - if Cryptid.enabled["Menu"] then - if Cryptid.enabled["M Jokers"] then - local mcard = {} - for k, _ in pairs(Cryptid.M_jokers) do - if G.P_CENTERS[k] then - mcard[#mcard + 1] = k - end - end - local option = math.random(#mcard) - local chosenoption = mcard[option] - if chosenoption == "j_cry_biggestm" or chosenoption == "j_cry_reverse" then --These don't render properly; replace these with loopy instead - SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS['j_cry_loopy'],{bypass_discovery_center = true, bypass_discovery_ui = true}) - else - SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS[chosenoption],{bypass_discovery_center = true, bypass_discovery_ui = true}) - end - else - SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS['j_jolly'],{bypass_discovery_center = true, bypass_discovery_ui = true}) - end - end - SC.T.y = G.ROOM.T.h/2 - SC_scale*G.CARD_H/2 - SC.ambient_tilt = 1 - SC.states.drag.can = false - SC.states.hover.can = false - SC.no_ui = true - G.VIBRATION = G.VIBRATION + 2 - play_sound('whoosh1', 0.7, 0.2) - play_sound('introPad1', 0.704, 0.6) - return true;end)})) - - --dissolve fool card and start to fade in the vortex - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 1.8,func = (function() --||||||||||| - SC:start_dissolve({G.C.WHITE, G.C.WHITE},true, 12, true) - play_sound('magic_crumple', 1, 0.5) - play_sound('splash_buildup', 1, 0.7) - return true;end)})) - - --create all the cards and suck them in - function make_splash_card(args) - args = args or {} - local angle = math.random()*2*3.14 - local card_size = (args.scale or 1.5)*(math.random() + 1) - local card_pos = args.card_pos or { - x = (18 + card_size)*math.sin(angle), - y = (18 + card_size)*math.cos(angle) - } - local card = Card( card_pos.x + G.ROOM.T.w/2 - G.CARD_W*card_size/2, - card_pos.y + G.ROOM.T.h/2 - G.CARD_H*card_size/2, - card_size*G.CARD_W, card_size*G.CARD_H, pseudorandom_element(G.P_CARDS), G.P_CENTERS.c_base) - if Cryptid.enabled["Menu"] then card:set_ability(get_random_consumable('cry_splash',{"no_grc"},nil,nil,true), true, nil) end - if math.random() > 0.8 then card.sprite_facing = 'back'; card.facing = 'back' end - card.no_shadow = true - card.states.hover.can = false - card.states.drag.can = false - card.vortex = true and not args.no_vortex - card.T.r = angle - return card, card_pos - end - - G.vortex_time = G.TIMERS.REAL - local temp_del = nil - - for i = 1, 200 do - temp_del = temp_del or 3 - G.E_MANAGER:add_event(Event({ - trigger = 'after', - blockable = false, - delay = temp_del, - func = (function() - local card, card_pos = make_splash_card({scale = 2 - i/300}) - local speed = math.max(2. - i*0.005, 0.001) - ease_value(card.T, 'scale', -card.T.scale, nil, nil, nil, 1.*speed, 'elastic') - ease_value(card.T, 'x', -card_pos.x, nil, nil, nil, 0.9*speed) - ease_value(card.T, 'y', -card_pos.y, nil, nil, nil, 0.9*speed) - local temp_pitch = i*0.007 + 0.6 - local temp_i = i - G.E_MANAGER:add_event(Event({ - blockable = false, - func = (function() - if card.T.scale <= 0 then - if temp_i < 30 then - play_sound('whoosh1', temp_pitch + math.random()*0.05, 0.25*(1 - temp_i/50)) - end - - if temp_i == 15 then - play_sound('whoosh_long',0.9, 0.7) - end - G.VIBRATION = G.VIBRATION + 0.1 - card:remove() - return true - end - end)})) - return true - end)})) - temp_del = temp_del + math.max(1/(i), math.max(0.2*(170-i)/500, 0.016)) - end - - --when faded to white, spit out the 'Fool's' cards and slowly have them settle in to place - G.E_MANAGER:add_event(Event({trigger = 'after',delay = 2.,func = (function() - G.SPLASH_BACK:remove() - G.SPLASH_BACK = G.SPLASH_FRONT - G.SPLASH_FRONT = nil - G:main_menu('splash') - return true;end)})) - return true - end) - })) -end - -function Game:main_menu(change_context) --True if main menu is accessed from the splash screen, false if it is skipped or accessed from the game - if change_context ~= 'splash' then - --Skip the timer to 14 seconds for all shaders that need it - G.TIMERS.REAL = 12 - G.TIMERS.TOTAL = 12 - else - --keep all sounds that came from splash screen - RESET_STATES(G.STATES.MENU) - end - - --Prepare the main menu, reset the default deck - self:prep_stage(G.STAGES.MAIN_MENU, G.STATES.MENU, true) - self.GAME.selected_back = Back(G.P_CENTERS.b_red) - - if (not G.SETTINGS.tutorial_complete) and G.SETTINGS.tutorial_progress.completed_parts['big_blind'] then G.SETTINGS.tutorial_complete = true end - - G.FUNCS.change_shadows{to_key = G.SETTINGS.GRAPHICS.shadows == 'On' and 1 or 2} - - ease_background_colour{new_colour = G.C.BLACK, contrast = 1} - - if G.SPLASH_FRONT then G.SPLASH_FRONT:remove(); G.SPLASH_FRONT = nil end - if G.SPLASH_BACK then G.SPLASH_BACK:remove(); G.SPLASH_BACK = nil end - G.SPLASH_BACK = Sprite(-30, -13, G.ROOM.T.w+60, G.ROOM.T.h+22, G.ASSET_ATLAS["ui_1"], {x = 2, y = 0}) - G.SPLASH_BACK:set_alignment({ - major = G.ROOM_ATTACH, - type = 'cm', - offset = {x=0,y=0} - }) - local splash_args = {mid_flash = change_context == 'splash' and 1.6 or 0.} - ease_value(splash_args, 'mid_flash', -(change_context == 'splash' and 1.6 or 0), nil, nil, nil, 4) - - G.SPLASH_BACK:define_draw_steps({{ - shader = 'splash', - send = { - {name = 'time', ref_table = G.TIMERS, ref_value = 'REAL_SHADER'}, - {name = 'vort_speed', val = 0.4}, - {name = 'colour_1', ref_table = G.C, ref_value = 'RED'}, - {name = 'colour_2', ref_table = G.C, ref_value = 'BLUE'}, - {name = 'mid_flash', ref_table = splash_args, ref_value = 'mid_flash'}, - {name = 'vort_offset', val = 0}, - }}}) - - --Display the unlocked decks and cards from the previous run - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - unlock_notify() - return true - end) - })) - - - local SC_scale = 1.1*(G.debug_splash_size_toggle and 0.8 or 1) - local CAI = { - TITLE_TOP_W = G.CARD_W, - TITLE_TOP_H = G.CARD_H, - } - self.title_top = CardArea( - 0, 0, - CAI.TITLE_TOP_W,CAI.TITLE_TOP_H, - {card_limit = 1, type = 'title'}) - - - G.SPLASH_LOGO = Sprite(0, 0, - 13*SC_scale, - 13*SC_scale*(G.ASSET_ATLAS["balatro"].py/G.ASSET_ATLAS["balatro"].px), - G.ASSET_ATLAS["balatro"], {x=0,y=0}) - - G.SPLASH_LOGO:set_alignment({ - major = G.title_top, - type = 'cm', - bond = 'Strong', - offset = {x=0,y=0} - }) - G.SPLASH_LOGO:define_draw_steps({{ - shader = 'dissolve', - }}) - - G.SPLASH_LOGO.dissolve_colours = {G.C.WHITE, G.C.WHITE} - G.SPLASH_LOGO.dissolve = 1 - - - local replace_card = Card(self.title_top.T.x, self.title_top.T.y, 1.2*G.CARD_W*SC_scale, 1.2*G.CARD_H*SC_scale, G.P_CARDS.S_A, G.P_CENTERS.c_base) - self.title_top:emplace(replace_card) - - replace_card:set_edition(G.P_CENTERS.e_cry_glitched and 'e_cry_glitched' or 'e_negative',true,true) - replace_card:set_seal('Gold', true, true) - replace_card.states.visible = false - replace_card.no_ui = true - replace_card.ambient_tilt = 0.0 - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = change_context == 'game' and 1.5 or 0, - blockable = false, - blocking = false, - func = (function() - if change_context == 'splash' then - replace_card.states.visible = true - replace_card:start_materialize({G.C.WHITE,G.C.WHITE}, true, 2.5) - play_sound('whoosh1', math.random()*0.1 + 0.3,0.3) - play_sound('crumple'..math.random(1,5), math.random()*0.2 + 0.6,0.65) - else - replace_card.states.visible = true - replace_card:start_materialize({G.C.WHITE,G.C.WHITE}, nil, 1.2) - end - G.VIBRATION = G.VIBRATION + 1 - return true - end)})) - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = change_context == 'splash' and 1.8 or change_context == 'game' and 2 or 0.5, - blockable = false, - blocking = false, - func = (function() - play_sound('magic_crumple'..(change_context == 'splash' and 2 or 3), (change_context == 'splash' and 1 or 1.3), 0.9) - play_sound('whoosh1', 0.4, 0.8) - ease_value(G.SPLASH_LOGO, 'dissolve', -1, nil, nil, nil, change_context == 'splash' and 2.3 or 0.9) - G.VIBRATION = G.VIBRATION + 1.5 - return true - end)})) - - delay(0.1 + (change_context == 'splash' and 2 or change_context == 'game' and 1.5 or 0)) - - if replace_card and (G.P_CENTERS.j_blueprint.unlocked) then - local viable_unlockables = {} - for k, v in ipairs(self.P_LOCKED) do - if (v.set == 'Voucher' or v.set == 'Joker') and not v.demo then - viable_unlockables[#viable_unlockables+1] = v - end - end - if #viable_unlockables > 0 then - local card - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 4.04, - func = (function() - card = Card(self.title_top.T.x, self.title_top.T.y, 1.2*G.CARD_W*SC_scale, 1.2*G.CARD_H*SC_scale, nil, pseudorandom_element(viable_unlockables) or self.P_CENTERS.j_joker) - card.no_ui = #viable_unlockables == 0 - card.states.visible = false - replace_card.parent = nil - replace_card:start_dissolve({G.C.BLACK, G.C.ORANGE, G.C.RED, G.C.GOLD}) - return true - end)})) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 1.04, - func = (function() - card:start_materialize() - self.title_top:emplace(card) - return true - end)})) - end - end - - G.E_MANAGER:add_event(Event({func = function() G.CONTROLLER.lock_input = false; return true end})) - set_screen_positions() - - self.title_top:sort('order') - self.title_top:set_ranks() - self.title_top:align_cards() - self.title_top:hard_set_cards() - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = change_context == 'splash' and 4.05 or change_context == 'game' and 3 or 1.5, - blockable = false, - blocking = false, - func = (function() - set_main_menu_UI() - return true - end) - })) - - --Do all career stat unlock checking here as well - for k, v in pairs(G.PROFILES[G.SETTINGS.profile].career_stats) do - check_for_unlock({type = 'career_stat', statname = k}) - end - check_for_unlock({type = 'blind_discoveries'}) - if change_context ~= "splash" then - if not (G.ACHIEVEMENTS and G.ACHIEVEMENTS['ach_cry_used_crash'] and G.ACHIEVEMENTS['ach_cry_used_crash'].earned) then check_for_unlock({type = 'ach_cry_used_crash'}) end - if not (G.ACHIEVEMENTS and G.ACHIEVEMENTS['ach_cry_traffic_jam'] and G.ACHIEVEMENTS['ach_cry_traffic_jam'].earned) then check_for_unlock({type = 'win_challenge_startup'}) end - if not (G.ACHIEVEMENTS and G.ACHIEVEMENTS['ach_cry_perfectly_balanced'] and G.ACHIEVEMENTS['ach_cry_perfectly_balanced'].earned) then check_for_unlock({type = 'win_stake_startup'}) end - end - - G.E_MANAGER:add_event(Event({ - blockable = false, - func = function() - set_discover_tallies() - for i = 1, #G.CHALLENGES do - if (G.CHALLENGES[i].id == 'c_cry_rush_hour' or G.CHALLENGES[i].id == 'c_cry_rush_hour_ii' or G.CHALLENGES[i].id == 'c_cry_rush_hour_iii') and #G.CHALLENGES[i].restrictions.banned_other == 0 then - for k, v in pairs(G.P_BLINDS) do - if k ~= "bl_cry_clock" and k ~= "bl_cry_lavender_loop" and v.boss then - G.CHALLENGES[i].restrictions.banned_other[#G.CHALLENGES[i].restrictions.banned_other+1] = {id = k, type = 'blind'} - end - end - end - end - set_profile_progress() - G.REFRESH_ALERTS = true - return true - end - })) - - --VERSION - UIBox{ - definition = - {n=G.UIT.ROOT, config={align = "cm", colour = G.C.UI.TRANSPARENT_DARK}, nodes={ - {n=G.UIT.T, config={text = G.VERSION, scale = 0.3, colour = G.C.UI.TEXT_LIGHT}} - }}, - config = {align="tri", offset = {x=0,y=0}, major = G.ROOM_ATTACH, bond = 'Weak'} - } -end - -function Game:demo_cta() --True if main menu is accessed from the splash screen, false if it is skipped or accessed from the game - --G.TIMERS.REAL = 12 - --G.TIMERS.TOTAL = 12 - --Prepare the main menu, reset the default deck - self:prep_stage(G.STAGES.MAIN_MENU, G.STATES.DEMO_CTA, true) - - self.GAME.selected_back = Back(G.P_CENTERS.b_red) - - G.FUNCS.change_shadows{to_key = G.SETTINGS.GRAPHICS.shadows == 'On' and 1 or 2} - - ease_background_colour{new_colour = G.C.BLACK, contrast = 1} - - if G.SPLASH_FRONT then G.SPLASH_FRONT:remove(); G.SPLASH_FRONT = nil end - if G.SPLASH_BACK then G.SPLASH_BACK:remove(); G.SPLASH_BACK = nil end - G.SPLASH_BACK = Sprite(-30, -13, G.ROOM.T.w+60, G.ROOM.T.h+22, G.ASSET_ATLAS["ui_1"], {x = 2, y = 0}) - G.SPLASH_BACK:set_alignment({ - major = G.ROOM_ATTACH, - type = 'cm', - offset = {x=0,y=0} - }) - local splash_args = {mid_flash = 1.6} - ease_value(splash_args, 'mid_flash', -1.6, nil, nil, nil, 4) - - G.SPLASH_BACK:define_draw_steps({{ - shader = 'splash', - send = { - {name = 'time', ref_table = G.TIMERS, ref_value = 'REAL_SHADER'}, - {name = 'vort_speed', val = 0.4}, - {name = 'colour_1', ref_table = G.C, ref_value = 'RED'}, - {name = 'colour_2', ref_table = G.C, ref_value = 'BLUE'}, - {name = 'mid_flash', ref_table = splash_args, ref_value = 'mid_flash'}, - {name = 'vort_offset', val = 0}, - }}}) - - local SC_scale = 0.9*(G.debug_splash_size_toggle and 0.8 or 1) - - local CAI = { - TITLE_TOP_W = G.CARD_W, - TITLE_TOP_H = G.CARD_H, - } - self.title_top = CardArea( - 0, 0, - CAI.TITLE_TOP_W,CAI.TITLE_TOP_H, - {card_limit = 1, type = 'title'}) - - - G.SPLASH_LOGO = Sprite(0, 0, - 13*SC_scale, - 13*SC_scale*(G.ASSET_ATLAS["balatro"].py/G.ASSET_ATLAS["balatro"].px), - G.ASSET_ATLAS["balatro"], {x=0,y=0}) - - G.SPLASH_LOGO:set_alignment({ - major = G.title_top, - type = 'cm', - bond = 'Strong', - offset = {x=0,y=0} - }) - G.SPLASH_LOGO:define_draw_steps({{ - shader = 'dissolve', - }}) - - G.SPLASH_LOGO.dissolve_colours = {G.C.WHITE, G.C.WHITE} - G.SPLASH_LOGO.dissolve = 1 - - local replace_card = Card(self.title_top.T.x, self.title_top.T.y, 1.2*G.CARD_W*SC_scale, 1.2*G.CARD_H*SC_scale, G.P_CARDS.S_A, G.P_CENTERS.c_base) - self.title_top:emplace(replace_card) - - replace_card:set_edition(G.P_CENTERS.e_cry_glitched and 'e_cry_glitched' or 'e_negative',true,true) - replace_card:set_seal('Gold', true, true) - replace_card.states.visible = false - replace_card.no_ui = true - replace_card.ambient_tilt = 0.0 - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 1.1, - blockable = false, - blocking = false, - func = (function() - replace_card.states.visible = true - replace_card:start_materialize({G.C.WHITE,G.C.WHITE}, true, 2.5) - play_sound('whoosh1', math.random()*0.1 + 0.3,0.3) - play_sound('crumple'..math.random(1,5), math.random()*0.2 + 0.6,0.65) - return true - end)})) - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 1.8, - blockable = false, - blocking = false, - func = (function() - play_sound('magic_crumple'..(2), 1, 0.9) - play_sound('whoosh1', 0.4, 0.8) - ease_value(G.SPLASH_LOGO, 'dissolve', -1, nil, nil, nil, 2.3) - return true - end)})) - - delay(0.1 + 2) - - G.E_MANAGER:add_event(Event({func = function() G.CONTROLLER.lock_input = false; return true end})) - set_screen_positions() - - self.title_top:sort('order') - self.title_top:set_ranks() - self.title_top:align_cards() - self.title_top:hard_set_cards() - - local playstack = Sprite(0,0,1.7,1.7,G.ASSET_ATLAS["playstack_logo"], {x=0, y=0}) - playstack.states.drag.can = false - local localthunk = Sprite(0,0,1*1390/560,1,G.ASSET_ATLAS["localthunk_logo"], {x=0, y=0}) - localthunk.states.drag.can = false - - self.MAIN_MENU_UI = UIBox{ - definition = {n=G.UIT.ROOT, config = {align = "cm",colour = G.C.CLEAR}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.3}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {'Sign up for the next demo!'}, colours = {G.C.WHITE},shadow = true, rotate = true, float = true, bump = true, scale = 0.9, spacing = 1, pop_in = 4.5})}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.3}, nodes={ - {n=G.UIT.C, config={align = "cl", minw = 5, minh = 1}, nodes={ - UIBox_button{button = 'go_to_menu', colour = G.C.ORANGE, minw = 2, minh = 1, label = {'BACK'}, scale = 0.4, col = true}, - }}, - UIBox_button{id = 'demo_cta_playbalatro', button = "go_to_playbalatro", colour = G.C.BLUE, minw = 7.65, minh = 1.95, label = {'PLAYBALATRO.COM'}, scale = 0.9, col = true}, - {n=G.UIT.C, config={align = "cr", minw = 5, minh = 1}, nodes={ - {n=G.UIT.O, config={object = localthunk}}, - {n=G.UIT.O, config={object = playstack}}, - }} - }} - }}, - config = {align="bmi", offset = {x=0,y=10}, major = G.ROOM_ATTACH, bond = 'Weak'} - } - self.MAIN_MENU_UI.states.visible = false - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 4.05, - blockable = false, - blocking = false, - func = (function() - self.MAIN_MENU_UI.states.visible = true - self.MAIN_MENU_UI.alignment.offset.y = 0 - self.MAIN_MENU_UI:align_to_major() - G.CONTROLLER:snap_to{node = self.MAIN_MENU_UI:get_UIE_by_ID('demo_cta_playbalatro')} - return true - end) - })) -end - -function Game:init_game_object() - local cards_played = {} - for _,v in ipairs(SMODS.Rank.obj_buffer) do - cards_played[v] = { suits = {}, total = 0 } - end - local bosses_used = {} - for k, v in pairs(G.P_BLINDS) do - if v.boss then bosses_used[k] = 0 end - end - return { - won = false, - round_scores = { - furthest_ante = {label = 'Ante', amt = 0}, - furthest_round = {label = 'Round', amt = 0}, - hand = {label = 'Best Hand', amt = 0}, - poker_hand = {label = 'Most Played Hand', amt = 0}, - new_collection = {label = 'New Discoveries', amt = 0}, - cards_played = {label = 'Cards Played', amt = 0}, - cards_discarded = {label = 'Cards Discarded', amt = 0}, - times_rerolled = {label = 'Times Rerolled', amt = 0}, - cards_purchased = {label = 'Cards Purchased', amt = 0}, - }, - joker_usage = {}, - consumeable_usage = {}, - hand_usage = {}, - last_tarot_planet = nil, - win_ante = 8, - stake = 1, - modifiers = {}, - starting_params = get_starting_params(), - banned_keys = {}, - round = 0, - probabilities = { - normal = 1, - }, - bosses_used = bosses_used, - pseudorandom = {}, - starting_deck_size = 52, - ecto_minus = 1, - cry_bonusvouchercount = 0, - cry_bonusvouchersused = {}, - voucher_edition_index = {}, - voucher_sticker_index = {eternal = {}, perishable = {}, rental = {}, pinned = {}, banana = {}}, -- might as well - pack_size = 2, - skips = 0, - STOP_USE = 0, - edition_rate = 1, - joker_rate = 20, - tarot_rate = 4, - planet_rate = 4, - spectral_rate = 0, - playing_card_rate = 0, - consumeable_buffer = 0, - joker_buffer = 0, - discount_percent = 0, - interest_cap = 25, - interest_amount = 1, - inflation = 0, - hands_played = 0, - unused_discards = 0, - perishable_rounds = 5, - rental_rate = 3, - cry_voucher_perishable_rounds = 8, - cry_voucher_rental_rate = 2, - cry_consumeable_rental_rate = 2, - cry_voucher_banana_odds = 12, - cry_consumeable_banana_odds = 4, - cry_pinned_consumeables = 0, - cry_shop_joker_price_modifier = 1, - blind = nil, - chips = to_big(0), - chips_text = '0', - voucher_text = '', - dollars = 0, - max_jokers = 0, - bankrupt_at = 0, - current_boss_streak = 0, - base_reroll_cost = 5, - blind_on_deck = nil, - sort = 'desc', - previous_round = { - dollars = 4 - }, - tags = {}, - tag_tally = 0, - pool_flags = {}, - used_jokers = {}, - used_vouchers = {}, - cry_owned_vouchers = {}, - current_round = { - current_hand = { - chips = to_big(0), - chip_text = '0', - mult = 0, - mult_text = '0', - chip_total = 0, - chip_total_text = '', - cry_asc_num = 0, - cry_asc_num_text = '', - handname = "", - hand_level = '' - }, - used_packs = {}, - cry_bonusvouchers = {}, - cry_voucher_stickers = {eternal = false, perishable = false, rental = false, pinned = false, banana = false}, - cry_voucher_edition = {}, - cards_flipped = 0, - round_text = 'Round ', - idol_card = {suit = 'Spades', rank = 'Ace'}, - mail_card = {rank = 'Ace'}, - ancient_card = {suit = 'Spades'}, - castle_card = {suit = 'Spades'}, - hands_left = 0, - hands_played = 0, - discards_left = 0, - discards_used = 0, - dollars = 0, - reroll_cost = 5, - reroll_cost_increase = 0, - jokers_purchased = 0, - free_rerolls = 0, - round_dollars = 0, - dollars_to_be_earned = '!!!', - most_played_poker_hand = 'High Card', - }, - round_resets = { - hands = 1, - discards = 1, - reroll_cost = 1, - temp_reroll_cost = nil, - temp_handsize = nil, - ante = 1, - ante_disp = number_format(1), - blind_ante = 1, - blind_states = {Small = 'Select', Big = 'Upcoming', Boss = 'Upcoming'}, - loc_blind_states = {Small = '', Big = '', Boss = ''}, - blind_choices = {Small = 'bl_small', Big = 'bl_big'}, - boss_rerolled = false, - }, - round_bonus = { - next_hands = 0, - discards = 0, - }, - shop = { - joker_max = 2, - }, - cards_played = cards_played, - disabled_suits = {}, - disabled_ranks = {}, - hands = { - ["Flush Five"] = {visible = false, order = 1, mult = 16, chips = 160, s_mult = 16, s_chips = 160, level = 1, l_mult = 3, l_chips = 50, played = 0, played_this_round = 0, example = {{'S_A', true},{'S_A', true},{'S_A', true},{'S_A', true},{'S_A', true}}}, - ["Flush House"] = {visible = false, order = 2, mult = 14, chips = 140, s_mult = 14, s_chips = 140, level = 1, l_mult = 4, l_chips = 40, played = 0, played_this_round = 0, example = {{'D_7', true},{'D_7', true},{'D_7', true},{'D_4', true},{'D_4', true}}}, - ["Five of a Kind"] = {visible = false, order = 3, mult = 12, chips = 120, s_mult = 12, s_chips = 120, level = 1, l_mult = 3, l_chips = 35, played = 0, played_this_round = 0, example = {{'S_A', true},{'H_A', true},{'H_A', true},{'C_A', true},{'D_A', true}}}, - ["Straight Flush"] = {visible = true, order = 4, mult = 8, chips = 100, s_mult = 8, s_chips = 100, level = 1, l_mult = 4, l_chips = 40, played = 0, played_this_round = 0, example = {{'S_Q', true},{'S_J', true},{'S_T', true},{'S_9', true},{'S_8', true}}}, - ["Four of a Kind"] = {visible = true, order = 5, mult = 7, chips = 60, s_mult = 7, s_chips = 60, level = 1, l_mult = 3, l_chips = 30, played = 0, played_this_round = 0, example = {{'S_J', true},{'H_J', true},{'C_J', true},{'D_J', true},{'C_3', false}}}, - ["Full House"] = {visible = true, order = 6, mult = 4, chips = 40, s_mult = 4, s_chips = 40, level = 1, l_mult = 2, l_chips = 25, played = 0, played_this_round = 0, example = {{'H_K', true},{'C_K', true},{'D_K', true},{'S_2', true},{'D_2', true}}}, - ["Flush"] = {visible = true, order = 7, mult = 4, chips = 35, s_mult = 4, s_chips = 35, level = 1, l_mult = 2, l_chips = 15, played = 0, played_this_round = 0, example = {{'H_A', true},{'H_K', true},{'H_T', true},{'H_5', true},{'H_4', true}}}, - ["Straight"] = {visible = true, order = 8, mult = 4, chips = 30, s_mult = 4, s_chips = 30, level = 1, l_mult = 3, l_chips = 30, played = 0, played_this_round = 0, example = {{'D_J', true},{'C_T', true},{'C_9', true},{'S_8', true},{'H_7', true}}}, - ["Three of a Kind"] = {visible = true, order = 9, mult = 3, chips = 30, s_mult = 3, s_chips = 30, level = 1, l_mult = 2, l_chips = 20, played = 0, played_this_round = 0, example = {{'S_T', true},{'C_T', true},{'D_T', true},{'H_6', false},{'D_5', false}}}, - ["Two Pair"] = {visible = true, order = 10,mult = 2, chips = 20, s_mult = 2, s_chips = 20, level = 1, l_mult = 1, l_chips = 20, played = 0, played_this_round = 0, example = {{'H_A', true},{'D_A', true},{'C_Q', false},{'H_4', true},{'C_4', true}}}, - ["Pair"] = {visible = true, order = 11,mult = 2, chips = 10, s_mult = 2, s_chips = 10, level = 1, l_mult = 1, l_chips = 15, played = 0, played_this_round = 0, example = {{'S_K', false},{'S_9', true},{'D_9', true},{'H_6', false},{'D_3', false}}}, - ["High Card"] = {visible = true, order = 12,mult = 1, chips = 5, s_mult = 1, s_chips = 5, level = 1, l_mult = 1, l_chips = 10, played = 0, played_this_round = 0, example = {{'S_A', true},{'D_Q', false},{'D_9', false},{'C_4', false},{'D_3', false}}}, - } - } -end - -function Game:start_run(args) - args = args or {} - - local saveTable = args.savetext or nil - G.SAVED_GAME = nil - - self:prep_stage(G.STAGES.RUN, saveTable and saveTable.STATE or G.STATES.BLIND_SELECT) - - G.STAGE = G.STAGES.RUN - if saveTable then - check_for_unlock({type = 'continue_game'}) - end - - G.STATE_COMPLETE = false - G.RESET_BLIND_STATES = true - - if not saveTable then ease_background_colour_blind(G.STATE, 'Small Blind') - else ease_background_colour_blind(G.STATE, saveTable.BLIND.name:gsub("%s+", "") ~= '' and saveTable.BLIND.name or 'Small Blind') end - - local selected_back = saveTable and saveTable.BACK.name or (args.challenge and args.challenge.deck and args.challenge.deck.type) or (self.GAME.viewed_back and self.GAME.viewed_back.name) or self.GAME.selected_back and self.GAME.selected_back.name or 'Red Deck' - selected_back = get_deck_from_name(selected_back) - self.GAME = saveTable and saveTable.GAME or self:init_game_object() - if (not saveTable or not saveTable.GAME) and Talisman and Talisman.igo then self.GAME = Talisman.igo(self.GAME) end - Handy.UI.init() - self.GAME.modifiers = self.GAME.modifiers or {} - self.GAME.stake = args.stake or self.GAME.stake or 1 - self.GAME.STOP_USE = 0 - self.GAME.selected_back = Back(selected_back) - self.GAME.selected_back_key = selected_back - G.GAME.cry_voucher_centers = {} - for k, v in pairs(G.P_CENTERS) do - if v.set == 'Voucher' then - G.GAME.cry_voucher_centers[k] = {config = {}} - G.GAME.cry_voucher_centers[k].config = copy_table(v.config) - end - end - - G.C.UI_CHIPS[1], G.C.UI_CHIPS[2], G.C.UI_CHIPS[3], G.C.UI_CHIPS[4] = G.C.BLUE[1], G.C.BLUE[2], G.C.BLUE[3], G.C.BLUE[4] - G.C.UI_MULT[1], G.C.UI_MULT[2], G.C.UI_MULT[3], G.C.UI_MULT[4] = G.C.RED[1], G.C.RED[2], G.C.RED[3], G.C.RED[4] - - if not saveTable then - if false then - if self.GAME.stake >= 2 then - self.GAME.modifiers.no_blind_reward = self.GAME.modifiers.no_blind_reward or {} - self.GAME.modifiers.no_blind_reward.Small = true - end - if self.GAME.stake >= 3 then self.GAME.modifiers.scaling = 2 end - if self.GAME.stake >= 4 then self.GAME.modifiers.enable_eternals_in_shop = true end - if self.GAME.stake >= 5 then self.GAME.starting_params.discards = self.GAME.starting_params.discards - 1 end - if self.GAME.stake >= 6 then self.GAME.modifiers.scaling = 3 end - if self.GAME.stake >= 7 then self.GAME.modifiers.enable_perishables_in_shop = true end - if self.GAME.stake >= 8 then self.GAME.modifiers.enable_rentals_in_shop = true end - end SMODS.setup_stake(self.GAME.stake) - - self.GAME.selected_back:apply_to_run() - - if args.challenge then - self.GAME.challenge = args.challenge.id - self.GAME.challenge_tab = args.challenge - local _ch = args.challenge - if _ch.jokers then - for k, v in ipairs(_ch.jokers) do - G.E_MANAGER:add_event(Event({ - func = function() - local _joker = add_joker(v.id, v.edition, k ~= 1) - if v.eternal then _joker:set_eternal(true) end - if v.pinned then _joker.pinned = true end - return true - end - })) - end - end - if _ch.consumeables then - for k, v in ipairs(_ch.consumeables) do - G.E_MANAGER:add_event(Event({ - func = function() - add_joker(v.id, nil, k ~= 1) - return true - end - })) - end - end - if _ch.vouchers then - for k, v in ipairs(_ch.vouchers) do - G.GAME.used_vouchers[v.id] = true - G.GAME.cry_owned_vouchers[v.id] = true - G.E_MANAGER:add_event(Event({ - func = function() - G.GAME.starting_voucher_count = (G.GAME.starting_voucher_count or 0) + 1 - Card.apply_to_run(nil, G.P_CENTERS[v.id]) - return true - end - })) - end - end - if _ch.rules then - if _ch.rules.modifiers then - for k, v in ipairs(_ch.rules.modifiers) do - self.GAME.starting_params[v.id] = v.value - end - end - if _ch.rules.custom then - for k, v in ipairs(_ch.rules.custom) do - if v.id == 'no_reward' then - self.GAME.modifiers.no_blind_reward = self.GAME.modifiers.no_blind_reward or {} - self.GAME.modifiers.no_blind_reward.Small = true - self.GAME.modifiers.no_blind_reward.Big = true - self.GAME.modifiers.no_blind_reward.Boss = true - elseif v.id == 'no_reward_specific' then - self.GAME.modifiers.no_blind_reward = self.GAME.modifiers.no_blind_reward or {} - self.GAME.modifiers.no_blind_reward[v.value] = true - elseif v.value then - self.GAME.modifiers[v.id] = v.value - elseif v.id == 'no_shop_jokers' then - self.GAME.joker_rate = 0 - else - self.GAME.modifiers[v.id] = true - end - end - end - end - if _ch.restrictions then - if _ch.restrictions.banned_cards then - for k, v in ipairs(_ch.restrictions.banned_cards) do - G.GAME.banned_keys[v.id] = true - if v.ids then - for kk, vv in ipairs(v.ids) do - G.GAME.banned_keys[vv] = true - end - end - end - end - if _ch.restrictions.banned_tags then - for k, v in ipairs(_ch.restrictions.banned_tags) do - G.GAME.banned_keys[v.id] = true - end - end - if _ch.restrictions.banned_other then - for k, v in ipairs(_ch.restrictions.banned_other) do - G.GAME.banned_keys[v.id] = true - end - end - end - end - - self.GAME.round_resets.hands = self.GAME.starting_params.hands - self.GAME.round_resets.discards = self.GAME.starting_params.discards - self.GAME.round_resets.reroll_cost = self.GAME.starting_params.reroll_cost - self.GAME.dollars = self.GAME.starting_params.dollars - self.GAME.base_reroll_cost = self.GAME.starting_params.reroll_cost - self.GAME.round_resets.reroll_cost = self.GAME.base_reroll_cost - self.GAME.current_round.reroll_cost = self.GAME.base_reroll_cost - end - - G.GAME.chips_text = '' - - if not saveTable then - if args.seed then self.GAME.seeded = true end - self.GAME.pseudorandom.seed = args.seed or (not (G.SETTINGS.tutorial_complete or G.SETTINGS.tutorial_progress.completed_parts['big_blind']) and "TUTORIAL") or generate_starting_seed() - end - - for k, v in pairs(self.GAME.pseudorandom) do if v == 0 then self.GAME.pseudorandom[k] = pseudohash(k..self.GAME.pseudorandom.seed) end end - self.GAME.pseudorandom.hashed_seed = pseudohash(self.GAME.pseudorandom.seed) - if G.GAME.modifiers.cry_misprint_min and not args.savetext then - for k, v in pairs(G.GAME.hands) do - v.chips = to_big(cry_format(v.chips * cry_log_random(pseudoseed('cry_misprint'),G.GAME.modifiers.cry_misprint_min,G.GAME.modifiers.cry_misprint_max),"%.2g")) - v.mult = to_big(cry_format(v.mult * cry_log_random(pseudoseed('cry_misprint'),G.GAME.modifiers.cry_misprint_min,G.GAME.modifiers.cry_misprint_max),"%.2g")) - v.l_chips = cry_format(v.l_chips * cry_log_random(pseudoseed('cry_misprint'),G.GAME.modifiers.cry_misprint_min,G.GAME.modifiers.cry_misprint_max),"%.2g") - v.l_mult = cry_format(v.l_mult * cry_log_random(pseudoseed('cry_misprint'),G.GAME.modifiers.cry_misprint_min,G.GAME.modifiers.cry_misprint_max),"%.2g") - v.s_chips = v.chips - v.s_mult = v.mult - end - end - - G:save_settings() - - if not self.GAME.round_resets.blind_tags then - self.GAME.round_resets.blind_tags = {} - end - - if not saveTable then - if G.GAME.modifiers.cry_big_boss_rate and pseudorandom('cry_big_boss') < G.GAME.modifiers.cry_big_boss_rate then - self.GAME.round_resets.blind_choices.Big = get_new_boss() - elseif G.GAME.modifiers.cry_rush_hour_ii then - self.GAME.round_resets.blind_choices.Small = get_new_boss() - self.GAME.round_resets.blind_choices.Big = get_new_boss() - else - self.GAME.round_resets.blind_choices.Big = 'bl_big' - end - self.GAME.round_resets.blind_choices.Boss = get_new_boss() - if not self.GAME.modifiers.cry_no_vouchers then - if not G.GAME.modifiers.cry_voucher_restock_antes or G.GAME.round_resets.ante % G.GAME.modifiers.cry_voucher_restock_antes == 0 then - self.GAME.current_round.voucher = G.SETTINGS.tutorial_progress and G.SETTINGS.tutorial_progress.forced_voucher or get_next_voucher_key() - for i = 1, self.GAME.cry_bonusvouchercount do - self.GAME.current_round.cry_bonusvouchers[i] = get_next_voucher_key() - end - end - else - very_fair_quip = pseudorandom_element(G.localization.misc.very_fair_quips, pseudoseed("cry_very_fair")) - end - self.GAME.current_round.cry_voucher_edition = cry_get_next_voucher_edition() - self.GAME.current_round.cry_voucher_stickers = cry_get_next_voucher_stickers() - self.GAME.round_resets.blind_tags.Small = G.SETTINGS.tutorial_progress and G.SETTINGS.tutorial_progress.forced_tags and G.SETTINGS.tutorial_progress.forced_tags[1] or get_next_tag_key() - self.GAME.round_resets.blind_tags.Big = G.SETTINGS.tutorial_progress and G.SETTINGS.tutorial_progress.forced_tags and G.SETTINGS.tutorial_progress.forced_tags[2] or get_next_tag_key() - else - if self.GAME.round_resets.blind and self.GAME.round_resets.blind.key then - self.GAME.round_resets.blind = G.P_BLINDS[self.GAME.round_resets.blind.key] - end - end - G.CONTROLLER.locks.load = true - G.E_MANAGER:add_event(Event({ - no_delete = true, - trigger = 'after', - blocking = false,blockable = false, - delay = 3.5, - timer = 'TOTAL', - func = function() - G.CONTROLLER.locks.load = nil - return true - end - })) - - if saveTable and saveTable.ACTION then - G.E_MANAGER:add_event(Event({delay = 0.5, trigger = 'after', blocking = false,blockable = false,func = (function() - G.E_MANAGER:add_event(Event({func = (function() - G.E_MANAGER:add_event(Event({func = (function() - for k, v in pairs(G.I.CARD) do - if v.sort_id == saveTable.ACTION.card then - G.FUNCS.use_card({config = {ref_table = v}}, nil, true) - end - end - return true - end) - })) - return true - end) - })) - return true - end) - })) - end - - local CAI = { - discard_W = G.CARD_W, - discard_H = G.CARD_H, - deck_W = G.CARD_W*1.1, - deck_H = 0.95*G.CARD_H, - hand_W = 6*G.CARD_W, - hand_H = 0.95*G.CARD_H, - play_W = 5.3*G.CARD_W, - play_H = 0.95*G.CARD_H, - joker_W = 4.9*G.CARD_W, - joker_H = 0.95*G.CARD_H, - consumeable_W = 2.3*G.CARD_W, - consumeable_H = 0.95*G.CARD_H - } - - - if not G.GAME.modifiers.cry_beta then - self.consumeables = CardArea( - 0, 0, - CAI.consumeable_W, - CAI.consumeable_H, - {card_limit = self.GAME.starting_params.consumable_slots, type = 'joker', highlight_limit = 1e100}) - - self.jokers = CardArea( - 0, 0, - CAI.joker_W, - CAI.joker_H, - {card_limit = self.GAME.starting_params.joker_slots, type = 'joker', highlight_limit = 1e100}) - - else - self.jokers = CardArea( - 0, 0, - CAI.joker_W+CAI.consumeable_W, - CAI.joker_H, - {card_limit = self.GAME.starting_params.joker_slots+self.GAME.starting_params.consumable_slots-1, type = 'joker', highlight_limit = 1e100}) - self.consumeables = self.jokers - end - self.discard = CardArea( - 0, 0, - CAI.discard_W,CAI.discard_H, - {card_limit = 1e308, type = 'discard'}) - self.deck = CardArea( - 0, 0, - CAI.deck_W,CAI.deck_H, - {card_limit = 52, type = 'deck'}) - self.hand = CardArea( - 0, 0, - CAI.hand_W,CAI.hand_H, - {card_limit = self.GAME.starting_params.hand_size, type = 'hand'}) - self.play = CardArea( - 0, 0, - CAI.play_W,CAI.play_H, - {card_limit = 5, type = 'play'}) - - G.playing_cards = {} - - set_screen_positions() - - G.SPLASH_BACK = Sprite(-30, -6, G.ROOM.T.w+60, G.ROOM.T.h+12, G.ASSET_ATLAS["ui_1"], {x = 2, y = 0}) - G.SPLASH_BACK:set_alignment({ - major = G.play, - type = 'cm', - bond = 'Strong', - offset = {x=0,y=0} - }) - - G.ARGS.spin = { - amount = 0, - real = 0, - eased = 0 - } - - G.SPLASH_BACK:define_draw_steps({{ - shader = 'background', - send = { - {name = 'time', ref_table = G.TIMERS, ref_value = 'REAL_SHADER'}, - {name = 'spin_time', ref_table = G.TIMERS, ref_value = 'BACKGROUND'}, - {name = 'colour_1', ref_table = G.C.BACKGROUND, ref_value = 'C'}, - {name = 'colour_2', ref_table = G.C.BACKGROUND, ref_value = 'L'}, - {name = 'colour_3', ref_table = G.C.BACKGROUND, ref_value = 'D'}, - {name = 'contrast', ref_table = G.C.BACKGROUND, ref_value = 'contrast'}, - {name = 'spin_amount', ref_table = G.ARGS.spin, ref_value = 'amount'} - }}}) - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - blocking = false, - blockable = false, - func = (function() - local _dt = G.ARGS.spin.amount > G.ARGS.spin.eased and G.real_dt*2. or 0.3*G.real_dt - local delta = G.ARGS.spin.real - G.ARGS.spin.eased - if math.abs(delta) > _dt then delta = delta*_dt/math.abs(delta) end - G.ARGS.spin.eased = G.ARGS.spin.eased + delta - G.ARGS.spin.amount = _dt*(G.ARGS.spin.eased) + (1 - _dt)*G.ARGS.spin.amount - G.TIMERS.BACKGROUND = G.TIMERS.BACKGROUND - 60*(G.ARGS.spin.eased - G.ARGS.spin.amount)*_dt - end) - })) - - if saveTable then - local cardAreas = saveTable.cardAreas - for k, v in pairs(cardAreas) do - if G[k] then G[k]:load(v) - else - G['load_'..k] = v - print("ERROR LOADING GAME: Card area '"..k.."' not instantiated before load") end - end - - for k, v in pairs(G.I.CARD) do - if v.playing_card then - table.insert(G.playing_cards, v) - end - end - for k, v in pairs(G.I.CARDAREA) do - v:align_cards() - v:hard_set_cards() - end - table.sort(G.playing_cards, function (a, b) return a.playing_card > b.playing_card end ) - else - local card_protos = nil - local _de = nil - if args.challenge and args.challenge.deck then - _de = args.challenge.deck - end - - if _de and _de.cards then - card_protos = _de.cards - end - - if not card_protos then - card_protos = {} - for k, v in pairs(self.P_CARDS) do - if type(SMODS.Ranks[v.value].in_pool) == 'function' and not SMODS.Ranks[v.value]:in_pool({initial_deck = true, suit = v.suit}) - or type(SMODS.Suits[v.suit].in_pool) == 'function' and not SMODS.Suits[v.suit]:in_pool({initial_deck = true, rank = v.value}) then - goto continue - end - local _ = nil - if self.GAME.starting_params.erratic_suits_and_ranks then - v, k = pseudorandom_element(G.P_CARDS, pseudoseed('erratic'), {starting_deck = true}) - end - local _r, _s = SMODS.Ranks[v.value].card_key, SMODS.Suits[v.suit].card_key - local keep, _e, _d, _g = true, nil, nil, nil - if _de then - if _de.yes_ranks and not _de.yes_ranks[_r] then keep = false end - if _de.no_ranks and _de.no_ranks[_r] then keep = false end - if _de.yes_suits and not _de.yes_suits[_s] then keep = false end - if _de.no_suits and _de.no_suits[_s] then keep = false end - if _de.enhancement then _e = _de.enhancement end - if _de.edition then _d = _de.edition end - if _de.gold_seal then _g = _de.gold_seal end - end - - if self.GAME.starting_params.no_faces and SMODS.Ranks[v.value].face then keep = false end - - if keep then card_protos[#card_protos+1] = {s=_s,r=_r,e=_e,d=_d,g=_g} end - ::continue:: - end - end - - if self.GAME.starting_params.extra_cards then - for k, v in pairs(self.GAME.starting_params.extra_cards) do - card_protos[#card_protos+1] = v - end - end - - table.sort(card_protos, function (a, b) return - ((a.s or '')..(a.r or '')..(a.e or '')..(a.d or '')..(a.g or '')) < - ((b.s or '')..(b.r or '')..(b.e or '')..(b.d or '')..(b.g or '')) end) - - for k, v in ipairs(card_protos) do - card_from_control(v) - end - - if G.GAME.modifiers.cry_ccd then - for k, v in pairs(G.playing_cards) do - v:set_ability(get_random_consumable('cry_ccd',{"no_doe", "no_grc"}, nil, nil, true), true, nil) - end - end - self.GAME.starting_deck_size = #G.playing_cards - end - - delay(0.5) - - if not saveTable then - G.GAME.current_round.discards_left = G.GAME.round_resets.discards - G.GAME.current_round.hands_left = G.GAME.round_resets.hands - self.deck:shuffle() - self.deck:hard_set_T() - reset_idol_card() - reset_mail_rank() - self.GAME.current_round.ancient_card.suit = nil - reset_ancient_card() - reset_castle_card() for _, mod in ipairs(SMODS.mod_list) do - if mod.reset_game_globals and type(mod.reset_game_globals) == 'function' then - mod.reset_game_globals(true) - end - end - end - - G.GAME.blind = Blind(0,0,2, 1) - self.deck:align_cards() - self.deck:hard_set_cards() - - self.HUD = UIBox{ - definition = create_UIBox_HUD(), - config = {align=('cli'), offset = {x=-0.7,y=0},major = G.ROOM_ATTACH} - } - self.HUD_blind = UIBox{ - definition = create_UIBox_HUD_blind(), - config = {major = G.HUD:get_UIE_by_ID('row_blind_bottom'), align = 'bmi', offset = {x=0,y=-10}, bond = 'Weak'} - } - self.HUD_tags = {} - - G.hand_text_area = { - chips = self.HUD:get_UIE_by_ID('hand_chips'), - mult = self.HUD:get_UIE_by_ID('hand_mult'), - ante = self.HUD:get_UIE_by_ID('ante_UI_count'), - round = self.HUD:get_UIE_by_ID('round_UI_count'), - chip_total = self.HUD:get_UIE_by_ID('hand_chip_total'), - handname = self.HUD:get_UIE_by_ID('hand_name'), - hand_level = self.HUD:get_UIE_by_ID('hand_level'), - game_chips = self.HUD:get_UIE_by_ID('chip_UI_count'), - blind_chips = self.HUD_blind:get_UIE_by_ID('HUD_blind_count'), - blind_spacer = self.HUD:get_UIE_by_ID('blind_spacer') - } - - check_and_set_high_score('most_money', G.GAME.dollars) - - if saveTable then - G.GAME.blind:load(saveTable.BLIND) - G.GAME.tags = {} - local tags = saveTable.tags or {} - for k, v in ipairs(tags) do - local _tag = Tag('tag_uncommon') - _tag:load(v) - add_tag(_tag, nil, true) - end - else - G.GAME.blind:set_blind(nil, nil, true) - reset_blinds() - end - - Cartomancer.update_tags_visibility() - G.FUNCS.blind_chip_UI_scale(G.hand_text_area.blind_chips) - - self.HUD:recalculate() - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - unlock_notify() - return true - end) - })) - -end - -function Game:update(dt) - nuGC(nil, nil, true) - - G.MAJORS = 0 - G.MINORS = 0 - - G.FRAMES.MOVE = G.FRAMES.MOVE + 1 - timer_checkpoint('start->discovery', 'update') - if not G.SETTINGS.tutorial_complete then G.FUNCS.tutorial_controller() end - timer_checkpoint('tallies', 'update') - modulate_sound(dt) - timer_checkpoint('sounds', 'update') - update_canvas_juice(dt) - timer_checkpoint('canvas and juice', 'update') - --Smooth out the dts to avoid any big jumps - self.TIMERS.REAL = self.TIMERS.REAL + dt - self.TIMERS.REAL_SHADER = G.SETTINGS.reduced_motion and 300 or self.TIMERS.REAL - self.TIMERS.UPTIME = self.TIMERS.UPTIME + dt - self.SETTINGS.DEMO.total_uptime = (self.SETTINGS.DEMO.total_uptime or 0) + dt - self.TIMERS.BACKGROUND = self.TIMERS.BACKGROUND + dt*(G.ARGS.spin and G.ARGS.spin.amount or 0) - self.real_dt = dt - - if require('debugplus.config').getValue('enableLongDT') and self.real_dt > 0.05 then print('LONG DT @ '..math.floor(G.TIMERS.REAL)..': '..self.real_dt) end - if not G.fbf or G.new_frame then - G.new_frame = false - - set_alerts() - timer_checkpoint('alerts', 'update') - - local http_resp = G.HTTP_MANAGER.in_channel:pop() - if http_resp then - G.ARGS.HIGH_SCORE_RESPONSE = http_resp - end - - - if G.SETTINGS.paused then dt = 0 end - - if G.STATE ~= G.ACC_state then G.ACC = 0 end - G.ACC_state = G.STATE - - if (G.STATE == G.STATES.HAND_PLAYED) or (G.STATE == G.STATES.NEW_ROUND) or Incantation and Incantation.accelerate then - G.ACC = math.min((G.ACC or 0) + dt*0.2*self.SETTINGS.GAMESPEED, 16) - elseif Handy.insta_cash_out.is_skipped then G.ACC = 999 - else - G.ACC = 0 - end - - self.SPEEDFACTOR = (G.STAGE == G.STAGES.RUN and not G.SETTINGS.paused and not G.screenwipe) and self.SETTINGS.GAMESPEED or 1 - self.SPEEDFACTOR = self.SPEEDFACTOR + math.max(0, math.abs(G.ACC) - 2) - self.SPEEDFACTOR = self.SPEEDFACTOR * Handy.speed_multiplier.value or 1 - - self.TIMERS.TOTAL = self.TIMERS.TOTAL + dt*(self.SPEEDFACTOR) - - self.C.DARK_EDITION[1] = 0.6+0.2*math.sin(self.TIMERS.REAL*1.3) - self.C.DARK_EDITION[3] = 0.6+0.2*(1- math.sin(self.TIMERS.REAL*1.3)) - self.C.DARK_EDITION[2] = math.min(self.C.DARK_EDITION[3], self.C.DARK_EDITION[1]) - - self.C.EDITION[1] = 0.7+0.2*(1+math.sin(self.TIMERS.REAL*1.5 + 0)) - self.C.EDITION[3] = 0.7+0.2*(1+math.sin(self.TIMERS.REAL*1.5 + 3)) - self.C.EDITION[2] = 0.7+0.2*(1+math.sin(self.TIMERS.REAL*1.5 + 6)) - for k, v in pairs(SMODS.Rarities) do - if v.gradient and type(v.gradient) == "function" then v:gradient(dt) end - end - - - self.E_MANAGER:update(self.real_dt) - timer_checkpoint('e_manager', 'update') - - if G.GAME.blind and G.boss_throw_hand and self.STATE == self.STATES.SELECTING_HAND then - if not self.boss_warning_text then - self.boss_warning_text = UIBox{ - definition = - {n=G.UIT.ROOT, config = {align = 'cm', colour = G.C.CLEAR, padding = 0.2}, nodes={ - {n=G.UIT.R, config = {align = 'cm', maxw = 1}, nodes={ - {n=G.UIT.O, config={object = DynaText({scale = 0.7, string = localize('ph_unscored_hand'), maxw = 9, colours = {G.C.WHITE},float = true, shadow = true, silent = true, pop_in = 0, pop_in_rate = 6})}}, - }}, - {n=G.UIT.R, config = {align = 'cm', maxw = 1}, nodes={ - {n=G.UIT.O, config={object = DynaText({scale = 0.6, string = G.GAME.blind:get_loc_debuff_text(), maxw = 9, colours = {G.C.WHITE},float = true, shadow = true, silent = true, pop_in = 0, pop_in_rate = 6})}}, - }} - }}, - config = { - align = 'cm', - offset ={x=0,y=-3.1}, - major = G.play, - } - } - self.boss_warning_text.attention_text = true - self.boss_warning_text.states.collide.can = false - G.GAME.blind.children.animatedSprite:juice_up(0.05, 0.02) - play_sound('chips1', math.random()*0.1 + 0.55, 0.12) - end - else - G.boss_throw_hand = nil - if self.boss_warning_text then - self.boss_warning_text:remove() - self.boss_warning_text = nil - end - end - - - if G.GAME.USING_RUN then - if not (self.STATE == self.STATES.STANDARD_PACK or self.STATE == self.STATES.BUFFOON_PACK or self.STATE == self.STATES.PLANET_PACK or self.STATE == self.STATES.TAROT_PACK or self.STATE == self.STATES.SPECTRAL_PACK or self.STATE == self.STATES.SMODS_BOOSTER_OPENED) then -- do you are have stupid - self.STATE = self.STATES.SHOP - end - if G.GAME.blind then G.GAME.blind:change_colour() end -- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - if G.load_cry_runarea then - G.cry_runarea = CardArea( - G.discard.T.x, - G.discard.T.y, - G.discard.T.w, - G.discard.T.h, - { type = "discard", card_limit = 1e100 } - ) - G.cry_runarea:load(G.load_cry_runarea) - G.load_cry_runarea = nil - end - end - if self.STATE == self.STATES.SELECTING_HAND then - if (not G.hand.cards[1]) and G.deck.cards[1] then - G.STATE = G.STATES.DRAW_TO_HAND - G.STATE_COMPLETE = false - else - self:update_selecting_hand(dt) - end - end - - if self.STATE == self.STATES.SHOP then - self:update_shop(dt) - end - - if self.STATE == self.STATES.PLAY_TAROT then - self:update_play_tarot(dt) - end - - if self.STATE == self.STATES.HAND_PLAYED then - self:update_hand_played(dt) - end - - if self.STATE == self.STATES.DRAW_TO_HAND then - self:update_draw_to_hand(dt) - end - - if self.STATE == self.STATES.NEW_ROUND then - self:update_new_round(dt) - end - - if self.STATE == self.STATES.BLIND_SELECT then - self:update_blind_select(dt) - end - - if self.STATE == self.STATES.ROUND_EVAL then - self:update_round_eval(dt) - end - - if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then - SMODS.OPENED_BOOSTER.config.center:update_pack(dt) - end - - if self.STATE == self.STATES.TAROT_PACK then - self:update_arcana_pack(dt) - end - - if self.STATE == self.STATES.SPECTRAL_PACK then - self:update_spectral_pack(dt) - end - - if self.STATE == self.STATES.STANDARD_PACK then - self:update_standard_pack(dt) - end - - if self.STATE == self.STATES.BUFFOON_PACK then - self:update_buffoon_pack(dt) - end - - if self.STATE == self.STATES.PLANET_PACK then - self:update_celestial_pack(dt) - end - - if self.STATE == self.STATES.GAME_OVER then - self:update_game_over(dt) - end - - if self.STATE == self.STATES.MENU then - self:update_menu(dt) - end - timer_checkpoint('states', 'update') - --animate all animated objects - remove_nils(self.ANIMATIONS) - - for k, v in pairs(self.ANIMATIONS) do - v:animate(self.real_dt*self.SPEEDFACTOR) - end - timer_checkpoint('animate', 'update') - - --move and update all other moveables - G.exp_times.xy = math.exp(-50*self.real_dt) - G.exp_times.scale = math.exp(-60*self.real_dt) - G.exp_times.r = math.exp(-190*self.real_dt) - - local move_dt = math.min(1/20, self.real_dt) - - G.exp_times.max_vel = 70*move_dt - - for k, v in pairs(self.MOVEABLES) do - if v.FRAME.MOVE < G.FRAMES.MOVE then v:move(move_dt) end - end - timer_checkpoint('move', 'update') - - for k, v in pairs(self.MOVEABLES) do - v:update(dt*self.SPEEDFACTOR) - v.states.collide.is = false - end - timer_checkpoint('update', 'update') - end - - self.CONTROLLER:update(self.real_dt) - - --update loc strings if needed - if G.prev_small_state ~= G.GAME.round_resets.blind_states.Small or - G.prev_large_state ~= G.GAME.round_resets.blind_states.Big or - G.prev_boss_state ~= G.GAME.round_resets.blind_states.Boss or G.RESET_BLIND_STATES then - G.RESET_BLIND_STATES = nil - G.prev_small_state = G.GAME.round_resets.blind_states.Small - G.prev_large_state = G.GAME.round_resets.blind_states.Big - G.prev_boss_state = G.GAME.round_resets.blind_states.Boss - G.GAME.round_resets.loc_blind_states.Small = localize(G.GAME.round_resets.blind_states.Small,'blind_states') - G.GAME.round_resets.loc_blind_states.Big = localize(G.GAME.round_resets.blind_states.Big,'blind_states') - G.GAME.round_resets.loc_blind_states.Boss = localize(G.GAME.round_resets.blind_states.Boss,'blind_states') - end - - --Send all steam updates if needed - if G.STEAM and G.STEAM.send_control.update_queued and ( - G.STEAM.send_control.force or - G.STEAM.send_control.last_sent_stage ~= G.STAGE or - G.STEAM.send_control.last_sent_time < G.TIMERS.UPTIME - 120) then - if G.STEAM.userStats.storeStats() then - G.STEAM.send_control.force = false - G.STEAM.send_control.last_sent_stage = G.STAGE - G.STEAM.send_control.last_sent_time = G.TIMERS.UPTIME - G.STEAM.send_control.update_queued = false - else - G.DEBUG_VALUE = 'UNABLE TO STORE STEAM STATS' - end - end - - - if G.DEBUG then - local text_count,uie_count, card_count, uib_count, all = 0,0, 0, 0,0 - for k, v in pairs(G.STAGE_OBJECTS[G.STAGE]) do - all = all + 1 - if v:is(DynaText) then text_count = text_count + 1 end - if v:is(Card) then card_count = card_count + 1 end - if v:is(UIElement) then uie_count = uie_count + 1 end - if v:is(UIBox) then uib_count = uib_count + 1 end - end - - G.DEBUG_VALUE = 'text: '..text_count..'\n'.. - 'uie: '..uie_count..'\n'.. - 'card: '..card_count..'\n'.. - 'uib: '..uib_count..'\n'..'all: '..all - end - - --Save every 10 seconds, unless forced or paused/unpaused - if not GLOBAL_cry_member_count_delay then GLOBAL_cry_member_count_delay = 0 end - if (GLOBAL_cry_member_count_delay > 5) or not GLOBAL_cry_member_count then -- it doesn't need to update this frequently? but it also doesn't need to be higher tbh... - if update_cry_member_count then update_cry_member_count() end -- i honestly hate nil checks like this, wish there was a shorthand - GLOBAL_cry_member_count_delay = 0 - else - GLOBAL_cry_member_count_delay = GLOBAL_cry_member_count_delay + dt - end - if G.FILE_HANDLER and G.FILE_HANDLER and G.FILE_HANDLER.update_queued and ( - G.FILE_HANDLER.force or - G.FILE_HANDLER.last_sent_stage ~= G.STAGE or - ((G.FILE_HANDLER.last_sent_pause ~= G.SETTINGS.paused) and G.FILE_HANDLER.run) or - (not G.FILE_HANDLER.last_sent_time or (G.FILE_HANDLER.last_sent_time < (G.TIMERS.UPTIME - G.F_SAVE_TIMER)))) then - - if G.FILE_HANDLER.metrics then - G.SAVE_MANAGER.channel:push({ - type = 'save_metrics', - save_metrics = G.ARGS.save_metrics - }) - end - - if G.FILE_HANDLER.progress then - G.SAVE_MANAGER.channel:push({ - type = 'save_progress', - save_progress = G.ARGS.save_progress - }) - elseif G.FILE_HANDLER.settings then - G.SAVE_MANAGER.channel:push({ - type = 'save_settings', - save_settings = G.ARGS.save_settings, - profile_num = G.SETTINGS.profile, - save_profile = G.PROFILES[G.SETTINGS.profile] - }) - end - - if G.FILE_HANDLER.run then - G.SAVE_MANAGER.channel:push({ - type = 'save_run', - save_table = G.ARGS.save_run, - profile_num = G.SETTINGS.profile}) - G.SAVED_GAME = nil - end - - G.FILE_HANDLER.force = false - G.FILE_HANDLER.last_sent_stage = G.STAGE - G.FILE_HANDLER.last_sent_time = G.TIMERS.UPTIME - G.FILE_HANDLER.last_sent_pause = G.SETTINGS.paused - G.FILE_HANDLER.settings = nil - G.FILE_HANDLER.progress = nil - G.FILE_HANDLER.metrics = nil - G.FILE_HANDLER.run = nil - end -end - -function Game:draw() - G.FRAMES.DRAW = G.FRAMES.DRAW + 1 - --draw the room - reset_drawhash() - if G.OVERLAY_TUTORIAL and not G.OVERLAY_MENU then G.under_overlay = true end - timer_checkpoint('start->canvas', 'draw') - love.graphics.setCanvas{self.CANVAS} - love.graphics.push() - love.graphics.scale(G.CANV_SCALE) - - love.graphics.setShader() - love.graphics.clear(0,0,0,1) - - if G.SPLASH_BACK then - if G.debug_background_toggle then - love.graphics.clear({0,1,0,1}) - else - love.graphics.push() - G.SPLASH_BACK:translate_container() - G.SPLASH_BACK:draw() - love.graphics.pop() - end - end - - if not G.debug_UI_toggle then - - for k, v in pairs(self.I.NODE) do - if not v.parent then - love.graphics.push() - v:translate_container() - v:draw() - love.graphics.pop() - end - end - - for k, v in pairs(self.I.MOVEABLE) do - if not v.parent then - love.graphics.push() - v:translate_container() - v:draw() - love.graphics.pop() - end - end - - if G.SPLASH_LOGO then - love.graphics.push() - G.SPLASH_LOGO:translate_container() - G.SPLASH_LOGO:draw() - love.graphics.pop() - end - - if G.debug_splash_size_toggle then - for k, v in pairs(self.I.CARDAREA) do - if not v.parent then - love.graphics.push() - v:translate_container() - v:draw() - love.graphics.pop() - end - end - else - if (not self.OVERLAY_MENU) or (not self.F_HIDE_BG) then - timer_checkpoint('primatives', 'draw') - for k, v in pairs(self.I.UIBOX) do - if not v.attention_text and not v.parent and v ~= self.OVERLAY_MENU and v ~= self.screenwipe and v ~= self.OVERLAY_TUTORIAL and v ~= self.debug_tools and v ~= self.online_leaderboard and v ~= self.achievement_notification then - love.graphics.push() - v:translate_container() - v:draw() - love.graphics.pop() - end - end - timer_checkpoint('uiboxes', 'draw') - for k, v in pairs(self.I.CARDAREA) do - if not v.parent then - love.graphics.push() - v:translate_container() - v:draw() - love.graphics.pop() - end - end - - for k, v in pairs(self.I.CARD) do - if (not v.parent and v ~= self.CONTROLLER.dragging.target and v ~= self.CONTROLLER.focused.target) then - love.graphics.push() - v:translate_container() - v:draw() - love.graphics.pop() - end - end - - for k, v in pairs(self.I.UIBOX) do - if v.attention_text and v ~= self.debug_tools and v ~= self.online_leaderboard and v ~= self.achievement_notification then - love.graphics.push() - v:translate_container() - v:draw() - love.graphics.pop() - end - end - - if G.SPLASH_FRONT then - love.graphics.push() - G.SPLASH_FRONT:translate_container() - G.SPLASH_FRONT:draw() - love.graphics.pop() - end - - G.under_overlay = false - if self.OVERLAY_TUTORIAL then - love.graphics.push() - self.OVERLAY_TUTORIAL:translate_container() - self.OVERLAY_TUTORIAL:draw() - love.graphics.pop() - - if self.OVERLAY_TUTORIAL.highlights then - for k, v in ipairs(self.OVERLAY_TUTORIAL.highlights) do - love.graphics.push() - v:translate_container() - v:draw() - if v.draw_children then - v:draw_self() - v:draw_children() - end - love.graphics.pop() - end - end - end - end - if (self.OVERLAY_MENU) or (not self.F_HIDE_BG) then - if self.OVERLAY_MENU and self.OVERLAY_MENU ~= self.CONTROLLER.dragging.target then - love.graphics.push() - self.OVERLAY_MENU:translate_container() - self.OVERLAY_MENU:draw() - love.graphics.pop() - end - end - - if self.debug_tools then - if self.debug_tools ~= self.CONTROLLER.dragging.target then - love.graphics.push() - self.debug_tools:translate_container() - self.debug_tools:draw() - love.graphics.pop() - end - end - - G.ALERT_ON_SCREEN = nil - for k, v in pairs(self.I.ALERT) do - love.graphics.push() - v:translate_container() - v:draw() - G.ALERT_ON_SCREEN = true - love.graphics.pop() - end - - if self.CONTROLLER.dragging.target and self.CONTROLLER.dragging.target ~= self.CONTROLLER.focused.target then - love.graphics.push() - G.CONTROLLER.dragging.target:translate_container() - G.CONTROLLER.dragging.target:draw() - love.graphics.pop() - end - - if self.CONTROLLER.focused.target and getmetatable(self.CONTROLLER.focused.target) == Card and - (self.CONTROLLER.focused.target.area ~= G.hand or self.CONTROLLER.focused.target == self.CONTROLLER.dragging.target) then - love.graphics.push() - G.CONTROLLER.focused.target:translate_container() - G.CONTROLLER.focused.target:draw() - love.graphics.pop() - end - - for k, v in pairs(self.I.POPUP) do - love.graphics.push() - v:translate_container() - v:draw() - love.graphics.pop() - end - - if self.achievement_notification then - love.graphics.push() - self.achievement_notification:translate_container() - self.achievement_notification:draw() - love.graphics.pop() - end - - - if self.screenwipe then - love.graphics.push() - self.screenwipe:translate_container() - self.screenwipe:draw() - love.graphics.pop() - end - - love.graphics.push() - self.CURSOR:translate_container() - love.graphics.translate(-self.CURSOR.T.w*G.TILESCALE*G.TILESIZE*0.5, -self.CURSOR.T.h*G.TILESCALE*G.TILESIZE*0.5) - self.CURSOR:draw() - love.graphics.pop() - timer_checkpoint('rest', 'draw') - end -end -love.graphics.pop() - - love.graphics.setCanvas(G.AA_CANVAS) - love.graphics.push() - love.graphics.setColor(G.C.WHITE) - if (not G.recording_mode or G.video_control )and true then - G.ARGS.eased_cursor_pos = G.ARGS.eased_cursor_pos or {x=G.CURSOR.T.x,y=G.CURSOR.T.y, sx = G.CONTROLLER.cursor_position.x, sy = G.CONTROLLER.cursor_position.y} - G.screenwipe_amt = G.screenwipe_amt and (0.95*G.screenwipe_amt + 0.05*((self.screenwipe and 0.4 or self.screenglitch and 0.4) or 0)) or 1 - G.SETTINGS.GRAPHICS.crt = G.SETTINGS.GRAPHICS.crt*0.3 - G.SHADERS['CRT']:send('distortion_fac', {1.0 + 0.07*G.SETTINGS.GRAPHICS.crt/100, 1.0 + 0.1*G.SETTINGS.GRAPHICS.crt/100}) - G.SHADERS['CRT']:send('scale_fac', {1.0 - 0.008*G.SETTINGS.GRAPHICS.crt/100, 1.0 - 0.008*G.SETTINGS.GRAPHICS.crt/100}) - G.SHADERS['CRT']:send('feather_fac', 0.01) - G.SHADERS['CRT']:send('bloom_fac', G.SETTINGS.GRAPHICS.bloom - 1) - G.SHADERS['CRT']:send('time',400 + G.TIMERS.REAL) - G.SHADERS['CRT']:send('noise_fac',0.001*G.SETTINGS.GRAPHICS.crt/100) - G.SHADERS['CRT']:send('crt_intensity', 0.16*G.SETTINGS.GRAPHICS.crt/100) - G.SHADERS['CRT']:send('glitch_intensity', glitched_intensity or 0) - G.SHADERS['CRT']:send('scanlines', G.CANVAS:getPixelHeight()*0.75/G.CANV_SCALE) - G.SHADERS['CRT']:send('mouse_screen_pos', G.video_control and {love.graphics.getWidth( )/2, love.graphics.getHeight( )/2} or {G.ARGS.eased_cursor_pos.sx, G.ARGS.eased_cursor_pos.sy}) - G.SHADERS['CRT']:send('screen_scale', G.TILESCALE*G.TILESIZE) - G.SHADERS['CRT']:send('hovering', 1) - love.graphics.setShader( G.SHADERS['CRT']) - G.SETTINGS.GRAPHICS.crt = G.SETTINGS.GRAPHICS.crt/0.3 - end - - love.graphics.draw(self.CANVAS, 0, 0) - love.graphics.pop() - - love.graphics.setCanvas() - love.graphics.setShader() - - if G.AA_CANVAS then - love.graphics.push() - love.graphics.scale(1/G.CANV_SCALE) - love.graphics.draw(G.AA_CANVAS, 0, 0) - love.graphics.pop() - end - - timer_checkpoint('canvas', 'draw') - - if require("debugplus.config").getValue("showHUD") and not G.video_control and G.F_VERBOSE then - love.graphics.push() - love.graphics.setColor(0, 1, 1,1) - local fps = love.timer.getFPS( ) - do - local otherSize = 0 - for k,v in pairs(G.E_MANAGER.queues or {}) do - if k ~= 'base' then - otherSize = otherSize + #v - end - end - if otherSize ~= 0 then - love.graphics.print(string.format("Current FPS: %d\nBase event queue: %d\nOther event queues: %d", fps, #(G.E_MANAGER.queues and G.E_MANAGER.queues.base or {}), otherSize), 10, 10) - else - love.graphics.print(string.format("Current FPS: %d\nBase event queue: %d", fps, #(G.E_MANAGER.queues and G.E_MANAGER.queues.base or {})), 10, 10) - end - end - - if G.check and G.SETTINGS.perf_mode then - local section_h = 30 - local resolution = 60*section_h - local poll_w = 1 - local v_off = 100 - for a, b in ipairs({G.check.update, G.check.draw}) do - for k, v in ipairs(b.checkpoint_list) do - love.graphics.setColor(0,0,0,0.2) - love.graphics.rectangle('fill', 12, 20 + v_off,poll_w+poll_w*#v.trend,-section_h + 5) - for kk, vv in ipairs(v.trend) do - if a == 2 then - love.graphics.setColor(0.3,0.7,0.7,1) - else - love.graphics.setColor(self:state_col(v.states[kk] or 123)) - end - love.graphics.rectangle('fill', 10+poll_w*kk, 20 + v_off, 5*poll_w, -(vv)*resolution) - end - v_off = v_off + section_h - end - local v_off = v_off - section_h * #b.checkpoint_list - for k, v in ipairs(b.checkpoint_list) do - love.graphics.setColor(a == 2 and 0.5 or 1, a == 2 and 1 or 0.5, 1,1) - love.graphics.print(v.label..': '..(string.format("%.2f",1000*(v.average or 0)))..'\n', 10, -section_h + 30 + v_off) - v_off = v_off + section_h - end - end - end - - love.graphics.pop() - end - timer_checkpoint('debug', 'draw') -end - -function Game:state_col(_state) - return (_state*15251252.2/5.132)%1, (_state*1422.5641311/5.42)%1, (_state*1522.1523122/5.132)%1, 1 -end - -function Game:update_selecting_hand(dt) - if not self.deck_preview and not G.OVERLAY_MENU and ( - (self.deck and self.deck.cards[1] and self.deck.cards[1].states.collide.is and ((not self.deck.cards[1].states.drag.is) or self.CONTROLLER.HID.touch) and (not self.CONTROLLER.HID.controller)) or - G.CONTROLLER.held_buttons.triggerleft) then - if self.buttons then - self.buttons.states.visible = false - end - self.deck_preview = UIBox{ - definition = self.UIDEF.deck_preview(), - config = {align='tm', offset = {x=0,y=-0.8},major = self.hand, bond = 'Weak'} - } - self.E_MANAGER:add_event(Event({ - blocking = false, - blockable = false, - func = function() - if self.deck_preview and not (((self.deck and self.deck.cards[1] and self.deck.cards[1].states.collide.is and not self.CONTROLLER.HID.controller)) or G.CONTROLLER.held_buttons.triggerleft) then - self.deck_preview:remove() - self.deck_preview = nil - local _card = G.CONTROLLER.focused.target - local start = G.TIMERS.REAL - self.E_MANAGER:add_event(Event({ - func = function() - if _card and _card.area and _card.area == G.hand then - local _x, _y = _card:put_focused_cursor() - G.CONTROLLER:update_cursor({x=_x/(G.TILESCALE*G.TILESIZE),y=_y/(G.TILESCALE*G.TILESIZE)}) - end - if start + 0.4 < G.TIMERS.REAL then - return true - end - end - })) - return true - end - end - })) - end - if not self.buttons and not self.deck_preview then - self.buttons = UIBox{ - definition = create_UIBox_buttons(), - config = {align="bm", offset = {x=0,y=0.3},major = G.hand, bond = 'Weak'} - } - end - if self.buttons and not self.buttons.states.visible and not self.deck_preview then - self.buttons.states.visible = true - end - - if #G.hand.cards < 1 and #G.deck.cards < 1 and #G.play.cards < 1 then - end_round() - end - - if self.shop and not G.GAME.USING_CODE then self.shop:remove(); self.shop = nil end - if not G.STATE_COMPLETE then - G.STATE_COMPLETE = true - if #G.hand.cards < 1 and #G.deck.cards < 1 then - end_round() - else - save_run() - G.CONTROLLER:recall_cardarea_focus('hand') - end - end -end - -function Game:update_shop(dt) - if not G.STATE_COMPLETE then - stop_use() - if not G.GAME.USING_RUN then ease_background_colour_blind(G.STATES.SHOP) end - local shop_exists = not not G.shop - G.shop = G.shop or UIBox{ - definition = G.UIDEF.shop(), - config = {align='tmi', offset = {x=0,y=G.ROOM.T.y+11},major = G.hand, bond = 'Weak'} - } - G.E_MANAGER:add_event(Event({ - func = function() - if not G.shop then return true end - G.shop.alignment.offset.y = -5.3 - G.shop.alignment.offset.x = 0 - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.2, - blockable = false, - func = function() - if math.abs(G.shop.T.y - G.shop.VT.y) < 3 then - G.ROOM.jiggle = G.ROOM.jiggle + 3 - play_sound('cardFan2') - for i = 1, #G.GAME.tags do - G.GAME.tags[i]:apply_to_run({type = 'shop_start'}) - end - local nosave_shop = nil - if not shop_exists then - - if G.load_shop_jokers then - nosave_shop = true - G.shop_jokers:load(G.load_shop_jokers) - for k, v in ipairs(G.shop_jokers.cards) do - create_shop_card_ui(v) - if v.ability.consumeable then v:start_materialize() end - for _kk, vvv in ipairs(G.GAME.tags) do - if vvv:apply_to_run({type = 'store_joker_modify', card = v}) then break end - end - end - G.load_shop_jokers = nil - else - for i = 1, G.GAME.shop.joker_max - #G.shop_jokers.cards do - G.shop_jokers:emplace(create_card_for_shop(G.shop_jokers)) - end - end - - if G.load_shop_vouchers then - nosave_shop = true - G.shop_vouchers:load(G.load_shop_vouchers) - for k, v in ipairs(G.shop_vouchers.cards) do - create_shop_card_ui(v) - v:start_materialize() - end - G.load_shop_vouchers = nil - else - if G.GAME.current_round.voucher and G.P_CENTERS[G.GAME.current_round.voucher] then - local card = Card(G.shop_vouchers.T.x + G.shop_vouchers.T.w/2, - G.shop_vouchers.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS[G.GAME.current_round.voucher],{bypass_discovery_center = true, bypass_discovery_ui = true}) - card.shop_voucher = true - cry_misprintize(card) - if G.GAME.events.ev_cry_choco2 then - card.misprint_cost_fac = (card.misprint_cost_fac or 1) * 2 - card:set_cost() - end - if G.GAME.modifiers.cry_enable_flipped_in_shop and pseudorandom('cry_flip_vouch'..G.GAME.round_resets.ante) > 0.7 then - card.cry_flipped = true - end - create_shop_card_ui(card, 'Voucher', G.shop_vouchers) - card:start_materialize() - if G.GAME.current_round.cry_voucher_edition then - card:set_edition(G.GAME.current_round.cry_voucher_edition, true, true) - end - if G.GAME.current_round.cry_voucher_stickers then - if G.GAME.current_round.cry_voucher_stickers.eternal == true then -- this is dumb but i'm not sure how to call functions from a string - card:set_eternal(true) - card.ability.eternal = true - end - if G.GAME.current_round.cry_voucher_stickers.perishable == true then - card.ability.perishable = true - end - if G.GAME.current_round.cry_voucher_stickers.rental == true then - card:set_rental(true) - card.ability.rental = true - end - if G.GAME.current_round.cry_voucher_stickers.pinned == true then - card.pinned = true - end - if G.GAME.current_round.cry_voucher_stickers.banana == true then - card.ability.banana = true - end - end - G.shop_vouchers:emplace(card) - end for i = 1, #G.GAME.current_round.cry_bonusvouchers do - if not G.GAME.cry_bonusvouchersused[i] then - local card = Card(G.shop_vouchers.T.x + G.shop_vouchers.T.w/2, - G.shop_vouchers.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS[G.GAME.current_round.cry_bonusvouchers[i]],{bypass_discovery_center = true, bypass_discovery_ui = true}) - card.shop_cry_bonusvoucher = i - cry_misprintize(card) - if G.GAME.events.ev_cry_choco2 then - card.misprint_cost_fac = (card.misprint_cost_fac or 1) * 2 - card:set_cost() - end - if G.GAME.modifiers.cry_enable_flipped_in_shop and pseudorandom('cry_flip_vouch'..G.GAME.round_resets.ante) > 0.7 then - card.cry_flipped = true - end - create_shop_card_ui(card, 'Voucher', G.shop_vouchers) - card:start_materialize() - if G.GAME.current_round.cry_voucher_edition then -- eh why not - card:set_edition(G.GAME.current_round.cry_voucher_edition, true, true) - end - G.shop_vouchers.config.card_limit = G.shop_vouchers.config.card_limit + 1 -- does this actually matter/even get reset??? i'm confused but whatever - G.shop_vouchers:emplace(card) - end -end - - end - - - if G.GAME.events.ev_cry_choco10 then - local add = true - for k, v in pairs(G.shop_vouchers.cards) do -- G.load_shop_vouchers is already set to nil here, just do a normal check - if v.ability.cry_antique then add = false end - end - if add then - local card = create_card('Joker', G.jokers, true, nil, nil, nil, nil, 'cry_antique') - cry_misprintize(card) - card.misprint_cost_fac = 50/card.cost - card:set_cost() - create_shop_card_ui(card, 'Voucher', G.shop_vouchers) - card:start_materialize() - card.ability.cry_antique = true - G.shop_vouchers.config.card_limit = G.shop_vouchers.config.card_limit + 1 - G.shop_vouchers:emplace(card) - end - end - if G.load_shop_booster then - nosave_shop = true - G.shop_booster:load(G.load_shop_booster) - for k, v in ipairs(G.shop_booster.cards) do - create_shop_card_ui(v) - v:start_materialize() - end - G.load_shop_booster = nil - else - for i = 1, G.GAME.modifiers.cry_no_boosters and 0 or G.GAME.modifiers.cry_booster_packs or 2 do - G.GAME.current_round.used_packs = G.GAME.current_round.used_packs or {} - if not G.GAME.current_round.used_packs[i] then - G.GAME.current_round.used_packs[i] = get_pack('shop_pack').key - end - - if G.GAME.current_round.used_packs[i] ~= 'USED' then - local card = Card(G.shop_booster.T.x + G.shop_booster.T.w/2, - G.shop_booster.T.y, G.CARD_W*(G.P_CENTERS[G.GAME.current_round.used_packs[i]].set == 'Booster' and 1.27 or 1), G.CARD_H*(G.P_CENTERS[G.GAME.current_round.used_packs[i]].set == 'Booster' and 1.27 or 1), G.P_CARDS.empty, G.P_CENTERS[G.GAME.current_round.used_packs[i]], {bypass_discovery_center = true, bypass_discovery_ui = true}) - cry_misprintize(card) - if G.GAME.modifiers.cry_enable_flipped_in_shop and pseudorandom('cry_flip_pack'..G.GAME.round_resets.ante) > 0.7 then - card.cry_flipped = true - end - create_shop_card_ui(card, 'Booster', G.shop_booster) - card.ability.booster_pos = i - card:start_materialize() - if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_random_edition then - card:set_edition(nil, true, true) - elseif G.GAME.modifiers.cry_force_random_edition then - local edition = cry_poll_random_edition() - card:set_edition(edition, true, true) - end - - local eternal_perishable_poll = pseudorandom('cry_bpet'..(key_append or '')..G.GAME.round_resets.ante) - if (G.GAME.modifiers.cry_force_sticker == 'eternal') or (G.GAME.modifiers.cry_sticker_sheet_plus) or (G.GAME.modifiers.cry_any_stickers and (G.GAME.modifiers.enable_eternals_in_shop and eternal_perishable_poll > 0.8)) then - card:set_eternal(true) - card.ability.eternal = true - end - if G.GAME.modifiers.enable_perishables_in_shop and G.GAME.modifiers.cry_any_stickers then -- i don't feel like messing with this, whatever - if not G.GAME.modifiers.cry_eternal_perishable_compat and ((eternal_perishable_poll > 0.6) and (eternal_perishable_poll <= 0.8)) then - card:set_perishable(true) - card.ability.perishable = true - end - if G.GAME.modifiers.cry_eternal_perishable_compat and pseudorandom('cry_bpper'..(key_append or '')..G.GAME.round_resets.ante) > 0.8 then - card:set_perishable(true) - card.ability.perishable = true - end - end - if (G.GAME.modifiers.cry_force_sticker == 'perishable') or (G.GAME.modifiers.cry_sticker_sheet_plus) then - card:set_perishable(true) - card.ability.perishable = true - end - if (G.GAME.modifiers.cry_force_sticker == 'rental') or (G.GAME.modifiers.cry_sticker_sheet_plus) or (G.GAME.modifiers.cry_any_stickers and (G.GAME.modifiers.enable_rentals_in_shop and pseudorandom('cry_bpssjr'..(key_append or '')..G.GAME.round_resets.ante) > 0.8)) then -- i should really just make this a function? so messy - card.ability.rental = true -- do not set_rental here to prevent cost from decreasing - end - if (G.GAME.modifiers.cry_force_sticker == 'pinned') or (G.GAME.modifiers.cry_sticker_sheet_plus) or (G.GAME.modifiers.cry_any_stickers and (G.GAME.modifiers.cry_enable_pinned_in_shop and pseudorandom('cry_bppin'..(key_append or '')..G.GAME.round_resets.ante) > 0.8)) then - card.pinned = true - end - if G.GAME.modifiers.cry_force_sticker == 'banana' or G.GAME.modifiers.cry_sticker_sheet_plus then - card.ability.banana = true - end - if not G.GAME.modifiers.cry_eternal_perishable_compat and G.GAME.modifiers.enable_banana and G.GAME.modifiers.cry_any_stickers and (pseudorandom('cry_bpbanana'..(key_append or '')..G.GAME.round_resets.ante) > 0.8) and (eternal_perishable_poll <= 0.8) then - card.ability.banana = true - end - if G.GAME.modifiers.cry_eternal_perishable_compat and G.GAME.modifiers.enable_banana and G.GAME.modifiers.cry_any_stickers and (pseudorandom('cry_bpbanana'..(key_append or '')..G.GAME.round_resets.ante) > 0.8) then - card.ability.banana = true - end - if G.GAME.modifiers.cry_sticker_sheet_plus then - for k, v in pairs(SMODS.Stickers) do - if v.apply and not v.no_sticker_sheet then v:apply(card, true) end - end - end - G.shop_booster:emplace(card) - end - end - - for i = 1, #G.GAME.tags do - G.GAME.tags[i]:apply_to_run({type = 'voucher_add'}) - end - for i = 1, #G.GAME.tags do - G.GAME.tags[i]:apply_to_run({type = 'shop_final_pass'}) - end - end - end - - G.CONTROLLER:snap_to({node = G.shop:get_UIE_by_ID('next_round_button')}) - if not nosave_shop then G.E_MANAGER:add_event(Event({ func = function() save_run(); return true end})) end - return true - end - end})) - return true - end - })) - G.STATE_COMPLETE = true - end - if self.buttons then self.buttons:remove(); self.buttons = nil end -end - -function Game:update_play_tarot(dt) - if self.buttons then self.buttons:remove(); self.buttons = nil end -end - -function Game:update_hand_played(dt) -G.GAME.chips = (G.GAME.chips or 0) -G.GAME.blind.chips = (G.GAME.blind.chips or math.huge) - if self.buttons then self.buttons:remove(); self.buttons = nil end - if self.shop and not G.GAME.USING_CODE then self.shop:remove(); self.shop = nil end - - if not G.STATE_COMPLETE then - G.STATE_COMPLETE = true - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - if to_big(G.GAME.chips) >= to_big(G.GAME.blind.chips) or G.GAME.current_round.hands_left < 1 then - G.STATE = G.STATES.NEW_ROUND - else - G.STATE = G.STATES.DRAW_TO_HAND - end - G.STATE_COMPLETE = false - return true - end - })) - end -end - -function Game:update_draw_to_hand(dt) -if G.GAME.selected_back and (G.GAME.selected_back.name == 'cry--Negative Deck' or G.GAME.selected_back.name == 'cry-Antimatter') and G.hand.config.card_limit <= 0 then -- 'cry--Negative Deck'... sure - G.hand.config.card_limit = 1 -end - if self.buttons then self.buttons:remove(); self.buttons = nil end - if self.shop and not G.GAME.USING_CODE then self.shop:remove(); self.shop = nil end - - if not G.STATE_COMPLETE then - G.STATE_COMPLETE = true - for i = 1, #G.GAME.tags do - G.GAME.tags[i]:apply_to_run({type = 'round_start_bonus'}) - end - ease_background_colour_blind(G.STATES.DRAW_TO_HAND) - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - if G.FUNCS.draw_from_deck_to_hand(nil) then - return true - end - - if G.GAME.current_round.hands_played == 0 and - G.GAME.current_round.discards_used == 0 and G.GAME.facing_blind then - for i = 1, #G.hand.cards do - eval_card(G.hand.cards[i], {first_hand_drawn = true}) - end - for i = 1, #G.jokers.cards do - G.jokers.cards[i]:calculate_joker({first_hand_drawn = true}) - end - G.GAME.selected_back:trigger_effect({context = 'first_hand_drawn'}) - end - - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.STATE = G.STATES.SELECTING_HAND - G.STATE_COMPLETE = false - G.GAME.blind:drawn_to_hand() - return true - end - })) - return true - end - })) - end -end - -function Game:update_new_round(dt) - if self.buttons then self.buttons:remove(); self.buttons = nil end - if self.shop and not G.GAME.USING_CODE then self.shop:remove(); self.shop = nil end - - if not G.STATE_COMPLETE then - G.STATE_COMPLETE = true - end_round() - end -end - -function Game:update_blind_select(dt) - if self.buttons then self.buttons:remove(); self.buttons = nil end - if self.shop and not G.GAME.USING_CODE then self.shop:remove(); self.shop = nil end - - if not G.STATE_COMPLETE then - stop_use() - ease_background_colour_blind(G.STATES.BLIND_SELECT) - G.E_MANAGER:add_event(Event({ func = function() save_run(); return true end})) - G.STATE_COMPLETE = true - G.CONTROLLER.interrupt.focus = true - G.E_MANAGER:add_event(Event({ func = function() - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - --G.GAME.round_resets.blind_states = G.GAME.round_resets.blind_states or {Small = 'Select', Big = 'Upcoming', Boss = 'Upcoming'} - --if G.GAME.round_resets.blind_states.Boss == 'Defeated' then - -- G.GAME.round_resets.blind_states.Small = 'Upcoming' - -- G.GAME.round_resets.blind_states.Big = 'Upcoming' - -- G.GAME.round_resets.blind_states.Boss = 'Upcoming' - -- G.GAME.blind_on_deck = 'Small' - -- G.GAME.round_resets.blind_choices.Boss = get_new_boss() - -- G.GAME.round_resets.boss_rerolled = false - --end - play_sound('cancel') - G.blind_select = UIBox{ - definition = create_UIBox_blind_select(), - config = {align="bmi", offset = {x=0,y=G.ROOM.T.y + 29},major = G.hand, bond = 'Weak'} - } - G.blind_select.alignment.offset.y = 0.8-(G.hand.T.y - G.jokers.T.y) + G.blind_select.T.h - G.ROOM.jiggle = G.ROOM.jiggle + 3 - G.blind_select.alignment.offset.x = 0 - G.CONTROLLER.lock_input = false - for i = 1, #G.GAME.tags do - G.GAME.tags[i]:apply_to_run({type = 'immediate'}) - end - for i = 1, #G.GAME.tags do - if G.GAME.tags[i]:apply_to_run({type = 'new_blind_choice'}) then break end - end - return true - end - })) ; return true end})) - end -end - -function Game:update_round_eval(dt) - if self.buttons then self.buttons:remove(); self.buttons = nil end - if self.shop and not G.GAME.USING_CODE then self.shop:remove(); self.shop = nil end - - if not G.STATE_COMPLETE then - stop_use() - G.STATE_COMPLETE = true - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.GAME.facing_blind = nil - save_run() - ease_background_colour_blind(G.STATES.ROUND_EVAL) - if G.GAME.events.ev_cry_choco6 and G.round_eval then return true end - G.round_eval = UIBox{ - definition = create_UIBox_round_evaluation(), - config = {align="bm", offset = {x=0,y=G.ROOM.T.y + 19},major = G.hand, bond = 'Weak'} - } - G.round_eval.alignment.offset.x = 0 - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - if G.round_eval.alignment.offset.y ~= -7.8 then - G.round_eval.alignment.offset.y = -7.8 - else - if math.abs(G.round_eval.T.y - G.round_eval.VT.y) < 3 then - G.ROOM.jiggle = G.ROOM.jiggle + 3 - play_sound('cardFan2') - delay(0.1) - G.FUNCS.evaluate_round() - return true - end - end - end})) - return true - end - })) - end -end - -function Game:update_arcana_pack(dt) - if self.buttons then self.buttons:remove(); self.buttons = nil end - if self.shop then G.shop.alignment.offset.y = G.ROOM.T.y+11 end - - if not G.STATE_COMPLETE then - G.STATE_COMPLETE = true - G.CONTROLLER.interrupt.focus = true - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.booster_pack_sparkles = Particles(1, 1, 0,0, { - timer = 0.015, - scale = 0.2, - initialize = true, - lifespan = 1, - speed = 1.1, - padding = -1, - attach = G.ROOM_ATTACH, - colours = {G.C.WHITE, lighten(G.C.PURPLE, 0.4), lighten(G.C.PURPLE, 0.2), lighten(G.C.GOLD, 0.2)}, - fill = true - }) - G.booster_pack_sparkles.fade_alpha = 1 - G.booster_pack_sparkles:fade(1, 0) - G.booster_pack = UIBox{ - definition = create_UIBox_arcana_pack(), - config = {align="tmi", offset = {x=0,y=G.ROOM.T.y + 9},major = G.hand, bond = 'Weak'} - } - G.booster_pack.alignment.offset.y = -2.2 - G.ROOM.jiggle = G.ROOM.jiggle + 3 - ease_background_colour_blind(G.STATES.TAROT_PACK) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.FUNCS.draw_from_deck_to_hand() - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.5, - func = function() - G.CONTROLLER:recall_cardarea_focus('pack_cards') - return true - end})) - return true - end - })) - return true - end - })) - end -end - -function Game:update_spectral_pack(dt) - if self.buttons then self.buttons:remove(); self.buttons = nil end - if self.shop then G.shop.alignment.offset.y = G.ROOM.T.y+11 end - - if not G.STATE_COMPLETE then - G.STATE_COMPLETE = true - G.CONTROLLER.interrupt.focus = true - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.booster_pack_sparkles = Particles(1, 1, 0,0, { - timer = 0.015, - scale = 0.1, - initialize = true, - lifespan = 3, - speed = 0.2, - padding = -1, - attach = G.ROOM_ATTACH, - colours = {G.C.WHITE, lighten(G.C.GOLD, 0.2)}, - fill = true - }) - G.booster_pack_sparkles.fade_alpha = 1 - G.booster_pack_sparkles:fade(1, 0) - G.booster_pack = UIBox{ - definition = create_UIBox_spectral_pack(), - config = {align="tmi", offset = {x=0,y=G.ROOM.T.y + 9},major = G.hand, bond = 'Weak'} - } - G.booster_pack.alignment.offset.y = -2.2 - G.ROOM.jiggle = G.ROOM.jiggle + 3 - ease_background_colour_blind(G.STATES.SPECTRAL_PACK) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.FUNCS.draw_from_deck_to_hand() - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.5, - func = function() - G.CONTROLLER:recall_cardarea_focus('pack_cards') - return true - end})) - return true - end - })) - return true - end - })) - end -end - -function Game:update_standard_pack(dt) - if self.buttons then self.buttons:remove(); self.buttons = nil end - if self.shop then G.shop.alignment.offset.y = G.ROOM.T.y+11 end - - if not G.STATE_COMPLETE then - G.STATE_COMPLETE = true - G.CONTROLLER.interrupt.focus = true - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.booster_pack_sparkles = Particles(1, 1, 0,0, { - timer = 0.015, - scale = 0.3, - initialize = true, - lifespan = 3, - speed = 0.2, - padding = -1, - attach = G.ROOM_ATTACH, - colours = {G.C.BLACK, G.C.RED}, - fill = true - }) - G.booster_pack_sparkles.fade_alpha = 1 - G.booster_pack_sparkles:fade(1, 0) - G.booster_pack = UIBox{ - definition = create_UIBox_standard_pack(), - config = {align="tmi", offset = {x=0,y=G.ROOM.T.y + 9},major = G.hand, bond = 'Weak'} - } - G.booster_pack.alignment.offset.y = -2.2 - G.ROOM.jiggle = G.ROOM.jiggle + 3 - ease_background_colour_blind(G.STATES.STANDARD_PACK) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.5, - func = function() - G.CONTROLLER:recall_cardarea_focus('pack_cards') - return true - end})) - return true - end - })) - return true - end - })) - end -end - -function Game:update_buffoon_pack(dt) - if self.buttons then self.buttons:remove(); self.buttons = nil end - if self.shop then G.shop.alignment.offset.y = G.ROOM.T.y+11 end - - if not G.STATE_COMPLETE then - G.STATE_COMPLETE = true - G.CONTROLLER.interrupt.focus = true - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.booster_pack = UIBox{ - definition = create_UIBox_buffoon_pack(), - config = {align="tmi", offset = {x=0,y=G.ROOM.T.y + 9},major = G.hand, bond = 'Weak'} - } - G.booster_pack.alignment.offset.y = -2.2 - G.ROOM.jiggle = G.ROOM.jiggle + 3 - ease_background_colour_blind(G.STATES.BUFFOON_PACK) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.5, - func = function() - G.CONTROLLER:recall_cardarea_focus('pack_cards') - return true - end})) - return true - end - })) - return true - end - })) - end -end - -function Game:update_celestial_pack(dt) - if self.buttons then self.buttons:remove(); self.buttons = nil end - if self.shop then G.shop.alignment.offset.y = G.ROOM.T.y+11 end - - if not G.STATE_COMPLETE then - G.STATE_COMPLETE = true - G.CONTROLLER.interrupt.focus = true - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - ease_background_colour_blind(G.STATES.PLANET_PACK) - G.booster_pack_stars = Particles(1, 1, 0,0, { - timer = 0.07, - scale = 0.1, - initialize = true, - lifespan = 15, - speed = 0.1, - padding = -4, - attach = G.ROOM_ATTACH, - colours = {G.C.WHITE, HEX('a7d6e0'), HEX('fddca0')}, - fill = true - }) - G.booster_pack_meteors = Particles(1, 1, 0,0, { - timer = 2, - scale = 0.05, - lifespan = 1.5, - speed = 4, - attach = G.ROOM_ATTACH, - colours = {G.C.WHITE}, - fill = true - }) - G.booster_pack = UIBox{ - definition = create_UIBox_celestial_pack(), - config = { - align="tmi", - offset = {x=0,y=G.ROOM.T.y + 9}, - major = G.hand, - bond = 'Weak' - } - } - G.booster_pack.alignment.offset.y = -2.2 - G.ROOM.jiggle = G.ROOM.jiggle + 3 - G.E_MANAGER:add_event(Event({ - func = function() - G.CONTROLLER:recall_cardarea_focus('pack_cards') - return true - end})) - return true - end - })) - end -end - -function Game:update_game_over(dt) - if not G.STATE_COMPLETE then - remove_save() - - if G.GAME.round_resets.ante <= G.GAME.win_ante then - if not G.GAME.seeded and not G.GAME.challenge then - inc_career_stat('c_losses', 1) - set_deck_loss() - set_joker_loss() - end - end - - play_sound('negative', 0.5, 0.7) - play_sound('whoosh2', 0.9, 0.7) - - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_game_over(), - config = {no_esc = true} - } - G.ROOM.jiggle = G.ROOM.jiggle + 3 - - if G.GAME.round_resets.ante <= G.GAME.win_ante then --Only add Jimbo to say a quip if the game over happens when the run is lost - local Jimbo = nil - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 2.5, - blocking = false, - func = (function() - if G.OVERLAY_MENU and G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') then - Jimbo = Card_Character({x = 0, y = 5}) - local spot = G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') - spot.config.object:remove() - spot.config.object = Jimbo - Jimbo.ui_object_updated = true - Jimbo:add_speech_bubble('lq_'..math.random(1,10), nil, {quip = true}) - Jimbo:say_stuff(5) - end - return true - end) - })) - end - - G.STATE_COMPLETE = true - end -end - -function Game:update_menu(dt) -end diff --git a/lovely/dump/globals.lua b/lovely/dump/globals.lua deleted file mode 100644 index e260402..0000000 --- a/lovely/dump/globals.lua +++ /dev/null @@ -1,517 +0,0 @@ -LOVELY_INTEGRITY = 'cc5ce14cedc1c6e4d37db4db11e97b078bdd8322493ee0e9f65dd96ca38abf95' - -VERSION = '1.0.1n' -VERSION = VERSION..'-FULL' ---check_version - ---Globals - -function Game:set_globals() - self.VERSION = VERSION - - --|||||||||||||||||||||||||||||| - -- Feature Flags - --|||||||||||||||||||||||||||||| - self.F_QUIT_BUTTON = true --Include the main menu 'Quit' button - self.F_SKIP_TUTORIAL = false --Completely skip the tutorial on fresh save - self.F_BASIC_CREDITS = false --Remove references to Daniel Linssens itch.io - self.F_EXTERNAL_LINKS = true --Remove all references to any external links (mainly for console) - self.F_ENABLE_PERF_OVERLAY = false --Disable debugging tool for performance of each frame - self.F_NO_SAVING = false --Disables all 'run' saving - self.F_MUTE = false --Force mute all sounds - self.F_SOUND_THREAD = true --Have sound in a separate thread entirely - if not sounds will run on main thread - self.F_VIDEO_SETTINGS = true --Let the player change their video settings - self.F_CTA = false --Call to Action video for the Demo - keep this as false - self.F_VERBOSE = true --Extra debug information on screen and in the console - self.F_HTTP_SCORES = false --Include HTTP scores to fetch/set high scores - self.F_RUMBLE = nil --Add rumble to the primary controller - adjust this for amount of rumble - self.F_CRASH_REPORTS = false --Send Crash reports over the internet - self.F_NO_ERROR_HAND = false --Hard crash without error message screen - self.F_SWAP_AB_PIPS = false --Swapping button pips for A and B buttons (mainly for switch) - self.F_SWAP_AB_BUTTONS = false --Swapping button function for A and B buttons (mainly for switch) - self.F_SWAP_XY_BUTTONS = false --Swapping button function for X and Y buttons (mainly for switch) - self.F_NO_ACHIEVEMENTS = false --Disable achievements - self.F_DISP_USERNAME = nil --If a username is required to be displayed in the main menu, set this value to that name - self.F_ENGLISH_ONLY = nil --Disable language selection - only in english - self.F_GUIDE = false --Replace back/select button with 'guide' button - self.F_JAN_CTA = false --Call to action for Jan demo - self.F_HIDE_BG = false --Hiding the game objects when paused - self.F_TROPHIES = false --use 'trophy' terminology instead of 'achievemnt' - self.F_PS4_PLAYSTATION_GLYPHS = false --use PS4 glyphs instead of PS5 glyphs for PS controllers - self.F_LOCAL_CLIPBOARD = false - self.F_SAVE_TIMER = 30 - self.F_MOBILE_UI = false - self.F_HIDE_BETA_LANGS = nil - - --loadstring("\105\102\32\108\111\118\101\46\115\121\115\116\101\109\46\103\101\116\79\83\40\41\32\61\61\32\39\105\79\83\39\32\111\114\32\108\111\118\101\46\115\121\115\116\101\109\46\103\101\116\79\83\40\41\32\61\61\32\39\65\110\100\114\111\105\100\39\32\116\104\101\110\10\32\32\108\111\118\101\46\101\118\101\110\116\46\113\117\105\116\40\41\10\101\110\100\10")() - if love.system.getOS() == 'Windows' then - self.F_DISCORD = true - self.F_SAVE_TIMER = 5 - self.F_ENGLISH_ONLY = false - self.F_CRASH_REPORTS = false - end - - if love.system.getOS() == 'OS X' then - self.F_SAVE_TIMER = 5 - self.F_DISCORD = true - self.F_ENGLISH_ONLY = false - self.F_CRASH_REPORTS = false - end - - if love.system.getOS() == 'Nintendo Switch' then - self.F_HIDE_BETA_LANGS = true - self.F_BASIC_CREDITS = true - self.F_NO_ERROR_HAND = true - self.F_QUIT_BUTTON = false - self.F_SKIP_TUTORIAL = false - self.F_ENABLE_PERF_OVERLAY = false - self.F_NO_SAVING = false - self.F_MUTE = false - self.F_SOUND_THREAD = true - self.F_SWAP_AB_PIPS = true - self.F_SWAP_AB_BUTTONS = false - self.F_SWAP_XY_BUTTONS = true - self.F_VIDEO_SETTINGS = false - self.F_RUMBLE = 0.7 - self.F_CTA = false - self.F_VERBOSE = false - self.F_NO_ACHIEVEMENTS = true - self.F_ENGLISH_ONLY = nil - - self.F_EXTERNAL_LINKS = false - self.F_HIDE_BG = true - end - - if love.system.getOS() == 'ps4' or love.system.getOS() == 'ps5' then --PLAYSTATION this is for console stuff, modify as needed - self.F_HIDE_BETA_LANGS = true - self.F_NO_ERROR_HAND = true - self.F_QUIT_BUTTON = false - self.F_SKIP_TUTORIAL = false - self.F_ENABLE_PERF_OVERLAY = false - self.F_NO_SAVING = false - self.F_MUTE = false - self.F_SOUND_THREAD = true - self.F_VIDEO_SETTINGS = false - self.F_RUMBLE = 0.5 - self.F_CTA = false - self.F_VERBOSE = false - - self.F_GUIDE = true - self.F_PS4_PLAYSTATION_GLYPHS = false - - self.F_EXTERNAL_LINKS = false - self.F_HIDE_BG = true - --self.F_LOCAL_CLIPBOARD = true - end - - if love.system.getOS() == 'xbox' then - self.F_HIDE_BETA_LANGS = true - self.F_NO_ERROR_HAND = true - self.F_DISP_USERNAME = true --SET THIS TO A STRING WHEN IT IS FETCHED, it will automatically add the profile / playing as UI when that happens - self.F_SKIP_TUTORIAL = false - self.F_ENABLE_PERF_OVERLAY = false - self.F_NO_SAVING = false - self.F_MUTE = false - self.F_SOUND_THREAD = true - self.F_VIDEO_SETTINGS = false - self.F_RUMBLE = 1.0 - self.F_CTA = false - self.F_VERBOSE = false - self.F_EXTERNAL_LINKS = false - self.F_HIDE_BG = true - end - - --|||||||||||||||||||||||||||||| - -- Time - --|||||||||||||||||||||||||||||| - self.SEED = os.time() - self.TIMERS = { - TOTAL=0, - REAL = 0, - REAL_SHADER = 0, - UPTIME = 0, - BACKGROUND = 0 - } - self.FRAMES = { - DRAW = 0, - MOVE = 0 - } - self.exp_times = {xy = 0, scale = 0, r = 0} - --|||||||||||||||||||||||||||||| - -- SETTINGS - --|||||||||||||||||||||||||||||| - self.SETTINGS = { - COMP = { - name = '', - prev_name = '', - submission_name = nil, - score = 0, - }, - DEMO = { - total_uptime = 0, - timed_CTA_shown = false, - win_CTA_shown = false, - quit_CTA_shown = false - }, - ACHIEVEMENTS_EARNED = {}, - crashreports = false, - colourblind_option = false, - language = 'en-us', - screenshake = true, - run_stake_stickers = false, - rumble = self.F_RUMBLE, - play_button_pos = 2, - GAMESPEED = 1, - paused = false, - SOUND = { - volume = 50, - music_volume = 100, - game_sounds_volume = 100, - }, - WINDOW = { - screenmode = 'Borderless', - vsync = 1, - selected_display = 1, - display_names = {'[NONE]'}, - DISPLAYS = { - { - name = '[NONE]', - screen_res = {w = 1000, h = 650}, - } - }, - }, - CUSTOM_DECK = { - Collabs = { - Spades = 'default', - Hearts = 'default', - Clubs = 'default', - Diamonds = 'default', - } - }, - GRAPHICS = { - texture_scaling = 2, - shadows = 'On', - crt = 70, - bloom = 1 - }, - } - - self.COLLABS = { - pos = { Jack = {x=0,y=0}, Queen = {x=1,y=0}, King = {x=2,y=0} }, - options = { - Spades = { - 'default', - 'collab_TW', - 'collab_CYP', - 'collab_SK', - 'collab_DS' - }, - Hearts = { - 'default', - 'collab_AU', - 'collab_TBoI', - 'collab_CL', - 'collab_D2' - }, - Clubs = { - 'default', - 'collab_VS', - 'collab_STS', - 'collab_PC', - 'collab_WF' - }, - Diamonds = { - 'default', - 'collab_DTD', - 'collab_SV', - 'collab_EG', - 'collab_XR' - } - }, - } - - self.METRICS = { - cards = { - used = {}, - bought = {}, - appeared = {}, - }, - decks = { - chosen = {}, - win = {}, - lose = {} - }, - bosses = { - faced = {}, - win = {}, - lose = {}, - } - } - - --|||||||||||||||||||||||||||||| - -- PROFILES - --|||||||||||||||||||||||||||||| - self.PROFILES = { - {}, - {}, - {}, - } - - --|||||||||||||||||||||||||||||| - -- RENDER SCALE - --|||||||||||||||||||||||||||||| - self.TILESIZE = 20 - self.TILESCALE = 3.65 - self.TILE_W = 20 - self.TILE_H = 11.5 - self.DRAW_HASH_BUFF = 2 - self.CARD_W = 2.4*35/41 - self.CARD_H = 2.4*47/41 - self.HIGHLIGHT_H = 0.2*self.CARD_H - self.COLLISION_BUFFER = 0.05 - - self.PITCH_MOD = 1 - - --|||||||||||||||||||||||||||||| - -- GAMESTATES - --|||||||||||||||||||||||||||||| - self.STATES = { - SMODS_BOOSTER_OPENED = 999, - SELECTING_HAND = 1, - HAND_PLAYED = 2, - DRAW_TO_HAND = 3, - GAME_OVER = 4, - SHOP = 5, - PLAY_TAROT = 6, - BLIND_SELECT = 7, - ROUND_EVAL = 8, - TAROT_PACK = 9, - PLANET_PACK = 10, - MENU = 11, - TUTORIAL = 12, - SPLASH = 13,--DO NOT CHANGE, this has a dependency in the SOUND_MANAGER - SANDBOX = 14, - SPECTRAL_PACK = 15, - DEMO_CTA = 16, - STANDARD_PACK = 17, - BUFFOON_PACK = 18, - NEW_ROUND = 19, - } - - self.STAGES = { - MAIN_MENU = 1, - RUN = 2, - SANDBOX = 3 - } - self.STAGE_OBJECTS = { - {},{},{} - } - self.STAGE = self.STAGES.MAIN_MENU - self.STATE = self.STATES.SPLASH - self.TAROT_INTERRUPT = nil - self.STATE_COMPLETE = false - - --|||||||||||||||||||||||||||||| - -- INSTANCES - --|||||||||||||||||||||||||||||| - self.ARGS = {} - self.FUNCS = {} - self.I = { - NODE = {}, - MOVEABLE = {}, - SPRITE = {}, - UIBOX = {}, - POPUP = {}, - CARD = {}, - CARDAREA = {}, - ALERT = {} - } - self.ANIMATION_ATLAS = {} - self.ASSET_ATLAS = {} - self.MOVEABLES = {} - self.ANIMATIONS = {} - self.DRAW_HASH = {} - - --|||||||||||||||||||||||||||||| - -- CONSTANTS - --|||||||||||||||||||||||||||||| - self.MIN_CLICK_DIST = 0.9 - self.MIN_HOVER_TIME = 0.1 - self.DEBUG = false - self.ANIMATION_FPS = 10 - self.VIBRATION = 0 - self.CHALLENGE_WINS = 5 - - --|||||||||||||||||||||||||||||| - -- COLOURS - --|||||||||||||||||||||||||||||| - self.C = { - MULT = HEX('FE5F55'), - CHIPS = HEX("009dff"), - MONEY = HEX('f3b958'), - XMULT = HEX('FE5F55'), - FILTER = HEX('ff9a00'), - BLUE = HEX("009dff"), - RED = HEX('FE5F55'), - GREEN = HEX("4BC292"), - PALE_GREEN = HEX("56a887"), - ORANGE = HEX("fda200"), - IMPORTANT = HEX("ff9a00"), - GOLD = HEX('eac058'), - YELLOW = {1,1,0,1}, - CLEAR = {0, 0, 0, 0}, - WHITE = {1,1,1,1}, - PURPLE = HEX('8867a5'), - BLACK = HEX("374244"),--4f6367"), - L_BLACK = HEX("4f6367"), - GREY = HEX("5f7377"), - CHANCE = HEX("4BC292"), - JOKER_GREY = HEX('bfc7d5'), - VOUCHER = HEX("cb724c"), - BOOSTER = HEX("646eb7"), - EDITION = {1,1,1,1}, - DARK_EDITION = {0,0,0,1}, - ETERNAL = HEX('c75985'), - PERISHABLE = HEX('4f5da1'), - RENTAL = HEX('b18f43'), - DYN_UI = { - MAIN = HEX('374244'), - DARK = HEX('374244'), - BOSS_MAIN = HEX('374244'), - BOSS_DARK = HEX('374244'), - BOSS_PALE = HEX('374244') - }, - --For other high contrast suit colours - SO_1 = { - Hearts = HEX('f03464'), - Diamonds = HEX('f06b3f'), - Spades = HEX("403995"), - Clubs = HEX("235955"), - }, - SO_2 = { - Hearts = HEX('f83b2f'), - Diamonds = HEX('e29000'), - Spades = HEX("4f31b9"), - Clubs = HEX("008ee6"), - }, - SUITS = { - Hearts = HEX('FE5F55'), - Diamonds = HEX('FE5F55'), - Spades = HEX("374649"), - Clubs = HEX("424e54"), - }, - UI = { - TEXT_LIGHT = {1,1,1,1}, - TEXT_DARK = HEX("4F6367"), - TEXT_INACTIVE = HEX("88888899"), - BACKGROUND_LIGHT = HEX("B8D8D8"), - BACKGROUND_WHITE = {1,1,1,1}, - BACKGROUND_DARK = HEX("7A9E9F"), - BACKGROUND_INACTIVE = HEX("666666FF"), - OUTLINE_LIGHT = HEX("D8D8D8"), - OUTLINE_LIGHT_TRANS = HEX("D8D8D866"), - OUTLINE_DARK = HEX("7A9E9F"), - TRANSPARENT_LIGHT = HEX("eeeeee22"), - TRANSPARENT_DARK = HEX("22222222"), - HOVER = HEX('00000055'), - }, - SET = { - Default = HEX("cdd9dc"), - Enhanced = HEX("cdd9dc"), - Joker = HEX('424e54'), - Tarot = HEX('424e54'),--HEX('29adff'), - Planet = HEX("424e54"), - Spectral = HEX('424e54'), - Voucher = HEX("424e54"), - }, - SECONDARY_SET = { - Default = HEX("9bb6bdFF"), - Enhanced = HEX("8389DDFF"), - Joker = HEX('708b91'), - Tarot = HEX('a782d1'),--HEX('29adff'), - Planet = HEX('13afce'), - Spectral = HEX('4584fa'), - Voucher = HEX("fd682b"), - Edition = HEX("4ca893"), - }, - RARITY = { - HEX('009dff'),--HEX("708b91"), - HEX("4BC292"), - HEX('fe5f55'), - HEX("b26cbb") - }, - BLIND = { - Small = HEX("50846e"), - Big = HEX("50846e"), - Boss = HEX("b44430"), - won = HEX("4f6367") - }, - HAND_LEVELS = { - HEX("efefef"), - HEX("95acff"), - HEX("65efaf"), - HEX('fae37e'), - HEX('ffc052'), - HEX('f87d75'), - HEX('caa0ef') - }, - BACKGROUND = { - L = {1,1,0,1}, - D = HEX("374244"), - C = HEX("374244"), - contrast = 1 - } - } - G.C.HAND_LEVELS[0] = G.C.RED - G.C.UI_CHIPS = copy_table(G.C.BLUE) - G.C.UI_MULT = copy_table(G.C.RED) - --|||||||||||||||||||||||||||||| - -- ENUMS - --|||||||||||||||||||||||||||||| - self.UIT = { - T=1, --text - B=2, --box (can be rounded) - C=3, --column - R=4, --row - O=5, --object - must be a Node - ROOT=7, - S=8, --slider - I=9, --input text box - padding = 0, --default padding - } - self.handlist = { - "Flush Five", - "Flush House", - "Five of a Kind", - "Straight Flush", - "Four of a Kind", - "Full House", - "Flush", - "Straight", - "Three of a Kind", - "Two Pair", - "Pair", - "High Card", - } - self.button_mapping = { - a = G.F_SWAP_AB_BUTTONS and 'b' or nil, - b = G.F_SWAP_AB_BUTTONS and 'a' or nil, - y = G.F_SWAP_XY_BUTTONS and 'x' or nil, - x = G.F_SWAP_XY_BUTTONS and 'y' or nil, - } - self.keybind_mapping = {{ - a = 'dpleft', - d = 'dpright', - w = 'dpup', - s = 'dpdown', - x = 'x', - c = 'y', - space = 'a', - shift = 'b', - esc = 'start', - q = 'triggerleft', - e = 'triggerright', - }} -end - -G = Game() diff --git a/lovely/dump/main.lua b/lovely/dump/main.lua deleted file mode 100644 index b241497..0000000 --- a/lovely/dump/main.lua +++ /dev/null @@ -1,4471 +0,0 @@ -LOVELY_INTEGRITY = 'b2c04153038fd7e4525be3be1bc642bcab91ec38fb988d0c5db268f85955e1dd' - - -local Cartomancer_replacements = { - { - find = [[ - for k, v in ipairs%(G%.playing_cards%) do - if v%.base%.suit then table%.insert%(SUITS%[v%.base%.suit%], v%) end]], - -- Steamodded<0917b - find_alt = [[ - for k, v in ipairs%(G%.playing_cards%) do - table%.insert%(SUITS%[v%.base%.suit%], v%)]], - place = [[ -local SUITS_SORTED = Cartomancer.tablecopy(SUITS) -for k, v in ipairs(G.playing_cards) do - if v.base.suit then - local greyed - if unplayed_only and not ((v.area and v.area == G.deck) or v.ability.wheel_flipped) then - greyed = true - end - local card_string = v:cart_to_string() - if greyed then - card_string = card_string .. "Greyed" -- for some reason format doesn't work and final string is `sGreyed` - end - if greyed and Cartomancer.SETTINGS.deck_view_hide_drawn_cards then - -- Ignore this card. - elseif not Cartomancer.SETTINGS.deck_view_stack_enabled then - -- Don't stack cards - local _scale = 0.7 - local copy = copy_card(v, nil, _scale) - - copy.greyed = greyed - copy.stacked_quantity = 1 - table.insert(SUITS_SORTED[v.base.suit], copy) - - elseif not SUITS[v.base.suit][card_string] then - -- Initiate stack - table.insert(SUITS_SORTED[v.base.suit], card_string) - - local _scale = 0.7 - local copy = copy_card(v, nil, _scale) - - copy.greyed = greyed - copy.stacked_quantity = 1 - - SUITS[v.base.suit][card_string] = copy - else - -- Stack cards - local stacked_card = SUITS[v.base.suit][card_string] - stacked_card.stacked_quantity = stacked_card.stacked_quantity + 1 - end - end]] - }, - - { - find = "card_limit = #SUITS%[suit_map%[j%]%],", - place = "card_limit = #SUITS_SORTED[suit_map[j]]," - }, - - { - find = [[ -for i = 1%, %#SUITS%[suit_map%[j%]%] do - if SUITS%[suit_map%[j%]%]%[i%] then - local greyed%, _scale = nil%, 0%.7 - if unplayed_only and not %(%(SUITS%[suit_map%[j%]%]%[i%]%.area and SUITS%[suit_map%[j%]%]%[i%]%.area == G%.deck%) or SUITS%[suit_map%[j%]%]%[i%]%.ability%.wheel_flipped%) then - greyed = true - end - local copy = copy_card%(SUITS%[suit_map%[j%]%]%[i%]%, nil%, _scale%) - copy%.greyed = greyed - copy%.T%.x = view_deck%.T%.x %+ view_deck%.T%.w %/ 2 - copy%.T%.y = view_deck%.T%.y - - copy:hard_set_T%(%) - view_deck:emplace%(copy%) - end - end]], - place = [[ -for i = 1%, %#SUITS_SORTED%[suit_map%[j%]%] do - local card - if not Cartomancer.SETTINGS.deck_view_stack_enabled then - card = SUITS_SORTED%[suit_map%[j%]%]%[i%] - else - local card_string = SUITS_SORTED%[suit_map%[j%]%]%[i%] - card = SUITS%[suit_map%[j%]%]%[card_string%] - end - - card%.T%.x = view_deck%.T%.x %+ view_deck%.T%.w%/2 - card%.T%.y = view_deck%.T%.y - card:create_quantity_display%(%) - - card:hard_set_T%(%) - view_deck:emplace%(card%) -end]] - }, - - { - find = ' modded and {n = G.UIT.R, config = {align = "cm"}, nodes = {', - place = [=[ - not unplayed_only and Cartomancer.add_unique_count() or nil, - modded and {n = G.UIT.R, config = {align = "cm"}, nodes = {]=] - }, - -} - - --- Mom, can we have lovely patches for overrides.lua? --- No, we have lovely patches at home - --- Lovely patches at home: - -local Cartomancer_nfs_read -local Cartomancer_nfs_read_override = function (containerOrName, nameOrSize, sizeOrNil) - local data, size = Cartomancer_nfs_read(containerOrName, nameOrSize, sizeOrNil) - - if type(containerOrName) ~= "string" then - return data, size - end - local overrides = '/overrides.lua' - if containerOrName:sub(-#overrides) ~= overrides then - return data, size - end - - local replaced = 0 - local total_replaced = 0 - for _, v in ipairs(Cartomancer_replacements) do - data, replaced = string.gsub(data, v.find, v.place) - - if replaced == 0 and v.find_alt then - data, replaced = string.gsub(data, v.find_alt, v.place) - end - - if replaced == 0 then - print("Failed to replace " .. v.find .. " for overrides.lua") - else - total_replaced = total_replaced + 1 - end - end - - print("Totally applied " .. total_replaced .. " replacements to overrides.lua") - - -- We no longer need this override - NFS.read = Cartomancer_nfs_read - - return data, size -end - ---- STEAMODDED CORE ---- MODULE STACKTRACE --- NOTE: This is a modifed version of https://github.com/ignacio/StackTracePlus/blob/master/src/StackTracePlus.lua --- Licensed under the MIT License. See https://github.com/ignacio/StackTracePlus/blob/master/LICENSE --- The MIT License --- Copyright (c) 2010 Ignacio Burgueño --- Permission is hereby granted, free of charge, to any person obtaining a copy --- of this software and associated documentation files (the "Software"), to deal --- in the Software without restriction, including without limitation the rights --- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --- copies of the Software, and to permit persons to whom the Software is --- furnished to do so, subject to the following conditions: --- The above copyright notice and this permission notice shall be included in --- all copies or substantial portions of the Software. --- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN --- THE SOFTWARE. --- tables -function loadStackTracePlus() - local _G = _G - local string, io, debug, coroutine = string, io, debug, coroutine - - -- functions - local tostring, print, require = tostring, print, require - local next, assert = next, assert - local pcall, type, pairs, ipairs = pcall, type, pairs, ipairs - local error = error - - assert(debug, "debug table must be available at this point") - - local io_open = io.open - local string_gmatch = string.gmatch - local string_sub = string.sub - local table_concat = table.concat - - local _M = { - max_tb_output_len = 70 -- controls the maximum length of the 'stringified' table before cutting with ' (more...)' - } - - -- this tables should be weak so the elements in them won't become uncollectable - local m_known_tables = { - [_G] = "_G (global table)" - } - local function add_known_module(name, desc) - local ok, mod = pcall(require, name) - if ok then - m_known_tables[mod] = desc - end - end - - add_known_module("string", "string module") - add_known_module("io", "io module") - add_known_module("os", "os module") - add_known_module("table", "table module") - add_known_module("math", "math module") - add_known_module("package", "package module") - add_known_module("debug", "debug module") - add_known_module("coroutine", "coroutine module") - - -- lua5.2 - add_known_module("bit32", "bit32 module") - -- luajit - add_known_module("bit", "bit module") - add_known_module("jit", "jit module") - -- lua5.3 - if _VERSION >= "Lua 5.3" then - add_known_module("utf8", "utf8 module") - end - - local m_user_known_tables = {} - - local m_known_functions = {} - for _, name in ipairs { -- Lua 5.2, 5.1 - "assert", "collectgarbage", "dofile", "error", "getmetatable", "ipairs", "load", "loadfile", "next", "pairs", - "pcall", "print", "rawequal", "rawget", "rawlen", "rawset", "require", "select", "setmetatable", "tonumber", - "tostring", "type", "xpcall", -- Lua 5.1 - "gcinfo", "getfenv", "loadstring", "module", "newproxy", "setfenv", "unpack" -- TODO: add table.* etc functions - } do - if _G[name] then - m_known_functions[_G[name]] = name - end - end - - local m_user_known_functions = {} - - local function safe_tostring(value) - local ok, err = pcall(tostring, value) - if ok then - return err - else - return (": '%s'"):format(err) - end - end - - -- Private: - -- Parses a line, looking for possible function definitions (in a very naïve way) - -- Returns '(anonymous)' if no function name was found in the line - local function ParseLine(line) - assert(type(line) == "string") - -- print(line) - local match = line:match("^%s*function%s+(%w+)") - if match then - -- print("+++++++++++++function", match) - return match - end - match = line:match("^%s*local%s+function%s+(%w+)") - if match then - -- print("++++++++++++local", match) - return match - end - match = line:match("^%s*local%s+(%w+)%s+=%s+function") - if match then - -- print("++++++++++++local func", match) - return match - end - match = line:match("%s*function%s*%(") -- this is an anonymous function - if match then - -- print("+++++++++++++function2", match) - return "(anonymous)" - end - return "(anonymous)" - end - - -- Private: - -- Tries to guess a function's name when the debug info structure does not have it. - -- It parses either the file or the string where the function is defined. - -- Returns '?' if the line where the function is defined is not found - local function GuessFunctionName(info) - -- print("guessing function name") - if type(info.source) == "string" and info.source:sub(1, 1) == "@" then - local file, err = io_open(info.source:sub(2), "r") - if not file then - print("file not found: " .. tostring(err)) -- whoops! - return "?" - end - local line - for _ = 1, info.linedefined do - line = file:read("*l") - end - if not line then - print("line not found") -- whoops! - return "?" - end - return ParseLine(line) - elseif type(info.source) == "string" and info.source:sub(1, 6) == "=[love" then - return "(LÖVE Function)" - else - local line - local lineNumber = 0 - for l in string_gmatch(info.source, "([^\n]+)\n-") do - lineNumber = lineNumber + 1 - if lineNumber == info.linedefined then - line = l - break - end - end - if not line then - print("line not found") -- whoops! - return "?" - end - return ParseLine(line) - end - end - - --- - -- Dumper instances are used to analyze stacks and collect its information. - -- - local Dumper = {} - - Dumper.new = function(thread) - local t = { - lines = {} - } - for k, v in pairs(Dumper) do - t[k] = v - end - - t.dumping_same_thread = (thread == coroutine.running()) - - -- if a thread was supplied, bind it to debug.info and debug.get - -- we also need to skip this additional level we are introducing in the callstack (only if we are running - -- in the same thread we're inspecting) - if type(thread) == "thread" then - t.getinfo = function(level, what) - if t.dumping_same_thread and type(level) == "number" then - level = level + 1 - end - return debug.getinfo(thread, level, what) - end - t.getlocal = function(level, loc) - if t.dumping_same_thread then - level = level + 1 - end - return debug.getlocal(thread, level, loc) - end - else - t.getinfo = debug.getinfo - t.getlocal = debug.getlocal - end - - return t - end - - -- helpers for collecting strings to be used when assembling the final trace - function Dumper:add(text) - self.lines[#self.lines + 1] = text - end - function Dumper:add_f(fmt, ...) - self:add(fmt:format(...)) - end - function Dumper:concat_lines() - return table_concat(self.lines) - end - - --- - -- Private: - -- Iterates over the local variables of a given function. - -- - -- @param level The stack level where the function is. - -- - function Dumper:DumpLocals(level) - local prefix = "\t " - local i = 1 - - if self.dumping_same_thread then - level = level + 1 - end - - local name, value = self.getlocal(level, i) - if not name then - return - end - self:add("\tLocal variables:\r\n") - while name do - if type(value) == "number" then - self:add_f("%s%s = number: %g\r\n", prefix, name, value) - elseif type(value) == "boolean" then - self:add_f("%s%s = boolean: %s\r\n", prefix, name, tostring(value)) - elseif type(value) == "string" then - self:add_f("%s%s = string: %q\r\n", prefix, name, value) - elseif type(value) == "userdata" then - self:add_f("%s%s = %s\r\n", prefix, name, safe_tostring(value)) - elseif type(value) == "nil" then - self:add_f("%s%s = nil\r\n", prefix, name) - elseif type(value) == "table" then - if m_known_tables[value] then - self:add_f("%s%s = %s\r\n", prefix, name, m_known_tables[value]) - elseif m_user_known_tables[value] then - self:add_f("%s%s = %s\r\n", prefix, name, m_user_known_tables[value]) - else - local txt = "{" - for k, v in pairs(value) do - txt = txt .. safe_tostring(k) .. ":" .. safe_tostring(v) - if #txt > _M.max_tb_output_len then - txt = txt .. " (more...)" - break - end - if next(value, k) then - txt = txt .. ", " - end - end - self:add_f("%s%s = %s %s\r\n", prefix, name, safe_tostring(value), txt .. "}") - end - elseif type(value) == "function" then - local info = self.getinfo(value, "nS") - local fun_name = info.name or m_known_functions[value] or m_user_known_functions[value] - if info.what == "C" then - self:add_f("%s%s = C %s\r\n", prefix, name, - (fun_name and ("function: " .. fun_name) or tostring(value))) - else - local source = info.short_src - if source:sub(2, 7) == "string" then - source = source:sub(9) -- uno más, por el espacio que viene (string "Baragent.Main", por ejemplo) - end - -- for k,v in pairs(info) do print(k,v) end - fun_name = fun_name or GuessFunctionName(info) - self:add_f("%s%s = Lua function '%s' (defined at line %d of chunk %s)\r\n", prefix, name, fun_name, - info.linedefined, source) - end - elseif type(value) == "thread" then - self:add_f("%sthread %q = %s\r\n", prefix, name, tostring(value)) - end - i = i + 1 - name, value = self.getlocal(level, i) - end - end - - --- - -- Public: - -- Collects a detailed stack trace, dumping locals, resolving function names when they're not available, etc. - -- This function is suitable to be used as an error handler with pcall or xpcall - -- - -- @param thread An optional thread whose stack is to be inspected (defaul is the current thread) - -- @param message An optional error string or object. - -- @param level An optional number telling at which level to start the traceback (default is 1) - -- - -- Returns a string with the stack trace and a string with the original error. - -- - function _M.stacktrace(thread, message, level) - if type(thread) ~= "thread" then - -- shift parameters left - thread, message, level = nil, thread, message - end - - thread = thread or coroutine.running() - - level = level or 1 - - local dumper = Dumper.new(thread) - - local original_error - - if type(message) == "table" then - dumper:add("an error object {\r\n") - local first = true - for k, v in pairs(message) do - if first then - dumper:add(" ") - first = false - else - dumper:add(",\r\n ") - end - dumper:add(safe_tostring(k)) - dumper:add(": ") - dumper:add(safe_tostring(v)) - end - dumper:add("\r\n}") - original_error = dumper:concat_lines() - elseif type(message) == "string" then - dumper:add(message) - original_error = message - end - - dumper:add("\r\n") - dumper:add [[ -Stack Traceback -=============== -]] - -- print(error_message) - - local level_to_show = level - if dumper.dumping_same_thread then - level = level + 1 - end - - local info = dumper.getinfo(level, "nSlf") - while info do - if info.what == "main" then - if string_sub(info.source, 1, 1) == "@" then - dumper:add_f("(%d) main chunk of file '%s' at line %d\r\n", level_to_show, - string_sub(info.source, 2), info.currentline) - elseif info.source and info.source:sub(1, 1) == "=" then - local str = info.source:sub(3, -2) - local props = {} - -- Split by space - for v in string.gmatch(str, "[^%s]+") do - table.insert(props, v) - end - local source = table.remove(props, 1) - if source == "love" then - dumper:add_f("(%d) main chunk of LÖVE file '%s' at line %d\r\n", level_to_show, - table.concat(props, " "):sub(2, -2), info.currentline) - elseif source == "SMODS" then - local modID = table.remove(props, 1) - local fileName = table.concat(props, " ") - if modID == '_' then - dumper:add_f("(%d) main chunk of Steamodded file '%s' at line %d\r\n", level_to_show, - fileName:sub(2, -2), info.currentline) - else - dumper:add_f("(%d) main chunk of file '%s' at line %d (from mod with id %s)\r\n", - level_to_show, fileName:sub(2, -2), info.currentline, modID) - end - elseif source == "lovely" then - local module = table.remove(props, 1) - local fileName = table.concat(props, " ") - dumper:add_f("(%d) main chunk of file '%s' at line %d (from lovely module %s)\r\n", - level_to_show, fileName:sub(2, -2), info.currentline, module) - else - dumper:add_f("(%d) main chunk of %s at line %d\r\n", level_to_show, info.source, - info.currentline) - end - else - dumper:add_f("(%d) main chunk of %s at line %d\r\n", level_to_show, info.source, info.currentline) - end - elseif info.what == "C" then - -- print(info.namewhat, info.name) - -- for k,v in pairs(info) do print(k,v, type(v)) end - local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name or - tostring(info.func) - dumper:add_f("(%d) %s C function '%s'\r\n", level_to_show, info.namewhat, function_name) - -- dumper:add_f("%s%s = C %s\r\n", prefix, name, (m_known_functions[value] and ("function: " .. m_known_functions[value]) or tostring(value))) - elseif info.what == "tail" then - -- print("tail") - -- for k,v in pairs(info) do print(k,v, type(v)) end--print(info.namewhat, info.name) - dumper:add_f("(%d) tail call\r\n", level_to_show) - dumper:DumpLocals(level) - elseif info.what == "Lua" then - local source = info.short_src - local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name - if source:sub(2, 7) == "string" then - source = source:sub(9) - end - local was_guessed = false - if not function_name or function_name == "?" then - -- for k,v in pairs(info) do print(k,v, type(v)) end - function_name = GuessFunctionName(info) - was_guessed = true - end - -- test if we have a file name - local function_type = (info.namewhat == "") and "function" or info.namewhat - if info.source and info.source:sub(1, 1) == "@" then - dumper:add_f("(%d) Lua %s '%s' at file '%s:%d'%s\r\n", level_to_show, function_type, function_name, - info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "") - elseif info.source and info.source:sub(1, 1) == '#' then - dumper:add_f("(%d) Lua %s '%s' at template '%s:%d'%s\r\n", level_to_show, function_type, - function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "") - elseif info.source and info.source:sub(1, 1) == "=" then - local str = info.source:sub(3, -2) - local props = {} - -- Split by space - for v in string.gmatch(str, "[^%s]+") do - table.insert(props, v) - end - local source = table.remove(props, 1) - if source == "love" then - dumper:add_f("(%d) LÖVE %s at file '%s:%d'%s\r\n", level_to_show, function_type, - table.concat(props, " "):sub(2, -2), info.currentline, was_guessed and " (best guess)" or "") - elseif source == "SMODS" then - local modID = table.remove(props, 1) - local fileName = table.concat(props, " ") - if modID == '_' then - dumper:add_f("(%d) Lua %s '%s' at Steamodded file '%s:%d' %s\r\n", level_to_show, - function_type, function_name, fileName:sub(2, -2), info.currentline, - was_guessed and " (best guess)" or "") - else - dumper:add_f("(%d) Lua %s '%s' at file '%s:%d' (from mod with id %s)%s\r\n", level_to_show, - function_type, function_name, fileName:sub(2, -2), info.currentline, modID, - was_guessed and " (best guess)" or "") - end - elseif source == "lovely" then - local module = table.remove(props, 1) - local fileName = table.concat(props, " ") - dumper:add_f("(%d) Lua %s '%s' at file '%s:%d' (from lovely module %s)%s\r\n", level_to_show, - function_type, function_name, fileName:sub(2, -2), info.currentline, module, - was_guessed and " (best guess)" or "") - else - dumper:add_f("(%d) Lua %s '%s' at line %d of chunk '%s'\r\n", level_to_show, function_type, - function_name, info.currentline, source) - end - else - dumper:add_f("(%d) Lua %s '%s' at line %d of chunk '%s'\r\n", level_to_show, function_type, - function_name, info.currentline, source) - end - dumper:DumpLocals(level) - else - dumper:add_f("(%d) unknown frame %s\r\n", level_to_show, info.what) - end - - level = level + 1 - level_to_show = level_to_show + 1 - info = dumper.getinfo(level, "nSlf") - end - - return dumper:concat_lines(), original_error - end - - -- - -- Adds a table to the list of known tables - function _M.add_known_table(tab, description) - if m_known_tables[tab] then - error("Cannot override an already known table") - end - m_user_known_tables[tab] = description - end - - -- - -- Adds a function to the list of known functions - function _M.add_known_function(fun, description) - if m_known_functions[fun] then - error("Cannot override an already known function") - end - m_user_known_functions[fun] = description - end - - return _M -end - --- Note: The below code is not from the original StackTracePlus.lua -local stackTraceAlreadyInjected = false - -function getDebugInfoForCrash() - local version = VERSION - if not version or type(version) ~= "string" then - local versionFile = love.filesystem.read("version.jkr") - if versionFile then - version = versionFile:match("[^\n]*") .. " (best guess)" - else - version = "???" - end - end - local modded_version = MODDED_VERSION - if not modded_version or type(modded_version) ~= "string" then - local moddedSuccess, reqVersion = pcall(require, "SMODS.version") - if moddedSuccess and type(reqVersion) == "string" then - modded_version = reqVersion - else - modded_version = "???" - end - end - - local info = "Additional Context:\nBalatro Version: " .. version .. "\nModded Version: " .. - (modded_version) - local major, minor, revision, codename = love.getVersion() - info = info .. string.format("\nLÖVE Version: %d.%d.%d", major, minor, revision) - - local lovely_success, lovely = pcall(require, "lovely") - if lovely_success then - info = info .. "\nLovely Version: " .. lovely.version - end - if SMODS and SMODS.Mods then - local mod_strings = "" - local lovely_strings = "" - local i = 1 - local lovely_i = 1 - for _, v in pairs(SMODS.Mods) do - if (v.can_load and (not v.meta_mod or v.lovely_only)) or (v.lovely and not v.can_load and not v.disabled) then - if v.lovely_only or (v.lovely and not v.can_load) then - lovely_strings = lovely_strings .. "\n " .. lovely_i .. ": " .. v.name - lovely_i = lovely_i + 1 - if not v.can_load then - lovely_strings = lovely_strings .. "\n Has Steamodded mod that failed to load." - if #v.load_issues.dependencies > 0 then - lovely_strings = lovely_strings .. "\n Missing Dependencies:" - for k, v in ipairs(v.load_issues.dependencies) do - lovely_strings = lovely_strings .. "\n " .. k .. ". " .. v - end - end - if #v.load_issues.conflicts > 0 then - lovely_strings = lovely_strings .. "\n Conflicts:" - for k, v in ipairs(v.load_issues.conflicts) do - lovely_strings = lovely_strings .. "\n " .. k .. ". " .. v - end - end - if v.load_issues.outdated then - lovely_strings = lovely_strings .. "\n Outdated Mod." - end - if v.load_issues.main_file_not_found then - lovely_strings = lovely_strings .. "\n Main file not found. (" .. v.main_file ..")" - end - end - else - mod_strings = mod_strings .. "\n " .. i .. ": " .. v.name .. " by " .. - table.concat(v.author, ", ") .. " [ID: " .. v.id .. - (v.priority ~= 0 and (", Priority: " .. v.priority) or "") .. - (v.version and v.version ~= '0.0.0' and (", Version: " .. v.version) or "") .. - (v.lovely and (", Uses Lovely") or "") .. "]" - i = i + 1 - local debugInfo = v.debug_info - if debugInfo then - if type(debugInfo) == "string" then - if #debugInfo ~= 0 then - mod_strings = mod_strings .. "\n " .. debugInfo - end - elseif type(debugInfo) == "table" then - for kk, vv in pairs(debugInfo) do - if type(vv) ~= 'nil' then - vv = tostring(vv) - end - if #vv ~= 0 then - mod_strings = mod_strings .. "\n " .. kk .. ": " .. vv - end - end - end - end - end - end - end - info = info .. "\nSteamodded Mods:" .. mod_strings .. "\nLovely Mods:" .. lovely_strings - end - return info -end - -function injectStackTrace() - if (stackTraceAlreadyInjected) then - return - end - stackTraceAlreadyInjected = true - local STP = loadStackTracePlus() - local utf8 = require("utf8") - - -- Modifed from https://love2d.org/wiki/love.errorhandler - function love.errorhandler(msg) - msg = tostring(msg) - - if not sendErrorMessage then - function sendErrorMessage(msg) - print(msg) - end - end - if not sendInfoMessage then - function sendInfoMessage(msg) - print(msg) - end - end - - sendErrorMessage("Oops! The game crashed\n" .. STP.stacktrace(msg), 'StackTrace') - - if not love.window or not love.graphics or not love.event then - return - end - - if not love.graphics.isCreated() or not love.window.isOpen() then - local success, status = pcall(love.window.setMode, 800, 600) - if not success or not status then - return - end - end - - -- Reset state. - if love.mouse then - love.mouse.setVisible(true) - love.mouse.setGrabbed(false) - love.mouse.setRelativeMode(false) - if love.mouse.isCursorSupported() then - love.mouse.setCursor() - end - end - if love.joystick then - -- Stop all joystick vibrations. - for i, v in ipairs(love.joystick.getJoysticks()) do - v:setVibration() - end - end - if love.audio then - love.audio.stop() - end - - love.graphics.reset() - local font = love.graphics.setNewFont("resources/fonts/m6x11plus.ttf", 20) - - local background = {0, 0, 1} - if G and G.C and G.C.BLACK then - background = G.C.BLACK - end - love.graphics.clear(background) - love.graphics.origin() - - local trace = STP.stacktrace("", 3) - - local sanitizedmsg = {} - for char in msg:gmatch(utf8.charpattern) do - table.insert(sanitizedmsg, char) - end - sanitizedmsg = table.concat(sanitizedmsg) - - local err = {} - - table.insert(err, "Oops! The game crashed:") - if sanitizedmsg:find("Syntax error: game.lua:4: '=' expected near 'Game'") then - table.insert(err, - 'Duplicate installation of Steamodded detected! Please clean your installation: Steam Library > Balatro > Properties > Installed Files > Verify integrity of game files.') - else - table.insert(err, sanitizedmsg) - end - if #sanitizedmsg ~= #msg then - table.insert(err, "Invalid UTF-8 string in error message.") - end - - local success, msg = pcall(getDebugInfoForCrash) - if success and msg then - table.insert(err, '\n' .. msg) - sendInfoMessage(msg, 'StackTrace') - else - table.insert(err, "\n" .. "Failed to get additional context :/") - sendErrorMessage("Failed to get additional context :/\n" .. msg, 'StackTrace') - end - - for l in trace:gmatch("(.-)\n") do - table.insert(err, l) - end - - local p = table.concat(err, "\n") - - p = p:gsub("\t", "") - p = p:gsub("%[string \"(.-)\"%]", "%1") - - local scrollOffset = 0 - local endHeight = 0 - love.keyboard.setKeyRepeat(true) - - local function scrollDown(amt) - if amt == nil then - amt = 18 - end - scrollOffset = scrollOffset + amt - if scrollOffset > endHeight then - scrollOffset = endHeight - end - end - - local function scrollUp(amt) - if amt == nil then - amt = 18 - end - scrollOffset = scrollOffset - amt - if scrollOffset < 0 then - scrollOffset = 0 - end - end - - local pos = 70 - local arrowSize = 20 - - local function calcEndHeight() - local font = love.graphics.getFont() - local rw, lines = font:getWrap(p, love.graphics.getWidth() - pos * 2) - local lineHeight = font:getHeight() - local atBottom = scrollOffset == endHeight and scrollOffset ~= 0 - endHeight = #lines * lineHeight - love.graphics.getHeight() + pos * 2 - if (endHeight < 0) then - endHeight = 0 - end - if scrollOffset > endHeight or atBottom then - scrollOffset = endHeight - end - end - - local function draw() - if not love.graphics.isActive() then - return - end - love.graphics.clear(background) - calcEndHeight() - love.graphics.printf(p, pos, pos - scrollOffset, love.graphics.getWidth() - pos * 2) - if scrollOffset ~= endHeight then - love.graphics.polygon("fill", love.graphics.getWidth() - (pos / 2), - love.graphics.getHeight() - arrowSize, love.graphics.getWidth() - (pos / 2) + arrowSize, - love.graphics.getHeight() - (arrowSize * 2), love.graphics.getWidth() - (pos / 2) - arrowSize, - love.graphics.getHeight() - (arrowSize * 2)) - end - if scrollOffset ~= 0 then - love.graphics.polygon("fill", love.graphics.getWidth() - (pos / 2), arrowSize, - love.graphics.getWidth() - (pos / 2) + arrowSize, arrowSize * 2, - love.graphics.getWidth() - (pos / 2) - arrowSize, arrowSize * 2) - end - love.graphics.present() - end - - local fullErrorText = p - local function copyToClipboard() - if not love.system then - return - end - love.system.setClipboardText(fullErrorText) - p = p .. "\nCopied to clipboard!" - end - - p = p .. "\n\nPress ESC to exit\nPress R to restart the game" - if love.system then - p = p .. "\nPress Ctrl+C or tap to copy this error" - end - - if G then - -- Kill threads (makes restarting possible) - if G.SOUND_MANAGER and G.SOUND_MANAGER.channel then - G.SOUND_MANAGER.channel:push({ - type = 'kill' - }) - end - if G.SAVE_MANAGER and G.SAVE_MANAGER.channel then - G.SAVE_MANAGER.channel:push({ - type = 'kill' - }) - end - if G.HTTP_MANAGER and G.HTTP_MANAGER.channel then - G.HTTP_MANAGER.channel:push({ - type = 'kill' - }) - end - end - - return function() - love.event.pump() - - for e, a, b, c in love.event.poll() do - if e == "quit" then - return 1 - elseif e == "keypressed" and a == "escape" then - return 1 - elseif e == "keypressed" and a == "c" and love.keyboard.isDown("lctrl", "rctrl") then - copyToClipboard() - elseif e == "keypressed" and a == "r" then - SMODS.restart_game() - elseif e == "keypressed" and a == "down" then - scrollDown() - elseif e == "keypressed" and a == "up" then - scrollUp() - elseif e == "keypressed" and a == "pagedown" then - scrollDown(love.graphics.getHeight()) - elseif e == "keypressed" and a == "pageup" then - scrollUp(love.graphics.getHeight()) - elseif e == "keypressed" and a == "home" then - scrollOffset = 0 - elseif e == "keypressed" and a == "end" then - scrollOffset = endHeight - elseif e == "wheelmoved" then - scrollUp(b * 20) - elseif e == "gamepadpressed" and b == "dpdown" then - scrollDown() - elseif e == "gamepadpressed" and b == "dpup" then - scrollUp() - elseif e == "gamepadpressed" and b == "a" then - return "restart" - elseif e == "gamepadpressed" and b == "x" then - copyToClipboard() - elseif e == "gamepadpressed" and (b == "b" or b == "back" or b == "start") then - return 1 - elseif e == "touchpressed" then - local name = love.window.getTitle() - if #name == 0 or name == "Untitled" then - name = "Game" - end - local buttons = {"OK", "Cancel", "Restart"} - if love.system then - buttons[4] = "Copy to clipboard" - end - local pressed = love.window.showMessageBox("Quit " .. name .. "?", "", buttons) - if pressed == 1 then - return 1 - elseif pressed == 3 then - return "restart" - elseif pressed == 4 then - copyToClipboard() - end - end - end - - draw() - - if love.timer then - love.timer.sleep(0.1) - end - end - - end -end - -injectStackTrace() - --- ---------------------------------------------- --- --------MOD CORE API STACKTRACE END----------- - -if (love.system.getOS() == 'OS X' ) and (jit.arch == 'arm64' or jit.arch == 'arm') then jit.off() end -do - local logger = require("debugplus.logger") - logger.registerLogHandler() -end -require "engine/object" -require "bit" -require "engine/string_packer" -require "engine/controller" -require "back" -require "tag" -require "engine/event" -require "engine/node" -require "engine/moveable" -require "engine/sprite" -require "engine/animatedsprite" -require "functions/misc_functions" -require "game" -require "globals" -require "engine/ui" -require "functions/UI_definitions" -require "functions/state_events" -require "functions/common_events" -require "functions/button_callbacks" -require "functions/misc_functions" -require "functions/test_functions" -require "card" -require "cardarea" -require "blind" -require "card_character" -require "engine/particles" -require "engine/text" -require "challenges" - -math.randomseed( G.SEED ) - -function love.run() - if love.load then love.load(love.arg.parseGameArguments(arg), arg) end - - -- We don't want the first frame's dt to include time taken by love.load. - if love.timer then love.timer.step() end - - local dt = 0 - local dt_smooth = 1/100 - local run_time = 0 - - -- Main loop time. - return function() - run_time = love.timer.getTime() - -- Process events. - if love.event and G and G.CONTROLLER then - love.event.pump() - local _n,_a,_b,_c,_d,_e,_f,touched - for name, a,b,c,d,e,f in love.event.poll() do - if name == "quit" then - if not love.quit or not love.quit() then - return a or 0 - end - end - if name == 'touchpressed' then - touched = true - elseif name == 'mousepressed' then - _n,_a,_b,_c,_d,_e,_f = name,a,b,c,d,e,f - else - love.handlers[name](a,b,c,d,e,f) - end - end - if _n then - love.handlers['mousepressed'](_a,_b,_c,touched) - end - end - - -- Update dt, as we'll be passing it to update - if love.timer then dt = love.timer.step() end - dt_smooth = math.min(0.8*dt_smooth + 0.2*dt, 0.1) - -- Call update and draw - if love.update then love.update(dt_smooth) end -- will pass 0 if love.timer is disabled - - if love.graphics and love.graphics.isActive() then - if love.draw then love.draw() end - love.graphics.present() - end - - run_time = math.min(love.timer.getTime() - run_time, 0.1) - G.FPS_CAP = G.FPS_CAP or 500 - if run_time < 1./G.FPS_CAP then love.timer.sleep(1./G.FPS_CAP - run_time) end - end -end - -Cryptid = {} -Cryptid.enabled = {} -Cryptid.memepack = {} -Cryptid.aliases = {} -Cryptid.food = {} -Cryptid.M_jokers = {} -Cryptid.Megavouchers = {} -function cry_format(...) - return ... -end -function love.load() - G:start_up() - --Steam integration - local os = love.system.getOS() - if os == 'OS X' or os == 'Windows' or os == 'Linux' then - local st = nil - --To control when steam communication happens, make sure to send updates to steam as little as possible - local cwd = NFS.getWorkingDirectory() - NFS.setWorkingDirectory(love.filesystem.getSourceBaseDirectory()) - if os == 'OS X' or os == 'Linux' then - local dir = love.filesystem.getSourceBaseDirectory() - local old_cpath = package.cpath - package.cpath = package.cpath .. ';' .. dir .. '/?.so' - local success, _st = pcall(require, 'luasteam') - if success then st = _st else sendWarnMessage(_st); st = {} end - package.cpath = old_cpath - else - local success, _st = pcall(require, 'luasteam') - if success then st = _st else sendWarnMessage(_st); st = {} end - end - - st.send_control = { - last_sent_time = -200, - last_sent_stage = -1, - force = false, - } - if not (st.init and st:init()) then - st = nil - end - NFS.setWorkingDirectory(cwd) - --Set up the render window and the stage for the splash screen, then enter the gameloop with :update - G.STEAM = st - else - end - - --Set the mouse to invisible immediately, this visibility is handled in the G.CONTROLLER - love.mouse.setVisible(false) -end - -function love.quit() - --Steam integration - if G.SOUND_MANAGER then G.SOUND_MANAGER.channel:push({type = 'stop'}) end - if G.STEAM then G.STEAM:shutdown() end -end - -function love.update( dt ) - --Perf monitoring checkpoint - timer_checkpoint(nil, 'update', true) - G:update(dt) -end - -function love.draw() - --Perf monitoring checkpoint - timer_checkpoint(nil, 'draw', true) - G:draw() - do - local console = require("debugplus.console") - console.doConsoleRender() - timer_checkpoint('DebugPlus Console', 'draw') - end -end - -function love.keypressed(key) -if Handy.controller.process_key(key, false) then return end -local console = require("debugplus.console") -if not console.consoleHandleKey(key) then return end - if not _RELEASE_MODE and G.keybind_mapping[key] then love.gamepadpressed(G.CONTROLLER.keyboard_controller, G.keybind_mapping[key]) - else - G.CONTROLLER:set_HID_flags('mouse') - G.CONTROLLER:key_press(key) - end -end - -function love.keyreleased(key) -if Handy.controller.process_key(key, true) then return end - if not _RELEASE_MODE and G.keybind_mapping[key] then love.gamepadreleased(G.CONTROLLER.keyboard_controller, G.keybind_mapping[key]) - else - G.CONTROLLER:set_HID_flags('mouse') - G.CONTROLLER:key_release(key) - end -end - -function love.gamepadpressed(joystick, button) - button = G.button_mapping[button] or button - G.CONTROLLER:set_gamepad(joystick) - G.CONTROLLER:set_HID_flags('button', button) - G.CONTROLLER:button_press(button) -end - -function love.gamepadreleased(joystick, button) - button = G.button_mapping[button] or button - G.CONTROLLER:set_gamepad(joystick) - G.CONTROLLER:set_HID_flags('button', button) - G.CONTROLLER:button_release(button) -end - -function love.mousepressed(x, y, button, touch) -if not touch and Handy.controller.process_mouse(button, false) then return end - G.CONTROLLER:set_HID_flags(touch and 'touch' or 'mouse') - if button == 1 then - G.CONTROLLER:queue_L_cursor_press(x, y) - end - if button == 2 then - G.CONTROLLER:queue_R_cursor_press(x, y) - end -end - - -function love.mousereleased(x, y, button) -if Handy.controller.process_mouse(button, true) then return end - if button == 1 then G.CONTROLLER:L_cursor_release(x, y) end -end - -function love.mousemoved(x, y, dx, dy, istouch) - G.CONTROLLER.last_touch_time = G.CONTROLLER.last_touch_time or -1 - if next(love.touch.getTouches()) ~= nil then - G.CONTROLLER.last_touch_time = G.TIMERS.UPTIME - end - G.CONTROLLER:set_HID_flags(G.CONTROLLER.last_touch_time > G.TIMERS.UPTIME - 0.2 and 'touch' or 'mouse') -end - -function love.joystickaxis( joystick, axis, value ) - if math.abs(value) > 0.2 and joystick:isGamepad() then - G.CONTROLLER:set_gamepad(joystick) - G.CONTROLLER:set_HID_flags('axis') - end -end - -if false then - if G.F_NO_ERROR_HAND then return end - msg = tostring(msg) - - if G.SETTINGS.crashreports and _RELEASE_MODE and G.F_CRASH_REPORTS then - local http_thread = love.thread.newThread([[ - local https = require('https') - CHANNEL = love.thread.getChannel("http_channel") - - while true do - --Monitor the channel for any new requests - local request = CHANNEL:demand() - if request then - https.request(request) - end - end - ]]) - local http_channel = love.thread.getChannel('http_channel') - http_thread:start() - local httpencode = function(str) - local char_to_hex = function(c) - return string.format("%%%02X", string.byte(c)) - end - str = str:gsub("\n", "\r\n"):gsub("([^%w _%%%-%.~])", char_to_hex):gsub(" ", "+") - return str - end - - - local error = msg - local file = string.sub(msg, 0, string.find(msg, ':')) - local function_line = string.sub(msg, string.len(file)+1) - function_line = string.sub(function_line, 0, string.find(function_line, ':')-1) - file = string.sub(file, 0, string.len(file)-1) - local trace = debug.traceback() - local boot_found, func_found = false, false - for l in string.gmatch(trace, "(.-)\n") do - if string.match(l, "boot.lua") then - boot_found = true - elseif boot_found and not func_found then - func_found = true - trace = '' - function_line = string.sub(l, string.find(l, 'in function')+12)..' line:'..function_line - end - - if boot_found and func_found then - trace = trace..l..'\n' - end - end - - http_channel:push('https://958ha8ong3.execute-api.us-east-2.amazonaws.com/?error='..httpencode(error)..'&file='..httpencode(file)..'&function_line='..httpencode(function_line)..'&trace='..httpencode(trace)..'&version='..(G.VERSION)) - end - - if not love.window or not love.graphics or not love.event then - return - end - - if not love.graphics.isCreated() or not love.window.isOpen() then - local success, status = pcall(love.window.setMode, 800, 600) - if not success or not status then - return - end - end - - -- Reset state. - if love.mouse then - love.mouse.setVisible(true) - love.mouse.setGrabbed(false) - love.mouse.setRelativeMode(false) - end - if love.joystick then - -- Stop all joystick vibrations. - for i,v in ipairs(love.joystick.getJoysticks()) do - v:setVibration() - end - end - if love.audio then love.audio.stop() end - love.graphics.reset() - local font = love.graphics.setNewFont("resources/fonts/m6x11plus.ttf", 20) - - love.graphics.clear(G.C.BLACK) - love.graphics.origin() - - - local p = 'Oops! Something went wrong:\n'..msg..'\n\n'..(not _RELEASE_MODE and debug.traceback() or G.SETTINGS.crashreports and - 'Since you are opted in to sending crash reports, LocalThunk HQ was sent some useful info about what happened.\nDon\'t worry! There is no identifying or personal information. If you would like\nto opt out, change the \'Crash Report\' setting to Off' or - 'Crash Reports are set to Off. If you would like to send crash reports, please opt in in the Game settings.\nThese crash reports help us avoid issues like this in the future') - - local function draw() - local pos = love.window.toPixels(70) - love.graphics.push() - love.graphics.clear(G.C.BLACK) - love.graphics.setColor(1., 1., 1., 1.) - love.graphics.printf(p, font, pos, pos, love.graphics.getWidth() - pos) - love.graphics.pop() - love.graphics.present() - - end - - while true do - love.event.pump() - - for e, a, b, c in love.event.poll() do - if e == "quit" then - return - elseif e == "keypressed" and a == "escape" then - return - elseif e == "touchpressed" then - local name = love.window.getTitle() - if #name == 0 or name == "Untitled" then name = "Game" end - local buttons = {"OK", "Cancel"} - local pressed = love.window.showMessageBox("Quit "..name.."?", "", buttons) - if pressed == 1 then - return - end - end - end - - draw() - - if love.timer then - love.timer.sleep(0.1) - end - end - -end - -function love.resize(w, h) - if w/h < 1 then --Dont allow the screen to be too square, since pop in occurs above and below screen - h = w/1 - end - - --When the window is resized, this code resizes the Canvas, then places the 'room' or gamearea into the middle without streching it - if w/h < G.window_prev.orig_ratio then - G.TILESCALE = G.window_prev.orig_scale*w/G.window_prev.w - else - G.TILESCALE = G.window_prev.orig_scale*h/G.window_prev.h - end - - if G.ROOM then - G.ROOM.T.w = G.TILE_W - G.ROOM.T.h = G.TILE_H - G.ROOM_ATTACH.T.w = G.TILE_W - G.ROOM_ATTACH.T.h = G.TILE_H - - if w/h < G.window_prev.orig_ratio then - G.ROOM.T.x = G.ROOM_PADDING_W - G.ROOM.T.y = (h/(G.TILESIZE*G.TILESCALE) - (G.ROOM.T.h+G.ROOM_PADDING_H))/2 + G.ROOM_PADDING_H/2 - else - G.ROOM.T.y = G.ROOM_PADDING_H - G.ROOM.T.x = (w/(G.TILESIZE*G.TILESCALE) - (G.ROOM.T.w+G.ROOM_PADDING_W))/2 + G.ROOM_PADDING_W/2 - end - - G.ROOM_ORIG = { - x = G.ROOM.T.x, - y = G.ROOM.T.y, - r = G.ROOM.T.r - } - - if G.buttons then G.buttons:recalculate() end - if G.HUD then G.HUD:recalculate() end - end - - G.WINDOWTRANS = { - x = 0, y = 0, - w = G.TILE_W+2*G.ROOM_PADDING_W, - h = G.TILE_H+2*G.ROOM_PADDING_H, - real_window_w = w, - real_window_h = h - } - - G.CANV_SCALE = 1 - - if love.system.getOS() == 'Windows' and false then --implement later if needed - local render_w, render_h = love.window.getDesktopDimensions(G.SETTINGS.WINDOW.selcted_display) - local unscaled_dims = love.window.getFullscreenModes(G.SETTINGS.WINDOW.selcted_display)[1] - - local DPI_scale = math.floor((0.5*unscaled_dims.width/render_w + 0.5*unscaled_dims.height/render_h)*500 + 0.5)/500 - - if DPI_scale > 1.1 then - G.CANV_SCALE = 1.5 - - G.AA_CANVAS = love.graphics.newCanvas(G.WINDOWTRANS.real_window_w*G.CANV_SCALE, G.WINDOWTRANS.real_window_h*G.CANV_SCALE, {type = '2d', readable = true}) - G.AA_CANVAS:setFilter('linear', 'linear') - else - G.AA_CANVAS = nil - end - end - - G.CANVAS = love.graphics.newCanvas(w*G.CANV_SCALE, h*G.CANV_SCALE, {type = '2d', readable = true}) - G.CANVAS:setFilter('linear', 'linear') -end - ---- STEAMODDED CORE ---- MODULE CORE - -SMODS = {} -MODDED_VERSION = require'SMODS.version' -SMODS.id = 'Steamodded' -SMODS.version = MODDED_VERSION:gsub('%-STEAMODDED', '') -SMODS.can_load = true -SMODS.meta_mod = true - --- Include lovely and nativefs modules -local nativefs = require "nativefs" -local lovely = require "lovely" -local json = require "json" - -local lovely_mod_dir = lovely.mod_dir:gsub("/$", "") -NFS = nativefs --- make lovely_mod_dir an absolute path. --- respects symlink/.. combos -NFS.setWorkingDirectory(lovely_mod_dir) -lovely_mod_dir = NFS.getWorkingDirectory() --- make sure NFS behaves the same as love.filesystem -NFS.setWorkingDirectory(love.filesystem.getSaveDirectory()) - -JSON = json - -local function set_mods_dir() - local love_dirs = { - love.filesystem.getSaveDirectory(), - love.filesystem.getSourceBaseDirectory() - } - for _, love_dir in ipairs(love_dirs) do - if lovely_mod_dir:sub(1, #love_dir) == love_dir then - -- relative path from love_dir - SMODS.MODS_DIR = lovely_mod_dir:sub(#love_dir+2) - NFS.setWorkingDirectory(love_dir) - return - end - end - SMODS.MODS_DIR = lovely_mod_dir -end -set_mods_dir() - -local function find_self(directory, target_filename, target_line, depth) - depth = depth or 1 - if depth > 3 then return end - for _, filename in ipairs(NFS.getDirectoryItems(directory)) do - local file_path = directory .. "/" .. filename - local file_type = NFS.getInfo(file_path).type - if file_type == 'directory' or file_type == 'symlink' then - local f = find_self(file_path, target_filename, target_line, depth+1) - if f then return f end - elseif filename == target_filename then - local first_line = NFS.read(file_path):match('^(.-)\n') - if first_line == target_line then - -- use parent directory - return directory:match('^(.+/)') - end - end - end -end - -SMODS.path = find_self(SMODS.MODS_DIR, 'core.lua', '--- STEAMODDED CORE') - -Cartomancer_nfs_read = NFS.read -NFS.read = Cartomancer_nfs_read_override - - -for _, path in ipairs { - "src/ui.lua", - "src/index.lua", - "src/utils.lua", - "src/overrides.lua", - "src/game_object.lua", - "src/logging.lua", - "src/compat_0_9_8.lua", - "src/loader.lua", -} do - assert(load(NFS.read(SMODS.path..path), ('=[SMODS _ "%s"]'):format(path)))() -end - -Handy = setmetatable({ - last_clicked_area = nil, - last_clicked_card = nil, - - utils = {}, -}, {}) - ---- @generic T ---- @generic S ---- @param target T ---- @param source S ---- @param ... any ---- @return T | S -function Handy.utils.table_merge(target, source, ...) - assert(type(target) == "table", "Target is not a table") - local tables_to_merge = { source, ... } - if #tables_to_merge == 0 then - return target - end - - for k, t in ipairs(tables_to_merge) do - assert(type(t) == "table", string.format("Expected a table as parameter %d", k)) - end - - for i = 1, #tables_to_merge do - local from = tables_to_merge[i] - for k, v in pairs(from) do - if type(k) == "number" then - table.insert(target, v) - elseif type(k) == "string" then - if type(v) == "table" then - target[k] = target[k] or {} - target[k] = Handy.utils.table_merge(target[k], v) - else - target[k] = v - end - end - end - end - - return target -end - -function Handy.utils.table_contains(t, value) - for i = #t, 1, -1 do - if t[i] and t[i] == value then - return true - end - end - return false -end - --- - -Handy.config = { - default = { - notifications_level = 3, - - insta_highlight = { - enabled = true, - }, - insta_buy_or_sell = { - enabled = true, - key_1 = "Shift", - key_2 = nil, - }, - insta_use = { - enabled = true, - key_1 = "Ctrl", - key_2 = nil, - }, - move_highlight = { - enabled = true, - - swap = { - enabled = true, - key_1 = "Shift", - key_2 = nil, - }, - to_end = { - enabled = true, - key_1 = "Ctrl", - key_2 = nil, - }, - - dx = { - one_left = { - enabled = true, - key_1 = "Left", - key_2 = nil, - }, - one_right = { - enabled = true, - key_1 = "Right", - key_2 = nil, - }, - }, - }, - - insta_cash_out = { - enabled = true, - key_1 = "Enter", - key_2 = nil, - }, - insta_booster_skip = { - enabled = true, - key_1 = "Enter", - key_2 = nil, - }, - - dangerous_actions = { - enabled = false, - - immediate_buy_and_sell = { - enabled = true, - key_1 = "Middle Mouse", - key_2 = nil, - - queue = { - enabled = false, - }, - }, - - nopeus_unsafe = { - enabled = true, - }, - }, - - speed_multiplier = { - enabled = true, - - key_1 = "Alt", - key_2 = nil, - }, - - shop_reroll = { - enabled = true, - key_1 = "Q", - key_2 = nil, - }, - play_and_discard = { - enabled = true, - play = { - enabled = true, - key_1 = nil, - key_2 = nil, - }, - discard = { - enabled = true, - key_1 = nil, - key_2 = nil, - }, - }, - - nopeus_interaction = { - enabled = true, - - key_1 = "]", - key_2 = nil, - }, - - not_just_yet_interaction = { - enabled = true, - key_1 = "Enter", - key_2 = nil, - }, - }, - current = {}, - - save = function() - if Handy.current_mod then - Handy.current_mod.config = Handy.config.current - SMODS.save_mod_config(Handy.current_mod) - end - end, -} -Handy.config.current = Handy.utils.table_merge({}, Handy.config.default) - --- - -Handy.fake_events = { - check = function(arg) - local fake_event = { - UIBox = arg.UIBox, - config = { - ref_table = arg.card, - button = arg.button, - id = arg.id, - }, - } - arg.func(fake_event) - return fake_event.config.button ~= nil, fake_event.config.button - end, - execute = function(arg) - if type(arg.func) == "function" then - arg.func({ - UIBox = arg.UIBox, - config = { - ref_table = arg.card, - button = arg.button, - id = arg.id, - }, - }) - end - end, -} -Handy.controller = { - bind_module = nil, - bind_key = nil, - bind_button = nil, - - update_bind_button_text = function(text) - local button_text = Handy.controller.bind_button.children[1].children[1] - button_text.config.text_drawable = nil - button_text.config.text = text - button_text:update_text() - button_text.UIBox:recalculate() - end, - init_bind = function(button) - button.config.button = nil - Handy.controller.bind_button = button - Handy.controller.bind_module = button.config.ref_table.module - Handy.controller.bind_key = button.config.ref_table.key - - Handy.controller.update_bind_button_text( - "[" .. (Handy.controller.bind_module[Handy.controller.bind_key] or "None") .. "]" - ) - end, - complete_bind = function(key) - Handy.controller.bind_module[Handy.controller.bind_key] = key - Handy.controller.update_bind_button_text(key or "None") - - Handy.controller.bind_button.config.button = "handy_init_keybind_change" - Handy.controller.bind_button = nil - Handy.controller.bind_module = nil - Handy.controller.bind_key = nil - end, - cancel_bind = function() - Handy.controller.update_bind_button_text(Handy.controller.bind_module[Handy.controller.bind_key] or "None") - - Handy.controller.bind_button.config.button = "handy_init_keybind_change" - Handy.controller.bind_button = nil - Handy.controller.bind_module = nil - Handy.controller.bind_key = nil - end, - - process_bind = function(key) - if not Handy.controller.bind_button then - return false - end - local parsed_key = Handy.controller.parse(key) - if parsed_key == "Escape" then - parsed_key = nil - end - Handy.controller.complete_bind(parsed_key) - Handy.config.save() - return true - end, - - parse_table = { - ["mouse1"] = "Left Mouse", - ["mouse2"] = "Right Mouse", - ["mouse3"] = "Middle Mouse", - ["mouse4"] = "Mouse 4", - ["mouse5"] = "Mouse 5", - ["wheelup"] = "Wheel Up", - ["wheeldown"] = "Wheel Down", - ["lshift"] = "Shift", - ["rshift"] = "Shift", - ["lctrl"] = "Ctrl", - ["rctrl"] = "Ctrl", - ["lalt"] = "Alt", - ["ralt"] = "Alt", - ["lgui"] = "GUI", - ["rgui"] = "GUI", - ["return"] = "Enter", - ["kpenter"] = "Enter", - ["pageup"] = "Page Up", - ["pagedown"] = "Page Down", - ["numlock"] = "Num Lock", - ["capslock"] = "Caps Lock", - ["scrolllock"] = "Scroll Lock", - }, - resolve_table = { - ["Left Mouse"] = { "mouse1" }, - ["Right Mouse"] = { "mouse2" }, - ["Middle Mouse"] = { "mouse3" }, - ["Mouse 4"] = { "mouse4" }, - ["Mouse 5"] = { "mouse5" }, - ["Wheel Up"] = { "wheelup" }, - ["Wheel Down"] = { "wheeldown" }, - ["Shift"] = { "lshift", "rshift" }, - ["Ctrl"] = { "lctrl", "rctrl" }, - ["Alt"] = { "lalt", "ralt" }, - ["GUI"] = { "lgui", "rgui" }, - ["Enter"] = { "return", "kpenter" }, - ["Page Up"] = { "pageup" }, - ["Page Down"] = { "pagedown" }, - ["Num Lock"] = { "numlock" }, - ["Caps Lock"] = { "capslock" }, - ["Scroll Lock"] = { "scrolllock" }, - }, - - mouse_to_key_table = { - [1] = "mouse1", - [2] = "mouse2", - [3] = "mouse3", - [4] = "mouse4", - [5] = "mouse5", - }, - wheel_to_key_table = { - [1] = "wheelup", - [2] = "wheeldown", - }, - - mouse_buttons = { - ["Left Mouse"] = 1, - ["Right Mouse"] = 2, - ["Middle Mouse"] = 3, - ["Mouse 4"] = 4, - ["Mouse 5"] = 5, - }, - wheel_buttons = { - ["Wheel Up"] = 1, - ["Wheel Down"] = 2, - }, - - parse = function(raw_key) - if not raw_key then - return nil - end - if Handy.controller.parse_table[raw_key] then - return Handy.controller.parse_table[raw_key] - elseif string.sub(raw_key, 1, 2) == "kp" then - return "NUM " .. string.sub(raw_key, 3) - else - return string.upper(string.sub(raw_key, 1, 1)) .. string.sub(raw_key, 2) - end - end, - resolve = function(parsed_key) - if not parsed_key then - return nil - end - if Handy.controller.resolve_table[parsed_key] then - return unpack(Handy.controller.resolve_table[parsed_key]) - elseif string.sub(parsed_key, 1, 4) == "NUM " then - return "kp" .. string.sub(parsed_key, 5) - else - local str = string.gsub(string.lower(parsed_key), "%s+", "") - return str - end - end, - is_down = function(...) - local parsed_keys = { ... } - for i = 1, #parsed_keys do - local parsed_key = parsed_keys[i] - if parsed_key and parsed_key ~= "Unknown" then - if Handy.controller.wheel_buttons[parsed_key] then - -- Well, skip - elseif Handy.controller.mouse_buttons[parsed_key] then - if love.mouse.isDown(Handy.controller.mouse_buttons[parsed_key]) then - return true - end - else - local success, is_down = pcall(function() - return love.keyboard.isDown(Handy.controller.resolve(parsed_key)) - end) - if success and is_down then - return true - end - end - end - end - return false - end, - is = function(raw_key, ...) - if not raw_key then - return false - end - local parsed_keys = { ... } - for i = 1, #parsed_keys do - local parsed_key = parsed_keys[i] - if parsed_key then - local resolved_key_1, resolved_key_2 = Handy.controller.resolve(parsed_key) - if raw_key and raw_key ~= "Unknown" and (raw_key == resolved_key_1 or raw_key == resolved_key_2) then - return true - end - end - end - return false - end, - - is_module_key_down = function(module) - return module and module.enabled and Handy.controller.is_down(module.key_1, module.key_2) - end, - is_module_key = function(module, raw_key) - return module and module.enabled and Handy.controller.is(raw_key, module.key_1, module.key_2) - end, - - process_key = function(key, released) - if not released then - if Handy.controller.process_bind(key) then - return true - end - - Handy.move_highlight.use(key) - Handy.speed_multiplier.use(key) - Handy.shop_reroll.use(key) - Handy.play_and_discard.use(key) - end - Handy.insta_booster_skip.use(key, released) - Handy.insta_cash_out.use(key, released) - Handy.not_just_yet_interaction.use(key, released) - Handy.dangerous_actions.toggle_queue(key, released) - Handy.UI.state_panel.update(key, released) - return false - end, - process_mouse = function(mouse, released) - local key = Handy.controller.mouse_to_key_table[mouse] - if not released then - if Handy.controller.process_bind(key) then - return true - end - - Handy.move_highlight.use(key) - Handy.speed_multiplier.use(key) - Handy.shop_reroll.use(key) - Handy.play_and_discard.use(key) - end - Handy.insta_booster_skip.use(key, released) - Handy.insta_cash_out.use(key, released) - Handy.not_just_yet_interaction.use(key, released) - Handy.dangerous_actions.toggle_queue(key, released) - Handy.UI.state_panel.update(key, released) - return false - end, - process_wheel = function(wheel) - local key = Handy.controller.wheel_to_key_table[wheel] - - if Handy.controller.process_bind(key) then - return true - end - - Handy.move_highlight.use(key) - Handy.speed_multiplier.use(key) - Handy.nopeus_interaction.use(key) - Handy.shop_reroll.use(key) - Handy.play_and_discard.use(key) - Handy.UI.state_panel.update(key, false) - end, - process_card_click = function(card) - if Handy.insta_actions.use(card) then - return true - end - Handy.last_clicked_card = card - Handy.last_clicked_area = card.area - return false - end, - process_card_hover = function(card) - if Handy.insta_highlight.use(card) then - return true - end - if Handy.dangerous_actions.use(card) then - return true - end - return false - end, - process_update = function(dt) - Handy.insta_booster_skip.update() - Handy.insta_cash_out.update() - Handy.not_just_yet_interaction.update() - Handy.UI.update(dt) - end, -} - --- - -Handy.insta_cash_out = { - is_hold = false, - - is_skipped = false, - is_button_created = false, - dollars = nil, - - can_execute = function(check) - if check then - return not not ( - Handy.insta_cash_out.is_hold - and G.STAGE == G.STAGES.RUN - and Handy.insta_cash_out.is_skipped - and not G.SETTINGS.paused - and G.round_eval - ) - else - return not not ( - Handy.insta_cash_out.is_hold - and G.STAGE == G.STAGES.RUN - and not Handy.insta_cash_out.is_skipped - and Handy.insta_cash_out.dollars - and not G.SETTINGS.paused - and G.round_eval - ) - end - end, - execute = function() - Handy.insta_cash_out.is_skipped = true - - if Handy.insta_cash_out.is_button_created then - G.GAME.current_round.dollars = Handy.insta_cash_out.dollars - Handy.insta_cash_out.dollars = nil - end - G.E_MANAGER:add_event(Event({ - trigger = "immediate", - func = function() - G.FUNCS.cash_out({ - config = { - id = "cash_out_button", - }, - }) - return true - end, - })) - return true - end, - - use = function(key, released) - if Handy.controller.is_module_key(Handy.config.current.insta_cash_out, key) then - Handy.insta_cash_out.is_hold = not released - end - return false - end, - - update = function() - if not Handy.config.current.insta_cash_out.enabled then - Handy.insta_cash_out.is_hold = false - end - return Handy.insta_cash_out.can_execute() and Handy.insta_cash_out.execute() or false - end, - - update_state_panel = function(state, key, released) - -- if G.STAGE ~= G.STAGES.RUN then - -- return false - -- end - -- if Handy.config.current.notifications_level < 4 then - -- return false - -- end - -- if Handy.insta_cash_out.can_execute(true) then - -- state.items.insta_cash_out = { - -- text = "Skip Cash Out", - -- hold = false, - -- order = 10, - -- } - -- return true - -- end - -- return false - end, -} - -Handy.insta_booster_skip = { - is_hold = false, - is_skipped = false, - - can_execute = function(check) - if check then - return not not ( - Handy.insta_booster_skip.is_hold - and G.STAGE == G.STAGES.RUN - and not G.SETTINGS.paused - and G.booster_pack - ) - end - return not not ( - Handy.insta_booster_skip.is_hold - and not Handy.insta_booster_skip.is_skipped - and G.STAGE == G.STAGES.RUN - and not G.SETTINGS.paused - and G.booster_pack - and Handy.fake_events.check({ - func = G.FUNCS.can_skip_booster, - }) - ) - end, - execute = function() - Handy.insta_booster_skip.is_skipped = true - G.E_MANAGER:add_event(Event({ - func = function() - G.FUNCS.skip_booster() - return true - end, - })) - return true - end, - - use = function(key, released) - if Handy.controller.is_module_key(Handy.config.current.insta_booster_skip, key) then - Handy.insta_booster_skip.is_hold = not released - end - return false - end, - - update = function() - if not Handy.config.current.insta_booster_skip.enabled then - Handy.insta_booster_skip.is_hold = false - end - return Handy.insta_booster_skip.can_execute() and Handy.insta_booster_skip.execute() or false - end, - - update_state_panel = function(state, key, released) - if G.STAGE ~= G.STAGES.RUN then - return false - end - if Handy.config.current.notifications_level < 4 then - return false - end - if Handy.insta_booster_skip.can_execute(true) then - state.items.insta_booster_skip = { - text = "Skip Booster Packs", - hold = Handy.insta_booster_skip.is_hold, - order = 10, - } - return true - end - return false - end, -} - -Handy.insta_highlight = { - can_execute = function(card) - return G.STAGE == G.STAGES.RUN - and Handy.config.current.insta_highlight.enabled - and card - and card.area == G.hand - -- TODO: fix it - and not next(love.touch.getTouches()) - and love.mouse.isDown(1) - and not card.highlighted - end, - execute = function(card) - card.area:add_to_highlighted(card) - return false - end, - - use = function(card) - return Handy.insta_highlight.can_execute(card) and Handy.insta_highlight.execute(card) or false - end, - - update_state_panel = function(state, key, released) end, -} - -Handy.insta_actions = { - get_actions = function() - return { - buy_or_sell = Handy.controller.is_module_key_down(Handy.config.current.insta_buy_or_sell), - use = Handy.controller.is_module_key_down(Handy.config.current.insta_use), - } - end, - can_execute = function(card, buy_or_sell, use) - return not not (G.STAGE == G.STAGES.RUN and (buy_or_sell or use) and card and card.area) - end, - execute = function(card, buy_or_sell, use, only_sell) - local target_button = nil - local is_shop_button = false - local is_custom_button = false - local is_playable_consumeable = false - - local base_background = G.UIDEF.card_focus_ui(card) - local base_attach = base_background:get_UIE_by_ID("ATTACH_TO_ME").children - local card_buttons = G.UIDEF.use_and_sell_buttons(card) - local result_funcs = {} - for _, node in ipairs(card_buttons.nodes) do - if node.config and node.config.func then - result_funcs[node.config.func] = node - end - end - local is_booster_pack_card = (G.pack_cards and card.area == G.pack_cards) and not card.ability.consumeable - - if use then - if card.area == G.hand and card.ability.consumeable then - local success, playale_consumeable_button = pcall(function() - -- G.UIDEF.use_and_sell_buttons(G.hand.highlighted[1]).nodes[1].nodes[2].nodes[1].nodes[1] - return card_buttons.nodes[1].nodes[2].nodes[1].nodes[1] - end) - if success and playale_consumeable_button then - target_button = playale_consumeable_button - is_custom_button = true - is_playable_consumeable = true - end - elseif result_funcs.can_select_alchemical or result_funcs.can_select_crazy_card then - -- Prevent cards to be selected when usage is required: - -- Alchemical cards, Cines - else - target_button = base_attach.buy_and_use - or (not is_booster_pack_card and base_attach.use) - or card.children.buy_and_use_button - is_shop_button = target_button == card.children.buy_and_use_button - end - elseif buy_or_sell then - target_button = card.children.buy_button - or result_funcs.can_select_crazy_card -- Cines - or result_funcs.can_select_alchemical -- Alchemical cards - or result_funcs.can_use_mupack -- Multipacks - or result_funcs.can_reserve_card -- Code cards, for example - or base_attach.buy - or base_attach.redeem - or base_attach.sell - or (is_booster_pack_card and base_attach.use) - - if only_sell and target_button ~= base_attach.sell then - target_button = nil - end - is_shop_button = target_button == card.children.buy_button - end - - if target_button and not is_custom_button and not is_shop_button then - for _, node in ipairs(card_buttons.nodes) do - if target_button == node then - is_custom_button = true - end - end - end - - local target_button_UIBox - local target_button_definition - - local cleanup = function() - base_background:remove() - if target_button_UIBox and is_custom_button then - target_button_UIBox:remove() - end - end - - if target_button then - if is_playable_consumeable then - card.area:add_to_highlighted(card) - if not card.highlighted then - cleanup() - return false - end - end - - target_button_UIBox = (is_custom_button and UIBox({ - definition = target_button, - config = {}, - })) or target_button - target_button_definition = (is_custom_button and target_button) - or (is_shop_button and target_button.definition) - or target_button.definition.nodes[1] - - local check, button = Handy.fake_events.check({ - func = G.FUNCS[target_button_definition.config.func], - button = nil, - id = target_button_definition.config.id, - card = card, - UIBox = target_button_UIBox, - }) - if check then - Handy.fake_events.execute({ - func = G.FUNCS[button or target_button_definition.config.button], - button = nil, - id = target_button_definition.config.id, - card = card, - UIBox = target_button_UIBox, - }) - cleanup() - return true - end - end - - cleanup() - return false - end, - - use = function(card) - if card.ability and card.ability.handy_dangerous_actions_used then - return true - end - - local actions = Handy.insta_actions.get_actions() - - return Handy.insta_actions.can_execute(card, actions.buy_or_sell, actions.use) - and Handy.insta_actions.execute(card, actions.buy_or_sell, actions.use) - or false - end, - - update_state_panel = function(state, key, released) - if G.STAGE ~= G.STAGES.RUN then - return false - end - if Handy.config.current.notifications_level < 4 then - return false - end - local result = false - local actions = Handy.insta_actions.get_actions() - if actions.use then - state.items.insta_use = { - text = "Quick use", - hold = true, - order = 10, - } - result = true - end - if actions.buy_or_sell then - state.items.quick_buy_and_sell = { - text = "Quick buy and sell", - hold = true, - order = 11, - } - result = true - end - return result - end, -} - -Handy.move_highlight = { - dx = { - one_left = -1, - one_right = 1, - }, - - get_dx = function(key, area) - for module_key, module in pairs(Handy.config.current.move_highlight.dx) do - if Handy.controller.is_module_key(module, key) then - return Handy.move_highlight.dx[module_key] - end - end - return nil - end, - get_actions = function(key, area) - return { - swap = Handy.controller.is_module_key_down(Handy.config.current.move_highlight.swap), - to_end = Handy.controller.is_module_key_down(Handy.config.current.move_highlight.to_end), - } - end, - - can_swap = function(key, area) - if not area then - return false - end - return not Handy.utils.table_contains({ - G.pack_cards, - G.shop_jokers, - G.shop_booster, - G.shop_vouchers, - }, area) - end, - cen_execute = function(key, area) - return not not ( - Handy.config.current.move_highlight.enabled - and G.STAGE == G.STAGES.RUN - and area - and area.highlighted - and area.highlighted[1] - and Handy.utils.table_contains({ - G.consumeables, - G.jokers, - G.cine_quests, - G.pack_cards, - G.shop_jokers, - G.shop_booster, - G.shop_vouchers, - }, area) - ) - end, - execute = function(key, area) - local dx = Handy.move_highlight.get_dx(key, area) - if not dx then - return false - end - - local current_card = area.highlighted[1] - for current_index = #area.cards, 1, -1 do - if area.cards[current_index] == current_card then - local actions = Handy.move_highlight.get_actions(key, area) - local next_index = actions.to_end and (dx > 0 and #area.cards or 1) - or ((#area.cards + current_index + dx - 1) % #area.cards) + 1 - if current_index == next_index then - return - end - local next_card = area.cards[next_index] - if not next_card then - return - end - if actions.swap and Handy.move_highlight.can_swap(key, area) then - if actions.to_end or next_index == 1 or next_index == #area.cards then - table.remove(area.cards, current_index) - table.insert(area.cards, next_index, current_card) - else - area.cards[next_index] = current_card - area.cards[current_index] = next_card - end - else - area:remove_from_highlighted(current_card) - area:add_to_highlighted(next_card) - end - return - end - end - end, - - use = function(key, area) - area = area or Handy.last_clicked_area - return Handy.move_highlight.cen_execute(key, area) and Handy.move_highlight.execute(key, area) or false - end, - - update_state_panel = function(state, key, released) end, -} - -Handy.dangerous_actions = { - sell_queue = {}, - - sell_next_card = function() - local card = table.remove(Handy.dangerous_actions.sell_queue, 1) - if not card then - stop_use() - return - end - - G.GAME.STOP_USE = 0 - Handy.insta_actions.execute(card, true, false, true) - - G.E_MANAGER:add_event(Event({ - blocking = false, - func = function() - if card.ability then - card.ability.handy_dangerous_actions_used = nil - end - return true - end, - })) - Handy.dangerous_actions.sell_next_card() - end, - - can_execute = function(card) - return G.STAGE == G.STAGES.RUN - and Handy.config.current.dangerous_actions.enabled - and card - and not (card.ability and card.ability.handy_dangerous_actions_used) - end, - execute = function(card) - if Handy.controller.is_module_key_down(Handy.config.current.dangerous_actions.immediate_buy_and_sell) then - if Handy.config.current.dangerous_actions.immediate_buy_and_sell.queue.enabled then - if not card.ability then - card.ability = {} - end - card.ability.handy_dangerous_actions_used = true - - table.insert(Handy.dangerous_actions.sell_queue, card) - Handy.UI.state_panel.update(nil, nil) - return false - else - local result = Handy.insta_actions.execute(card, true, false) - if result then - if not card.ability then - card.ability = {} - end - card.ability.handy_dangerous_actions_used = true - - G.CONTROLLER.locks.selling_card = nil - G.CONTROLLER.locks.use = nil - G.GAME.STOP_USE = 0 - - G.E_MANAGER:add_event(Event({ - func = function() - if card.ability then - card.ability.handy_dangerous_actions_used = nil - end - return true - end, - })) - end - return result - end - end - return false - end, - - use = function(card) - return Handy.dangerous_actions.can_execute(card) and Handy.dangerous_actions.execute(card) or false - end, - - toggle_queue = function(key, released) - if Handy.controller.is_module_key(Handy.config.current.dangerous_actions.immediate_buy_and_sell, key) then - if released then - Handy.dangerous_actions.sell_next_card() - else - Handy.dangerous_actions.sell_queue = {} - end - end - end, - - update_state_panel = function(state, key, released) - if G.STAGE ~= G.STAGES.RUN then - return false - end - - if not Handy.config.current.dangerous_actions.enabled then - return false - end - if Handy.config.current.notifications_level < 2 then - return false - end - if Handy.controller.is_module_key_down(Handy.config.current.dangerous_actions.immediate_buy_and_sell) then - state.dangerous = true - state.items.dangerous_hint = { - text = "[Unsafe] Bugs can appear!", - dangerous = true, - hold = true, - order = 99999999, - } - if state.items.quick_buy_and_sell then - state.items.quick_buy_and_sell.dangerous = true - elseif Handy.insta_actions.get_actions().buy_or_sell then - local text = "Quick sell" - if Handy.config.current.dangerous_actions.immediate_buy_and_sell.queue.enabled then - text = text .. " [" .. #Handy.dangerous_actions.sell_queue .. " in queue]" - end - state.items.quick_buy_and_sell = { - text = text, - hold = true, - order = 11, - dangerous = true, - } - end - return true - end - return false - end, -} - -Handy.speed_multiplier = { - value = 1, - - get_actions = function(key) - return { - multiply = key == Handy.controller.wheel_to_key_table[1], - divide = key == Handy.controller.wheel_to_key_table[2], - } - end, - can_execute = function(key) - return Handy.config.current.speed_multiplier.enabled - and not G.OVERLAY_MENU - and Handy.controller.is_module_key_down(Handy.config.current.speed_multiplier) - end, - - execute = function(key) - local actions = Handy.speed_multiplier.get_actions(key) - if actions.multiply then - Handy.speed_multiplier.multiply() - end - if actions.divide then - Handy.speed_multiplier.divide() - end - return false - end, - - multiply = function() - Handy.speed_multiplier.value = math.min(512, Handy.speed_multiplier.value * 2) - end, - divide = function() - Handy.speed_multiplier.value = math.max(0.001953125, Handy.speed_multiplier.value / 2) - end, - - use = function(key) - return Handy.speed_multiplier.can_execute(key) and Handy.speed_multiplier.execute(key) or false - end, - - update_state_panel = function(state, key, released) - if not key or not Handy.speed_multiplier.can_execute(key) then - return false - end - if Handy.config.current.notifications_level < 3 then - return false - end - - local actions = Handy.speed_multiplier.get_actions(key) - - if actions.multiply or actions.divide then - state.items.change_speed_multiplier = { - text = "Game speed multiplier: " - .. ( - Handy.speed_multiplier.value >= 1 and Handy.speed_multiplier.value - or ("1/" .. (1 / Handy.speed_multiplier.value)) - ), - hold = false, - order = 5, - } - return true - end - return false - end, -} - -Handy.shop_reroll = { - can_execute = function(key) - return G.STATE == G.STATES.SHOP - and Handy.fake_events.check({ func = G.FUNCS.can_reroll, button = "reroll_shop" }) - and Handy.controller.is_module_key(Handy.config.current.shop_reroll, key) - end, - execute = function(key) - G.FUNCS.reroll_shop() - return false - end, - - use = function(key) - return Handy.shop_reroll.can_execute(key) and Handy.shop_reroll.execute(key) or false - end, -} - -Handy.play_and_discard = { - get_actions = function(key) - return { - discard = Handy.controller.is_module_key(Handy.config.current.play_and_discard.discard, key), - play = Handy.controller.is_module_key(Handy.config.current.play_and_discard.play, key), - } - end, - - can_execute = function(play, discard) - return not not ( - Handy.config.current.play_and_discard.enabled - and G.STATE == G.STATES.SELECTING_HAND - and ( - (discard and Handy.fake_events.check({ - func = G.FUNCS.can_discard, - })) or (play and Handy.fake_events.check({ - func = G.FUNCS.can_play, - })) - ) - ) - end, - execute = function(play, discard) - if discard then - Handy.fake_events.execute({ - func = G.FUNCS.discard_cards_from_highlighted, - }) - elseif play then - Handy.fake_events.execute({ - func = G.FUNCS.play_cards_from_highlighted, - }) - end - return false - end, - - use = function(key) - local actions = Handy.play_and_discard.get_actions(key) - return Handy.play_and_discard.can_execute(actions.play, actions.discard) - and Handy.play_and_discard.execute(actions.play, actions.discard) - or false - end, -} - -Handy.nopeus_interaction = { - is_present = function() - return type(Nopeus) == "table" - end, - - get_actions = function(key) - return { - increase = key == Handy.controller.wheel_to_key_table[1], - decrease = key == Handy.controller.wheel_to_key_table[2], - } - end, - - can_dangerous = function() - return not not ( - Handy.config.current.dangerous_actions.enabled - and Handy.config.current.dangerous_actions.nopeus_unsafe.enabled - ) - end, - can_execute = function(key) - return not not ( - Handy.config.current.nopeus_interaction.enabled - and Handy.nopeus_interaction.is_present() - and not G.OVERLAY_MENU - and Handy.controller.is_module_key_down(Handy.config.current.nopeus_interaction) - ) - end, - execute = function(key) - local actions = Handy.nopeus_interaction.get_actions(key) - if actions.increase then - Handy.nopeus_interaction.increase() - end - if actions.decrease then - Handy.nopeus_interaction.decrease() - end - end, - - change = function(dx) - if not Handy.nopeus_interaction.is_present() then - G.SETTINGS.FASTFORWARD = 0 - elseif Nopeus.Optimised then - G.SETTINGS.FASTFORWARD = math.min( - Handy.nopeus_interaction.can_dangerous() and 4 or 3, - math.max(0, (G.SETTINGS.FASTFORWARD or 0) + dx) - ) - else - G.SETTINGS.FASTFORWARD = math.min( - Handy.nopeus_interaction.can_dangerous() and 3 or 2, - math.max(0, (G.SETTINGS.FASTFORWARD or 0) + dx) - ) - end - end, - increase = function() - Handy.nopeus_interaction.change(1) - end, - decrease = function() - Handy.nopeus_interaction.change(-1) - end, - - use = function(key) - return Handy.nopeus_interaction.can_execute(key) and Handy.nopeus_interaction.execute(key) or false - end, - - update_state_panel = function(state, key, released) - if not Handy.nopeus_interaction.is_present() then - return false - end - if not key or not Handy.nopeus_interaction.can_execute(key) then - return false - end - - local actions = Handy.nopeus_interaction.get_actions(key) - - if actions.increase or actions.decrease then - local states = { - Nopeus.Off, - Nopeus.Planets, - Nopeus.On, - Nopeus.Unsafe, - } - if Nopeus.Optimised then - states = { - Nopeus.Off, - Nopeus.Planets, - Nopeus.On, - Nopeus.Optimised, - Nopeus.Unsafe, - } - end - - local is_dangerous = G.SETTINGS.FASTFORWARD == (#states - 1) - - if is_dangerous then - state.dangerous = true - if Handy.config.current.notifications_level < 2 then - return false - end - else - if Handy.config.current.notifications_level < 3 then - return false - end - end - - state.items.change_nopeus_fastforward = { - text = "Nopeus fast-forward: " .. states[(G.SETTINGS.FASTFORWARD or 0) + 1], - hold = false, - order = 4, - dangerous = is_dangerous, - } - return true - end - return false - end, -} - -Handy.not_just_yet_interaction = { - is_present = function() - return G and G.FUNCS and G.FUNCS.njy_endround ~= nil - end, - - can_execute = function(check) - return not not ( - Handy.not_just_yet_interaction.is_present() - and GLOBAL_njy_vanilla_override - and G.STATE_COMPLETE - and G.buttons - and G.buttons.states - and G.buttons.states.visible - and G.GAME - and G.GAME.chips - and G.GAME.blind - and G.GAME.blind.chips - and to_big(G.GAME.chips) >= to_big(G.GAME.blind.chips) - ) - end, - execute = function() - stop_use() - G.STATE = G.STATES.NEW_ROUND - end_round() - end, - - use = function(key, released) - if Handy.controller.is_module_key(Handy.config.current.not_just_yet_interaction, key) then - GLOBAL_njy_vanilla_override = not released - end - return false - end, - - update = function() - if not Handy.config.current.not_just_yet_interaction.enabled then - GLOBAL_njy_vanilla_override = nil - end - return Handy.not_just_yet_interaction.can_execute() and Handy.not_just_yet_interaction.execute() or false - end, -} - --- - --- - -Handy.UI = { - counter = 1, - C = { - TEXT = HEX("FFFFFF"), - BLACK = HEX("000000"), - RED = HEX("FF0000"), - - DYN_BASE_APLHA = { - CONTAINER = 0.6, - - TEXT = 1, - TEXT_DANGEROUS = 1, - }, - - DYN = { - CONTAINER = HEX("000000"), - - TEXT = HEX("FFFFFF"), - TEXT_DANGEROUS = HEX("FFEEEE"), - }, - }, - state_panel = { - element = nil, - - title = nil, - items = nil, - - previous_state = { - dangerous = false, - title = {}, - items = {}, - sub_items = {}, - hold = false, - }, - current_state = { - dangerous = false, - title = {}, - items = {}, - sub_items = {}, - hold = false, - }, - - get_definition = function() - local state_panel = Handy.UI.state_panel - - local items_raw = {} - for _, item in pairs(state_panel.current_state.items) do - table.insert(items_raw, item) - end - - table.sort(items_raw, function(a, b) - return a.order < b.order - end) - - local items = {} - for _, item in ipairs(items_raw) do - table.insert(items, { - n = G.UIT.R, - config = { - align = "cm", - padding = 0.035, - }, - nodes = { - { - n = G.UIT.T, - config = { - text = item.text, - scale = 0.225, - colour = item.dangerous and Handy.UI.C.DYN.TEXT_DANGEROUS or Handy.UI.C.DYN.TEXT, - shadow = true, - }, - }, - }, - }) - end - - return { - n = G.UIT.ROOT, - config = { align = "cm", padding = 0.1, r = 0.1, colour = G.C.CLEAR, id = "handy_state_panel" }, - nodes = { - { - n = G.UIT.C, - config = { - align = "cm", - padding = 0.125, - r = 0.1, - colour = Handy.UI.C.DYN.CONTAINER, - }, - nodes = { - { - n = G.UIT.R, - config = { - align = "cm", - }, - nodes = { - { - n = G.UIT.T, - config = { - text = state_panel.current_state.title.text, - scale = 0.3, - colour = Handy.UI.C.DYN.TEXT, - shadow = true, - id = "handy_state_title", - }, - }, - }, - }, - { - n = G.UIT.R, - config = { - align = "cm", - }, - nodes = { - { - n = G.UIT.C, - config = { - align = "cm", - id = "handy_state_items", - }, - nodes = items, - }, - }, - }, - }, - }, - }, - } - end, - emplace = function() - if Handy.UI.state_panel.element then - Handy.UI.state_panel.element:remove() - end - local element = UIBox({ - definition = Handy.UI.state_panel.get_definition(), - config = { - instance_type = "ALERT", - align = "cm", - major = G.ROOM_ATTACH, - can_collide = false, - offset = { - x = 0, - y = 3.5, - }, - }, - }) - Handy.UI.state_panel.element = element - Handy.UI.state_panel.title = element:get_UIE_by_ID("handy_state_title") - Handy.UI.state_panel.items = element:get_UIE_by_ID("handy_state_items") - end, - - update = function(key, released) - local state_panel = Handy.UI.state_panel - - local state = { - dangerous = false, - title = {}, - items = {}, - sub_items = {}, - } - - local is_changed = false - - for _, part in ipairs({ - Handy.speed_multiplier, - Handy.insta_booster_skip, - Handy.insta_cash_out, - Handy.insta_actions, - Handy.insta_highlight, - Handy.move_highlight, - Handy.nopeus_interaction, - Handy.dangerous_actions, - }) do - local temp_result = part.update_state_panel(state, key, released) - is_changed = is_changed or temp_result or false - end - - if is_changed then - if state.dangerous then - state.title.text = "Dangerous actions" - else - state.title.text = "Quick actions" - end - - for _, item in pairs(state.items) do - if item.hold then - state.hold = true - end - end - - local color = Handy.UI.C.DYN.CONTAINER - local target_color = state.dangerous and Handy.UI.C.RED or Handy.UI.C.BLACK - color[1] = target_color[1] - color[2] = target_color[2] - color[3] = target_color[3] - - Handy.UI.counter = 0 - state_panel.previous_state = state_panel.current_state - state_panel.current_state = state - - state_panel.emplace() - else - state_panel.current_state.hold = false - end - end, - }, - - update = function(dt) - if Handy.UI.state_panel.current_state.hold then - Handy.UI.counter = 0 - elseif Handy.UI.counter < 1 then - Handy.UI.counter = Handy.UI.counter + dt - end - local multiplier = math.min(1, math.max(0, (1 - Handy.UI.counter) * 2)) - for key, color in pairs(Handy.UI.C.DYN) do - color[4] = (Handy.UI.C.DYN_BASE_APLHA[key] or 1) * multiplier - end - end, -} - -function Handy.UI.init() - Handy.UI.counter = 1 - Handy.UI.state_panel.emplace() - Handy.UI.update(0) -end - --- - -local love_update_ref = love.update -function love.update(dt, ...) - love_update_ref(dt, ...) - Handy.controller.process_update(dt) -end - -local wheel_moved_ref = love.wheelmoved or function() end -function love.wheelmoved(x, y) - wheel_moved_ref(x, y) - Handy.controller.process_wheel(y > 0 and 1 or 2) -end - --- - -function Handy.emplace_steamodded() - Handy.current_mod = SMODS.current_mod - Handy.config.current = Handy.utils.table_merge({}, Handy.config.default, SMODS.current_mod.config) - - Handy.current_mod.extra_tabs = function() - return { - { - label = "Overall", - tab_definition_function = function() - return Handy.UI.get_config_tab("Overall") - end, - }, - { - label = "Interactions", - tab_definition_function = function() - return Handy.UI.get_config_tab("Interactions") - end, - }, - { - label = "Dangerous", - tab_definition_function = function() - return Handy.UI.get_config_tab("Dangerous") - end, - }, - { - label = "Keybinds", - tab_definition_function = function() - return Handy.UI.get_config_tab("Keybinds") - end, - }, - { - label = "More keybinds", - tab_definition_function = function() - return Handy.UI.get_config_tab("Keybinds 2") - end, - }, - } - end - - G.E_MANAGER:add_event(Event({ - func = function() - G.njy_keybind = nil - return true - end, - })) -end - -function G.FUNCS.handy_toggle_module_enabled(arg, module) - if not module then - return - end - module.enabled = arg - if module == Handy.config.current.speed_multiplier then - Handy.speed_multiplier.value = 1 - elseif - module == Handy.config.current.dangerous_actions - or module == Handy.config.current.nopeus_interaction - or module == Handy.config.current.dangerous_actions.nopeus_unsafe - then - Handy.nopeus_interaction.change(0) - end - Handy.config.save() -end - -function G.FUNCS.handy_change_notifications_level(arg) - Handy.config.current.notifications_level = arg.to_key - Handy.config.save() -end - -function G.FUNCS.handy_init_keybind_change(e) - Handy.controller.init_bind(e) -end - -Handy.UI.PARTS = { - create_module_checkbox = function(module, label, text_prefix, text_lines, skip_keybinds) - local desc_lines = { - { n = G.UIT.R, config = { minw = 5.25 } }, - } - - if skip_keybinds then - table.insert(desc_lines, { - n = G.UIT.R, - config = { padding = 0.025 }, - nodes = { - { - n = G.UIT.T, - config = { - text = text_prefix .. " " .. text_lines[1], - scale = 0.3, - colour = G.C.TEXT_LIGHT, - }, - }, - }, - }) - else - local key_desc = module.key_2 - and { - { - n = G.UIT.T, - config = { - text = text_prefix .. " [", - scale = 0.3, - colour = G.C.TEXT_LIGHT, - }, - }, - { - n = G.UIT.T, - config = { - ref_table = module, - ref_value = "key_1", - scale = 0.3, - colour = G.C.TEXT_LIGHT, - }, - }, - { - n = G.UIT.T, - config = { - text = "] or [", - scale = 0.3, - colour = G.C.TEXT_LIGHT, - }, - }, - { - n = G.UIT.T, - config = { - ref_table = module, - ref_value = "key_2", - scale = 0.3, - colour = G.C.TEXT_LIGHT, - }, - }, - { - n = G.UIT.T, - config = { - text = "] " .. text_lines[1], - scale = 0.3, - colour = G.C.TEXT_LIGHT, - }, - }, - } - or { - { - n = G.UIT.T, - config = { - text = text_prefix .. " [", - scale = 0.3, - colour = G.C.TEXT_LIGHT, - }, - }, - { - n = G.UIT.T, - config = { - ref_table = module, - ref_value = "key_1", - scale = 0.3, - colour = G.C.TEXT_LIGHT, - }, - }, - { - n = G.UIT.T, - config = { - text = "] " .. text_lines[1], - scale = 0.3, - colour = G.C.TEXT_LIGHT, - }, - }, - } - table.insert(desc_lines, { - n = G.UIT.R, - config = { padding = 0.025 }, - nodes = key_desc, - }) - end - - for i = 2, #text_lines do - table.insert(desc_lines, { - n = G.UIT.R, - config = { padding = 0.025 }, - nodes = { - { - n = G.UIT.T, - config = { - text = text_lines[i], - scale = 0.3, - colour = G.C.TEXT_LIGHT, - }, - }, - }, - }) - end - - local label_lines = {} - if type(label) == "string" then - label = { label } - end - for i = 1, #label do - table.insert(label_lines, { - n = G.UIT.R, - config = { minw = 2.75 }, - nodes = { - { - n = G.UIT.T, - config = { - text = label[i], - scale = 0.4, - colour = G.C.WHITE, - }, - }, - }, - }) - end - - return { - n = G.UIT.R, - config = { align = "cm" }, - nodes = { - { - n = G.UIT.C, - config = { align = "cm" }, - nodes = label_lines, - }, - { - n = G.UIT.C, - config = { align = "cm" }, - nodes = { - create_toggle({ - callback = function(b) - return G.FUNCS.handy_toggle_module_enabled(b, module) - end, - label_scale = 0.4, - label = "", - ref_table = module, - ref_value = "enabled", - w = 0, - }), - }, - }, - { - n = G.UIT.C, - config = { minw = 0.1 }, - }, - { - n = G.UIT.C, - config = { align = "cm" }, - nodes = desc_lines, - }, - }, - } - end, - - create_module_section = function(label) - return { - n = G.UIT.R, - config = { align = "cm", padding = 0.1 }, - nodes = { - { - n = G.UIT.T, - config = { text = label, colour = G.C.WHITE, scale = 0.4, align = "cm" }, - }, - }, - } - end, - create_module_keybind = function(module, label, plus, dangerous) - return { - n = G.UIT.R, - config = { align = "cm", padding = 0.05 }, - nodes = { - { - n = G.UIT.C, - config = { align = "c", minw = 4 }, - nodes = { - { - n = G.UIT.T, - config = { text = label, colour = G.C.WHITE, scale = 0.35 }, - }, - }, - }, - { - n = G.UIT.C, - config = { align = "cm", minw = 0.75 }, - }, - UIBox_button({ - label = { module.key_1 or "None" }, - col = true, - colour = dangerous and G.C.MULT or G.C.CHIPS, - scale = 0.35, - minw = 2.75, - minh = 0.45, - ref_table = { - module = module, - key = "key_1", - }, - button = "handy_init_keybind_change", - }), - { - n = G.UIT.C, - config = { align = "cm", minw = 0.6 }, - nodes = { - { - n = G.UIT.T, - config = { text = plus and "+" or "or", colour = G.C.WHITE, scale = 0.3 }, - }, - }, - }, - UIBox_button({ - label = { module.key_2 or "None" }, - col = true, - colour = dangerous and G.C.MULT or G.C.CHIPS, - scale = 0.35, - minw = 2.75, - minh = 0.45, - ref_table = { - module = module, - key = "key_2", - }, - button = "handy_init_keybind_change", - }), - }, - } - end, -} - -Handy.UI.get_config_tab_overall = function() - return { - { - n = G.UIT.R, - config = { padding = 0.05, align = "cm" }, - nodes = { - create_option_cycle({ - minw = 3, - label = "Notifications level", - scale = 0.8, - options = { - "None", - "Dangerous", - "Game state", - "All", - }, - opt_callback = "handy_change_notifications_level", - current_option = Handy.config.current.notifications_level, - }), - }, - }, - { n = G.UIT.R, config = { padding = 0.05 }, nodes = {} }, - { - n = G.UIT.R, - nodes = { - { - n = G.UIT.C, - nodes = { - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.insta_highlight, - "Quick Highlight", - "Hold [Left Mouse]", - { - "and", - "hover cards in hand to highlight", - }, - true - ), - { n = G.UIT.R, config = { minh = 0.25 } }, - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.insta_buy_or_sell, - "Quick Buy/Sell", - "Hold", - { - "to", - "buy or sell card on Left-Click", - "instead of selection", - } - ), - { n = G.UIT.R, config = { minh = 0.25 } }, - Handy.UI.PARTS.create_module_checkbox(Handy.config.current.insta_use, "Quick use", "Hold", { - "to", - "use (if possible) card on Left-Click", - "instead of selection", - "(overrides Quick Buy/Sell)", - }), - { n = G.UIT.R, config = { minh = 0.25 } }, - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.move_highlight, - "Move highlight", - "Press", - { - "[" - .. tostring(Handy.config.current.move_highlight.dx.one_left.key_1) - .. "] or [" - .. tostring(Handy.config.current.move_highlight.dx.one_right.key_1) - .. "]", - "to move highlight in card area.", - "Hold [" - .. tostring(Handy.config.current.move_highlight.swap.key_1) - .. "] to move card instead.", - "Hold [" - .. tostring(Handy.config.current.move_highlight.to_end.key_1) - .. "] to move to first/last card", - }, - true - ), - }, - }, - { - n = G.UIT.C, - config = { minw = 4 }, - nodes = { - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.insta_cash_out, - "Quick Cash Out", - "Press", - { - "to", - "speedup animation and", - "skip Cash Out stage", - } - ), - { n = G.UIT.R, config = { minh = 0.25 } }, - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.insta_booster_skip, - { "Quick skip", "Booster Packs" }, - "Hold", - { - "to", - "skip booster pack", - } - ), - { n = G.UIT.R, config = { minh = 0.25 } }, - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.speed_multiplier, - "Speed Multiplier", - "Hold", - { - "and", - "[Wheel Up] to multiply or", - "[Wheel Down] to divide game speed", - } - ), - { n = G.UIT.R, config = { minh = 0.25 } }, - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.shop_reroll, - "Shop Reroll", - "Press", - { - "to", - "reroll a shop", - } - ), - { n = G.UIT.R, config = { minh = 0.25 } }, - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.play_and_discard, - "Play/Discard", - "Press", - { - "[" .. tostring(Handy.config.current.play_and_discard.play.key_1) .. "] to play a hand", - "or [" - .. tostring(Handy.config.current.play_and_discard.discard.key_1) - .. "] to discard", - }, - true - ), - }, - }, - }, - }, - } -end - -Handy.UI.get_config_tab_interactions = function() - return { - { - n = G.UIT.R, - nodes = { - { - n = G.UIT.C, - nodes = { - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.nopeus_interaction, - { "Nopeus:", "fast-forward" }, - "Hold", - { - "and", - "[Wheel Up] to increase or", - "[Wheel Down] to decrease", - "fast-forward setting", - } - ), - { - n = G.UIT.R, - config = { minh = 0.25 }, - }, - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.not_just_yet_interaction, - { "NotJustYet:", "End round" }, - "Press", - { - "to", - "end round", - } - ), - }, - }, - }, - }, - } -end - -Handy.UI.get_config_tab_dangerous = function() - return { - -- { - -- n = G.UIT.R, - -- config = { padding = 0.05, align = "cm" }, - -- nodes = { - - -- }, - -- }, - -- { n = G.UIT.R, config = { padding = 0.05 }, nodes = {} }, - { - n = G.UIT.R, - nodes = { - { - n = G.UIT.C, - nodes = { - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.dangerous_actions, - { "Dangerous", "actions" }, - "Enable", - { - "unsafe controls. They're", - "designed to be speed-first,", - "which can cause bugs or crashes", - }, - true - ), - { n = G.UIT.R, config = { minh = 0.5 } }, - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.dangerous_actions.immediate_buy_and_sell, - "Instant Sell", - "Hold", - { - "to", - "sell card on hover", - "very fast", - } - ), - { n = G.UIT.R, config = { minh = 0.1 } }, - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.dangerous_actions.immediate_buy_and_sell.queue, - "Sell Queue", - "Start", - { - "selling cards only when", - "keybind was released", - }, - true - ), - { n = G.UIT.R, config = { minh = 0.25 } }, - Handy.UI.PARTS.create_module_checkbox( - Handy.config.current.dangerous_actions.nopeus_unsafe, - { "Nopeus: Unsafe", "fast-forward" }, - "Allow", - { - "increase fast-forward", - 'setting to "Unsafe"', - }, - true - ), - }, - }, - }, - }, - } -end - -Handy.UI.get_config_tab_keybinds = function() - return { - Handy.UI.PARTS.create_module_section("Quick Actions"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.insta_buy_or_sell, "Quick Buy/Sell"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.insta_use, "Quick Use"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.insta_cash_out, "Quick Cash Out"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.insta_booster_skip, "Quick skip Booster Packs"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.shop_reroll, "Shop reroll"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.play_and_discard.play, "Play hand"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.play_and_discard.discard, "Discard"), - Handy.UI.PARTS.create_module_keybind( - Handy.config.current.dangerous_actions.immediate_buy_and_sell, - "Instant Buy/Sell", - false, - true - ), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.not_just_yet_interaction, "NotJustYet: End round"), - } -end - -Handy.UI.get_config_tab_keybinds_2 = function() - return { - Handy.UI.PARTS.create_module_section("Game state"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.speed_multiplier, "Speed Multiplier"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.nopeus_interaction, "Nopeus: fast-forward"), - Handy.UI.PARTS.create_module_section("Move highlight"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.move_highlight.dx.one_left, "Move one left"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.move_highlight.dx.one_right, "Move one right"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.move_highlight.swap, "Move card"), - Handy.UI.PARTS.create_module_keybind(Handy.config.current.move_highlight.to_end, "Move to end"), - } -end - -Handy.UI.get_config_tab = function(_tab) - local result = { - n = G.UIT.ROOT, - config = { align = "cm", padding = 0.05, colour = G.C.CLEAR, minh = 5, minw = 5 }, - nodes = {}, - } - if _tab == "Overall" then - result.nodes = Handy.UI.get_config_tab_overall() - elseif _tab == "Interactions" then - result.nodes = Handy.UI.get_config_tab_interactions() - elseif _tab == "Dangerous" then - result.nodes = Handy.UI.get_config_tab_dangerous() - elseif _tab == "Keybinds" then - result.nodes = Handy.UI.get_config_tab_keybinds() - elseif _tab == "Keybinds 2" then - result.nodes = Handy.UI.get_config_tab_keybinds_2() - end - return result -end - -local lovely = require("lovely") -local nativefs = require("nativefs") - -if not nativefs.getInfo(lovely.mod_dir .. "/Talisman") then - error( - 'Could not find proper Talisman folder.\nPlease make sure the folder for Talisman is named exactly "Talisman" and not "Talisman-main" or anything else.') -end - -Talisman = {config_file = {disable_anims = true, break_infinity = "omeganum", score_opt_id = 2}} -if nativefs.read(lovely.mod_dir.."/Talisman/config.lua") then - Talisman.config_file = STR_UNPACK(nativefs.read(lovely.mod_dir.."/Talisman/config.lua")) - - if Talisman.config_file.break_infinity and type(Talisman.config_file.break_infinity) ~= 'string' then - Talisman.config_file.break_infinity = "omeganum" - end -end -if not SMODS or not JSON then - local createOptionsRef = create_UIBox_options - function create_UIBox_options() - contents = createOptionsRef() - local m = UIBox_button({ - minw = 5, - button = "talismanMenu", - label = { - "Talisman" - }, - colour = G.C.GOLD - }) - table.insert(contents.nodes[1].nodes[1].nodes[1].nodes, #contents.nodes[1].nodes[1].nodes[1].nodes + 1, m) - return contents - end -end - -Talisman.config_tab = function() - tal_nodes = {{n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = "Select features to enable:", colours = {G.C.WHITE}, shadow = true, scale = 0.4})}}, - }},create_toggle({label = "Disable Scoring Animations", ref_table = Talisman.config_file, ref_value = "disable_anims", - callback = function(_set_toggle) - nativefs.write(lovely.mod_dir .. "/Talisman/config.lua", STR_PACK(Talisman.config_file)) - end}), - create_option_cycle({ - label = "Score Limit (requires game restart)", - scale = 0.8, - w = 6, - options = {"Vanilla (e308)", "BigNum (ee308)", "OmegaNum (e10##1000)"}, - opt_callback = 'talisman_upd_score_opt', - current_option = Talisman.config_file.score_opt_id, - })} - return { - n = G.UIT.ROOT, - config = { - emboss = 0.05, - minh = 6, - r = 0.1, - minw = 10, - align = "cm", - padding = 0.2, - colour = G.C.BLACK - }, - nodes = tal_nodes - } - end -G.FUNCS.talismanMenu = function(e) - local tabs = create_tabs({ - snap_to_nav = true, - tabs = { - { - label = "Talisman", - chosen = true, - tab_definition_function = Talisman.config_tab - }, - }}) - G.FUNCS.overlay_menu{ - definition = create_UIBox_generic_options({ - back_func = "options", - contents = {tabs} - }), - config = {offset = {x=0,y=10}} - } -end -G.FUNCS.talisman_upd_score_opt = function(e) - Talisman.config_file.score_opt_id = e.to_key - local score_opts = {"", "bignumber", "omeganum"} - Talisman.config_file.break_infinity = score_opts[e.to_key] - nativefs.write(lovely.mod_dir .. "/Talisman/config.lua", STR_PACK(Talisman.config_file)) -end -if Talisman.config_file.break_infinity then - Big, err = nativefs.load(lovely.mod_dir.."/Talisman/big-num/"..Talisman.config_file.break_infinity..".lua") - if not err then Big = Big() else Big = nil end - Notations = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations.lua")() - -- We call this after init_game_object to leave room for mods that add more poker hands - Talisman.igo = function(obj) - for _, v in pairs(obj.hands) do - v.chips = to_big(v.chips) - v.mult = to_big(v.mult) - v.s_chips = to_big(v.s_chips) - v.s_mult = to_big(v.s_mult) - v.l_chips = to_big(v.l_chips) - v.l_mult = to_big(v.l_mult) - end - return obj - end - - local nf = number_format - function number_format(num, e_switch_point) - if type(num) == 'table' then - num = to_big(num) - G.E_SWITCH_POINT = G.E_SWITCH_POINT or 100000000000 - if num < to_big(e_switch_point or G.E_SWITCH_POINT) then - return nf(num:to_number(), e_switch_point) - else - return Notations.Balatro:format(num, 3) - end - else return nf(num, e_switch_point) end - end - - local mf = math.floor - function math.floor(x) - if type(x) == 'table' then return x:floor() end - return mf(x) - end - - local l10 = math.log10 - function math.log10(x) - if type(x) == 'table' then return l10(math.min(x:to_number(),1e300)) end--x:log10() end - return l10(x) - end - - local lg = math.log - function math.log(x, y) - if not y then y = 2.718281828459045 end - if type(x) == 'table' then return lg(math.min(x:to_number(),1e300),y) end --x:log(y) end - return lg(x,y) - end - - if SMODS then - function SMODS.get_blind_amount(ante) - local k = to_big(0.75) - local scale = G.GAME.modifiers.scaling - local amounts = { - to_big(300), - to_big(700 + 100*scale), - to_big(1400 + 600*scale), - to_big(2100 + 2900*scale), - to_big(15000 + 5000*scale*math.log(scale)), - to_big(12000 + 8000*(scale+1)*(0.4*scale)), - to_big(10000 + 25000*(scale+1)*((scale/4)^2)), - to_big(50000 * (scale+1)^2 * (scale/7)^2) - } - - if ante < 1 then return to_big(100) end - if ante <= 8 then - local amount = amounts[ante] - if (amount:lt(R.E_MAX_SAFE_INTEGER)) then - local exponent = to_big(10)^(math.floor(amount:log10() - to_big(1))):to_number() - amount = math.floor(amount / exponent):to_number() * exponent - end - amount:normalize() - return amount - end - local a, b, c, d = amounts[8], amounts[8]/amounts[7], ante-8, 1 + 0.2*(ante-8) - local amount = math.floor(a*(b + (b*k*c)^d)^c) - if (amount:lt(R.E_MAX_SAFE_INTEGER)) then - local exponent = to_big(10)^(math.floor(amount:log10() - to_big(1))):to_number() - amount = math.floor(amount / exponent):to_number() * exponent - end - amount:normalize() - return amount - end - end - -- There's too much to override here so we just fully replace this function - -- Note that any ante scaling tweaks will need to manually changed... - local gba = get_blind_amount - function get_blind_amount(ante) - if G.GAME.modifiers.scaling and G.GAME.modifiers.scaling > 3 then return SMODS.get_blind_amount(ante) end - if type(to_big(1)) == 'number' then return gba(ante) end - local k = to_big(0.75) - if not G.GAME.modifiers.scaling or G.GAME.modifiers.scaling == 1 then - local amounts = { - to_big(300), to_big(800), to_big(2000), to_big(5000), to_big(11000), to_big(20000), to_big(35000), to_big(50000) - } - if ante < 1 then return to_big(100) end - if ante <= 8 then return amounts[ante] end - local a, b, c, d = amounts[8],1.6,ante-8, 1 + 0.2*(ante-8) - local amount = a*(b+(k*c)^d)^c - if (amount:lt(R.E_MAX_SAFE_INTEGER)) then - local exponent = to_big(10)^(math.floor(amount:log10() - to_big(1))):to_number() - amount = math.floor(amount / exponent):to_number() * exponent - end - amount:normalize() - return amount - elseif G.GAME.modifiers.scaling == 2 then - local amounts = { - to_big(300), to_big(900), to_big(2600), to_big(8000), to_big(20000), to_big(36000), to_big(60000), to_big(100000) - --300, 900, 2400, 7000, 18000, 32000, 56000, 90000 - } - if ante < 1 then return to_big(100) end - if ante <= 8 then return amounts[ante] end - local a, b, c, d = amounts[8],1.6,ante-8, 1 + 0.2*(ante-8) - local amount = a*(b+(k*c)^d)^c - if (amount:lt(R.E_MAX_SAFE_INTEGER)) then - local exponent = to_big(10)^(math.floor(amount:log10() - to_big(1))):to_number() - amount = math.floor(amount / exponent):to_number() * exponent - end - amount:normalize() - return amount - elseif G.GAME.modifiers.scaling == 3 then - local amounts = { - to_big(300), to_big(1000), to_big(3200), to_big(9000), to_big(25000), to_big(60000), to_big(110000), to_big(200000) - --300, 1000, 3000, 8000, 22000, 50000, 90000, 180000 - } - if ante < 1 then return to_big(100) end - if ante <= 8 then return amounts[ante] end - local a, b, c, d = amounts[8],1.6,ante-8, 1 + 0.2*(ante-8) - local amount = a*(b+(k*c)^d)^c - if (amount:lt(R.E_MAX_SAFE_INTEGER)) then - local exponent = to_big(10)^(math.floor(amount:log10() - to_big(1))):to_number() - amount = math.floor(amount / exponent):to_number() * exponent - end - amount:normalize() - return amount - end - end - - function check_and_set_high_score(score, amt) - if G.GAME.round_scores[score] and to_big(math.floor(amt)) > to_big(G.GAME.round_scores[score].amt) then - G.GAME.round_scores[score].amt = to_big(math.floor(amt)) - end - if G.GAME.seeded then return end - --[[if G.PROFILES[G.SETTINGS.profile].high_scores[score] and math.floor(amt) > G.PROFILES[G.SETTINGS.profile].high_scores[score].amt then - if G.GAME.round_scores[score] then G.GAME.round_scores[score].high_score = true end - G.PROFILES[G.SETTINGS.profile].high_scores[score].amt = math.floor(amt) - G:save_settings() - end--]] --going to hold off on modifying this until proper save loading exists - end - - local sn = scale_number - function scale_number(number, scale, max, e_switch_point) - if not Big then return sn(number, scale, max, e_switch_point) end - scale = to_big(scale) - G.E_SWITCH_POINT = G.E_SWITCH_POINT or 100000000000 - if not number or not is_number(number) then return scale end - if not max then max = 10000 end - if to_big(number).e and to_big(number).e == 10^1000 then - scale = scale*math.floor(math.log(max*10, 10))/7 - end - if to_big(number) >= to_big(e_switch_point or G.E_SWITCH_POINT) then - if (to_big(to_big(number):log10()) <= to_big(999)) then - scale = scale*math.floor(math.log(max*10, 10))/math.floor(math.log(1000000*10, 10)) - else - scale = scale*math.floor(math.log(max*10, 10))/math.floor(math.max(7,string.len(number_format(number))-1)) - end - elseif to_big(number) >= to_big(max) then - scale = scale*math.floor(math.log(max*10, 10))/math.floor(math.log(number*10, 10)) - end - return math.min(3, scale:to_number()) - end - - local tsj = G.FUNCS.text_super_juice - function G.FUNCS.text_super_juice(e, _amount) - if _amount > 2 then _amount = 2 end - return tsj(e, _amount) - end - - local max = math.max - --don't return a Big unless we have to - it causes nativefs to break - function math.max(x, y) - if type(x) == 'table' or type(y) == 'table' then - x = to_big(x) - y = to_big(y) - if (x > y) then - return x - else - return y - end - else return max(x,y) end - end - - local min = math.min - function math.min(x, y) - if type(x) == 'table' or type(y) == 'table' then - x = to_big(x) - y = to_big(y) - if (x < y) then - return x - else - return y - end - else return min(x,y) end - end - - local sqrt = math.sqrt - function math.sqrt(x) - if type(x) == 'table' then - if getmetatable(x) == BigMeta then return x:sqrt() end - if getmetatable(x) == OmegaMeta then return x:pow(0.5) end - end - return sqrt(x) - end - - - - local old_abs = math.abs - function math.abs(x) - if type(x) == 'table' then - x = to_big(x) - if (x < to_big(0)) then - return -1 * x - else - return x - end - else return old_abs(x) end - end -end - -function is_number(x) - if type(x) == 'number' then return true end - if type(x) == 'table' and ((x.e and x.m) or (x.array and x.sign)) then return true end - return false -end - -function to_big(x, y) - if Big and Big.m then - return Big:new(x,y) - elseif Big and Big.array then - local result = Big:create(x) - result.sign = y or result.sign or x.sign or 1 - return result - elseif is_number(x) then - return x * 10^(y or 0) - - elseif type(x) == "nil" then - return 0 - else - if ((#x>=2) and ((x[2]>=2) or (x[2]==1) and (x[1]>308))) then - return 1e309 - end - if (x[2]==1) then - return math.pow(10,x[1]) - end - return x[1]*(y or 1); - end -end -function to_number(x) - if type(x) == 'table' and (getmetatable(x) == BigMeta or getmetatable(x) == OmegaMeta) then - return x:to_number() - else - return x - end -end - ---patch to remove animations -local cest = card_eval_status_text -function card_eval_status_text(a,b,c,d,e,f) - if not Talisman.config_file.disable_anims then cest(a,b,c,d,e,f) end -end -local jc = juice_card -function juice_card(x) - if not Talisman.config_file.disable_anims then jc(x) end -end -function tal_uht(config, vals) - local col = G.C.GREEN - if vals.chips and G.GAME.current_round.current_hand.chips ~= vals.chips then - local delta = (is_number(vals.chips) and is_number(G.GAME.current_round.current_hand.chips)) and (vals.chips - G.GAME.current_round.current_hand.chips) or 0 - if to_big(delta) < to_big(0) then delta = number_format(delta); col = G.C.RED - elseif to_big(delta) > to_big(0) then delta = '+'..number_format(delta) - else delta = number_format(delta) - end - if type(vals.chips) == 'string' then delta = vals.chips end - G.GAME.current_round.current_hand.chips = vals.chips - if G.hand_text_area.chips.config.object then - G.hand_text_area.chips:update(0) - end - end - if vals.mult and G.GAME.current_round.current_hand.mult ~= vals.mult then - local delta = (is_number(vals.mult) and is_number(G.GAME.current_round.current_hand.mult))and (vals.mult - G.GAME.current_round.current_hand.mult) or 0 - if to_big(delta) < to_big(0) then delta = number_format(delta); col = G.C.RED - elseif to_big(delta) > to_big(0) then delta = '+'..number_format(delta) - else delta = number_format(delta) - end - if type(vals.mult) == 'string' then delta = vals.mult end - G.GAME.current_round.current_hand.mult = vals.mult - if G.hand_text_area.mult.config.object then - G.hand_text_area.mult:update(0) - end - end - if vals.handname and G.GAME.current_round.current_hand.handname ~= vals.handname then - G.GAME.current_round.current_hand.handname = vals.handname - end - if vals.chip_total then G.GAME.current_round.current_hand.chip_total = vals.chip_total;G.hand_text_area.chip_total.config.object:pulse(0.5) end - if vals.level and G.GAME.current_round.current_hand.hand_level ~= ' '..localize('k_lvl')..tostring(vals.level) then - if vals.level == '' then - G.GAME.current_round.current_hand.hand_level = vals.level - else - G.GAME.current_round.current_hand.hand_level = ' '..localize('k_lvl')..tostring(vals.level) - if type(vals.level) == 'number' then - G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[math.min(vals.level, 7)] - else - G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[1] - end - end - end - return true -end -local uht = update_hand_text -function update_hand_text(config, vals) - if Talisman.config_file.disable_anims then - if G.latest_uht then - local chips = G.latest_uht.vals.chips - local mult = G.latest_uht.vals.mult - if not vals.chips then vals.chips = chips end - if not vals.mult then vals.mult = mult end - end - G.latest_uht = {config = config, vals = vals} - else uht(config, vals) - end -end -local upd = Game.update -function Game:update(dt) - upd(self, dt) - if G.latest_uht and G.latest_uht.config and G.latest_uht.vals then - tal_uht(G.latest_uht.config, G.latest_uht.vals) - G.latest_uht = nil - end - if Talisman.dollar_update then - G.HUD:get_UIE_by_ID('dollar_text_UI').config.object:update() - G.HUD:recalculate() - Talisman.dollar_update = false - end -end ---scoring coroutine -local oldplay = G.FUNCS.evaluate_play - -function G.FUNCS.evaluate_play() - G.SCORING_COROUTINE = coroutine.create(oldplay) - G.LAST_SCORING_YIELD = love.timer.getTime() - G.CARD_CALC_COUNTS = {} -- keys = cards, values = table containing numbers - local success, err = coroutine.resume(G.SCORING_COROUTINE) - if not success then - error(err) - end -end - - -local oldupd = love.update -function love.update(dt, ...) - oldupd(dt, ...) - if G.SCORING_COROUTINE then - if collectgarbage("count") > 1024*1024 then - collectgarbage("collect") - end - if coroutine.status(G.SCORING_COROUTINE) == "dead" then - G.SCORING_COROUTINE = nil - G.FUNCS.exit_overlay_menu() - local totalCalcs = 0 - for i, v in pairs(G.CARD_CALC_COUNTS) do - totalCalcs = totalCalcs + v[1] - end - G.GAME.LAST_CALCS = totalCalcs - else - G.SCORING_TEXT = nil - if not G.OVERLAY_MENU then - G.scoring_text = {"Calculating...", "", "", ""} - G.SCORING_TEXT = { - {n = G.UIT.C, nodes = { - {n = G.UIT.R, config = {padding = 0.1, align = "cm"}, nodes = { - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.scoring_text, ref_value = 1}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 1, silent = true})}}, - }},{n = G.UIT.R, nodes = { - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.scoring_text, ref_value = 2}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4, silent = true})}}, - }},{n = G.UIT.R, nodes = { - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.scoring_text, ref_value = 3}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4, silent = true})}}, - }},{n = G.UIT.R, nodes = { - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.scoring_text, ref_value = 4}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4, silent = true})}}, - }}}}} - G.FUNCS.overlay_menu({ - definition = - {n=G.UIT.ROOT, minw = G.ROOM.T.w*5, minh = G.ROOM.T.h*5, config={align = "cm", padding = 9999, offset = {x = 0, y = -3}, r = 0.1, colour = {G.C.GREY[1], G.C.GREY[2], G.C.GREY[3],0.7}}, nodes= G.SCORING_TEXT}, - config = {align="cm", offset = {x=0,y=0}, major = G.ROOM_ATTACH, bond = 'Weak'} - }) - else - - if G.OVERLAY_MENU and G.scoring_text then - local totalCalcs = 0 - for i, v in pairs(G.CARD_CALC_COUNTS) do - totalCalcs = totalCalcs + v[1] - end - local jokersYetToScore = #G.jokers.cards + #G.play.cards - #G.CARD_CALC_COUNTS - G.scoring_text[1] = "Calculating..." - G.scoring_text[2] = "Elapsed calculations: "..tostring(totalCalcs) - G.scoring_text[3] = "Cards yet to score: "..tostring(jokersYetToScore) - G.scoring_text[4] = "Calculations last played hand: " .. tostring(G.GAME.LAST_CALCS or "Unknown") - end - - end - --this coroutine allows us to stagger GC cycles through - --the main source of waste in terms of memory (especially w joker retriggers) is through local variables that become garbage - --this practically eliminates the memory overhead of scoring - --event queue overhead seems to not exist if Talismans Disable Scoring Animations is off. - --event manager has to wait for scoring to finish until it can keep processing events anyways. - - - G.LAST_SCORING_YIELD = love.timer.getTime() - - local success, msg = coroutine.resume(G.SCORING_COROUTINE) - if not success then - error(msg) - end - end - end -end - - - -TIME_BETWEEN_SCORING_FRAMES = 0.03 -- 30 fps during scoring --- we dont want overhead from updates making scoring much slower --- originally 10 fps, I think 30 fps is a good way to balance it while making it look smooth, too ---wrap everything in calculating contexts so we can do more things with it -Talisman.calculating_joker = false -Talisman.calculating_score = false -Talisman.calculating_card = false -Talisman.dollar_update = false -local ccj = Card.calculate_joker -function Card:calculate_joker(context) - --scoring coroutine - G.CURRENT_SCORING_CARD = self - G.CARD_CALC_COUNTS = G.CARD_CALC_COUNTS or {} - if G.CARD_CALC_COUNTS[self] then - G.CARD_CALC_COUNTS[self][1] = G.CARD_CALC_COUNTS[self][1] + 1 - else - G.CARD_CALC_COUNTS[self] = {1, 1} - end - - - if G.LAST_SCORING_YIELD and ((love.timer.getTime() - G.LAST_SCORING_YIELD) > TIME_BETWEEN_SCORING_FRAMES) and coroutine.running() then - coroutine.yield() - end - Talisman.calculating_joker = true - local ret = ccj(self, context) - - if ret and type(ret) == "table" and ret.repetitions then - G.CARD_CALC_COUNTS[ret.card] = G.CARD_CALC_COUNTS[ret.card] or {1,1} - G.CARD_CALC_COUNTS[ret.card][2] = G.CARD_CALC_COUNTS[ret.card][2] + ret.repetitions - end - Talisman.calculating_joker = false - return ret -end -local cuc = Card.use_consumable -function Card:use_consumable(x,y) - Talisman.calculating_score = true - local ret = cuc(self, x,y) - Talisman.calculating_score = false - return ret -end -local gfep = G.FUNCS.evaluate_play -G.FUNCS.evaluate_play = function(e) - Talisman.calculating_score = true - local ret = gfep(e) - Talisman.calculating_score = false - return ret -end ---[[local ec = eval_card -function eval_card() - Talisman.calculating_card = true - local ret = ec() - Talisman.calculating_card = false - return ret -end--]] -local sm = Card.start_materialize -function Card:start_materialize(a,b,c) - if Talisman.config_file.disable_anims and (Talisman.calculating_joker or Talisman.calculating_score or Talisman.calculating_card) then return end - return sm(self,a,b,c) -end -local sd = Card.start_dissolve -function Card:start_dissolve(a,b,c,d) - if Talisman.config_file.disable_anims and (Talisman.calculating_joker or Talisman.calculating_score or Talisman.calculating_card) then self:remove() return end - return sd(self,a,b,c,d) -end -local ss = Card.set_seal -function Card:set_seal(a,b,immediate) - return ss(self,a,b,Talisman.config_file.disable_anims and (Talisman.calculating_joker or Talisman.calculating_score or Talisman.calculating_card) or immediate) -end - -function Card:get_chip_x_bonus() - if self.debuff then return 0 end - if self.ability.set == 'Joker' then return 0 end - if (self.ability.x_chips or 0) <= 1 then return 0 end - return self.ability.x_chips -end - -function Card:get_chip_e_bonus() - if self.debuff then return 0 end - if self.ability.set == 'Joker' then return 0 end - if (self.ability.e_chips or 0) <= 1 then return 0 end - return self.ability.e_chips -end - -function Card:get_chip_ee_bonus() - if self.debuff then return 0 end - if self.ability.set == 'Joker' then return 0 end - if (self.ability.ee_chips or 0) <= 1 then return 0 end - return self.ability.ee_chips -end - -function Card:get_chip_eee_bonus() - if self.debuff then return 0 end - if self.ability.set == 'Joker' then return 0 end - if (self.ability.eee_chips or 0) <= 1 then return 0 end - return self.ability.eee_chips -end - -function Card:get_chip_hyper_bonus() - if self.debuff then return {0,0} end - if self.ability.set == 'Joker' then return {0,0} end - if type(self.ability.hyper_chips) ~= 'table' then return {0,0} end - if (self.ability.hyper_chips[1] <= 0 or self.ability.hyper_chips[2] <= 0) then return {0,0} end - return self.ability.hyper_chips -end - -function Card:get_chip_e_mult() - if self.debuff then return 0 end - if self.ability.set == 'Joker' then return 0 end - if (self.ability.e_mult or 0) <= 1 then return 0 end - return self.ability.e_mult -end - -function Card:get_chip_ee_mult() - if self.debuff then return 0 end - if self.ability.set == 'Joker' then return 0 end - if (self.ability.ee_mult or 0) <= 1 then return 0 end - return self.ability.ee_mult -end - -function Card:get_chip_eee_mult() - if self.debuff then return 0 end - if self.ability.set == 'Joker' then return 0 end - if (self.ability.eee_mult or 0) <= 1 then return 0 end - return self.ability.eee_mult -end - -function Card:get_chip_hyper_mult() - if self.debuff then return {0,0} end - if self.ability.set == 'Joker' then return {0,0} end - if type(self.ability.hyper_mult) ~= 'table' then return {0,0} end - if (self.ability.hyper_mult[1] <= 0 or self.ability.hyper_mult[2] <= 0) then return {0,0} end - return self.ability.hyper_mult -end - ---Easing fixes ---Changed this to always work; it's less pretty but fine for held in hand things -local edo = ease_dollars -function ease_dollars(mod, instant) - if Talisman.config_file.disable_anims then--and (Talisman.calculating_joker or Talisman.calculating_score or Talisman.calculating_card) then - mod = mod or 0 - if mod < 0 then inc_career_stat('c_dollars_earned', mod) end - G.GAME.dollars = G.GAME.dollars + mod - Talisman.dollar_update = true - else return edo(mod, instant) end -end - -local su = G.start_up -function safe_str_unpack(str) - local chunk, err = loadstring(str) - if chunk then - setfenv(chunk, {Big = Big, BigMeta = BigMeta, OmegaMeta = OmegaMeta, to_big = to_big, inf = 1.79769e308}) -- Use an empty environment to prevent access to potentially harmful functions - local success, result = pcall(chunk) - if success then - return result - else - print("Error unpacking string: " .. result) - return nil - end - else - print("Error loading string: " .. err) - return nil - end - end -function G:start_up() - STR_UNPACK = safe_str_unpack - su(self) - STR_UNPACK = safe_str_unpack -end - ---Skip round animation things -local gfer = G.FUNCS.evaluate_round -function G.FUNCS.evaluate_round() - if Talisman.config_file.disable_anims then - if to_big(G.GAME.chips) >= to_big(G.GAME.blind.chips) then - add_round_eval_row({dollars = G.GAME.blind.dollars, name='blind1', pitch = 0.95}) - else - add_round_eval_row({dollars = 0, name='blind1', pitch = 0.95, saved = true}) - end - local arer = add_round_eval_row - add_round_eval_row = function() return end - local dollars = gfer() - add_round_eval_row = arer - add_round_eval_row({name = 'bottom', dollars = Talisman.dollars}) - else - return gfer() - end -end - ---some debugging functions ---[[local callstep=0 -function printCallerInfo() - -- Get debug info for the caller of the function that called printCallerInfo - local info = debug.getinfo(3, "Sl") - callstep = callstep+1 - if info then - print("["..callstep.."] "..(info.short_src or "???")..":"..(info.currentline or "unknown")) - else - print("Caller information not available") - end -end -local emae = EventManager.add_event -function EventManager:add_event(x,y,z) - printCallerInfo() - return emae(self,x,y,z) -end--]] - -require 'cartomancer.init' - -Cartomancer.path = assert( - Cartomancer.find_self('cartomancer.lua'), - "Failed to find mod folder. Make sure that `Cartomancer` folder has `cartomancer.lua` file!" -) - -Cartomancer.load_mod_file('internal/config.lua', 'internal.config') -Cartomancer.load_mod_file('internal/atlas.lua', 'internal.atlas') -Cartomancer.load_mod_file('internal/ui.lua', 'internal.ui') -Cartomancer.load_mod_file('internal/keybinds.lua', 'internal.keybinds') - -Cartomancer.load_mod_file('core/view-deck.lua', 'core.view-deck') -Cartomancer.load_mod_file('core/flames.lua', 'core.flames') -Cartomancer.load_mod_file('core/optimizations.lua', 'core.optimizations') -Cartomancer.load_mod_file('core/jokers.lua', 'core.jokers') -Cartomancer.load_mod_file('core/hand.lua', 'core.hand') - -Cartomancer.load_config() - -Cartomancer.INTERNAL_jokers_menu = false - --- TODO dedicated keybinds file? keybinds need to load after config -Cartomancer.register_keybind { - name = 'hide_joker', - func = function (controller) - Cartomancer.hide_hovered_joker(controller) - end -} - -Cartomancer.register_keybind { - name = 'toggle_tags', - func = function (controller) - Cartomancer.SETTINGS.hide_tags = not Cartomancer.SETTINGS.hide_tags - Cartomancer.update_tags_visibility() - end -} - -Cartomancer.register_keybind { - name = 'toggle_consumables', - func = function (controller) - Cartomancer.SETTINGS.hide_consumables = not Cartomancer.SETTINGS.hide_consumables - end -} - -Cartomancer.register_keybind { - name = 'toggle_deck', - func = function (controller) - Cartomancer.SETTINGS.hide_deck = not Cartomancer.SETTINGS.hide_deck - end -} - -Cartomancer.register_keybind { - name = 'toggle_jokers', - func = function (controller) - if not (G and G.jokers) then - return - end - G.jokers.cart_hide_all = not G.jokers.cart_hide_all - - if G.jokers.cart_hide_all then - Cartomancer.hide_all_jokers() - else - Cartomancer.show_all_jokers() - end - Cartomancer.align_G_jokers() - end -} - -Cartomancer.register_keybind { - name = 'toggle_jokers_buttons', - func = function (controller) - Cartomancer.SETTINGS.jokers_controls_buttons = not Cartomancer.SETTINGS.jokers_controls_buttons - end -} diff --git a/lovely/dump/tag.lua b/lovely/dump/tag.lua deleted file mode 100644 index 8b9a561..0000000 --- a/lovely/dump/tag.lua +++ /dev/null @@ -1,789 +0,0 @@ -LOVELY_INTEGRITY = '28c37f9c0f5cf94954059dedc38a88cb0f1dbceb28b6a40c9df225d84bb10fe5' - ---Class -Tag = Object:extend() - ---Class Methods -function Tag:init(_tag, for_collection, _blind_type) - self.key = _tag - local proto = G.P_TAGS[_tag] or G.tag_undiscovered - self.config = copy_table(proto.config) - self.pos = proto.pos - self.name = proto.name - self.tally = G.GAME.tag_tally or 0 - self.triggered = false - G.tagid = G.tagid or 0 - self.ID = G.tagid - G.tagid = G.tagid + 1 - self.ability = { - orbital_hand = '['..localize('k_poker_hand')..']', - blind_type = _blind_type - } - G.GAME.tag_tally = G.GAME.tag_tally and (G.GAME.tag_tally + 1) or 1 - if not for_collection then self:set_ability() end -end - -function Tag:nope() - G.E_MANAGER:add_event(Event({ - delay = 0.2, - trigger = 'after', - func = (function() - attention_text({ - text = 'NOPE', - colour = G.C.WHITE, - scale = 0.7, - hold = 0.3/G.SETTINGS.GAMESPEED, - cover = self.HUD_tag, - cover_colour = G.C.BLACK, - align = 'cm', - }) - play_sound('cancel', 1.4, 0.5) - return true - end) - })) - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.1, - func = (function() - self.HUD_tag.states.visible = false - play_sound('cancel', 1.26, 0.5) - return true - end) - })) - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.5, - func = (function() - self:remove() - return true - end) - })) -end - -function Tag:yep(message, _colour, func) - stop_use() - - G.E_MANAGER:add_event(Event({ - delay = 0.4, - trigger = 'after', - func = (function() - attention_text({ - text = message, - colour = G.C.WHITE, - scale = 1, - hold = 0.3/G.SETTINGS.GAMESPEED, - cover = self.HUD_tag, - cover_colour = _colour or G.C.GREEN, - align = 'cm', - }) - 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) - })) - G.E_MANAGER:add_event(Event({ - func = (function() - self.HUD_tag.states.visible = false - return true - end) - })) - G.E_MANAGER:add_event(Event({ - func = func - })) - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.7, - func = (function() - self:remove() - return true - end) - })) -end - -function Tag:set_ability() - local obj = SMODS.Tags[self.key] - local res - if obj and obj.set_ability and type(obj.set_ability) == 'function' then - obj:set_ability(self) - end - if self.name == 'Orbital Tag' then - if G.orbital_hand then - self.ability.orbital_hand = G.orbital_hand - elseif self.ability.blind_type then - if G.GAME.orbital_choices and G.GAME.orbital_choices[G.GAME.round_resets.ante][self.ability.blind_type] then - self.ability.orbital_hand = G.GAME.orbital_choices[G.GAME.round_resets.ante][self.ability.blind_type] - end - end - end -end - -function Tag:apply_to_run(_context) - if self.triggered then return end - local obj = SMODS.Tags[self.key] - local res - if obj and obj.apply and type(obj.apply) == 'function' then - res = obj:apply(self, _context) - end - if res then return res end - if not self.triggered and self.config.type == _context.type then - if _context.type == 'eval' then - if self.name == 'Investment Tag' and - G.GAME.last_blind and G.GAME.last_blind.boss then - self:yep('+', G.C.GOLD,function() - return true - end) - self.triggered = true - return { - dollars = self.config.dollars, - condition = localize('ph_defeat_the_boss'), - pos = self.pos, - tag = self - } - end - elseif _context.type == 'immediate' then - local lock = self.ID - G.CONTROLLER.locks[lock] = true - if self.name == 'Top-up Tag' then - self:yep('+', G.C.PURPLE,function() - for i = 1, self.config.spawn_jokers do - if G.jokers and #G.jokers.cards < G.jokers.config.card_limit then - local card = create_card('Joker', G.jokers, nil, 0, nil, nil, nil, 'top') - card:add_to_deck() - G.jokers:emplace(card) - end - end - G.CONTROLLER.locks[lock] = nil - return true - end) - self.triggered = true - return true - end - if self.name == 'Skip Tag' then - self:yep('+', G.C.MONEY,function() - G.CONTROLLER.locks[lock] = nil - return true - end) - ease_dollars((G.GAME.skips or 0)*self.config.skip_bonus) - self.triggered = true - return true - end - if self.name == 'Garbage Tag' then - self:yep('+', G.C.MONEY,function() - G.CONTROLLER.locks[lock] = nil - return true - end) - ease_dollars((G.GAME.unused_discards or 0)*self.config.dollars_per_discard) - self.triggered = true - return true - end - if self.name == 'Handy Tag' then - self:yep('+', G.C.MONEY,function() - G.CONTROLLER.locks[lock] = nil - return true - end) - ease_dollars((G.GAME.hands_played or 0)*self.config.dollars_per_hand) - self.triggered = true - return true - end - if self.name == 'Economy Tag' then - self:yep('+', G.C.MONEY,function() - G.CONTROLLER.locks[lock] = nil - return true - end) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - ease_dollars(math.min(self.config.max, math.max(0,G.GAME.dollars)), true) - return true - end - })) - self.triggered = true - return true - end - if self.name == 'Orbital Tag' then - if (not self.ability.orbital_hand) or (not G.GAME.hands[self.ability.orbital_hand]) 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 - - self.ability.orbital_hand = pseudorandom_element(_poker_hands, pseudoseed('orbital')) - end - update_hand_text({sound = 'button', volume = 0.7, pitch = 0.8, delay = 0.3}, { - handname= self.ability.orbital_hand, - chips = G.GAME.hands[self.ability.orbital_hand].chips, - mult = G.GAME.hands[self.ability.orbital_hand].mult, - level= G.GAME.hands[self.ability.orbital_hand].level}) - level_up_hand(self, self.ability.orbital_hand, nil, self.config.levels) - update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''}) - self:yep('+', G.C.MONEY,function() - G.CONTROLLER.locks[lock] = nil - return true - end) - self.triggered = true - return true - end - elseif _context.type == 'new_blind_choice' then - local lock = self.ID - G.CONTROLLER.locks[lock] = true - if self.name == 'Charm Tag' then - self:yep('+', G.C.PURPLE,function() - local key = 'p_arcana_mega_'..(math.random(1,2)) - local card = Card(G.play.T.x + G.play.T.w/2 - G.CARD_W*1.27/2, - G.play.T.y + G.play.T.h/2-G.CARD_H*1.27/2, G.CARD_W*1.27, G.CARD_H*1.27, G.P_CARDS.empty, G.P_CENTERS[key], {bypass_discovery_center = true, bypass_discovery_ui = true}) - card.cost = 0 - card.from_tag = true - G.FUNCS.use_card({config = {ref_table = card}}) - if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_random_edition then - card:set_edition(nil, true, true) - elseif G.GAME.modifiers.cry_force_random_edition then - local edition = cry_poll_random_edition() - card:set_edition(edition, true, true) - end - card:start_materialize() - G.CONTROLLER.locks[lock] = nil - return true - end) - self.triggered = true - return true - end - if self.name == 'Meteor Tag' then - self:yep('+', G.C.SECONDARY_SET.Planet,function() - local key = 'p_celestial_mega_'..(math.random(1,2)) - local card = Card(G.play.T.x + G.play.T.w/2 - G.CARD_W*1.27/2, - G.play.T.y + G.play.T.h/2-G.CARD_H*1.27/2, G.CARD_W*1.27, G.CARD_H*1.27, G.P_CARDS.empty, G.P_CENTERS[key], {bypass_discovery_center = true, bypass_discovery_ui = true}) - card.cost = 0 - card.from_tag = true - G.FUNCS.use_card({config = {ref_table = card}}) - if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_random_edition then - card:set_edition(nil, true, true) - elseif G.GAME.modifiers.cry_force_random_edition then - local edition = cry_poll_random_edition() - card:set_edition(edition, true, true) - end - card:start_materialize() - G.CONTROLLER.locks[lock] = nil - return true - end) - self.triggered = true - return true - end - if self.name == 'Ethereal Tag' then - self:yep('+', G.C.SECONDARY_SET.Spectral,function() - local key = 'p_spectral_normal_1' - local card = Card(G.play.T.x + G.play.T.w/2 - G.CARD_W*1.27/2, - G.play.T.y + G.play.T.h/2-G.CARD_H*1.27/2, G.CARD_W*1.27, G.CARD_H*1.27, G.P_CARDS.empty, G.P_CENTERS[key], {bypass_discovery_center = true, bypass_discovery_ui = true}) - card.cost = 0 - card.from_tag = true - G.FUNCS.use_card({config = {ref_table = card}}) - if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_random_edition then - card:set_edition(nil, true, true) - elseif G.GAME.modifiers.cry_force_random_edition then - local edition = cry_poll_random_edition() - card:set_edition(edition, true, true) - end - card:start_materialize() - G.CONTROLLER.locks[lock] = nil - return true - end) - self.triggered = true - return true - end - if self.name == 'Standard Tag' then - self:yep('+', G.C.SECONDARY_SET.Spectral,function() - local key = 'p_standard_mega_1' - local card = Card(G.play.T.x + G.play.T.w/2 - G.CARD_W*1.27/2, - G.play.T.y + G.play.T.h/2-G.CARD_H*1.27/2, G.CARD_W*1.27, G.CARD_H*1.27, G.P_CARDS.empty, G.P_CENTERS[key], {bypass_discovery_center = true, bypass_discovery_ui = true}) - card.cost = 0 - card.from_tag = true - G.FUNCS.use_card({config = {ref_table = card}}) - if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_random_edition then - card:set_edition(nil, true, true) - elseif G.GAME.modifiers.cry_force_random_edition then - local edition = cry_poll_random_edition() - card:set_edition(edition, true, true) - end - card:start_materialize() - G.CONTROLLER.locks[lock] = nil - return true - end) - self.triggered = true - return true - end - if self.name == 'Buffoon Tag' then - self:yep('+', G.C.SECONDARY_SET.Spectral,function() - local key = 'p_buffoon_mega_1' - local card = Card(G.play.T.x + G.play.T.w/2 - G.CARD_W*1.27/2, - G.play.T.y + G.play.T.h/2-G.CARD_H*1.27/2, G.CARD_W*1.27, G.CARD_H*1.27, G.P_CARDS.empty, G.P_CENTERS[key], {bypass_discovery_center = true, bypass_discovery_ui = true}) - card.cost = 0 - card.from_tag = true - G.FUNCS.use_card({config = {ref_table = card}}) - if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_random_edition then - card:set_edition(nil, true, true) - elseif G.GAME.modifiers.cry_force_random_edition then - local edition = cry_poll_random_edition() - card:set_edition(edition, true, true) - end - card:start_materialize() - G.CONTROLLER.locks[lock] = nil - return true - end) - self.triggered = true - return true - end - if self.name == 'Boss Tag' then - local lock = self.ID - G.CONTROLLER.locks[lock] = true - self:yep('+', G.C.GREEN,function() - G.from_boss_tag = true - G.FUNCS.reroll_boss() - - G.E_MANAGER:add_event(Event({func = function() - G.E_MANAGER:add_event(Event({func = function() - G.CONTROLLER.locks[lock] = nil - return true; end})) - return true; end})) - - return true - end) - self.triggered = true - return true - end - elseif _context.type == 'voucher_add' then - if self.name == 'Voucher Tag' then - self:yep('+', G.C.SECONDARY_SET.Voucher,function() - G.ARGS.voucher_tag = G.ARGS.voucher_tag or {} - local voucher_key = get_next_voucher_key(true) - G.ARGS.voucher_tag[voucher_key] = true - G.shop_vouchers.config.card_limit = G.shop_vouchers.config.card_limit + 1 - local card = Card(G.shop_vouchers.T.x + G.shop_vouchers.T.w/2, - G.shop_vouchers.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS[voucher_key],{bypass_discovery_center = true, bypass_discovery_ui = true}) - cry_misprintize(card) - if G.GAME.events.ev_cry_choco2 then - card.misprint_cost_fac = (card.misprint_cost_fac or 1) * 2 - card:set_cost() - end - create_shop_card_ui(card, 'Voucher', G.shop_vouchers) - if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_random_edition then - card:set_edition(nil, true, true) - elseif G.GAME.modifiers.cry_force_random_edition then - local edition = cry_poll_random_edition() - card:set_edition(edition, true, true) - end - card:start_materialize() - if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_random_edition then - card:set_edition(nil, true) - elseif G.GAME.modifiers.cry_force_random_edition then - local edition = cry_poll_random_edition() - card:set_edition(edition, true) - end - - if G.GAME.modifiers.cry_force_sticker == 'eternal' or G.GAME.modifiers.cry_sticker_sheet_plus then - card:set_eternal(true) - card.ability.eternal = true - end - if G.GAME.modifiers.cry_force_sticker == 'perishable' or G.GAME.modifiers.cry_sticker_sheet_plus then - card:set_perishable(true) - card.ability.perishable = true - end - if G.GAME.modifiers.cry_force_sticker == 'rental' or G.GAME.modifiers.cry_sticker_sheet_plus then - card:set_rental(true) - card.ability.rental = true - end - if G.GAME.modifiers.cry_force_sticker == 'pinned' or G.GAME.modifiers.cry_sticker_sheet_plus then - card.pinned = true - end - if G.GAME.modifiers.cry_force_sticker == 'banana' or G.GAME.modifiers.cry_sticker_sheet_plus then - card.ability.banana = true - end - if G.GAME.modifiers.cry_sticker_sheet_plus then - for k, v in pairs(SMODS.Stickers) do - if v.apply and not v.no_sticker_sheet then v:apply(card, true) end - end - end - G.shop_vouchers:emplace(card) - G.ARGS.voucher_tag = nil - return true - end) - self.triggered = true - end - elseif _context.type == 'tag_add' then - if self.name == 'Double Tag' and _context.tag.key ~= 'tag_double' then - local lock = self.ID - G.CONTROLLER.locks[lock] = true - self:yep('+', G.C.BLUE,function() - if _context.tag.ability and _context.tag.ability.orbital_hand then - G.orbital_hand = _context.tag.ability.orbital_hand - end - local tag = Tag(_context.tag.key) - if _context.tag.key == "tag_cry_rework" then - tag.ability.rework_edition = _context.tag.ability.rework_edition - tag.ability.rework_key = _context.tag.ability.rework_key - end - add_tag(tag) - G.orbital_hand = nil - G.CONTROLLER.locks[lock] = nil - return true - end) - self.triggered = true - end - elseif _context.type == 'round_start_bonus' then - if self.name == 'Juggle Tag' then - self:yep('+', G.C.BLUE,function() - return true - end) - G.hand:change_size(self.config.h_size) - G.GAME.round_resets.temp_handsize = (G.GAME.round_resets.temp_handsize or 0) + self.config.h_size - self.triggered = true - return true - end - elseif _context.type == 'store_joker_create' then - local card = nil - if self.name == 'Rare Tag' then - local rares_in_posession = {0} - for k, v in ipairs(G.jokers.cards) do - if v.config.center.rarity == 3 and not rares_in_posession[v.config.center.key] then - rares_in_posession[1] = rares_in_posession[1] + 1 - rares_in_posession[v.config.center.key] = true - end - end - - if #G.P_JOKER_RARITY_POOLS[3] > rares_in_posession[1] then - card = create_card('Joker', _context.area, nil, 1, nil, nil, nil, 'rta') - create_shop_card_ui(card, 'Joker', _context.area) - card.states.visible = false - self:yep('+', G.C.RED,function() - if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_random_edition then - card:set_edition(nil, true, true) - elseif G.GAME.modifiers.cry_force_random_edition then - local edition = cry_poll_random_edition() - card:set_edition(edition, true, true) - end - card:start_materialize() - card.ability.couponed = true - card:set_cost() - return true - end) - else - self:nope() - end - self.triggered = true - elseif self.name == 'Uncommon Tag' then - card = create_card('Joker', _context.area, nil, 0.9, nil, nil, nil, 'uta') - create_shop_card_ui(card, 'Joker', _context.area) - card.states.visible = false - self:yep('+', G.C.GREEN,function() - if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_random_edition then - card:set_edition(nil, true, true) - elseif G.GAME.modifiers.cry_force_random_edition then - local edition = cry_poll_random_edition() - card:set_edition(edition, true, true) - end - card:start_materialize() - card.ability.couponed = true - card:set_cost() - return true - end) - end - self.triggered = true - return card - elseif _context.type == 'shop_start' then - if self.name == 'D6 Tag' and not G.GAME.shop_d6ed then - G.GAME.shop_d6ed = true - self:yep('+', G.C.GREEN,function() - G.GAME.round_resets.temp_reroll_cost = 0 - calculate_reroll_cost(true) - return true - end) - self.triggered = true - return true - end - elseif _context.type == 'store_joker_modify' then - local _applied = nil - if not _context.card.edition and not _context.card.temp_edition and _context.card.ability.set == 'Joker' then - local lock = self.ID - G.CONTROLLER.locks[lock] = true - if self.name == 'Foil Tag' then - _context.card.temp_edition = true - self:yep('+', G.C.DARK_EDITION,function() - _context.card:set_edition({foil = true}, true) - _context.card.ability.couponed = true - _context.card:set_cost() - _context.card.temp_edition = nil - G.CONTROLLER.locks[lock] = nil - return true - end) - _applied = true - elseif self.name == 'Holographic Tag' then - _context.card.temp_edition = true - self:yep('+', G.C.DARK_EDITION,function() - _context.card.temp_edition = nil - _context.card:set_edition({holo = true}, true) - _context.card.ability.couponed = true - _context.card:set_cost() - G.CONTROLLER.locks[lock] = nil - return true - end) - _applied = true - elseif self.name == 'Polychrome Tag' then - _context.card.temp_edition = true - self:yep('+', G.C.DARK_EDITION,function() - _context.card.temp_edition = nil - _context.card:set_edition({polychrome = true}, true) - _context.card.ability.couponed = true - _context.card:set_cost() - G.CONTROLLER.locks[lock] = nil - return true - end) - _applied = true - elseif self.name == 'Negative Tag' then - _context.card.temp_edition = true - self:yep('+', G.C.DARK_EDITION,function() - _context.card.temp_edition = nil - _context.card:set_edition({negative = true}, true) - _context.card.ability.couponed = true - _context.card:set_cost() - G.CONTROLLER.locks[lock] = nil - return true - end) - _applied = true - end - self.triggered = true - end - - return _applied - elseif _context.type == 'shop_final_pass' then - if self.name == 'Coupon Tag' and (G.shop and not G.GAME.shop_free) then - G.GAME.shop_free = true - self:yep('+', G.C.GREEN,function() - if G.shop_jokers and G.shop_booster then - for k, v in pairs(G.shop_jokers.cards) do - v.ability.couponed = true - v:set_cost() - end - for k, v in pairs(G.shop_booster.cards) do - v.ability.couponed = true - v:set_cost() - end - end - return true - end) - self.triggered = true - return true - end - end - end -end - -function Tag:save() - return { - key = self.key, - tally = self.tally, - ability = self.ability - } -end - -function Tag:load(tag_savetable) - self.key = tag_savetable.key - local proto = G.P_TAGS[self.key] or G.tag_undiscovered - self.config = copy_table(proto.config) - self.pos = proto.pos - self.name = proto.name - self.tally = tag_savetable.tally - self.ability = tag_savetable.ability - G.GAME.tag_tally = math.max(self.tally, G.GAME.tag_tally) + 1 -end - -function Tag:juice_up(_scale, _rot) - if self.tag_sprite then self.tag_sprite:juice_up(_scale, _rot) end -end - -function Tag:generate_UI(_size) - _size = _size or 0.8 - - local tag_sprite_tab = nil - - local tag_sprite = Sprite(0,0,_size*1,_size*1,G.ASSET_ATLAS[(not self.hide_ability) and G.P_TAGS[self.key].atlas or "tags"], (self.hide_ability) and G.tag_undiscovered.pos or self.pos) - tag_sprite.T.scale = 1 - tag_sprite_tab = {n= G.UIT.C, config={align = "cm", ref_table = self, group = self.tally}, nodes={ - {n=G.UIT.O, config={w=_size*1,h=_size*1, colour = G.C.BLUE, object = tag_sprite, focus_with_object = true}}, - }} - tag_sprite:define_draw_steps({ - {shader = 'dissolve', shadow_height = 0.05}, - {shader = 'dissolve'}, - }) - tag_sprite.float = true - tag_sprite.states.hover.can = true - tag_sprite.states.drag.can = false - tag_sprite.states.collide.can = true - if self.key == 'tag_cry_cat' then tag_sprite.states.click.can = true; tag_sprite.states.drag.can = true end - tag_sprite.config = {tag = self, force_focus = true} - - tag_sprite.hover = function(_self) - if not G.CONTROLLER.dragging.target or G.CONTROLLER.using_touch then - if not _self.hovering and _self.states.visible then - _self.hovering = true - if _self == tag_sprite then - _self.hover_tilt = 3 - _self:juice_up(0.05, 0.02) - play_sound('paper1', math.random()*0.1 + 0.55, 0.42) - if self.key == 'tag_cry_cat' then - local rand = math.random(4) - play_sound('cry_meow'..rand, 1.26, 0.25) - end - play_sound('tarot2', math.random()*0.1 + 0.55, 0.09) - end - - self:get_uibox_table(tag_sprite) - _self.config.h_popup = G.UIDEF.card_h_popup(_self) - _self.config.h_popup_config = (_self.T.x > G.ROOM.T.w*0.4) and - {align = 'cl', offset = {x=-0.1,y=0},parent = _self} or - {align = 'cr', offset = {x=0.1,y=0},parent = _self} - Node.hover(_self) - if _self.children.alert then - _self.children.alert:remove() - _self.children.alert = nil - if self.key and G.P_TAGS[self.key] then G.P_TAGS[self.key].alerted = true end - G:save_progress() - end - end - end - end - tag_sprite.stop_hover = function(_self) _self.hovering = false; Node.stop_hover(_self); _self.hover_tilt = 0 end - tag_sprite.click = function(_self) - if self.key == 'tag_cry_cat' and self.HUD_tag then - for i = 1, #G.GAME.tags do - local other_cat = G.GAME.tags[i] - if other_cat.key == 'tag_cry_cat' then - if not self.ability.level then self.ability.level = 1 end - if not other_cat.ability.level then other_cat.ability.level = 1 end -- setting ability just doesn't seem to be working... so you get this - if (self.ability.level == other_cat.ability.level) and (other_cat ~= self) and not cry_too_fast_kitty then - cry_too_fast_kitty = true - local perc = (other_cat.ability.level + 1)/10 - if perc > 1 then perc = 1 end - G.E_MANAGER:add_event(Event({ - delay = 0.0, - trigger = 'immediate', - func = (function() - attention_text({ - text = ""..other_cat.ability.level, - colour = G.C.WHITE, - scale = 1, - hold = 0.3/G.SETTINGS.GAMESPEED, - cover = other_cat.HUD_tag, - cover_colour = G.C.DARK_EDITION, - align = 'cm', - }) - play_sound('generic1', 0.8 + perc/2, 0.6) - play_sound('multhit1', 0.9 + perc/2, 0.4) - return true - end) - })) - G.E_MANAGER:add_event(Event({ - delay = 0.0, - trigger = 'immediate', - func = (function() - attention_text({ - text = "-", - colour = G.C.WHITE, - scale = 1, - hold = 0.3/G.SETTINGS.GAMESPEED, - cover = self.HUD_tag, - cover_colour = G.C.RED, - align = 'cm', - }) - return true - end) - })) - G.E_MANAGER:add_event(Event({ - func = (function() - self.HUD_tag.states.visible = false - return true - end) - })) - G.E_MANAGER:add_event(Event({ -- i have no idea what this does but i'm not messing with it - func = func - })) - - other_cat.ability.level = other_cat.ability.level + 1 - - G.E_MANAGER:add_event(Event({ - trigger = 'after', - delay = 0.7, - func = (function() - self:remove() - cry_too_fast_kitty = nil - return true - end) - })) - break - end - end - end - end - end - - tag_sprite:juice_up() - self.tag_sprite = tag_sprite - - return tag_sprite_tab, tag_sprite -end - -function Tag:get_uibox_table(tag_sprite) - tag_sprite = tag_sprite or self.tag_sprite - local name_to_check, loc_vars = self.name, {} - if name_to_check == 'Uncommon Tag' then - elseif name_to_check == 'Investment Tag' then loc_vars = {self.config.dollars} - elseif name_to_check == 'Handy Tag' then loc_vars = {self.config.dollars_per_hand, self.config.dollars_per_hand*(G.GAME.hands_played or 0)} - elseif name_to_check == 'Garbage Tag' then loc_vars = {self.config.dollars_per_discard, self.config.dollars_per_discard*(G.GAME.unused_discards or 0)} - elseif name_to_check == 'Juggle Tag' then loc_vars = {self.config.h_size} - elseif name_to_check == 'Top-up Tag' then loc_vars = {self.config.spawn_jokers} - elseif name_to_check == 'Skip Tag' then loc_vars = {self.config.skip_bonus, self.config.skip_bonus*((G.GAME.skips or 0)+1)} - elseif name_to_check == 'Orbital Tag' then loc_vars = { - (self.ability.orbital_hand == '['..localize('k_poker_hand')..']') and self.ability.orbital_hand or localize(self.ability.orbital_hand, 'poker_hands'), self.config.levels} - elseif name_to_check == 'Economy Tag' then loc_vars = {self.config.max} - elseif name_to_check == "cry-Rework Tag" then loc_vars = { - self.ability and self.ability.rework_edition and localize{type = "name_text", set = "Edition", key = self.ability.rework_edition} or "["..string.lower(localize("k_edition")).."]", - self.ability and self.ability.rework_key and localize{type = "name_text", set = "Joker", key = self.ability.rework_key} or "["..string.lower(localize("k_joker")).."]", - } - elseif name_to_check == "cry-Cat Tag" then loc_vars = {self.ability.level or 1} - end - tag_sprite.ability_UIBox_table = generate_card_ui(G.P_TAGS[self.key], nil, loc_vars, (self.hide_ability) and 'Undiscovered' or 'Tag', nil, (self.hide_ability), nil, nil, self) - return tag_sprite -end - -function Tag:remove_from_game() - local tag_key = nil - for k, v in pairs(G.GAME.tags) do - if v == self then tag_key = k end - end - table.remove(G.GAME.tags, tag_key) -end - -function Tag:remove() - self:remove_from_game() - local HUD_tag_key = nil - for k, v in pairs(G.HUD_tags) do - if v == self.HUD_tag then HUD_tag_key = k end - end - - if HUD_tag_key then - if G.HUD_tags and G.HUD_tags[HUD_tag_key+1] then - if HUD_tag_key == 1 then - G.HUD_tags[HUD_tag_key+1]:set_alignment({type = 'bri', - offset = {x=0.7,y=0}, - xy_bond = 'Weak', - major = G.ROOM_ATTACH}) - else - G.HUD_tags[HUD_tag_key+1]:set_role({ - xy_bond = 'Weak', - major = G.HUD_tags[HUD_tag_key-1]}) - end - end - table.remove(G.HUD_tags, HUD_tag_key) - end - - self.HUD_tag:remove() -end