#💻・modding-dev
1 messages · Page 638 of 1
change_base
im pretty sure the restrictions table takes a function now so you can use that to return all other blinds to ban them
main.lua:1970: [SMODS wath_mod "jokers.lua"]:235: attempt to index field 'wath_mod_rainbow_joker' (a nil value)
is this a syntax error
im getting a simular crash "game.lua:1432 attempt to index global 'pokermon_config' [a nil value]
can someone help?
if this is not a mod youre making i recommend asking #⚙・modding-general
this is probably your pokermon folder being nested
what does that mean?
idk what that means
what part
so how do i fix that
idk why it is nil in the first place but you can do what you do in loc_vars to have a fallback value
oh
are you calling reset_wath_mod_rainbow_joker anywhere
yeah at the bottom
i basically just copied the ancient joker code and edited the effect so i think it has to be a syntax error i made while modifying it
i have tried like 3 different ways to manually set wath_mod_rainbow_joker but it still says it's a nil value
can you show me your current code including reset_game_globals
can i see reset_game_globals too
also this is not what i meant, i meant using the local suit line in calculate
what is that
i see
that's why i asked this, call means to use the function and the function is not used anywhere so it wont do anything
still not working even after adding the global reset script
If I want to check for the presence of a specific modded joker, can I check for the key “prefix_jokerkey” or does that not work
did you restart the run
j_modprefix_key
https://github.com/nh6574/VanillaRemade/wiki#how-do-i-get-if-the-player-has-a-certain-card
Missing the j, got it
y'know i like to imagine i have the capacity to be intelligent
I’m taking ownership of the blue seal to modify it, part of what I want to do involves making it not perform its usual function but it seems like overriding the calculate function just adds to it rather than replacing it. Is there a way for me to modify its usual calculate function?
normally I'd say change its internal name (not key)
but i think seals are an exception to that piece of vanilla logic
im pretty sure blue seal is hardcoded so you would need to patch it
I was worried that might be the case, I think I approached my implementation from a bad starting point
Basically I’m making a guy that makes it so blue seals give negative planets
I implemented it by taking ownership of the blue seal, but since I’m not replacing the calculate but adding to it, they just end up making the negative planet as well as the normal planet
you can hook create_card and check if it uses seed blusl :3
Interesting may
Okay*
So the card creation knows that it’s coming from a blue seal
yes
Sounds like I can skip taking ownership entirely which is probably the best practice
i would say take ownership is usually best practice
this is just easier and take ownership is janky in this case exactly
Good to know moving forward, this was my first time using take ownership so I wasn’t really sure what the limits were
in theory smods should unhardcode this to make take ownership work properly
lucky cards had the same problem but its fixed now iirc
also i wanted to ask what SEALS was in this context? i know its related to the mod, but i dont know what i would replace it with if i put it in my code.
global table that seals on everything stores stuff in, such as those functions
SEALS = {
get_ids = function()
-- this is SEALS.get_ids
end
}
Trying to figure out how to hook SMODS.add_card for the blue seal thing but struggling to find documentation for add_card and how to access stuff like the seed thing to detect if the card was created by a blue seal
it needs to be vanilla create_card, not the smods one
the seed is the key append
Yeah I realized that after I sent it and already swapped that
The key thing should be all I’m missing then
the key is “blusl”?
idk what you mean key (i think you're confused??) but key_append is "blusl" for blue seals
Yeah I mean key append
Trying to do it like this
First time doing any sort of hook thing so I could easily be going about it wrong
Is there a specific location I should be putting the hook?
I couldn't find that one, is it not under Card
I see
Alright let me try that
How I tried to implement it
Somehow, all it managed to do is make it so blue seals give random planets when the joker is present
I managed to code my way into making a joker that reverts blue seals to their prebuff state
Oh ignore this I already see an issue
i see several issues
local create_card_ref = create_card
function create_card(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append)
local card = create_card_ref(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append)
if next(SMODS.find_card("key")) and key_append == "blusl" then
card:set_edition("e_negative")
end
return card
end
Yeah it's making more sense. I am very very curious on how exactly whatever I did the first time led to the blue seals acting that way
because you removed all the arguments
specifically forced_key where the planet key is passed
ohhhhhh
Can't get the key_append to work, figuring out through debug prints that it isn't working but the joker check is. Tried "key_append == "bluesl"" and "card.key_append == "bluesl"" Simple mistype
wouldnt i need to copy the code for any functions in that get_X_same code?
i mean yes, you would need to actually copy the code to get a copy of the code
I stop coding for a month and all of a sudden it's like I'm relearning how to speak English
🙂↕️
I need to make some more jokers and get the gears turning again
Thanks for the help the negative planet joker works now, hopefully now I can properly hook things in the future when it comes up
is there a way to check if your last action was either playing a hand or a discard?
Should be very easy to code but wanted to know if that already exists somewhere so I don't repeat code
is there a better way of doing this? this also doesn't work if any +mult comes after it
this is trying to balance by a %
[i can't find what AiJ does because it uses a custom return]
it depends on what you mean by action and what you want to do
cant you search for the return on the guthub
git
not for this no
I got it done but thanks for asking
I just did this, even if it's very dirty
Also is saving anything in G going to cause issues other than possibly causing issues with other mods?
that's how i would do it
afaik you can return balanced = true or smth like this to o plasma deck effect
it might conflict with other mods so i would add the mod prefix
also saving things in G doesn't save them to the savefile
yeah but that's not what theyre doing
Yeah luckily I don't need them to be saved to the mod file, G.GAME is for that though, right?
it's like a custom plasma
yes, but it's all or nothing
no good if you want to balance a percentage
yes
I thought it does support number value for balanced
I'll check but i don't think so
i dont think so
relatively, yeah, should be easy
the main thing you'd have to do is
decide what it would mean to balance over 100%
maybe just clamp it in 0 < n < 100
maybe optionally allow -100 < n < 100
This kind of effect present in mp challenge
Where balance actually destabilize
anyone know of a mod that extends SMODS.Center or similar that i can look at as reference?
From the key of a blind, how can I access to the blind itself? Like say I have bl_club and I want to know if this blind is a showdown boss or not (most likely by checking blind.boss.showdown, but the problem is getting the blind object)
edit: G.P_BLINDS[key]
K new question
I want to add a keybind to my mod but I want the user to be able to change the key. How do I do that in my config menu? I know Handy has keybinds that we can change but the code it all over the place I don't understand shit 💀 and i don't know any other mod that lets you change keybinds
after that i just set key_pressed = SMODS.current_mod.config.key in the SMODS.Keybind, but i need a config menu for that to begin with
anyone know why the contents of G.GAME.elle_popup_shops[shop].data aren't saving?
-- Init game hook - initialize game variables
local igo_hook = Game.init_game_object
function Game:init_game_object()
local g = igo_hook(self)
-- Add shops here
g.elle_popup_shops = {
-- Rebecca Shop
rebecca = {
default_reroll = 4, -- Reroll cost when shop resets
reroll = 4, -- Actual reroll cost
reroll_cost = 2, -- Cost increase amount
reset_on_open = true,
data = {}, -- This isn't saving for some reason???
first_open=true
},
-- [[BIG SHOP]]
spamton = {
reset_on_open = true,
default_reroll = 4, -- Reroll cost when shop resets
reroll = 4, -- Actual reroll cost
reroll_cost = 2, -- Cost increase amount
data = {},
first_open=true
}
}
return g
end```for context, it's a table that contains tables that contain `:save`d cards
_ _ i'm going out for a few days, i'll worry abt this once i get back
Remove the ''
Is the table being emptied, or are the contents replaced with 'MANUAL_REPLACE'?
i'm doing the same thing that i was doing before i refactored the code to fit multiple shops
and it was working fine before
i know it's going into the table just fine bc the contents persist when closing and opening the shop
it only disappears when exiting the run and going back in
but other things like the reroll cost persist
you can see the full file here
-# https://github.com/ellestuff/ellejokers/blob/main/lua/popup_shop.lua
how do i get a hands current mult?
this is a future me problem, i'm going out for new years 
I have created a patch for latest version of balatro
that removes junk code
and optimizes images and font
to use less file size
i doubt i can post it on GitHub though
You definitely cant
Oh yeah definitely not
also this patch will make game not compatible with most mods for sure
why does the halving get undone immediately when a card is scored
SMODS.Seal {
key = 'flint',
atlas = 'wacleseals',
pos = { x = 11, y = 1 },
badge_colour = HEX("e56a2f"),
config = { extra = { xmult = 2 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.seal.extra.xmult } }
end,
calculate = function(self, card, context)
if context.before and context.cardarea == G.play then
mult = mod_mult(math.max(math.floor(mult * 0.5 + 0.5), 1))
hand_chips = mod_chips(math.max(math.floor(hand_chips * 0.5 + 0.5), 0))
update_hand_text({ sound = 'chips2', modded = true }, { chips = hand_chips, mult = mult })
end
if context.main_scoring and context.cardarea == G.play then
return {
xmult = card.ability.seal.extra.xmult
}
end
end
}
if context.initial_scoring_step and context.cardarea == G.play then
return {
mult_mod = (-mult)+math.max(math.floor(mult * 0.5 + 0.5), 1)
chip_mod = (-hand_chips)+math.max(math.floor(hand_chips * 0.5 + 0.5), 0)
}
end
SMODS.Atlas {
key = "LBPHC",
path = "LBPHC.png",
px = 71,
py = 95,
}
SMODS.Atlas {
key = "LBPLC",
path = "LBPLC.png",
px = 71,
py = 95,
}
SMODS.DeckSkin {
key = "LBP",
suit = "Spades",
loc_txt = "LittleBigPlanet",
palettes = {
{
key = 'lc',
ranks = {'Jack', 'Queen', "King"},
display_ranks = {"King", "Queen", "Jack"},
atlas = "LBPLC",
pos_style = 'ranks',
},
{
key = 'hc',
ranks = {'Jack', 'Queen', "King"},
display_ranks = {"King", "Queen", "Jack"},
atlas = "LBPHC",
pos_style = 'ranks',
colour = HEX("1E2C30"),
},
},
}
ah thanks
question: how do i stop this from unflipping the card when selecting it
if card.facing == 'front' and context.cardarea ~= G.play then card:flip() end
if card.facing == 'back' and context.cardarea == G.play then card:flip() end
if card.facing == 'front' and context.after and context.cardarea == G.play then card:flip() end
change the second if to an elseif
what's happening is the first if flips the card, then the second one checks its facing, it's facedown, and it flips it
INFO - [G] 2025-12-30 02:58:03 :: ERROR :: StackTrace :: Oops! The game crashed
[SMODS _ "src/utils.lua"]:3255: attempt to concatenate local 'atlas_key' (a boolean value)
Stack Traceback
===============
(1) Lua local 'handler' at file 'main.lua:612'
Local variables:
msg = string: "[SMODS _ \"src/utils.lua\"]:3255: attempt to concatenate local 'atlas_key' (a boolean value)"
(*temporary) = Lua function '?' (defined at line 31 of chunk [SMODS _ "src/logging.lua"])
(*temporary) = string: "Oops! The game crashed\
"
(2) LÖVE metamethod at file 'boot.lua:352'
Local variables:
errhand = Lua function '?' (defined at line 598 of chunk main.lua)
handler = Lua function '?' (defined at line 598 of chunk main.lua)
(3) Lua field 'create_sprite' at Steamodded file 'src/utils.lua:3255'
Local variables:
X = number: 5.68212
Y = number: 2.93309
W = number: 2.45854
H = number: 3.30146
atlas = nil
pos = table: 0x33d94fe8 {y:0, x:2}
atlas_key = boolean: false
(*temporary) = C function: assert
(*temporary) = nil
(*temporary) = string: "SMODS.create_sprite called with invalid atlas key: "
(*temporary) = boolean: false
(*temporary) = number: 151
(*temporary) = table: 0x33fd8958 {click_offset:table: 0x33aab498, children:table: 0x33e13ed0, sprite_pos:table: 0x337d2bb0, T:table: 0x33df0368, offset:table: 0x33db2280, role:table: 0x33de2918 (more...)}
(*temporary) = number: 2.70674
(*temporary) = string: "attempt to concatenate local 'atlas_key' (a boolean value)"
(4) Lua method 'set_sprites' at Steamodded file 'src/overrides.lua:1744'
Local variables:
self = table: 0x33ab1510 {click_offset:table: 0x33f9fbe0, palette:table: 0x33d91de8, children:table: 0x33dcd7f0, ambient_tilt:0.2, parent:table: 0x33feb108, alignment:table: 0x33d666b8 (more...)}
_center = nil
_front = table: 0x33fb35f8 {lc_atlas:cards_1, pos:table: 0x33fb36e8, value:King, hc_atlas:cards_2, name:King of Spades, suit:Spades}
_atlas = nil
_pos = table: 0x33d94fe8 {y:0, x:2}
(*temporary) = table: 0x33dcd7f0 {front:table: 0x33fd8958, center:table: 0x33d65550, back:table: 0x33de8588, shadow:table: 0x33df8800}```
crashes when loading custom skin, says there is no atlas key?
still does it
then you have additional problems to solve, which i am unable to divine from the tiny out of context code snippet you have provided
here's the entire code ig
SMODS.Seal {
key = 'fish',
atlas = 'wacleseals',
pos = { x = 4, y = 0 },
badge_colour = HEX("3e85bd"),
config = { extra = { chips = 11, prepped = nil, upgraded = nil } },
loc_vars = function(self, info_queue, card)
return { vars = {
card.ability.seal.extra.chips
} }
end,
calculate = function(self, card, context)
if card.facing == 'front' and context.cardarea ~= G.play then card:flip()
elseif card.facing == 'back' and context.cardarea == G.play then card:flip() end
if card.facing == 'front' and context.after and context.cardarea == G.play then card:flip() end
if context.press_play then
if context.cardarea == G.hand then
card.ability.seal.extra.prepped = true
end
end
if context.to_area == G.hand and card.ability.seal.extra.prepped then
context.other_card.ability.perma_bonus = (context.other_card.ability.perma_bonus or 0) + card.ability.seal.extra.chips
card.ability.seal.extra.upgraded = true
end
if context.setting_blind or context.hand_drawn then
card.ability.seal.extra.prepped = false
if card.ability.seal.extra.upgraded then
card.ability.seal.extra.upgraded = false
return {
message = localize("k_upgrade_ex"),
colour = HEX("3e85bd"),
}
end
end
if context.end_of_round then
card.ability.seal.extra.prepped = false
end
end,
}
I dont understand why the mod crashed when it tried loading the sprite
descriptions = {
Other = {
tcg_ox_seal = {
name = "The Ox",
text = {
"test",
},
},
},
},
misc = {
labels = {
tcg_ox_seal = "The Ox",
},
},
ah thanks
it's stated in the docs btw
the patch works with mods
Does anyone have an idea on why it crashes when i switch to my custom 3-card) deck skin?
SMODS.Atlas {
key = "LBPHC",
path = "LBPHC.png",
px = 142,
py = 190,
}
SMODS.Atlas {
key = "LBPLC",
path = "LBPLC.png",
px = 142,
py = 190,
}
SMODS.DeckSkin {
key = "LBP",
suit = "Spades",
loc_txt = "LittleBigPlanet",
palettes = {
{
key = 'lc',
ranks = {'Jack', 'Queen', "King"},
display_ranks = {"King", "Queen", "Jack"},
atlas = "LBPLC",
pos_style = 'ranks',
},
{
key = 'hc',
ranks = {'Jack', 'Queen', "King"},
display_ranks = {"King", "Queen", "Jack"},
atlas = "LBPHC",
pos_style = 'ranks',
colour = HEX("1E2C30"),
},
},
}
atlas in SMODS.DeckSkin must include your mod prefix iirc
here's mine as an example, sgt is the mod prefix
do you happen to know why there is extra contrast on my hc skin
add field hc_default
hc_default = true, right
cuz i did that
ugh its not the same color as the other cards
then I have no idea
uhhh i just reduced the base skin contrast by 25%
hc default is for the unchanged cards
Careful, rule 4 in #📜・modding-rules
u think it would be possible to have a custom description on the display cards like the FoJ packs?
here
played_this_round is a boolean value that is equal to if the hand has been played this round.
wrong image fuck
ah ok
so smth like this
Yes.
ok all of a sudden it ain't working
SMODS.Seal {
key = 'eye',
atlas = 'wacleseals',
pos = { x = 4, y = 1 },
badge_colour = HEX("4b71e4"),
config = { extra = { xmult = 1, eye_gain = 0.25 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.seal.extra.xmult, card.ability.seal.extra.eye_gain } }
end,
calculate = function(self, card, context)
if context.before and context.main_eval and G.GAME.hands[context.scoring_name] and G.GAME.hands[context.scoring_name].played_this_round then
card.ability.seal.extra.xmult = 1
return {
message = localize("k_reset"),
colour = HEX("4b71e4")
}
end
if context.before and context.cardarea == G.play and not G.GAME.hands[context.scoring_name].played_this_round then
card.ability.seal.extra.xmult = card.ability.seal.extra.xmult + card.ability.seal.extra.eye_gain
return {
message = localize { type = 'variable', key = 'a_xmult', vars = { card.ability.seal.extra.eye_gain } },
colour = HEX("4b71e4")
}
end
if context.main_scoring and context.cardarea == G.play then
return {
xmult = card.ability.seal.extra.xmult
}
end
end
}
-# supposed to gain xmult before scoring
-# it just does nothing
update: i found a fix
...which was to REWRITE THE FUCKING CODE AND DERIVE IT FROM A JOKER THAT DOES A SIMILAR THING 😭
I am very surprised nobody did this yet https://github.com/Steamodded/smods/pull/1148
Hopefully this makes the lives of people who use custom cardareas way easier
Is there a function similar to SMODS.merge_lists but instead of making a list of cards that are in EITHER of the lists, it makes a list of cards that are in BOTH lists?
cough cough Ortalab Mythos shop slot cough
Lmfao
chat how do i make a new deck
wdym new deck
a custom deck for my mod
as in a red deck or as in deck skin
a new deck, all stone cards with seals
oh yeah, blindside at home
-ish
ehhhhhhh
oh hey, I can help with this
in my mod, my code basically just iterates through all the cards and changes them after instantiation
dunno if that’s standard or even the best way of doing it, but oh well
here’s my code for a mult deck:
SMODS.Back {
key = "multDeck",
atlas = "Deck",
pos = {
x = 0,
y = 0
},
loc_txt = {
name = "Mult Deck",
text = {"{C:MULT}+4{} mult", "Added cards also get changed"}
},
apply = function(self)
G.E_MANAGER:add_event(Event({
func = function(self)
for _, _card in pairs(G.playing_cards) do
_card:set_ability('m_mult')
end
return true
end
}))
end,
calculate = function(self, card, context)
if context.playing_card_added then
for _, _card in pairs(context.cards) do
_card:set_ability('m_mult')
end
end
end
}
For the cards that don't come from the deck you should be hooking Card:set_ability
I do use that; what specifically would you change?
like is it the context or something?
loc_vars = function(self, info_queue, card)
info_queue[#info_queue+1] = G.P_SEALS.wip_burned
local numerator, denominator = SMODS.get_probability_vars(card, card.ability.extra.burn_num, card.ability.extra.burn_denom)
return { vars = { numerator, denominator } }
end,
calculate = function(self, card, context)
if context.after and context.cardarea == G.jokers then
for _, scored_card in ipairs(context.scoring_hand) do
if SMODS.pseudorandom_probability(card, 'wip_flame', card.ability.extra.burn_num, card.ability.extra.burn_denom) then
scored_card:set_seal("wip_burned")
return {
message = localize('k_burn'),
colour = G.C.SUITS.Hearts
}
end
end
end
end
im trying to make a joker that's supposed to give scored cards a seal but it only applies to one card per scored hand when i debug
when you return from a function the function ends
Ah
Well im trying to make it based on a 1 in 5 chance for every card, so is there any way to do that?
don't return in the loop
if you want a message for each card then you can use SMODS.calculate_effect({message = localize('k_burn'),colour = G.C.SUITS.Hearts}, card) but it needs to be in an event for the correct timing
tyyyyy :3
Do modded hands like Spectra get stored in evaluate_poker_hand(), or is there somewhere else where they all end up while a hand is calculated?
functions don't store stuff but that's where all hands are calculated yes
if you need the current hand outside an object i would recommend just getting it with mod calculate
If it's not the function that stores the hand criteria, then how does it tell?
The function is called by G.FUNCS.get_poker_hand_info which does a couple more things and returns all info about the poker hand and then it is passed to the different functions/contexts as local variables
So, it's G.FUNCS.get_poker_hand_info that stores hand criteria for all modded hands?
functions don't store things
If you need the function that evaluates each hand you need to look at each SMODS.PokerHand.evaluate https://github.com/Steamodded/smods/wiki/SMODS.PokerHand
I was looking in G.FUNCS.get_poker_hand_info and evaluate_poker_hand() in hopes of making this. I figure it shouldn't be so difficult to re-calculate the Chips and Mult and poker hand type, but knowing which hand to downgrade to (i.e., Three of a Kind -> Pair) has got me stumped.
i have locvars like this, but when i instantly crash instead when entering the shop.
i might be stupid
does it have to be a valid hand with the cards selected or just the next one down in the poker hand menu?
The next one down.
that's in G.handlist
Try putting G.GAME and G.GAME.probabilities.normal in parentheses (), see if that clears that up.
post the crash also
the crash was from me calling the config table "ability"
I mean that, say, a Straight Flush or a Straight Spectrum would be bumped down to a Straight, a Full House to a Two Pair, and a High Card would go unaffected.
i might be a idiot
so it needs to be a valid hand then
you can already get all the contained hands in context.poker_hands, just pair that with G.handlist
So, I chop off the first element in context.poker_hands and evaluate off of the new first element instead?
And how do I call that context from within a patch that's not within the SMODS.Blind{} code?
why are you doing it in a patch
So it happens 'fore any other hand-scoring calculation is done.
i was saying to just get the next hand in G.handlist and then just replace the current hand with that
But wouldn't that judge a Straight Flush as a Four of a Kind instead of a Straight?
Or just the next one down that's also in context.poker_hands?
yes
(well all of them are in poker_hands but the next non-empty one)
I also want these hands to have the Chips/Mult of the next-lowest-down hand type. Do I just run G.FUNCS.get_poker_hand_info(G.play.cards) a second time?
that context that i linked does that
how does steamodded make it so the wheel boss blind displays denominator changes? vanilla localization doesnt allow for it and i cant seem to find it in SMODS code or localization
It takes ownership of it in src/game_object.lua
Is there resources pac, with all the codes from the vanilla Jokers?
Because trying to figure the Odd and Even mechanic
Do the duplicate edition descriptions without formatting in v_dictionary ever even get used?
anyone know of a mod that extends SMODS.Center or similar?
how can I debuff all cards besides face cards for a boss blind
if context.debuff_card and not context.debuff_card:is_face(true) then return {debuff = true} end
cheers
what's the best way to remove some ranks from the deck? [i'm working on a deck, not a joker]
like config.no_faces but more loose
Remove them manually in an event in apply
gotcha 👍 thanks
how can i add a variable to G.GAME that'll get made on every new run so i can use it in functions later?
use SMODS.current_mod.reset_game_globals function and check run_start
SMODS.current_mod.reset_game_globals = function(run_start)
if run_start then G.GAME.thegremlin = {} end
end
as example.
i see
where do i put this tho? if i want it to always be present?
just in the main lua file so this code always runs?
put this anywhere where the code would run yeah
i see, thanks!
is there any way to check if a deck skin is currently being used?
how does pos_style = ‘rank’ work and how is it different from ‘suit’?
is rank just any cards that i want?
finished the base mahjong custom hand, now I need to figure out if I can implement custom rewards and bonuses based on the yaku of a hand instead of just making more mahjong hand variants as seperate poker hands
ex. golden joker's extra cash but gained from scoring a specific custom hand variation
ok so I found the logic for to do list, how would I implement it as a constant game state instead of being tied to the joker object?
you can save stuff in a table in G.GAME using something like the code just above
pos style ranks is according to the ranks you listed on ur lua
suit is according to a suit
and deck is for 52
collab by default does the face cards iirc
implemented first yaku in the same implementation as royal flush on straight flush, hopefully I can detect that in G.GAME
I forget if todo list actually puts down royal flush or not
what
mahjong
yeah I'll eventually make the honor tiles
and the mahjong deck will start with the increased selection and hand size
i got an idea
sure
not related
but u making ur mahjong
and my mom pestering me with facebook invites
scrabble balatro
so if i wanted aces and face cards id use rank and put ace, king, queen, jack in the ranks?
yes
how would the sprites be laid out?
np
i usually use the collab pos style with all the face cards on one sprite, its just like that right
yeah but u have to add the ace i guess
got it
I've got a joker that's supposed to disable the boss if the first discard of the round is a single card with a seal, but when the ability is triggered the game crashes. It only started doing that after I added the part at the bottom to juice the joker up. I'm going a bit mad trying to fix it when I'm probably just missing something obvious
try removing the context.blueprint_card or
ok, I'll report back in a sec
wait no its this message i think
oh what about it
no idea but the discarded card is nil for some reason
weird
I'm very new to this so forgive me if I sound foolish
still trying out what you said anyway
i would try removing that message too
maybe it removes the card before the message but that shouldnt happen normally
yeah it's weird
im trying to patch this line in better_calc.toml in smods:
if SMODS.has_enhancement(scoring_hand[i], 'm_glass') and scoring_hand[i]:can_calculate() and SMODS.pseudorandom_probability(scoring_hand[i], 'glass', 1, scoring_hand[i].ability.name == 'Glass Card' and scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) then
i have this in my toml file:
pattern = "if SMODS.has_enhancement(scoring_hand[i], 'm_glass') and scoring_hand[i]:can_calculate() and SMODS.pseudorandom_probability(scoring_hand[i], 'glass', 1, scoring_hand[i].ability.name == 'Glass Card' and scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) then"
but then it says in the log:
WARN - [♥] Pattern 'if SMODS.has_enhancement(scoring_hand[i], \'m_glass\') and scoring_hand[i]:can_calculate() and SMODS.pseudorandom_probability(scoring_hand[i], \'glass\', 1, scoring_hand[i].ability.name == \'Glass Card\' and scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) then' on target 'functions/state_events.lua' for pattern patch from Cryptid\lovely\Probability.toml resulted in no matches
What is going on here??
whats the priority of your file
also i think glass cards are taken ownership of
yeah i dont see that smods patch apply in my dump
eh it's like 5 and smods is like -10 that shouldn't be the issue here i think if i understand how it works
i dont want the trigger code i want the destroy code
im trying to fix the cryptid's glass stake
so in glass stake it should treat every card like glass so it can break but with just lower probability
well no idea how cryptid does it but that's the destroy code i just linked
it just doesn't work lmao
well, in the toml file it just references the outdated smods line
It gives a chance for cards to break after scoring right?
and also i think it just hasnt been updated to the newest smods probability thingy
so i tried to fix that, but ran into this issue
oh i see the code
Im pretty sure it could just use stake calculate now that thats a thing
If the goal is just to destroy cards
targeting glass cards is not going to work
this ^
ah i see
And to force cards to shatter you could set a flag on the card right before destroying and check for that in a hook to whatever smods function checks if a card should shatter
Well then it would also affect card destruction that isnt from the stake
SMODS.shatters im sleepy
true
ughhh bruuuh i see
and here i was thinking that it would be an easy fix 🥲
well thanks anyway guys <3
it's not hard, give me a sec
from reading the code i assume only playing cards are destroyed right?
yea, yea
i mean yea its prob not super hard but its late tho so i think imma just go to sleep lol
something like this
local glass = {
object_type = "Stake",
name = "cry-Glass Stake",
key = "glass",
pos = { x = 2, y = 2 },
atlas = "stake",
applied_stakes = { "cry_ruby" },
modifiers = function()
G.GAME.modifiers.cry_shatter_rate = 30
end,
shiny = true,
order = 21,
colour = HEX("ffffff8f"),
calculate = function(self, context)
if context.destroy_card and context.cardarea == G.play and G.GAME.modifiers.cry_shatter_rate
and SMODS.pseudorandom_probability(self, 'cry_shatter', 1, G.GAME.modifiers.cry_shatter_rate) and not SMODS.is_eternal(context.destroy_card) then
card.cry_glass_trigger = true
return { remove = true }
end
end
}
local smods_shatters_ref = SMODS.shatters
function SMODS.shatters(card)
return card.cry_glass_trigger or smods_shatters_ref(card)
end
tyvm! ❤️
you could make this more global by moving the calculate to SMODS.current_mod.calculate if other things use that modifier in the future
i see
also, speaking of broken cryptid stakes there's azure stake, which is supposed to take away 20% off of joker values but it uses cryptid's misprintize lib and upon the first look it wasn't really obvious to me what went wrong there so i just kinda gave up on it for now 🫠
oh dont ask me about misprintize i refuse to deal with that
Ahahahahh yea i'd imagine
my jokers stay with their values intact as Thunk intended
Azure stake should be simple enough i imagine, just hook Card.set_ability and use Cryptid.manipulate on the card if its a joker
yeaaa i kinda thought of that but idk, isn't that more like a hack tho?
I mean i dont see any issues with it
Card.set_ability is the same function that sets all the base values
So thats the perfect place to apply the azure stake modifier
huh alright i'll look into it ig, thanks
i just didn't even really look that deep into it i kinda just skimmed through it, trying to understand
This isn't reevaluating the played hand like I want it to. Whenever I select/deselect a card, the innermost code-block activates, but I want it to only kick in when the hand is played. What do I do?
LAPSEMS.next_lowest_valid_hand = function(table_of_hands, allotted_decreases )
local allotted_decreases = allotted_decreases or 1
local number_of_decreases = 0
local final_product = nil
local forbidden_hands = {'High Card', 'None'}
for i = 1, #G.handlist do
current_hand = G.handlist[i]
if #table_of_hands[current_hand] > 0 then
number_of_decreases = number_of_decreases + 1
final_product = current_hand
if number_of_decreases >= allotted_decreases then
return final_product
end
end
end
return final_product or (forbidden_hands[1] or 'High Card')
end
calculate = function(self, blind, context)
if not blind.disabled then
if context.evaluate_poker_hand then
blind.triggered = true
blind:wiggle()
replace_scoring_hand = LAPSEMS.next_lowest_valid_hand(context.poker_hands)
end
end
end
i think you would need to set a flag in context.press_play to prevent selection
but i personally think it would be more player friendly if the code worked on selection too
the first problem is that you're not returning replace_scoring_hand
Do you mean
return {
replace_scoring_hand = LAPSEMS.next_lowest_valid_hand(context.poker_hands)
}
```?
how do i detect if a card was retriggered?
?
i'm trying to make a joker that adds half of a base card's chips to the joker when that card gets retriggered
Is it possible to add a dummy playing card that doesn't show up in the UI, only for calculation purposes?
I want to do a calcaulation for a tarot card without making my code super redundant, and I feel like having a dummy card be created for the purpose of it sounds like a decent option.
What's going on in the code:
- A copy of the selected card is created and its suit is changed into... say a spade.
- The selected card is "merged" with the dummy card, to keep consistency with the rest of my code.
- The dummy card is deleted
I plan on having all this behind the scenes so the dummy card doesn't actually.. exist when playing.
There's probably a better way of doing this, but I don't know how.
You mean like a fake card?
Kind of. Just something behind the scenes that doesn't have card randomly appear out of nowhere, if that makes sense
lowkey im scared this is super obvious and i should just read the manual
couldn't you just manually construct the card object to gaslight your functions
what do they use
thats probably a good idea but sounds kinda jank
not really vanilla does it all the time
What do your functions do?
mostly with ui shit
also you could just
allow your functions to take suit and rank
instead of a card
---@param card1 table | Card
---@param card2 table | Card
---@return table
--- Returns the combined rank table of two cards.
CARDMERGE.MergeRankTables = function(card1, card2)
local rankTable1 = CARDMERGE.InitRankTable(card1)
local rankTable2 = CARDMERGE.InitRankTable(card2)
return MergeTables(rankTable1, rankTable2)
end
function MergeTables(table1, table2)
local output = {}
for key, _ in pairs(table1) do
output[key] = true
end
for key, _ in pairs(table2) do
if not table1[key] then
output[key] = true
end
end
return output
end```
what does CARDMERGE.InitRankTable do
sanitization
let me see
---@param card table | Card
---@return table
--- Returns the rank table of a card.
CARDMERGE.InitRankTable = function(card)
if not card:rank_table() or card:rank_table() == {} then
if SMODS.has_no_rank(card) then
return {}
else
local output = {}
output[card:get_id()] = true
return output
end
end
return card:rank_table()
end```
a solution is really close i just don't know what the output format is lmao
what is rank_table 💀
anyway what i'm getting at is this
Couldn't you just put the suit in the table in the card manually?
you can check if that card input in InitRankTable is an object with suit and rank
and use those values accordingly
i could but that would involve a whole other function
No, it wouldn't.
if card.rank and card.suit then
and whatever is needed for proper output
and then any card can be a rank and suit object instead
Also nothing can ever be equal to {}
beautiful
i was overcomplicating it WAY too much
i have indirectly contributed to this mod two times now
probably because this is really cool
is making a new context just calling a different value on calculate_joker
don't do it on calculate_joker
do it on calculate_context
SMODS.calculate_context
also make sure to do SMODS.calculate_effect on the return value
if you want return tables to work
No, it's SMODS.trigger_effects
they are two different functions
you seem to be correct
also why are you just always here
this stuff is making my head hurt
i wanna code a free reroll shop joker , how can i code it?
and a joker that can make all suits to 1 suit
You mean a joker that makes all rerolls free?
What part of the code in this creates the area where you can click the logo? im clicking the middle of the R and its still processing it 😭
(I only took the code from someone else...)
furthermore, this is the area the logo occupies, so its not like the sprite has that big of dead space in it
holy peak
actually at the y axis it isnt that bad
but like
on the x axis it stretches longer than the O
but its not the same with the left side
its still bigger
I’m not entirely sure what might be going wrong here
Tho I’m surprised 12 is your base scale value since mine is 6 and appears far larger
for some reason its extremely small
even though its the same size (i adjusted the logo size accordingly to what i saw)
Are you using any patches for this? My version does but I don’t remember if Thunder did too
oh yeah if its any help, the transformation of the logo is a bit jagged (like the movement wasnt centralized)
What are you doing in the push/pop patch? That seems to be the most significant variable and I can’t quite seem to understand it
I really just copied it since I have 0 clue how this actually works right now...
😭
Well here’s my menu patch file if you wanna reference that https://github.com/the-Astra/Maximus/blob/dev/lovely/menu.toml
ok! i figured it out!! tnx
Gonna poke in here as well, is there anyone here that knows a decent amount about Balatro text inputs that I could bounce off fixing some really annoying UI bugs with?
I'm probably not able to help ya' but I'd be interested to hear about the Bugs 
ive done exactly one text input after learning the dark arts of UI coding so theres like a 30% chance i can fix it
obligatory curator plug
Any tips for improvement?
so sick but maybe even too much, very high res in comparision to vanilla artstyle
aside of that, fire
haha thanks! might have something to do with what it does 😛
I might simplify it a bit
Bit too much, yet, it looks great.
Keep a copy of the original if you are going to simplify it. Just because uh...
that's gonna make downscaling to 1x a true goofy experience (cough cough that Exotic joker from Cryptid that draws entire deck to hand when Blind is selected cough)
easiest will probably be to scale up my 1x, didnt realize that in the 2x the highest detail is 2x2
fix letters a bit and still so fire
truee
Hey guys, I have a mod idea but I don't have much time to develop it, I mainly do Game Design, does anyone want to collaborate?
Also, DM me if you're interested to join me on a game project. I've got some of the game design ready. I'll be using Monogame framework with C#. It's a 2D platformer, there's more details if anyone is interested, just DM me. Looking mainly for programmers, maybe game designers, artists and sound designers.
Maybe not fixing that is a cost I am willing to pay, the fade effect is epic on its own
How does one rescore a joker?
I was thinking about this one, I mean... As far as I understand, you technically want a Red-Seal effect... Right??
The Joker scores, with it's Eddition and Enhancement and all, and then it just does it again right after (right?)
No, I want it to be like calling SMODS.score_card on a playing card, but for jokers.
isn't that what Card.calculate_joker does?
unless that doesnt repeat joker retriggers but i kinda would expect it to
was this from reddit?
No, all that does is calculate the main joker effect.
I made a reddit post, asking for people to help me, but since no-one responded I'm working on the art myself
And "eval_card()" doesn't work because.....?
It doesn't include retriggers.
Wait SMODS.Blind doesnt have update function????
I meant the card art did you get it from a reddit post?
nope, I made it
Ah. alright cause I remember seeing sometinhg like that is that someone on reddit made a concept of third tier vouchers that somehow the art looked like mixels and well not fit for balatro style which I ended up remaking those into the faithful balatro style or if the art of the third vouchers would look like if they are in balatro: #🎨・fan-art message
but honestly glad to know that you made the art and you're improving it
cause I thought when I saw the mixels I thought you got it from a reddit post that had those mixels
so anyways, good job!
thanks! no mixels tho, did em by hand
Another one, done with the art for now tho, soo much work
how can i make a proper cardarea
Who want to buy basmati fried rice
I mean at this point I'm just looking at the Joker-Section from "state_events.lua" -> "evaluate_play" in my Lovely-Dump
Best thing you could do is to grab that section and rewrite it for one Joker and put that into a function
I'm currently testing it a bit and that approach seems to work fine.. I kinda can't help any further than that, sorry :/
local my_card_area = CardArea(
x_position, y_position, -- Position on screen
width, height, -- Dimensions
{ -- Configuration table
card_limit = 5, -- Maximum cards
type = 'custom', -- Area type
highlight_limit = 1, -- Max highlighted cards
card_w = G.CARD_W, -- Card width
card_h = G.CARD_H -- Card height
}
)
Try adding something like this to your start_run override, doesnt do much without any supporting functions but it gets you a place you can emplace cards into
Who want to Bur fried rice
how do i calculate context on a custom card i have (extended from SMODS.Center)
thanks mods ahah
NO!
hook SMODS.calculate_context to also calculate the new cardarea
thank you
alright so i have this code here in the glass stake and the problem is
that the probability procs way too much than it should and also
sometimes the glass break effect happens and sometimes just the regular card destroy effect
calculate = function(self, context)
if context.destroy_card and context.cardarea == G.play and G.GAME.modifiers.cry_shatter_rate then
for i = 1, #G.play.cards do
if SMODS.pseudorandom_probability(self, 'cry_shatter', 1, G.GAME.modifiers.cry_shatter_rate) and not SMODS.is_eternal(context.destroy_card) then
G.play.cards[i].cry_glass_trigger = true
return { remove = true }
end
end
end
end,
local smods_shatters_ref = SMODS.shatters
function SMODS.shatters(card)
return card.cry_glass_trigger or smods_shatters_ref(card)
end
^code in the override file
anyone have any ideas?
you shouldnt be doing a for loop
context.destroy_card already happens individually for each card
i see
i just didnt understand how to then reference the card because
in the original code that 'N wrote:
local glass = {
object_type = "Stake",
name = "cry-Glass Stake",
key = "glass",
pos = { x = 2, y = 2 },
atlas = "stake",
applied_stakes = { "cry_ruby" },
modifiers = function()
G.GAME.modifiers.cry_shatter_rate = 30
end,
shiny = true,
order = 21,
colour = HEX("ffffff8f"),
calculate = function(self, context)
if context.destroy_card and context.cardarea == G.play and G.GAME.modifiers.cry_shatter_rate
and SMODS.pseudorandom_probability(self, 'cry_shatter', 1, G.GAME.modifiers.cry_shatter_rate) and not SMODS.is_eternal(context.destroy_card) then
card.cry_glass_trigger = true
return { remove = true }
end
end
}
local smods_shatters_ref = SMODS.shatters
function SMODS.shatters(card)
return card.cry_glass_trigger or smods_shatters_ref(card)
end
theres a problem that "card" is a nil reference
yeah it should be context.destroy_card.cry_glass_trigger
ok, looks like that works, tyvm <3
Anyone know if there's a way to change an atlas through the config menu?
wdym
Like could I do something like
SMODS.Atlas{
key = 'Jokers', --atlas key
path = function(self,args)
return config.alternate_sprites
end,
px = 71,
py = 95
}
To be able point to a different image in the atlas while the game is open
??
i mean yeah
like a switch case i guess?
or if u can put "n" as part of your key
have something that changes "n"
heres the code, idk what i did wrong
good idea
better screenshot
post full crash log
try changing ur trinket key to CJmod_gold
same result
your reddit gold is pointing to something that doesnt exist
missing Trinket field during loc init
wdym?
G.localization.descriptions.Trinket is nil
if you're using localization files, it's easy to add entries like this:
descriptions = {
Trinket = {
trk_CJMod_gold = {
name = "Reddit Gold",
text = {
"{C:money}+#1#{} blind payout",
},
},
},
},
however, if you insist on using loc_txt field on each of your object, then the following snippet is needed:
SMODS.current_mod.process_loc_text = function()
G.localization.descriptions.Trinket = {}
end
anyone know how I could redeem a voucher, say when joker's conditions meet
check vanillaremade wiki, in the section to make a random voucher
(you can ignore the random part)
30% is decent chances
how do i detect if a card was retriggered? i wanna make a joker that scales in chip value whenever cards get retriggered
Let me roll out of bed
i made my custom center but why wont it get moved to the correct cardarea (its meant to be the one at the right)
and why is it stretched
code
SMODS.add_card({set = 'Trinket', area = G.trinkets})
is there a way to find if the current booster pack is celestial?
goner
Code?
same code, i just removed the emplace and added the area key in the add_card
its this:
SMODS.add_card({set="Trinket", area = G.trinkets})
i dont understand how calculate_context works. can i use it to detect if a card was retriggered?
i looked in here but i still dont really get it
No, it just calls a context.
too much text, gimmie it in 10 words
modding balatro cannot be summed up in just ten words
thats what a bad modder would say
like as in making or playing mods
makin mods
@queen crescent
you have to learn a whole programming language and how to properly reference documentation + reference materials like VanillaRemade
GOD DAMNIT
i know how to program blud i just dont know how to put that in balatro
John
Oh dear
i forgot to lock him in there 😭
well you've gotta set up the modding framework, learn what metadata is required for the framework to read a mod, and then learn how to interact with the API that the framework provides
which is all explained in the initial link you were given :)
can you sum it up in 5 emojis
Might have killed the idoled panopticon
⚗️ 🚂 ⁉️ 💌 🔰
I don't get the last one, the inverted chevron
I also don't know the exact meaning of the alembic emoji even though I've seen it around
japanese symbol for beginner
its like a symbol for learner drivers in japan i think?
はい
yea the last one is literally just beginner, something something everyone starts somewhere
and ⚗️ looks like 🥀
mostly known for being a super long text to speech input
magnifying glass tilted right is also popular
🔎
its just mag_right
how do i see what scaling a joker would give without actually scaling it
save the original value, scale it, then measure the difference, then unscale it
im spitballing here
man what
💔
i dont think we have future sight for joker values gng
the issue with the joker is
actually let me just show you it
it displays what the scaled payout is instead of the actual payout
well
the actual value
because the actual payout is what the scaled payout would be
Imagine using this to make all the consumables green #ShillingMyMod
mega-green...
Oh wait I can't post sendhimtotheprincipalsofficeandhavehimexpelled gif because I'm oppressed in this server
you can send the gif if instead of sending a link you upload the file
this code is trying to get the chips from a card that was retriggered and add them to a joker. i'm using a custom context that was patched in (seen in 2nd image) but it doesn't trigger when in an if statement with context.individual. how do i get this to work?
@daring fern i used a patch you made for detecting retriggers, do you know a workaround to this? i cant think of a way to get the exact card that was retriggered to get its nominal chip value
what do you have against dream journal :broken
Okay, here's my issue: I have these text inputs that are directly associated with sliders because I'm trying to replicte some general functions of image editing programs
I have code on both sides that's meant to replace the value of the slider or text input when one is changed. The slider example is here:
But often times when I do this replacement, the cursor/input position gets dealigned in the process (if the change changes the number of active digits in the ref value), which then results in, say, selecting the text input and only being able to change the second digit
And before I added a thing to set a minimum number of letters in the text input, it was even worse, because sometimes it wouldn't let me tab all the way to the right because the ref value was two digits and it clamps the position to the length of the ref value
I have a full helper function I made specifically to try to do this as basically "change the value and then call transpose" but even it seems faulty
looks scary
I'm lookin at vanilla remade and i see that sometimes, nil, true is returned instead of not returning
It says its for joker retrigger purposes but is doing this type of return necessary for non-joker effects
wdym
like for consumable code?
for global mod calc code
well uhh
i don't know if thats being retriggered
it might be helpful for post trigger stuff I think
true
like context.post_trigger might not fire if the calculate doesn't return
depends on if you want things to be able to posttrigger on your calculate
I don’t think mod calc functions can be retriggered or post triggered
I could be wrong though
Scarier than anything I've ever worked with
cant you just have a separate text input value which sets the internal value to itself after being updated so it doesnt "live update" but when you confirm changing the text input value the slider value and the internal value update
that sounds like it would solve the problem
I have something similar for a separate text input, though I still encounter some of the cursor offset problems
how do i get the chip value from a card that was retriggered? im hooking into insert_repetitions to try and find the card that retriggered, and then get the chip value from it.
right now im testing it by printing the card's chip value, and it does it when patching it but NOT when hooking it fsr
is there something i'm doing wrong?
anyone there?
you're not actually hooking SMODS.insert_repetitions
you're overwriting insert_repetitions (without smods)
ohhh
do i remove SMODS from the top one, or add SMODS to the bottom one?
sry for late response
sadly i got another problem
same
We all have problems
for choosing cards for criteria most common rank I need check card.base.nominal? Because rn I'm checking card.base.value 
value is correct
if i wanna take money from the player, do i need to use the money buffer?
i see the tooth in vanilla remade just uses ease_dollars() without involving the buffer
is that fine?
I am trying to figure out what be the proper codding for a Joker that looks for hands (pair, fullhouse exc) made using pairs
Is it similar to the color sin jokers code or may looking something too complicated
lmfao mood
okay i figured out what caused the problem but not how to solve it
Because trying out to make Jokers that trigger on Even and Odd values
so im hooking SMODS.insert_repetitions to try and get the chip value of a retriggered card, but this only seems to work when the card is retriggered by a red seal, NOT when a joker (sock, hack, etc.) retriggers it!
i know this because ive been printing the chip value in the original function and it only returns a non-zero value when retriggered by red seals
is there a better way to get the chip value of any card that gets retriggered? this has been bugging me literally all day 😭
am i doing something wrong with this? i want these to use the undiscovered sprite of vouchers
SMODS.UndiscoveredSprite {
key = "Deal",
prefix_config = { atlas = false },
atlas = "Voucher",
pos = { x = 8, y = 2 },
}```
effect_card is the card that is calling the retriggers.
Also you can't put cards in G.GAME
as long as it's not during scoring
im trying to pass a variable from main.lua to my joker's code
i thought global variables had to start with G.GAME
hi so im having a weird issue
basically if i discard a card in the final_scoring_step then hooking G.FUNCS.draw_from_play_to_discard to draw it to hand makes it draw the cards face down
you can put the card's key or index or whatever into a variable in G.GAME, you can't put the card object itself into it though
despite specifying "up" in the draw carsd call
dumb question but how do i do that
you can probably put effect_card.base.value into your variable and then use that in your joker
help
which one is the card that gets retriggered
How would I modify a vanilla joker when I obtain a specific modded joker?
(context: we're trying to make a legendary joker that prevents others from resetting (ex: hit the road))
hi so how would you prevent a card from being flipped temporarily?
hook card:flip
how do you update the chips on a card that had its rank changed right before being scored?
i have a joker that Strength-Tarots scored cards before the hand is scored, but they still score with their old chip values before the strength upgrade
how are you changing the rank
try removing the event
i copied this almost 1-1 from the vanillaremade strength tarot code
except i removed the deselect function at the end and changed the select context to scoring_hand
does that affect my answer
seems like it'd affect this pretty majorly in ways i dont understand
ill give it a shot though
well i do understand
i trust you
it will fuck up the animation tho
should i remove all the events from this code
yyyeahh
just the modify rank one for now
thats what i was worried about ^^"
if there's a way to do the animation it will be by delaying the sprite change rather than using an event, but i don't know if there's functionality for that at the moment
that's unfortunate
ok it's not documented but modify_rank has a way to delay the sprites it seems
the third argument has to be true, but i dont know if it does it automatically or you need to change the sprite manually
playing_card:set_sprites(nil, playing_card) it looks like
you would put that in the event
nil
ah no it takes a card prototype i think
playing_card:set_sprites(nil, G.P_CARDS[playing_card.config.card_key]) maybe
like this?
all of the context.scoring_hand[i] inside the event
it's like that in vanillaremade
it's the key for the card as rank_suit
yayyy it works, thank you so much for your help!
is there a way to change what the blueprint compatibility ui looks like? instead of it saying "compatible" and "incompatible" with a coloured background, I want it to say different things with no background
also @red flower if youre still available, is there a way to get the chip value from a retriggered card? ive been strugglign with that all day today and moved onto another joker to work on after failing to make it work
I only ask because I tried toying with it myself and even the smallest edit makes it say "ERROR"
you would need to patch or take_ownership of blueprint and brainstorm
no idea sorry
no worries, thanks for all the help! ^^
ok, I'll see what I can do with that
oh wait, would that change what it looks like for all jokers that use it? (blueprint, brainstorm, etc) I only want it to look different for a specific joker
do you want the display on bp/bs to look different for a joker or do you want a joker that has a display similar to bp/bs? i didnt fully get it
the former, I know how to implement the display on a joker, but when I tried to change what it said (even if I only changed a single letter) it would only say "ERROR" in-game
I'm just wondering how (or if) that can be avoided
wait i forgot G.FUNCS.blueprint_compat exists
you can hook that and change the values when it's copying your card
how did you do it
I essentially just copied the code from vanilla remade
when I tried to change where it said "compatible" and "incompatible" that's what made it say "ERROR"
ohh then you wanted the latter lmao maybe i didnt ask the question correctly
oh yeah sorry
can you show me where you changed it
sorry for the shoddy visual
remove the whole localize(...) and put the string there instead
localize looks for k_compatible in the localization file
ok cool, I'll try that out, thanks
I'll report back if it doesn't work or I'm too lost
loc_vars is called whenever you hover a card to show its description, and that's not how SMODS.scale_card is supposed to be used I believe
why should it completely fall apart into pieces when its used in a unexpected way
not even the full system
just the modifying part
SMODS.scale_card is a lot more complicated than you think
well i need to predict what it does
im litterally looking at the source code for it right now
i see nothing that should fall apart and crumble
that's what I meant
looking at SMODS.scale_card alone isn't enough to understand the problem
local ret = obj:calc_scaling(_card, card, initial, scalar_value, args)
is like the one place i can see causing a problem
mostly because its the one place actually using card
see?
besides args.ref_table = args.ref_table or card.ability.extra
also the scaling message thing
a card is still needed to display attention text
what are you trying to do exactly
the card seemly poisons the well affter being displayed
predict the future
for the player of course
huh
full joker code
so you're trying to scale the payout
SMODS.Joker {
key = "green",
atlas = "awesomejokers",
rarity = 2,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = false,
discovered = true,
cost = 6,
pos = { x = 2, y = 4 },
config = { extra = { dollars = 0, scale = 1 } },
loc_vars = function(self, info_queue, card)
-- the player might be fooled if its not a scale above what its currrently
local fake_table = {
["dollars"] = card.ability.extra.dollars,
["scale"] = card.ability.extra.scale
}
SMODS.scale_card(card, {
ref_table = fake_table,
ref_value = "dollars",
scalar_value = "scale",
no_message = true
})
return { vars = { card.ability.extra.scale, fake_table["dollars"] } }
end,
calculate = function (self, card, context)
if context.end_of_round and context.main_eval then
SMODS.scale_card(card, {
ref_table = card.ability.extra,
ref_value = "dollars",
scalar_value = "scale",
no_message = true
})
end
end,
calc_dollar_bonus = function(self, card)
return card.ability.extra.dollars
end
}
golden joker if it was awesome
you probably don't need 40% of this 🪱
ah
well its supposed to be altered to show it
you want this joker to show the proper future value when a calc_scaling joker is present
what breaks here
i tested it
after hovering over it
all calc_scaling breaks
or perhaps
the calc_scaling on the joker breaks
no return value
presumely
i would have to do a smods patch to really see what's going on
calc_scaling = function(self, card, other_card, initial_value, scalar_value, args)
if scalar_value > 0 and not args.dont_repeat then
return {
override_scalar_value = { -- this will override the scalar_value
value = scalar_value*2, -- set the scalar_value to X
-- other calculation return keys accepted here, timing is before the scaling event
},
}
end
end
this is the calc_scaling im testing with
the args.dont_repeat is from old code
doens't hurt nobody
tbh I have never used calc_scaling
not all mods need one, for balancing purposes of course
calc_scaling could be getting overwritten
no i added
prints in
prints just
stopped running
i disabled some mods
seems to be a
mod incompatibility 😨
ouch
im betting aiko
so updating their mod then testing
never mind i have the latest version
not them
hmm
stocking stuffering
i'll update that
is there any alternatives for a while true?
i mean
what's the goal exactly
eliminate repeats from a random picker so i don't have to use a giant list full of every individual valid card number
happy 13th month smods
We're back in the building again
how do i automatically debuff jokers if they're to the left of a specific joker (and rebuff them when they aren't to the left of that joker)?
currently the code doesn't automatically make the jokers to the left of the joker debuffed, and it takes two hands (1 to make them visually debuff, and 2 to show the debuffed jokers don't trigger)
how can i make them debuff and undebuff automatically depending on their position to the eldritch joker?
is there a context that triggers constantly whenever the game is active that makes this work?
oh thank you\
i know this is unrelated but what did jimbo do to deserve that 😭
Chat what are the variables for chip requirement texts on blind select screen
did he look outside
it was beautiful
looks outside
no photographs
no ballots
looks outside
🫠
i think messing with update() broke the entire game
i was trying to debuff jokers to the left of the eldritch, and undebuff jokers to the right of it
in real time
is there a simpler/less jannk way to do this xD
hook Card:stop_drag maybe?
does that do what it sounds like it does
in my head i wanted this joker to function as an easy way to debuff whichever jokers you needed at a certain time
so if you arent able to drag it i feel like that takes some of that purpose away
Tbh I would suggest doing this with something that updates only when the joker's position updates
oh?
Because SMODS.debuff_card sets a permanent flag
oh no stop_drag is when a card is no longer being dragged
So you don't need to do it every frame
ohhhhh
i also wanna know if there's just a simpler way to write this code, im writing it at like 3 in the monring (its actually 4 am now)
ill try anything once
/hj
ill see you guys later, might try the stop drag thing tmrw!
ok so i wrote this:
local set_ability_ref = Card.set_ability
function Card:set_ability(ability, from_edition, mute)
set_ability_ref(self, ability, from_edition, mute)
if G.GAME.modifiers.cry_jkr_misprint_mod and self.ability.set == "Joker" then
Cryptid.manipulate(self, { value = G.GAME.modifiers.cry_jkr_misprint_mod})
end
end
but it doesn't work
does it just do nothing
yea, looks like
am i doing this right?
I'm trying to make a joker that removes the effect of Steel Cards so they don't give their mult, I'm assuming it would use the take_ownership function but I'm not sure what to do to get rid of an effect
Only give xmult if the joker cannot be found
<@&1133519078540185692>
oh that's a clever workaround
did what I say break a rule?
nah there was a scam account
ah I didn't see that
they get deleted very fast
is there a context or flag or something for whenever a run is opened (including continuing a run)?
I know Throwback has something like that as an unlock condition maybe? I'd assume so at least
but I don't know that much
depending on what you want it to interact with, you might have to put the result in an event so that the thing loads first
does load() trigger whenever the object is first loaded
i havent used it before
it runs when the game is loaded
oh good!
how so
something like this https://github.com/wingedcatgirl/MintysSillyMod/blob/next/jokers/bonkdice.lua#L34
like this?
that check_jokers_left_of_eldritch function is in main.lua
okay so. you only need to put it in an event if you want it to interact with something that hasn't loaded yet
the event would start by returning false if the thing hasn't loaded yet
that way it would wait until the thing loads
do all of the jokers load at the same time
ahh by taking the check_jokers_left_of_eldritch() out of the event?
lemme try
yeah that broke it jfdsk
it actually DID work when it was in the event which is nice
would the code to make this happen need to go with the code for the joker in question I want this effect for, or would it have to go somewhere else? I just want to ask before I potentially waste time because I don't know much about this sort of thing
what is the correct way of writing this apply function to call SMODS.change_play_limit() and increase the play limit from default to 14?
key = "mahjong_red",
pos = { x = 0, y = 0 },
config = { discards = 1},
loc_vars = function(self, info_queue, back)
return { vars = { self.config.discards } }
end,
apply = function(self, back)
G.GAME.SMODS.change_play_limit(9)
end
}```
might need to fix this```lua
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then
if i > 1 then
Cryptid.manipulate(G.jokers.cards[i+1], { value = card.ability.extra.vm })
SMODS.calculate_effect({ message = "X" ..card.ability.extra.vm, colour = G.C.FILTER, instant = true}, card)
end
if i < #G.jokers.cards then
Cryptid.manipulate(G.jokers.cards[i-1], { value = card.ability.extra.vm })
SMODS.calculate_effect({ message = "X".. card.ability.extra.vm, colour = G.C.FILTER, instant = true}, card)
end
end
end
fixed:
SMODS.Back {
key = "mahjong_red",
pos = { x = 0, y = 0 },
config = { discards = 1 },
loc_vars = function(self, info_queue, back)
return { vars = { self.config.discards} }
end,
apply = function(self, back)
G.E_MANAGER:add_event(Event({
func = function()
SMODS.change_play_limit(9)
return true
end
}))
end
}```
how would I add cards to G.playing_cards in the event function?
similar to the checkered deck code but instead of swapping suits adding extra copies of each card and some other cards
unless G.playing_cards is a table and I can just directly append to it but that doesn't seem right
im making my patch into a python script on github
so it can be massed used for testing
"it fully works with all mods"
"hypothetical increased performance on IoTs and even more hard drive friendly"
I'm trying to make steel cards not give mult when a specific joker (mechsupport) is owned, I've got this code for that but they're still giving mult regardless. I have kind of frankensteined the code together so maybe there's just something I'm missing?
SMODS.Enhancement:take_ownership('m_steel',
{
loc_vars = function(self, info_queue, card)
if not ((function()
for i, v in pairs(G.jokers.cards) do
if v.config.center.key == "j_mysingingjokers_mechsupport" then
return true
end
end
end)()) then
return { vars = { card.ability.h_x_mult } }
end
end
},
true
)
Hey, quick question for anyone... I want to start building a mod that introduces a joker that increases the playable hand size from 5 to 6. (This would introduce the concept of having 6 of a kind, flush 6, and split houses which I'd implement later) However I'm struggling to find what file actually controls that aspect of the game. It has to exist somewhere but I just don't know where to look, or if it's even accessible. Any ideas?
got it
SMODS.Back {
key = "mahjong_red",
pos = { x = 0, y = 0 },
config = { discards = 1 },
loc_vars = function(self, info_queue, back)
return { vars = { self.config.discards} }
end,
apply = function(self, back)
G.E_MANAGER:add_event(Event({
func = function()
SMODS.change_play_limit(9)
return true
end
}))
local suits = {'S','C','D','H'}
local ranks = {'2','3','4','5','6','7','8','9','10','J','Q','K','A'}
for i=1,3 do
for _, suit in ipairs(suits) do
for _, rank in ipairs(ranks) do
G.E_MANAGER:add_event(Event({
trigger = 'after', delay = 0.05,
func = function()
local card = SMODS.add_card({set = 'Base', area = G.deck, suit = suit, rank = rank})
return true
end
}))
end
end
end
end
}```
whats the timers for anyway
Working with tags and I have a system in place for tags that have different kinds of effects (postive, negative, etc) and I'm trying to create a consumable that can remove a specific group of tags. In this case, negative (or bad). The removal works just fine, but I'm having trouble setting the can_use of the consumable to work when you have any negative tags. This is what I have currently.
can_use = function(self, card)
for i = 1, #G.GAME.tags do
if G.GAME.tags[i].config.tag.kind == 'negative' then
return true
end
end
end
anyone have a good example of a custom playing card implementation?
is it possible to add a gradient to a mod badge?
Few mods do this
you can change SMODS.current_mod.badge_colour to be a gradient in your code
iirc
i have this in main.lua but it's not replacing the placeholder color with a gradient
oof
whats up
don't do that in the update loop at all
i don't know if you need to wait for loading
but doing it in the update loop fucks internal state
SMODS.current_mod changes for each mod
ah
