#💻・modding-dev
1 messages · Page 87 of 1
could maybe try playing with negative padding
is there a context like end_of_round that doesn't trigger like 11 times?
(this is context.end_of_round)
Gros Michel?
actually, let me see, u might be a genius
suprisingly it still is just context.end_of_round
if context.end_of_round and not context.repetition and not context.individual then
ya but it still doesn't fix it
oh i tought u were giving me gros michel's context lemme try this
:o it works!
thanks! <3
Hi sorry to bother, i have a question i don’t where how to put it but are mods compatible with each other ?
most of them are
thanks i finally try the mods, and tbh im interested into creating one, y’all got me haha
It is on my list
(i just don't know how to begin, i suppose think of what each joker is talking about)
personally i think only certain jokers should talk
the non special ones are BORING......
mostly, jimbo (aka normal joker), the legendaries, some rares like: burnt joker: "it HURTS", or baseball: when beating blind: "home run!", the idol just names what it's changed to
just little funny things
oops all 6 could just say a random number between 1-6
just those small things that make them stand out
if you win a probability because of oa6 (you wouldn't have won it without) it yells "6!"
that be hard
i thin
there should be a way to have support for other mods so other mods can take
talk
if you lose with hack it says tough crowd
sounds pretty cool, and mod compat would be preferred yeah
could just be a community mod
like cryptid where people can suggest or code things
and just let that mod handle all the mod compat? it's possible
hell yes, public chatting as jokers lol
man who do i want to be? 🤔
didn't work well
i'm just gonna manually add the text to the image now
don't wanna deal with ui anymore
STEAMODDED 1.0.0
A tutorial on how to make a modded Joker.
https://github.com/art-muncher/Example-Mod -- EXAMPLE MOD
https://github.com/Steamopollys/Steamodded -- STEAMODDED
https://github.com/art-muncher -- My github!
...
whats wrong with my code (expected behavious: once for each J_fnj_gerald you own, x2 mult when playing a king)
calculate = function(self, card, context)
if context.individual then
local geralds = SMODS.find_card("j_fnj_gerald")
local geraldcount = #geralds
if context.other_card:get_id() == 13 then
if geraldcount then
Xmult_mod = card.ability.extra.Xmult
for i = 1, geraldcount do
message = '._.'
Xmult_mod = Xmult_mod + card.ability.extra.Xmult
end
end
end
end
end,
}
bruh
holup
lol i cant use codeblocks anymore ;-;
i like ur smiley + pareidolia combo but wtf is this supposed to be 😭 i don't understant
calculate = function(self, card, context)
if context.individual then
local geralds = SMODS.find_card("j_fnj_gerald")
local geraldcount = #geralds
if context.other_card:get_id() == 13 then
if geraldcount then
Xmult_mod = card.ability.extra.Xmult
for i = 1, geraldcount do
message = '._.'
Xmult_mod = Xmult_mod + card.ability.extra.Xmult
end
end
end
end
end,
}
make sure you escape the underscores _ in your message
the underscore in j_fnj_gerald broke it and idk why
fr
calculate = function(self, card, context)
if context.individual then
local geralds = SMODS.find_card("j_fnj_gerald")
local geraldcount = #geralds
if context.other_card:get_id() == 13 then
if geraldcount then
Xmult_mod = card.ability.extra.Xmult
for i = 1, geraldcount do
message = '._.'
Xmult_mod = Xmult_mod + card.ability.extra.Xmult
end
end
end
end
end,
}
for some stupid reason backticks don't have higher priority
what the fuck
Maybe try using draw_card?
that is the result of draw card
Ah
card_eval_status_text(v,"extra",nil,nil,nil,{message = "Cleaned!", colour = G.C.BLUE})
v:set_ability(G.P_CENTERS.c_base, nil, true)
v:set_edition(nil,true,false)
v:set_seal(nil,false,true)
v:juice_up()
return true end }))
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.5,func = function()
if ClearCardArea.config.type == 'deck' then
draw_card(G.play,G.hand, 1, 'up', true, v, nil, true)
G.deck:emplace(v, nil, false)
else
draw_card(G.play,G.hand, 1, 'up', true, v, nil, true)
end
return true end }))```
why is this not working
Does SMODS.find_card find more than one card, or just the first instance of that card? The name seems to imply the latter
trying to think of the easiest card concept from the v/s card pool
maybe look at what the game does when right clicking?
where would that be
why is there gaps in my cards
why is it sayin 12/8
there is 10 cards
what
when i played some cards some stayed in my hand flipped? i also cant select them????
what is happening???
i quantum entangled my cards?????
i needf help bro 😭
my balatro is cursed
Cleaned!
yea
cuz its supposed to "clean" the cards
it picks 2 modified cards from the deck, and cleans them and its supposed to put them back into the deck
but that is not working
deck or hand
deck or hand
rn its only taking from deck
draw_card(G.play,G.hand, 1, 'up', true, v, nil, true)
G.hand:add_to_highlighted(v,true)
G.FUNCS.discard_cards_from_highlighted(nil, true)```
v is the card
G.hand.highlighted = {} 
area:unhighlight_all() exists
where were you here!!!
did not work
there are phantom cards
im scared
v:set_ability(G.P_CENTERS.c_base, nil, true)
v:set_edition(nil,true,false)
v:set_seal(nil,false,true)
v:juice_up()``` is something wrong here?
I'll ask again. Are you trying to investigate game code at all?
You need to select/deselect card. If you don't know how to do it, first what should come to your mind is "how other joker/tarot/blind do this stuff?"
You searching for it, and investigate all methods they used
Or, find a class defines a card area, CardArea, and just take a look what methods this class have. What they do, what arguments they have
the crazy part is
i have the same exact code somewhere else, and it works
but when i put the code in the other place it doent worek
i did the whole draw cards after it didnt work
You're do something with card without respecting events order, as a result desync happened and game think you dding cards twice
When you use familiar, game add this steps in event queue
- Move card from G.consumeables to G.play
- Remove one card from hand
- Add 2 cards to hand
- Dissolve
All actions performed one after another
im hooking use consumable though
function Card:use_consumeable(args)
stop_use()
...
else
UseRef(self,args)
end
end```
the else doesnt happen when i use familiar in this case
(intended)
Most likely you do smth like "if card is Familiar, execute consumeable effect and after that clear created cards"
If you just copy-paste familiar code then 
Why are you breaking vanilla stuff?
wdym
if (G.GAME.TGTMCurseChance > 0) and (self.ability.set == 'Tarot') and (pseudorandom(pseudoseed("Curse")) < G.GAME.TGTMCurseChance) then the consumable is used normally, but when the spooky curse activates, it doesnt
In this case fine
if v.edition or v.config.center ~= G.P_CENTERS.c_base or v.seal then
print(v.edition)
print(v.config.center ~= G.P_CENTERS.c_base)
print(v.seal)
if cleared <= maxClear then
local ClearCardArea = v.area
if ClearCardArea.config.type == 'deck' then
draw_card(G.deck,G.hand, 1, 'up',true,v, nil, true)
end
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.3,func = function()
G.play:emplace(v)
print(v.facing)
print(ClearCardArea.config.type)
return true end }))
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.5,func = function()
card_eval_status_text(v,"extra",nil,nil,nil,{message = "Cleaned!", colour = G.C.BLUE})
v:set_ability(G.P_CENTERS.c_base, nil, true)
v:set_edition(nil,true,false)
v:set_seal(nil,false,true)
v:juice_up()
return true end }))
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.5,func = function()
if ClearCardArea.config.type == 'deck' then
--draw_card(G.play,G.hand, 1, 'up', true, v, nil, true)
--G.hand:add_to_highlighted(v,true)
G.deck:emplace(v,nil,false)
else
draw_card(G.play,G.hand, 1, 'up', true, v, nil, true)
end
return true end }))
end
cleared = cleared+1
G.FUNCS.discard_cards_from_highlighted(nil, true)
end
end```
this is the spectral code
also a G.hand:unhighlight_all() at the beggining
is it possible to half the amount of chips the hand currently has with just steammodded, or will that require talisman to piggyback off of Xchips?
i was thinking of grabbing the amount of chips currently played, halving it with chips_amount / chips, but i wasnt sure how to make that the new number
maybe doing something like:
chips_amount / chips = new_chips_amount,
return{
chips_amount = new_chips_amount
}```
but that might just add half to the value? idk
other than jokers, what's the most common thing people ask for help in creating for modding?
might make a tutorial out of it
like blinds? consumeables?
im making some and have no clue
consumables it is!
What about the best ways to test efficiently? Beyond "Ehm install DebugPlus"?
erm
does this joker look good? in tern of code and if the random is set up properly?
gives you essenitally anything and everything you need
what is this supposed to do
when lucky card scores, 1 in 5 chance of 2x xmult, 1 in 10 for 10$
Test-driven development really seems to be a design-centerpiece of LUA, hm?
just wanted to know if i made the randomness correctly, and if oops all 6's can manipulate it
I think you need a '' .. G.GAME... behind the G.GAME.probabilities.normal
or "1"?
Nah not for the 1
how do you mean?
''..G.GAME.probabilities.normal or 1
y?
Lua moment
and, what is it supposed to do?
I really hate how loose Lua is as a programming language lol
Ofc, this comes from me only using C++ mainly
It's so wildly more forgiving
Using ' ' .. let's you turn an int variable into a string
Oh wait the 1 needs it too
So it goes ''..(G.GAME and G.GAME.probabilities.normal or 1)
It's written so in the og code
i dont know how to rmove these phantom cards
it changed, nothing? ._.
when i emplace to G.play, when i draw_card from G.play to G.hand, it creates ghost cards
joker works fine, just blueprint/brainstorm is weirdly happening more than once
Once you return in the calculate, nothing else will run after that statement. So if a card is a lucky card and it fulfills the first if check, the other if statement won't execute. I don't know if that was your intention
1 in 3 for 2 xmult, 1 in 10 for 10$
Thats litterally it
Do you intend for those to both happen at the same time sometimes?
simply write an entire mod using ffi
Ye, both happen when lucky card scores
You know, you're on to something lol
The way you have it up there, it will first check the x2 mult, and if that succeeds, it will give the xmult and never even check for the money. If it fails, that's when it'll check the money. Both things can't happen at the same time with how it's written
Ooh
Okey
I'll see if i can merge them together tmr
i'm trying to make a joker that adds +4 chips (a la wee joker) per unscoring card played and it's not working. i'm not totally sure why. any help?
SMODS.Joker {
name = 'Soaker Joker',
key = 'j_spl',
atlas = 'splashjokeratl',
rarity = 3,
cost = 8,
unlocked = true,
discovered = true,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
config = {extra = {chips = 0, chip_gain = 4}},
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.chips, card.ability.extra.chip_gain } }
end,
loc_txt = {
name = 'Soaker Joker',
text = {
"{C:chips}+#2#{} Chips for each played",
"card that is unscoring",
"{C:inactive}(Currently {}{C:chips}+#1#{}{C:inactive} Chips){}"
}
},
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
for i = 1, #context.full_hand do
local scoredandPlayed = false
for i = 1, #context.scoring_hand do
if context.full_hand[i]:get_id() == context.scoring_hand[i]:get_id() then
scoredandPlayed = true
end
if not scoredandPlayed then
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain
context.full_hand[i]:juice_up()
return {
message = 'Upgraded!',
colour = G.C.CHIPS,
card = card
}
end
end
end
if context.joker_main then
return {
chip_mod = card.ability.extra.chips,
colour = G.C.CHIPS,
message = localize { type = 'variable', key = 'a_chips', vars = { card.ability.extra.chips } }
}
end
end
end
}
You have two i variables. The inner one needs to be named j, or something unique from i
ah, okay
neither message plays though, weirdly? the ticker goes up so i know it's iterating the variable but it's not adding the actual chips to the total nor is it giving the message when it gets the chips from unscored cards
Similar issue to above, it looks like you're trying to return multiple times from the same function call. You can only return once
...huh.
i just don't know where the thing that gets the chips from unscoring cards would go if not in calculate
Once it finds the first not scoredAndPlayed it returns the upgraded, and the calculate function finishes for that instance
Let me try to word this right
A solution, I mean
Instead of returning a message, you can call the eval_card_status_text() function, and do the message that way. I think I did that with one of my jokers and it worked out good
Let me find an example
So for you, you would replace your return under context.individual with something like this:
card_eval_status_text(card, 'extra', nil, nil, nil, { message = 'Upgraded!', colour = G.C.CHIPS})
Try that
okay! one moment
btw, just so i'm clear, when I say return multiple times from the same function call, I don't mean that you can't have the return statement under context.individual and the return statement under context.joker_main. I mean that you expected the for loop to return a message for each iteration of the for loop, when in actuality the for loop will actually stop after the first return statement
Idk how to fix
i think that text is working now but... it's a little confused now
i'm not even sure how it did that
-the scoring is... not acting how it should
-it's not actually giving the chips despite it being clearly stated
i have actually no idea what to do here
my life would be a lot easier if i could find an "is card scoring" function
I think context.scoring_hand only includes cards that are scored, so the not scored card wouldn't be in that
I'll have to grab this code and take a look at it on my PC later when I have access to it
It's hard to debug on a phone lol
yeah, currently i'm iterating to see if i card in context.full_hand is equal to a card in context.scoring hand
this being the current code:
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
for i = 1, #context.full_hand do
local scoredandPlayed = false
for j = 1, #context.scoring_hand do
if context.full_hand[i] == context.scoring_hand[j] then
scoredandPlayed = true
end
if not scoredandPlayed then
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain
context.full_hand[i]:juice_up()
card_eval_status_text(card, 'extra', nil, nil, nil, { message = 'Upgraded!', colour = G.C.CHIPS})
end
end
end
if context.joker_main then
return {
chip_mod = card.ability.extra.chips,
colour = G.C.CHIPS,
message = localize { type = 'variable', key = 'a_chips', vars = { card.ability.extra.chips } }
}
end
end
end
Try this real quick:
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play then
for i = 1, #context.full_hand do
for j = 1, #context.scoring_hand do
if not context.full_hand[i] == context.scoring_hand[j] then
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain
context.full_hand[i]:juice_up()
card_eval_status_text(card, 'extra', nil, nil, nil, { message = 'Upgraded!', colour = G.C.CHIPS})
end
end
end
end
if context.joker_main then
return {
chip_mod = card.ability.extra.chips,
colour = G.C.CHIPS,
message = localize { type = 'variable', key = 'a_chips', vars = { card.ability.extra.chips } }
}
end
end
end
I haven't tested it, so be warned
can you send me the whole mod directory real quick so I can run it?
will try it, there's the current one ^
Does anyone know where you set this text for booster packs?
group_key I believe?
I'll just link you the line https://github.com/Steamopollys/Steamodded/blob/main/core/game_object.lua#L1443
(you might need a localization file for it?)
You need either a localization file with the entry or define the SMODS function for it like here:
function SMODS.current_mod.process_loc_text() G.localization.misc.dictionary['k_poke_pocket_pack'] = "Pocket Pack" end
Replace with your specific names of course
Also mtg mod when 👀
right now!!!
if i can figure out how to get these packs to work that is
I don't know how to allow the player to take the consumable cards out of the pack without having to use them
cryptid's code cards have a "pull" option that moves it to the consumable area
Yeah, I've been trying to use that code but it just throws an error
Also, how does code outside of your main file work with steamodded? I can't figure out how to put things in other files
It just doesn't run
You need to import it
How do I do that?
SMODS.load_file("path/to/file.lua")() iirc
yes
This is my error message when I try to implement the cryptid code
im still trying to fix this drawing thing
I've almost got it figured out I think
my cards have the deck back on both sides of the card
how do i put the normal face on them
i think its something to do with G.deck card area
you have to use pairs() or ipairs() to iterate over stuff in lua
when i emplace something from G.hand to G.play it leaves a ghost card
i'm so stupid 😭 thanks
do i have to table.remove some stuff?
when scoring
what do i have to do
Hi
There is no a script or something for install lovely and steamodded with 1 click like a .bat with git or something
That will help a lot of people
I'm trying to implement a seal that has an event when the played card scores, what context should I be checking for?
👀
thats good? i dont have any frame of refrence is this a major acomplishment/
just a cool feature
awesome
Nice
not by any means done unfortunately
If you’re playing a hand that would normally cause the game to run out of memory, does this fix that?
only came up with it just a minute ago
ya

why doesn't the label show up?
does this look fixed compared to before?
It looks like it'll work to me, just make sure you aren't adding money twice. I'm not sure if ease_dollars and the dollars in the return statement will add it twice
oh okey, i will
ok smth ain't right.. when card is first scored it gives +0 money? ._. and from what i can see the xmult goes like: original 1x, blueprint1 1x, blueprint2 2x, blueprint3 3x
and all i did was remove the "dollars = card.ability.extra.money"
Well, one thing you could try is something like this:
local give_money = pseudorandom('sandstone') < G.GAME.probabilities.normal / card.ability.extra.odds_money
local give_Xmult = pseudorandom('sandstone') < G.GAME.probabilities.normal / card.ability.extra.odds_Xmult
if give_money and not give_Xmult then
return {
dollars = card.ability.extra.money,
card = card
}
end
if not give_money and give_Xmult then
return {
x_mult = card.ability.extra.Xmult,
card = card
}
end
if give_money and give_Xmult then
return {
dollars = card.ability.extra.money,
x_mult = card.ability.extra.Xmult,
card = card
}
end
It's kind of clunky, but it should get the job done
Although I haven't tested it
@tepid sky
wow, thanks!
I feel like there's a better way to do that to cover all the cases
Yeah, there probably is, but I was just trying to whip up something real quick that would work
And I just found a better way:
local give_money = pseudorandom('sandstone') < G.GAME.probabilities.normal / card.ability.extra.odds_money
local give_Xmult = pseudorandom('sandstone') < G.GAME.probabilities.normal / card.ability.extra.odds_Xmult
local result = { card = card }
if give_money then
result.dollars = card.ability.extra.money
end
if give_Xmult then
result.x_mult = card.ability.extra.Xmult
end
return result
That should work
@tepid sky
what do you mean?
lemme try smth rq
that = this
Oh, I meant to put that stuff inside the context.individual etc... if statement
and inside the lucky card check
I just didn't feel like writing all that stuff out lol
Just take the code I provided you and place it inside the Lucky Card check, removing all the code you had in there
so your heirarchy will be
context.individual
lucky card?
my code
should be good
I believe you need a different seed for each one, so something like 'sandstone_mult' and 'sandstone_money' for the pseudorandom parameters. At least that's how lucky cards do it in the base game
next question. how do i make astronomer? (as a smods joker)
cuz i cannot get it working
Need to hook into set cost
If that’s how set cost works internally, it looks reasonable
That’ll reset the values for when you pick it up
I got a simple question
So I have in the config of a card a thing called "planet_chips" and "planet_mult". Essentially, it's a way to make it easier to do mult and chips on a planet for an existing handtype
Only problem atm is trying to get the loc_txt to load the planet_chips/mult in the card
you need to add self.config.extra.planet_mult as the 3rd index and self.config.extra.planet_chips as the 4th index when returning the table under loc_vars function
Ah that's where my problem was
I was putting ability not config
thanks
Lemme see if i put it in right
Ayyyy
Thanks again!
playing card not giving x mult?
also still need help with this
shouldnt it be things like x_mult = card.config.x_mult? and not self?
i can FINALLY work on the actual runes
config.x_mult returns the xmult mod value
yes, but dont all self’s need to be cards in SMODS? thats what i’ve seen and been doing, and it works fine for me
uh oh, somethings wrong
local card = create_card("Runes", G.consumeables, nil, nil, nil, nil, nil, "TGTM_runes") this is how to spawn a random rune right? does this remove the rune from the pool?
local card = create_card("Runes", G.consumeables, nil, nil, nil, nil, nil, "TGTM_runes")
print(card.ability.name)
card:add_to_deck()
G.consumeables:emplace(card)
end```This should spawn 2 runes, this is almost directly copied from the emperor
more like automoton from cryptid
working on a Cement Seal that makes the sealed card act like a stone card
for balance purposes, should this include the +50 chips, or just leave it at always scores+resistant to debuffing?
what sprite creating software should i use?
would be using it but its 20 bucks lol
... i suspect the answer to this is going to make me feel very silly, but why is my seal's name and description showing blank
SMODS.Seal {
object_type = "Seal",
name = "cement_seal",
key = "cement",
badge_colour = HEX("545454"), --a cement-y grey, hopefully
config = {extra = {chips = 50}},
loc_txt = {
label = 'Cement Seal',
description = {
name = 'Cement Seal',
text = {
'Acts like a {C:attention}Stone Card',
'({C:chips}+#1# Chips{}, scores even if',
'not part of played hand,',
'resistant to debuffs)',
}
},
},
loc_vars = function(self, info_queue)
return { vars = {self.config.extra.chips, } }
end,
atlas = "cementseal",
pos = {x = 0, y = 0},
calculate = function(self, card, context)
if not context.repetition_only and context.cardarea == G.play then
return {
chips = self.config.chips
}
end
end
}```
pretty sure that's not how loc_txt is structured
its
loc_txt = {
name = "string",
label = "string",
text = {
"string1",
"string2"
}
}
i pulled that format straight out of the seal example mod included with steamodded
... but i haven't checked whether it works right in that mod, so one moment
yep, it's broken in the example mod too
lol
guess someone should update that
if i had a guess the example mods would be from 0.9.8
that was my guess too, though it at least had its requirement updated to the current steamodded and apparently literally nothing else
what's this?
a mod i'm working on
haven't officially published it yet but if you wanna check it out early https://github.com/wingedcatgirl/MintysSillyMod
stickers not showing?
I'm trying to add a new joker that has the same static ability as smeared joker, but this doesn't seem to be doing anything?
try changing the position to at and payload to next(find_joker('Smeared Joker')) or next(find_joker('hel-smearflowerpot'))
patches.pattern has to match a complete line iirc
patches.regex can be used for single words etc
next(find_joker('Smeared Joker's))next(find_joker('Smeared Joker)) is not syntactically valid
ohhg
yeah no what lars said
mb i just woke up
thank you so much!
i got the cement seal to give points, but i'm stuck on making the card always score or be immune to debuffing
okay amend that i think i just worked out debuff immunity
yep confirmed confirmed, debuff immunity in place
but why won't they splash...
Trying to program in the effect of flower pot, but only caring about two suits...
if context.joker_main then
local suits = {
['Hearts'] = 0,
['Spades'] = 0
}
for i = 1, #context.scoring_hand do
if context.scoring_hand[i].ability.name ~= 'Wild Card' then
if context.scoring_hand[i]:is_suit('Hearts', true) and suits["Hearts"] == 0 then suits["Hearts"] = suits["Hearts"] + 1
elseif context.scoring_hand[i]:is_suit('Spades', true) and suits["Spades"] == 0 then suits["Spades"] = suits["Spades"] + 1 end
end
end
for i = 1, #context.scoring_hand do
if context.scoring_hand[i].ability.name == 'Wild Card' then
if context.scoring_hand[i]:is_suit('Hearts') and suits["Hearts"] == 0 then suits["Hearts"] = suits["Hearts"] + 1
elseif context.scoring_hand[i]:is_suit('Spades') and suits["Spades"] == 0 then suits["Spades"] = suits["Spades"] + 1 end
end
end
if suits["Hearts"] >= card.ability.extra.num_red and
suits["Spades"] >= card.ability.extra.num_black then
return {
message = localize{type='variable',key='a_xmult',vars={card.ability.extra.Xmult}},
Xmult_mod = card.ability.extra.Xmult
}
end
end
end```
It just isn't triggering
[[patches]]
[patches.pattern]
target = "state_events.lua"
position = "at"
pattern = " if G.play.cards[i].ability.effect == 'Stone Card' then"
payload = " if G.play.cards[i].ability.effect == 'Stone Card' or G.play.cards[i].seal == 'minty_cement' then"
match_indent = true```
i cannot for the life of me work out what's wrong with this lovely.toml patch
it does seem to be patching, the log doesn't have a WARN that it found no matches
it just doesn't make the card always score
this could probably be done in the seal definition somehow rather than lovely.toml but idk how lel
functions/state_events.lua
that was the problem??
the log didn't say anything about that!
bizarre
but it does work now
yeah if you're trying to patch something in a folder you have to put it in the target string
tried to remake obelisk but got a crash?
i know what line is wrong but idk what is wrong about it
which one is line 1023
the one which is highlighted
aka the one with v.played >= ....
it seems that (G.GAME.hands[context.scoring_name].played or 0) is the problem
I'm assuming context.scoring_name is not always defined
but you should probably just be doing a lot of prints
prints?
oh print like that
print my beloved
DebugPlus dev also has it's own print wrapper if you're silly like that
I am a print believer
i enjoy print
I use print for dev and other stuff for stuff that may be shown to a user
mostly handleLog becuase I'm in DebugPlus internal land
why does talisman just straight up inject itself straight into main.lua btw
straightly...
cause it needs to be run
print enjoyer 
it can't just load the file and execute it??
lovely module/appending?
loadfile
dofile
read & loadstring
the one love2d loadfile function
ignore that dofile is just loadfile 🔥
and how are you going to run those without injecting code?
oh no
talisman injects the entire talisman.lua file into main.lua
it's more convient probably
it's quite inconvenient when there's an error and you have to trace it back by looking in the main.lua lovely dump for the appropriate like and then go find the corresponding line in talisman itself
is talisman an SMODS mod
if not that explains it
okay then yeah it'd have no way to find itself
it just has a little SMODS compat
well it does load some modules dynamically
ehh you still can find yourself with just the vanilla functions.
I do it for Flower Pot
I mean it's just more annoying
can you do it cleanly though
someone bribe meth to add paths to lovely
SMODS does it, but it does require pretty much scanning the entire mod dir
very inconvenient
You can be a bit lazy and just make an educated guess on the file name
like if you just see if the folder name starts with talisman case insesntive
it will match most cases
but also if you had two mods starting with talisman then it kinda screws up
Unfortualtly, it's not simple to modify lovely to save metadata for patches
it requuires pretty much a rewrite of how lovely handles patches
https://discord.com/channels/1116389027176787968/1307525934366326855
can someone help me test this in long runs?
Is there any way to change the current round's chips without scoring?
Yes
But if you want it to also be able to handle you winning a bit more code is nessicary
Do you know of any mods that have done this that I could study?
awesome thanks
having issues making this return the value of the mult, instead of the value of total hands played during the run
changing out the function in the return is something i am looking to do, but i dont know what to replace it with
can someone dm me a video on how to mod the game
im coming up with nothing
can someone please help me
return where exactly
nevermind, i figured it out
what did you do
new question
should this be the value that is actually played, or should it be 160(the value after playing a hand)
my movator the brokies
How do you specify a custom joker order in the collection for modded jokers?
how do i make blueprint interactivity with modded jokers?
I thought that might be how it works, but it isn't how it's doing it in the mod i'm working on. I saw that Pokermon has its order in Pokedex order, but I'm failing to find where that's defined
You can check for context.blueprint in calculate iirc
Looks to me like thye are just defined in pokedex order
like this one for example
Weird. Here I have calling_card defined as the first joker in the CONFIG, but when the function that registers them runs, the first joker in-game is quick_fix
I think pairs doesn't has a defined order
I should use an i-based for loop instead then probably?
yeah porbably
?
what about it?
does it say incompatible?
if so you probably need to add blueprint_compat = true, to your joker definiton
gotcha
I forget if it's true by default or not
it WORKS but it doesnt DISPLAY
does it display on your card twice?
I think theres a bug where it sometimes behaves like a retrigget instead of a blueprint
where do i put the compat?
something in steamodded
what do you mean?
then you don't have the blueprint_compat = true, on your joker
how do i make it so that you can spawn more than 1 conumable of a type?
after i spawn 1 of each , it jimbos me :(
how are you spawning them?
print(card.ability.name)
card:add_to_deck()
G.consumeables:emplace(card)```
is it something with create_card?
let me check
yeah probably
should also probably use SMODS.create_card
or at least that is what I've been told
oh this is a custom set
function create_card(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append) its probably with forced key, but i dont know how to use forced key
forced key just creates a card with the given key
chances are you need to setuip something so runes have a fallback card
I'm not familar with making new card types
is that default card?
wait what am i talking about
is there any way to get a random consumable of "runes" without using a pool?
how much should a card that does dusk on the first hand insteado f the last cost?
dusk is rarity 2
so base price around thjat
it has negative synergy with dna
is there a way to create something like this for a modded consumable?
sure it and dna don't like eachother, but it can still make like
insane money while being duplicated
you would use hand 1 on dna, then the rest of the hands arent retriggered
dna is one card
if its baron i can see it
which is for SETUP anyway
ok
@weary jungle it doesn't seem documented but I think you can just set default = "key" on your consumeable type to set a default consumeable for when you have all of them
what should i make loc_vars do
that definitly has been documented, i remember something like thatr
it might have been removed or smth
I found it in the code but I couldn't find where it was diocumented
but i want it to be random, no fallback or pools, just a random card, doesnt matter if you have it or not
so like if showman is around?
yea
is this a fine loc_vars
id probably put "in the first hand of round"
or do i need to do
yeah ill do that
do i need to do card.ability.extra.repeitions
also you have a loc_vars, so probably add "retriggers all played cards #1# time"
so the loc_vars is shown
?
i think so yea
how do i check for first hand of a round
if the hand currently played = max hands probably
yea
what color are retrigger text popups
im seeing a :in_pool function, im not sure where it is
isnt it red again
is G.C.FILTER
thank you!!!
how do you set a pool to allow duplicated!
game tweaking
also let me know if i wrote this wrong
?!?!?!
this line keeps erroring out
please help?
remove the extra.
your config skips that step
(i'm really not clear on what that step does, but i know it changes the relevant variable name)
Put the stuff back into an extra, since the game tries to read some stuff if it's not in extra and attempts to do various effects, which doesn't mix well with how steamodded loads jokers into the game, and I don't believe repetitions work like that, give me a second to find my code,
i just don't know how to write repetitions
Yeah, you're using the joker_main context and attempting to use repetitions on the joker itself, rather than the playing cards.
Look for where it says that it checks for repetition effects in jokers in this message, and then check for the contexts that are provided during that step.
sorry im kinda dumb
No worries, that's why you read resources to learn, I didn't know everything immediately once I decided to try modding Balatro either.
I think I explained it in the example mod, but just in case - the calculate function is called when you do most options, for every single joker you have. It checks their calculate code with contexts to see whether or not it should apply the effect, depending on what's inside of the context provided.
wait does the joker config automatically get copied into card.ability.extra?
or do you have to manually copy it?
Anything in config gets copied into card.ability, but there's code that checks for specific terms in card.ability which can cause issues with modded jokers, but it doesn't cause any issues with card.ability.extra, since there's no code that checks in specifically card.ability.extra.
Unless you know the source code well enough to know those terms and how they apply, it's generally just much easier to stay away from it so that you can have all your logic defined within your joker.
ah
i might just need this written for me tbh
Also, you'll want to have card = context.other_card rather than your normal card = card, because how the return works, is that it's saying, the returned object card is the card object it receives from the calculate function, which is the joker itself - saying card = context.other_card means that it's saying, the returned object card is context.other_card.
This is usually a specific individual playing card, but if you try to call it during a context where it doesn't exist - say like you started a blind, a time where context is called for things like Ceremonial Dagger and Madness, then it'll return nil and cause a crash, because there's nothing to work with.
So, you usually want to have a context check to make sure it's a phase where context.other_card exists first, before working with context.other_card.
If so, this is where my help stops - I'm all for teaching, I'm not doing other people's projects for them, though.
understandable
have day
i don't actually want it written for me, I just don't understand what context is required for repetition, as the part of the post you posted just says "with context"
It's saying all the contexts within those blocks are contained within the table context, so you want to check to see if the values in context match the contexts that should be provided, otherwise, you don't want it to activate.
So, if you have something that applies an effect to Jokers, located in cardarea G.jokers, you want to check for if context.cardarea == G.jokers to see if it applies - but you don't want it to pass if context.cardarea contains G.hand and not the G.jokers you're looking for.
It's really just a giant if tree to make sure it's being activated at the correct time.
Are you talking about full_hand, or?
Yeah, you can do it wherever - before, in the same line, after, as long as it is being checked before the action is triggered.
Wait, should rephrase that,
eval_card evaluates any card, including jokers and such - when it's used on a joker, it'll call the calculate function in the joker, and when used on a playing card, like in this case, it evaluates how many chips and such to give.
having trouble creating a booster pack
How are you defining the description?
Try adding your mod prefix into the key, so that it's p_gems_gemstone_normal. You might also need to add in the _1 as well, but I don't remember for sure.
Nice, look at the third line under stack traceback, right under local variables in your log - it shows what it was specifically looking for, and since it couldn't find it, it returned nil.
Even if you can't fully read it, being able to pinpoint information can usually give you some ideas of some stuff to try doing.
so that's what the extra is for
i'll try to remember that in future
still confused why my stickers aren't showing
label also errors
@shell tangle you think you can help?
The sticker API was kind of finicky last I checked, and I haven't been watching it closely for any updates. Haven't touched it myself because of how finicky the API felt, so not sure.
Send the code you have for the sticker, and localization as well ideally, I can at least have a look.
Can I just increase G.GAME.current_round.hands_left to give an additional hand or is there a function?
What's the full path where the two descriptions are located? G.localization.description.Other, or?
Also, I think you need to maybe put it as loc_txt? Not completely sure.
G.localization.Other
and the labels in G.localization.misc.labels
everything in description table
The sticker will never show up because you overrode the apply function to do nothing.
So even when you force the sticker to apply it'll just do nothing
ohh
Also removed doesn't exist as a sticker function.
i'll make that another function
those 2 are custom functions i use to remove/add values from a card
I was completely off with what I was thinking if that did solve it, so I don't know how to properly work with stickers, apologies.
its fine, its not documented so its just a case of trial and error lol
all i have left to do is fix the labels erroring (like in this image) and make pearl gem act like a stone card & always score
still trying to find an answer to this
I'm having a strange bug where multiple Blueprints will increase the amount of activations on the leftward Blueprints
For instance,
BP + BP + BP + Joker
gives
3 + 2 + 1 + 1
instances of Mult
Only using DebugPlus, Steamodded, lovely, and my mod (which has not touched BP code)
Anyone know what's happening?
this happens for vanilla jokers too to be clear
Likely something with steamodded
I think it might change how blueprint behaves
seems like a bug though
yippee
it looks like you need to set config to
config = {extra = {repetitions = 1}}
You forgot the "extra" table
youre so right
yeah
?
.
your loc_vars is wrong
vars = {card.ability.extra.repetitions}
numbers right, still no retriggering
i know this if statement doesnt work because it will never work at 0, but idrk what to replace that last part with
try looking at how dusk does it?
oh you're missing the context
context.repetition, context.cardarea,context.full_hand, etc,
look at how its structured up top
because of how balatro code is structured they're all checking if its in context.repetition and context.cardarea == G.play
you cant just write cardarea == G.play because that doesnt trigger it
,
again
you need to put "context." beforehand
you cant just write the word itself
ohn
also you should prolly add a context.repetition check
because that's the stage of the game where it checks if cards are repeated
it isnt about what it does its about when it does it
and context.repetition is when it happens
still not working
,,,that checks for the second hand played
well 0 doesnt work either
i changed it to 1 and it didnt work
still nothing
its retriggering on the second hand
,
regardless
,,,really?
huh,,
are you sure you saved it correctly and restarted
that looks about right to me
well nice
how would i make a consumable give 1.5X per face card for the whole round?, i have a global for it, how do i make it give 1.5x mult
how do i use lovely patches
ok im gonna be dumb for a sec
what line is line 85
aand what does the error say
i've been staring at this for a bit and i cannot find any missing ends/closing brackets
is it possible at all you forgot to save the file or smth everything is correct there
there might also be some of that awful invisible white space that sometimes occurs for peolple
do you have the github link? I cannot find a file with that name on github
its my github lol
I can't test code from an image, I need text characters 🙃
trying to make it so there's a 1 in 3 chance for a scoring card to level the upgraded hand, but it triggers 3 times instead of once, am i doing it right?
add context.individual
Weird, I have no issues or crashes with the github code when launching balatro. https://www.soscisurvey.de/tools/view-chars.php also shows no issues for me, but I am still suspecting there's an invisible character on your side that's not on the github?
idk
it works on my desktop, not my laptop
regardless, i have a new issue
i want to make this
idk how to check duplicate hand type
Check hand type when played - if it does not exist, add to a temporary table and give +15 mult. If it does exist in the table, skip.
you can have it collect hand types and store them internally and then check whether it's seen it before to decide whether to give mult or not, then clear it's memory at the end of the round
The Eye? pretty much the same
make sure you're not doing self:juice_up but card:juice_up
im not juicing up anything
return {
x_mult = 1.5,
colour = G.C.RED,
card = self
}
end```is it card = card?
can we normalise providing some context to crash reports and also line numbers on screenshots of code
or something
then you should show your code instead of making us guess based on your error 🙃
card = card
I'm personally a bigger fan of posting the code as text instead of screenshot
ehh, both are useful
screenshots are useful as long as they have line numbers for quickly pinning down where the error is happening
is there a list of every possible context?
I like being able to copy-paste the code
where uh
as long as it's small enough for me to be able to reproduce the error
^ this is missing retrigger api stuff though
it is 100% missing retrigger api
awesome
not if you want to account for any modded hands
my mod is meant to just go on top of basegame
but you can just have an empty list
that works
where do i make the list?
or more specifically, how do i append the hands to handlist
how do i make sure chips never go negative if i give -50 chips?
are you asking how to append to a list in lua?
lua doesn't have lists, only tables
also known as dictionaries or (hash)maps in other languages
hashmaps/dictionaries is what ive heard before
though you might want to use Thunk's method where the hand is the key instead
that way you don't have to iterate over the whole table
how do i get the chips currently scored?
got it working 
hmmph
idk how to write the calculate for thid
i might need more help
you want to do something like this
if not table[hand] then
table[hand] = true
return {your return table}
end
if I've read what you've said correctly
are "tables" made with [] or {}
not sure, but it'll probably be something like G.GAME.chips
i was wrong i mean chips before scoring, like chips X mult
yeah this looks right
started working on converting the calculation guide to the wiki https://github.com/Steamopollys/Steamodded/wiki/Calculation-Context-Guide
G.GAME.chips is the scored chips, i need the unscored chips
Are there any mods that let you open a booster pack outside of the shop? Trying to get my code to work and want a reference
based on this, if i am reading this correctly (i might not) the chips before scoring is hand_chips? so id look for G.GAME.hand_chips?
hand_chips is a global value of the chips scored so far in that hand
so, if i were to check if G.GAME.hand_chips is above 50, this would prevent negative chips?
or is it just hand_chips
ok i did ti
Sorry for the ping but I've been messing around with your code and this happens when the blind is finished
does this art look good?
I like it, but maybe it could be shiny
So is the card supposed to be the gemstone: if so, it looks great!
It depends when you're messing with the score. It's super finnicy. What state are you trying to run it on. You might need to adapt the code
I'm running it from a consumable
I'm new to modding, and I want to make a second joker in my mod (i'm going off a tutorial and an example mod). Which part do I copy?
right yeah it won't work as is. You can dispatch an event to end the round
You should be able to do this https://github.com/MathIsFun0/Cryptid/blob/main/Items/CodeCards.lua#L303-L318
lol the instant you said that I opened up the cryptid source
Thanks so much for your help
Yeah I also wrote the semicolon code
I've written like 3 different things that set the score and end the round now
Glad that i'm getting it straight from the expert
Yeah the game wasn't designed with endign the round early in mind
Works like a charm!
but if you ensure you're in the right state, nothing should break too bad
i figured it out
but how do I make this spawn a spectral card instead of Jimbo?
Don't pass the key to force and change the set to Spectral
also consider using SMODS.create_card
it's a bit nicer to use
Someone needs to document it somewhere
I kinda wanna move my jokers into a seperate .lua file, should I do that?
ok
assert(SMODS.load_file("file.lua"))()
is the simplest way to load another file
and throws errors if it fails to load
ok
and how do i change the name of my mod so it shows up as that instead of "Example Mod" in game?
In the header under name
where's that
top of your main file
do you have a header in multiple lua files?
there's only 1 lua file in my mod
"Twelve Souls"
show the full header
after changing it
Sorry I already undoed it ages ago
well if you change it now does it work?
i will try
Shouldn't mods be using a json file for this stuff? That's what I read in the steamodded wiki
this happens, I changed MOD_NAME to Twelve Souls
I had a duplicate of my lua file in a different folder, maybe it should work now?
Yeah loading 2 versions of the same mod is UB
yeah
okay, got the mod name working but how do I change the color of this label?
the one below the rarity
you can modify the G.jokers.config.card_limit (iirc) in your add_to_deck and remove_from_deck methods
so how do I make it not spawn a joker (am I doing it right btw)
Don't tell it to spawn a joker
like this? also I just want it to be passive not activated when you select a blind, anyway did I do it right again?
I'm not sure what you are trying to do?
string theory just gives 2 joker slots, does the context.setting_blind effect that?
why aren't you using add_to_deck and remove_from_deck like Wilson suggested?
oh you have no idea how
nope, no idea how
remember I'm new to this kinda stuff
cryptid doesn't use SMOD.Joker btw, would using what it uses be easier?
you can just use SMODS.Joker
ok
the reason cryptid does it that way is to make importing files easier I think?
oh ok
either that or it's easier when disabling sections of the mod through the config
in either case, not really relevant for you
add_to_deck and remove_from_deck aren't part of calculate, they are their own functions
no one knows why cryptid does it the way it does it’s weird and wonky and 🤷♂️
oh
I thought Cryptid did use SMODS.Joker
But it separated the data into another file
It’s just that the separation is wonky
so how do I change it?
G.jokers is where the Jokers are stored, G.jokers.config.card_limit is how many you can have
Well, technically Jokers are in G.jokers.cards IIRC
G.jokers is the CardArea object
make those functions not part of the function but of the joker object
Does the indentation matter?
It does not
I thought so
I'm gonna scream if another person comes in with indentation that doesn't even remotely make sense
It makes it more readable
what happened here? looks fine to me.
This is what happens with there are people writing mods who don't write code
You’ve put it in the wrong place
presumably didn't open or close a context or bracket correctly
here is my code /j
Make the text color white, coward
comma
I should add a comma?
Can someone tell me why my code don 't work 😢
😭
here's some more of it ig
remember G.prof then? this is them now. feel old yet?
oml
you take it out of the calculate function
like everyone here has told you twice

I feel like this is a learn lua moment
Certified ™️
It could also be a learn to read moment
i feel like it's a common sense issue if you can't see the those 2 functions should be structured just like any other in the table
Why ask for help if you ignore the answer
learn lua + 98% of balatro user's can't read moment
like this?
yeah
No
No
oh
There’s a missing end still
missing end
The indentation is correct, but the code doesnt follow the indentations
where should I put it?
well the if doesn't have an end
to close the if statement in the calculate function
tbh I wish VSCode treated the if and end's liek the brackets where it matches them
???
kate does but it doesn't have a bunch of other nice features I like
lmao wtf is that
should it look like this now
Also something seems fucky with the SMODS.Joker
yeah that's good
kate?
common
talking about the screenshot
what about this evil fellow at the end?
but no I don't know what kate is either
brother it has a clearly written comment
oh I suppose pool isn't self epxlanatory
that's whether it'll show up in the game
tbh I wonder if an extension could tell vscode to treat the if's and functions as brackets with the ends
still, why is it red
it looks evil and I don't like it
red means unmatched
@torn grove
yes
i just fixed that by removing it
oh so the last } isn't mandatory?
are you genuinely trolling
It mean's it's unbalenced
wdym, i'm new to this kinda stuff
canendish isn't allowed in the pool until gros micheal dies