Compare commits

...

13 commits
1.2.7 ... main

Author SHA1 Message Date
57344e1f00
Add sell value on merge, handle consumables and tags separately 2026-01-16 20:49:30 +01:00
13257d91b3
Update submodule 2025-07-02 18:24:55 +02:00
e1e0ce0661
Speed up animation when many tags exist 2025-06-29 00:09:03 +02:00
8cf3988bcc
Remove redundant files 2025-06-24 14:35:23 +02:00
ac2157799e
Remove legendary background 2025-06-24 14:32:26 +02:00
97d50cbb48
Add escape hatch 2025-06-24 14:32:07 +02:00
270b163c22
Update .editorconfig 2025-05-02 23:42:36 +02:00
396a1ff322
Add Afterimage spectral card 2025-05-02 05:23:15 +02:00
12d7e17b72
Re-add missing localization 2025-04-17 01:26:38 +02:00
98e855e314
Remove redundant localization 2025-04-17 01:22:25 +02:00
961225f64d
Remove leaky challenges 2025-04-17 01:15:28 +02:00
Emik
609172919b
Improve probability restoration
Prevents rigged probabilities from leaking into other cards
2025-04-11 19:31:22 +02:00
Emik
db5ced1704
Fix merge ability 2025-04-05 03:09:42 +02:00
16 changed files with 126 additions and 103 deletions

View file

@ -20,11 +20,11 @@ continuation_indent = 4
# this mean utf8 length , if this is 'unset' then the line width is no longer checked # this mean utf8 length , if this is 'unset' then the line width is no longer checked
# this option decides when to chopdown the code # this option decides when to chopdown the code
max_line_length = lf max_line_length = 120
# optional crlf/lf/cr/auto, if it is 'auto', in windows it is crlf other platforms are lf # optional crlf/lf/cr/auto, if it is 'auto', in windows it is crlf other platforms are lf
# in neovim the value 'auto' is not a valid option, please use 'unset' # in neovim the value 'auto' is not a valid option, please use 'unset'
end_of_line = auto end_of_line = lf
# none/ comma / semicolon / only_kv_colon # none/ comma / semicolon / only_kv_colon
table_separator_style = none table_separator_style = none

View file

@ -1,6 +0,0 @@
{
"Lua.diagnostics.globals": [
"Jen",
"Jane"
]
}

BIN
assets/1x/afterimage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
assets/2x/afterimage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -3,18 +3,18 @@ return {
Blind = { Blind = {
bl_Roland_improbable = { bl_Roland_improbable = {
name = "The Improbable", name = "The Improbable",
text = {"{C:attention}All probabilities", "cannot happen"} text = {"{C:attention}All probabilities", "cannot happen"},
}, },
bl_Roland_nimble = { bl_Roland_nimble = {
name = "The Nimble", name = "The Nimble",
text = {"The first {C:attention}5 cards", "drawn are {C:attention}played"} text = {"The first {C:attention}5 cards", "drawn are {C:attention}played"},
}, },
}, },
Joker = { Joker = {
j_Roland_escapey = { j_Roland_escapey = {
name = "Escapey", name = "Escapey",
text = { text = {
"Destroy {C:attention}tags{} and {C:attention}non-selected", "Destroy {C:attention}tags{} or {C:attention}non-selected",
"{C:attention}consumables{} on use. Level up", "{C:attention}consumables{} on use. Level up",
"the {C:planet}most played hand{} by {C:planet}#1#{}", "the {C:planet}most played hand{} by {C:planet}#1#{}",
"for each destroyed object", "for each destroyed object",
@ -23,49 +23,51 @@ return {
"#3#{C:inactive,s:0.75,E:1}#4#{C:red,s:1.5,E:1}#5#", "#3#{C:inactive,s:0.75,E:1}#4#{C:red,s:1.5,E:1}#5#",
"#6#{C:blue,E:1}#7#{}#8#{C:inactive,s:0.75,E:1}#9#{C:red,s:1.5,E:1}#10#", "#6#{C:blue,E:1}#7#{}#8#{C:inactive,s:0.75,E:1}#9#{C:red,s:1.5,E:1}#10#",
}, },
merge = {"Since no objects apply, merge", "with other ", " jokers"}, merge = {"Since no objects apply, fuse", "with other ", " jokers"},
quotes = { quotes = {
marble = {{"there is no escape..."}}, marble = {{"there is no escape..."}},
normal = { normal = {
{"I can't wait to", "work with you!"}, {"I can't wait to", "work with you!"},
{"Did you need something", "from me?"}, {"Did you need something", "from me?"},
{"Oh! I'm just so", "happy to see you!"}, {"Oh! I'm just so", "happy to see you!"},
{"Can I talk about something irrelevant?", "I promise it won't be long."}, {"Can I talk about something irrelevant?", "I promise it won't be long."},
{"Can you introduce me to your friends?", "Assuming you have friends of course!"}, {"Can you introduce me to your friends?", "Assuming you have friends of course!"},
}, },
scared = { scared = {
{"What am I", "going to do?!"}, {"What am I", "going to do?!"},
{"I'm not scared,", "you are!"}, {"I'm not scared,", "you are!"},
{"Tell me when", "this is over..."}, {"Tell me when", "this is over..."},
{"I can't keep", "looking at this!"}, {"I can't keep", "looking at this!"},
{"Let me go hide in", "this corner... Okay?"}, {"Let me go hide in", "this corner... Okay?"},
}, },
}, },
} },
}, },
Spectral = { Spectral = {
c_Roland_afterimage = {
name = "Afterimage",
text = {
"Add {C:dark_edition}Negative {}to {C:attention}#1#",
"selected card in hand",
"{C:red}#2#{} hand size",
},
},
c_Roland_void = { c_Roland_void = {
name = "Void", name = "Void",
text = { text = {
"{C:red}Destroys {X:red,C:white}all{} owned", "{C:red}Destroys {X:red,C:white}all{} owned",
"playing cards {}for", "playing cards {}for",
"{C:attention}#1# {C:dark_edition}Negative {C:spectral}Cryptids", "{C:attention}#1# {C:dark_edition}Negative {C:spectral}Cryptids",
} },
} },
} },
}, },
misc = { misc = {
challenge_names = { challenge_names = {
c_Roland_Soaring = "Soaring",
c_Roland_Jokerful = "Jokerful", c_Roland_Jokerful = "Jokerful",
c_Roland_Ascension = "Ascension",
c_Roland_Balanced_Jokers = "Balanced Jokers",
}, },
v_text = { v_text = {
ch_c_Roland_Accelerated = {"Start with {C:blue}Accelerated Deck"},
ch_c_Roland_Saint = {"Start with an {C:attention}Eternal {C:legendary}Saint"},
ch_c_Roland_Jokerful = {"Only the {C:common}default Joker{} can appear in shops"}, ch_c_Roland_Jokerful = {"Only the {C:common}default Joker{} can appear in shops"},
ch_c_Roland_Balanced_Jokers = {"All Cryptid and Jen's jokers {C:attention}cannot appear"}, },
} },
}
} }

View file

@ -6,7 +6,7 @@
"author": [ "author": [
"Emik" "Emik"
], ],
"version": "1.2.7", "version": "1.4.5",
"badge_colour": "8BE9FD", "badge_colour": "8BE9FD",
"main_file": "src/main.lua", "main_file": "src/main.lua",
"badge_text_colour": "44475A", "badge_text_colour": "44475A",

@ -1 +1 @@
Subproject commit 5954713389e218b093dafd6121828de978af1dc2 Subproject commit 4f3eae046476664b720a96f91b0e04f388709bbb

View file

@ -36,15 +36,15 @@ function Game:update(dt)
return return
end end
local normal = orig.normal
local mt = { local mt = {
orig = orig, orig = orig,
__index = function(_, k) __index = function(_, k)
return k == "normal" and 0 or orig[k] return k == "normal" and 0 or orig[k]
end, end,
__newindex = function(_, k, v) __newindex = function(_, k, v)
if k ~= "normal" or v ~= 0 then orig[k] = (k == "normal" and v == 0) and normal or v
orig[k] = v
end
end, end,
} }

View file

@ -1,5 +1,4 @@
local jokerful = {banned_cards = {}} local jokerful = {banned_cards = {}}
local balanced_jokers = {banned_cards = {}}
SMODS.Challenge { SMODS.Challenge {
key = "Jokerful", key = "Jokerful",
@ -7,40 +6,9 @@ SMODS.Challenge {
restrictions = jokerful, restrictions = jokerful,
} }
local deck = {}
local card = {eternal = true, cry_absolute = true}
SMODS.Challenge {
key = "Ascension",
deck = deck,
jokers = {card},
rules = {custom = {{id = "Roland_Saint"}, {id = "Roland_Accelerated"}}},
}
if Cryptid then
SMODS.Challenge {
key = "Soaring",
deck = deck,
jokers = {card},
sleeve = "sleeve_cry_equilibrium_sleeve",
rules = {custom = {{id = "Roland_Saint"}, {id = "Roland_Accelerated"}}},
}
end
SMODS.Challenge {
key = "Balanced_Jokers",
restrictions = balanced_jokers,
rules = {custom = {{id = "Roland_Balanced_Jokers"}}},
}
G.E_MANAGER:add_event(Event { G.E_MANAGER:add_event(Event {
trigger = "immediate", trigger = "immediate",
func = function() func = function()
if Jen or Jane then
deck.type = Jen and "b_jen_nitro" or "b_jane_nitro"
card.id = Jen and "j_jen_saint" or "j_jane_saint"
end
F.foreach( F.foreach(
F.filter( F.filter(
G.P_CENTERS, G.P_CENTERS,
@ -49,14 +17,6 @@ G.E_MANAGER:add_event(Event {
function(v) table.insert(jokerful.banned_cards, {id = v.key}) end function(v) table.insert(jokerful.banned_cards, {id = v.key}) end
) )
F.foreach(
F.filter(
jokerful.banned_cards,
function(v) return v.id:sub(1, 6) == "j_cry_" or v.id:sub(1, 6) == "j_jen_" end
),
function(v) table.insert(balanced_jokers.banned_cards, {id = v.key}) end
)
return true return true
end, end,
}) })

View file

@ -26,7 +26,7 @@ end
local function is_mergeable_with(it) local function is_mergeable_with(it)
return function(card) return function(card)
return it.rank ~= card.rank and return it.rank ~= card.rank and
card.key == "j_Roland_Escapey" and not card.label == "j_Roland_escapey" and not
(card.ability or {}).eternal (card.ability or {}).eternal
end end
end end
@ -52,16 +52,19 @@ SMODS.Joker {
blueprint_compat = false, blueprint_compat = false,
loc_vars = function(_, _, card) loc_vars = function(_, _, card)
local loc_self = G.localization.descriptions.Joker.j_Roland_escapey local loc_self = G.localization.descriptions.Joker.j_Roland_escapey
---@diagnostic disable-next-line: undefined-global
local sinister = (Jen or {}).sinister or G.escapey_sinister
local quotes = loc_self.quotes local quotes = loc_self.quotes
local merge = G.jokers local merge = G.jokers
and F.count(F.filter(G.jokers.cards, is_mergeable_with(card))) > 1 and F.count(F.filter(G.jokers.cards, is_mergeable_with(card))) > 0
and loc_self.merge or {} and loc_self.merge or {}
local normal = (merge[1] or (Jen or Jane or {}).sinister) and {} or local normal = (merge[1] or sinister) and {} or
pseudorandom_element(quotes.normal, pseudoseed("EscapeyQuotes")) or {} pseudorandom_element(quotes.normal, pseudoseed("EscapeyQuotes")) or {}
local scared = (merge[1] or not (Jen or Jane or {}).sinister) and {} or local scared = (merge[1] or not sinister) and {} or
pseudorandom_element(quotes.scared, pseudoseed("EscapeyQuotes")) or {} pseudorandom_element(quotes.scared, pseudoseed("EscapeyQuotes")) or {}
return { return {
@ -84,6 +87,7 @@ SMODS.Joker {
G.escapey_debugger(F.reduce(context, "", function(acc, _, next) return acc .. ", " .. next end, pairs):sub(2)) G.escapey_debugger(F.reduce(context, "", function(acc, _, next) return acc .. ", " .. next end, pairs):sub(2))
end end
end, end,
---@param card Card
Bakery_can_use = function(_, card) Bakery_can_use = function(_, card)
return not card.debuff and can_use() and ( return not card.debuff and can_use() and (
#G.GAME.tags ~= 0 or #G.GAME.tags ~= 0 or
@ -91,27 +95,40 @@ SMODS.Joker {
F.any(F.filter(G.jokers.cards, is_mergeable_with(card))) F.any(F.filter(G.jokers.cards, is_mergeable_with(card)))
) )
end, end,
---@param card Card
Bakery_use_button_text = function(_, card) Bakery_use_button_text = function(_, card)
return card.debuff and "DEBUFFED" or if card.debuff then
((#G.GAME.tags == 0 and not return "DEBUFFED"
F.any(G.consumeables.cards, destructible) and end
F.any(F.filter(G.jokers.cards, is_mergeable_with(card)))) and "MERGE" or "ESCAPE")
return #G.GAME.tags == 0 and F.count(G.consumeables.cards, destructible) == 0 and
F.any(F.filter(G.jokers.cards, is_mergeable_with(card))) and "FUSE" or "ESCAPE"
end, end,
---@param card Card
Bakery_use_joker = function(_, card) Bakery_use_joker = function(_, card)
local hand, object_count = common_hand(), F.count(F.filter(G.consumeables.cards, destructible)) + #G.GAME.tags if card.debuff then
return
end
local consumables = F.filter(G.consumeables.cards, destructible)
local consumable_count = F.count(consumables)
local object_count = consumable_count + #G.GAME.tags
if object_count == 0 then if object_count == 0 then
local sum = 0 local level_sum, sell_sum = 0, 0
F.foreach( F.foreach(
F.filter(G.jokers.cards, is_mergeable_with(card)), F.filter(G.jokers.cards, is_mergeable_with(card)),
function(v) function(v)
sum = sum + v.ability.extra.level_up_by * (v.getEvalQty and v:getEvalQty() or 1) level_sum = level_sum + v.ability.extra.level_up_by * (v.getEvalQty and v:getEvalQty() or 1)
sell_sum = sell_sum + v.sell_cost * (v.getEvalQty and v:getEvalQty() or 1)
v:start_dissolve({HEX("57ecab")}, nil, 1.6) v:start_dissolve({HEX("57ecab")}, nil, 1.6)
end end
) )
card.ability.extra.level_up_by = card.ability.extra.level_up_by + sum card.ability.extra.level_up_by = card.ability.extra.level_up_by + level_sum
card.sell_cost = card.sell_cost + sell_sum
return
end end
local function update(name, chip, mul, lv, notif, snd, vol, pit, de) local function update(name, chip, mul, lv, notif, snd, vol, pit, de)
@ -148,6 +165,8 @@ SMODS.Joker {
end end
end end
local hand = common_hand()
if hand == "all" or hand == "allhands" or hand == "all_hands" then if hand == "all" or hand == "allhands" or hand == "all_hands" then
update(localize("k_all_hands"), "...", "...", "") update(localize("k_all_hands"), "...", "...", "")
elseif G.GAME.hands[hand or "NO_HAND_SPECIFIED"] then elseif G.GAME.hands[hand or "NO_HAND_SPECIFIED"] then
@ -159,19 +178,24 @@ SMODS.Joker {
) )
end end
F.foreach( if consumable_count == 0 then
F.filter(G.consumeables.cards, destructible), local trigger = #G.GAME.tags >= 30 and "immediate" or "before"
function(v) local delay = #G.GAME.tags >= 30 and 0 or 1 / #G.GAME.tags
v:start_dissolve({HEX("57ecab")}, nil, 1.6)
end
)
F.foreach( F.foreach(
G.GAME.tags, G.GAME.tags,
function(v) function(v)
G.E_MANAGER:add_event(Event({trigger = "immediate", func = fast_delete(v)})) G.E_MANAGER:add_event(Event {trigger = trigger, blocking = #G.GAME.tags < 30, delay = delay, func = fast_delete(v)})
end end
) )
else
F.foreach(
consumables,
function(v)
v:start_dissolve({HEX("57ecab")}, nil, 1.6)
end
)
end
level_up_hand(card, hand, nil, object_count * card.ability.extra.level_up_by) level_up_hand(card, hand, nil, object_count * card.ability.extra.level_up_by)

View file

@ -1,5 +1,3 @@
SMODS.Sound({key = "void", path = "void.ogg"})
local function can_use() local function can_use()
return not ((G.play and #G.play.cards > 0 or return not ((G.play and #G.play.cards > 0 or
G.CONTROLLER.locked or G.CONTROLLER.locked or
@ -9,6 +7,15 @@ local function can_use()
G.STATE ~= G.STATES.PLAY_TAROT) G.STATE ~= G.STATES.PLAY_TAROT)
end end
SMODS.Sound({key = "void", path = "void.ogg"})
SMODS.Atlas {
px = 71,
py = 95,
key = "afterimage",
path = "afterimage.png",
}
SMODS.Atlas { SMODS.Atlas {
px = 71, px = 71,
py = 95, py = 95,
@ -16,6 +23,42 @@ SMODS.Atlas {
path = "void.png", path = "void.png",
} }
SMODS.Consumable {
key = "afterimage",
set = "Spectral",
pos = {x = 0, y = 0},
cost = 6,
atlas = "afterimage",
config = {extra = {amount = 1, hand = -1}},
loc_vars = function(_, _, card)
return {vars = {card.ability.extra.amount, card.ability.extra.hand}}
end,
can_use = function(_, card)
return can_use() and card.ability.extra.amount == #Bakery_API.get_highlighted()
end,
use = function(_, card, _, _)
for _, v in ipairs(Bakery_API.get_highlighted()) do
G.E_MANAGER:add_event(Event {
delay = 0.1,
func = function()
v:set_edition({negative = true})
v:juice_up(0.5, 0.5)
return true
end,
})
end
G.E_MANAGER:add_event(Event {
delay = 0.1,
func = function()
G.hand:change_size(card.ability.extra.hand)
Bakery_API.unhighlight_all()
return true
end,
})
end,
}
SMODS.Consumable { SMODS.Consumable {
key = "void", key = "void",
set = "Spectral", set = "Spectral",