-The are a total of 15 fusions added in the mod, with more coming in the future!
+There are a total of 15 fusions added in the mod!
You can find a list of their abilities, as well as the jokers needed to make them, in this link: https://itayfeder.github.io/Fusion-Jokers/
@@ -51,4 +51,5 @@ Developers can call the function `FusionJokers.fusions:add_fusion()` to register
## 🎉 Credits
-- The mod was written by [**Itayfeder**](https://github.com/stars/itayfeder/lists/balatro-modding), with art created by [**Lyman**](https://github.com/spikeof2010)
+- The original mod was written by [**Itayfeder**](https://github.com/stars/itayfeder/lists/balatro-modding), with art created by [**Lyman**](https://github.com/spikeof2010)
+- [**elbe**](https://github.com/lshtech) did several patches to handle breaking changes in Steamodded, as well as various other features
From f2d63f46fdccc7e7c71565d71ce3f0966fabf81e Mon Sep 17 00:00:00 2001
From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com>
Date: Fri, 24 Jan 2025 01:32:25 -0500
Subject: [PATCH 05/91] oh yeah fix the stone card thing
---
mod/FusionJokers.lua | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mod/FusionJokers.lua b/mod/FusionJokers.lua
index 27233e4..9128a2a 100644
--- a/mod/FusionJokers.lua
+++ b/mod/FusionJokers.lua
@@ -750,7 +750,7 @@ function SMODS.INIT.FusionJokers()
function SMODS.Jokers.j_dynamic_duo.calculate(card, context)
if context.individual and context.cardarea == G.play and
- not context.other_card:is_face() then
+ not context.other_card:is_face() and not SMODS.has_no_rank(context.other_card) then
return {
mult = card.ability.extra.mult,
chips = card.ability.extra.chips,
From ecaf911962db9c55cf471a54c3bf210a75301f85 Mon Sep 17 00:00:00 2001
From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com>
Date: Fri, 24 Jan 2025 01:34:30 -0500
Subject: [PATCH 06/91] that's a bettercalc function, so dependency
---
mod/FusionJokers.lua | 1 +
1 file changed, 1 insertion(+)
diff --git a/mod/FusionJokers.lua b/mod/FusionJokers.lua
index 9128a2a..0286e5d 100644
--- a/mod/FusionJokers.lua
+++ b/mod/FusionJokers.lua
@@ -6,6 +6,7 @@
--- BADGE_COLOUR: B26CBB
--- PRIORITY: -10000
--- PREFIX: fuse
+--- DEPENDENCIES: [Steamodded>=1.0.0~ALPHA-1307d]
--- CONFLICTS: [Talisman<=2.0]
----------------------------------------------
------------MOD CODE -------------------------
From 78d95f0c18b132fb69a559713e5bc956601d3ed1 Mon Sep 17 00:00:00 2001
From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com>
Date: Mon, 24 Mar 2025 17:24:25 -0400
Subject: [PATCH 07/91] Block fusion ingredience from appearing if fusion is
present
---
mod/FusionJokers.lua | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/mod/FusionJokers.lua b/mod/FusionJokers.lua
index 0286e5d..644c4dc 100644
--- a/mod/FusionJokers.lua
+++ b/mod/FusionJokers.lua
@@ -81,6 +81,23 @@ FusionJokers.fusions = {
}, result_joker = "j_camping_trip", cost = 10 },
}
+for _, fusion in ipairs(FusionJokers.fusions) do
+ local fused = fusion.result_joker
+
+ for _, component in ipairs(fusion.jokers) do
+ local component_name = component.name
+
+ SMODS.Joker:take_ownership(component_name, {
+ in_pool = function(self, args)
+ if #SMODS.find_card('j_showman') > 0 then return true end -- Allow finding copies if Showman is present
+ if #SMODS.find_card(fused) > 0 then return false end -- If the fused Joker exists, remove both components
+ return true
+ end
+ }, true) -- silent | suppresses mod badge
+ end
+end
+
+
local rarity = SMODS.Rarity{
key = "fusion",
loc_txt = {
From b9072b3917d76334f25011778386857d7c60f83a Mon Sep 17 00:00:00 2001
From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com>
Date: Mon, 24 Mar 2025 17:34:12 -0400
Subject: [PATCH 08/91] added a config about it
---
README.md | 5 +++++
mod/FusionJokers.lua | 3 +++
mod/config.lua | 3 +++
mod/configui.lua | 11 +++++++++++
4 files changed, 22 insertions(+)
create mode 100644 mod/config.lua
create mode 100644 mod/configui.lua
diff --git a/README.md b/README.md
index 094df83..3fc7ce2 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,7 @@
- [About](#about)
- [How to Download](#how_to_download)
+- [Config](#config)
- [Fusion API (For Developers)](#fusion_api)
- [Credits](#credits)
@@ -43,6 +44,10 @@ You can find a list of their abilities, as well as the jokers needed to make the
- Download the latest release of Fusion Jokers
- Extract the downloaded mod to the Mods folder (at %appdata%/Balatro/Mods)
+## ⚙️ Config
+
+- '''Block used components from reappearing''': Jokers used in a fusion cannot reappear if the fusion is present. Currently only applies to Fusion Jokers fusions; cross-mod functionality is planned. Default true.
+
## ➕ Fusion API (For Developers)
The mod adds a way for other developers to create their own fusions!
diff --git a/mod/FusionJokers.lua b/mod/FusionJokers.lua
index 644c4dc..ba310ba 100644
--- a/mod/FusionJokers.lua
+++ b/mod/FusionJokers.lua
@@ -81,6 +81,9 @@ FusionJokers.fusions = {
}, result_joker = "j_camping_trip", cost = 10 },
}
+FusionJokers.fusionconfig = SMODS.current_mod.config
+SMODS.load_file('configui.lua')()
+
for _, fusion in ipairs(FusionJokers.fusions) do
local fused = fusion.result_joker
diff --git a/mod/config.lua b/mod/config.lua
new file mode 100644
index 0000000..a2dda85
--- /dev/null
+++ b/mod/config.lua
@@ -0,0 +1,3 @@
+return {
+ ["block_components"] = true,
+}
\ No newline at end of file
diff --git a/mod/configui.lua b/mod/configui.lua
new file mode 100644
index 0000000..a90fed8
--- /dev/null
+++ b/mod/configui.lua
@@ -0,0 +1,11 @@
+SMODS.current_mod.config_tab = function()
+ return {n = G.UIT.ROOT, config = {r = 0.1, minw = 8, minh = 6, align = "tl", padding = 0.2, colour = G.C.BLACK}, nodes = {
+ {n = G.UIT.C, config = {minw=1, minh=1, align = "tl", colour = G.C.CLEAR, padding = 0.15}, nodes = {
+ create_toggle({
+ label = "Block used components from reappearing",
+ ref_table = FusionJokers.fusionconfig,
+ ref_value = 'block_components',
+ }),
+ }}
+ }}
+end
\ No newline at end of file
From 7f902c2cfcdf4b0d6f008e74d08116e29cc4f186 Mon Sep 17 00:00:00 2001
From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com>
Date: Mon, 24 Mar 2025 17:45:05 -0400
Subject: [PATCH 09/91] ... make the config *functional*, minty
---
mod/FusionJokers.lua | 1 +
1 file changed, 1 insertion(+)
diff --git a/mod/FusionJokers.lua b/mod/FusionJokers.lua
index ba310ba..d0bebd9 100644
--- a/mod/FusionJokers.lua
+++ b/mod/FusionJokers.lua
@@ -93,6 +93,7 @@ for _, fusion in ipairs(FusionJokers.fusions) do
SMODS.Joker:take_ownership(component_name, {
in_pool = function(self, args)
if #SMODS.find_card('j_showman') > 0 then return true end -- Allow finding copies if Showman is present
+ if not FusionJokers.fusionconfig.block_components then return true end --If the option is disabled, don't do the check
if #SMODS.find_card(fused) > 0 then return false end -- If the fused Joker exists, remove both components
return true
end
From 9d0441b2796da1fe39053fd1ff0572e2b5ea5a00 Mon Sep 17 00:00:00 2001
From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com>
Date: Sun, 20 Apr 2025 13:04:14 -0400
Subject: [PATCH 10/91] update so many things to modern standards
---
mod/FusionJokers.json | 19 +
mod/FusionJokers.lua | 1036 ++-----------------------------
mod/assets/1x/j_flip_flop.png | Bin 1335 -> 23470 bytes
mod/assets/2x/j_flip_flop.png | Bin 1779 -> 23688 bytes
mod/jokers/bigbang.lua | 50 ++
mod/jokers/campingtrip.lua | 66 ++
mod/jokers/clubwizard.lua | 50 ++
mod/jokers/collectiblechaos.lua | 68 ++
mod/jokers/commercialdriver.lua | 70 +++
mod/jokers/dementiajoker.lua | 70 +++
mod/jokers/diamondbard.lua | 57 ++
mod/jokers/dynamicduo.lua | 53 ++
mod/jokers/flagbearer.lua | 82 +++
mod/jokers/flipflop.lua | 135 ++++
mod/jokers/goldenegg.lua | 57 ++
mod/jokers/heartpaladin.lua | 64 ++
mod/jokers/moonmarauder.lua | 117 ++++
mod/jokers/royaldecree.lua | 61 ++
mod/jokers/spadearcher.lua | 69 ++
mod/jokers/staroracle.lua | 68 ++
mod/jokers/uncannyface.lua | 59 ++
mod/localization/en-us.lua | 189 ++++++
22 files changed, 1465 insertions(+), 975 deletions(-)
create mode 100644 mod/FusionJokers.json
create mode 100644 mod/jokers/bigbang.lua
create mode 100644 mod/jokers/campingtrip.lua
create mode 100644 mod/jokers/clubwizard.lua
create mode 100644 mod/jokers/collectiblechaos.lua
create mode 100644 mod/jokers/commercialdriver.lua
create mode 100644 mod/jokers/dementiajoker.lua
create mode 100644 mod/jokers/diamondbard.lua
create mode 100644 mod/jokers/dynamicduo.lua
create mode 100644 mod/jokers/flagbearer.lua
create mode 100644 mod/jokers/flipflop.lua
create mode 100644 mod/jokers/goldenegg.lua
create mode 100644 mod/jokers/heartpaladin.lua
create mode 100644 mod/jokers/moonmarauder.lua
create mode 100644 mod/jokers/royaldecree.lua
create mode 100644 mod/jokers/spadearcher.lua
create mode 100644 mod/jokers/staroracle.lua
create mode 100644 mod/jokers/uncannyface.lua
create mode 100644 mod/localization/en-us.lua
diff --git a/mod/FusionJokers.json b/mod/FusionJokers.json
new file mode 100644
index 0000000..c248312
--- /dev/null
+++ b/mod/FusionJokers.json
@@ -0,0 +1,19 @@
+{
+ "id": "FusionJokers",
+ "name": "Fusion Jokers",
+ "display_name": "Fusion Jokers",
+ "author": ["itayfeder", "Lyman"],
+ "description": "Adds the ability to fuse jokers into special new jokers!",
+ "prefix": "fuse",
+ "main_file": "FusionJokers.lua",
+ "priority": -10000,
+ "badge_colour": "B26CBB",
+ "badge_text_colour": "FFFFFF",
+ "version": "1.0.0",
+ "dependencies": [
+ "Steamodded (>=1.0.0~ALPHA-1307d)",
+ ],
+ "conflicts": [
+ "Talisman (<=2.0)",
+ ],
+}
\ No newline at end of file
diff --git a/mod/FusionJokers.lua b/mod/FusionJokers.lua
index d0bebd9..2156724 100644
--- a/mod/FusionJokers.lua
+++ b/mod/FusionJokers.lua
@@ -1,17 +1,3 @@
---- STEAMODDED HEADER
---- MOD_NAME: Fusion Jokers
---- MOD_ID: FusionJokers
---- MOD_AUTHOR: [itayfeder, Lyman]
---- MOD_DESCRIPTION: Adds the ability to fuse jokers into special new jokers!
---- BADGE_COLOUR: B26CBB
---- PRIORITY: -10000
---- PREFIX: fuse
---- DEPENDENCIES: [Steamodded>=1.0.0~ALPHA-1307d]
---- CONFLICTS: [Talisman<=2.0]
-----------------------------------------------
-------------MOD CODE -------------------------
-
-
G.localization.misc.dictionary["k_fusion"] = "Fusion"
G.localization.misc.dictionary["k_flipped_ex"] = "Flipped!"
G.localization.misc.dictionary["k_copied_ex"] = "Cloned!"
@@ -22,63 +8,63 @@ FusionJokers.fusions = {
{ jokers = {
{ name = "j_greedy_joker", carry_stat = nil, extra_stat = false },
{ name = "j_rough_gem", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_diamond_bard", cost = 12 },
+ }, result_joker = "j_fuse_diamond_bard", cost = 12 },
{ jokers = {
{ name = "j_lusty_joker", carry_stat = nil, extra_stat = false },
{ name = "j_bloodstone", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_heart_paladin", cost = 12 },
+ }, result_joker = "j_fuse_heart_paladin", cost = 12 },
{ jokers = {
{ name = "j_wrathful_joker", carry_stat = nil, extra_stat = false },
{ name = "j_arrowhead", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_spade_archer", cost = 12 },
+ }, result_joker = "j_fuse_spade_archer", cost = 12 },
{ jokers = {
{ name = "j_gluttenous_joker", carry_stat = nil, extra_stat = false },
{ name = "j_onyx_agate", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_club_wizard", cost = 12 },
+ }, result_joker = "j_fuse_club_wizard", cost = 12 },
{ jokers = {
{ name = "j_supernova", carry_stat = nil, extra_stat = false },
{ name = "j_constellation", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_big_bang", cost = 11 },
+ }, result_joker = "j_fuse_big_bang", cost = 11 },
{ jokers = {
{ name = "j_even_steven", carry_stat = nil, extra_stat = false },
{ name = "j_odd_todd", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_dynamic_duo", cost = 8 },
+ }, result_joker = "j_fuse_dynamic_duo", cost = 8 },
{ jokers = {
{ name = "j_flash", carry_stat = "mult", extra_stat = false },
{ name = "j_chaos", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_collectible_chaos_card", cost = 9 },
+ }, result_joker = "j_fuse_collectible_chaos_card", cost = 9 },
{ jokers = {
{ name = "j_juggler", carry_stat = nil, extra_stat = false },
{ name = "j_drunkard", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_flip_flop", cost = 9 },
+ }, result_joker = "j_fuse_flip_flop", cost = 9 },
{ jokers = {
{ name = "j_business", carry_stat = nil, extra_stat = false },
{ name = "j_reserved_parking", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_royal_decree", cost = 10 },
+ }, result_joker = "j_fuse_royal_decree", cost = 10 },
{ jokers = {
{ name = "j_abstract", carry_stat = nil, extra_stat = false },
{ name = "j_riff_raff", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_dementia_joker", cost = 8 },
+ }, result_joker = "j_fuse_dementia_joker", cost = 8 },
{ jokers = {
{ name = "j_egg", carry_stat = "extra_value", extra_stat = false },
{ name = "j_golden", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_golden_egg", cost = 10 },
+ }, result_joker = "j_fuse_golden_egg", cost = 10 },
{ jokers = {
{ name = "j_banner", carry_stat = nil, extra_stat = false },
{ name = "j_green_joker", carry_stat = "mult", extra_stat = false }
- }, result_joker = "j_flag_bearer", cost = 9 },
+ }, result_joker = "j_fuse_flag_bearer", cost = 9 },
{ jokers = {
{ name = "j_scary_face", carry_stat = nil, extra_stat = false },
{ name = "j_smiley", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_uncanny_face", cost = 8 },
+ }, result_joker = "j_fuse_uncanny_face", cost = 8 },
{ jokers = {
{ name = "j_ride_the_bus", carry_stat = nil, extra_stat = false },
{ name = "j_drivers_license", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_commercial_driver", cost = 8 },
+ }, result_joker = "j_fuse_commercial_driver", cost = 8 },
{ jokers = {
{ name = "j_hiker", carry_stat = nil, extra_stat = false },
{ name = "j_dusk", carry_stat = nil, extra_stat = false }
- }, result_joker = "j_camping_trip", cost = 10 },
+ }, result_joker = "j_fuse_camping_trip", cost = 10 },
}
FusionJokers.fusionconfig = SMODS.current_mod.config
@@ -102,16 +88,8 @@ for _, fusion in ipairs(FusionJokers.fusions) do
end
-local rarity = SMODS.Rarity{
+SMODS.Rarity{
key = "fusion",
- loc_txt = {
- name = "Fusion",
- text = {
- "Can only be obtained",
- "through {C:attention}Fusing{}",
- "two specific Jokers"
- }
- },
default_weight = 0,
badge_colour = HEX("F7D762"),
pools = {["Joker"] = false},
@@ -122,20 +100,40 @@ local rarity = SMODS.Rarity{
local SMODS_Joker_inject=SMODS.Joker.inject
SMODS.Joker.inject =function(self)
- if self.rarity == 5 then
- self.rarity = rarity.key
+ if self.rarity == 5 or self.rarity == "fusion" then
+ self.rarity = "fuse_fusion"
end
SMODS_Joker_inject(self)
end
function FusionJokers.fusions:add_fusion(joker1, carry_stat1, extra1, joker2, carry_stat2, extra2, result_joker, cost, merged_stat, merge_stat1, merge_stat2, merge_extra)
- table.insert(self,
+ table.insert(self,
{ jokers = {
{ name = joker1, carry_stat = carry_stat1, extra_stat = extra1, merge_stat = merge_stat1 },
{ name = joker2, carry_stat = carry_stat2, extra_stat = extra2, merge_stat = merge_stat2 }
}, result_joker = result_joker, cost = cost, merged_stat = merged_stat, merge_extra = merge_extra })
end
+SMODS.load_file('jokers/diamondbard.lua')()
+SMODS.load_file('jokers/heartpaladin.lua')()
+SMODS.load_file('jokers/spadearcher.lua')()
+SMODS.load_file('jokers/clubwizard.lua')()
+if (SMODS.Mods["SixSuits"] or {}).can_load then
+ SMODS.load_file('jokers/moonmarauder.lua')()
+ SMODS.load_file('jokers/staroracle.lua')()
+end
+SMODS.load_file('jokers/bigbang.lua')()
+SMODS.load_file('jokers/dynamicduo.lua')()
+SMODS.load_file('jokers/collectiblechaos.lua')()
+SMODS.load_file('jokers/flipflop.lua')()
+SMODS.load_file('jokers/royaldecree.lua')()
+SMODS.load_file('jokers/dementiajoker.lua')()
+SMODS.load_file('jokers/goldenegg.lua')()
+SMODS.load_file('jokers/flagbearer.lua')()
+SMODS.load_file('jokers/uncannyface.lua')()
+SMODS.load_file('jokers/commercialdriver.lua')()
+SMODS.load_file('jokers/campingtrip.lua')()
+
local to_number = to_number or function(num)
return num
end
@@ -180,7 +178,7 @@ function Card:can_fuse_card()
return true
end
end
- end
+ end
return false
end
@@ -191,7 +189,7 @@ function Card:get_card_fusion()
return fusion
end
end
- end
+ end
return nil
end
@@ -308,7 +306,7 @@ function Card:fuse_card()
--G.jokers.cards[pos]:start_dissolve({G.C.GOLD})
G.jokers.cards[pos.pos]:remove()
end
-
+
delay(0.3)
j_fusion:add_to_deck()
@@ -344,7 +342,7 @@ G.FUNCS.fuse_card = function(e)
end
G.FUNCS.can_fuse_card = function(e)
- if e.config.ref_table:can_fuse_card() then
+ if e.config.ref_table:can_fuse_card() then
e.config.colour = G.C.DARK_EDITION
e.config.button = 'fuse_card'
else
@@ -358,11 +356,11 @@ G.FUNCS.can_fuse_card = function(e)
local use_and_sell_buttonsref = G.UIDEF.use_and_sell_buttons
function G.UIDEF.use_and_sell_buttons(card)
local retval = use_and_sell_buttonsref(card)
-
+
if card.area and card.area.config.type == 'joker' and card.ability.set == 'Joker' and card.ability.fusion then
- local fuse =
+ local fuse =
{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, hover = true, shadow = true, colour = G.C.GOLD, one_press = true, button = 'sell_card', func = 'can_fuse_card'}, nodes={
{n=G.UIT.B, config = {w=0.1,h=0.6}},
{n=G.UIT.C, config={align = "tm"}, nodes={
@@ -402,42 +400,35 @@ function G.UIDEF.card_h_popup(card)
return retval
end
+
+
+local flip = {
+ x = 0,
+ y = 0
+}
+local flop = {
+ x = 0,
+ y = 1
+}
local updateref = Card.update
function Card:update(dt)
updateref(self, dt)
if G.STAGE == G.STAGES.RUN then
- if self.ability.name == "Flip-Flop" then
- if self.ability.extra.side == "mult" then
- if (self.config.center.atlas ~= "j_flip_flop" or G.localization.descriptions["Joker"]["j_flip_flop"] ~= G.localization.descriptions["Joker"]["j_flip_flop_mult"]) then
- G.localization.descriptions["Joker"]["j_flip_flop"] = G.localization.descriptions["Joker"]["j_flip_flop_mult"]
- self.config.center.atlas = "j_flip_flop"
- self:set_sprites(self.config.center)
- end
- else
- if (self.config.center.atlas ~= "j_flop_flip" or G.localization.descriptions["Joker"]["j_flip_flop"] ~= G.localization.descriptions["Joker"]["j_flip_flop_chips"]) then
- G.localization.descriptions["Joker"]["j_flip_flop"] = G.localization.descriptions["Joker"]["j_flip_flop_chips"]
- self.config.center.atlas = "j_flop_flip"
- self:set_sprites(self.config.center)
- end
- end
- end
-
-
if self:get_card_fusion() ~= nil then
self.ability.fusion = self.ability.fusion or {}
local my_fusion = self:get_card_fusion()
self.fusion_cost = my_fusion.cost
- if self:can_fuse_card() and not self.ability.fusion.jiggle then
+ if self:can_fuse_card() and not self.ability.fusion.jiggle then
juice_card_until(self, function(card) return (card:can_fuse_card()) end, true)
self.ability.fusion.jiggle = true
end
-
- if not self:can_fuse_card() and self.ability.fusion.jiggle then
+
+ if not self:can_fuse_card() and self.ability.fusion.jiggle then
self.ability.fusion.jiggle = false
end
end
@@ -476,7 +467,7 @@ function Card:remove_from_deck(from_debuff)
G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls - 1
calculate_reroll_cost(true)
end
-
+
if self.ability.name == 'Flip-Flop' then
if self.ability.extra.side == "mult" then
G.hand:change_size(-self.ability.extra.hands)
@@ -502,17 +493,6 @@ function new_round()
calculate_reroll_cost(true)
end
-
-local calculate_dollar_bonusref = Card.calculate_dollar_bonus
-function Card:calculate_dollar_bonus()
- if self.ability.set == "Joker" then
- if self.ability.name == 'Golden Egg' then
- return self.ability.extra.dollars
- end
- end
- return calculate_dollar_bonusref(self)
-end
-
-- local shatterref = Card.shatter
-- function Card:shatter()
-- G.E_MANAGER:add_event(Event({
@@ -526,7 +506,7 @@ end
-- end
-- return true end)
-- }))
-
+
-- shatterref(self)
-- end
@@ -534,897 +514,3 @@ end
-
-function SMODS.INIT.FusionJokers()
- local mod_id = "FusionJokers"
- local mod_obj = SMODS.findModByID(mod_id)
-
- table.insert(G.P_JOKER_RARITY_POOLS, {})
- table.insert(G.C.RARITY, HEX("F7D762"))
-
- loc_colour("mult", nil)
- G.ARGS.LOC_COLOURS["fusion"] = G.C.RARITY[5]
-
-
-
- local diamond_bard_def = {
- name = "Diamond Bard",
- text = {
- "Played cards with {C:diamonds}Diamond{} suit give",
- "{C:money}$#1#{}, as well as {C:mult}+#2#{} Mult for every ",
- "{C:money}$#3#{} you have when scored",
- "{C:inactive}(#4# + #5#)"
- }
- }
-
- local diamond_bard = SMODS.Joker:new("Diamond Bard", "diamond_bard", {extra = {
- money_threshold = 20, mult = 4, money = 1, joker1 = "j_greedy_joker", joker2 = "j_rough_gem"
- }}, { x = 0, y = 0 }, diamond_bard_def, rarity.key, 12, true, false, true, true)
- SMODS.Sprite:new("j_diamond_bard", mod_obj.path, "j_diamond_bard.png", 71, 95, "asset_atli"):register();
- diamond_bard:register()
-
- function SMODS.Jokers.j_diamond_bard.loc_def(card)
- return {card.ability.extra.money, card.ability.extra.mult, card.ability.extra.money_threshold,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_diamond_bard.calculate(card, context)
- if context.individual and context.cardarea == G.play and
- context.other_card:is_suit('Diamonds') then
- G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + to_big(card.ability.extra.money)
- G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)}))
- return {
- dollars = card.ability.extra.money,
- mult = card.ability.extra.mult * (1 + math.floor(to_number(G.GAME.dollars) / card.ability.extra.money_threshold)),
- card = card
- }
- end
- end
-
-
-
- local heart_paladin_def = {
- name = "Heart Paladin",
- text = {
- "Played cards with {C:hearts}Heart{} suit give",
- "{X:mult,C:white}X#1#{} Mult when scored.",
- "{C:green}#2# in #3#{} chance to re-trigger",
- "{C:inactive}(#4# + #5#)"
- }
- }
-
- local heart_paladin = SMODS.Joker:new("Heart Paladin", "heart_paladin", {extra = {
- odds = 3, Xmult = 1.5, joker1 = "j_lusty_joker", joker2 = "j_bloodstone"
- }}, { x = 0, y = 0 }, heart_paladin_def, rarity.key, 12, true, false, true, true)
- SMODS.Sprite:new("j_heart_paladin", mod_obj.path, "j_heart_paladin.png", 71, 95, "asset_atli"):register();
- heart_paladin:register()
-
- function SMODS.Jokers.j_heart_paladin.loc_def(card)
- return {card.ability.extra.Xmult, ''..(G.GAME and G.GAME.probabilities.normal or 1), card.ability.extra.odds,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_heart_paladin.calculate(card, context)
- if context.individual and context.cardarea == G.play and
- context.other_card:is_suit('Hearts') then
- return {
- x_mult = card.ability.extra.Xmult,
- card = card
- }
- end
-
- if context.repetition and context.cardarea == G.play and
- context.other_card:is_suit('Hearts') then
- if pseudorandom('heart_paladin') < G.GAME.probabilities.normal/card.ability.extra.odds then
- return {
- message = localize('k_again_ex'),
- repetitions = 1,
- card = card
- }
- end
- end
- end
-
-
-
- local spade_archer_def = {
- name = "Spade Archer",
- text = {
- "Played cards with {C:spades}Spade{} suit give",
- "{C:chips}+#1#{} Chips when scored. Gains {C:chips}+#2#{} ",
- "chips when 5 {C:spades}Spades{} are played",
- "{C:inactive}(#3# + #4#)"
- }
- }
-
- local spade_archer = SMODS.Joker:new("Spade Archer", "spade_archer", {extra = {
- chips = 50, chip_mod = 10, joker1 = "j_wrathful_joker", joker2 = "j_arrowhead"
- }}, { x = 0, y = 0 }, spade_archer_def, rarity.key, 12, true, false, true, true)
- SMODS.Sprite:new("j_spade_archer", mod_obj.path, "j_spade_archer.png", 71, 95, "asset_atli"):register();
- spade_archer:register()
-
- function SMODS.Jokers.j_spade_archer.loc_def(card)
- return {card.ability.extra.chips, card.ability.extra.chip_mod,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_spade_archer.calculate(card, context)
- if context.individual and context.cardarea == G.play and
- context.other_card:is_suit('Spades') then
- return {
- chips = card.ability.extra.chips,
- card = card
- }
- end
-
- if context.before and context.cardarea == G.jokers then
- local spades = 0
- for k, v in ipairs(context.scoring_hand) do
- if v:is_suit('Spades') then
- spades = spades + 1
- end
- end
- if spades == 5 then
- card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_mod
- return {
- message = localize('k_upgrade_ex'),
- colour = G.C.CHIPS,
- card = card
- }
- end
- end
- end
-
-
-
- local club_wizard_def = {
- name = "Club Wizard",
- text = {
- "Played cards with {C:clubs}Club{} suit",
- "give {C:mult}+#1#{} Mult when scored",
- "{C:inactive}(#2# + #3#)"
- }
- }
-
- local club_wizard = SMODS.Joker:new("Club Wizard", "club_wizard", {extra = {
- mult = 24, joker1 = "j_gluttenous_joker", joker2 = "j_onyx_agate"
- }}, { x = 0, y = 0 }, club_wizard_def, rarity.key, 12, true, false, true, true)
- SMODS.Sprite:new("j_club_wizard", mod_obj.path, "j_club_wizard.png", 71, 95, "asset_atli"):register();
- club_wizard:register()
-
- function SMODS.Jokers.j_club_wizard.loc_def(card)
- return {card.ability.extra.mult,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_club_wizard.calculate(card, context)
- if context.individual and context.cardarea == G.play and
- context.other_card:is_suit('Clubs') then
- return {
- mult = card.ability.extra.mult,
- card = card
- }
- end
- end
-
-
-
- local big_bang_def = {
- name = "Big Bang",
- text = {
- "{X:mult,C:white} X#1# {} Mult per the number",
- "of times {C:attention}poker hand{} has been played",
- "plus the level of the {C:attention}poker hand{}.",
- "{C:inactive}(#2# + #3#)"
-
- }
- }
-
- local big_bang = SMODS.Joker:new("Big Bang", "big_bang", {extra = {
- Xmult = 0.1, joker1 = "j_supernova", joker2 = "j_constellation"
- }}, { x = 0, y = 0 }, big_bang_def, rarity.key, 11, true, false, true, true)
- SMODS.Sprite:new("j_big_bang", mod_obj.path, "j_big_bang.png", 71, 95, "asset_atli"):register();
- big_bang:register()
-
- function SMODS.Jokers.j_big_bang.loc_def(card)
- return {card.ability.extra.Xmult,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_big_bang.calculate(card, context)
- if context.cardarea == G.jokers and context.joker_main and context.scoring_name then
- local mult_val = 1 + card.ability.extra.Xmult * (G.GAME.hands[context.scoring_name].level + G.GAME.hands[context.scoring_name].played)
- return {
- message = localize{type='variable',key='a_xmult',vars={mult_val}},
- Xmult_mod = mult_val
- }
- end
- end
-
-
-
- local dynamic_duo_def = {
- name = "Dynamic Duo",
- text = {
- "Played {C:attention}number{} cards give {C:mult}+#1#{} Mult ",
- "and {C:chips}+#2#{} Chips when scored.",
- "{C:inactive}(#3# + #4#)"
-
- }
- }
-
- local dynamic_duo = SMODS.Joker:new("Dynamic Duo", "dynamic_duo", {extra = {
- mult = 4, chips = 30, joker1 = "j_even_steven", joker2 = "j_odd_todd"
- }}, { x = 0, y = 0 }, dynamic_duo_def, rarity.key, 8, true, false, true, true)
- SMODS.Sprite:new("j_dynamic_duo", mod_obj.path, "j_dynamic_duo.png", 71, 95, "asset_atli"):register();
- dynamic_duo:register()
-
- function SMODS.Jokers.j_dynamic_duo.loc_def(card)
- return {card.ability.extra.mult, card.ability.extra.chips,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_dynamic_duo.calculate(card, context)
- if context.individual and context.cardarea == G.play and
- not context.other_card:is_face() and not SMODS.has_no_rank(context.other_card) then
- return {
- mult = card.ability.extra.mult,
- chips = card.ability.extra.chips,
- card = card
- }
- end
- end
-
- local collectible_chaos_card_def = {
- name = "Collectible Chaos Card",
- text = {
- "{C:mult}+#1#{} Mult per {C:attention}reroll{} in the shop.",
- "{C:attention}#2#{} free {C:green}Reroll{} per shop",
- "{C:inactive}(Currently {C:mult}+#3#{C:inactive} Mult)",
- "{C:inactive}(#4# + #5#)"
-
- }
- }
-
- local collectible_chaos_card = SMODS.Joker:new("Collectible Chaos Card", "collectible_chaos_card", {extra = {
- per_reroll = 2, free = 1, joker1 = "j_chaos", joker2 = "j_flash"
- }, mult = 0}, { x = 0, y = 0 }, collectible_chaos_card_def, rarity.key, 9, true, false, true, true)
- SMODS.Sprite:new("j_collectible_chaos_card", mod_obj.path, "j_collectible_chaos_card.png", 71, 95, "asset_atli"):register();
- collectible_chaos_card:register()
-
- function SMODS.Jokers.j_collectible_chaos_card.loc_def(card)
- return {card.ability.extra.per_reroll, card.ability.extra.free, card.ability.mult,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_collectible_chaos_card.calculate(card, context)
- if context.reroll_shop and not context.blueprint then
- card.ability.mult = card.ability.mult + card.ability.extra.per_reroll
- G.E_MANAGER:add_event(Event({
- func = (function()
- card_eval_status_text(card, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_mult', vars = {card.ability.mult}}, colour = G.C.MULT})
- return true
- end)}))
- end
-
- if context.cardarea == G.jokers and card.ability.mult > 0 and context.joker_main then
- return {
- message = localize{type='variable',key='a_mult',vars={card.ability.mult}},
- mult_mod = card.ability.mult
- }
- end
- end
-
-
-
- local flip_flop_hand_def = {
- name = "Flip-Flop",
- text = {
- "{C:attention}+#1#{} hand size. {C:red}+#2#{} Mult",
- "{C:attention}Flips{} after each blind",
- "{C:inactive}(#3# + #4#)"
-
- }
- }
-
- local flip_flop_discard_def = {
- name = "Flip-Flop",
- text = {
- "{C:red}+#1#{} discard. {C:chips}+#2#{} Chips",
- "{C:attention}Flips{} after each blind",
- "{C:inactive}(#3# + #4#)"
-
- }
- }
-
- local flip_flop = SMODS.Joker:new("Flip-Flop", "flip_flop", {extra = {
- hands = 2, discards = 2, mult = 8, chips = 50, side = "mult", joker1 = "j_juggler", joker2 = "j_drunkard"
- }}, { x = 0, y = 0 }, flip_flop_hand_def, rarity.key, 9, true, false, false, true)
- SMODS.Sprite:new("j_flip_flop", mod_obj.path, "j_flip_flop.png", 71, 95, "asset_atli"):register();
- SMODS.Sprite:new("j_flop_flip", mod_obj.path, "j_flop_flip.png", 71, 95, "asset_atli"):register();
- flip_flop:register()
-
- G.localization.descriptions["Joker"]["j_flip_flop_chips"] = flip_flop_discard_def
- G.localization.descriptions["Joker"]["j_flip_flop_mult"] = flip_flop_hand_def
-
-
- function SMODS.Jokers.j_flip_flop.loc_def(card)
- if card.ability.extra.side == "mult" then
- return {card.ability.extra.hands, card.ability.extra.mult,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- else
- return {card.ability.extra.discards, card.ability.extra.chips,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
- end
-
- function SMODS.Jokers.j_flip_flop.calculate(card, context)
- if context.end_of_round and not context.blueprint and not context.repetition and not context.individual then
- if card.ability.extra.side == "mult" then
- G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false,
- func = function()
- card.ability.extra.side = "chips"
- G.localization.descriptions["Joker"]["j_flip_flop"] = G.localization.descriptions["Joker"]["j_flip_flop_chips"]
- card:juice_up(1, 1)
- card.config.center.atlas = "j_flop_flip"
- card:set_sprites(card.config.center)
-
- return true; end}))
-
- G.hand:change_size(-card.ability.extra.hands)
- G.GAME.round_resets.discards = G.GAME.round_resets.discards + card.ability.extra.discards
- ease_discard(card.ability.extra.discards)
-
- return {
- message = localize('k_flipped_ex'),
- colour = G.C.CHIPS
- }
- else
- G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false,
- func = function()
- card.ability.extra.side = "mult"
- G.localization.descriptions["Joker"]["j_flip_flop"] = G.localization.descriptions["Joker"]["j_flip_flop_mult"]
- card:juice_up(1, 1)
- card.config.center.atlas = "j_flip_flop"
- card:set_sprites(card.config.center)
-
- return true; end}))
-
- G.hand:change_size(card.ability.extra.hands)
- G.GAME.round_resets.discards = G.GAME.round_resets.discards - card.ability.extra.discards
- ease_discard(-card.ability.extra.discards)
-
- return {
- message = localize('k_flipped_ex'),
- colour = G.C.MULT
- }
- end
-
- end
-
- if context.cardarea == G.jokers and context.joker_main then
- if card.ability.extra.side == "mult" then
- return {
- message = localize{type='variable',key='a_mult',vars={card.ability.extra.mult}},
- mult_mod = card.ability.extra.mult,
- colour = G.C.MULT
- }
- else
- return {
- message = localize{type='variable',key='a_chips',vars={card.ability.extra.chips}},
- chip_mod = card.ability.extra.chips,
- colour = G.C.CHIPS
- }
- end
-
- end
- end
-
-
-
- local royal_decree_def = {
- name = "Royal Decree",
- text = {
- "Played {C:attention}face{} cards give {C:money}$#1#{} when scored.",
- "Each {C:attention}face{} card held in hand",
- "at end of round gives {C:money}$#1#{}",
- "{C:inactive}(#2# + #3#)"
-
- }
- }
-
- local royal_decree = SMODS.Joker:new("Royal Decree", "royal_decree", {extra = {
- dollars = 2, joker1 = "j_business", joker2 = "j_reserved_parking"
- }, mult = 0}, { x = 0, y = 0 }, royal_decree_def, rarity.key, 10, true, false, true, true)
- SMODS.Sprite:new("j_royal_decree", mod_obj.path, "j_royal_decree.png", 71, 95, "asset_atli"):register();
- royal_decree:register()
-
- function SMODS.Jokers.j_royal_decree.loc_def(card)
- return {card.ability.extra.dollars,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_royal_decree.calculate(card, context)
- if context.end_of_round and context.individual then
- if context.cardarea == G.hand and context.other_card:is_face() then
- return {
- h_dollars = 2,
- card = card
- }
- end
- end
-
- if context.cardarea == G.play and context.individual and context.other_card:is_face() then
- G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + 2
- G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)}))
- return {
- dollars = 2,
- card = card
- }
-
- end
- end
-
-
-
- local dementia_joker_def = {
- name = "Dementia Joker",
- text = {
- "{C:mult}+#1#{} Mult for each {C:attention}Joker{} card.",
- "{C:green}#2# in #3#{} chance to {C:attention}clone{} if ",
- "not {C:dark_edition}Negative{} after you beat a blind",
- "{C:inactive}(Currently {C:mult}+#4#{C:inactive} Mult)",
- "{C:inactive}(#5# + #6#)"
-
- }
- }
-
- local dementia_joker = SMODS.Joker:new("Dementia Joker", "dementia_joker", {extra = {
- mult = 3, odds = 3, joker1 = "j_abstract", joker2 = "j_riff_raff"
- }, mult = 0}, { x = 0, y = 0 }, dementia_joker_def, rarity.key, 8, true, false, true, true)
- SMODS.Sprite:new("j_dementia_joker", mod_obj.path, "j_dementia_joker.png", 71, 95, "asset_atli"):register();
- dementia_joker:register()
-
- function SMODS.Jokers.j_dementia_joker.loc_def(card)
- return {card.ability.extra.mult, ''..(G.GAME and G.GAME.probabilities.normal or 1), card.ability.extra.odds,
- (G.jokers and G.jokers.cards and #G.jokers.cards or 0)*card.ability.extra.mult,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_dementia_joker.calculate(card, context)
- if context.end_of_round and not context.blueprint and not context.repetition and not context.individual then
- if pseudorandom('dementia_joker') < G.GAME.probabilities.normal/card.ability.extra.odds
- and not (card.edition and card.edition.negative) then
- local card = copy_card(card, nil, nil, nil, card.edition and card.edition.negative)
- card:set_edition({negative = true}, true)
- card:add_to_deck()
- G.jokers:emplace(card)
- return {
- message = localize('k_copied_ex'),
- colour = G.C.DARK_EDITION
- }
- end
- end
-
- if context.cardarea == G.jokers and context.joker_main 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*card.ability.extra.mult}},
- mult_mod = x*card.ability.extra.mult
- }
- end
- end
-
-
-
- local golden_egg_def = {
- name = "Golden Egg",
- text = {
- "Gains {C:money}$#1#{} of {C:attention}sell value{}",
- " at end of round.",
- " Earn {C:money}$#1#{} at end of round",
- "{C:inactive}(#2# + #3#)"
-
- }
- }
-
- local golden_egg = SMODS.Joker:new("Golden Egg", "golden_egg", {extra = {
- dollars = 4, joker1 = "j_egg", joker2 = "j_golden"
- }, mult = 0}, { x = 0, y = 0 }, golden_egg_def, rarity.key, 10, true, false, false, true)
- SMODS.Sprite:new("j_golden_egg", mod_obj.path, "j_golden_egg.png", 71, 95, "asset_atli"):register();
- golden_egg:register()
-
- function SMODS.Jokers.j_golden_egg.loc_def(card)
- return {card.ability.extra.dollars,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_golden_egg.calculate(card, context)
- if context.end_of_round and not context.blueprint and not context.repetition and not context.individual then
- card.ability.extra_value = card.ability.extra_value + card.ability.extra.dollars
- card:set_cost()
- return {
- message = localize('k_val_up'),
- colour = G.C.MONEY
- }
- end
- end
-
-
-
- local flag_bearer_def = {
- name = "Flag Bearer",
- text = {
- "{C:mult}+#1#{} Mult per hand played, {C:mult}-#2#{} Mult",
- "per discard. Mult is multiplied by",
- " remaining {C:attention}discards{}",
- "{C:inactive}(Currently {C:mult}+#3#{C:inactive} Mult)",
- "{C:inactive}(#4# + #5#)"
-
- }
- }
-
- local flag_bearer = SMODS.Joker:new("Flag Bearer", "flag_bearer", {extra = {
- hand_add = 1, discard_sub = 1, joker1 = "j_banner", joker2 = "j_green_joker"
- }, mult = 0}, { x = 0, y = 0 }, flag_bearer_def, rarity.key, 9, true, false, false, true)
- SMODS.Sprite:new("j_flag_bearer", mod_obj.path, "j_flag_bearer.png", 71, 95, "asset_atli"):register();
- flag_bearer:register()
-
- function SMODS.Jokers.j_flag_bearer.loc_def(card)
- return {card.ability.extra.hand_add, card.ability.extra.discard_sub, card.ability.mult * (G.GAME.current_round.discards_left or 0),
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_flag_bearer.calculate(card, context)
- if context.discard and not context.blueprint and context.other_card == context.full_hand[#context.full_hand] then
- local prev_mult = card.ability.mult
- card.ability.mult = math.max(0, card.ability.mult - card.ability.extra.discard_sub)
- if card.ability.mult ~= prev_mult then
- return {
- message = localize{type='variable',key='a_mult_minus',vars={card.ability.extra.discard_sub}},
- colour = G.C.RED,
- card = card
- }
- end
- end
-
- if context.cardarea == G.jokers and context.before then
- if not context.blueprint then
- card.ability.mult = card.ability.mult + card.ability.extra.hand_add
- return {
- card = card,
- message = localize{type='variable',key='a_mult',vars={card.ability.extra.hand_add}}
- }
- end
- end
-
- if context.cardarea == G.jokers and context.joker_main then
- local mult = card.ability.mult * G.GAME.current_round.discards_left
- return {
- message = localize{type='variable',key='a_mult',vars={mult}},
- mult_mod = mult
- }
- end
- end
-
-
- local uncanny_face_def = {
- name = "Uncanny Face",
- text = {
- "Played {C:attention}face{} cards give {C:chips}+#1#{} Chips and",
- "{C:mult}+#2#{} Mult for every {C:attention}face{} card",
- " in the scoring hand",
- "{C:inactive}(#3# + #4#)"
-
- }
- }
-
- local uncanny_face = SMODS.Joker:new("Uncanny Face", "uncanny_face", {extra = {
- chips = 15, mult = 2, joker1 = "j_scary_face", joker2 = "j_smiley"
- }}, { x = 0, y = 0 }, uncanny_face_def, rarity.key, 8, true, false, true, true)
- SMODS.Sprite:new("j_uncanny_face", mod_obj.path, "j_uncanny_face.png", 71, 95, "asset_atli"):register();
- uncanny_face:register()
-
- function SMODS.Jokers.j_uncanny_face.loc_def(card)
- return {card.ability.extra.chips, card.ability.extra.mult,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_uncanny_face.calculate(card, context)
- if context.individual and context.cardarea == G.play and
- context.other_card:is_face() then
- local faces = 0
- for k, v in ipairs(context.scoring_hand) do
- if v:is_face() then
- faces = faces + 1
- end
- end
- return {
- mult = card.ability.extra.mult * faces,
- chips = card.ability.extra.chips * faces,
- card = card
- }
- end
- end
-
-
- local commercial_driver_def = {
- name = "Commercial Driver",
- text = {
- "{X:mult,C:white} X#1# {} Mult per consecutive hand",
- "played with a scoring {C:attention}enhanced{} card",
- "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)",
- "{C:inactive}(#3# + #4#)"
- }
- }
-
- local commercial_driver = SMODS.Joker:new("Commercial Driver", "commercial_driver", {extra = {
- bonus = 0.25, total = 1, joker1 = "j_ride_the_bus", joker2 = "j_drivers_license"
- }}, { x = 0, y = 0 }, commercial_driver_def, rarity.key, 8, true, false, true, true)
- SMODS.Sprite:new("j_commercial_driver", mod_obj.path, "j_commercial_driver.png", 71, 95, "asset_atli"):register();
- commercial_driver:register()
-
- function SMODS.Jokers.j_commercial_driver.loc_def(card)
- return {card.ability.extra.bonus, card.ability.extra.total,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_commercial_driver.calculate(card, context)
- if context.before and context.cardarea == G.jokers then
- local enhanced = false
- for i = 1, #context.scoring_hand do
- if context.scoring_hand[i].config.center ~= G.P_CENTERS.c_base then enhanced = true end
- end
- if not enhanced then
- local last_mult = card.ability.extra.total
- card.ability.extra.total = 1
- if last_mult > 0 then
- return {
- card = card,
- message = localize('k_reset')
- }
- end
- else
- card.ability.extra.total = card.ability.extra.total + card.ability.extra.bonus
- end
- end
-
- if context.cardarea == G.jokers and context.joker_main then
- return {
- message = localize{type='variable',key='a_xmult',vars={card.ability.extra.total}},
- Xmult_mod = card.ability.extra.total
- }
- end
- end
-
-
- local camping_trip_def = {
- name = "Camping Trip",
- text = {
- "Played {C:attention}cards{} permanently gains",
- "{C:chips}+#1#{} Chips when scored",
- "({C:chips}+#2#{} on the final hand)",
- "Your final hand triggers twice",
- "{C:inactive}(#3# + #4#)"
- }
- }
-
- local camping_trip = SMODS.Joker:new("Camping Trip", "camping_trip", {extra = {
- bonus_base = 5, bonus_final = 10, joker1 = "j_hiker", joker2 = "j_dusk"
- }}, { x = 0, y = 0 }, camping_trip_def, rarity.key, 10, true, false, true, true)
- SMODS.Sprite:new("j_camping_trip", mod_obj.path, "j_camping_trip.png", 71, 95, "asset_atli"):register();
- camping_trip:register()
-
- function SMODS.Jokers.j_camping_trip.loc_def(card)
- return {card.ability.extra.bonus_base, card.ability.extra.bonus_final,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_camping_trip.calculate(card, context)
- if context.individual and context.cardarea == G.play then
- context.other_card.ability.perma_bonus = context.other_card.ability.perma_bonus or 0
- if G.GAME.current_round.hands_left == 0 then
- context.other_card.ability.perma_bonus = context.other_card.ability.perma_bonus + card.ability.extra.bonus_final
- else
- context.other_card.ability.perma_bonus = context.other_card.ability.perma_bonus + card.ability.extra.bonus_base
- end
-
- return {
- extra = {message = localize('k_upgrade_ex'), colour = G.C.CHIPS},
- colour = G.C.CHIPS,
- card = card
- }
- end
-
- if context.repetition and context.cardarea == G.play and G.GAME.current_round.hands_left == 0 then
- return {
- message = localize('k_again_ex'),
- repetitions = 1,
- card = card
- }
- end
- end
-
-
- ----- SixSuits collab !!!!! ------------------
- ----------------------------------------------
-
- if SMODS.INIT.SixSuit then
-
- local star_oracle_def = {
- name = "Star Oracle",
- text = {
- "{C:attention}+2{} consumable slots.",
- "{C:green}#1# in #2#{} chance for played cards",
- " with {C:stars}Star{} suit to create a",
- "random {C:spectral}Spectral{} card when scored",
- "{C:inactive}(#3# + #4#)"
-
- }
- }
-
- local star_oracle = SMODS.Joker:new("Star Oracle", "star_oracle", {extra = {
- odds = 10, slots = 2, joker1 = "j_envious_joker", joker2 = "j_star_ruby"
- }}, { x = 0, y = 0 }, star_oracle_def, rarity.key, 12, true, false, true, true)
- SMODS.Sprite:new("j_star_oracle", mod_obj.path, "j_star_oracle.png", 71, 95, "asset_atli"):register();
- star_oracle:register()
-
- function SMODS.Jokers.j_star_oracle.loc_def(card)
- return { '' .. (G.GAME and G.GAME.probabilities.normal or 1), card.ability.extra.odds,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_star_oracle.calculate(card, context)
- if context.individual and
- context.cardarea == G.play and
- context.other_card:is_suit('Stars') and
- #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit and
- pseudorandom('starruby') < G.GAME.probabilities.normal / card.ability.extra.odds 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, 'ruby')
- _card:add_to_deck()
- G.consumeables:emplace(_card)
- G.GAME.consumeable_buffer = 0
- return true
- end)
- }))
- card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil,
- { message = localize('k_plus_spectral'), colour = G.C.SECONDARY_SET.Spectral })
- return {}
- end
- end
-
-
-
- local moon_marauder_def = {
- name = "Moon Marauder",
- text = {
- "{C:green}#1# in #2#{} chance for played cards with",
- "{C:moons}Moon{} suit to become {C:attention}Glass{} Cards.",
- "played {C:moons}Moon{} {C:attention}Glass{} cards never shatter",
- "{C:inactive}(#3# + #4#)"
-
- }
- }
-
- local moon_marauder = SMODS.Joker:new("Moon Marauder", "moon_marauder", {extra = {
- odds = 3, joker1 = "j_slothful_joker", joker2 = "j_rainbow_moonstone"
- }}, { x = 0, y = 0 }, moon_marauder_def, rarity.key, 12, true, false, true, true)
- SMODS.Sprite:new("j_moon_marauder", mod_obj.path, "j_moon_marauder.png", 71, 95, "asset_atli"):register();
- moon_marauder:register()
-
- function SMODS.Jokers.j_moon_marauder.loc_def(card)
- return { '' .. (G.GAME and G.GAME.probabilities.normal or 1), card.ability.extra.odds,
- localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'},
- localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'}}
- end
-
- function SMODS.Jokers.j_moon_marauder.calculate(card, context)
- if context.before and (context.cardarea == G.jokers) then
- local moons = {}
- for _, v in ipairs(context.full_hand) do
- if v:is_suit('Moons') and not (v.ability.name == 'Glass Card') and pseudorandom('moon_marauder') < G.GAME.probabilities.normal / card.ability.extra.odds then
- moons[#moons + 1] = v
- v:set_ability(G.P_CENTERS.m_glass, nil, true)
- G.E_MANAGER:add_event(Event({
- func = function()
- v:juice_up()
- return true
- end
- }))
- end
- end
- if #moons > 0 then
- return {
- message = localize('k_glass'),
- colour = G.C.SECONDARY_SET.Enhanced,
- card = context.blueprint_card or card
- }
- end
- end
-
- if context.remove_playing_cards and not context.blueprint then
- -- G.E_MANAGER:add_event(Event({
- -- trigger = 'after',
- -- delay = 1,
- -- func = function()
- -- sendDebugMessage(tostring(#context.removed))
- -- for k, v in ipairs(context.removed) do
- -- sendDebugMessage(tostring(v.shattered))
- -- if v.shattered then
- -- local _card = Card(G.play.T.x, G.play.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS.c_base, {playing_card = G.playing_card})
-
- -- _card = copy_card(v, _card, nil, G.playing_card)
- -- _card:start_materialize({G.C.SECONDARY_SET.Enhanced})
- -- G.deck:emplace(_card)
-
- -- G.E_MANAGER:add_event(Event({
- -- func = function()
- -- card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil,
- -- { message = localize('k_in_tact_ex'), colour = G.C.SECONDARY_SET.edition })
- -- return true
- -- end
- -- }))
- -- end
- -- end
- -- end
- -- }))
- sendDebugMessage(tostring(#context.removed))
- for k, v in ipairs(context.removed) do
- sendDebugMessage(tostring(v.shattered))
- if v.shattered then
- local _card = Card(G.play.T.x, G.play.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS.c_base, {playing_card = G.playing_card})
-
- G.playing_card = (G.playing_card and G.playing_card + 1) or 1
- _card = copy_card(v, _card, nil, G.playing_card)
- _card:start_materialize({G.C.SECONDARY_SET.Enhanced})
- G.deck:emplace(_card)
- table.insert(G.playing_cards, _card)
-
- G.E_MANAGER:add_event(Event({
- func = function()
- card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil,
- { message = localize('k_in_tact_ex'), colour = G.C.SECONDARY_SET.edition })
- return true
- end
- }))
- end
- end
- end
- end
-
- FusionJokers.fusions:add_fusion("j_envious_joker", nil, false, "j_star_ruby", nil, false, "j_star_oracle", 12)
- FusionJokers.fusions:add_fusion("j_slothful_joker", nil, false, "j_rainbow_moonstone", nil, false, "j_moon_marauder", 12)
- end
-
- ----------------------------------------------
- ----------------------------------------------
-
-end
-
-----------------------------------------------
-------------MOD CODE END----------------------
diff --git a/mod/assets/1x/j_flip_flop.png b/mod/assets/1x/j_flip_flop.png
index 2919b84ced4aeaa5b27bf0b2becaef28dc031301..65156730f41d4cbf94ca8f2530e605bda806df79 100644
GIT binary patch
literal 23470
zcmV(#K;*xPP)bTf>+LmeZlb? zdd9(W3+Q26cN||#mS|s}DxO<=ox@!VGyDt?PkX_jf6sxM9~l}TkT^E&?ELV}8dca_ zT{VR%HDkxYixrI%P@$AZhQ#nGhffTa=F8?|Qr@B+2Oyq?Vy*b42)65|VwNQ2W1 z#Zf914d|sGeuTq+g$<4@(S!1yb2uGNJwyrwO%5XVsXIT}*?bxW#M(-Mb{vRv+z*o` z2z_B>SYl_((PXVf(2yyf;QXFbiTV^sgJEP^RDM9098IeQf&+tN245#VaI`?u$Wg$J z36#;yE8D@DQ<)Ol{L4ayAfT#};*#z@a_~#4aY}>JN5wGc%pqvQk)2^_$6;~OCI^*O z3*pP_&X$u2s }pz!#LqaYrUX*VCJD@Nu;WybC5|;PQyWfI ztL>bI;e>*Fj*1&+fEEnX7~OJOt;2y#0>#drql%R?{
XBw28XimaMPG5ykaTw0g3te!!w6RV3&=bxR7gOYH tL9Z!)2l*)|e@`LlN6O!K{)4{1{{R^$J?gOfX5#<=002ovPDHLkV1iL$WfuSd diff --git a/mod/assets/2x/j_flip_flop.png b/mod/assets/2x/j_flip_flop.png index 3933296a23a9984dfaa0a314d0e816314cea7227..3d609a6c58447154244cd59db3b19fdb0cbba520 100644 GIT binary patch literal 23688 zcmV(%K;plNP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+NHf)w&gaiZTqiM>>`L1pT&_#s !B%;z`z(F03GZ9{D1H9KmYSTp~M)Elxr)!l#{ JV6*-QV^C#UxHr}*pF&-YrN zJNj+){r~&U_U>oqDehEQ>hkqa|2*RU6F `SK3iBN2 z!`~zH5ZSIbq%gxB-mvz+M;P2 dvNjXCn=gRcW->_ooG zRoNT7jLk|ZV?Q-DZ0OEcPC4h2Yi_ycyIdueTuP}$P`v9^(@}FRwboX9z1!7N%dNE9 zTI=oZv0s2@?xok>dhhqmXWm@-=C^Nt;J%;uTu*xP@sy`N?di`wFrSe|9%a ;vQgr9sv$IFMB1djAyJs`FW9(pB zA?7#yvv)`Q?5I2U|7+ilnts{0_`lt`!>#+5JNM_leYb1VFf{g#eZ0^`Jukd(<+?(t zd{%o#e$O^}7}ltsBZqv9*mJ%xkE`ETXtA=m{j5EVT%YuE0e<3s&%$S%#B;y$EWXin zoASIX^|5+C{6-$FzHH6p3Gz&VWt=gOIrwb6FSI$ 0YrsiAYB(AP8L z^E`K4BjmnD?Ox{n@k|Ej{Z#vz_{iz!+~pbJ@xRk~x8r)(+xZ6%))squ$I@A_HnA^u z^6oX3@RT;%`C{;GPB!x-2G?trr}GnUYj2qcH+jYUu;Crh3S)*oE^LRDWCdP~q@~F2 zu$wn4f^E%oSL}h^pL}v=* d!=gcsd&<)dlI db}E!PY4fm+s^{m-mDYs>1!wE&sUric}DhBfn1V#qlEc*jVA+pYHmrqX=RRlF3N zc(3_lEbV#=c7MX)LK _>TW zdjozGfS)Us#s)7)-#KbD%7;f1ci~wz%u(Xg)6+Gg`{6$iaPUf#tCZ9tV3k{s7$o2q zt3cZ-*QxKFLwe6wgMHW=Hg)y4V!|ulZN@r|=j!E|tl-=(_pjXIC$9(xd&joEgPpn3 zz+kV|^4lL!yuMoXjWs8H|K z;zOZx^S;^Z(kB))dIwsL9I@u08?MAozE7^A(kes TbbkZLkI#s zYJ3AI6IpD$raez9vE6L{J+Ob_a>W2Z<_(t-tH^8YwfV73zb+D(4e9d-Ixc>LTNA*l zZ@d?v$X|1fI7`x?MKLH!=(U#Ba9-uhh+i9Y{QDikRo}rsBOrq}-vi$d&jH5wrS&9T z@QeiR1wz)F+u@PVT jzQj@Lb0{f7Ovk`hi=`gN@g_v*nl$8J-> zY=O`FSQ#TGSlk7&_9WOBZa?mI6RwPd=exExy1?A|vMzZ8|Ji?g_~Vaz{62=2Q1DaY zV?M8XV}yeMU4>|(N?ZZqS6M6^5$eH{ls5t9Y*C$~&R)3AQ+tWMzeRAAf&$qOfu|2h z1(6B5f#K9+h3jpABlp4{Uk}prs&l><7)xyLPz^r%Z3*d^u=7a7043`sQH08XQv~!D z4lY&+tVDy6aF94*5Ri$7{WI>MNP0tAl+B1CJuL4QmIO6C4v1IfX~ zr}S}#nn2eGc3-t#Cw_i)RjuIO1M#B|&@4V}aa)^T<*^JzU;xi^KoK7FFgyB|#;QOC zh%`i7U=aAf`$K4Xt^xKv5UuBLbmQ23 57sU|9}LW4osyxo%IIaWtUNwD(DQ)l zfP$fC0z6@Dz+TJMwO$<(q*{j`!(H`Df^y$}j{N2Y%_eN&f^B%ii66rNt`}On?)xRs z*IOp^gmd+)=HmkS?#>_Y9j@6FP`$E*MB5slpK0Rz{=*UPYr#b>m;z$G^YhPrj3@Qr z^-t&$=v{KZWNQtv3*fShv2Df$_`@SUa0|L%*C*VAkiA{|Js>Nq@llv9-jC Rp4@n2HZ00B3p)R6uYXt+rM4=w2$~@6CFVU=w zf(fU05Z$;DBisELazKO^DYOz!+lV$b6RIFRJp9D@&&dO$IEh^^)CQzK3s-mp%$6l% zkCi|Zc7%E7>zzFwgiL|eBmq#x#)kxPxu7-aQqx>R3VaV%HiPEG+_NAXW(PTQ=VC}M zgwQ;o2oYl3P#hRzmW$!QY%yljUfm9d2i+1|!!OMaS0pgNnA)}Y5*PqDt$skZb6yXA z1V1{Tu7n`y=8fxUaky2w7P}62W4T#bILAE)daboP0#O6a-pu;V{HEC;zY*RXwH;*G zxJ$W^T6cwq;`bd>iQ8cdMuKwUsR%AuI=gs1&pO_~`hp)s`-V4whOnD4-i{+>KqB${ zZLjiJMkBH2mWo4PZ?Fb0#eq&3+X}yNtl#Z*59Y91GaGRcA1UJEsY9Cp6|%Hzw>9 z!?>S(BNuUNwy(pFN+tyM_`uHK4}^soKpCFwZB^ib+g H5V65B--jJ#B?{UVzQV6&w09z^T$nLVc&WP*D2T>9k 7$~w pF=`^{g01GQ41|%7IK2c_D$%3rDGV4FV~jVENe>;3Y>OW`=H} z?0v@dB!Fx1+z_ec-2%N4ySd`qj 7!TBk0Oi6$hKLWWJAaoJ z`prVNO$~{apdXl>!DieVOa>!^76XBqDFfWt)1x53polX!+k#6DaSy-7J@>Uhajtgk z%Y9wzE-WNaxVReL8()`G3IX9~jmp@#2i*5F ?15z9xHqW zDtwE0pT*W=^(TQfy)MKc8h%YvsVvT;kTaS5CYFl@MMYny4uid)sYXTWTXTfH-r+v* z1=a`dbj{OH#E+x;BJR%(;X}`>5N7d_qz_>@UklEXp)>g8<}7Nz`W$y0kaf0}6@$~Y zhN@fn86C%9qX~*^VY>(X2n~7jTzF{ H$Bi2?n$2d_(V};|bBAlmJJ=&g4B$RrU 2vZCh|(v3N8l27%j)#Y7)LzJ3Cu>)@o)+t*$YoSiNW0bz}4>0 zH?@dgzYUi1128D)(kDZ9{LX!_M)hz1&==@MHryg7E=&t|eTl<3v~(To1*gCh5$n*$ zUX;aYwgjR^m?rwLLO>%=Cc`Jnn&u{aL7Pz?$%BS>vc(mea$XQ#T%^vFUfBK%;(~@N zKsERfVtlRrSrrFH7}mLn@^BR$xZN*A7OsYdcv6$rjCruM{0f*zuvx(9t><1iKjDK# z069iE;S-~6u8wGa@IXWzi(H<-cfmbRA>d8eEgN51qy>bPEA@u9VPp5ABGoZ+l==!V z7MTXTmgj!n3in2Uyb7&!lpzeC`uJO9awotG^NKj2LKp!P(V>W-h9C1KASDwmZnj41 zr*Sue`@z3QGONKpU^~R%)`AhXv|eQGIyC0T?cs`Qk@SAx0~z)Z)DZXv#zPGRW}z)g z0D(0?F0t_J37CyKu;t8_J;Y2{MpXr}!0Cn6KoAqROhk>5NDEc(y`SJrxe6HCP0y8x zj>kzZxjCVq$UYOHGU21ENL4!k5P6mYxx(!ZwJW@vy}pc#Cgj?UemD`T#Y{xW&2-uT zLJCm+s%uf-IO2L>TzFVu7vBT@4d24*h+t8DlL-fGTsR4kg!&AWUc^JtwE;XRCAM`5 zxCx>SFJ*P1we>(E0;+_`jHV&RBJQ|d7(Vz6+Lsqk=q8y65JPPT87*fmS*?rsfc#&k zkPf{7ZdtL1kpk{K9&dGE&LAeC;4O&|X8xv{<3>0l*)pI)bmqfvASB?Z2YL`OBTLd2;qDES$XVqb;mG~21LjXeVsmp48Nt2@grZVd3@rPFGqFAJ za^M&ei+n(c5|0|}a<-w>9zb8bQ6JbCoceh^!{h-Pwx&G-+jo+_FHn(nH>rRQl_0^( zZ#b#hFv9PFlg@g>YEy@Vai1)2LrLP|ZJGjj($u8$!&(Iwkig8%LI6BS Gv3=?SPe z%O5^Jp+O>J_|*xi%~=$xpJSCd%)u_$6rPOI=IeZEJ~4q<7Z`{1*eS!EFg$+B7-H_& zKZL<#eS08lk7xm_=w~ro++s|yCiW?-Fe>tyU>$C8|9HXN+Dw&l`7$+4i7bI>z)1^t z32 fl;AgHoEo~-3gjD i9g%8;g+a!r2g;}3Y-R63+gR^YOs#PGGY5qJaPkRu~0Sxc`CmH+!Iu~ zYwLt}!sO~H_Q|>zOtkI{%#FQgY2+I4r3lfQd?p^jFFcRA;0juF7QypI)|^1dmw}_k zr< @qq`MN%~p)c#b>c6I1NVB{P7hmTKqANsQ( zn{Psa=SA^}u#s~lHY$dYWLZ!!Q){3B90`d5cBPwWOlU@i$G3#*5(@`+0ethZR<%F` z4pidp&a&`Ci4r3q49Z0itS;6k-1!AQ(n;iA<$P}TZwu83Q5_}+5dkpu1I9yug$(k% zSWm}F4F#E9g$JNM+7mnU=?0lQUV}_d3;KziM@+X Tm#c`hKy30}=p14CV<;h*zi>^c(gE=NRlJ zpNY&ob2)eUhqqTk91VKb51+q-evx1Y!_F~gPyi5NZ}Qe9wVSB*!M&lHUx^mL>p8}m z-*pa^0tUGxJP-wd9y(t} uUjDIqj<^w*tOg{4~n+ZKconZ+G?QKu^K1v#217g0- ze*%6@WnOtYWIW4Tkx>aD3lB`NztgiKe9A1ghnWw6z-~eb?q*&wYwJsNMOdUAs6FR^ zBaKO9WRYX-4IoGE;uK(Rvhe44fe@$#(G9U|er6Oa5j4pBAYqAGkma>76^y)Kj@%V0 zfd2tkv8n jJ(9;MS1vhzV2opfQ0q=5{n>j0d z~D>>VZu2p&NCz84&qAjaIGQOuW-GRyGi^8x)CLW zj3(c=ILqWQEBayrAOz4Td6A1E%-SN-!rLdIBA_eA>|C7qf9kowINOh}p8P0&ghi*D zFf;B-@Ot47EK+&6hj#=bEq4m^BGS%m%*zDZh<)_eY<1Uh2_P8RBxpgHRJ8cmPM7fE zEPOKK31)Xy&)(PONf=1_a$lz4db!hObn(DwUOU6@xdepPG%h}bc&Wq**6skB796o) zX#5mg#xFp3!1u8pwiU$#g@VZS3rI$!!3|LbxIC;Vs3WoSl}<35m=8Hd(T|-DM~Y&W z=CVK{Xb$j+>E0#7tvxnETK5NpLX1|7w#*C37~+9UMNr&CA`E<(q{d|NbRr_u;6wt% z7L1Ky7;V`yc{xe}#Di(w`~cfFucM-zOv20?M8_vQ)W_RqO$4_~we}HKZ1@B`?_gyE zETEX51f^C2hVhXD5e_pojqqfE ddV~ewOrHUAP-h-#H1L2uD#mQ6;$tQn@aIv{V%S`Pr#wMM!Md^C5lt2G z$19=^a_l7#YuK5)L894!8~1oVDF?#E0WGh%vD~!Os@Lzjnq;Nag1h~5%)axVKMvZ> zE%W!4z-6FRgcM>QY!=sXk+6B7 wwJnry5#oY178jw1)x-*fWQfH{yi3(`tOsN$31Gvdfkz*&Vto^Vvji4sy{Gj= z`Ha?0I|GXBpOLsX5FF4#pb!8s5pm@sbc1kt&^6cv22ac&AoPmtlc|850NiR`0_i 4%)NF>5U0Qq
GrE;dsz{7t?8k2pqMY4a>s%UsatV0RFf3dEM*L+=-JBMG(Bm zuZ9tT_6Q>kL*@t~G3-4$mDe&DdxS`h(Vp<7yoUu9L!+Wr>iD7C;qs{m_(@nTPx3 z3r}ZZ`#Z~g0M-~@z=$v5Qtu9Bpx=dNTm(!&`MCB;2cOjVMtE>@HrCTot_i3jOY4rl zu$g*!fYf2C+-uB9)pZlQI(xc!G(0{)uitbQ2p2jQ8T#B%*u-O=R(Zkm%{HJ6o`!>= z>L)VnxtE6tFl3m0IRLdg4z7;nv9t5TS@CVtKCc-bB5TFbAq?hh2w5zR2WKX~3w{Lp zvGm7z86=)Ak4FU0om(cNW>4fYiUP}tt_*jFjNPH$EUL#?cr-YNBP=e2EIW;|#X~ZT zc_1}bzanfKUJ34=W?+|9n9cgbwejh~kZK@&Ky=`55uTk1^`2Nl^Fc&Z;?{@wEAcfL z@R8P=mjxcQ!80F^oQKqh07HO?FER=#+K^6wRqf_(F+*0Iz2dSB2Li5jNhMV`iQI|N zFc2u+odY*S(D%T6nLR$CZXQH%TRcB(3iysFyD>9-na~Wr;htp?M{q|Z0J^?3(=SN| zi{vmDHV!NH*gn7()Hjk_zQ%RmQy=7i8r49_d2B7y+j~i1cuZCyuPtvpiTxGU6T)KY z-nhBVti%&cyKz6V+@@Uv ##&2(KcPT@|$_;-26HYGv)@M#-jj_pki+3kO>itYVnbk&QfHUPcxY zy6jj$%%A|SeMZaUd2m=a5&nk-Yxngoun}a&V5dwZSm{%-9`@N2dQU~+bI8GA7=J1z zG(CLB6)rr%vdaC(`|M~DmODbCwj_Csp*LYY05uEiGZ_Ji!E`+lQ5dk$4; j z`u>#jI72dBx~wv*j|XbFX@qNF4G2B7Y Xw>&jNRG>?%NUj}O-r_F5r z{a8?rYTIdOt`ARrEcoS-0YVftPW!kO5pG@X6M`5cib96UPXba8Y#MI+M8d*Awx{IL zE6!onsv2xS!mHUDBM6p}z`u7%61wF($^(SS)3kZZPS4~i2Q)BV)v_TEDZ%R-$7oi` z9=oy}%RbZ4QJ^JoT_h#)s+e3bi@VegCdGmF=QL3PnDY$lRrWwW`QJgjD@fseY>$;o z9PbB0J57W_+Fvx2=L1vifkhZ>G65?P`!93Nx5WleI%YnxGON0-Eu^8-E1Q;vG(fJ| z5~N(}rh=@c#ZV!(h!g1bB!Y^Z#Qe7$)7+RkoLHK7CZ}v`#mqGwMJQWOs61iJkfvJ- z(Qird0;jIntf!9kI6*q(A?y?wR)?}Do*4eE__TgxyiE$YsS?EuYvDpXD2oau;A%I% z!dg8$L;Y=ndLz9|=bx (8A1+u?k`#-j30Z(OK;2 Pjd&0>>@99{->Q16q ibT{R94OnS_Ev zp +E3 z76>m_+k1vn3S{@TUkUnp6GgdwL?9Y5+L($RugmkUY|F>M`vEiJvxiO*x%FJ$nxqH^ zs;wxB2wI!3J%(AJ1-{oMJCHHUmIsE#7msGNI^V~ncemk!#YowBk9WVG+QM6W0+dJn z@a^&Bs9~UFdF&>aXwNS7EXgVm9z0o@LKy0@ZxG &eC{7fZTk* z8OO6qBQ2aq&nu=<(_`n+3!xihS17-i1?Q!q0Rj|C!N>=(!t5~dvwIr-yvKhj_JH%@ z!x{SIseoFhcJ#-vB_?~W@LD)rJ0Dp;olsa%K>Z^w0r=-D%05(H6wre@#VWIzd>w z(;Lh OA;GBy=rW+r?qW+B34y* zavKt;X(N1Zpw=#9bY14Yc7-aogjuot*b0w)T4Emg>#8thtoyMT6nw|{&0k}&d8Oxo zH{L37@EB+DV6<5dyo$KU^1;Qc=eqc=M+XWae*aT5UYaM}xAl$vfUBGcI-<^*kuJH# zmXL&DH?pByvRTp7&BHFBj<1zo1JuX$yCsGz@1Dw|v9Ulj3eIAohu<&OLh-cVzB&HA z+|@Kr;y0|Z3}-^qcwFwCCdd}+fL=4bM(hF>> !1{o7p0681+E}c;cAB1|biE>H *Yo9+}ETz`oZ?BwciC#eJk`sSGLytq!ud? 1SwX-SjxR10q&a+)aw(DA&naKlid82_;F~v)z&F1OCN| zYv3%;jceD~?o>~-hq-2rjnDGh7aTIYu1zA8p_eY}P>cZV^XgVf!8-9!_!HWU&Ej6} z#N7}lUNjzD2ky!59UzsdbD-G>O+0;Ul1OzocA{GzPxwGr+i^f;J2YRsZ=d5>v2Gi2 z8WmqNH3(e2+pHThDT3wEgK3@=6M$<%G9XY0 6z!{*z(Jnl; zG}z@Wu!A19qksn2?q7kmpRbA9B~yk}y1P(Ei9eQcn}?j{aP+eTs PFBu4#e zaWuw_Ftzgmznl>~B6#7dAFQi)vK)m_NmQ}I_AU?*C{Hk~+S$T|Bw2)c)1cW+d6a4g zPI|>IUhm4sBE1~e3SIWM2GJi#N>K`nkMS>kS>0-;dbx7%y2Ht0U+mb8AW4?QKVj#@ zYQG1# $~!JG&%kQFJ4;!Zq_QyB;x_ (s pl|58KU zD;n<;X`ws)>p 8h6wwJ?wJn23yjwtp5NHos6+eyH;;^CUP+5s s z%j1av|DU@I!*lT+FOO(JqBWNUMk_*+Y;F#7MUWa?X;(e;5U)_qbQWm#@=TN1W8X1? zreaN=W+gUsT1q^$eCV?k^mjiSBtbD@#5|=^mOyyOV4X1dJ?(^gaXKvLeTZw&W%Ho6 zfm}L!v3~tMJ(B>KqSOFE)I79(223Fk0`kstX9Ei`?}pa{`+zg;$Z4V1SLB51nfk(# z(j-Xv3k$IWuNiiKLHM)HP~8IB$TQ7;lqjAP!n>l;>;-Fd%Y%St$X>7>8)6#aBEvev z%TxxSf7(uH5hFKvrFqzL&%cqrrUdNj;v)eVplIOpC>Ap>7i)9jeM|R({uVRK&2)fO zFKXxm2LezF!Lr!v7*I&d_+?k_wbjxC=AW(|W`(+oGH^mk-_1+NrAwhwk2@nDtMx?0 z> &!RiTDWM-D@&jI}eSUEDYd{b%P@q;NZbIXFBa$=QXFJT0-Y>kZ<+}&VvwPq{ ziTdG*PCn4UtGC)Vje^M^mMHdWZjnF_C6ETqd_Gw0d7t|rVdDfM9p$-9+;=m#I5!dk zlS%M8gxwLWWJmUajCwbqGqy-Z@&aPST!LkUN$!a%eBT4^QanFHy52cjT0Pi>qdrUY zQ)uq0nHz=uSiJ}$Dr7Nx({cBl&=3@VHrIb&2|WkKOe-ielm%AX@o8%_X6wl!HdX|8 z>qGt2Evb9(G>FB50D7w7_ND>fG;Iy}4Qp4z97LXA_{?}R{)6MZW?3&M9w5VbfC$b2 z+e9`Np(@8rL__ba$eYV_tch`D=@ZvHr+PV=m3+-F07zw*K@sl*%3p$9EzN!|V9LxS z)akPE_O|4%9~Q;4gxOj?4TVtp#%uR{RO@3+W+%_0ZR;YmG(?E~M9>91@g1i6(Ln96 zxCCdh=>!{_5i0tcZMlOjfu0*Y@kGZP(LIJC(q!AKEj3y?Fpi0zAhV_;Hg?Sh()3-E zfSU+1SGUeC{fM4X1u3P(#Mx*&LyDy;5H*wvkrq92Ckz<<;fFX~N~(QL)V!(5;#n(C zJO&E8I%5Q8`x;<~9XrGDb_X;ZpZMuQ*Ajn;pW*$!O+a;eDy?@tyw^uoVcB-)%!mo3 ze$LUb->73`{h#0R(DnVAW$}m7{0g1+9vt8FUD`})OZP8Lng1Ex!MC9g)*oFao|Jp7 zWK?#u|HejFH-CZJ#84+g5D~DvE`r izc!I6akeDc^N`dyT!G-BB(wmC^~WbXq$u^U zjpG6QQG X}C!AUZyKogPQ1x># zZVzBQx7Y&|Y(_wZB!j@RF^dJriycOTto7Jju+8pB*f@T5$_=c!u%?aY^w6{0G)lAt zr<#3#+Kby(FiGcdO?xvHH|)T9c!B_~AXUuEhkD}Py)4kG0N+Y#qI4f-a4c(?5C@Oo zoL5q9qegq$m);MFhv_CGU9v;F*%NYsk`}TC%^*}cTKPelwSq?%55dq`HU}5XSqae#x0- vpMxB-IiY `Alfz>j={AG>NbSE8rFdgqA zQ$>kF4Vy*N*TGit#pw-MCtqI&v{ !-&7TkAV$!WuZ@4D9W= zl8N@++7G|EZE$79SSK*B4965$;1M2+3hf#Ta{9~Kx#3VL0uerOq5I)UQC*qO*YgIv z@NQ7hTFh#c-tOzN<3bj{EPmY80YDvQEDzoq2tB-@$DRRviJ ^>~kFOgiZe{lKP|GX|jFi z{F}sitW&MQDKV;)=)jWEtQQ)=gtmRaK^9ss@TObU(M%x`i>+s}q6jNWF!`7rbaf~w z>=4{jrmACp%>U(L-K1@oSSt&5q9gY4o9A_3Fn)Pp>)~xY(JY76t+=Z_SdW<~J`za) zuZicAELq02Pc<;Y>m6S>E_gtL?E2}1tZ9G$>h|ohfs-h2Hsl>nfgx;wiU^cF=i!~^ z%`HK%Fvu$n%nLdMiMEbkG5;PcY_{}K_jvehGtHKc5NH9)0zVufp%xZ#(4#*C*RqBm zRaS{Twzj=7--j_CrZR20SJim-V|Vs>b!&ZWDzY!h`bahrY8xfL4vUDMGWUS6gzMZ# zhnROer|p*OV1xzjrq|HYOIm2xQVAtQHV)I{UWrc2841MLwR?p?G{O;gmmQ(ui9<-( zBc#(hF7}yQoj{|KgblU2=jzDUE(bCTZ0Zr7|00aS;Rzq!fQ$p6c#6IFo>q(i`b@{9 z*#wnL(6Jj<7h)Wmg+~d!7I
-S*0uI#Es7COp+&5yLpK7L49WJi}{ l4lS zLhtiDveg&}9Z%{L0Qm%UwtM~V2?s1NG7qsJ(S@ElsAcwD01cMo*CFk;$m8s6uqRK& z339^ 5L0nEV zvQS{OlnirsHDKr41BhraF9n;VKG?!=Usi3!J);WjHF?l#KyYf*9&UI0&BPO1HsQp; zgoNJeE1a@51$x1b;0G-a`?vA_00Xhr5gl$PoMk!|vFwR w2@Kq+4@1Z_x# z)v||^E!GZS*nC7LJ4Tf!!?!)XdEqaJ3Bs(Bx0$D^4yCx`DzOpj9PT)l0rLGQX$O%w z)^1bsJ+TE0usn{3b4mq#6#4%PBe$ncEWae=$Dc<%^6_O*OV3X8o6362+?`~Qr}c>C zyQBb(>Ie)T|ALMDcS3%Gf>u?2+IWBI;(d1c@5b@dBcJcS4_g|gc^2#unq_g8wq}EE zPlST;m>k|?f1JH0ML*tVveapA;Q?j93^V@Os#AXEB!2lgCr%*w@vy#vB8q83l42xZ zHs`h@77xc8Bt%&WE bZG5b@z+h?)YP?`@sCyoF6P71k_7#3E4* z7PrRd+{OJju}&Xn5u)h<3uD3Wz=f8L@r3ye298X*qwOorvs)a8xHGLTTxVOi&sI!4 zdYbXtp$dTdob5fPq1K86qKl(<;~qKIEfHNWF!^v@@1xtWZ7rf{mH`3uSi_77)X&jd zhj7ft*L_ZJYd5CT?UlbA8g-$FLr0$NF$$kbGW_TSbHG0TNWihAvm75*Vfw*pyY;-n zzX_#!?_B9%qZ0IYIAPL>Gm)EysZAS?Ek?5R(UCj}X@GO}4uNASh+qJIM`J=Wo;^-- zWTis2IW^xr^XdNpa|`S(Au>T3>apHxDKD_P=i9oPe5YB&?{jJ!PO2Ic)rOHma4v$~ z+og}gK6t sa%ViaD7=~53 Hy-v zvv~S3xJQ=s!tU2lEZcyFGe*zGv2h+BfIHY8;#0PU7XsQG^y47}abVgJka9GqeW5_> zEl)0X)Z!D?h28j#qd$f8BYPgIGUzZJCtP|Q2-C3@$?+8!$MW zJf>w5B^@s?*RE${g0-)RoZV}A5!tQ VRJvu-6z{Xp}NW(7NZcejFK0Cr8lvUJAN?{o5v zxjU9D!?yY)l{0 0w*dH?3`c7^}J;J+I;^F`tB^B%TS z5ur~b5|H-;^iw`Bdjhb$PUMQ#) =?rsFvH{|6tKG>haFsY;YFAAr2GQH-t_x)g7Oo4wR~uB z0f55BaTx27>peUe0k%~jn3}%eB)x%#+k TR+!7M@@#-g?jD&y=did?3gax&6GjO74%l4Sd9h|*|NU&zH z*LGeK3+FWye+R3y?!P#3pgaG{5eJqm*iCDp>V~E0WLaAotfR%=d&{TAuLzzBA$K4O zmIF70MjW2)BK49{;mLM2KYQ#jI YV zZG_H?`>&@5pNW;b%Q(f?q}&T#eC!Sm@TauT!r|o2T=(1up9lW*1^pANz^RH=qK>JM z$P(oVHLYihmz<@u%T5vAtO$!_BEsTIV%`xw3dq$F5f21in0D${G8xCp^cHT%)Cwrg z=@ym*z?hO{hK^u+Z*^NGt^tLM2SS(hR|na8!u=a4;jv#_;3S4&AvyAL*uXBwu%&i= z3h6CtIm$kB%!GnZ6(+F8cAp iv+tpi^fnN1;+{~S# zMGl@&IDO@IL|IK9jaM|SlRPZh&oDP0!Y-HT_ye&X )#fIePR6Z--@~%mHK|tgx^(g`R$GJj`lpVvuxR9);bR8ij$yGKP-yPhn7XK z)U3oV_`IXXOc{g^(JERSyV`OXIGBAt*0%sOHYqwS%fdMy))~|mA^BzjHW?NLgZ1S1 z3W79&XAc~+NzRGhH=x%ZYx8cE<#MwAW#GkVOh??sc+bK>(7?j#yiMRCg^}~~ex{%x z#R*5xr=+brAoo6bPUq}5D;l!ZWftao?tq=&yD3q4bx_6%cGEf7%5g65u{jJO%N{Ea z*`ZF&V&mw@_HM!rPVC?SXAHBCj_13ZhrFKl?^MZUG3`MNOOU^gBDi <>a*eM%>MgJ-V pcA)8&vGXs)H_E8}6= z8NU1sY`++sEw%S>BzLfl&xyk_u=6t5rcXNzD|p-A(jnH<$zFsf5&t%^4ZpP$2mk`{ z@7qz_L~c6_hVA8O1q-m9krZvy4W3ols0j7LQgP7c1Vq!6+rYwJuzP1)-p7j6U1(&I z3_uB(#0ipsb!Axe#Y%-t$Obz?Ad-WV7G*?-cv`BQj4te)**JT%5rywrWGCGD9 !`(tyC`W}`M9njuR#GaK|H~b-`1)pKxZ+o3=1D+1ExZZ6BFbsVi-Z|_@JZ%0z zEAtOv>+ -hEhS7BgvBlC{EXcc^c1;l)eQkyk^RZ|eTyD00?!zt5 zhV51j^E1@_Izjmw8&IpnM=23uEEU`R2~x#Sx+4lK8kJgI7EyQ@;Uu?eu^Vgm#8>MD zkJ_&GVgDSxs;B{XZ%0Ca >1hz_t?6gQly92Zmpn1 %`WV;5wc z4k>dU)y;JeA?|q{?Bv^r9F^qJ879hK^HXi-5at!QDn2_*Ai~BRk#RZJVV{9Q2aebP z)yH#JyETHdh4eSz0e M$WFNmaSrC9wNTBPAC4y3OEYLUV-HS@pCxj6P tTyxkdO7JQ3m zD_aMH!7n`9_p)I2%h|k! ~B z 5{yn$H20ngvm37hL_0dMu0pHLDBK@2m^ZuS>F#6QMzEm) zo*kr{(b>w*Xd@aq2R>RZ4O#9)k=?meU{f&Ca6?dTI5#20Y8KGep`mQ#c}!5+k&X5n zuG>+&*Ys3zOs7=(9;Qkt@L UnM?E&<6 z-KxnqcOa+%2W#Jni~00zP0^X_D4YB`yYoFV=-Z^Bh*?VnEWu8eT2FYbbH?Cro1(Do zJ&AdHKn?)9-X+H}Xy6GV DfV_90-FXE9~uG5S|-<^JsWo}lX6#ZlPvWVr_ z8nAjDBMa@&6K7s{1_*8TkjU~uCw*Q h!U)>YJCZH1H4T?*)YaG ZgR3y9j0{?08 #WnPZ7530vrYNwOt z^q77N&GUmXY#;f&bkND^9wFKEq2|F#mJ>TZGxfNmssySQY!W<9$Ms&_p&5u_E8Z`s zbvR+8Lb;>ko$yItz*Y9)F(?J4Y>q5kVdfxpRY=?GYN0a3#xdl;+oujK?m4X8_enU{ zYyrPS*4Lpe>^)#YI0~&f-P)w5S#RQd+#JVIK{l3ExZcPR2%;__Z|81dwZsaKm~Wx9 zIL{xy_AGIFm~~m11~522wkU1SWoLj#ujZDVDQpXO-h&v%*kdg`8G(1AvVG?TCXV;F z;VU&R@z{YdPPv~u7iiw+9S)q;+Q)F<*5&&oz^eVKHKN$D(8j~}0GPIU?TC*cgfzXK z)iW)1oG(Pt&!KHw1?-ZAt3+Foiw*Cg9f~pMlsAtI2x^wupcNc~?Ob^@)cgA%rA^sd zNY=C{HD<-k7{nym#$04CjairsX0w$gOLjv@(I9oBvR|Q6mdKVU+$3ZqOZFv_rM@5P z-rGID??3mP-}k>e=X}n*m*;ss&+~depZEE^&-r|w0YU3}34syEj@%Q2BpDS-OLBH- zvJFij%w&bJ>{-GQDkWxl;meWwRE<^%`A~1oG@Tvd3#Qiht~Pz~&2bPF!qq)a)h{^3 zFioayFrA$PXbrxnVRw7Kk=cxY|FbvXzSnLyGH);-TKuI+`?r_5F%p9PN=u3*~S4 zl~4=L`QsM?Wy_~CL#Azib=D y$T3&Y#n-E7?IvXZya>8&+sRj$6)a?y9=_8r5NIST1H3a< !=<>7Hm}n0aw^0(b^cz<=Pi}#Ay^WfvY1UR~sWZp!^X@#k z%^ZH!Cu>DZ*kQ+;%PCtv_Q<_#$g8GoJSS^9t0{dw=j-uPFV 0evxn~U z%fgbx!TFE2KGj(?z2WOyx{g wWe%j$Ydo4;Jme=9-|Z7Y4Hew3^fYw>&w z{=u*3Y~F9arftcaG*m*wE)}Ck6WS58lil*pHd;AB?_quiY@%K|ouW=(d6d+P(l|&z zvohZz(Bw7x!0PkD%5#+e^{vvz&X&@-D_wzy*|EI!X@2t6LF;%LSC;NlTBcF5I#r?? zBEm@K`to;)Uy56M^S=d@r---sp+mp Z1*BG72J~t1FN>)G22vX2Lo!96WpF>g XD{HyKFp~Sc2t(K(xO{1oy zvirjN5)no#UR93+haq^sv0tVN+K61KCthE;r4Q&QaCPs>?~Q!guS{|YnA3VavEV=Z zY9i;OS TY9>KJbba#ecjH^&Z||;*a;VT@0-@*`sIaAqBhen zZgqu%wU-<&hIblE*QUl9TNI3bgpvl){<=rR#`liVrQ#*_ye#+aIqZqJn LoYw~=hN>bJruAWD2rHa$MaoLNC8%|mZ6w_`u?h2|w?c<1jP5i9@?24bCO{>qc z!;C+QME4N10?MC+&~P|{0S@;^wG*Jm3D57c=E>?~GS3{^4E2 0iwCVkQj)Otiep z9t3aLyt$?*lK8epx~A=VNtJi{H7mn-Lti|W+PWb^K3V0$a_xg*cpcmak&vb|7;(vQ z({tIJMB^CmNYuS^m;ts;?5SG2=wd??T2I0gXncoNQZk;s+u*3<7Dd7OI~mbJ^cvdl z28D5%D a}l;u}td>T)+&WazL~&IU}C*=0k~eFyZmAM1$f_l;iHclw5n7jKeO zM@s`$Iq?nMm$HS=4kmm$Zx 6>^Tp?~XQvwCj2o^5As^}rcx&HsZxmQx zdaNa-!_GxMOY~UiBf}ohrm$l Vf)%Io(NiGzQf+NL==BBAQSyrK_KqG4^TB({qO&B &pdT0#m~7MY4MJAUE^1klq|bmnjv7zo76%S*)zq2kVR zg22#dGz1EVz~Nv(0?hVt;}E@pmkal;LVU+KPGOT+GzN#}?xwJcNpy7g;Ako;0`m%g z_~*(nG5HhTjs1fKfDec_kpY3JKq0QKke@Z!96e6} uwF;r#3fp#CTB-=zPDeN7mUGBLp%cPDwQx@T})Q*qTkhU`wFkuhscG#o)9 ztCHYgM-mzMFc*ea1rx~#A{dEuR6{~3NEnht`3cIvjm;stktnNB0JsVbz(J@|NJs<> z33gOR!NEu(90f*09m!y_qa%_8RfVgnJCc5aFlEtztR&KZ_G%T13_ww#P&9(5Mgddd zR5BQ;4rGU;8UhK1QAs2s3=M<9)KF_sWD@3tJIj>_EGNyC=tO}q+?>`XRtd-G5DYXG z;VRI-MhJ8whYBcYDjL(=JiPy!u%Nk8%sIqWHeu>WRhXJOObrcJMX5rOe+gMqSZp8@ zS21Bw6~uSk)n&l|!2rY(SMwAASknMv!QfaFBFCL&;qFe?R9tmQVO4W2y%n(E7v&_4 z4M_N`X8ezwH>WVa_rBi(blTdKg2GzbVu+;gM%YA83VF>Cp!a=> OUgJLjDgY z*foKlwgEuz`xvmj0J|0B&+Y05XR9>+4}U+_;(urXfd1FWKjQaay8fl>A2INcg#XR1 zf9d*14E!VEf3xfVjV__T4m=b$;3>!pIL?fkzmx-xLUIIS3q9b!qVD%^-@ciWoC2Fy zK)jXi?(UVFpcRKxz?4`p@NpGzz~z|X&4Jo%Z-DBZAOS}s{o|nU4YDVJ&KAZ=8#V|e zQoVW!)Vbdw1B0751}1u&J__y>Q<7x`E~$V(o3#y&>sWZd9Z!v5en4&0Q`&I*;?B4r zbApgzhB@KQk;^D8Z-XMw-{b9)vZ-%fKX;67Jb97dryby*ALg?3Zmt^6?xRclO*R^8 z??=dr_ LHKmZyWTryRHu|N~R4|RKb$B4$ewF zZ;A}o9`GIS@X)@_j4%FR^Ii^*JE2mA?(~08FY4zzd974bKWj*EcW6GUVJ@juZ(q8# z!-wkdda|SH;gx!3&7r6JP%}H*>aXZz2KT>~F3zDbTXBMoC G&Jr_h))b+(+bv3Zt^TMtvZ5w(v0(hODDNo)DM;Wf*Ax=NF$I~e`$ zIS!DFy#EW42fSR@+jmQHzfkh*QSVRUxtGj`Zh~blKV&GHYOJhFSr=wmU6phAlF=Ns zval&5HWF1lQXVA0YLz`D+3UA6Ery ziqL9$;#{^(#05LW`=p1P r z@t$u>M>%$3;B@s#{_!*$<{g=k1ElG&qF3A{MUzK)S(Eu$ZiMjzsHbc}t4vh}bp8P1 z0B_0Y5@Bf2S0ux;x;@(xZX6>4JB*jfOfGD#^WBNE2(7YQe71N+_#i5*{(+QaC2_3i zE$VoU=_UI_V&QhF=0Ig(fRd+-B-IeZl3#UW4!v<6hHb~`+>YxjW?-{-l9=3$^7vGR z+pUVRN&-Q~YKbxK#)Hi@DVgcJH|g(}8WKrqW}p2qCY^oA`@D&sw}?;o @)xOUgNQDDC&M%Ijo;AtUAk=pSYGG0uyouVHoB$9N c-1A)H`9MrUYrx!?}g3P`rMf~SVJZ=M^K+!DH?G8JCflz+7< zqQuav{7RGkE9+(Fqc4^wyMi9xEc7Pw_9yvNTF2yEh-UZL04>*KA11j#2wB i+2>f#&h9Zo;1Pc~Q>A zzuH9y6MW!P1;|gCO^;E6sL#Pms&_r2UaD-|8C98EniM_11w-?@8J#a20iS(uJ>pgr zom{88VPh=eDm`;TOFcU;8lI&j^%%rGmF~JFWlMx~e7-;bT7;YSLBtX6gACvBFZ)b% z-$m%{;Mk*|ha2eBmbDLyX 96n_&jv<9RAIv(`k3Z57`dl!@l7%^fN4_2sWDl5PLcmHdlNo z>9B4M9Az)K#m`6Lsq2PdH! sBJG4r&j)gQ9_nX!>Zd2Pd0Jj_xfhY76Dg|63 z9-dL-2%+3^d&tdJ!hUd>&~DA#n4lF5&2D+gjo@dKWNnk(0*`uM&|mpmb#2}_F(?pK zzPa__ZkeIIy~)CL?C1jJ9g(f|h^Mc7;`hybcvk0RPG!j)i5+n3_L+HPY%kb;h}|(- zGIP^$sA2uM^HE!&Fy`SeU_tKK^~Y(_=k01sLmrP@$*SJVrQBMtzI!;fZtwk#JCbAH zKNikN=o^NcG}{r(PQ}o@gv>9Dk63aSK|{Ow*t~nZ&0)kN+>vfn`A(jlM!>xwp|NX` z@R9=|*KFa4{*Yb0nF+ZYsJ XRpulbKJ;-|h(;DefP46FahQ?%>%Tda;a%e_YIdWYY^SgD)Gh eK0E3?Zcv`hit7fYY_GuPoyFyGOcfvL3@MSHonK?E_^>eMv!46Ssz)6j>f{bY*}M z>iCB?FH63N#vbdfg$K=^SOs>iAGTizQ^ wR5&!@I32;bRa{vGi!vFvd!vV){sAK>D224prK~#8N<(*+~+&BzG+r9LX z|No0m!x@^SBpYe2Kuq@mYfB@Ee2sV01pUw-AGhMJIzPS@N!(Hg!Ow5SmF}sd^c%UW z&YzQc2~B^069_$5=k@wWd`;*{I(jZgW0&FBq62LmDA>|NM< yMX=FAruS|?1(CRI_Llt((u5`0d*+MI(3)pS*a5`>qLtCPDv(0 zp>eI@^wz2Dlw>kcV0=#I{yMJV_Z6&U)KSP~pkUyCm9U$mGdk$t5U(r9)laDB!JI~& z*X!4>YoWXAxX_sln^n|T)GXJ54z8MRxWCRhdzmYp+L}67LLGGW56fk^TGiN`L^9WS zf(}~wH3Na1V$9aSObq0Xwu=5bQKXjR*spnye1;Ha>zUwh(BWU2u|^^6wr5qy6|nQE zI-DbanRPtbv8w 8$)ps|mC00j#jboRVn@9%6LI{sy+P6+LFkX*^!Uxx?S zjCbdEbVxq^Iqt55BHp5wqX1r^lbMB>YI3lDCYdfeYpMBR0e#OmT*%+XT*cjve~KPD zK+}U+2UlP&MhM|A2!(@O>sqdl&U`R*h-?PxItU@ID^5aB(8+fvbohf7)^P{wIzS4U zzf;FEvpC++>N-H;ubT7RHFwuRL*OID1AkZn8qPvKKhwF^y1ULfkb5^24EBvfGHddG zL~k854HO!fQwJzKgw%Cl2Op}#w)yU0PGlq{G|fWXV=e=QkJFin7T6&pQ(~sR1KT7N z4X#B<4;`XFgbsyV32V%}EwF8a`ePWdVkh*_(J+x^ya{&hg!1E3Fz~8ZLQm2Gs}Rnw z4=dL^7wV(qcW@>HRw3IYo}~kcK;fl-4(3$|*v5f2O*&^nch}i-t+NW@O1PK54q7R( z7rMKSeWit>L2clejo!FtLRlw-KK-!N$xt--HXRD(JMji=OR&RrRw15nX%_;hi*?rZ z5$L0X5$_;$6#O)!p~M^?=_*7e;6e^|%y-g9r*3qinq?ujtU| ued>tOiGV8-)nuVy8b!Hi^ z0|kSQIwT9JgP~|J3sFhiwvUQZ8V)+@_<;~ohw`x4d=_E~ti*vQb)~C+4qxhUqEm%{ z;=xWQQ200 $s361B};}4)eO&PY2)dIm+x?tUCFg35_h&ONXVts>4=D{2s)AJg;=q@y4~-I%ip; zAi-Y{^GfW?C;I8s1I}C;;7t!O){=O#&JGk=k zyqUk&eC0_x|L?) 0 and context.joker_main then + return { + message = localize{type='variable',key='a_mult',vars={card.ability.extra.mult}}, + mult_mod = card.ability.extra.mult + } + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/commercialdriver.lua b/mod/jokers/commercialdriver.lua new file mode 100644 index 0000000..45ed394 --- /dev/null +++ b/mod/jokers/commercialdriver.lua @@ -0,0 +1,70 @@ +SMODS.Atlas { + key = 'commercial_driver', + path = "j_commercial_driver.png", + px = 71, + py = 95 +} + +SMODS.Joker { + key = "commercial_driver", + name = "Commercial Driver", + atlas = 'commercial_driver', + pos = { + x = 0, + y = 0 + }, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + bonus = 0.25, + total = 1, + joker1 = "j_ride_the_bus", + joker2 = "j_drivers_license" + } + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + card.ability.extra.bonus, + card.ability.extra.total, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + } + end, + calculate = function(self, card, context) + if context.before and context.cardarea == G.jokers then + local enhanced = false + for i = 1, #context.scoring_hand do + if context.scoring_hand[i].config.center ~= G.P_CENTERS.c_base then enhanced = true end + end + if not enhanced then + local last_mult = card.ability.extra.total + card.ability.extra.total = 1 + if last_mult > 0 then + return { + card = card, + message = localize('k_reset') + } + end + else + card.ability.extra.total = card.ability.extra.total + card.ability.extra.bonus + end + end + + if context.cardarea == G.jokers and context.joker_main then + return { + message = localize{type='variable',key='a_xmult',vars={card.ability.extra.total}}, + Xmult_mod = card.ability.extra.total + } + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/dementiajoker.lua b/mod/jokers/dementiajoker.lua new file mode 100644 index 0000000..f046768 --- /dev/null +++ b/mod/jokers/dementiajoker.lua @@ -0,0 +1,70 @@ +SMODS.Atlas { + key = 'dementia_joker', + path = "j_dementia_joker.png", + px = 71, + py = 95 +} + +SMODS.Joker { + key = "dementia_joker", + name = "Dementia Joker", + atlas = 'dementia_joker', + pos = { + x = 0, + y = 0 + }, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + mult = 3, + odds = 3, + joker1 = "j_abstract", + joker2 = "j_riff_raff", + } + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + card.ability.extra.mult, + ''..(G.GAME and G.GAME.probabilities.normal or 1), card.ability.extra.odds, + (G.jokers and G.jokers.cards and #G.jokers.cards or 0)*card.ability.extra.mult, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + } + end, + calculate = function(self, card, context) + if context.end_of_round and not context.blueprint and not context.repetition and not context.individual then + if pseudorandom('dementia_joker') < G.GAME.probabilities.normal/card.ability.extra.odds + and not (card.edition and card.edition.negative) then + local card = copy_card(card, nil, nil, nil, card.edition and card.edition.negative) + card:set_edition({negative = true}, true) + card:add_to_deck() + G.jokers:emplace(card) + return { + message = localize('k_copied_ex'), + colour = G.C.DARK_EDITION + } + end + end + + if context.cardarea == G.jokers and context.joker_main 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*card.ability.extra.mult}}, + mult_mod = x*card.ability.extra.mult + } + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/diamondbard.lua b/mod/jokers/diamondbard.lua new file mode 100644 index 0000000..e23b0e3 --- /dev/null +++ b/mod/jokers/diamondbard.lua @@ -0,0 +1,57 @@ +SMODS.Atlas { + key = 'diamond_bard', + path = "j_diamond_bard.png", + px = 71, + py = 95 +} + +SMODS.Joker { + key = "diamond_bard", + name = "Diamond Bard", + atlas = 'diamond_bard', + pos = { + x = 0, + y = 0 + }, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + money_threshold = 20, + mult = 4, + money = 1, + joker1 = "j_greedy_joker", + joker2 = "j_rough_gem", + } + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + card.ability.extra.money, + card.ability.extra.mult, + card.ability.extra.money_threshold, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + } + end, + calculate = function(self, card, context) + if context.individual and context.cardarea == G.play and + context.other_card:is_suit('Diamonds') then + G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + to_big(card.ability.extra.money) + G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)})) + return { + dollars = card.ability.extra.money, + mult = card.ability.extra.mult * (1 + math.floor(to_number(G.GAME.dollars) / card.ability.extra.money_threshold)), + card = card + } + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/dynamicduo.lua b/mod/jokers/dynamicduo.lua new file mode 100644 index 0000000..3a64e4b --- /dev/null +++ b/mod/jokers/dynamicduo.lua @@ -0,0 +1,53 @@ +SMODS.Atlas { + key = 'dynamic_duo', + path = "j_dynamic_duo.png", + px = 71, + py = 95 +} + +SMODS.Joker { + key = "dynamic_duo", + name = "Dynamic Duo", + atlas = 'dynamic_duo', + pos = { + x = 0, + y = 0 + }, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + mult = 4, + chips = 30, + joker1 = "j_even_steven", + joker2 = "j_odd_todd" + } + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + card.ability.extra.mult, + card.ability.extra.chips, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + } + end, + calculate = function(self, card, context) + if context.individual and context.cardarea == G.play and + not context.other_card:is_face() and not SMODS.has_no_rank(context.other_card) then + return { + mult = card.ability.extra.mult, + chips = card.ability.extra.chips, + card = card + } + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/flagbearer.lua b/mod/jokers/flagbearer.lua new file mode 100644 index 0000000..51819e8 --- /dev/null +++ b/mod/jokers/flagbearer.lua @@ -0,0 +1,82 @@ +SMODS.Atlas { + key = 'flag_bearer', + path = "j_flag_bearer.png", + px = 71, + py = 95 +} + +SMODS.Joker { + key = "flag_bearer", + name = "Flag Bearer", + atlas = 'flag_bearer', + pos = { + x = 0, + y = 0 + }, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + hand_add = 1, + discard_sub = 1, + mult = 0, + joker1 = "j_banner", + joker2 = "j_green_joker" + } + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + card.ability.extra.hand_add, + card.ability.extra.discard_sub, + card.ability.extra.mult * (G.GAME.current_round.discards_left or 0), + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + } + end, + set_ability = function(self, card, initial, delay_sprites) + if card.ability.mult and (card.ability.extra.mult == 0) then + card.ability.extra.mult = card.ability.mult + card.ability.mult = nil + end + end, + calculate = function(self, card, context) + if context.discard and not context.blueprint and context.other_card == context.full_hand[#context.full_hand] then + local prev_mult = card.ability.extra.mult + card.ability.extra.mult = math.max(0, card.ability.extra.mult - card.ability.extra.discard_sub) + if card.ability.extra.mult ~= prev_mult then + return { + message = localize{type='variable',key='a_mult_minus',vars={card.ability.extra.discard_sub}}, + colour = G.C.RED, + card = card + } + end + end + + if context.cardarea == G.jokers and context.before then + if not context.blueprint then + card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.hand_add + return { + card = card, + message = localize{type='variable',key='a_mult',vars={card.ability.extra.hand_add}} + } + end + end + + if context.cardarea == G.jokers and context.joker_main then + local mult = card.ability.extra.mult * G.GAME.current_round.discards_left + return { + message = localize{type='variable',key='a_mult',vars={mult}}, + mult_mod = mult + } + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/flipflop.lua b/mod/jokers/flipflop.lua new file mode 100644 index 0000000..a3e42aa --- /dev/null +++ b/mod/jokers/flipflop.lua @@ -0,0 +1,135 @@ +SMODS.Atlas { + key = 'flip_flop', + path = "j_flip_flop.png", + px = 71, + py = 95 +} + +local flip = { + x = 0, + y = 0 +} + +local flop = { + x = 1, + y = 0 +} + +SMODS.Joker { + key = "flip_flop", + name = "Flip-Flop", + atlas = "flip_flop", + pos = flip, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + hands = 2, + discards = 2, + mult = 8, + chips = 50, + side = "mult", + joker1 = "j_juggler", + joker2 = "j_drunkard" + } + }, + loc_vars = function(self, info_queue, card) + local result = {} + if card.ability.extra.side == "mult" then + result = { + card.ability.extra.hands, + card.ability.extra.mult, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + else + result = { + card.ability.extra.discards, + card.ability.extra.chips, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + end + + return { + key = self.key.."_"..card.ability.extra.side, + vars = result + } + end, + set_ability = function(self, card, initial, delay_sprites) + local flipref = card.config.center + if card.ability.extra.side == "mult" then + flipref.pos = flip + card:set_sprites(flipref) + else + flipref.pos = flop + card:set_sprites(flipref) + end + end, + calculate = function(self, card, context) + local flipref = card.config.center + if context.end_of_round and not context.blueprint and not context.repetition and not context.individual then + if card.ability.extra.side == "mult" then + G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false, + func = function() + card.ability.extra.side = "chips" + card:juice_up(1, 1) + flipref.pos = flop + card:set_sprites(flipref) + + return true; end})) + + G.hand:change_size(-card.ability.extra.hands) + G.GAME.round_resets.discards = G.GAME.round_resets.discards + card.ability.extra.discards + ease_discard(card.ability.extra.discards) + + return { + message = localize('k_flipped_ex'), + colour = G.C.CHIPS + } + else + G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false, + func = function() + card.ability.extra.side = "mult" + card:juice_up(1, 1) + flipref.pos = flip + card:set_sprites(flipref) + + return true; end})) + + G.hand:change_size(card.ability.extra.hands) + G.GAME.round_resets.discards = G.GAME.round_resets.discards - card.ability.extra.discards + ease_discard(-card.ability.extra.discards) + + return { + message = localize('k_flipped_ex'), + colour = G.C.MULT + } + end + + end + + if context.cardarea == G.jokers and context.joker_main then + if card.ability.extra.side == "mult" then + return { + message = localize{type='variable',key='a_mult',vars={card.ability.extra.mult}}, + mult_mod = card.ability.extra.mult, + colour = G.C.MULT + } + else + return { + message = localize{type='variable',key='a_chips',vars={card.ability.extra.chips}}, + chip_mod = card.ability.extra.chips, + colour = G.C.CHIPS + } + end + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/goldenegg.lua b/mod/jokers/goldenegg.lua new file mode 100644 index 0000000..fddaa59 --- /dev/null +++ b/mod/jokers/goldenegg.lua @@ -0,0 +1,57 @@ +SMODS.Atlas { + key = 'golden_egg', + path = "j_golden_egg.png", + px = 71, + py = 95 +} + +SMODS.Joker { + key = "golden_egg", + name = "Golden Egg", + atlas = 'golden_egg', + pos = { + x = 0, + y = 0 + }, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + dollars = 4, + joker1 = "j_egg", + joker2 = "j_golden" + } + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + card.ability.extra.dollars, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + } + end, + set_ability = function(self, card, initial, delay_sprites) + card:set_cost() + end, + calc_dollar_bonus = function(self, card) + return card.ability.extra.dollars + end, + calculate = function(self, card, context) + if context.end_of_round and not context.blueprint and not context.repetition and not context.individual then + card.ability.extra_value = card.ability.extra_value + card.ability.extra.dollars + card:set_cost() + return { + message = localize('k_val_up'), + colour = G.C.MONEY + } + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/heartpaladin.lua b/mod/jokers/heartpaladin.lua new file mode 100644 index 0000000..6dc7bd6 --- /dev/null +++ b/mod/jokers/heartpaladin.lua @@ -0,0 +1,64 @@ +SMODS.Atlas { + key = 'heart_paladin', + path = "j_heart_paladin.png", + px = 71, + py = 95 +} + +SMODS.Joker { + key = "heart_paladin", + name = "Heart Paladin", + atlas = 'heart_paladin', + pos = { + x = 0, + y = 0 + }, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + odds = 3, + Xmult = 1.5, + joker1 = "j_lusty_joker", + joker2 = "j_bloodstone" + } + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + card.ability.extra.Xmult, + ''..(G.GAME and G.GAME.probabilities.normal or 1), + card.ability.extra.odds, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + } + end, + calculate = function(self, card, context) + if context.individual and context.cardarea == G.play and + context.other_card:is_suit('Hearts') then + return { + x_mult = card.ability.extra.Xmult, + card = card + } + end + + if context.repetition and context.cardarea == G.play and + context.other_card:is_suit('Hearts') then + if pseudorandom('heart_paladin') < G.GAME.probabilities.normal/card.ability.extra.odds then + return { + message = localize('k_again_ex'), + repetitions = 1, + card = card + } + end + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/moonmarauder.lua b/mod/jokers/moonmarauder.lua new file mode 100644 index 0000000..fba3a36 --- /dev/null +++ b/mod/jokers/moonmarauder.lua @@ -0,0 +1,117 @@ +FusionJokers.fusions:add_fusion("j_slothful_joker", nil, false, "j_rainbow_moonstone", nil, false, "j_fuse_moon_marauder", 12) + +SMODS.Atlas { + key = 'moon_marauder', + path = "j_moon_marauder.png", + px = 71, + py = 95 +} + +SMODS.Joker { + key = "moon_marauder", + name = "Moon Marauder", + atlas = 'moon_marauder', + pos = { + x = 0, + y = 0 + }, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + odds = 3, + joker1 = "j_slothful_joker", + joker2 = "j_rainbow_moonstone" + } + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + '' .. (G.GAME and G.GAME.probabilities.normal or 1), + card.ability.extra.odds, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + } + end, + calculate = function(self, card, context) + if context.before and (context.cardarea == G.jokers) then + local moons = {} + for _, v in ipairs(context.full_hand) do + if v:is_suit('Moons') and not (v.ability.name == 'Glass Card') and pseudorandom('moon_marauder') < G.GAME.probabilities.normal / card.ability.extra.odds then + moons[#moons + 1] = v + v:set_ability(G.P_CENTERS.m_glass, nil, true) + G.E_MANAGER:add_event(Event({ + func = function() + v:juice_up() + return true + end + })) + end + end + if #moons > 0 then + return { + message = localize('k_glass'), + colour = G.C.SECONDARY_SET.Enhanced, + card = context.blueprint_card or card + } + end + end + + if context.remove_playing_cards and not context.blueprint then + -- G.E_MANAGER:add_event(Event({ + -- trigger = 'after', + -- delay = 1, + -- func = function() + -- sendDebugMessage(tostring(#context.removed)) + -- for k, v in ipairs(context.removed) do + -- sendDebugMessage(tostring(v.shattered)) + -- if v.shattered then + -- local _card = Card(G.play.T.x, G.play.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS.c_base, {playing_card = G.playing_card}) + + -- _card = copy_card(v, _card, nil, G.playing_card) + -- _card:start_materialize({G.C.SECONDARY_SET.Enhanced}) + -- G.deck:emplace(_card) + + -- G.E_MANAGER:add_event(Event({ + -- func = function() + -- card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, + -- { message = localize('k_in_tact_ex'), colour = G.C.SECONDARY_SET.edition }) + -- return true + -- end + -- })) + -- end + -- end + -- end + -- })) + sendDebugMessage(tostring(#context.removed)) + for k, v in ipairs(context.removed) do + sendDebugMessage(tostring(v.shattered)) + if v.shattered then + local _card = Card(G.play.T.x, G.play.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS.c_base, {playing_card = G.playing_card}) + + G.playing_card = (G.playing_card and G.playing_card + 1) or 1 + _card = copy_card(v, _card, nil, G.playing_card) + _card:start_materialize({G.C.SECONDARY_SET.Enhanced}) + G.deck:emplace(_card) + table.insert(G.playing_cards, _card) + + G.E_MANAGER:add_event(Event({ + func = function() + card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, + { message = localize('k_in_tact_ex'), colour = G.C.SECONDARY_SET.edition }) + return true + end + })) + end + end + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/royaldecree.lua b/mod/jokers/royaldecree.lua new file mode 100644 index 0000000..11188a3 --- /dev/null +++ b/mod/jokers/royaldecree.lua @@ -0,0 +1,61 @@ +SMODS.Atlas { + key = 'royal_decree', + path = "j_royal_decree.png", + px = 71, + py = 95 +} + +SMODS.Joker { + key = "royal_decree", + name = "Royal Decree", + atlas = 'royal_decree', + pos = { + x = 0, + y = 0 + }, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + dollars = 2, + joker1 = "j_business", + joker2 = "j_reserved_parking", + } + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + card.ability.extra.dollars, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + } + end, + calculate = function(self, card, context) + if context.end_of_round and context.individual then + if context.cardarea == G.hand and context.other_card:is_face() then + return { + h_dollars = 2, + card = card + } + end + end + + if context.cardarea == G.play and context.individual and context.other_card:is_face() then + G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + 2 + G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)})) + return { + dollars = 2, + card = card + } + + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/spadearcher.lua b/mod/jokers/spadearcher.lua new file mode 100644 index 0000000..698df0c --- /dev/null +++ b/mod/jokers/spadearcher.lua @@ -0,0 +1,69 @@ +SMODS.Atlas { + key = 'spade_archer', + path = "j_spade_archer.png", + px = 71, + py = 95 +} + +SMODS.Joker { + key = "spade_archer", + name = "Spade Archer", + atlas = 'spade_archer', + pos = { + x = 0, + y = 0 + }, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + chips = 50, + chip_mod = 10, + joker1 = "j_wrathful_joker", + joker2 = "j_arrowhead" + } + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + card.ability.extra.chips, + card.ability.extra.chip_mod, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + } + end, + calculate = function(self, card, context) + if context.individual and context.cardarea == G.play and + context.other_card:is_suit('Spades') then + return { + chips = card.ability.extra.chips, + card = card + } + end + + if context.before and context.cardarea == G.jokers then + local spades = 0 + for k, v in ipairs(context.scoring_hand) do + if v:is_suit('Spades') then + spades = spades + 1 + end + end + if spades == 5 then + card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_mod + return { + message = localize('k_upgrade_ex'), + colour = G.C.CHIPS, + card = card + } + end + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/staroracle.lua b/mod/jokers/staroracle.lua new file mode 100644 index 0000000..ad00cce --- /dev/null +++ b/mod/jokers/staroracle.lua @@ -0,0 +1,68 @@ +FusionJokers.fusions:add_fusion("j_envious_joker", nil, false, "j_star_ruby", nil, false, "j_fuse_star_oracle", 12) + +SMODS.Atlas { + key = 'star_oracle', + path = "j_star_oracle.png", + px = 71, + py = 95 +} + +SMODS.Joker { + key = "star_oracle", + name = "Star Oracle", + atlas = 'star_oracle', + pos = { + x = 0, + y = 0 + }, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + odds = 10, + slots = 2, + joker1 = "j_envious_joker", + joker2 = "j_star_ruby", + } + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + '' .. (G.GAME and G.GAME.probabilities.normal or 1), + card.ability.extra.odds, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + } + end, + calculate = function(self, card, context) + if context.individual and + context.cardarea == G.play and + context.other_card:is_suit('Stars') and + #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit and + pseudorandom('starruby') < G.GAME.probabilities.normal / card.ability.extra.odds 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, 'ruby') + _card:add_to_deck() + G.consumeables:emplace(_card) + G.GAME.consumeable_buffer = 0 + return true + end) + })) + card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, + { message = localize('k_plus_spectral'), colour = G.C.SECONDARY_SET.Spectral }) + return {} + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/jokers/uncannyface.lua b/mod/jokers/uncannyface.lua new file mode 100644 index 0000000..d8a301e --- /dev/null +++ b/mod/jokers/uncannyface.lua @@ -0,0 +1,59 @@ +SMODS.Atlas { + key = 'uncanny_face', + path = "j_uncanny_face.png", + px = 71, + py = 95 +} + +SMODS.Joker { + key = "uncanny_face", + name = "Uncanny Face", + atlas = 'uncanny_face', + pos = { + x = 0, + y = 0 + }, + rarity = "fuse_fusion", + cost = 12, + unlocked = true, + discovered = false, + eternal_compat = true, + perishable_compat = true, + blueprint_compat = true, + config = { + extra = { + chips = 15, + mult = 2, + joker1 = "j_scary_face", + joker2 = "j_smiley" + } + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + card.ability.extra.chips, + card.ability.extra.mult, + localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, + localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} + } + } + end, + calculate = function(self, card, context) + if context.individual and context.cardarea == G.play and + context.other_card:is_face() then + local faces = 0 + for k, v in ipairs(context.scoring_hand) do + if v:is_face() then + faces = faces + 1 + end + end + return { + mult = card.ability.extra.mult * faces, + chips = card.ability.extra.chips * faces, + card = card + } + end + end +} + +-- See localization/en-us.lua to create joker text \ No newline at end of file diff --git a/mod/localization/en-us.lua b/mod/localization/en-us.lua new file mode 100644 index 0000000..e062610 --- /dev/null +++ b/mod/localization/en-us.lua @@ -0,0 +1,189 @@ +return { + ["misc"] = { + ["dictionary"] = { + ["k_fusion"] = "Fusion", + ["k_fuse_fusion"] = "Fusion", + ["k_flipped_ex"] = "Flipped!", + ["k_copied_ex"] = "Cloned!", + ["k_in_tact_ex"] = "In-Tact!", + ["b_fuse"] = "FUSE", + }, + ["labels"] = { + ["k_fuse_fusion"] = "Fusion", + }, + }, + ["descriptions"] = { + ["Joker"] = { + ["j_fuse_diamond_bard"] = { + ["name"] = "Diamond Bard", + ["text"] = { + "Played cards with {C:diamonds}Diamond{} suit give", + "{C:money}$#1#{}, as well as {C:mult}+#2#{} Mult for every ", + "{C:money}$#3#{} you have when scored", + "{C:inactive}(#4# + #5#)", + }, + }, + ["j_fuse_heart_paladin"] = { + ["name"] = "Heart Paladin", + ["text"] = { + "Played cards with {C:hearts}Heart{} suit give", + "{X:mult,C:white}X#1#{} Mult when scored.", + "{C:green}#2# in #3#{} chance to re-trigger", + "{C:inactive}(#4# + #5#)", + }, + }, + ["j_fuse_spade_archer"] = { + ["name"] = "Spade Archer", + ["text"] = { + "Played cards with {C:spades}Spade{} suit give", + "{C:chips}+#1#{} Chips when scored. Gains {C:chips}+#2#{} ", + "chips when 5 {C:spades}Spades{} are played", + "{C:inactive}(#3# + #4#)", + }, + }, + ["j_fuse_club_wizard"] = { + ["name"] = "Club Wizard", + ["text"] = { + "Played cards with {C:clubs}Club{} suit", + "give {C:mult}+#1#{} Mult when scored", + "{C:inactive}(#2# + #3#)", + }, + }, + ["j_fuse_big_bang"] = { + ["name"] = "Big Bang", + ["text"] = { + "{X:mult,C:white} X#1# {} Mult per the number", + "of times {C:attention}poker hand{} has been played", + "plus the level of the {C:attention}poker hand{}.", + "{C:inactive}(#2# + #3#)", + }, + }, + ["j_fuse_dynamic_duo"] = { + ["name"] = "Dynamic Duo", + ["text"] = { + "Played {C:attention}number{} cards give {C:mult}+#1#{} Mult ", + "and {C:chips}+#2#{} Chips when scored.", + "{C:inactive}(#3# + #4#)", + }, + }, + ["j_fuse_collectible_chaos_card"] = { + ["name"] = "Collectible Chaos Card", + ["text"] = { + "{C:mult}+#1#{} Mult per {C:attention}reroll{} in the shop.", + "{C:attention}#2#{} free {C:green}Reroll{} per shop", + "{C:inactive}(Currently {C:mult}+#3#{C:inactive} Mult)", + "{C:inactive}(#4# + #5#)", + }, + }, + ["j_fuse_flip_flop"] = { + ["name"] = "Flip-Flop", + ["text"] = { + "{C:attention}+#1#{} hand size. {C:red}+#2#{} Mult", + "{C:attention}Flips{} after each blind", + "{C:inactive}(#3# + #4#)", + }, + }, + ["j_fuse_flip_flop_mult"] = { + ["name"] = "Flip-Flop", + ["text"] = { + "{C:attention}+#1#{} hand size. {C:red}+#2#{} Mult", + "{C:attention}Flips{} after each blind", + "{C:inactive}(#3# + #4#)", + }, + }, + ["j_fuse_flip_flop_chips"] = { + ["name"] = "Flip-Flop", + ["text"] = { + "{C:red}+#1#{} discard. {C:chips}+#2#{} Chips", + "{C:attention}Flips{} after each blind", + "{C:inactive}(#3# + #4#)", + }, + }, + ["j_fuse_royal_decree"] = { + ["name"] = "Royal Decree", + ["text"] = { + "Played {C:attention}face{} cards give {C:money}$#1#{} when scored.", + "Each {C:attention}face{} card held in hand", + "at end of round gives {C:money}$#1#{}", + "{C:inactive}(#2# + #3#)", + }, + }, + ["j_fuse_dementia_joker"] = { + ["name"] = "Dementia Joker", + ["text"] = { + "{C:mult}+#1#{} Mult for each {C:attention}Joker{} card.", + "{C:green}#2# in #3#{} chance to {C:attention}clone{} if ", + "not {C:dark_edition}Negative{} after you beat a blind", + "{C:inactive}(Currently {C:mult}+#4#{C:inactive} Mult)", + "{C:inactive}(#5# + #6#)", + }, + }, + ["j_fuse_golden_egg"] = { + ["name"] = "Golden Egg", + ["text"] = { + "Gains {C:money}$#1#{} of {C:attention}sell value{}", + " at end of round.", + " Earn {C:money}$#1#{} at end of round", + "{C:inactive}(#2# + #3#)", + }, + }, + ["j_fuse_flag_bearer"] = { + ["name"] = "Flag Bearer", + ["text"] = { + "{C:mult}+#1#{} Mult per hand played, {C:mult}-#2#{} Mult", + "per discard. Mult is multiplied by", + " remaining {C:attention}discards{}", + "{C:inactive}(Currently {C:mult}+#3#{C:inactive} Mult)", + "{C:inactive}(#4# + #5#)", + }, + }, + ["j_fuse_uncanny_face"] = { + ["name"] = "Uncanny Face", + ["text"] = { + "Played {C:attention}face{} cards give {C:chips}+#1#{} Chips and", + "{C:mult}+#2#{} Mult for every {C:attention}face{} card", + " in the scoring hand", + "{C:inactive}(#3# + #4#)", + }, + }, + ["j_fuse_commercial_driver"] = { + ["name"] = "Commercial Driver", + ["text"] = { + "{X:mult,C:white} X#1# {} Mult per consecutive hand", + "played with a scoring {C:attention}enhanced{} card", + "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)", + "{C:inactive}(#3# + #4#)", + }, + }, + ["j_fuse_camping_trip"] = { + ["name"] = "Camping Trip", + ["text"] = { + "Played {C:attention}cards{} permanently gains", + "{C:chips}+#1#{} Chips when scored", + "({C:chips}+#2#{} on the final hand)", + "Your final hand triggers twice", + "{C:inactive}(#3# + #4#)", + }, + }, + ["j_fuse_star_oracle"] = { + ["name"] = "Star Oracle", + ["text"] = { + "{C:attention}+2{} consumable slots.", + "{C:green}#1# in #2#{} chance for played cards", + " with {C:stars}Star{} suit to create a", + "random {C:spectral}Spectral{} card when scored", + "{C:inactive}(#3# + #4#)", + }, + }, + ["j_fuse_moon_marauder"] = { + ["name"] = "Moon Marauder", + ["text"] = { + "{C:green}#1# in #2#{} chance for played cards with", + "{C:moons}Moon{} suit to become {C:attention}Glass{} Cards.", + "played {C:moons}Moon{} {C:attention}Glass{} cards never shatter", + "{C:inactive}(#3# + #4#)", + }, + }, + }, + }, +} \ No newline at end of file From 8e2b58941aeffbba82d8ae5d814b5b0824fb85f0 Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Sun, 20 Apr 2025 13:06:07 -0400 Subject: [PATCH 11/91] right, we ended up not needing that --- mod/FusionJokers.lua | 8 -------- 1 file changed, 8 deletions(-) diff --git a/mod/FusionJokers.lua b/mod/FusionJokers.lua index 2156724..7f52789 100644 --- a/mod/FusionJokers.lua +++ b/mod/FusionJokers.lua @@ -402,14 +402,6 @@ end -local flip = { - x = 0, - y = 0 -} -local flop = { - x = 0, - y = 1 -} local updateref = Card.update function Card:update(dt) updateref(self, dt) From c668b22a580877e021a4589d793052ea6f7bccec Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Sun, 20 Apr 2025 13:21:06 -0400 Subject: [PATCH 12/91] update more things to modern standards --- mod/FusionJokers.lua | 58 --------------------------------- mod/jokers/collectiblechaos.lua | 20 ++++++++++-- mod/jokers/flipflop.lua | 16 +++++++++ mod/jokers/staroracle.lua | 6 ++++ 4 files changed, 40 insertions(+), 60 deletions(-) diff --git a/mod/FusionJokers.lua b/mod/FusionJokers.lua index 7f52789..a38e63b 100644 --- a/mod/FusionJokers.lua +++ b/mod/FusionJokers.lua @@ -427,64 +427,6 @@ function Card:update(dt) end end - -local add_to_deckref = Card.add_to_deck -function Card:add_to_deck(from_debuff) - if not self.added_to_deck then - if self.ability.name == 'Collectible Chaos Card' then - G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls + 1 - calculate_reroll_cost(true) - end - - if self.ability.name == 'Flip-Flop' then - if self.ability.extra.side == "mult" then - G.hand:change_size(self.ability.extra.hands) - else - G.GAME.round_resets.discards = G.GAME.round_resets.discards + self.ability.extra.discards - ease_discard(self.ability.extra.discards) - end - end - - if self.ability.name == 'Star Oracle' then - G.consumeables:change_size(self.ability.extra.slots) - end - end - add_to_deckref(self, from_debuff) -end - -local remove_from_deckref = Card.remove_from_deck -function Card:remove_from_deck(from_debuff) - if self.added_to_deck then - if self.ability.name == 'Collectible Chaos Card' then - G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls - 1 - calculate_reroll_cost(true) - end - - if self.ability.name == 'Flip-Flop' then - if self.ability.extra.side == "mult" then - G.hand:change_size(-self.ability.extra.hands) - else - G.GAME.round_resets.discards = G.GAME.round_resets.discards - self.ability.extra.discards - ease_discard(-self.ability.extra.discards) - end - end - - if self.ability.name == 'Star Oracle' then - G.consumeables:change_size(-self.ability.extra.slots) - end - end - remove_from_deckref(self, from_debuff) -end - -local new_roundref = new_round -function new_round() - new_roundref() - local chaos = find_joker('Collectible Chaos Card') - G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls or 0 - G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls + #chaos - calculate_reroll_cost(true) -end - -- local shatterref = Card.shatter -- function Card:shatter() -- G.E_MANAGER:add_event(Event({ diff --git a/mod/jokers/collectiblechaos.lua b/mod/jokers/collectiblechaos.lua index f02021e..4fc3b5b 100644 --- a/mod/jokers/collectiblechaos.lua +++ b/mod/jokers/collectiblechaos.lua @@ -23,9 +23,9 @@ SMODS.Joker { config = { extra = { per_reroll = 2, - free = 1, + free = 1, mult = 0, - joker1 = "j_chaos", + joker1 = "j_chaos", joker2 = "j_flash" } }, @@ -40,6 +40,16 @@ SMODS.Joker { } } end, + add_to_deck = function(self, from_debuff) + if not from_debuff then -- no gameplan shenanigans for bunco enjoyers :p + G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls + self.ability.extra.free + calculate_reroll_cost(true) + end + end, + remove_from_deck = function(self, from_debuff) + G.GAME.current_round.free_rerolls = math.max(G.GAME.current_round.free_rerolls - self.ability.extra.free, 0) + calculate_reroll_cost(true) + end, set_ability = function(self, card, initial, delay_sprites) if card.ability.mult and (card.ability.extra.mult == 0) then card.ability.extra.mult = card.ability.mult @@ -47,6 +57,12 @@ SMODS.Joker { end end, calculate = function(self, card, context) + if context.starting_shop then + G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls or 0 + G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls + card.ability.extra.free + calculate_reroll_cost(true) + end + if context.reroll_shop and not context.blueprint then card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.per_reroll G.E_MANAGER:add_event(Event({ diff --git a/mod/jokers/flipflop.lua b/mod/jokers/flipflop.lua index a3e42aa..c09d10f 100644 --- a/mod/jokers/flipflop.lua +++ b/mod/jokers/flipflop.lua @@ -71,6 +71,22 @@ SMODS.Joker { card:set_sprites(flipref) end end, + add_to_deck = function(self, from_debuff) + if self.ability.extra.side == "mult" then + G.hand:change_size(self.ability.extra.hands) + else + G.GAME.round_resets.discards = G.GAME.round_resets.discards + self.ability.extra.discards + ease_discard(self.ability.extra.discards) + end + end, + remove_from_deck = function(self, from_debuff) + if self.ability.extra.side == "mult" then + G.hand:change_size(-self.ability.extra.hands) + else + G.GAME.round_resets.discards = G.GAME.round_resets.discards - self.ability.extra.discards + ease_discard(-self.ability.extra.discards) + end + end, calculate = function(self, card, context) local flipref = card.config.center if context.end_of_round and not context.blueprint and not context.repetition and not context.individual then diff --git a/mod/jokers/staroracle.lua b/mod/jokers/staroracle.lua index ad00cce..03409b2 100644 --- a/mod/jokers/staroracle.lua +++ b/mod/jokers/staroracle.lua @@ -40,6 +40,12 @@ SMODS.Joker { } } end, + add_to_deck = function(self, from_debuff) + G.consumeables:change_size(self.ability.extra.slots) + end, + remove_from_deck = function(self, from_debuff) + G.consumeables:change_size(-self.ability.extra.slots) + end, calculate = function(self, card, context) if context.individual and context.cardarea == G.play and From 8d7437d12bb4cef54d41fffa1368b3c097f1474b Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Sun, 20 Apr 2025 13:29:00 -0400 Subject: [PATCH 13/91] you can't copy that :p --- mod/jokers/collectiblechaos.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/jokers/collectiblechaos.lua b/mod/jokers/collectiblechaos.lua index 4fc3b5b..cbe4c37 100644 --- a/mod/jokers/collectiblechaos.lua +++ b/mod/jokers/collectiblechaos.lua @@ -57,7 +57,7 @@ SMODS.Joker { end end, calculate = function(self, card, context) - if context.starting_shop then + if context.starting_shop and not context.blueprint then G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls or 0 G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls + card.ability.extra.free calculate_reroll_cost(true) From 8aa3bd5fff24ed9c73007119de63a67e2246fbb7 Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Sun, 20 Apr 2025 13:31:15 -0400 Subject: [PATCH 14/91] what's a 'release', never heard of it --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3fc7ce2..8548a7e 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ You can find a list of their abilities, as well as the jokers needed to make the ## ⬇ How to Download - The mod requires Steamodded. You can see info about how to use it [here](https://github.com/Steamopollys/Steamodded) -- Download the latest release of Fusion Jokers +- Download the latest commit of Fusion Jokers from the green "Code" button up there - Extract the downloaded mod to the Mods folder (at %appdata%/Balatro/Mods) ## ⚙️ Config From 222286db29b203facdde90aab174e35afeb83ced Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Sun, 20 Apr 2025 17:26:03 -0400 Subject: [PATCH 15/91] me: 'i wonder how to fix the issue where it takes another round before it inherits sell value'. the noble add_to_deck(): --- mod/jokers/goldenegg.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/jokers/goldenegg.lua b/mod/jokers/goldenegg.lua index fddaa59..93521e8 100644 --- a/mod/jokers/goldenegg.lua +++ b/mod/jokers/goldenegg.lua @@ -36,7 +36,7 @@ SMODS.Joker { } } end, - set_ability = function(self, card, initial, delay_sprites) + add_to_deck = function (self, card, from_debuff) card:set_cost() end, calc_dollar_bonus = function(self, card) From 045371ac43abb1956c419853b4f779bc7e74da9f Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Sun, 20 Apr 2025 18:32:21 -0400 Subject: [PATCH 16/91] why was this local --- mod/FusionJokers.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mod/FusionJokers.lua b/mod/FusionJokers.lua index a38e63b..ea1ae4d 100644 --- a/mod/FusionJokers.lua +++ b/mod/FusionJokers.lua @@ -134,11 +134,11 @@ SMODS.load_file('jokers/uncannyface.lua')() SMODS.load_file('jokers/commercialdriver.lua')() SMODS.load_file('jokers/campingtrip.lua')() -local to_number = to_number or function(num) +to_number = to_number or function(num) return num end -local to_big = to_big or function(num) +to_big = to_big or function(num) return num end From 11eba38283409aa5aefdab62bf924fe9e8f9e35f Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Sun, 27 Apr 2025 12:48:21 -0400 Subject: [PATCH 17/91] update dd to todd's new value --- mod/jokers/dynamicduo.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mod/jokers/dynamicduo.lua b/mod/jokers/dynamicduo.lua index 3a64e4b..047646c 100644 --- a/mod/jokers/dynamicduo.lua +++ b/mod/jokers/dynamicduo.lua @@ -22,16 +22,16 @@ SMODS.Joker { blueprint_compat = true, config = { extra = { - mult = 4, - chips = 30, - joker1 = "j_even_steven", + mult = 4, + chips = 31, + joker1 = "j_even_steven", joker2 = "j_odd_todd" } }, loc_vars = function(self, info_queue, card) return { vars = { - card.ability.extra.mult, + card.ability.extra.mult, card.ability.extra.chips, localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} From 45cac7e5376e1d3b7ccb753435612f945cef9fd4 Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Sun, 27 Apr 2025 12:50:41 -0400 Subject: [PATCH 18/91] ... use markdown syntax, not mediawiki --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8548a7e..686baea 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ You can find a list of their abilities, as well as the jokers needed to make the ## ⚙️ Config -- '''Block used components from reappearing''': Jokers used in a fusion cannot reappear if the fusion is present. Currently only applies to Fusion Jokers fusions; cross-mod functionality is planned. Default true. +- **Block used components from reappearing**: Jokers used in a fusion cannot reappear if the fusion is present. Currently only applies to Fusion Jokers fusions; cross-mod functionality is planned. Default true. ## ➕ Fusion API (For Developers) From 61ab9a02180d6b86676c2163da216a091808f867 Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Sun, 27 Apr 2025 12:51:00 -0400 Subject: [PATCH 19/91] clarify that --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 686baea..9be4e77 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ You can find a list of their abilities, as well as the jokers needed to make the ## ⚙️ Config -- **Block used components from reappearing**: Jokers used in a fusion cannot reappear if the fusion is present. Currently only applies to Fusion Jokers fusions; cross-mod functionality is planned. Default true. +- **Block used components from reappearing**: Jokers used in a fusion cannot reappear if the fusion is present (unless Showman is also present). Currently only applies to Fusion Jokers fusions; cross-mod functionality is planned. Default true. ## ➕ Fusion API (For Developers) From 0498f439fe3252755c1f7cb26111f4fd90e72c89 Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Wed, 30 Apr 2025 13:57:53 -0400 Subject: [PATCH 20/91] document the api --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 9be4e77..0f781d0 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,20 @@ The mod adds a way for other developers to create their own fusions! Developers can call the function `FusionJokers.fusions:add_fusion()` to register their own fusion to the game. The function also allows them to determine carried stats between the component jokers and the fusion joker. +```lua +FusionJokers.fusions:add_fusion( + joker1, --string, component joker's key + carry_stat1, --string, name of stat to carry into fusion + extra1, --boolean, is the carry stat in an "extra" table or not + joker2, -- + carry_stat2, -- same as 1, but for the other component joker + extra2, -- + result_joker, --result of fusion + cost, --cost to fuse + merged_stat, merge_stat1, merge_stat2, merge_extra --TODO explain these +) +``` + ## 🎉 Credits - The original mod was written by [**Itayfeder**](https://github.com/stars/itayfeder/lists/balatro-modding), with art created by [**Lyman**](https://github.com/spikeof2010) From a9130bab1696ac6a3a92bbe779b7f4fbc2643615 Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Wed, 30 Apr 2025 14:42:03 -0400 Subject: [PATCH 21/91] more smods 1.0 updates --- mod/jokers/collectiblechaos.lua | 8 ++++---- mod/jokers/flipflop.lua | 20 ++++++++++---------- mod/jokers/moonmarauder.lua | 6 +++--- mod/jokers/staroracle.lua | 14 +++++++------- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/mod/jokers/collectiblechaos.lua b/mod/jokers/collectiblechaos.lua index cbe4c37..112b328 100644 --- a/mod/jokers/collectiblechaos.lua +++ b/mod/jokers/collectiblechaos.lua @@ -40,14 +40,14 @@ SMODS.Joker { } } end, - add_to_deck = function(self, from_debuff) + add_to_deck = function(self, card, from_debuff) if not from_debuff then -- no gameplan shenanigans for bunco enjoyers :p - G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls + self.ability.extra.free + G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls + card.ability.extra.free calculate_reroll_cost(true) end end, - remove_from_deck = function(self, from_debuff) - G.GAME.current_round.free_rerolls = math.max(G.GAME.current_round.free_rerolls - self.ability.extra.free, 0) + remove_from_deck = function(self, card, from_debuff) + G.GAME.current_round.free_rerolls = math.max(G.GAME.current_round.free_rerolls - card.ability.extra.free, 0) calculate_reroll_cost(true) end, set_ability = function(self, card, initial, delay_sprites) diff --git a/mod/jokers/flipflop.lua b/mod/jokers/flipflop.lua index c09d10f..f2b59d6 100644 --- a/mod/jokers/flipflop.lua +++ b/mod/jokers/flipflop.lua @@ -71,20 +71,20 @@ SMODS.Joker { card:set_sprites(flipref) end end, - add_to_deck = function(self, from_debuff) - if self.ability.extra.side == "mult" then - G.hand:change_size(self.ability.extra.hands) + add_to_deck = function(self, card, from_debuff) + if card.ability.extra.side == "mult" then + G.hand:change_size(card.ability.extra.hands) else - G.GAME.round_resets.discards = G.GAME.round_resets.discards + self.ability.extra.discards - ease_discard(self.ability.extra.discards) + G.GAME.round_resets.discards = G.GAME.round_resets.discards + card.ability.extra.discards + ease_discard(card.ability.extra.discards) end end, - remove_from_deck = function(self, from_debuff) - if self.ability.extra.side == "mult" then - G.hand:change_size(-self.ability.extra.hands) + remove_from_deck = function(self, card, from_debuff) + if card.ability.extra.side == "mult" then + G.hand:change_size(-card.ability.extra.hands) else - G.GAME.round_resets.discards = G.GAME.round_resets.discards - self.ability.extra.discards - ease_discard(-self.ability.extra.discards) + G.GAME.round_resets.discards = G.GAME.round_resets.discards - card.ability.extra.discards + ease_discard(-eval_card.ability.extra.discards) end end, calculate = function(self, card, context) diff --git a/mod/jokers/moonmarauder.lua b/mod/jokers/moonmarauder.lua index fba3a36..4ce3784 100644 --- a/mod/jokers/moonmarauder.lua +++ b/mod/jokers/moonmarauder.lua @@ -1,4 +1,4 @@ -FusionJokers.fusions:add_fusion("j_slothful_joker", nil, false, "j_rainbow_moonstone", nil, false, "j_fuse_moon_marauder", 12) +FusionJokers.fusions:add_fusion("j_six_slothful_joker", nil, false, "j_six_moonstone", nil, false, "j_fuse_moon_marauder", 12) SMODS.Atlas { key = 'moon_marauder', @@ -25,8 +25,8 @@ SMODS.Joker { config = { extra = { odds = 3, - joker1 = "j_slothful_joker", - joker2 = "j_rainbow_moonstone" + joker1 = "j_six_slothful_joker", + joker2 = "j_six_moonstone" } }, loc_vars = function(self, info_queue, card) diff --git a/mod/jokers/staroracle.lua b/mod/jokers/staroracle.lua index 03409b2..84447c4 100644 --- a/mod/jokers/staroracle.lua +++ b/mod/jokers/staroracle.lua @@ -1,4 +1,4 @@ -FusionJokers.fusions:add_fusion("j_envious_joker", nil, false, "j_star_ruby", nil, false, "j_fuse_star_oracle", 12) +FusionJokers.fusions:add_fusion("j_six_envious_joker", nil, false, "j_six_star_ruby", nil, false, "j_fuse_star_oracle", 12) SMODS.Atlas { key = 'star_oracle', @@ -26,8 +26,8 @@ SMODS.Joker { extra = { odds = 10, slots = 2, - joker1 = "j_envious_joker", - joker2 = "j_star_ruby", + joker1 = "j_six_envious_joker", + joker2 = "j_six_star_ruby", } }, loc_vars = function(self, info_queue, card) @@ -40,11 +40,11 @@ SMODS.Joker { } } end, - add_to_deck = function(self, from_debuff) - G.consumeables:change_size(self.ability.extra.slots) + add_to_deck = function(self, card, from_debuff) + G.consumeables:change_size(card.ability.extra.slots) end, - remove_from_deck = function(self, from_debuff) - G.consumeables:change_size(-self.ability.extra.slots) + remove_from_deck = function(self, card, from_debuff) + G.consumeables:change_size(-card.ability.extra.slots) end, calculate = function(self, card, context) if context.individual and From 6fc1382830ca21b064ab7f3173f1ebf090e3440b Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Fri, 2 May 2025 11:59:12 -0400 Subject: [PATCH 22/91] don't double upgrade spade archer just because blueprint is there :p --- mod/jokers/spadearcher.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/jokers/spadearcher.lua b/mod/jokers/spadearcher.lua index 698df0c..5e923c9 100644 --- a/mod/jokers/spadearcher.lua +++ b/mod/jokers/spadearcher.lua @@ -47,7 +47,7 @@ SMODS.Joker { } end - if context.before and context.cardarea == G.jokers then + if context.before and context.cardarea == G.jokers and not context.blueprint then local spades = 0 for k, v in ipairs(context.scoring_hand) do if v:is_suit('Spades') then From 0ff9279b3ddd6a7293a7e3e576304fa1bfb3ed2d Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Fri, 2 May 2025 12:03:41 -0400 Subject: [PATCH 23/91] ?? where did that come from --- mod/jokers/flipflop.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/jokers/flipflop.lua b/mod/jokers/flipflop.lua index f2b59d6..675b24e 100644 --- a/mod/jokers/flipflop.lua +++ b/mod/jokers/flipflop.lua @@ -84,7 +84,7 @@ SMODS.Joker { G.hand:change_size(-card.ability.extra.hands) else G.GAME.round_resets.discards = G.GAME.round_resets.discards - card.ability.extra.discards - ease_discard(-eval_card.ability.extra.discards) + ease_discard(-card.ability.extra.discards) end end, calculate = function(self, card, context) From 3c5f530f4ed351355112bee1c98c7ffdc4d08105 Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Fri, 2 May 2025 13:17:40 -0400 Subject: [PATCH 24/91] give this a beta version number for reference --- mod/FusionJokers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/FusionJokers.json b/mod/FusionJokers.json index c248312..d0718b6 100644 --- a/mod/FusionJokers.json +++ b/mod/FusionJokers.json @@ -9,7 +9,7 @@ "priority": -10000, "badge_colour": "B26CBB", "badge_text_colour": "FFFFFF", - "version": "1.0.0", + "version": "1.0.0~BETA-00502a", "dependencies": [ "Steamodded (>=1.0.0~ALPHA-1307d)", ], From 376a7f959d40dd91a93abd402d7a8bac9cdaf8cc Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Thu, 15 May 2025 22:42:31 -0400 Subject: [PATCH 25/91] spade archer now scales with 5+ spades --- mod/jokers/spadearcher.lua | 2 +- mod/localization/en-us.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mod/jokers/spadearcher.lua b/mod/jokers/spadearcher.lua index 5e923c9..15b96a2 100644 --- a/mod/jokers/spadearcher.lua +++ b/mod/jokers/spadearcher.lua @@ -54,7 +54,7 @@ SMODS.Joker { spades = spades + 1 end end - if spades == 5 then + if spades >= 5 then card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_mod return { message = localize('k_upgrade_ex'), diff --git a/mod/localization/en-us.lua b/mod/localization/en-us.lua index e062610..99ae859 100644 --- a/mod/localization/en-us.lua +++ b/mod/localization/en-us.lua @@ -37,7 +37,7 @@ return { ["text"] = { "Played cards with {C:spades}Spade{} suit give", "{C:chips}+#1#{} Chips when scored. Gains {C:chips}+#2#{} ", - "chips when 5 {C:spades}Spades{} are played", + "chips when 5 or more {C:spades}Spades{} are played", "{C:inactive}(#3# + #4#)", }, }, From f0ded6ece3483e6840ad914d3bd07b39899dfa35 Mon Sep 17 00:00:00 2001 From: wingedcatgirl <69098783+wingedcatgirl@users.noreply.github.com> Date: Thu, 15 May 2025 22:43:00 -0400 Subject: [PATCH 26/91] version --- mod/FusionJokers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/FusionJokers.json b/mod/FusionJokers.json index d0718b6..27c0944 100644 --- a/mod/FusionJokers.json +++ b/mod/FusionJokers.json @@ -9,7 +9,7 @@ "priority": -10000, "badge_colour": "B26CBB", "badge_text_colour": "FFFFFF", - "version": "1.0.0~BETA-00502a", + "version": "1.0.0~BETA-00515a", "dependencies": [ "Steamodded (>=1.0.0~ALPHA-1307d)", ], From 7004a3428d206d589b4a2a92fa014a39a08cd1dc Mon Sep 17 00:00:00 2001 From: Matthew Yarnot Date: Mon, 19 May 2025 19:10:53 -0500 Subject: [PATCH 27/91] Add files via upload --- mod/jokers/bigbang.lua | 17 +++++++++++++++ mod/jokers/campingtrip.lua | 18 ++++++++++++++++ mod/jokers/clubwizard.lua | 28 ++++++++++++++++++++++++ mod/jokers/collectiblechaos.lua | 9 ++++++++ mod/jokers/commercialdriver.lua | 12 +++++++++++ mod/jokers/dementiajoker.lua | 23 ++++++++++++++++++++ mod/jokers/diamondbard.lua | 34 +++++++++++++++++++++++++++++ mod/jokers/dynamicduo.lua | 29 +++++++++++++++++++++++++ mod/jokers/flagbearer.lua | 12 +++++++++++ mod/jokers/flipflop.lua | 21 ++++++++++++++++++ mod/jokers/goldenegg.lua | 24 +++++++++++++++++++++ mod/jokers/heartpaladin.lua | 36 +++++++++++++++++++++++++++++++ mod/jokers/royaldecree.lua | 38 +++++++++++++++++++++++++++++++++ mod/jokers/spadearcher.lua | 30 +++++++++++++++++++++++++- mod/jokers/uncannyface.lua | 31 +++++++++++++++++++++++++++ 15 files changed, 361 insertions(+), 1 deletion(-) diff --git a/mod/jokers/bigbang.lua b/mod/jokers/bigbang.lua index 1e45860..3e2ff6d 100644 --- a/mod/jokers/bigbang.lua +++ b/mod/jokers/bigbang.lua @@ -44,6 +44,23 @@ SMODS.Joker { Xmult_mod = mult_val } end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.joker_display_values", ref_value = "Xmult", retrigger_type = "exp" } + } + } + }, + calc_function = function(card) + local text, _, _ = JokerDisplay.evaluate_hand() + card.joker_display_values.Xmult = 1 + card.ability.extra.Xmult * ((text ~= 'Unknown' and G.GAME and G.GAME.hands[text] and G.GAME.hands[text].level + G.GAME.hands[text].played + (next(G.play.cards) and 0 or 1)) or + 0) + end + } end } diff --git a/mod/jokers/campingtrip.lua b/mod/jokers/campingtrip.lua index bbfad48..7f39524 100644 --- a/mod/jokers/campingtrip.lua +++ b/mod/jokers/campingtrip.lua @@ -60,6 +60,24 @@ SMODS.Joker { card = card } end + end, + joker_display_def = function(JokerDisplay) + return { + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "active" }, + { text = ")" }, + }, + calc_function = function(card) + card.joker_display_values.active = G.GAME and G.GAME.current_round.hands_left <= 1 and + localize("jdis_active") or localize("jdis_inactive") + end, + retrigger_function = function(playing_card, scoring_hand, held_in_hand, joker_card) + if held_in_hand then return 0 end + return G.GAME and G.GAME.current_round.hands_left <= 1 and + joker_card.ability.extra * JokerDisplay.calculate_joker_triggers(joker_card) or 0 + end + } end } diff --git a/mod/jokers/clubwizard.lua b/mod/jokers/clubwizard.lua index 174bc13..6716cb8 100644 --- a/mod/jokers/clubwizard.lua +++ b/mod/jokers/clubwizard.lua @@ -44,6 +44,34 @@ SMODS.Joker { card = card } end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "mult", retrigger_type = "mult" }, + }, + text_config = { colour = G.C.MULT }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = lighten(G.C.SUITS["Clubs"], 0.35) }, + { text = ")" } + }, + calc_function = function(card) + local mult = 0 + local text, _, scoring_hand = JokerDisplay.evaluate_hand() + if text ~= 'Unknown' then + for _, scoring_card in pairs(scoring_hand) do + if scoring_card:is_suit("Clubs") then + mult = mult + + card.ability.extra.mult * JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) + end + end + end + card.joker_display_values.mult = mult + card.joker_display_values.localized_text = localize("Clubs", 'suits_plural') + end + } end } diff --git a/mod/jokers/collectiblechaos.lua b/mod/jokers/collectiblechaos.lua index 112b328..143c28c 100644 --- a/mod/jokers/collectiblechaos.lua +++ b/mod/jokers/collectiblechaos.lua @@ -78,6 +78,15 @@ SMODS.Joker { mult_mod = card.ability.extra.mult } end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { text = "+" }, + { ref_table = "card.ability", ref_value = "mult", retrigger_type = "mult" } + }, + text_config = { colour = G.C.MULT }, + } end } diff --git a/mod/jokers/commercialdriver.lua b/mod/jokers/commercialdriver.lua index 45ed394..20753f8 100644 --- a/mod/jokers/commercialdriver.lua +++ b/mod/jokers/commercialdriver.lua @@ -64,6 +64,18 @@ SMODS.Joker { Xmult_mod = card.ability.extra.total } end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.ability.extra", ref_value = "total" } + } + } + } + } end } diff --git a/mod/jokers/dementiajoker.lua b/mod/jokers/dementiajoker.lua index f046768..12c2a38 100644 --- a/mod/jokers/dementiajoker.lua +++ b/mod/jokers/dementiajoker.lua @@ -64,6 +64,29 @@ SMODS.Joker { mult_mod = x*card.ability.extra.mult } end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "mult", retrigger_type = "mult" } + }, + extra = { + { + { ref_table = "card.joker_display_values", ref_value = "odds" }, + } + }, + extra_config = { colour = G.C.GREEN, scale = 0.3 }, + text_config = { colour = G.C.MULT }, + calc_function = function(card) + card.joker_display_values.mult = (G.jokers and G.jokers.cards and #G.jokers.cards or 0) * card.ability.extra.mult + if card.edition and card.edition.negative then + card.joker_display_values.odds = "" + else + card.joker_display_values.odds = localize { type = 'variable', key = "jdis_odds", vars = { (G.GAME and G.GAME.probabilities.normal or 1), card.ability.extra.odds } } + end + end + } end } diff --git a/mod/jokers/diamondbard.lua b/mod/jokers/diamondbard.lua index e23b0e3..10ab58c 100644 --- a/mod/jokers/diamondbard.lua +++ b/mod/jokers/diamondbard.lua @@ -51,6 +51,40 @@ SMODS.Joker { card = card } end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { text = "+", colour = G.C.MULT }, + { ref_table = "card.joker_display_values", ref_value = "mult", retrigger_type = "mult", colour = G.C.MULT }, + { text = ", " }, + { text = "+$", colour = G.C.GOLD }, + { ref_table = "card.joker_display_values", ref_value = "dollars", retrigger_type = "mult", colour = G.C.GOLD }, + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = lighten(G.C.SUITS["Diamonds"], 0.35) }, + { text = ")" } + }, + calc_function = function(card) + local mult = 0 + local dollars = 0 + local text, _, scoring_hand = JokerDisplay.evaluate_hand() + if text ~= 'Unknown' then + for _, scoring_card in pairs(scoring_hand) do + if scoring_card:is_suit("Diamonds") then + mult = mult + + card.ability.extra.mult * (1 + math.floor(to_number(G.GAME.dollars) / card.ability.extra.money_threshold)) * JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) + dollars = dollars + + card.ability.extra.money * JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) + end + end + end + card.joker_display_values.mult = mult + card.joker_display_values.dollars = dollars + card.joker_display_values.localized_text = localize("Diamonds", 'suits_plural') + end + } end } diff --git a/mod/jokers/dynamicduo.lua b/mod/jokers/dynamicduo.lua index 047646c..d397ce3 100644 --- a/mod/jokers/dynamicduo.lua +++ b/mod/jokers/dynamicduo.lua @@ -47,6 +47,35 @@ SMODS.Joker { card = card } end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { text = "+", colour = G.C.CHIPS }, + { ref_table = "card.joker_display_values", ref_value = "chips", colour = G.C.CHIPS, retrigger_type = "mult" }, + { text = " +", colour = G.C.MULT }, + { ref_table = "card.joker_display_values", ref_value = "mult", colour = G.C.MULT, retrigger_type = "mult" } + }, + reminder_text = { + { ref_table = "card.joker_display_values", ref_value = "localized_text" } + }, + calc_function = function(card) + local chips, mult = 0, 0 + local text, _, scoring_hand = JokerDisplay.evaluate_hand() + if text ~= 'Unknown' then + for _, scoring_card in pairs(scoring_hand) do + if not scoring_card:is_face() then + local retriggers = JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) + chips = chips + card.ability.extra.chips * retriggers + mult = mult + card.ability.extra.mult * retriggers + end + end + end + card.joker_display_values.mult = mult + card.joker_display_values.chips = chips + card.joker_display_values.localized_text = localize("k_numbered_cards") + end + } end } diff --git a/mod/jokers/flagbearer.lua b/mod/jokers/flagbearer.lua index 51819e8..b626b3b 100644 --- a/mod/jokers/flagbearer.lua +++ b/mod/jokers/flagbearer.lua @@ -76,6 +76,18 @@ SMODS.Joker { mult_mod = mult } end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "mult", retrigger_type = "mult" }, + }, + text_config = { colour = G.C.MULT }, + calc_function = function(card) + card.joker_display_values.mult = card.ability.extra.mult * G.GAME.current_round.discards_left + end + } end } diff --git a/mod/jokers/flipflop.lua b/mod/jokers/flipflop.lua index 675b24e..cd7e027 100644 --- a/mod/jokers/flipflop.lua +++ b/mod/jokers/flipflop.lua @@ -44,6 +44,8 @@ SMODS.Joker { result = { card.ability.extra.hands, card.ability.extra.mult, + card.ability.extra.discards, + card.ability.extra.chips, localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} } @@ -51,6 +53,8 @@ SMODS.Joker { result = { card.ability.extra.discards, card.ability.extra.chips, + card.ability.extra.hands, + card.ability.extra.mult, localize{type = 'name_text', key = card.ability.extra.joker1, set = 'Joker'}, localize{type = 'name_text', key = card.ability.extra.joker2, set = 'Joker'} } @@ -145,6 +149,23 @@ SMODS.Joker { } end end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { ref_table = "card.joker_display_values", ref_value = "chips", retrigger_type = "mult", colour = G.C.CHIPS }, + { ref_table = "card.joker_display_values", ref_value = "mult", retrigger_type = "mult", colour = G.C.MULT }, + }, + calc_function = function(card) + if card.ability.extra.side == "mult" then + card.joker_display_values.chips = "" + card.joker_display_values.mult = "+" .. card.ability.extra.mult + else + card.joker_display_values.chips = "+" .. card.ability.extra.chips + card.joker_display_values.mult = "" + end + end + } end } diff --git a/mod/jokers/goldenegg.lua b/mod/jokers/goldenegg.lua index 93521e8..79508ae 100644 --- a/mod/jokers/goldenegg.lua +++ b/mod/jokers/goldenegg.lua @@ -51,6 +51,30 @@ SMODS.Joker { colour = G.C.MONEY } end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { text = "+$" }, + { ref_table = "card.ability.extra", ref_value = "dollars" }, + { text = " /round" }, + }, + text_config = { colour = G.C.GOLD }, + reminder_text = { + { ref_table = "card.joker_display_values", ref_value = "localized_text" }, + }, + calc_function = function(card) + card.joker_display_values.localized_text = "(" .. localize("k_round") .. ")" + end, + reminder_text = { + { text = "(" }, + { text = "$", colour = G.C.GOLD }, + { ref_table = "card", ref_value = "sell_cost", colour = G.C.GOLD }, + { text = " Sell Value", colour = G.C.GOLD }, + { text = ")" }, + }, + reminder_text_config = { scale = 0.35 } + } end } diff --git a/mod/jokers/heartpaladin.lua b/mod/jokers/heartpaladin.lua index 6dc7bd6..c7c551b 100644 --- a/mod/jokers/heartpaladin.lua +++ b/mod/jokers/heartpaladin.lua @@ -58,6 +58,42 @@ SMODS.Joker { } end end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { + border_nodes = { + { ref_table = "card.joker_display_values", ref_value = "prefix" }, + { ref_table = "card.joker_display_values", ref_value = "Xmult", retrigger_type = "mult" } + } + } + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = lighten(G.C.SUITS["Hearts"], 0.35) }, + { text = ")" } + }, + calc_function = function(card) + local x_mult = 1 + local text, _, scoring_hand = JokerDisplay.evaluate_hand() + local m = 1.5 + card.joker_display_values.prefix = "X" + if G.GAME.probabilities.normal == 1 then + card.joker_display_values.prefix = "X ~" + m = 1.25 + end + if text ~= 'Unknown' then + for _, scoring_card in pairs(scoring_hand) do + if scoring_card:is_suit("Hearts") then + x_mult = x_mult * m ^ JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) + end + end + end + card.joker_display_values.Xmult = x_mult + card.joker_display_values.localized_text = localize("Hearts", 'suits_plural') + end + } end } diff --git a/mod/jokers/royaldecree.lua b/mod/jokers/royaldecree.lua index 11188a3..b77c369 100644 --- a/mod/jokers/royaldecree.lua +++ b/mod/jokers/royaldecree.lua @@ -55,6 +55,44 @@ SMODS.Joker { } end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { text = "$", colour = G.C.GOLD }, + { ref_table = "card.joker_display_values", ref_value = "count", retrigger_type = "mult", colour = G.C.GOLD }, + { text = " (played)", colour = G.C.GOLD }, + }, + reminder_text = { + { text = "$", colour = G.C.GOLD }, + { ref_table = "card.joker_display_values", ref_value = "count2", retrigger_type = "mult", colour = G.C.GOLD }, + { text = " (held)", colour = G.C.GOLD }, + }, + reminder_text_config = { scale = 0.35 }, + calc_function = function(card) + local count = 0 + local text, _, scoring_hand = JokerDisplay.evaluate_hand() + if text ~= 'Unknown' then + for _, scoring_card in pairs(scoring_hand) do + if scoring_card:is_face() then + count = count + card.ability.extra.dollars * + JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) + end + end + end + card.joker_display_values.count = count + local playing_hand = next(G.play.cards) + local count = 0 + for _, playing_card in ipairs(G.hand.cards) do + if playing_hand or not playing_card.highlighted then + if playing_card.facing and not (playing_card.facing == 'back') and playing_card:is_face() then + count = count + 2 * JokerDisplay.calculate_card_triggers(playing_card, nil, true) + end + end + end + card.joker_display_values.count2 = count + end + } end } diff --git a/mod/jokers/spadearcher.lua b/mod/jokers/spadearcher.lua index 15b96a2..0639f49 100644 --- a/mod/jokers/spadearcher.lua +++ b/mod/jokers/spadearcher.lua @@ -54,7 +54,7 @@ SMODS.Joker { spades = spades + 1 end end - if spades >= 5 then + if spades == 5 then card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_mod return { message = localize('k_upgrade_ex'), @@ -63,6 +63,34 @@ SMODS.Joker { } end end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "chips", retrigger_type = "mult" }, + }, + text_config = { colour = G.C.CHIPS }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = lighten(G.C.SUITS["Spades"], 0.35) }, + { text = ")" } + }, + calc_function = function(card) + local chips = 0 + local text, _, scoring_hand = JokerDisplay.evaluate_hand() + if text ~= 'Unknown' then + for _, scoring_card in pairs(scoring_hand) do + if scoring_card:is_suit("Spades") then + chips = chips + + card.ability.extra.chips * JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) + end + end + end + card.joker_display_values.chips = chips + card.joker_display_values.localized_text = localize("Spades", 'suits_plural') + end + } end } diff --git a/mod/jokers/uncannyface.lua b/mod/jokers/uncannyface.lua index d8a301e..96913b5 100644 --- a/mod/jokers/uncannyface.lua +++ b/mod/jokers/uncannyface.lua @@ -53,6 +53,37 @@ SMODS.Joker { card = card } end + end, + joker_display_def = function(JokerDisplay) + return { + text = { + { text = "+", colour = G.C.CHIPS }, + { ref_table = "card.joker_display_values", ref_value = "chips", colour = G.C.CHIPS, retrigger_type = "mult" }, + { text = " +", colour = G.C.MULT }, + { ref_table = "card.joker_display_values", ref_value = "mult", colour = G.C.MULT, retrigger_type = "mult" } + }, + reminder_text = { + { ref_table = "card.joker_display_values", ref_value = "localized_text" } + }, + calc_function = function(card) + local chips, mult = 0, 0 + local face = 0 + local text, _, scoring_hand = JokerDisplay.evaluate_hand() + if text ~= 'Unknown' then + for _, scoring_card in pairs(scoring_hand) do + if scoring_card:is_face() then + local retriggers = JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) + face = face + 1 + chips = chips + card.ability.extra.chips * retriggers + mult = mult + card.ability.extra.mult * retriggers + end + end + end + card.joker_display_values.mult = mult * face + card.joker_display_values.chips = chips * face + card.joker_display_values.localized_text = localize("k_face_cards") + end + } end } From 2fc2e44a6167e76745fcabbea51552bfc93649b9 Mon Sep 17 00:00:00 2001 From: Matthew Yarnot Date: Mon, 19 May 2025 19:19:15 -0500 Subject: [PATCH 28/91] Club Wizard/Spade Archer sprites for CB setting --- mod/jokers/clubwizard.lua | 7 +++++++ mod/jokers/spadearcher.lua | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/mod/jokers/clubwizard.lua b/mod/jokers/clubwizard.lua index 6716cb8..9444faa 100644 --- a/mod/jokers/clubwizard.lua +++ b/mod/jokers/clubwizard.lua @@ -72,6 +72,13 @@ SMODS.Joker { card.joker_display_values.localized_text = localize("Clubs", 'suits_plural') end } + end, + update = function(self, card, dt) + if G.SETTINGS.colourblind_option then + card.children.center:set_sprite_pos({ x = 1, y = 0}) + else + card.children.center:set_sprite_pos({ x = 0, y = 0}) + end end } diff --git a/mod/jokers/spadearcher.lua b/mod/jokers/spadearcher.lua index 0639f49..4c63b80 100644 --- a/mod/jokers/spadearcher.lua +++ b/mod/jokers/spadearcher.lua @@ -91,6 +91,13 @@ SMODS.Joker { card.joker_display_values.localized_text = localize("Spades", 'suits_plural') end } + end, + update = function(self, card, dt) + if G.SETTINGS.colourblind_option then + card.children.center:set_sprite_pos({ x = 1, y = 0}) + else + card.children.center:set_sprite_pos({ x = 0, y = 0}) + end end } From 65f5d155420d40f5869f8f4922b9f7276bbca9a4 Mon Sep 17 00:00:00 2001 From: Matthew Yarnot Date: Mon, 19 May 2025 19:22:16 -0500 Subject: [PATCH 29/91] CW/SA sprites for colorblind setting --- mod/assets/2x/j_club_wizard.png | Bin 2040 -> 4705 bytes mod/assets/2x/j_spade_archer.png | Bin 2007 -> 4740 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/mod/assets/2x/j_club_wizard.png b/mod/assets/2x/j_club_wizard.png index 78ca4ea5d7c2615a07af61e89133d099b7799c6c..90eb3f8880a230ba2d0b048a95219e96bd7db201 100644 GIT binary patch literal 4705 zcmai22|Sc*+aI!3nkXD;vM*&Rj>Op2Sc{C^WC>ZKBOc2jDx^U*wjs+%Ol8d+P4=Y{ zF_sxJnig_o84{A6;=QMHzW4jS_kGXreSW|Dxv%@WuIJva|9xH8{UljineN#owhIP> z?J+k)*}z~N2tc>+?Evq-B*S=6afH~Io`hA>5YwQ+^l#4j7 zpL~Bnv!8F_9Iz>{0sm9~%b+kIO67%d0Zr9k)m1s}|Jf^hMDF{4_Cx?Q`{4xra{kn` zL23c&udmcpRoT*$rKO)5*1Z>CFo8C6l#yM8+icz~XuM94i@u`&rEzn6UZac>&|u{0 zqm}OP{`WLN*;skQFmHru`M{jSwaar)CUpOhXQdpI%d1P9I3}I<7IL_-zY{$w;oik~ zeR-fai}HN<0kPt$l&e)%OR5TsLlYS|S>Vp&Zg8+GaBJE7>+)c4R!AJ#fJ)WRxI6;& zt!?S?-bul*!iOwZa=x#n#lNB#ApN2l+E~hj?A?jz-B5b;UQmX#YboiAGM(n%)IkZJ z8S2g2-viz!Y0ol<@*$!T;$rv6Av(UuZF4BM$K#Jkzlavv@FnDnCfe}Oc-{JO^%BFj zKY}FZpr&j2AA&Ul^?Ugh1=O?