#💻・modding-dev
1 messages · Page 594 of 1
i dont understand what you mean
initial_scoring_step is before jokers
Yea I was lost for a sec
okay, aside juice_up() looking weird, the bug is fixed! thanks!
-$3 popup being off-sync with substraction animation is pretty concerning though, is that how money manipulations look in smods' newest version? or is it as specific as setting seal before the card is scored?
it's off-sync with rough gem too. weird
sad
Making a resource for fonts, and so I'm having to fill in some. Z and Q letters for spectral cards didnt exist, what do we think about these customs? Should i change anything about them?
yooooo thank u for this, ive always been looking for the lettrs used in spectral cards
Q seems to look fine
i think those look good
just wait, ill release it with some more fonts too. Soon.
what about Z?
Looks a little odd but overall it's good imo
should i change it? would it be better without the little nibs? Im wondering if the flourish/style gets in the way of readability
Yea the left one looks a bit like an 8, but the right one looks decent
heres an in-practice comparison
asked around and from a distance its readable so im keeping the flourish :)
For aesthetic I like the 1st, but the 2nd is a lot more readable...what I'd probably do is have a switch so you can swap between versions if its unreadable to some people
chat i need wording help
They could also add multiple letter varieties, like the two Zs
Like what they get to pick aesthetics or readability so probably consider adding both
yeah
i personally vote B tbh, since i personally value clarity over aesthetic
but A isn't too bad i probably would still know what word it is
plus if it's just the sprite then it's really not an issue
So I am new to the modding scene...and havent coded in 2 years, so I know I'mma screw up a lot lol. I'm just trying to make the values of the Joker's chances and +mult pop up for the card but they're not and just saying 'nul,' I'll give all the code I have for a possible fix on that (also just trying to figure out how to mod in its effects so thats why theres a lot extra)
SMODS.Joker{
key = 'RocketLauncher',
loc_txt = {
name = 'Rocket Launcher',
text = {
'{C:green}#1# in #20#{} chance',
'to gain {C:mult}+#100#{} Mult',
'{C:red}and destroy itself!{}'
}
},
config = {
odds = 20,
mult = 100,
},
rarity = 1,
blueprint_compat = false,
eternal_compat = false,
atlas = 'DRY_Jokers',
pos = {x = 0, y = 0},
cost = 4,
loc_vars = function(self, info_queue, card)
local probabilities_normal, odds = SMODS.get_probability_vars(card, 1, card.ability.odds, "RocketLauncher")
return { vars = { probabilities_normal, odds, card.ability.mult } }
end,
calculate = function(self, card, context)
if context.joker_main then
if SMODS.pseudorandom_probability(card, "RocketLuncher_mult", 1, card.ability.odds, "RocketLauncher_mult") then
SMODS.calculate_effect({ mult = card.ability.mult }, card)
end
end
end
}
I think loc_txt is the source of the issue
it should be #1#, #2# and #3#
So what I'd want is
SMODS.Joker{
key = 'RocketLauncher',
loc_txt = {
name = 'Rocket Launcher',
text = {
'{C:green}#1# in #2#{} chance',
'to gain {C:mult}+#3#{} Mult',
'{C:red}and destroy itself!{}'
}
},
config = {
odds = 20,
mult = 100,
},
rarity = 1,
blueprint_compat = false,
eternal_compat = false,
atlas = 'DRY_Jokers',
pos = {x = 0, y = 0},
cost = 4,
loc_vars = function(self, info_queue, card)
local probabilities_normal, odds = SMODS.get_probability_vars(card, 1, card.ability.odds, "RocketLauncher")
return { vars = { probabilities_normal, odds, card.ability.mult } }
end,
calculate = function(self, card, context)
if context.joker_main then
if SMODS.pseudorandom_probability(card, "RocketLuncher_mult", 1, card.ability.odds, "RocketLauncher_mult") then
SMODS.calculate_effect({ mult = card.ability.mult }, card)
end
end
end
}
yes
alright, thank you! :)
Also for context.ante_end, is there a reason why it triggers twice?
Honestly I just copied from a card that was similar to what I was doing, forgot it had 2 things on that card
Well at least the description shouldn't show nil as far as it seems
Yes, it triggers once for the modify context and once for when the ante actually changes
context.end_of_round triggers like fifteen billion times
kid named main_eval
G.GAME.blind.boss only allows it to trigger after the boss blind is beaten I believe
Btw I only seemed to manage to have the deck give mult via context.before but that didn't really work as it doesn't run after the game sets the hand values, essentially overriding the mult gain
you can do context.ante_change and context.ante_end
context.ante_change accounts for any sort of Ante changes, like the vouchers no?
if you still want to do end_of_round it should be context.end_of_round and context.main_eval and context.beat_boss
I'm testing it rn 😭
yes but not with context.ante_end, thats only when you beat the last blind
its better for mods that add extra boss blinds
Alright I will give that a shot
Idk if context.ante_change would work at all since I have a spectral that moves players back antes
like i said with context.ante_end it will only trigger after the boss blind
what is it
Triggering twice
i am going to cry
Same honestly..
Me too
What could cause this error? (i've added a new deck and it crashes)
code and full log pls
one sec
missing mod prefix on voucher
also it should be vouchers = { <voucher 1>, <voucher 2>}
what is this for
Had to do custom B, J, Q, V, Y, and Z. What do we think?
Alright heres a Consumable Font Generator
Download and use to your own delight
Ill provide it in my post https://discord.com/channels/1116389027176787968/1346880030629695498 to come back to
how can i make that the deck start at ante 5 without crashing
Is everything's in order here?
Put it in an event.
G.GAME.round_resets.ante = self.config.extra.ante_level
G.GAME.round_resets.blind_ante = G.GAME.round_resets.ante
in your apply function
No, you don't hook inside calculate
You shouldn't be hooking inside calculate
what are you trying to do here
+1$ cost to all jokers on boss blind defeat
actually I was originally trying to do Jokers cost extra $ equal to current Ante
but no idea how
copy gift card's code from vanillaremade
move the hook outside calculate
and remove the event mangaer part
couple other issues with this hook as well
hold on theres a guide for this
G.GAME.inflation = G.GAME.inflation + 1
same as the challenge uses
nvm me use this
forgot Inflation existed
Is there a definition for "Jokers' cost"?
so I can equalize it to Antes
👌
idk if that affects just joker though
It doesn't
I just can't find any mods that utilized this effect or anything similar
Rewrite your hook
cryptid has smth that increases the cost of jokers only
according to the guide that i sent
and also yeah that
thank you
it's not specifically ante 5 but it's a problem that i can fix it myself
dont put it in calculate
kk
yeah ease_ante is for increasing antes not setting it
Like this?
local old_ret
what's old_ret?
just delete this it's doing nothing
ok
oh wait I should return ret
I think
hook is in main lua
How do I ref it in the deck's code?
either create a modifier in G.GAME.modifiers with the deck and then check for that in the hook
or just check for the selected deck in the hook
like this?
no, it should be G.GAME.selected_back == "b_hnds_premiumdeck"
besides that its fine from the looks of it
how can i run some code if the player restarts a run/goes to the main menu?
G.GAME.selected_back.effect.center.key
oh
so when you delete a run?
yeah
hook Game:delete_run
i have another problem with decks
i want that the deck start with a specific voucher WITHOUT using loc_vars
try G.GAME.selected_back and G.GAME.selected_back.effect.center.key == "b_hnds_premiumdeck"
👌
Why would loc vars change anything tho🥺
It's just text to description
who do i throw this at
because this:
update your steamodded vro
also you created an infinite loop somewhere
you need config not loc_vars
also whats wrong with loc_vars 💔
The 2nd one isn't even loc vars
Do I leave the deck's code blank?
yeah
is this how I get the lenght of the Joker name
No crashes but no cost increase either
Did I make a mistake here?
oh
I see
the double == 🔥
im gonna cry

Anyone know how to get Edition information to show up beside the tooltip?
info_queue in loc_vars
^ it's documented in smods localization wiki iirc
😭
should be G.localization.descriptions.Joker[G.jokers.cards[1].config.center.key].name
also why not just add #name directly
if G.jokers and G.jokers.cards[1] then
local name = localize{type = "name_text", key = G.jokers.cards[1].config.center.key, set = G.jokers.cards[1].ability.set} --set can just be "joker" but this is to be safe from shenanigans
local mult = #name
end
whats with the for loop
i assume its scaling or else they would need to return something
when does it scale
idk its not my joker
i thought loc_vars was the reason that the Starting vouchers in the decks maneged to not crash the game
To you and @frosty rampart: that worked.
When Giga is going to be on the wheel of mod Im gonna be sooo happy
its not scalling
its the lenght of the name
like if the name is Joker it would give 5 mult
should just say +1 mult for every character in the leftmost joker's name
get sounds like it scales
tldr never use get in a joker description ever
it never seems to work out
now what's wrong with it
yeah but if I want to show it on the joker
which line is 21
9+10
you stupid
should up the /8 part while you're at it
how do you manipulate the value of one of the abilities of a selected card?
like that its working fine
wait actually lemme try smth
what should i cram into his noggin
still didn't fix the issue
why are you still using card.ability.extra.mult
you know you can also do the same as in loc_vars for calculate right
ik yeah but less line of code like that ?
it will not update until you hover the joker
4 hyperintelligent brains. https://youtu.be/i4YaAUA0eEM
doing anything that affects gameplay in loc_vars is generally bad practice
better like that
oh wait mb
self.ability.extra not self.config.extra
it is self.config.extra for decks
self is the prototype object, it does not have an ability table
still bad
yep
would this work
for checking if its not himself do I do that:
if G.jokers.cards[1] ~= self then
G.jokers.cards[1] ~= card
but in the loc_vars
center instead of card then
omg yeah
I forgot everything
I take just a day for doing some homework and I forget everything
try back.ability.extra
didn't work again
yeah because apply_to_run is a function of a card object
the first argument has to be a card iirc
I made it uncommun and 6$ since the mult can be 30
is there a context for entering the shop? i'd like to force every card in the shop to be polychrome
context.starting_shop
thank you
still waiting
local voucher = SMODS.create_card {
key = self.config.extra.voucher
}
G.vouchers:emplace(voucher)
voucher:apply_to_run(G.P_CENTERS[voucher.config.center.key])
try this
ok
didn't work again again
hmmmmmmm
try adding area = G.vouchers to the SMODS.create_card ig
idk why SMODS.create_card needs that tbh but 🤷
didn't work again again again
thats the same screenshot
or is this just a "start with overstock" deck
exactly
yep
i have No Idea then
is there any reason you cant just put a vouchers directly in the config
this seems way more complicated
doing that only works if there's not an apply function afaik
wait rlly
yeah
ghost deck hex also works with an apply function
Back:apply is a seperate function thats called inside of Back:apply_to_run
and apply_to_run handles all the built-in functionality
ok soo just for cheking i redownload the lasted release of smods
and changed the "voucher" config to "vouchers"
this are the result
no like
thats not directly in config
still in extra
you shouldnt need apply for this
(also vouchers should be a table of keys)
it can just be config = { vouchers = { "v_overstock_norm" } }
why did thunk call it overstock_norm instead of just overstock
because theres also overstock plus
that one can be called overstock_plus then
am going insane
it is
just make the apply an empty function
you dont need to do anything in apply for vouchers
ok now i need to find a way to do that in the joker forge codegeneration
for the codegen, i imagine you could just take any keys from "apply voucher" effects and drop them into vouchers
thgaats all i got though idk jackshit about how jf works
Sorry to butt in the middle here, just having trouble with sound effects. I think its file directory thats being weird but unsure how to fix it
I have the sounds in my assets folder in its own folder called sounds and have the below code. It all worked just fine before I put the sound in
SMODS.Sound {
key = 'EXPLODE',
path = 'explosion.ogg',
pitch = 0.8,
volume = 0.7
}
---and---
if context.joker_main then
if SMODS.pseudorandom_probability(card, "RocketLuncher_mult", 1, card.ability.odds, "RocketLauncher_mult") then
SMODS.calculate_effect({ mult = card.ability.mult }, card)
SMODS.destroy_cards(card, nil, nil, true)
G.GAME.pool_flags.RocketLauncher_extinct = true
return {
message = 'BOOM!',
colour = G.C.RED,
sound = 'EXPLODE'
}
The sound key in the return needs your mod prefix
oh, duh. Thanks!
Still is crashing when I try to use it
SMODS.Sound {
key = 'DRY_Jokers',
path = 'explosion.ogg',
pitch = 0.8,
volume = 0.7
}
--and--
if context.joker_main then
if SMODS.pseudorandom_probability(card, "RocketLuncher_mult", 1, card.ability.odds, "RocketLauncher_mult") then
SMODS.calculate_effect({ mult = card.ability.mult }, card)
SMODS.destroy_cards(card, nil, nil, true)
G.GAME.pool_flags.RocketLauncher_extinct = true
return {
message = 'BOOM!',
colour = G.C.RED,
sound = 'explosion'
}
else
return {
message = 'No Ammo!',
}
end
end
end
}
ohhhh, so in the code to do the sound do the key?
what
Idk, I'm somehow confused
what you had before was correct it was just missing the mod prefix at the start
oh
Like the prefix in your metadata json file
ohhh, so I'd wanna search for the sound prefix_explosion?
how do i add a joker with a sticker?
SMODS.add_card({set = 'Joker', stickers = {'modprefix_key'}})
I have a Joker that runs calculate_context with a specific key intended for another Joker to receive, i.e.:
SMODS.Joker {
...
key = 'joker_1',
calculate = function(self, card, context)
if context.end_of_round and context.game_over == false and not context.blueprint then
print('test')
SMODS.calculate_context({custom_key = true})
return {...}
end
end
...
}
SMODS.Joker {
...
key = 'joker_2',
calculate = function(self, card, context)
if context.custom_key then
...
end
end
...
}
But joker_2 doesn't run when joker_1 sends the context, even if print('test') and the return occurs; what do I do?
oh, forgot to mention; multiple jokers send context.custom_key, and I'd like this to be a context key to allow more jokers than joker_2 to detect the specific context
this should be working
weird
It does get a little darker in-game than in the texture, but I wouldn't describe it as extreme as you're describing
show a comparison?
what shades of black are you usiing
left one is in game
maybe something to do with the crt filter?
im sorry but im not familiar with that?
what is it
just for refrence the normal planet cards look much more like the ones in the textures
only my "custom" ones look darker to me
ok so apparently this is caused by the context table containing a value that is a card that is destroyed before calculate_context
ohh thanks
im fairly certain that a lower CRT filter still applies a saturation effect on the entire screen
causing sprite differences
Could I get some more coding help? Been trying to figure this out for a few hours and haven't had any luck
bruh
ok then
key = "trifuricated",
path = "j_trifuricated.png",
px = 71,
py = 95
})
local sigil = {
object_type = "Sigil",
atlas = "trifuricated",
key = 'trifuricated',
pos = { x = 0, y = 5 },
badge_colour = G.C.RED,
calculate = function(self, card, context)
if context.repetition then
return {
repetitions = card.ability.sigil.extra.triggers,
}
end
end,
loc_vars = function(self, info_queue, card)
info_queue[#info_queue + 1] = G.P_SIGILS[card.ability.extra.sigil]
return { vars = { self.config.extra.retriggers } }
end
}```
Sigils are meant to work like Stickers or Seals
I'm having trouble giving the sigil to a joker inherently, so i can't test if it even works or not yet
key = "mantisgod",
pos = { x = 0, y = 0 },
rarity = 1,
blueprint_compat = true,
eternal_compat = true,
unlocked = true,
discovered = true,
effect = nil,
soul_pos = nil,
atlas = "mantisgod",
cost = 1,
config = { extra = { chips = 10, mult = 1, sigil = "trifuricated" } },
func = function()
set_ability(card.ability.sigil, nil, true)
return true
end,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.chips, card.ability.extra.mult, card.ability.extra.sigil } }
end,
calculate = function(self, card, context)
if context.joker_main then
return {
chips = card.ability.extra.chips,
mult = card.ability.extra.mult,
sigil = card.ability.extra.sigil,
}
end
end
}```
can someone help me explain how to make achievement
Trying to figure out how to make my times mult on my custom joker display in white text like Balatro does, this is what I saw in other code but its not working for me and is still in black
loc_txt = {
name = 'The Orb Larcenists',
text = {
'{C:green}#1# in #2#{} chance',
'for {X:mult, C:white}X#3#{} Mult',
}
},
thank you :)
you aren't really making the sigil properly, you're just creating a table
it needs to be local sigil = SMODS.GameObject:extend { to make it a game object; you could also extend SMODS.Sticker instead to borrow some sticker defaults but then you have to do some shenanigans to get sigils out of the Stickers page in the collection
key = "trifuricated",
path = "j_trifuricated.png",
px = 71,
py = 95
})
SMODS.Sticker = {
key = 'trifuricated',
badge_colour = G.C.RED,
pos = { x = 0, y = -5 },
blueprint_compat = true,
config = { extra = { retriggers = 2 } },
calculate = function(self, card, context)
if context.repetition then
return {
repetitions = card.ability.sigil.extra.triggers,
}
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { self.config.extra.retriggers } }
end
}```
```SMODS.Joker {
key = "mantisgod",
pos = { x = 0, y = 0 },
rarity = 1,
blueprint_compat = true,
eternal_compat = true,
unlocked = true,
discovered = true,
effect = nil,
soul_pos = nil,
atlas = "mantisgod",
cost = 1,
config = { extra = { chips = 10, mult = 1, sticker = "trifuricated" } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.chips, card.ability.extra.mult, card.ability.extra.sticker } }
end,
calculate = function(self, card, context)
if context.joker_main then
return {
chips = card.ability.extra.chips,
mult = card.ability.extra.mult,
sigil = card.ability.extra.sticker,
}
end
end
}```
I don't understand what the issue is, as far as I can tell I'm using Stickers and the functions correctly
crash error in relation
Gng is there anyone here who can make art for my balatro mod (its just a crappy joke mod mainly for my friend group but idk anyone who can do art)
I can probably pay via like steam games (dm if unterested]
remove the = from
SMODS.Sticker = {
also idk what sigil = card.ability.extra.sticker, does here
OH SHOOT I DIDNT CHANGE IT
The only thing I'm still stuck on is giving a Joker a Sticker inherently
like, it always has it?
yes
do card:add_sticker("modprefix_key", true) in add_to_deck
then it won't show up in the shop until after you buy it I think
do it in set_ability instead (with a bit of extra work if you don't want it to have the sticker in the collection)
yeah i dont know why i said add to deck lol i was thinking set_ability
well now its crashing whenever it try to load the sticker in
Do any of you know how to get the rank of the most recent card added to deck?
make a mod calculate function and track it with context.playing_card_added
"Mod calculate function"? D'you mean put it in calculate = function(self, card, context)?
yea
SMODS.current_mod.calculate = function(self, context)
718 if context.pre_discard then
719 for _, card in ipairs(context.full_hand) do
720 if not context.blueprint then
721 G.E_MANAGER:add_event(Event({
722 func = function()
723 if not G.STATES.SELECTING_HAND then return false end
724 draw_card(G.discard, G.hand, nil, "up", true, context.other_card)
725 return true
726 end
727 }))
728 end
729 end
730
731 context.other_card.ability.perma_h_x_mult = (context.other_card.ability.perma_h_x_mult or 1) + card.ability.extra.xmhandgain
732 card:juice_up(0.5, 0.5)
733 context.other_card:juice_up(0.5, 0.5)
734
735 return {
736 extra = {
737 card = card,
738 message = localize("k_upgrade_ex"),
739 colour = G.C.MULT
740 },
741 }
742 end``` ok anyone know why this isnt drawing my cards to hand? its also for some reason erroring with a "attempt to index a nil value" on line 731
theres no other_card in pre_discard
oh
What does this do?
its identical to a calculate function but runs globally
it's the same as for jokers but global
you dont need to own a joker for it to work
I'm asking for a Joker I'm making.
oh wait i just realized also G.STATE == G.STATES.SELECTING_HAND lol ^^"
yes and the solution was to keep track of the last card using that
you can store it in a G global i think
theres nothing else that keeps track of the last card added
So, could I put a SMODS.current_mod.calculate = function(self, context) and calculate = function(self, card, context) function in the same Joker?
no
the first one goes outside the joker
you have the calculate function globally tracking it and writing to G.GAME.yourmod_last_added
and your joker can then read from that global
So, do I need only return context.playing_card_added:get_id()?
well, what are you trying to do exactly
Determine the rank of the card that was most recently added to deck!
Why ever not?
you set G.GAME.yourmod_last_rank
i dont think the return value for mod calcs are used
<@&1133519078540185692>
BEGONE CRYPTO BRO
What, then?
in context.playing_card_added, context.cards is the list of cards added
you want to take the last card in the list and save the id or rank key (you can use get_id) to something like G.GAME.modprefix_last_rank
So, would context.cards[#context.cards]:get_id() work?
yeah
Wouldn't that be changed if the most recent card added was later destroyed?
Perhaps I could make it only kick in when a card's added to deck.
if you destroy the card, it was still the most recent card added to your deck. doesn't matter that it doesn't exist anymore
oh i didnt know that cool
if youure really worried you could make a list of the most recent cards added
but like meta said i dont think it would matter
Would this still do the trick?
if context.playing_card_added then
local most_recent_rank = context.cards[#context.cards]:get_id(),
end
Cribbed from Hologram.
no, because the local disappears as soon as that calculate function ends (which would be immediately)
it needs to be in G.GAME.modprefix_last_rank for other objects to be able to access it later
(replace "modprefix" with your mod's actual prefix)
Would it still work, though, if most_recent_rank was defined outside of the if statement?
local most_recent_rank
if context.playing_card_added then
most_recent_rank = context.cards[#context.cards]:get_id(),
end
no
because then the local gets overwritten with a nil the next time the calculate function runs (which would be immediately)
the calculate function runs many many times over the course of a single hand
again
it needs to be in
G.GAME.modprefix_last_rankfor other objects to be able to access it later
Would this work?
most_recent_rank = G.GAME.<modprefix>_last_rank
G.GAME.modprefix_last_rank is a variable you should be setting/modifying yourself
you are making it exist in the global mod calculate
and then you can reference it in the joker you want to use it in
G.GAME.<modprefix>_last_rank = context.cards[#context.cards]:get_id()
how did you do this formatting
Do you mean to say that G.GAME.<modprefix>_last_rank gets overwritten all the time with the newest rank?
i don't know how much clearer i can make it
if you put the line i'm replying to in context.playing_card_added in your global mod calculate function, then G.GAME.<modprefix>_last_rank will always be the rank of the last card you added to the deck
if you use a local in any capacity, it will not persist longer than a fraction of a second. it must be a variable stored in G.GAME
At the risk of frustrating you even more, I ask: what is a global mod calculate function?
this thing
I have G.GAME.<modprefix>_last_rank defined outside of any function.
Am I doing this right?
SMODS.current_mod.calculate = function(self, context)
G.GAME.<modprefix>_last_rank = context.cards[#context.cards]:get_id()
end
nearly
- it still needs the
context.playing_cards_addedcheck - replace
<modprefix>with your mod's actual prefix (technically you don't need to, but for identification/uniqueness/making sense purposes it's a very good idea)
you should in case another mod decides to also add G.GAME.last_rank
is there a built in way to change a voucher's price when it spawns or am i gonna have to hack one together
(the voucher is intended to be redeemed multiple times and get more expensive each time)
i mean like natural spawns
I see in Clearance Sale's code that it applies G.GAME.discount_percent, presumably to everything, and I'm currently peering at Astronomer's code and I'll report my findings soon...
Looks like it sets their self.cost to 0.
Here's how it determines if it's a Planet Card or a Celestial Pack:
if (self.ability.set == 'Planet' or (self.ability.set == 'Booster' and self.config.center.kind == 'Celestial')) then
self.cost = 0
end
I hope this helps.
i'm confused this doesn't decrease joker slots when the round is ended
like, it does decrease the number of joker slots, just not from the "only in blind effect"
...
if ((G.GAME.blind:get_type() == "Small" or G.GAME.blind:get_type() == "Big" or G.GAME.blind.boss) and not context.blueprint) and card.ability.extra.context == 1 then
G.jokers.config.card_limit = G.jokers.config.card_limit + card.ability.extra.joker_slots
card.ability.extra.context = 0
end
if context.end_of_round and not context.game_over and context.main_eval and not context.blueprint then
if card.ability.extra.joker_slots >= 2 then
G.jokers.config.card_limit = G.jokers.config.card_limit - card.ability.extra.joker_slots
card.ability.extra.joker_slots = card.ability.extra.joker_slots - card.ability.extra.joker_slots_mod
card.ability.extra.context = 1
end
...
here i'll record a video showing what's happening
One thing I like to do a lot for these things is see how existing Jokers do their thing. Here's what I pulled from Ramen:
if context.discard and not context.blueprint then
if card.ability.extra.Xmult - card.ability.extra.Xmult_loss <= 1 then
SMODS.destroy_cards(card, nil, nil, true)
return {
message = localize('k_eaten_ex'),
colour = G.C.FILTER
}
else
card.ability.extra.Xmult = card.ability.extra.Xmult - card.ability.extra.Xmult_loss
return {
message = localize { type = 'variable', key = 'a_xmult_minus', vars = { card.ability.extra.Xmult_loss } },
colour = G.C.RED
}
end
end
722 blocking = false,
723 func = function()
724 if G.STATE ~= G.STATES.DRAW_TO_HAND then return false end
725 -- gimmie my quickdraws damnit
726 draw_card(G.discard, G.hand, nil, "up", true, c, 0.01)
727 SMODS.draw_cards(1)
728 card:juice_up(0.5, 0.5)
729 return true
730 end
731 }))``` does anyone know why this is drawing cards so slow? i want it to be at the same speed as normal drawing
Say, does anyone know how to have a consumable add chips to a score after use? Or mult, or even xmult?
I can dig up some astronomica code for resolving +score or xscore, but if you mean like modify the chips or mult of next hand played I have no idea
That's what I meant, but I think I figured something. Mind if I show it?
how do i check if a player is on a specific stake
See if player is on small blind. if so, yes. if not,
see if player is on big blind. if so, yes. if not,
see what boss blind player is on
(if they are in blind anyway)
SMODS.stake_from_index(G.GAME.stake) == "key" should work
Say, N, any help with this?
do you want to add it to the next hand played?
Yeah, but only the next hand.
you can either keep the consumable in the slots and use calculate with it or use something like the global mod calculate to keep track of how much chips or mult should be added next hand
Mind if I show the base code I figured up? (very vague, likely won't work.)
ok
no it wont
I kinda figured. Where does it break?
- calculate is not an attribute of an event
- if the idea is to have the calculate on a delay with the event that's not how functions work
If I fix those, will it work as I think it will?
So, for my idea to work as it should, just set the global mod calculator to whatever I want it to be for the card?
you would need to save how much chips or mult you want to give somewhere and then return that in the mod calculate, in context.main_scoring or something
Closer to this?
not even close no
lol
-- in yiur consumable
use = function(self, card, area)
G.GAME.modprefix_iron_mult = (G.GAME.modprefix_iron_mult or 0) + number
end
-- somewhere else in your file
SMODS.current_mod.calculate = function(self, context)
if context.main_scoring then
local give_mult = G.GAME.modprefix_iron_mult or 0
G.GAME.modprefix_iron_mult = 0
return { mult = give_mult }
end
end
something like that
key = "iron",
set = "xiferp_lement",
cost = 3,
pos = { x = 3, y = 5 },
use = function(self, card, area)
G.GAME.xiferp_iron_mult = (G.GAME.xiferp_iron_mult or 0) + 4
end
end
SMODS.xiferp.calculate = function(self, context)
if context.main_scoring then
local give_mult = G.GAME.xiferp_iron_mult or 0
G.GAME.xiferp_iron_mult = 0
return { mult = give_mult }
end
end
} ```
like so?
Ah. And if I swap mult with chips it works much the same there?
yeah
Okay. one last thing.
How do I make it so that it adds per card of a certain rank? (Ik this is joker, not consumable-level, but I have an idea)
per card of a certain rank in deck? or in the hand played?
in hand played
you can check context.scoring_hand like you would in a joker
or use context.individual
that makes more sense actually
key = "iron",
set = "xiferp_Element",
cost = 3,
pos = { x = 3, y = 5 },
use = function(self, card, area)
G.GAME.xiferp_iron_mult = (G.GAME.xiferp_iron_mult or 0) + 5
end
end
SMODS.current_mod.calculate = function(self, context)
if context.individual and context.cardarea == G.play and context.other_card:get_id() == 7 and context.main_scoring then
local give_mult = G.GAME.xiferp_iron_mult or 0
G.GAME.xiferp_iron_mult = 0
return { mult = give_mult }
end
end
}```
like so?
you would remove context.main_scoring in that case and the part that does G.GAME.xiferp_iron_mult = 0 would need to be moved to context.after so it doesnt reset on the first card (unless thats what you want)
key = "iron",
set = "xiferp_Element",
cost = 3,
pos = { x = 3, y = 5 },
use = function(self, card, area)
G.GAME.xiferp_iron_mult = (G.GAME.xiferp_iron_mult or 0) + 4
end
end
SMODS.current_mod.calculate = function(self, context)
if context.individual and context.cardarea == G.play and context.other_card:get_id() == 7 then
local give_mult = G.GAME.xiferp_iron_mult or 0
return { mult = give_mult }
end
if context.after then
G.GAME.xiferp_iron_mult = 0
end
}```
like this or?
youre missing an end but yes
lil stuck on why it's only doing "omega defeated" despite being on the proper stake
Thank you, N. I would make a joker of you if I may
i think stake has to be lowercase, i corrected my other post
i would also evaluate it in debugplus beforehand to see what it returns
it was indeed the lowercase issue
trigger = 'after',
delay = 0.2,
func = function()
SMODS.destroy_cards(G.hand.pseudorandom)
return true
end
}))
delay(0.3)
end,```
Will this destroy a random card in hand?
no
what's missing?
G.hand.pseudorandom is not a thing
i would recommend looking at the vanilla remade wiki, there's a section for getting a random element from a table
you would use G.hand.cards in that case
-- set before...
local xiferp_kill_the_cards = pseudorandom("xiferp_youdienow", G.hand.cards)
-- and now...
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.2,
func = function()
SMODS.destroy_cards(xiferp_kill_the_cards)
return true
end
}))
like this?
Does anyone know how to pass a string as an argument out of loc_vars?
see above
no
what's wrong?
that's not how you use pseudorandom and not the function you should be using
Never mind, figured it out.
what's the function I should use?
pseudorandom_element
it is in the wiki I mentioned
okay, anything else?
Set up your lsp
I'll write about it after I got home from the dentist
Is that not just the rest of the card, or the atlas?
nevermind, figured it out. Setting it up now
Is there a way I'd be able to combine this code? I cant figure it out without my coder saying something is wrong
loc_vars = function(self, info_queue, card)
local probabilities_normal, odds = SMODS.get_probability_vars(card, 3, card.ability.odds, "Eastville")
return { loc_txt = {
name = "NOT Westville :D",
text = {
"Gains {X:mult,C:white}X#1#{} Mult for",
"{C:attention}each{} discarded card",
"{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)"
}
},
}
end,
--And--
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.xmult_gain, card.ability.xmult } }
end,
why do you have the loc_txt in your loc_vars
the loc_txt should be its own seprate thing
Its intentional, I'm wanting a chance to change its name
not how you do it
https://github.com/nh6574/VanillaRemade/wiki#how-do-i-change-the-name-or-description-of-a-card-dynamically
I'll take a look and see what I can find, thanks!
So my 2 code lines should be like this?
loc_vars = function(self, info_queue, card)
local probabilities_normal, odds = SMODS.get_probability_vars(card, 3, card.ability.odds, "Eastville")
return { descriptions = {
Joker = {
j_DRY_Eastville = {
name = "Eastville",
text = {
"Gains {X:mult,C:white}X#1#{} Mult for",
"{C:attention}each{} discarded card",
"{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)"
},
j_DRY_Eastville_alt = {
name = "Eastville 2",
text = {
"Gains {X:mult,C:white}X#1#{} Mult for",
"{C:attention}each{} discarded card",
"{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)"
}
}
}
}
} }
end,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.xmult_gain, card.ability.xmult } }
end,
no, i would reread what it says on the wiki
Confused then, cause I basically copied the code over and replaced as needed
In your localization file (like en-us.lua):
Oh...I just have 1 main code line
and the .json, of course
So...what would I do in that case? Cause I'm unsure how to add another file and have it connected
After running my base code through a debugger, I got this. Anything that got messed up?
Doing a simple Joker where it just multiplies chips, game crashed so I know I'm doing something wrong and its always been returning 1 every other time (having a calculate function still had it at 1)
config = {
xchips = 1.5,
},
loc_vars = function(self, info_queue, center)
return {vars = {center.ability.extra.xchips}}
end
you dont have extra in your config
ahh
okay, I have the extra but the multiplier is still not applying in rounds, would I need the calculate function?
it wont do anything without one
Okay, I dont know why I thought it would. Thanks
Okay, progress
loc_vars = function(self, info_queue, center)
return {vars = {center.ability.extra.xchips}}
end,
calculate = function(self, card, context)
if context.joker_main then
return {
xchips = card.ability.xchips
}
end
end
still doesn't work though
from vanilla remade, just use this as a base
SMODS.Joker {
key = "joker",
pos = { x = 0, y = 0 },
rarity = 1,
blueprint_compat = true,
cost = 2,
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 = card.ability.extra.mult
}
end
end
}```
how do you set the icon to the mod
make an atlas with the key modicon iirc
Would this be too complicated to make in terms of coding?
No, it would probably just be setting a flag and a hook.
Flag? Whats that?
(I just learned what hooks are yesterday lol)
It's a value that is used to signal that something has happened, so you would set the flag when it's sold and you would check for that in the hook.
Ohh ic ic
So if the flag was set, hook would be able to activate and add Art to the Pack
Right?
Yes.
how do you remove a joker from the main pool while also keeping it on other pools?
I know its
in_pool = function() return false end,
to remove it from ALL pools
but idk about JUST the main pool
actually just using that could work?
What do you mean the main pool?
appearing in the shop and via judgement creation
I want them to only be generated via a single consumable so I dont want them in the main joker pool
can you use add_card with a pool?
Anyone know how to set release mode in conf.lua through a mod? I wanna make a Balatro mod that just does that rather than having to unzip the .exe file to enable/disable debug mode
No, DebugPlus
What's debug plus?
I have discovered you cannot
I dont understand.
does anyone have any idea how to make it so it creates one of these four randomly
pools dont work with add_card
anyone got experience with malverk? had no issue replacing most textures in the game using it but for blind chips (which the repo lists as one of the things that malverk can replace) i get this crash on launch
Change key_append to key and put pseudorandom_element() around the table.
oh ive never used pseudorandom uhh
do I just make the array/table inside pseudorandom
yes okay
didnt work
im probably missing an argument in pseudorandom
No, it's key not key_ also you need to keep the keys in a table.
shit I just realized
I was wondering why keeping it in a table wasnt working either
the _ is barely visible lol
You need animated = true
ah
now i get this crash when selecting blinds in the collection
wait i need to specify frames dont i
there ya go
also need help replacing the title screen
wait i can literally just check the file size
am i duymb
px = 333, py = 216
hey guys i made the mistake of coding my mod with pokermon installed and now when i disable pokermon my custom planet cards (they work with pokermon on) crash the game with: functions/misc_functions.lua:2031: attempt to index field 'colours' (a nil value)
can you help me figure out what part of this code is a pokermon dependency?
So I'm running into the same issue as last night; the sticker doesn't seem to be adding itself to the card
key = "mantisgod",
pos = { x = 0, y = 0 },
rarity = 1,
blueprint_compat = true,
eternal_compat = true,
unlocked = true,
discovered = true,
effect = nil,
soul_pos = nil,
atlas = "mantisgod",
cost = 1,
config = { extra = { chips = 10, mult = 1 }, },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.chips, card.ability.extra.mult,} }
end,
set_ability = function(self, card)
card:add_sticker("inscrypt_trifuricated", true)
end,
calculate = function(self, card, context)
if context.joker_main then
return {
chips = card.ability.extra.chips,
mult = card.ability.extra.mult,
}
end
end
}```
```SMODS.Sticker{
key = "trifuricated",
badge_colour = G.C.RED,
pos = { x = 0, y = -5 },
config = { extra = { retriggers = 2 } },
calculate = function(self, card, context)
if context.repetition then
return {
repetitions = card.ability.seal.extra.triggers,
}
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { self.config.extra.retriggers } }
end
}```
And this is the code for the Joker and the Sticker
yo you're doing an inscryption mod
ye :3
i'd be glad to be part of the team if you need
i'm also making a mod and could use help if this makes an equal exchange
idk if I'll need extra help yet cuz I just started but I'll def keep it in mind if I end up needing it
yeah in the beginning it's easy
SURE NOT SEEMING LIKE IT lol, I've been stuck on how Stickers work for the past like 18 hours
i think there's a force sticker thing
force_stickers = {"prefix_trifurcated"}
try this
also i see there's an ERROR popup on the card, that may actually be the sticker and you mismatched the pos or loc_txt
so it doesn't have a sprite or text
have you tried it in game?
not yet i'm still struggling on actually apllying the sticker
this is the error i keep getting
i even set the pos to 0, 0
key = "mantisgod",
pos = { x = 0, y = 0 },
rarity = 1,
blueprint_compat = true,
eternal_compat = true,
unlocked = true,
discovered = true,
effect = nil,
soul_pos = nil,
atlas = "mantisgod",
cost = 1,
config = { extra = { chips = 10, mult = 1 }, },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.chips, card.ability.extra.mult } }
end,
set_ability = function(self, card)
card:force_sticker("inscrypt_trifuricated", true)
end,
calculate = function(self, card, context)
if context.joker_main then
return {
chips = card.ability.extra.chips,
mult = card.ability.extra.mult,
}
end
end
}```
i checked the collection, the game recignizes there's an added sticker but is not loading data
stickers = { "inscrypt_trifuricated" },
force_stickers = true
i think you need this
You store the old weight in a variable and you set it back to that.
does that go under the joker code or the sticker code
joker
yeah that's what i figured, that's why it's visualizing as error
you need to set the sprite and the loc_text to show properly
or add localization file
j_inscrypt_trifuricated = {
name = "Trifuricated",
text = {
"Retrigger this",
"card {c:attention}+#1#{}",
"additional times."
},```
but except graphics it should still work
key = "trifuricated",
path = "j_trifuricated.png",
px = 71,
py = 95
})```
:\
hold on i'll check to be sure
yeah remove the j_ stickers and seals don't need prefixes
also in your sticker code you have pos = { x = 0, y = -5 }, i think you should have pos = { x = 0, y = 0 }, if it's the fist one in the sheet, don't think negative coordinates have a meaning
yeah that's what i changed it to
would i add this as a function, an ability, or?
stickers = { "inscrypt_trifuricated" },
force_stickers = true
end,```
it's crashing because of an unexpected symbol near 'end' but i dont see what's incorrect about this function
that's the error when you have mismatched ends and brackets
always check if all ends are matched
i suggest using visual code studio with the lua extention cause it tells you beforehand when this type of errors would happen
that IS what i'm using, im just not observant
it's loding into the game now, but when the mantisgod attempts to call force_sticker, it's saying it's a nil value
but i should have it defined correctly
card:force_sticker("inscrypt_trifuricated", true)
end,```
how do you check the last played hand?
key = "mantisgod",
pos = { x = 0, y = 0 },
rarity = 1,
blueprint_compat = true,
eternal_compat = true,
unlocked = true,
discovered = true,
effect = nil,
soul_pos = nil,
atlas = "mantisgod",
cost = 1,
config = { extra = { chips = 10, mult = 1 }, },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.chips, card.ability.extra.mult } }
end,
apply = function(self)
stickers = { "inscrypt_trifuricated" },
force_stickers = true
end,
calculate = function(self, card, context)
if context.joker_main then
return {
chips = card.ability.extra.chips,
mult = card.ability.extra.mult,
}
end
end
}```
don't think you need this
also it's probably wrong
G.GAME.last_hand_played
could you help me with this? it gives crash functions/misc_functions.lua:2031: attempt to index field 'colours' (a nil value)
What does your localization look like?
im so confused 😭
You are using V but you're not returning any colours.
so what should i change it to?
do i need to put the hex color after V: in localization or do i need to return it inside the poker hand
loc_vars = function(self, info_queue, center)
return {
vars = {
G.GAME.hands["modprefix_key"].level,
localize("modprefix_key", "poker_hands"),
G.GAME.hands["modprefix_key"].l_mult,
G.GAME.hands["modprefix_key"].l_chips,
colours = {
(
G.GAME.hands["modprefix_key"].level == 1 and G.C.UI.TEXT_DARK
or G.C.HAND_LEVELS[math.min(7, G.GAME.hands["modprefix_key"].level)]
),
},
},
}
end
ok so the sticker is applying itself now, but the retriggers don't work, stating that "sticker" with in card.ability.sticker.extra.retriggers is nil
key = "trifuricated",
badge_colour = G.C.RED,
pos = { x = 0, y = 0 },
config = { extra = { retriggers = 2 } },
calculate = function(self, card, context)
if context.repetition then
return {
repetitions = card.ability.sticker.extra.retriggers,
}
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { self.config.extra.retriggers } }
end
}```
i tried taking sticker out but no dice
card.ability.modprefix_key.extra.retriggers also it should be if (context.repetition or context.retrigger_joker_check) and context.other_card == card
like this?
key = "trifuricated",
badge_colour = G.C.RED,
pos = { x = 6, y = 1 },
config = { extra = { retriggers = 2 } },
calculate = function(self, card, context)
if (context.repetition or context.retrigger_joker_check) and context.other_card == card then
return {
repetitions = card.ability.trifuricated.extra.retriggers,
}
end
end,
loc_vars = function(self, info_queue, card)
return { vars = { self.config.extra.retriggers } }
end
}```
Undiscovered boosters iirc
No, it should be card.ability.modprefix_key.extra.retriggers
oh thought i changed it back sorry
oh okay thanks
still no dice
Do you have joker retriggers enabled?
where would i find/put that?
SMODS.current_mod.optional_features = function()
return {
retrigger_joker = true,
}
end
THATS THE TICKET
thank you so much!
Is there a way to trigger a hand decrease for the round
I want to make a card that uses up a hand when you score it
ease_hands_played(-1)
ye.
Hey, is there a good way to apply a shader to all cards of a consumable type?
Yes, SMODS.DrawStep
is there an example for how to use it? docs seem to be a bit terse
apparently yes
is there a way to make Again! popup (during card retriggers from jokers) say something different for a specific joker?
actually no, i figured it out
but how can i make it display the number of repeats left?
there was a function for resetting the game right
i thought it was in the smods wiki but i can't find it
Is there a method to get the cards within a booster pack when it's opened from a joker context? open_booster seems to trigger too early for that
SMODS.restart_game
thanks lul
Put it in an event.
im a bit lost on how this works
Can you elaborate on that?
ty
is there a way for a joker that creates other cards to exclude a specific card from ever being created by it?
i have a joker that has a chance to create a random legendary joker when boss blind is defeated, but if it creates chicot, the ui bugs out and i also think the ante increases for some reason
i don't know how to fix when that happens so is there a way to just have it exclude chicot from the possible jokers it can create while still targetting legendary jokers in general?
Have you tried putting it in an event?
chicot gone rouge
pretty sure you can use
G.E_MANAGER:add_event(Event({
func = function()
SMODS.add_card {
set = 'Joker',
rarity = 'Legendary',
}
return true
end
}))
oh fuck sakes formatting is ass
No, it would be rarity = 'Legendary'
oh
Is there a way to restart scoring the whole hand?
G.FUNCS.evaluate_play()
I assume I can call that within an event?
ok that's not quite what I am looking for
Then what are you looking for?
...not quite.
how does one modify blind size (upon picking up a joker or smth similar for example) so that it's also reflected in the blind select screen?
for me that straight up locked up the game.
Look for mentions of SMODS.get_blind_amount through code?
SMODS.score_card(card, context) could be used, where card is the exact card you want to score and the context is the context that it'd score with.
this seems hardcoded/not exactly what i need
You can hook the function.
Do you want the cards in the played hand to score twice or do you want scoring to happen twice?
is that function used ingame for the blinds?
id just like to be able to do smth like this but "globally"
ah i see
figured it out
only thing is that the "again" text happens after rather than before
replace the 10's with 1's :clueless:
but like i fudges with the size and alisgments and they're not lining up
pad the rest with spaces?
I forget if this font has monospace figures or not
it's not
dam
Code?
you could proably rewrite the display to be a 5x5 grid of text entries with sufficient padding
my setup rn
or what the actual word for padding is
does this also handle calling additional contexts afterwards and actually calculating the effects? because ive been just manually using eval_card this whole time
if context.joker_main then
for _,v in ipairs(SMODS.get_card_areas("playing_cards")) do
SMODS.calculate_main_scoring({cardarea = v, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands }, v == G.play and scoring_hand)
delay(0.3)
end
return {
message = 'Again!',
colour = G.C.AMBER
}
end
it is tho, or at least i think that's what i've done
you can have a look and see
does the text need to be same size?
easiest fix would be max_h and max_w i think
or what the equivalent is i dont remember exact balatro ui names for the stuff
would that shrink the 10s or grow everything else
shrink the 10s
however let me check what its called again
another option is
adding a padding
i think?
padding: the extra space inside the edges of the current node.
Standard values are 0.05 or 0.1.
Directly using eval_card has been long not the preferred method for such... it doesn't even account for quantum enhancements.
the text nodes do not
if context.joker_main then
return {
func = function()
SMODS.calculate_effect({message = localize('k_again_ex')}, card)
for i ,v in ipairs(SMODS.get_card_areas("playing_cards")) do
SMODS.calculate_main_scoring({cardarea = v, full_hand = G.play.cards, scoring_hand = context.scoring_hand, scoring_name = context.scoring_name, poker_hands = context.poker_hands }, v == G.play and scoring_hand or nil)
delay(0.3)
end
end
}
end
ty, that sounds correct
oh i just used it because entropy used it. will SMODS.score_card also keep the cardarea put into context.cardarea for context.main_scoring when calculating the following context.individual? since ive been using it to calculate cards as if they were in different areas
The card itself doesn't have to be in the matching cardarea, even.
SMODS.score_card(G.deck.cards[1], context) will score the card in deck even if the context.cardarea is G.play, G.hand and such.
nope still not aligned
what did you say about maxh and maxw again? do i replace h and w with them or do they both have to be there
i think replace h and w
try to decrease the maxw and maxh?
yeah you might be in the value tweaking hell stage of the ui rn
how could i make context.destroying_card calculate for cards held in hand? im trying to make something that makes cards in hand act as if they were played which does currently work, but i havent gotten glass destruction and such to work
As in, have a card in hand by the source of a destruction effect?
wdym
Hook SMODS.calculate_destroying_cards
Do spectral packs have weird behaviour when you open too many of them? I opened a bunch and now every single one of them contains deja vu and incantation and I'm not sure if I got into a weird rng loop or if this is intended behaviour
do you have every other spectral card
no, I do not
I had something very very similiar:
If your Joker selects and triggers a card in hand, give that cards a tag
Then just use context.destroy_card (maybe with cardarea set to hand) and look for the tag
Also as example, my Joker that needed to destroy Triggered cards in hand:``` calculate = function(self, card, context)
if context.repetition then --> Some Context that Selects a Card
if next(SMODS.get_enhancements(context.other_card)) then
context.other_card.SEMBY_repeated = (context.other_card.SEMBY_repeated or 0) + 1
return { repetitions = card.ability.extra.repetitions }
end
end
if context.destroy_card and not context.blueprint then
if context.destroy_card.SEMBY_repeated then
local destroy = false
if next(SMODS.get_enhancements(context.destroy_card)) then
for i = 1, context.destroy_card.SEMBY_repeated do
if SMODS.pseudorandom_probability(card, 'SEMBY_benthic_bloom', 1, (G.P_CENTERS.m_glass.config.extra or 4)) then
destroy = true
break
end
end
end
context.destroy_card.SEMBY_repeated = nil
if destroy then
context.destroy_card.shattered = true
return { remove = true }
end
end
end
end,
mega spectral packs look like this
not sure if I messed something up or if this just. happens
no yea that's strange
somehow you got nearly every spectral card taken out of the pool
incantation is the default spectral card when there's nothing left in the pool, so that's why there are so many of them
and i guess deja vu is still in the pool
what's that joker do btw?
It is supposed to upgrade one card in a spectral pack, but I think it also inadvertently removes the original card from the pool for some reason
yea that's probably related to the issue
function upgrade_spectral(self, card, context)
local cards = {};
for k,v in pairs(G.pack_cards.cards) do
if v.ability.set == "Spectral" and spectral_upgrade[v.config.center.key] then
cards[#cards+1] = { idx=k, v=v, key=spectral_upgrade[v.config.center.key] };
end
end
local sel = pseudorandom_element(cards, pseudoseed('ustr_ext_upgrade'));
if not sel then return end
local card = create_card('ExtSpectral', G.pack_cards, nil, nil, nil, nil, sel.key, 'ustr-signal')
card:add_to_deck();
G.pack_cards.cards[sel.idx] = card;
card:set_card_area(G.pack_cards);
card:juice_up(0.6,0.4);
end
did I do this wrong
ok I assume the problem is that the card isn't properly destroyed and so the game assumes it is still being held by the player in some form
Why are you using set_card_area instead of emplace?
function upgrade_spectral(self, card, context)
local cards = {};
for _,v in pairs(G.pack_cards.cards) do
if v.ability.set == "Spectral" and spectral_upgrade[v.config.center.key] then
cards[#cards+1] = v
end
end
local sel = pseudorandom_element(cards, pseudoseed('ustr_ext_upgrade'));
sel:set_ability(spectral_upgrade[sel.config.center.key])
card:juice_up(0.6,0.4)
end
no idea, this was written a few months ago targeting a much earlier version of steamodded
this kind of changes the effect of the card being destroyed and replaced, but I'll take it. Thank you!
How do I properly destroy the card, anyway?
either card:remove() or card:start_dissolve()
tyvm
using set_ability is usually equivalent to destroying and replacing though from what i know
besides that editions and such get kept
...makes me think of moving the breaking trigger from the Joker itself to that function too.
finally i removed all the jank code i had from global mod calculate to patch jank behaviour 🎉
all my shit works normally without jank now woo
my ransom sticker can work normally now
imagine having jank in your code couldnt be me
unrelated dont look at how i shuffle a list
surely its with pseudoshuffle(list, seed) :clueless:
actually now im curious
so I changed 8 ball's odds from 1 in 4 to 1 in 2, it was working fine but randomly it just stopped working and I have no idea why
if you're overriding a vanilla joker's calculate i think you need to return in all cases or it will try to run the original
that's messed up. I like it
its beautiful
Scoring the held in hand glass cards like that is 2x likely to break... so a single Oops! would shatter them.
No, just do config = {extra = 2}
...I already have that.
...and a bunch of other mods do too.
..why debian?
you can combine them to make A Perfectly Normal Dice
after each hand it chooses a random sprite from 1 to 6
¯_(ツ)_/¯
and depending on which number it's showing, odds are skewed differently
"Stability" was the term I came up for the idea... so, reducing probabilities came out of that..?
...and, frankly, I have Oops! as vouchers...
1 is 50%
2 is 75%
3 is 90%
4 is 110%
5 is 150%
6 is 200%
nicel ooking vouchers
funny opportunity is to have the dice affects itself
maybe have it have a 1 in 2 chance to change its face after each hand
but of course its own effect is influencing how often it changes faces
egg egg egg egg d'egg l'egg egg
bread egg
Fair use - The original video was educational, but is now comedic (captions).
okay i need to stop putting random unrelated shit in this chat see yall soon
...this is based off of that.
I knew someone would've had that idea by now
And those two vouchers upgrade Seal^2.
creats two egg???
how would i make it so that showdown blinds can spawn at any time
or, just every 4 antes or something
what if it turns from creating one egg into creating handful of peas
i think that might be funy
yea ik i just wanted more people to know about it :)
i like that
handful of peas
https://youtu.be/Oz1LRbX_aYY occured at one point because of it.
A very specific configuration of Balatro mods ended up in this very funny interaction whilst I've been developing my own mod further. This likely would have gone on for a good while...
do you have an egg seals that create seals when scored
rh mentioned
No, but a good idea.
stepswitcher joker
toggles between buffing Aces and 3 and buffing 2s and 4s each hand
or maybe just odd and even if thats too weak
Fan Club Monkey joker that triggers if hand contains three of a kind
Folks, simple question: this custom seal makes it so that the card the card affected by it creates 2 spectral cards when destroyed. I figured out how to make it generate 1 spectral card, how can I make it gen 2 (without overflowing consumbale slots)?
copy from vanillaremade emperor if you havent looked at that yet
also context.destroy_card is whats used to check a card for destruction, not for when a card is destroyed
should I use something else?
It worked fine so far
you should be checking if context.removed contains the card in context.remove_playing_cards
and you probably need a hook to Card:can_calculate, since Card.getting_sliced is set on destroying playing cards in a lot of cases

lmao
you are killing my hopes of finishing it with every new sentence
😭
ill try to figure it out
fr
I forgot I have this brilliant mind working with me
chat what's context.main_eval for? it doesn't say it on the wiki and the code i found for end-of-round stuff has it
context.main_eval is true when no secondary card is being evaluated, im pretty sure its only used to check for the main joker evaluation in context.end_of_round rather than effects on playing cards
would you be so kind as to dumb it down a bit for me to understand? i mean no offense when saying this 😭
i think it's basically the main phase of score calc
like when all the number going up actually happen
you know context.individual and context.repetition?
i do know reptition! kinda. I believe it's the condition when the game looks for repetitions when scoring something
yeah so basically both of those contexts run once per card (in play and held in hand)
the reason main_eval exists for end_of_round is that it also runs alongside those contexts so it's basically
end_of_round + main_eval (once)
end_of_round + individual (once per card in hand)
end_of_round + repetition (once per card in hand)
i have a blueprint-like joker that copies another random compatible joker if a hand is played, and keeps copying said joker until the hand is played again (it then switches the joker it's copying)
this works perfectly for the most part, however at the moment i store the copied joker in the card's config as an object which definitely isn't the best way to go about it, and leads to the joker it copies not being saved on run save/load. how should i store the joker object it's copying to go around this?
Store the cards sort_id instead.
then just iterate through all jokers and copy the one that matches said sort_id?
Yes.
perfect, thanks
How can I make a blind that add 2 ante instead of 1 when it is defeated ?
defeat = function() ease_ante(1) end
thanks you!
does anyone know how the hell to set up jokerdisplay
nothings showing up ingame
ok well setting text to a static value doesnt show anything either
is it not "j_hypr_test" like the id in the localization file?
It is.
...you also are referencing card.ability.Xmult and not card.ability.extra.mult
i switched it to just this and nothings showing still
https://github.com/TheOneGoofAli/TOGAPackBalatro/blob/main/items/crossmod/jokerdisplay.lua What about trying like this?
is there a way to access the shop's first voucher card while in a blind?
G.shop_vouchers.cards only works when youre in the shop and theres a vouncher
When exiting shop, "store" the key of the voucher somewhere.
i'd look into how cryptid does ://LOG
I have this card that changes name at a certain time on the game, I wanna make it a chance thing instead. Is there a way I can change the if for that to work? (I'd want it to be a 1/615 chance)
config = {
xmult_gain = 0.01,
xmult = 1,
odds = 615,
},
loc_vars = function(self, info_queue, card)
if math.fmod(os.time(), 615) == 0 then
return {
key = "j_DRY_Westville",
vars = { card.ability.xmult_gain, card.ability.xmult }
}
end
return { vars = { card.ability.xmult_gain, card.ability.xmult } }
end,
G.GAME.current_round.voucher[1]
if math.random() < 1/615 then ...
usually would use pseudorandom for things that affect gameplay but shouldnt matter here
since I didnt need to use the odds variable would I just delete that?
you could also replace 615 with card.ability.odds if you want
its still just changing 1 number to modify the chance though
fair enough
Is there a way to make it so that things that would usually show Badges, don't?
I want the Sigils (stickers) to not generate a badge when applied to a card
this is for the key, right? i meant for it to be the card object
hide_badge = true
No, because it doesn't exist anymore.
yeh
where the hell is togabalatro defined
how can i check if the player has beaten the small/big blind of the current ante?
G.GAME.round_resets.blind_states.Small == 'Defeated' and G.GAME.round_resets.blind_states.Big == 'Defeated'
i see, thank you
SMODS.create_card({key = G.GAME.current_round.voucher[1].key})
found it
You don't need to do it exactly like that.
aand nothing
Just do
local jdef = JokerDisplay.Definitions
jdef['j_modprefix_key'] = {
...
}
oh it can be local?
Ye.
So that you don't type JokerDisplay.Definitions['j_modprefix_key'] each time.
I just decided to attach it to my global.
local jdef = JokerDisplay.Definitions
jdef["j_hypr_test"] = { -- test
text = {
text = "Test",
colour = G.C.attention
}
}
still giving this result
theres a way to let a consumable be used, only when selected a specific joker rarity?
check G.jokers.highlighted[1] and G.jokers.highlighted[1].config.center.rarity == <key>
personally i just add the joker_display_def inside the SMODS.joker
wow my discord did not scroll down
No, G.jokers.highlighted[1] and G.jokers.highlighted[1]:is_rarity('modprefix_key')
hey i'm having trouble implementing a name change to a custom pokerhand much like royal flush does to straight flush, i copied the code from vanilla remade and updated the localization but it makes my game crash
Code?
local briscolaflush = true
for j = 1, #scoring_hand do
local rank = SMODS.Ranks[scoring_hand[j].base.value]
briscolaflush = briscolaflush and (rank.key == 'Ace' or rank.key == '3') end
if briscolaflush then
return 'napoli_Briscola Flush House Trentuno'
end
end
}```
Log?
Anyone know why the badge is saying "error"? I can't find the code to give the badge a different name
there's a second place you have to localize stickers, gimme a sec
hi jokerdisplay guy here what's the issue?
in your localization file, add modprefix_stickerkey = "Trifurcated" to the misc -> labels table
i'll try, and see if it works. Either way, thanks for the advice
wasn't there an example blueprint reimplementation somewhere
the issue is that nothings happening