#💻・modding-dev
1 messages · Page 634 of 1
SMODS.Joker {
key = "osotabawasoyuli",
blueprint_compat = true,
rarity = 3,
cost = 6,
pos = { x = 5, y = 3 },
atlas = "mmjokerz",
calculate = function(self, card, context)
if context.end_of_round and G.GAME.current_round.discards_used == 0 then
G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1
G.E_MANAGER:add_event(Event({
trigger = 'before',
delay = 0.0,
func = function()
SMODS.add_card({ key = 'c_death', edition = 'e_negative' })
G.GAME.consumeable_buffer = 0
return true
end
}))
end
end
}
if context.end_of_round and G.GAME.current_round.discards_used == 0 and context.main_eval
this will cause it to make 1 right
Yes.
ah noted
it works now thanks
--- Apply astral rules to Astral Planet cards
function apply_astral_rules()
for _, c in pairs(SMODS.Consumables) do
if c.giga_data and c.giga_data.astral_base then
local base_key = c.giga_data.astral_base
local flag = "giga_astral_" .. base_key
local base = SMODS.Consumables[base_key]
if base then
base.no_pool_flag = flag
end
local old_add = c.add_to_deck
c.add_to_deck = function(self, card, from_debuff)
G.GAME.pool_flags[flag] = true
if old_add then
return old_add(self, card, from_debuff)
end
end
end
end
end
I have this function I want to call it when every consumeable has been load so I can update them
but idk what function I should hook
question: how do i do an action to the last scored card in a hand
if context.individual and context.other_card == context.scoring_hand[#context.scoring_hand]
SMODS.injectItems
ok nice thx
thanks
so context.scoring_hand[#context.scoring_hand] is the last scored card in a hand
I got this crash
something[#something] is the last object in any table named something
because #something is the length of any table named something, and lua tables are 1-indexed
Code?
It should be G.P_CENTERS not SMODS.Consumeable
yeah but I just want to apply it to consumable
let's break it down
bad argument #1 to 'pairs': something about the function call to pairs is wrong, in particular the first argument
(table expected, got nil): SMODS.Consumeable is nil, not an actual table. because SMODS.Consumeable doesn't exist (and even if there was a table of all consumables that SMODS added, it'd be SMODS.Consumeables by convention)
are there any non-consumables that have giga_data.astral_base in them?
if not, then there's no problem with going through all the centers
it's not a big deal in the grand scheme of things, it'll be very fast because it doesn't do anything on the centers you don't care about
?
on smods 1016c
but yeah idk why my thing is so hard to do
eris shouldnt spawn if their is already an astral eris
nodes = {
create_option_cycle({
align = "tl",
ref_table = dandysworld.config_file,
ref_value = "epic",
current_option = dandysworld.config_file.epic,
w = 4,
label = localize('dw_options_epicjokersTitle'),
options = {
localize('dw_options_epicjokers0'),
localize('dw_options_epicjokers1'),
localize('dw_options_epicjokers2'),
},
opt_callback = 'epic_joker_config'
}),
simple_text_container('dw_options_seasonal', {
align = "tl",
}),
create_toggle({
align = "tl",
label = localize('dw_options_easter'),
ref_table = dandysworld.config_file,
ref_value = "easter",
callback = function(_set_toggle)
dandysworld.config_file.grasslanderJokers = _set_toggle
dandysworld.config.grasslanderJokers = _set_toggle
NFS.write(dandysworld.config_path, STR_PACK(dandysworld.config_file))
end
}),
}```
Anyone know why the simple label doesn't show up?
yeah but I dont find when in get_current_pool I need to patch
game crashes when i obtain my custom joker, why is this
elseif not (G.GAME.used_jokers[v.key] and not pool_opts.allow_duplicates and not SMODS.showman(v.key)) and
You need a context check.
ah thanks
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
position = "after"
pattern = '''
elseif not (G.GAME.used_jokers[v.key] and not pool_opts.allow_duplicates and not SMODS.showman(v.key)) and
'''
payload = '''
v.giga_data and v.giga_data.astral_variant == _type and
'''
match_indent = true
times = 1```
something like that
Anyone know how to modify the cost of a card? I'm trying to remake Cryptid's Epic Tag
No, it would be position = 'at' and elseif not ((G.GAME.used_jokers[v.key] or v.giga_data and v.giga_data.astral_variant and G.GAME.used_jokers[v.giga_data.astral_variant]) and not pool_opts.allow_duplicates and not SMODS.showman(v.key)) and
Anyone know how to make a card's cost half in shop?
Two astral planets is an insane pull lmao
Hook Card:set_cost
Really? it has to be a hook?
I mean, I'm willing to do it but it's just odd that there isn't an actual thing in SMODS to override it easier.
Ah well.
now the generation work but how do I fix that when I have telescope its always giving me the astral instead of the normal one
there's already a PR for that btw
Nice
Anyone know where the code is for the UI helper functions?
UIBox_button(args)
create_toggle(args)
create_slider(args)
create_text_input(args)
simple_text_container(_loc, args)
create_UIBox_generic_options(args)
create_option_cycle(args)```
functions/UI_definitions.lua
hey guys where would i find the list of every game color
In your IDE search for self.C = {
It applies the whole color table during some initial setup
Don't remember if it's in prep_stage or what
awesome
how do i randomize probabilities? (to a reasonable value)
staring at balatro code to figure out shop ui wasnt such a good idea after all
-# ive learnt nothing
how do you change a card's properties after scoring
-# context.scoring_hand doesn't seem to work
What is the goal?
change a card to a random suit and rank (currently, for temporary testing, changes the card's rank to an ace) after scoring
oh wait i might be stupid hold on
okay it does work now
you can put the delay() in the event manager to delay the reshuffle animation right
it delays everything in the event
yeah since it changes to an ace i can just put the delay(x) at the end and it will show the card for x seconds right
to aces is insane if you know the context of this 😭
how do i randomize probabilities?
(if cryptlib is required i do have it)
i can't juice up the card in the event...
i want the juicing event after the card transforms but this doesn't seem to work hold on
calculate = function(self, card, context)
if context.after and context.cardarea == G.play and SMODS.pseudorandom_probability(card, 'ijsj_hazy_r', G.GAME.probabilities.normal, card.ability.extra.odds) then
G.E_MANAGER:add_event(Event({
func = function()
assert(SMODS.change_base(card, nil, 'Ace'))
card:juice_up(0.3, 0.5)
return true
end
}))
end
end,
You mean you want to randomize all probabilities once, or randomize them every time they are called?
using a consumable
all yea
Yes, do you want to set all probabilities to the same random number or set all probabilities to different random numbers, also you mean you want to do it once when the consumable is used?
when the consumable is used, all probabilities are immediately changed, different numbers
use = function(self, card, area, copier)
G.GAME.modprefix_randomized_probabilities = G.GAME.modprefix_randomized_probabilities or {}
for k, v in pairs(G.I.CARD) do
if v.sort_id then
G.GAME.modprefix_randomized_probabilities[v.sort_id] = {numerator = pseudorandom('seed', number, number), denominator = pseudorandom('seed', number, number)}
end
end
end
SMODS.current_mod.calculate = function(self, context)
if G.GAME.modprefix_randomized_probabilities and next(G.GAME.modprefix_randomized_probabilities) and context.mod_probability and Card.is(context.trigger_obj, Card) and context.trigger_obj.sort_id and G.GAME.modprefix_randomized_probabilities[context.trigger_obj.sort_id] then
return G.GAME.modprefix_randomized_probabilities[context.trigger_obj.sort_id]
end
end
am i doing something wrong?```lua
SMODS.Consumable {
key = 'virtuality',
set = 'Infinity',
atlas = "atlas_Virtual",
pos = { x = 0, y = 0 },
loc_txt = {
name = "Virtuality",
text = {"Randomizes {C:green}all probabilities{}"}
},
config = {
min = 0.5,
max = 5
},
loc_vars = function(self, info_queue, card)
return { vars = { number_format(self.config.min), number_format(self.config.max) } }
end,
can_use = function(self, card)
return true
end,
use = function(self, card, area, copier)
G.GAME.busterb_randomized_probabilities = G.GAME.busterb_randomized_probabilities or {}
for k, v in pairs(G.I.CARD) do
if v.sort_id then
G.GAME.busterb_randomized_probabilities[v.sort_id] = {numerator = pseudorandom('busterb_virtualrnd', self.config.min, self.config.max), denominator = pseudorandom('busterb_virtualrnd', self.config.min, self.config.max)}
end
end
end,
draw = function(self, card, layer)
if (layer == 'card' or layer == 'both') and card.sprite_facing == 'front' then
card.children.center:draw_shader('booster', nil, card.ARGS.send_to_shader)
end
end
}
SMODS.current_mod.calculate = function(self, context)
if G.GAME.busterb_randomized_probabilities and next(G.GAME.busterb_randomized_probabilities) and context.mod_probability and Card.is(context.trigger_obj, Card) and context.trigger_obj.sort_id and G.GAME.busterb_randomized_probabilities[context.trigger_obj.sort_id] then
return G.GAME.busterb_randomized_probabilities[context.trigger_obj.sort_id]
end
end
bump
eris you know anything about chance manipulation?
Hook or patch SMODS.is_eternal
What happens if you print G.GAME.busterb_randomized_probabilities?
print(G.GAME.busterb_randomized_probabilities)?
chance is still locked at 1 in 2 (using bloodstone here)
returning to this as i had to go to eep, does it have to be a Card:update hook or can i use the joker's update function
nvmd i just saw what msg it was replying to

what part of the function should i be looking at? it doesnt seem to be checking a set or cardarea at all, but it still returns false on consumables
The line before return ret
What happens if you print in the if in SMODS.current_mod.calculate?
if you're just changing what it returns, then you may as well just use a hook
like here's my eternal hook for this joker
local eternal_hook = SMODS.is_eternal
function SMODS.is_eternal(card, ...)
local eh = eternal_hook(card, ...)
if (card.config.center_key == "j_elle_cassie2") then return true end
return eh
end```
wha
ok wait
No, they're trying to make it work on consumables.
ah
the if not card.config.center.eternal_compat and not ovr_compat then ret = false end
It doesn’t return “if!”
how do i get when the score's on fire?
uhh you could just check for if your blind chips are greater than the blind requirement
please help how do i ui i wanna make a menu like grim's skill tree
💔
what letter do quips use
oh theres just a check for that??
awesome
i think its just modprefix_key
-# i do this in my mod and it works fine
hm
idk
SMODS.Consumable {
key = 'virtuality',
set = 'Infinity',
atlas = "atlas_Virtual",
pos = { x = 0, y = 0 },
loc_txt = {
name = "Virtuality",
text = {"Randomizes {C:green}all probabilities{}"}
},
config = {
min = 0.5,
max = 5
},
loc_vars = function(self, info_queue, card)
return { vars = { number_format(self.config.min), number_format(self.config.max) } }
end,
can_use = function(self, card)
return true
end,
use = function(self, card, area, copier)
for k, v in pairs(G.I.CARD) do
if v.ability then
v.ability.busterb_numerator_mod = (v.ability.busterb_numerator_mod or 1) * pseudorandom('busterb_virtualnum', self.config.min, self.config.max); v.ability.busterb_denominator_mod = (v.ability.busterb_denominator_mod or 1) * pseudorandom('busterb_virtualden', self.config.min, self.config.max)
print("yea!")
end
end
end,
draw = function(self, card, layer)
if (layer == 'card' or layer == 'both') and card.sprite_facing == 'front' then
card.children.center:draw_shader('booster', nil, card.ARGS.send_to_shader)
end
end
}
SMODS.current_mod.calculate = function(self, context)
if v.ability.busterb_numerator_mod and v.ability.busterb_denominator_mod and
Card.is(context.trigger_obj, Card) and
context.mod_probability and context.trigger_obj.ability then
print("if!")
return { numerator = context.numerator * (context.trigger_obj.ability.busterb_numerator_mod or 1), denominator = context.denominator * (context.trigger_obj.ability.busterb_denominator_mod) }
end
end
This still doesn’t work
virtual insanity
could someone tell me please how i can do the separation between two texts ? i want to give a space between "Gain an [...] the round" and "Boss Blinds give no reward"
```lua
loc_txt= {
name = 'Jam Sybil',
text = { "Gain an extra {C:money}$#1#{}",
"by remaning {C:red}discard{}",
"At the end of the round",
"{C:attention}Boss Blinds{} gives no reward",
},},
You mean a multi-box?
probably that i think
The description staying within the joker 'box' but separated (but not outside like the enhancements descriptions for exemple
loc_txt = {
name = 'Jam Sybil',
text = {
{
'Gain an extra {C:money}$#1#{}',
'by remaning {C:red}discard{}',
'At the end of the round',
},
{
'{C:attention}Boss Blinds{} gives no reward',
}
},
},
Oh i see, thanks a lot
Do the sticker weight variables in G.GAME (e.g. G.GAME.rental_rate) get auto-generated for modded stickers, or do they only exist for vanilla stickers
No, G.GAME.rental_rate is how much money you lose from rental.
how do you change an atlas's texture path in runtime?
how would one change how much interest you get
I've checked balatro's code and it seems hardcoded as far as I see
or well I got a weird idea
nah
what is it you're trying to do with the interest
also is that the vanilla code or the lovely dump
How would I check when a card with a certain sticker is added to the deck within that stickers code.
Hook Card:add_to_deck
How would I get whether or not a card has the sticker when added to deck?
if card.ability.modprefix_key
real quick but how do I check what the current deck being used is, for an if statement?
for me works if G.GAME.selected_back.effect.center.key == "b_modID_deck" then
Is there a way to get the rank of a stone card? get_id() does not return an actual rank off a stone card.
how about card.base.id
I've always wondered what the specific use of stone cards returning a random number is
Does anyone have the slightest idea why one works and the other doesn't? (it should technically turn every joker square if it is already not square)
if not G.jokers.cards[i].ability.name == 'Square Joker' then
-- so
-- G.jokers.cards[i].ability.name ~= 'Square Joker'
-- works, but
-- not G.jokers.cards[i].ability.name == 'Square Joker'
-- doesn't
play_sound('whoosh1', 0.55, 0.62)
G.jokers.cards[i]:set_ability("j_square")
end
end```
$1 per $3 instead of $1 per $5, and from vanilla code
i do
it has something to do with not operator takin priority
so your not G.jokers.cards[i].ability.name == 'Square Joker' lua interprets as (not G.jokers.cards[i].ability.name) == 'Square Joker'
which should always be false
also i advise for you to check for joker's key instead
God I hate this little thing. I don't know how many times I've been caught out by this
But yeah in cases like this it's correct to use ~= operator
I actually have implemented a patch for that, my mod is CTEH_mod on github and the file about interest rate is lovely/interest_rate.toml, I've also changed in the localization the To the Moon description to include the new parameter
coolio
probably so they don't accidentally form straights or oaks
i have no idea if that actually holds in the game as released but there's all sorts of artifacts in the code that make it clear changes were made
Does the vanilla random function ensure that successive random calls are never identical?
Because funnily if it didn't, I wonder if you could get ultra Uber lucky and accidentally score an oak because all the stone cards returned the same id at the time of calc
how on earth do i make SMODS.calculate_individual_effect return MULTIPLE effects
Use SMODS.trigger_effects() instead
????
No I mean, if you need multiple effects calculated, you use trigger_effects, which itself calls calculate_individual_effect for each key in the return tables
Trigger effects takes a list of return tables
Actually I might be wrong, it might just be SMODS.calculate_effects
what i'm trying to do here is have a "dual" effect where mult also gives chips
i already have a table that swaps around keys
how the hell do i modify evaluations
Hmmm so like universally?
i also need some way to see if the given mult/chips was from the swapping
so no stack overflow, duh
Mmmmm yeah might be a little harder. I do think the best idea is to hook SMODS.calculate_effect() and check the effect table passed into it. That should be equivalent to what you'd expect a calculate return table to be. So if you do your thing to swap to the other key if it's not present (chips vs mult), you can then return something as a flag in the function's ret table to indicate that the swap has occurred?
Dunno how effective an explanation this is, but that sounds like what I'd do
how do i modify a joker's calc ulations before it is added to total score
Bump
is there any way to set a card's extra table during creation?
is the card doing that itself or to other cards?
im trying to modify the extra table with smods.create_card
SMODS.create_card returns the created card
so you can store it in a local variable and then add onto the extra table after
this is just how i did it
if theres_a_mindware and not effect.from_mindware then
local new_effect = Copy3(effect)
new_effect[key] = nil
new_effect.from_mindware = true
local is_chips = MyDreamJournal.chipmodkeys[key]
local is_mult = MyDreamJournal.multmodkeys[key]
local is_additive = ((is_chips == "add") and true) or ((is_mult == "add") and true)
local new_amount = amount
if is_additive and is_chips then
new_amount = new_amount/7.5
elseif is_additive and is_mult then
new_amount = new_amount*7.5
end
new_effect[MyDreamJournal.chipmultopswap[key]] = new_amount
SMODS.calculate_effect(new_effect, scored_card, from_edition)
end
this is inside calculate_individual_effect btw
Hm! I guess that does also work
copy3 is just a table copying function since idk how much detail i can lose 💔
the only issue is
that the converted value shows up BEFORE the actual one
does SMODS also support negative values for G.GAME.modifiers.scaling?
but that just seems unfixable 💔
Yeah cause unfortunately you're inserting something before the previous calc has finished
how do i add in a info_queue for a modded edition
oh my line breaks
why do you say X(2/15) instead of just /7.5
HE RUINED MY DREAM JOURNAL
ok fine
blame @umbral zodiac
no im blaming you
why are you still blaming me for this
why wouldn't i
i didnt even tell you to do that i just said bsaically sure whatever when you chose to do it because i said 1/7.5 looked strange
jalatro how do i modify jokers' scoring
as in how do i modify the values they returne
d
i cant find anything in documentation about
it
...context.post_trigger, checking context.other_card and modifying resulting context.other_ret? 🤔
-# iirc that way-
-# Need to enable post_trigger optional feature tho.
what do you mean other ret is stored in t he card
if not context.post_trigger and not context.retrigger_joker_check and SMODS.optional_features.post_trigger then
SMODS.calculate_context({blueprint_card = context.blueprint_card, post_trigger = true, other_card = card, other_context = context, other_ret = ret}, post_trig)
end
modifying context.other_ret.jokers does work, though i recommend hooking SMODS.calculate_individual_effect where possible
https://github.com/TheOneGoofAli/TOGAPackBalatro/blob/06881c98299e0f527cde0dfa38666faa3b4c3e0b/items/hooks.lua#L478-L523
-# Just keep in mind some vanilla Jokers may display their intended values and not the changes-
this is making me feel like a skid for not understanding at all
???????
oh it got removed now
huh
Triggered a false positive from Discord earlier. 😅
If you're working with a localization file and want to see the changes w/o restarting game with DebugPlus present,
eval G:set_language(); G:init_item_prototypes()
hold M
when using smods
o damn fr
didn't know that one
alt-f5 is faster
only downside is how easy it is to fatfinger alt-f4 instead
context is annoying
new to texture modding - are cards displayed on a white background? and then other effects (gold, steel) just replacing the white background? So transparency is needed on assets to see underneath?
how would i make a hook to call a function so that it plays a custom sound whenever the score catches on fire
Yes.
is it possible?
I don't know if this is the best way but you could maybe use SMODS.current_mod.calculate like this:
SMODS.current_mod.calculate = function(self,context)
if context.after and SMODS.last_hand_oneshot then
print("[play sound]")
end
end
Definitely
let me try
so like this works but
the sound overlaps 😭
i only want them to play once
and it doesnt stop when the scoring ends too
SMODS.current_mod.calculate = function(self, context)
if SMODS.calculate_round_score() > G.GAME.blind.chips then
play_sound("hs_highscoring", 1, 1)
G.GAME.highscore_hit = true
end
if context.after then
G.GAME.highscore_hit = nil
end
end
this is what it looks like
maybe
hmmmmmmm
oh wait im trying that and it seems like it doesnt work
you could have a flag for when its playing or not
oh thats good
but of course it doesnt stop after scoring
oh i realised you could do
if SMODS.calculate_round_score() > G.GAME.blind.chips and not G.GAME.highscore_hit then
now just need a way to stop music
mhm
you could try use this SMODS.Sound:create_stop_sound(key, times) in context.after
yeah sure ill try that
does anyone have any idea how to mess with the fire color?
is it possible to make consumables do things if still in hand? still WIP for now but I want to make it increase blind size slightly as theres no way to sell this specific card until the money amount has been paid off
Use the calculate function.
We are getting gay in here
Mod?
This is an in progress feature that's not in the latest release from last month
how can i check if a joker is part of a certain pool
how can i track how much money is spent? what i mean is I want something to trigger after say $10 was spent for a joker function
if card.config.center.pools and card.config.center.pools.key
thanks
I have tried changing some settings in VSCode that has allowed the hover to appear (specifically the hover delay), but on hover the only thing that appears is a popup on hover that says "Loading..." before disappearing incredibly quickly. Has anyone else encountered this issue? I can share the test function if it would be helpful for diagnosing this situation
how do i make a consumable select jokers
bump
Sooo hands now show up in the collection
Say I take ownership, non-silently, of 5oak so that if i play a 6oak it displays "Six of a Kind", is there a way to display 6oak in the collection instead of 5oak? And subsequent question, if I also make it display 7oak, is there a way to add both 6oak and 7oak in the collection even if they're technically just renamed 5oaks?
G.jokers:add_to_highlighted(card)
i meant allow the consumable to be used on jokers
You mean you want to get the highlighted joker?
i want to check if a joker's highlighted
local original_flame_handler = G.FUNCS.flame_handler
G.FUNCS.flame_handler = function(e)
original_flame_handler(e)
for k, v in pairs(G.ARGS.flame_handler) do -- Run it back
local _F = G.ARGS[v.arg_tab]
if _F then
if not _F.sound then --init
_F.sound = play_sound('hs_highscoring', 1, 0) -- pitch = 1, volume = 0 initially
end
local vol = math.min(1, _F.real_intensity / 5)
_F.sound:set_volume(vol)
end
end
end
am i doing this right
something must be wrong here```lua
SMODS.Consumable {
key = 'virtuality',
set = 'Infinity',
atlas = "atlas_Virtual",
pos = { x = 0, y = 0 },
loc_txt = {
name = "Virtuality",
text = {"Resets the shop."}
},
config = {
},
can_use = function(self, card)
return G.STATE == G.STATES.SHOP
end,
use = function(self, card, area, copier)
G.shop:remove()
G.shop = nil
G.SHOP_SIGN:remove()
G.SHOP_SIGN = nil
G.GAME.current_round.used_packs = nil
G.STATE_COMPLETE = false
G:update_shop()
end,
draw = function(self, card, layer)
if (layer == 'card' or layer == 'both') and card.sprite_facing == 'front' then
card.children.center:draw_shader('booster', nil, card.ARGS.send_to_shader)
end
end
}```
istj if i have to use cryptidlib to make a joker consumable i'll
it looks like this for some reason
how do i add lines to localization that only appear when certain mods are installed
just set a global variable for it smh my head
nvm you actually did use it but you didnt check for it for some reason
you can put a not G.GAME.highscore_hit check in the caught on fire check so that it only runs once when its on fire
hot potato has it
in which joker?
self insert jokers like we are jtem, oops a programmer and horsechicot one
which lua is responsible for the sound of the flame
tfym
like the organ sound whenever the flame appears
the sound
in G.ARGS.ambient_sounds i think
thanks
its actually played in the function AMBIENT in engine/sound.lua and its handled in G.ARGS.ambient_control though
its weird
weird
variables for suit names is kind of crazy
why did you define everything you know is wrong and just not using it
those who know
is it supposed to be at the check
SMODS.find_card("j_MDJ_etykiw") and suitless(self)
because the first part is always truthy
SMODS.find_card always return a table which is truthy
also what the fuck is
local clubs = "Clubs"
local spades = "Spades"
local hearts = "Hearts"
local diamonds = "Diamonds"
if self.base.suit == clubs then return diamonds == suit end
if self.base.suit == diamonds then return clubs == suit end
if self.base.suit == hearts then return spades == suit end
if self.base.suit == spades then return hearts == suit end
i'll never tell you
youre not changing the variables in any ways
you will never know
and its locally used in 1 place
i used to do that but with get_id
WHAT DO YOU MEAN
every single one
calculate = function(self, card, context)
if context.using_consumeable and context.consumeable.ability.set == 'Planet' and G.hand.cards[1] and SMODS.pseudorandom_probability(card, 'cymbal_aquatic_book', card.ability.extra.numerator, card.ability.extra.odds, 'aquaplanet') then
local no_seal = {}
for _, playing_card in ipairs(G.hand.cards) do
local has_seal = false
for i = 1, #G.hand.cards do
local c = G.hand.cards[i]
if c.seal == nil
then has_seal = true
end
end
if not has_seal then
no_seal[#no_seal + 1] = playing_card
end
end
local sealed_card = pseudorandom_element(no_seal, pseudoseed('cymbal_aquatic_book'))
G.E_MANAGER:add_event(Event({
func = function()
play_sound('tarot1')
sealed_card:juice_up(0.3, 0.5)
return true
end
}))
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.1,
func = function()
sealed_card:set_seal(card.ability.extra.seal, nil, true)
return true
end
}))
end
end
Hello ! Got an issue with my joker, it's meant to give a blue seal on a random card in hand after using a planet card, it did worked but would happen that it can do on a card with a seal on it already (and even if it is a blue seal), tried to fix that but got this crash error now so if someone could help that would be appreciated ^^
If c.seal == nil that means the card doesn't have a seal.
oh wait, yeah i've done it wrong ops
though i don't think it should crash since it's appanrelty sealed_card that got the nil value
Yes, because no_seal would be empty if none of the cards had seals.
local no_seal = {}
for _, playing_card in ipairs(G.hand.cards) do
local has_seal = false
for i = 1, #G.hand.cards do
local c = G.hand.cards[i]
if c.seal ~= nil
then has_seal = true
end
end
if not has_seal then
no_seal[#no_seal + 1] = playing_card
end
end
i made the fix and now any card that have a seal count as havign a seal, normally now in that case even if all cards in hand had a seal, it wouldn't crash right ?
No, it would crash, because no_seal would be empty if every card had a seal.
Ah i see, guess i'll need a nul check on this
Well i just noticed my game woudl crash the moment one of my cards had a seal, i think i messed up somewhere
calculate = function(self, card, context)
if context.using_consumeable and context.consumeable.ability.set == 'Planet' and G.hand.cards and SMODS.pseudorandom_probability(card, 'cymbal_aquatic_book', card.ability.extra.numerator, card.ability.extra.odds, 'aquaplanet') then
local no_seal = {}
for _, playing_card in ipairs(G.hand.cards) do
local sealent = false
for i = 1, #G.hand.cards do
local c = G.hand.cards[i]
if c.seal == nil
then sealent = true
end
end
if sealent then
no_seal[#no_seal + 1] = playing_card
end
end
if #no_seal > 0 then
local sealed_card = pseudorandom_element(no_seal, pseudoseed('cymbal_aquatic_book'))
G.E_MANAGER:add_event(Event({
func = function()
play_sound('tarot1')
sealed_card:juice_up(0.3, 0.5)
return true
end
}))
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.1,
func = function()
sealed_card:set_seal(card.ability.extra.seal, nil, true)
return true
end
}))
end
end
end
Well i'll admit i don't get what i did, now it'll seal the same card with a seal and will crash if all cards got a seal, i suppose for the sealing the same card with a seal is about the for _, playing_card in ipairs(G.hand.cards) do part but for the nil check i tried to do something but ended up wrong somehow ?
well the nil check has been fixed so that's that
in the end i managed to fix it and the fix was easier than i did think it'll be
local function unlockJoker(key)
local joker = G.P_CENTERS[key]
if joker and not joker.unlocked then
joker.unlocked = true
G:save_progress()
return true
end
return false
end
local function lockJoker(key)
local joker = G.P_CENTERS[key]
if joker and joker.unlocked then
joker.unlocked = false
G:save_progress()
return true
end
return false
end
hi, does anyone know how I can save the unlocked state across sessions?
Is there really no G.GAME variables for rerolls done in a run?
I ask cause the game does keep track somehwere, just where, I dunno
G.GAME.round_scores.times_rerolled.amt?
ok how did yall get quip loc to work
Doing this works for me
return {
misc = {
quips = {
modprefix_key = {
"text"
},
},
},
}```
hmmm
ill probably dump the loc after i do all the loc_txt for 0.0.2a
i have it ready
That seemed to do it, thank you!
i will do extra things just to be sure
hiiii @grand violet
why doesn't
SMODS.add_card { key = "j_joker", stickers = { "eternal" } }work
for reference
SMODS.add_card { key = "j_joker", edition = "e_negative" }does
stickers = { eternal = true, rental = true }
oh ty
:/
that didn't work
but anyways SMODS.add_card { key = "j_joker", stickers = { "eternal" }, force_stickers = true } does
how do u make an enhancement act like another one
search "quantum enhancements"
check on wiki
ok but what do you return
You need to return table like ```lua
{
m_lucky = true,
m_steel = true
}
ok thx
m not e
yeah, m_prefix_key
e for editions, you're right
how do you make a sub-set of a pair? like double 4: two 4s.
is there a way to initially set badges on a joker? like I want to have the badge "Art: Person A", & "Code: Person B", etc.
Trying to make a joker that gives cards chips when they are given a different enhancement than they had before. I have no issues with that.
However, I don't want the effect to go off when a card is copied (like by Death or DNA). That is my current problem. I added a patch to make context for when a card is copied, and it works just fine.
[manifest]
version = "1.0.0"
priority = 0
# Calcute copy_card
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''new_card:set_base(other.config.card)m'''
position = "after"
match_indent = true
payload = '''SMODS.calculate_context({copying_card = true})'''
But it doesn't work with the joker itself and I'm not sure why
calculate = function(self, card, context)
if context.setting_ability and not context.unchanged and not context.copying_card then
context.other_card.ability.perma_bonus = (context.other_card.ability.perma_bonus or 0) +
card.ability.extra.chips
return {
message = localize('k_upgrade_ex'),
colour = G.C.CHIPS
}
end
end
I want to make a mod with a joker that will swap the chips for the mult (the values that is)
How would I do that?
I am working on it atm, actually
I just gotta get lua setup in VSCODE for syntax highlighting
neither of these prints are being printed (the rest of the code isn't running either) what's wrong with this code
I actually, have never done a mod before (I do know lua pretty well) -
someone did this already
umm okay?
i dont remember what mod it was either morefluff or sdm0's stuff it's the blahaj you can go reference it
I'm okay, I'm looking at the docs rn
fr?
swap = true
wow
mightve been plasma related at some point
bump help
Where do I put this? I'm looking in the docs rn, but I'll double check
Okay, I'll have to look into that - I'm new to modding
hey y'all, i updated steamodded to the new release, and there's now a warning in my code that the second return of the pseudorandom_element function cannot be assigned to a variable. how would i fix this?
the joker this is from actually seems to still work fine, but like, what's up
Is it just a syntax error?
there are a lot of mods that do this
because you can just return swap = true
yeah i didnt know that it was that common
i don't really know what to make of it lol
or like what even changed
this is just vscode warning you that _index can be nil, and table.remove must have the second argument be a number
Does the mod work at least?
i just did tonumber(_index) and the warning is gone
so i guess that's fine?
but i dunno why it wants me to do this now since it was fine before the update
yeah!
i dont think thatll fix it if _index is nil
but yellow warnings can usually just be ignored
i guess it's fine... lol
I can't get my first mod detected by Balatro
I'm having some issues, can someone help me out? I think it might be my metadata
oh wait
{
"id": "jokersToTheMoon",
"name": "Jokers to the Moon",
"display_name": "",
"author": [
"connorwillchris"
],
"description": "",
"prefix": "",
"main_file": "main.lua",
"priority": 0,
"badge_colour": "",
"badge_text_colour": "",
"version": "",
"dependencies": []
}```
I'm dumb, I have no dependancies haha
but wow, it still doesn't load
SMODS.Atlas {
key = "atlas_jokersToTheMoon",
path = "jokersToTheMoon.png",
px = 71,
py = 95,
}
SMODS.Joker {
key = "j_joker2",
loc_txt = {
name = "Joker2",
text = {
"Fucks your mom!"
}
},
rarity = 1,
atlas = "atlas_jokersToTheMoon",
pos = { x = 0, y = 0 },
cost = 3,
config = {
extra = { mult = 4}
},
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.mult } }
end,
calculate = function(self, card, context)
if context.joker_main then
return {
mult_mod = card.ability.config.extra.mult,
message = localize {
type = "variable",
key = "a_mult",
vars = {
card.ability.extra.mult
}
}
}
end
end
}
This is the lua file, mostly for shits and giggles and taken mostly from the docs
try looking in the logs to see where your mod is being loaded
usually itll give the reason for skipping a mod
might be my dependancies I changed
(also kinda unrelated but if youre going to do more modding i HIGHLY recommend using vanillaremade as a reference for most things https://github.com/nh6574/VanillaRemade)
I;ll take a look
does the mod show up in the mods menu at least?
nope
prefix might need to be a non-empty string
same with the badge and badge text colours
I think it's the prefix
I put a basic prefix
j2tm
okay weird
it's using my .vscode/settings.json file
okay now it works
...wweird
I have an weird question. I was looking through the smods GitHub wiki, specifically this: https://github.com/Steamodded/smods/wiki/SMODS.Atlas -- would this be able to overwrite the sprites the game uses for the default cards? Specifically the blank white card that gets used for the cards in hand. Deck skins don't feature the white card back and instead are just the overlay part of the card, I want to completely overwrite the white part of the card with a new sprite. Any ideas? I can explain further if needed.
youre probably best off making a #1300851004186820690 texture pack
I already use Malverk for the jokers, can Malverk accomplish this too or is that not part of Malverk?
I tried overwriting the blank card on the "enhancements.png" or whatever it is called and it didn't work. Is there another approach to overwrite it? I'm still new to the modding scene.
just make an AltTexture with malverk that only changes c_base
I never tried that. Is there an example that I could refer to? Like another pack that does that exact thing? If you can point me in the right direction that would be great.
I have a pack that skins the jokers with my own textures already
One that I am making I mean
you can just do ```lua
AltTexture {
key = 'whatever',
set = 'Default',
path = 'spritesheet.png',
keys = {
'c_base' = true
},
}
and then just have the spritesheet be a single card sprite being the retextured base card
So that would overwrite the blank white part? I'll try that in a little bit and if it works, you're a life saver. My texture pack will be very neat. My main issue is that I could never get rid of the white part with my own texture. I think I could figure it out with this to help, thanks
Another small question. Could this also be expanded to all the card enhancements too? I've only used Malverk for Jokers so far so I don't know the full capabilities of it yet.
you can use malverk for any sprites
Ok, that helps. Thank you
Oh yeah @gaunt thistle question, can you default the lovely console to appear on another monitor than the main Balatro window?
... hmm
It's a native console so.. probably?
I would need to spawn the console, somehow get the console's window handle, and then translate it to the second screen
it would be complicated 😭
That's alright, mostly wanted to know if that was already supported
yeah, not currently. if we ever do a console UI (instead of the windows one) then itll be a lot easier
SMODS.Joker{ --Mr. Beast
key = "mrbeast",
config = {
extra = {
repetitions0 = 2,
repetitions = 2
}
},
loc_txt = {
['name'] = 'Mr. Beast',
['text'] = {
[1] = 'If first hand of round',
[2] = 'has only 1 card, {C:enhanced}Enhance{}',
[3] = 'it with {C:money}Gold{} and give it',
[4] = 'a {C:money}Gold{} seal{}. Cards with',
[5] = '{C:money}Gold{} and {C:money}Gold{} seal trigger',
[6] = '2 more times when played',
[7] = 'or held in hand'
},
['unlock'] = {
[1] = 'Unlocked by default.'
}
},
pos = {
x = 0,
y = 0
},
display_size = {
w = 71 * 1,
h = 95 * 1
},
cost = 6,
rarity = 3,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = true,
atlas = 'CustomJokers',
pools = { ["randomst_randomst_jokers"] = true },
calculate = function(self, card, context)
if context.repetition and context.cardarea == G.play then
if (to_big(#context.scoring_hand) == to_big(1) and G.GAME.current_round.hands_played == 0) then
local scored_card = context.other_card
G.E_MANAGER:add_event(Event({
func = function()
scored_card:set_ability(G.P_CENTERS.m_gold)
scored_card:set_seal("Gold", true)
card_eval_status_text(scored_card, 'extra', nil, nil, nil, {message = "Card Modified!", colour = G.C.ORANGE})
return true
end
}))
elseif (SMODS.get_enhancements(context.other_card)["m_gold"] == true and context.other_card.seal == "Gold") then
return {
repetitions = 2,
message = localize('k_again_ex')
}
end
end
if context.repetition and context.cardarea == G.hand and context.end_of_round and (next(context.card_effects[1]) or #context.card_effects > 1) then
if (SMODS.get_enhancements(context.other_card)["m_gold"] == true and context.other_card.seal == "Gold") then
return {
repetitions = 2,
message = localize('k_again_ex')
}
end
end
end
}
@gaunt thistle
if context.repetition and (context.cardarea == G.hand or context.cardarea == G.play) and context.end_of_round and (next(context.card_effects[1]) or #context.card_effects > 1) then
if (SMODS.has_enhancement(context.other_card, 'm_gold') and context.other_card:get_seal() == 'Gold') then
return {
repetitions = 2,
message = localize('k_again_ex')
}
end
end
thanks for the reply!!!
uhh im not too good with coding idk what this means
It's your code for the retriggers, but I fixed it.
uhh im rlly sorry im dumb and dont really know where that goes lol, i use jokerforge
@daring fern
💀
someone pls help
game crashes when i play a card now SMODS.Joker{ -- Mr. Beast
key = "mrbeast",
config = {
extra = {
repetitions0 = 2,
repetitions = 2
}
},
loc_txt = {
['name'] = 'Mr. Beast',
['text'] = {
[1] = 'If first hand of round',
[2] = 'has only 1 card, {C:enhanced}Enhance{}',
[3] = 'it with {C:money}Gold{} and give it',
[4] = 'a {C:money}Gold{} seal{}. Cards with',
[5] = '{C:money}Gold{} and {C:money}Gold{} seal trigger',
[6] = '2 more times when played',
[7] = 'or held in hand'
},
['unlock'] = {
[1] = 'Unlocked by default.'
}
},
pos = {
x = 0,
y = 0
},
display_size = {
w = 71,
h = 95
},
cost = 6,
rarity = 3,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = true,
atlas = 'CustomJokers',
pools = { ["randomst_randomst_jokers"] = true },
calculate = function(self, card, context)
----------------------------------------------------------------
-- FIRST HAND OF ROUND: APPLY GOLD + GOLD SEAL
----------------------------------------------------------------
if context.cardarea == G.play and G.GAME.current_round.hands_played == 0 then
local hand = G.PLAY.current_hand
if #hand == 1 then
local c = context.card or hand[1]
if c then
if not SMODS.has_enhancement(c, 'm_gold') then
c:set_ability(G.P_CENTERS.m_gold)
end
if c:get_seal() ~= 'Gold' then
c:set_seal('Gold', true)
end
card_eval_status_text(
c,
'extra',
nil,
nil,
nil,
{ message = "Card Modified!", colour = G.C.ORANGE }
)
end
end
end
----------------------------------------------------------------
-- RETRIGGER GOLD & GOLD SEAL
----------------------------------------------------------------
if context.repetition and (context.cardarea == G.hand or context.cardarea == G.play)
and context.end_of_round and (next(context.card_effects[1]) or #context.card_effects > 1) then
if SMODS.has_enhancement(context.other_card, 'm_gold') and context.other_card:get_seal() == 'Gold' then
return {
repetitions = 2,
message = localize('k_again_ex')
}
end
end
end
}
What the
someone gave me a fix but im not good at coding so idk what to do with the fix he gave me
first off
based
also what is the issue that you're dealing with
dude if your jokerforge joker doesnt work and you cant use the help that was given to you i think you should try learning how to make mods with lua
i should
especially considering jokerforge can only do so much
jf is only good for starting at the VERY BASICS of balatro modding
-# and even then it's still ass
bascially when i play a card with gold and a gold seal i want it to retrigger 2 times, and the same when held in hand at end of round, and when first hand of round contains 1 card (dna) i want it to give it gold and a gold seal, the problem was that the retrigger when played didnt work, the held in hand one did tho
ok im most likely just gonna recode half of this because jf code is dogshit
thanks
that is if i don't fall asleep midway through
i'm trying to make a joker that has an effect whenever a spectral pack is skipped, but i can't figure out how to tell if the pack being skipped is a spectral pack specifically
tried using if G.STATE == G.STATES.SPECTRAL_PACK but that didn't work
does anyone know a solution?
if context.booster.kind == 'Spectral'
thank you
nvm
ur not recoding it?
also can someone pls teach me lua, ive looked at vids b4 and just straight up didnt understand
I'm trying to make animated standard deck. I can animate single cards for each suit, but I can't figure out how to animate multiple cards per suit. Does anyone know how to do it?
In my experience, and this may not work for you, but for me it helped to look through a working mods jokers and look at how they are done and use that to understand how different effects are done, but idk may not help you
Could use some help here if anyone's up, I'm making a ridiculously dumb mod where the assets are all screenshots, I would love to make a border effect on all the photos to make them look like legit jokers but I don't want to individually do all 50 of them, anyone got a suggestion and maybe a frame I could use for reference?
ill try that thanks
Might be a bit boring ngl but it worked for me lol
any mods reccommended that have simple jokers?
Hmm ill lyk which one I did when im off work lol
I feel like it was cryptid but I could be wrong idr
When using quantum enhancements, how do I make a card also show the description and label of the enhancement its copying?
Patch generate_card_ui
🫡
how can I track how much money is spent so far? The plan is for this to increase blind size until the $60 has been repaid
oh yea how does the AUT table in generate card ui work
you could use context.buying_card i think that gets passed how much money you spent
I need the amount of money spent
context.money_altered
oh
so like if a $5 item is bought the amount needed to pay off goes down by 5
if i were to overwrite gnerate_card_ui how would i call the original version of it
and WHAT DOES AUT DO
I want the owed amount at the bottom to go down by 1 per dollar spent, such as a 5 dollar item reducing owed amt by 5, how can I do that?
You would save the old function in a variable then call that.
if context.money_altered and context.amount < 0 then
card.ability.extra.variable = math.max(card.ability.extra.variable-context.amount, 0)
end
thanmk
ok it reduces if cashing out, how can i circumvent this
eh know what it works
How can I automatically give me the joker in my run for testing purposes?
debugplus
send a link if you can
hover over the joker in the collection and press 3
a bit of math later and now it does what i wanted
if you cash out it doesnt add to the loan but if you buy it subtracts
3 as in the keypad 3, or does it not matter?
it doesnt matter i think
Okay, it's not discovered, but is this an issue?
oh uh press 2 to discover it
it added money when cashing out, i just tweaked it to work with my vision i was intending
How do I enable debugplus or is this a mod?
Yes, and I fixed it.
eh fair enough
its a mod
dp is a mod
thanks
Also, I use Aseprite for pixel art. How can I export a png as 2x the size for the 2x folder?
is there like a list of all contexts cause I have never seen context.money_altered in the smods wiki before
Oh neat, thank you
ctrl-alt-shift + s opens an export menu that lets you set the path and resize amount
yeah, I figured it out with some googleing lol
nice
but thank you so much!
also, files will remember your export settings, so, for example, your jokers.png will always have its export settings make the 2x file and in its correct path
I see, thanks
how do i make it so that something happens whenever you hover over a joker and press a key
does anyone know how the xmult sound was made
Anybody know how to make the same changes to a large group of images?
SMODS.Keybind and check for G.CONTROLLER.hovering.target
ty
related to that, how would i add a config tab and keybinds
originally wasnt but i thought about it
tried looking at other mods but theres always a bunch of other options so not sure what im looking for
hii i was wondering
SMODS.Enhancement:take_ownership('gold', {
generate_ui = function(self, info_queue, card, desc_nodes, specific_vars, full_UI_table)
SMODS.Enhancement.generate_ui(self, info_queue, card, desc_nodes, specific_vars, full_UI_table)
``` why does this make the variable nil in the description
what exactly is the difference between generate_ui and generate_card_ui
how do i check what deck is currently being used
how do i take ownership and ADD to a function instead of overwriting
You save the old function in a variable before you take ownership.
o
Does anyone know how to make music play when you have a specific joker in your hand? I'm mostly using Joker Forge and it doesn't have that feature, and I tried looking at the Smods API but I have no idea how it works, nor how to code
G.GAME.selected_back.effect.center.key
problem: G.P_CENTERS.m_gold.generate_ui is NIL
but overwriting it with take_ownership ruins the rest of the ui
pls help
why is it so hard to add the description of one card to another
how do i actually do multiple description boxes? this doesnt seem to work for me for some reason
how to change hand size for one blind?
G.hand:change_size(number)
G.GAME.round_resets.temp_handsize = (G.GAME.round_resets.temp_handsize or 0) + number
I tried messing with the joker card's lua file but it resulted in a crash every time
Tried matching the layout of name and text?
just finished setting up an entire windows vm just to run paint.net 😮💨
why are there seriously no good alternatives that run on linux
qualatro does this for a bunch of its jokers
see how its implemented there
How would I check how? Should I download the mod and check the lua files?
does it not work with wine?
Oh seems very complicated
right
thankfully my (very recently retired) old laptop has windows
so i could re‐use the product key
Not sure if im missing something but I'm not seeing where or how the music is played
also check out https://github.com/Steamodded/smods/wiki/SMODS.Sound
This is what I checked but I'm not sure if im not understanding it but I could not for the life of me find out how to implement it correctly, and I would just crash my game
select_music_track = function()
return next(find_joker("cry-Jimball"))
and Cryptid_config.Cryptid
and Cryptid_config.Cryptid.jimball_music
-- Lowering priority for edition Jimballs later
and 200
end,
the function select_music_track in SMODS.Sound must return true for the track to be used as BG music
How do I add a context for checking when a playing card is destroyed? context.destroy_card hasn't worked.
why are my messages not sending
context.remove_playing_cards
what in the fresh hell is going on here
finally
im using a localized mod description btw
That worked.
is this where that bit from hotpot came from
anyways how do i recalculate the played hand so enhancements/changes score before they were played initially
it actually came from #1325646527292637194 message
How would I implement that into this? Not sure if should send the whole thing in the chat.
It needs to be implemented in SMODS.Sound
See the code i linked
you check if the joker is owned there
Would that be a seperate lua file?
doesnt need to be
So should I put that code in the top of the jokers lua?
Joker Forge seperates the jokers into their own lua files
oh god jokerforge
Or maybe in the main lua
Idk how to code 😭
I found the lua for sounds. I think I would edit it like this? not sure what the Cryptid_config.Cryptid is. Idk what the mod does in its code
I got it to work
SMODS.Atlas {
key = 'dwVoucher_timesup',
path = 'timesup.png',
atlas_table = 'ANIMATION_ATLAS',
frames = 21,
px = 71,
py = 95,
}
SMODS.Voucher {
key = 'timesup',
atlas = 'dwVoucher_timesup',
pos = { x = 0, y = 0 },
config = { extra = {blind = 'j_dandy_dyle'} },
loc_vars = function(self, info_queue, card)
return { vars = {} }
end,
redeem = function(self, card)
G.E_MANAGER:add_event(Event({
func = function()
G.FORCE_BOSS = card.ability.extra.blind
return true
end
}))
end
}```
Anyone know how to animate vouchers?
i think you have to code it manually
Update SMODS
Nope not anymore
you can use fps = whatever now i think
oh nice
10 is the default for everything, if you want it different set it to whatever otherwise you don’t need it
Ah cool
I set fps to 10 cos my thing had over 42 frames which made the thing go 20 fps
lmfao
?
The cat png
yea that's the pfp of the smods github acc
neat
Is this a new update to Steamodded? This doesn't show up for me.
yes
How recent? I'm not up-to-date for when i should update my mods.
i forgot how to check for if a boss blind is beaten
if context.end_of_round and context.beat_boss
do i also add main_eval?
Yes, if it's not an enhancement, edition or seal.
how do i add a juice_up() or a delay before shuffle during context.after
like yesterday
chat help my code doesnt run
neither print statement shows up
i am very confused
i cant show the full code
That's my contribution to SMODS. 😂
petition for smods to add loading screen tips
What object is it in?
a joker
Is it in your slots like normal?
everything about the joker works
it is in the slots
the sprite and description show up and it doesn't crash when I do anything
its effect just doesn't run and I don't get why
other things that trigger on the same context work
just not my thing
i guess i should find out if other contexts are failing too
local output = ""
for k, v in pairs(context) do output = output .. k .. ': ' .. type(v) .. ' / ' end
print(output)
can you throw this at the top of the calc function?
I'm assuming it doesn't print using_consumeable then
it does
this will sound really dumb but try deleting the conditional and typing it again
oh
weird
im gonna be annoyed if i remove the other code and it works properly
they printed now
was it saved before?
maybe not
the rest of the effect isn't working but i think I get why
is g.playing.cards ipairs or pairs
G.playing_cards
i wrote it correctly in the code
ipairs can work, yes.
uhhh
is there any way i can trigger effects on debuffed cards? i.e. i want debuffed cards held in hand to give money, but it won't trigger because they're debuffed
you should be able to check card.debuffed shouldnt you
well yeah i can do if context.individual and context.other_card.debuff then
but the effect won't actually go off on the card, because it's debuffed
ohh my god i'm fuckin stupid
i was changing the joker's perma_bonus value instead of the card's
theres a joker that does something like this in a mod i have ill try to find it
it would be very helpful if you could!
you can simulate it by iterating over the hand
well this effect goes on the joker, not on the debuffed card itself, so that's not the issue here
i want the debuffed card to give money so i.e. it can be retriggerable with the mime
you might need a context function hook or a lovely patch
i think those would be able to "simulate" the cards giving the effect since they are not on the card
theyd just check for the enhancement or whatever it is you're dong it on?
i can simulate it by counting debuffed cards in the hand and having the joker give the money, yeah, but that's not exactly what i want...
mime retriggers in context.cardarea == G.hand doesnt it
yeah
just use SMODS.calculate_effect within whatever context you want
you can't calculate debuffed cards though
how do i set sticker in SMODS.create_card ?
that's the point of debuffed carxs
and what's the function to add/remove stickers?
Card:add_sticker(key)
for create_card, do stickers = {'key1', 'key2' ...}
probably add force_stickers = true too
and to remove?
Card:remove_sticker(key)
print("beware the {C:attention}pipeline")
i'm not actually seeing anything in the code for calculate effect specifically that blocks it
theres code in the main scoring loop and such but
print("code explode")
well thats pretty easy to hook isn't it?
attempt to call method 'remove_stickers' (a nil value)
not to allow debuffed cards to calculate in a very specific circumstance, no
i have j:remove_stickers('perishable')
remove_sticker, not plural
i mean can't you just do a global flag and call calculate effect
there is an ignore_debuff argument right there, could i not pass it along from the calculate function somehow...?
its on the context
you could set it on the context object probably
no, you can't access this function for the debuffed card from your joker
context.ignore_debuff = true
mayhaps
this is context abuse though and will probably cause ultrajank
would it not reset itself to the appropriate value next time it's used though?
yeah but if other cards are doing calculations they may trigger on the debuffed card depending on when ignore_debuff is set
which i'm going to check actually
yeah it doesn't reset itself after every calc call
so could i save it in a local var and then set it back to what it was after the joker is done?
though idk how exactly i would get the right timing... maybe if i put the whole thing into an event or something
you could but i'm going to try to make a better solution for you
since i really don't like this haha
i'm really not good enough at coding to be making any substantial claims on this lol
i'm intrigued! actually though what is context.ignore_debuff even for? none of the jokers in vanilla remade use it
the context for when a card is debuffed by a blind
i thought maybe flower pot would use it because debuffed cards still count their suits but nope
since that exists apparently
new booster pack meta
is being crunchy part of the meta
yes
okay so i didn't need to look for anything at all
despite what they said
you can just use calculate_effect on debuffed cards
i tried it
like this:
if card.debuff then
SMODS.calculate_effect({ what you would put in a calculation return }, card)
end
with this being in a loop looping over the cards
it might actually
you should try it
it wont
but i was not able to test it without coding a whole joker
well here
calculate = function(self, card, context)
if context.end_of_round and not context.game_over and context.cardarea == G.hand
and context.individual and context.other_card.debuff
then
-- Muhnee buffer
G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + card.ability.extra.money
return {
dollars = card.ability.extra.money,
message_card = context.other_card,
-- Reset muhnee buffer
func = function()
G.E_MANAGER:add_event(Event({
func = function()
G.GAME.dollar_buffer = 0
return true
end
}))
end
}
end
end
this doesn't do anything at all
debuffed cards will not be assigned as context.other_card
i'll try it with calculate_effect but i don't see why it would be any different?
oh? huh
yeah thats why i said to loop over the played cards
guys is there a way to make a certain consumable set not be copied by perkeo?
alright well, this works! but because i'm now doing it in context.main_eval instead of context.individual, it doesn't interact with the mime
oof. im sure I could try to whip up a solution but I am currently about to be occupied for an hourish
you've already helped a lot, thank you!
maybe i could manually repeat the iterating over cards once for each mime the player has?
then i'd also have to account for bp/bs copying the mime somehow...
i’m wondering why that is? does having debuffed cards in there mess with stuff?
that's how thunk wrote the code
it makes more sense to block debuffed cards from being calculated than it does to check whether a card is debuffed in every effect on cards
https://cdn.discordapp.com/attachments/1443067047591542867/1452683513340887191/image.png?ex=694ab473&is=694962f3&hm=e85bc51546112bb75eb83f43d5b20422db55330aec37d3f9125840880e902589&
https://cdn.discordapp.com/attachments/1443067047591542867/1452683390942974072/image.png?ex=694ab455&is=694962d5&hm=adaf15963898c25ff32ccb6f99d67624c02cdb9a03bb2027c5fdf4bbd653713a&
https://cdn.discordapp.com/attachments/1443067047591542867/1452684160677445753/IMG_1704.png?ex=694ab50d&is=6949638d&hm=473e688cf16a3cb792e95ee54f42b850740a330e21bb36818077d068d9d2e299&
idk what i'm doing wrong
i think it should be saved = true instead of a message
which photo
now here’s another idea. i see that there’s a SMODS.calculate_context() function. from the description i don’t understand what it does, but could i use it to like, calculate context.individual for each debuffed card when i’m iterating through the hand?
in your code
no its accurate
that's the text for when you're revived, when you're saved by mr. bones, it would say "saved by mr. bones"
the issue is that saved returns a key to localization.misc.dictionary
you dont put the actual message displayed there
also is it even possible to fire context.force_trigger during end of round?
that's or
if you're using demicolon, this joker will gain a revive when forcetriggered
no but
you put the forcetrigger check INSIDE the end of round check
demicolon doesnt trigger at end of round
if (context.main_eval and context.beat_boss) or context.forcetrigger then```
also why are you running code if the save check failed
if context.end_of_round then
if context.force_trigger...```
the inner block isnt run if its not end of round
oh right
i forgot about that
why are you setting the eemult value at game over also
you can simplify the code a lot by just using the tally + 1 as the eemult number
you have two redundant variables for the same thing
also the description in general is kinda a mess
oh wait i misread that
gains 1 revive when
boss blind is defeated
lose 1 revive when death is prevented
and gain ^^1 mult
(currently ^^1 and 7 revives)```
you dont need a seperate tally just make it add to the eemult counter
how do i explain this?
surely it should just be "lose 1 revive"
exactly
you gain the total tally as ^^mult when death is prevented.
eemult?
oh
ye
why don't you just call it like tmult
hang on
technically, talisman refers to it as eemult
oh ok
gains 1 revive
when boss blind is defeated
lose 1 revive when death is prevented
and gain ^^1 mult
then increase mult gain by 1
(currently ^^1 and 7 revives)```
then just make the gain ^^1 mult a variable too
personally i dont think it needs the exponential scaling but you do you ig
where do i put the gain_mod and mult_mod?
calculate = function(self, card, context)
if
not context.blueprint and
(context.force_trigger
or (context.end_of_round
and context.main_eval
and context.beat_round
and not context.game_over))
then
card.ability.extra.revives = card.ability.extra.revives + 1
return { message = "+" .. card.ability.extra.scale .. "revives", colour = HEX("d86a0") }
end
if context.game_over and card.ability.extra.revives > 0 and not context.blueprint then
card.ability.extra.revives = card.ability.extra.revives - 1
card.ability.extra.eemult = card.ability.extra.eemult + card.ability.extra.scale
card.ability.extra.scale = card.ability.extra.scale + 1
G.E_MANAGER:add_event(Event({
func = function()
G.hand_text_area.blind_chips:juice_up()
G.hand_text_area.game_chips:juice_up()
end
}))
return { saved = "k_whatever_key_you_want" }
end
if context.joker_main then return { ee_mult = card.ability.extra.eemult, colour = HEX("d86a0")```
?
oh also you probably shouldnt be hardcoding the colour
you have a custom rarity right
yes
smods already adds its colour to the global colour table
i assume its like G.LOC_COLOURS.pfx_raritykey
actually hang on i can make this a bit clener
calculate = function(self, card, context)
if context.joker_main then return { ee_mult = card.ability.extra.eemult, colour = HEX("d86a0") }
if context.blueprint then return end
if
context.force_trigger
or (context.end_of_round
and context.main_eval
and context.beat_round
and not context.game_over)
then
card.ability.extra.revives = card.ability.extra.revives + 1
return { message = "+1 revives", colour = HEX("d86a0") }
end
if context.game_over and card.ability.extra.revives > 0 then
card.ability.extra.revives = card.ability.extra.revives - 1
card.ability.extra.eemult = card.ability.extra.eemult + card.ability.extra.scale
card.ability.extra.scale = card.ability.extra.scale + 1
G.E_MANAGER:add_event(Event({
func = function()
G.hand_text_area.blind_chips:juice_up()
G.hand_text_area.game_chips:juice_up()
end
}))
return { saved = "k_whatever_key_you_want" }
end
``` always abuse early returns if possible \:)
now we dont have to check every if block for blueprint since if it was blueprint then it already exited on line 4
oh yeah, i usually tend to not use direct numbers during calculate functions because i have a joker that manipulates values.
ffair
just replace all the stuff with a static card.ability.extra.whatever
also you can just use localize("k_upgrade_ex") to get the generic "Upgrade!" text, its probably cleaner
is scale the tally?
yea
the way this is worded directly adds 1 to how much the mult is scaling by
wait hang on
why are you setting a custom colour for the eemult trigger
careless use of free will i geuss
lol
again id say use the global colour table
so its easier to change down the line
wait, the tally starts at 0```lua
if context.game_over and card.ability.extra.revives > 0 and not context.blueprint then
card.ability.extra.revives = card.ability.extra.revives - card.ability.immutable.deduction
card.ability.extra.eemult = card.ability.extra.eemult + card.ability.immutable.tally
card.ability.immutable.tally = card.ability.immutable.tally + 1
isn't it immutable.tally supposed to go first before extra.eemult?
huh, alr
it's context.beat_boss cause it's looking for if the boss blind is defeated
yea
so why did you write context.beat_round
oh oops
dawg wtf
ik this might be an easy question but how do i change the number of discards/hands/hand size? i think things like vouchers just do it by default just by setting up config, and i want to do it in some other effect
I downloaded the newest SMODS, and any time I use a planet, I keep getting this'
did you check vanillaremade
Hand Size:
And for Hands & Discards
tysm
balala font coding :0
how do i make a vanilla enhancement display the info_queue of another enhancement
hmm is that vsc
Where is the swap property for jokers and how can I change it to true?
it's np++ i think
i use np++ and i cant tell
maybe its becayse i only use light mode 😔
eh i mean it matches close enough to vs code
theres like two billion themes
and the indent highlighting (the lines) are the same
Why does calling copy_table() on G.jokers.cards trigger a stack overflow?
can anyone explain to me what SMODS.calculate_context() actually does? can i somehow use it to calculate a card under a different context?
where would i hook for checking hand type when playing?
it needs to be a hook bc this is for a challenge rule
challenges have calculate functions
This does switch around positions of two random Joker cards, but the one moved to the right still triggers before the one on the left. What do I do?
-- self.config.extra.jokers_to_shuffle = 2
calculate = function(self, blind, context)
if not G.GAME.blind.disabled then
if context.press_play then
local table_of_valid_joker_indices = {}
for i = 1, #G.jokers.cards do
if not G.jokers.cards[i].pinned then
table_of_valid_joker_indices[#table_of_valid_joker_indices + 1] = i
end
end
if #table_of_valid_joker_indices >= self.config.extra.jokers_to_shuffle then
table_of_valid_joker_indices = LAPSEMS.extract_randomized_elements_from_table(table_of_valid_joker_indices, self.config.extra.jokers_to_shuffle)
G.jokers.cards[table_of_valid_joker_indices[1]], G.jokers.cards[table_of_valid_joker_indices[2]] = G.jokers.cards[table_of_valid_joker_indices[2]], G.jokers.cards[table_of_valid_joker_indices[1]]
blind.triggered = true
blind:wiggle()
end
end
end
end
it isn't listed on the smods wiki page for challenges
Devs update the wiki and my life is yours!!!
is this a recent thing or smth? cuz every modded challenge i saw (which tbf wasnt alot) only used rules
meanwhile i only used rules for localization and relied on calculate for everything
it was added in august, so still fairly recent
also, although i've now put it in a calculate function, i do want to make it a rule at some point
yea you can make challenge rules that just have text and nothing else
that's not what i mean
i mean a rule that does something
i've added a rule that's just text but i want an actual rule that does it
how do rules even work? i havent figured that out yet
you add the rule and it does the thing
for example, my mod has elle_no_shop and adding that to a challenge disables the shop completly
yeah so how does that work, i dont think adding a string alone will just obliterate shops
i have a patch that checks for the challenge rule
yes
though i've since added edge cases for hotpotato and theencounter(separate mod for hotpot's event system) events, as they usually appear after the shop
so from what im seeing rules just get added to the modifiers list in g.game and then when you patch you check for em?
yep
Where do i begin?
okuhh question
so for mod probability
how do you get if the triggering object is in an info queue
and getting the card its attached to
trigger_obj.fake_card should be true for anything in an info queue
dont think you can get the description its attached to though
damn
is there any way to set a variable or something when you actually set the info queue in the other card
or is there just no way to do this
what is even the goal
basically im making a joker that makes gold cards act as glass cards with double the chances
and camostar wanted to make it display the glass infoqueue with the doubled probabilities
but the probability check only checks for if a card is both glass and gold, which obviously the infoqueue isnt
and just making all glass infoqueues have double probabilities would look weird
you can probably just make the vars for the info queue manually then
?
just find what order the variables are in for vanilla glass cards
the P_CENTER only saves the xmult and denominator
info_queue[#info_queue+1] = { set = "Enhanced", key = "m_glass", config = {...} }
iirc
config?
so basically just put a list of vars into config?
yes