#💻・modding-dev
1 messages · Page 694 of 1
gulps
I DONT KNOW WHAT IM DOINGGGGG 😭
in my brain im thinking
discard straight -> joker juices up + says "active!" -> gives xmult
discard any other poker hand -> nothing happens
local _, _, poker_hands = G.FUNCS.get_poker_hand_info(context.full_hand) gives you the poker hands and then you can do next(poker_hands[card.ability.extra.type])
replace card.ability.extra.type, "poker_hands" with localize(card.ability.extra.type, "poker_hands")
oh right the localize part
also local variables reset every time a function is called
so i should go for a proper variable instead?
passed will always be false in joker main
card.ability one yes
store passed in cae
or cai
ive been on vscode too much today omg
those are my snippets for card.ability.extra and card.ability.immutable
card area information?
cryptid 🤢
its a good idea to use
I have it for fixed probabilities, rank/suit storage, and state storage
i dont like when other mods dictate how basic code is written
fair
cryptid was the first mod I look through for code (fortunately I didnt learn like anything so no bad lua specific coding practices where learned)
calculate = function(self, card, context)
if card.ability.extra.passed == true then
local eval = function() return context.end_of_round and not G.RESET_JIGGLES end -- Evaluates when Juice ends
juice_card_until(card, eval, true) -- Juice begins
return {
localize('k_active_ex') -- Returns "Active!"
}
end
if context.pre_discard then
local _, _, poker_hands = G.FUNCS.get_poker_hand_info(context.full_hand) -- Checks Poker Hands
if next(poker_hands[card.ability.extra.type]) then -- Checks if it matches the Type
card.ability.extra.passed = true -- Passed becomes True
end
end
if card.ability.extra.passed == true and context.joker_main then -- Joker Main will not trigger unless Passed is also true
return {
xmult = card.ability.extra.xmult
}
end
end
}
joker works, it just doesnt juice up or return a message properly
discord wont let me send screenshots omfg
discord's being janky rn, it's not a you issue
oh i see
but yeah, i keep getting [Util] Found effect table with no assigned repetitions during repetition check
no idea what that means
you are returning an tsble during a repetition context
yeah but what does that mean
the first if statement doesn't have a context check
anyway yea that usually just means you have too loose context checks (or in your case, no context check at all). the if card.ability.extra.passed == true part is running in a bunch of contexts, including during repetition contexts
smods only expects you to return { repetitions = something } or nothing at all during repetition contexts, and will print that warning if you return anything else
your function is being called with context.repetition set to true and is returning useless data
ohh
mari is using passed a lot more recently ,,,, 🥺
okay so i fixed the issue but it still doesnt juice up
put the juice up in the if statement where you make it true
-- Fireworks
SMODS.Joker {
key = "fireworks",
config = { extra = { xmult = 3, type = 'Straight', passed = false } },
pos = { x = 5, y = 2 },
cost = 9,
rarity = 3,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = false,
atlas = 'HatchetJokers',
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.xmult, localize(card.ability.extra.type, 'poker_hands') } }
end,
calculate = function(self, card, context)
if context.pre_discard and card.ability.extra.passed == true then
local eval = function() return context.end_of_round and not G.RESET_JIGGLES end -- Evaluates when Juice ends
juice_card_until(card, eval, true) -- Juice begins
return {
localize('k_active_ex') -- Returns "Active!"
}
end
if context.pre_discard then
local _, _, poker_hands = G.FUNCS.get_poker_hand_info(context.full_hand) -- Checks Poker Hands
if next(poker_hands[card.ability.extra.type]) then -- Checks if it matches the Type
card.ability.extra.passed = true -- Passed becomes True
end
end
if card.ability.extra.passed == true and context.joker_main then -- Joker Main will not trigger unless Passed is also true
return {
xmult = card.ability.extra.xmult
}
end
end
}```
?
do this
lines 21 - 25 should be moved to after -- Passed becomes True
-- Fireworks
SMODS.Joker {
key = "fireworks",
config = { extra = { xmult = 3, type = 'Straight', passed = false } },
pos = { x = 5, y = 2 },
cost = 9,
rarity = 3,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = false,
atlas = 'HatchetJokers',
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.xmult, localize(card.ability.extra.type, 'poker_hands') } }
end,
calculate = function(self, card, context)
if context.pre_discard then
local _, _, poker_hands = G.FUNCS.get_poker_hand_info(context.full_hand) -- Checks Poker Hands
if next(poker_hands[card.ability.extra.type]) then -- Checks if it matches the Type
card.ability.extra.passed = true -- Passed becomes True
end
if context.pre_discard and card.ability.extra.passed == true then
local eval = function() return context.end_of_round and not G.RESET_JIGGLES end -- Evaluates when Juice ends
juice_card_until(card, eval, true) -- Juice begins
return {
localize('k_active_ex') -- Returns "Active!"
}
end
end
if card.ability.extra.passed == true and context.joker_main then -- Joker Main will not trigger unless Passed is also true
return {
xmult = card.ability.extra.xmult
}
end
end
}```
Like this?
you have 2 ends in a row
o
anyways it still does nothing
-- Fireworks
SMODS.Joker {
key = "fireworks",
config = { extra = { xmult = 3, type = 'Straight', passed = false } },
pos = { x = 5, y = 2 },
cost = 9,
rarity = 3,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = false,
atlas = 'HatchetJokers',
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.xmult, localize(card.ability.extra.type, 'poker_hands') } }
end,
calculate = function(self, card, context)
if context.pre_discard then
local _, _, poker_hands = G.FUNCS.get_poker_hand_info(context.full_hand) -- Checks Poker Hands
if next(poker_hands[card.ability.extra.type]) then -- Checks if it matches the Type
card.ability.extra.passed = true -- Passed becomes True
end
if context.pre_discard and card.ability.extra.passed == true then
local eval = function() return context.end_of_round and not G.RESET_JIGGLES end -- Evaluates when Juice ends
juice_card_until(card, eval, true) -- Juice begins
return {
localize('k_active_ex') -- Returns "Active!"
}
end
if card.ability.extra.passed == true and context.joker_main then -- Joker Main will not trigger unless Passed is also true
return {
xmult = card.ability.extra.xmult
}
end
end
end
}```
current state of fireworks
omg
you have 1 pre discard check
can someone else help I really don't wanna type code on mobile ;-;
i had an idea for a mechanic where each joker could be marked with a grade, and the grade would multiply any values on the joker by an amount, what would i need to do to achieve something like that
I moved the code from my main lua file into separate files (IE. jokers.lua) and everything is fine, but my spectral card that adds my custom seal stopped working idk why
does the prefix stop working or smth?
wait I know why
balatro isn't picking up the json file like before, why could that happen?
did you assert those separate files in your main.lua
yes
Oh i figured it out, there was a typo on the version: part of the json, and so the prefix changed from the one I set to the default one
because it wasn't picking up the json
what string do i put here for each suit
just the capitalized name of the suit for all vanilla suits
aight thx
-- Wheelbarrow
SMODS.Joker {
key = "wheelbarrow",
config = { extra = { odds = 7, xmult = 1, xmult_gain = 0.2 } },
pos = { x = 6, y = 3 },
cost = 7,
rarity = 2,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = false,
atlas = 'HatchetJokers',
loc_vars = function(self, info_queue, card)
local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'j_hatch_wheelbarrow')
return { vars = { numerator, denominator, card.ability.extra.xmult, card.ability.extra.xmult_gain } }
end,
calculate = function(self, card, context)
if context.stay_flipped and context.to_area == G.hand and SMODS.pseudorandom_probability(card, 'j_hatch_wheelbarrow', 1, card.ability.extra.odds) then
return {
stay_flipped = true
}
end
if context.individual and context.cardarea == G.play
and context.other_card.facing == 'back' then
card.ability.extra.xmult = card.ability.extra.xmult + card.ability.extra.xmult_gain
return {
message = "Upgrade!",
colour = G.C.MULT
}
end
if context.joker_main then
return {
Xmult = card.ability.extra.xmult
}
end
end
}
how do i make this joker work
the idea is that its supposed to upgrade its xmult per flipped card
wait ```lua
if context.individual and context.cardarea == G.play
and context.other_card.facing == 'back' then
nvm that did nothing
heres the updated code
ill leave it here for todae
is there a context for when a separate joker triggers
trying to make a joker that gives you money if 4 or more other jokers triggered
maybe make a count go up when if context.other_joker
I think it's context.post_trigger
value manipulation is kind of rough to implement, but if you make your mod depend on a library mod that implements it (either Blockbuster Value Manipulation or Spectrallib) then you could easily just make them be stickers
uhmm how can i make it so when u skip a blind it plays a video that fills your whole screen?
You're gonna want to look for something like Yahimod's "Video Tag"
i was looking through it.. i dont know if it tickles my fancy tho.. i want the thing to fill the scren really
You can try looking through the Fish Tarot or the Fish Blind from the same mod. That might help
oh yea good point
Anyone know how to check if the game is past a certain ante?
whats the filename for tarots anyway?
nvm i think its consumables.lua
tf is a g.showfish
the current ante is G.GAME.round_resets.ante
That'll work. Thanks
if you want to view the current value of chips and mult during the middle of scoring (so at the moment when the calculate code is running), it's just the globals hand_chips and mult
oh.. no more like adding. istg i used to know it now i dont
return chips or mult during calculation? or xchips or xmult if you want to multiply
https://github.com/Steamodded/smods/wiki/Calculate-Functions
sorry its like at the end of round.. i want to add +100 chips and remove 50 mult
its like saying chips isnt a thing and weve already had that thing about variables so im questioning if i wrote it wrong
end of round meaning you want to modify a joker's values, or do you actually mean end of a played hand?
like uhhhh yk how blue joker adds chips? kinda like that
yea
return chips in context.joker_main
i highly recommend reading the link i sent
and/or checking how blue joker works in vanillaremade
alright..
it does say chips is valid but it crashes.. maybe the game doesnt want me removing value
could you like
post your code
returning mult and chips is a modifier, not something that completely replaces the value. it should just be chips = 100 and mult = -50
ohhhhhh
(also you said you wanted +100 chips and -50 mult, but you're doing the opposite here)
oh either you read it wrong or i wrote it wrong its supposed to be that way
alrighty
can i disable the message that shows up and just have smack?
if thats too hard thats fine
but anyways how would i make it so that thing happens when uhhhhh you have a certain card
like joker card
if you would direct your attention to the page i already linked
OHHHHHHHH FUCK
anyway to be clear, you only want this effect to happen if you happen to have another specific joker?
yea like this joker cards ability st8s that for every copy of this card.. add 1.5 mult for example
i dont need the 1.5 mult its just an example
what is the exact effect you want for this
the answer changes whether it's "check if you own a specific joker" or "check how many copies of this joker you own"
a think a mix of both?
could you just list the actual ability
as of now i can change things but for know i wrote this
SMODS.find_card("j_modprefix_key") will return a table of every copy of the joker j_modprefix_key that you own (replace modprefix with the relevant mod prefix, and key with the key of the joker)
#SMODS.find_card("j_modprefix_key") (note the # at the start) will return the total number of that specific joker that you own. so you can just return { mult = #SMODS.find_card("j_modprefix_banhammer") * 25 }
OH YEA
but what if theres two... yk what well work on that when i make the other card
is SMODS.find_card a variable?\
it's a function
alright.. how do i use it in a form
it returns a variable
oh yea..
i did smth like this and it worked but now it doesnt
I'm trying to have this randomly force-select the amount of cards a player can select, but it picks too few.
I've already toyed around with the i = 1 part to see if that helps, got nowhere.
not G.GAME.chips < 50 is bad for multiple reasons
not x < yis treated as(not x) < y. you should just usex >= yG.GAME.chipsis your current round score. you should usehand_chipsinstead like i mentioned earlier
OHHHHHHH
local cards = SMODS.shallow_copy(G.hand.cards)
for i=1, G.hand.config.highlighted_limit do
local forced_card, index = pseudorandom_element(cards, self.key)
forced_card.ability.forced_selection = true
G.hand:add_to_highlighted(forced_card)
table.remove(cards, index)
end
it's possibly selecting the same card multiple times, since cards highlighted in hand are still held in hand
I didn't check for that.
...how do I check if it is?
Thanks
yes, by making a separate table of all the cards in your hand then you can remove them once they're selected so you can't reselect them
now how can i write SMODS.find_card("j_epicerMod_hammer1") in a way that wokrs
confirm that "epicerMod" is actually the prefix of your mod (you defined it in your mod's json file)
alr
and show the full joker definition for hammer1?
ok so it should be SMODS.find_card("j_epicerMod_nonplushiehammer"), because that's what you put as the key for it
Well, it's working a lot better now. Only issue is that won't select 5 cards every hand.
wheres the icons for the decks hiding in the files
Well, that's REALLY not supposed to happen.
i love the missing gap!
gotta be one of my favorite card
Thank you SMODS for the missing card. Truly a great addition.
shit now i gotta add that
Ok, but how do I actually fix the gap?
i wouldnt know id have to think like you in a sense and then learn how what went wrong
Try adding G.hand:remove_from_highlighted(forced_card) before the G.hand:add_to_highlighted(forced_card) and change the for loop to for i=1, G.hand.config.highlighted_limit-#G.hand.highlighted do
Giving it a try now
H u h
Is it the fact that SMODS is pulling cards that just don't exist into the table?
What can I run in DebugPlus to see what cards are in my hand? I may have an idea.
No, that means there are multiple of the same card in G.play
For context, I ABSOLUTELY just stole the code from Cerulean Bell and I'm trying to hack a solution together.
That makes more sense. Is there some way to see if a card is already selected and skip over it if it is?
if card.highlighted
I'm gonna assume that has to go inside the for loop.
And the code would need to be changed to remove the highlighted card from the table.
how to add seals
eval G.cards.hand
Add seal to cards or make a seal?
card:set_seal('modprefix_key')
alright but what if its red seal
card:set_seal('Red')
ohhhh.
Yeah, it's kind of nice when it comes to that.
Yep, that's certainly NOT how to do it.
local cards = SMODS.shallow_copy(G.hand.cards)
for i=1, G.hand.config.highlighted_limit-#G.hand.highlighted do
local forced_card, index = pseudorandom_element(cards, self.key)
forced_card.ability.forced_selection = true
if not forced_card.highlighted then
G.hand:add_to_highlighted(forced_card)
end
table.remove(cards, index)
end
Now we finally have it working
is context.other_card:set_ability("m_steel", nil, true) correct?
is there any way to display emojis or something similar for card descriptions?
i put this but for probably many reasons it didnt show up at all
I don't exactly know if emojis are supported.
Also a "fatass teto" joke. Daring today, aren't we? /s
yea so i might have done this..... (dw i dontthink i need help)
You would have to use a font that supports emojis.
my jokerforge project that im using to make the spritesheets had this from a while ago and i didnt really know what to do for it
None of the m(number_here)x(number_here) fonts support it.
w8 wut
?
i was just going off of the smods wiki for making my mod
Oh..
and it did say to use an atlas so i am
is delay() affected by gamespeed?
also, what is the game's base delay between cards when iterating thru cards (for things like scoring)
0.9375
and i assume that delay isn't affected by gamespeed
Yes.
why

syntac error
code?
Specifically in Laminated.lua
then theres your issue
it looks like you aren't provding correct data to dynatext
please send code
or else we can't help
i dont know WHAT its doing wrong
do i have to fill out all fields
idk, i've never used that mod before
is it up tod ate?
it may not work with current smods
theres was several dynatext changes in zeebee
reminds me of one of my mod's cards lol
😋
So it debuffs a random card and all that I need it to, but it won't buff it back after the blind is won.
if the card is debuffed with SMODS.debuff_card it needs to be rebuffed manually
you can do it in blind.disable and blind.defeat
I tried having it rebuff when defeated with the defeat function, but it crashes.
Unless there's a convenient context I can use
It's not a bug, it's a ✨ feature ✨
what's the crash
attempt to index local 'card' (a nil value)
But since the blind gives 20 bucks, I'm not changing it atp.
ok
Sorry for wasting time ¯_(ツ)_/¯
how can i hide vanilla jokers?
i think they want to hide them with their mod
you can no_collection all of them with take_ownership probably
local ranks, bust = {}, false
for k, v in pairs(G.hand.cards) do -- go through all cards held in hand
if ranks[v:get_id()] then -- does this rank have an entry in the dictionary?
bust = true -- if so, it's a repeat rank. BUST!
end
ranks[v:get_id()] = true -- now we add it to the dictionary
end
card.ability.extra.mult = #ranks
if context.other_card and bust == false then
return {
mult = card.ability.extra.mult
}
end
end```
so here's my code for a joker i'm reworking. however, instead of cards giving mult, the joker just shakes violently and no mult is given from cards
ah i see
given that it only gives mult if every card held in hand has a unique rank, you can just use #G.hand.cards instead, since the number of cards in hand equals the number of ranks in hand
where do I copy this specifically?
You can put it anywhere as long as it's not in anything.
what a crazy way to do it
I'm trying to wrap my head around what's the actual issue, it gives g= nil
Try adding vars = {} to the localize table.
oh yeah that did it! ; 0 ;
oh that's weird
how can I make it,,,, not, be there
just change it back to ObjectType?
Yes, also remove the cards table.
right because it already injects it no?
Yes.
casual testing shop
I have one questiomn, why no text?
can i see the whole thing
can you read the comments in your loc_vars i wrote specifically because of this issue..
in general if you return key in loc_vars you need a localization file and not loc_txt
yeah I haven't gotten around to that part yeah
this could be an attribute right?
have we made attributes work on consumables?
i've read that they should work
No, also they want it to work with modded consumables.
what does the weight variable do on boosters?
mb for taking too long but it crashes my game before creating any jokers
do i need to define a pool?
yes
shi mb
ight thanks
how do I target both cards in play and in hand?
for what
this gives me an error whats wrong
return { vars = { card.ability.extra.Xmult_gain, card.ability.extra.Xmult }, colours = { {1, 0, 0, 1}, } }
uhhmmmm
i wanna dd that
(context.cardarea == G.play or context.cardarea == G.hand)
what's the error
ah colours should be inside vars
missing a comma after the sound
change the pitch in the smods sound
oh... how can i do that
did you read the docs
like pitch = __?
yes
the docs answer that :3
oh I managed to find the same conclusion
go read them we write them for a reason
ok so i fixed that but one question
if my joker is square like.. how do i make it look like its in the middle like square joker in the sense that its all square and theres no extra space at the bottom
like this in the sense.. you cant see my mouse but you can see my mouse at the bottom of the joker
:0 it work
is it not already?
nvm i see it
thanks
im trying to play with the pitch but it doesnt work
can i see the code
0.7 is the default
alr but its still like really low pitched compared to what its supposed to sound like
its supposed to sound like this
what number did you put it
0.7 is the default 😭
so it's the one it is without pitch = ...
you want something higher like 1
i put one and nothing changed tho but i can try again
hmm it might only work with music
i have only tried it with music at least
you might need to edit the sound
alr.. is this right tho?
yahimod is carrying me in learning balatro modding ngl
same tho
i stole code from dr whatsapp to help make paper dolls
bruh
you shouldn't check for the score manually, check context.game_over == false
== true
i stole code from jack black to make a joker that activates if you have no face cards in your deck
I don't think yamimod is a good starting point
there are complicated and peculiar effects that might spook you
it works fine im just asking if i can even write and card.ability.extra.roundspawned > round
am i able to make the cost of a joker a decimal without it rounding up
true... thats why i get people in this server to dumb it down for me
G.GAME.round?
OHHHHH okie
but also can i make it so on spawn a variable changes
for the joker
on spawn as in when you get it or when it appears anywhere
like when its in your deck essentially
then use add_to_deck
add_to_deck = function(self, card, from_debuff)
if not from_debuff then
-- initial effects on adding card to deck
end
-- otherwise effects added on removing debuff on this card
end
ohhhhhhh okie
it may pair with remove_from_deck
how to check number of total joker slots someone has
remove_from_deck = function(self, card, from_debuff)
if not from_debuff then
-- undo effects on destroying this card
end
-- otherwise effects removed by debuffing this card
end
for example 0/THISNUMBER
G.jokers.config.card_limit
thanks
missing comma after end of add_to_deck field
also https://github.com/nh6574/VanillaRemade/wiki#3-set-up-the-lua-lsp this will help you a lot in mod development
it works :0
i use that tooo sometimes
nvm sometimes if it works it means the other half just wont die so i need to find out
ok i fixed it :D
if im using an event that has delays, do i need to multiply the delay by the gamespeed in some way to make gamespeed affect the delay time
the game speed affects the delay by default afaik
if im having something that iterates through the cards, what delay would i use
i was told 0.9375 by someone else
cause thats what the game uses
for i,v in ipairs(viableHand) do
if i <= diseaseCards then
v:set_ability("m_CGN_Disease", nil, true)
G.E_MANAGER:add_event(Event({
func = function()
v:juice_up()
return true
end
}))
SMODS.calculate_effect({message="Infected!",colour = G.C.GREEN}, v)
delay(0.9375)
end
end
end
this is what i have currently
actually nvm
why does this work in yahimod but not in anywhere else
i have the getJokerID function
do you have retriggers enabled
also context.other_card ~= self will always be true
and card = card is not necessary
and returning nil, true there is wrong since it indicates you are doing an effect but you are actually not
how do i enable that
This Joker
isn't properly copying the changes from this Joker when copying the card after this activates on the same hand.
As in, fraudfirst gives the card an edition, but, despite copying it after the edition is applied, fraudsecond doesn't copy it with the new edition. (It copies cards that start with an edition fine, and also works perfectly fine with Midas Mask.
ty it works :D
now i have made the bbno$ joker that larps a joker to its left
I just use add_tag({ key = get_next_tag_key() }).
I don't think that should be recommended
I just used Pity Prize’s code.
it uses a different seed right?
For the tag generation
I’ll check on it later.
how to change the rank of a card
thank you!
acutally, this is about making them increase and decrease, right? im just trying to set a new rank for a card
am i js an idiot 😭
i linked to the one above that
no i had this happen multiple times this week
if context.before and #context.full_hand == 1 then
assert(SMODS.change_base(card, nil, 'Ace'))
G.E_MANAGER:add_event(Event({
func = function()
card:set_sprites(nil, card.config.card)
return true
end
}))
end
end```
card is not the played card
sticker failed
D:
bumping this
fraudfirst applies the edition in an event so it happens after
you need to either copy in an event or remove the event
for _, scored_card in ipairs(context.scoring_hand) do
assert(SMODS.change_base(scored_card, nil, 'Ace'))
G.E_MANAGER:add_event(Event({
func = function()
scored_card:set_sprites(nil, scored_card.config.card)
return {
message = localize('Ace!'),
colour = G.C.BLUE,
scored_card:juice_up(),
card:juice_up()
}
end,
}))
end
end```
where am i supposed to put the return 😭 am i intellegent
it should juice up and message after play hand button is clicked
the right joker has a very small sprite size which is scaled up using display_size, but that seems to heavily mess with the tilt. Is there some easy fix for this?
bot
`config = {extra = {numerator = 1, denominator = 2, x_chips = 2, trigger = nil}},
loc_vars = function(self, info_queue, card)
local num, denom = SMODS.get_probability_vars(card, card.ability.extra.numerator, card.ability.extra.denominator)
return {vars = {num, denom, card.ability.extra.x_chips}}
end,`
Im getting a crash on the local num, denom line and i fr cant seem to fix it, its when i hover over a card with the edition
this is the crash
attempt to index field 'extra' (a nil value)
can anyone point me in some sort of direction to try and fix this im just so lost lol
for some reason this is crashing when im trying to change a card to hearts, my best guess is that in "SMODS.change_base(card, 'Hearts')" "card" needs to be something else, but i don't know what
if context.individual and context.cardarea == G.play and
SMODS.pseudorandom_probability(card, 'omega_toilet', 1, card.ability.extra.odds) then
assert(SMODS.change_base(card, 'Hearts'))
G.E_MANAGER:add_event(Event({
func = function()
card:juice_up()
return true
end
}))
end
end```
like this? cuz it's still crashing calculate = function(self, card, context) if context.individual and context.cardarea == G.play and SMODS.pseudorandom_probability(card, 'omega_toilet', 1, card.ability.extra.odds) then assert(SMODS.change_base(context.other_card, 'Hearts')) G.E_MANAGER:add_event(Event({ func = function() context.other_card:juice_up() return true end })) end end
outside the event
also the juice_ups shouldnt go there
m
*mb
did you restart the run before testing
ok thank u now it works!
just one thing, can i make it so it only changes into hearts when it's scoring? because it's turning them into hearts all before scoring
theres example code i wrote for that in the docs
can one like myself add planet cards (so that they appear on the planet card section and not add another consumable section in the collection) but that doesn't appear where normal planets would (ie doesn't appear in celestial packs, shop, blue seal)
oh wow
I peered through this whole page I didn't see that part
everything in it is so interesting
the in_pool function, I just add it to the SMODS.Consumable?
so it would be
return not args or args.source ~= "Celestial"
end```
woops
to remove it from celestial packs?
No, it would be 'pl1'
I see, key_append = "vremade_pl1"
I was looking for where the hell the pool was in there
hi, does anyone know how i would go about getting specifically the cards held in hand that trigger a held in hand ability?
how would i go about modifying the badge for a planet card, e.g if i add a moon, changing it to say "moon"
set_card_type_badge = function(self, card, badges)
table.insert(badges, create_badge(text, card_type_colour, card_type_text_colour, 1.2))
end
thanking you
for the planet cards, how can I make it level up two hands at once, or one hand two times
how do I get the texture width and height in shaders?
idk looks fine to me
custom use function
just calling SMODS.upgrade_poker_hands in use should work
That’s what I’m saying
I think it’s cuz it’s on an edition fr
that would be useful to know beforehand lol
yeah editions are in card.edition? i think
Imma try it when I get home from work lol
check vanillaremade editions if you haven't
wai hold on
Yeah I saw that looks awesome, will def check that out too
you need a can_use i think
can_use needs to be defined iirc
oh I was looking for that
where it go ;-;
I thought it was force_use
force_usw sounds like a cryptid thing
caught in the act
oh it was way simpler than I thought I didn't need a custom function
key = "caribbean",
set = "Planet",
pos = {x = 1, y = 0},
cost = 6,
in_pool = function(self, args)
return not args or args.source ~= "pl1"
end,
can_use = function(self, card)
return true
end,
use = function(self, card, area)
SMODS.upgrade_poker_hands({hands = {"Pair", "Two Pair" }, level_up = 1, from = card})
end
}
what makes the secret hand planets appear during the run?
config = softlock handles it automatically?
yes
for something more complicated you can use in_pool
Ran out of ideas for mod development? Come on over to https://discord.com/channels/1116389027176787968/1403705257292337162 today!
- User-made ideas!
- User-made ideas!
- User-made ideas!
and most importantly, - User-made ideas!
This is the exact same thing I posted in #⚙・modding-general but with this text added
How would I be able to get a card to give you an extra hand when it is drawn in the first hand?
if context.first_hand_drawn then
for k, v in pairs(G.hand.cards) do
if v == card then
ease_hands_played(1)
end
end
end
does weight work for consumables
Yes, as long as you have the object_weights optional feature enabled.
does that affect the other consumables o_°
No, it only affects the consumables you set it on.
I'm reading the doc but I don't understand how I enable it?
SMODS.current_mod.optional_features = function()
return {
object_weights = true,
}
end
thank uu
Using this, how can I make the card immediately get discarded after the effects trigger?
card.area:add_to_highlighted(card)
G.FUNCS.discard_cards_from_highlighted(nil, true)
is there already pre-existing japanese unicode for balatro/smods ?
how do i use it for localization
I don't believe m6x11plus has support for Japanese unicode.
You'll need a localization folder and an en-us.lua inside it with your mod.
the Japanese language option in Balatro does not use m6x11plus
@pastel kernel #⚙・modding-general message
You'll wanna look at DNA for dupe code.
As for the discard, there's a context for discarding that may work.
How do I check for when literally ANY action is taken (sell Joker, click a card, deselect, etc.)?
You could check for the mouse being clicked and any keyboard key being pressed.
Oh that's even funnier with what I wanna do with this Blind. Does Lua has some kind of os thing to check for that?
No, you would hook Controller:L_cursor_press and Controller:queue_R_cursor_press and Controller:key_press_update
Nevermind, what contexts are for a card being selected or Joker being sold?
I don't wanna do any more hooking functions.
There is no context for selecting a card, so you have to hook.
So what file do I look for exactly?
engine/controller.lua
Thank you
So apparently Balatro didn't like this solution somehow
I'm gonna try changing the blind's key
Nope, changing it did not work.
Mind you, there are 3 other hooked functions that have the exact same added code, but SMODS doesn't complain about those lines.
ONLY happens with Controller:key_press_update
what did pseudorandom_element do to you that you're refusing to use it
I'm using the same solution I used a long while ago in my decks.lua for randomness.
Because l a z y.
I wouldn't call a long if-else chain lazy
as for the error
if G.GAME.blind and ...
If you know of a way to randomly select a .WAV file from 10 random ones, I'd actually kinda like to know how.
pseudorandom_element({ "key1", "key2", ... }, "seed") ?????
...yeah, that would probably be so much easier.
ikr
So VERY BAD news:
Those really bad hooks mess with TooManyJokers and DebugPlus even working.
I couldn't even force summon the blind without meeting its requirements.
How do I summon things from the DebugPlus command line?
Don't know what you mean, SMODS, those files exist right in the folder they belong
...then probably not registered with SMODS.Sound.
Yep, forgot to do that, and now that works.
But NOW:
I renamed the .wav to .ogg, and that's probably why, isn't it
Game couldn't properly read those files as the OGGs it expects.
Can I modify this code somehow to ignore the sounds if certain keys are pressed?
I need it to ignore if T or 1, 2, or 3 is pressed.
Are you running the old function?
Old function?
Here's what I'm hoping will do the trick:
if G.GAME.blind and G.GAME.blind.config.blind.key and not (love.keypressed('tab') or love.keypressed('1') or love.keypressed('2') or love.keypressed('3') or love.keypressed('t')) == "bl_WCCO_arya_only_audio_assault" then```
You need to save Controller.key_press_update before you hook it then run that in the hook.
How do I save it before the hook?
local oldcontrollerkeypressupdate = Controller.key_press_update
Alright, so just drop that outside the hooks and all good or drop that in before the function in every hook?
Ok, so doing this and throwing local oldcontrollerkeypressupdate = Controller.key_press_update outside all the hooks changed nothing.
Yes, you also have to run the old function and return it's return.
What exactly do you mean by "old function"?
oldcontrollerkeypressupdate
So let me see if I have this right:
I have to have the local oldcontrollerkeypressupdate = Controller.key_press_update outside ALL hooks and somehow return... its return (which I have no clue how that works.)
Because I hooked like 3 or 4 like you previously said to.
No, you would replace Controller.key_press_update with the function you are hooking.
...Yeah, got no clue what you exactly mean. I'm trying to figure out where I'd need to put what exactly.
local oldcontrollerlcursorpress = Controller.L_cursor_press
function Controller:L_cursor_press(x, y)
local g = oldcontrollerlcursorpress(x, y)
-- Code
return g
end
local oldcontrollerqueuercursorpress = Controller.queue_R_cursor_press
function Controller:queue_R_cursor_press(x, y)
local g = oldcontrollerqueuercursorpress(x, y)
-- Code
return g
end
local oldcontrollerkeypressupdate = Controller.key_press_update
function Controller:key_press_update(key, dt)
local g = oldcontrollerkeypressupdate(key, dt)
-- Code
return g
end
...yeah, that makes a lot more sense seeing it like that.
Thanks for doing all that
i couldn't find it yesterday
utility page
i was searching there but idk what exactly im looking for
isnt that exactly what im doing right now?
i need a different context (i think)
you want to delay the sprite changing right?
or did i misunderstand
anyway what i was saying was that there's a snippet of code right there for the card to work like midas mask
the context doesnt matter because all scoring contexts run before scoring and the animations are done in events (see: https://github.com/nh6574/VanillaRemade/wiki#why-does-the-animation-play-before-scoring-when-the-context-i-put-it-in-occurs-later)
ohhhh i think i understand
yeahhh now it works, thanks!
wait nvm, because im saving which card to change into hearts before the event, only the last card is turning into hearts, how do i fix this because i can't just put the "context.other_card" inside the event calculate = function(self, card, context) if context.individual and context.cardarea == G.play and SMODS.pseudorandom_probability(card, 'omega_toilet', 1, card.ability.extra.odds) then le_card = context.other_card G.E_MANAGER:add_event(Event({ func = function() le_card:juice_up() play_sound('tarot2', 1, 0.4) assert(SMODS.change_base(le_card, 'Hearts')) return true end })) end end
this is why you use local variables
OHHH yeah that fixed it, thank you!
keep in mind this will change the card's suit after scoring
yes yes that's intended
i think it's a bit unintuitive if the animation happens during
since the player will expect for it to count for other jokers
hmm maybe, but imagine you play a flush and it cancels out the flush since a card changed suits
that's not how it works
exactly
no i mean it wont cancel the flush
the poker hand is decided before scoring begins
yeah, so it doesn't matter if all cards change into hearts before or during scoring animations
atleast for me it looks better this way
if it happens before other jokers will count it, if it happens after they won't
the problem is that the change is happening visually before other jokers score which might be confusing
if you don't care that's fine just letting you know
ok ok
how come when i use #1# #2# #3# etc. in my descriptions, sometimes for jokers it says nil, but sometimes it says the real number?
your loc_vars functions are messed up
do i have to define it in loc_vars? i thought it took it from the config
#1# = first value in returned vars
yes 😭
mb mb 😭
SMODS.Atlas {
key = 'smiler',
path = 'smiler.png',
px = 71,
py = 95
}
SMODS.Joker {
key = 'smiler',
loc_txt = {
name = "{V:1}S{}M{V:1}I{}L{V:1}E{}!",
text = {
"Played {C:attention}face{} cards score {X:mult,C:white}X1.5{} Mult,",
"but have a {C:green}1 in 2{} chance to {C:attention}destroy{} themselves"
}
},
atlas = 'smiler',
pos = { x = 0, y = 0 },
rarity = 2,
cost = 5,
blueprint_compat = true,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = true,
config = { extra = { Xmult = 1.5, odds = 2 } },
loc_vars = function(self, info_queue, card)
local new_numerator, new_denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, 'j_sink_smiler')
return { vars = { card.ability.extra.Xmult, new_numerator, new_denominator, colours = { HEX('FFFF00') } }, }
end,
calculate = function(self, card, context)
if context.individual and context.cardarea == G.play and context.other_card:is_face() then
do return {
Xmult = card.ability.extra.Xmult
} end
if SMODS.pseudorandom_probability(card, 'sink_smiler', 1, card.ability.extra.odds) then
return {
remove = true,
}
end
end
end
}```
this code wont trigger the odds to destroy a [played] face card?
because you are always returning before the probability happens
also its just not in the correct context to begin with
u right
im so smart
you need to do it in context.destroy_card with the same other checks
fuck
--first played card is retriggered for every hand destroyed this ante
SMODS.Joker {
-- How the code refers to the joker.
key = 'sailboat',
atlas = 'JokersGrabBag',
pos = { x = 1, y = 0 },
rarity = "gb_boss",
config = { extra = { repetitions = 1}},
loc_txt = {
['name'] = 'Compass',
['text'] = {
[1] = 'Played number cards have a',
[2] = '{C: green}1 in 5{} chance to be retriggered.',
},
['unlock'] = {
[1] = 'Unlocked by default.'
}
},
cost = 7,
blueprint_compat = false,
perishable_compat = true,
eternal_compat = true,
demicoloncompat = true,
discovered = true,
unlocked = true,
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.odds} }
end,
if context.repetition and context.cardarea == G.play then
if context.other_card == context.scoring_hand[1] then
return {
repetitions = card.ability.extra.repetitions,
message = localize('k_again_ex')
}
end
end,
in_pool = function(self, args)
return gb_is_blind_defeated("bl_wheeloffortune_compass")
end
set_badges = function (self, card, badges)
SMODS.create_mod_badges({ mod = SMODS.find_mod("GrabBag")[1] }, badges)
end
}```
So tried hooking some functions in controller.lua, and now I have this.
There are apparently no other instances of this error in the server.
return { vars = {colours = { HEX('#3E436F'), HEX('#FF0000') } }, { extra = { card.ability.extra.Xchips, }, } }
colours crashes my game, what did i format wrong
This is inside a loc_vars, yes?
Also, mind providing crash log?
Can you screenshot your code? I wanna see something to mark it out of possibilities real quick.
Why are you trying to do extra = {card.ability.extra.XChips} in the loc_vars?
That MIGHT be causing it.
ill check rq
ah nope
sma ecrash log
*same crash log
nvm i fixed irt
*it
thanks
This one been fixed yet?
Wait, there's no calculate function for your Joker.
@daring fern Everything I touch somehow breaks. I literally followed your steps from #💻・modding-dev message.
ok this works, and so does the previous code, somewhat anyway
the code retriggers the effects 7 more times
and it also stays highlighted even after discarding
nevermid
it CONTINUOUSLY retriggers and add glitched, nonexistant cards when it triggers
Ghost cards, the bane of Balatro modders.
I think SomethingCom gave me a way to stop that from happening a while ago.
what am i possibly doing wrong here to get this result
1x file in 2x folder
i checked the 2x file and it apparently is 2x
you know what im just gonna scrap my lost card idea
is the default weight 10 or 1.0? I don't know if I misinterpret it or not
Well, hold on, maybe I can help fix it up.
the estrogen blind
the wiki clearly says it's 10?
yeah because of what the other person said, in vanilla it's 1.0
that is for anything that isn't already weighted in vanilla
I just wanted to make sure
if only
I was scared I was wrong
for boosters, the weights are built around 1 as default, but it'd still be 10 if you were to not specify one
ultimately you can scale your weights however you like, what matters is what other objects exist to interact with it
My mod is murdering me in San Fransisco rn.
What's wrong with it?
I'm trying to follow Astra's modding guide but it's killing me anyway
Uuuhhhh
I really do not know
It was working fine at first
Any crash logs, unintended behaviors?
But I started working on the first Joker and it crashes on launch now
Crash log pls?
I got a little help in Support, supposedly I had a typo, but when I fixed it I'm still getting the crash
I fixed the NSFS typo to NFS
Try downloading a non-dev release of Steamodded
Wait now it's saying NFS is a typo as well
NFS deals with the file system if I'm not mistaken
correct
please send the code
Also update your Steamodded. 0930a is WAY out of date.
It was working fine tho
this is an issue of your smods being old
I've been playing with mods on this version and it's been fine
SMODS.NFS is newer than the smods you have
OOOHHHHHHHH.
the guide is made with current smods in mind
OMG.
which means you'll run into issues using something older
Is there a process I need to go through to replace the version?
Yeah, it's best to try and keep up with the newest (non-dev!) version when possible, even if it requires refactoring code.
update the location for the lsp but thats about it
Or can I just take the current version out and plop the new one in.
Yep, just do this
if your developing you should use the latest version though
...I don't use dev builds of Steamodded. Am I wrong for that?
no, but it can make updating harder
Fingers crossed
Eh, potato potato. I deal with it when it's needed.
Ah. Your LOVELY is not 1.0.0, it's still in 0.9.0.
Ope!
uhh
so uh
there is no lovely 1.0.0
That didn't work DX
Wait, then what's the newest LOVELY
i made lovely 1.0.0
0.9.0 is the most recent version
are you good with computers
feli shut up /lh
follow the install guide on the lovely github
use this if you own windows
(i need feedback)
I use Windows, but I have the latest LOVELY version as far as I know.
I downloaded the newest version and that didn't work either :(
why not
what does it say now
whats the crash
I'll keep this in mind later tho
like if you dont know what you're doing i think my tool is very "i dont know what i'm doing" friendly
Oh I just forgot to remove the old version am stoopid
congrats your smarter than 90% of people in modding support
cuase you actaully noticed the issue
what does it say now
The same thing as before :(
I can't even refute that.
the lovely thing?
did you delete the wrong verison.dll?
WAIT IT'S BACK
do you mean the lovely folder
Like a haunted doll I threw out DX
because thats. thats not lovely
did you remove the lovely folder fomr your mods folder?
it just contains logs and stuff
yeah thats just an info folder
...
Yeah, that's fine if it reappears.
Sometimes you'll need the LOVELY folder as it'll log crashes.
or just use feli's thingy
can u use my thing
Okay I did it AGAIN
think
WHAT THE FUCK IS GOING ON
🤔
are you still deleting the lovely folder
yeah you shouldnt delete the lovely folder
STOP DELETING THE LOVELY FOLDER
Please stop deleting the LOVELY folder
me when i delete the lovely folder
are you even reading
It's fine, it won't be an issue
;sob:
I didn't delete it this time DX
yeah but
I just moved it OUT
its meant to come back
Yes. It's MEANT to be there. You're good.
Whyyyyyy...........
as i said it contains logs and stuff
I want the new one :(
Yea :3
you should follow the install guide on the lovely github
mu
try this if you cant read
µ
😭
Then the LOVELY folder is not what you need to deal with. What you need to deal with is known as version.DLL, which is the file that LOVELY uses.
i'm not bullying you
read the messages 😭
i'm directing you to an easy installer
I'm REEEAAADIIIING
lovely github install guide
I did the atlas on these cards the same I did for all the others but they don't appear in game?
my sibling in christ, we're trying to help you out
its so easy
yes
the shilling knows no bounds
That's all us Balatro mod devs do at some point\
its so i can display how easy it is on the ezInstaller thread
I'm sorry I'm so dumb chat
because i've seen 500 people struggle with installing this
no its fine, not everyone is tech savvy
If it's your first time doing this, you're not alone.
Is this info on replacing it DX
atlas lowercase
This doesn't look like info on replacing it DX
delete the old version.dll
what is a dx
put the new version.dll there
Just remove the old version.dll and slap in the new one.
D: + XD
o kurwa
updating is just installing it again but a newer version
Well, noted for whenever I need to know that.
and getting rid of the old one but it should prompt you to do that anyway
if not use the installer
stop shilling
:(
NOOOOO
STUPID STUPID STUPID GAHH
FOOOLISH HANDS
RUUIIIIIIN EVERRYTHIIIING /j
I'm gonna use the thingy....
BROOOOOOO
WHY IS IT TRYING TO OPEN IN MY THING
WHY
ARE YOU DOING THIS
whar
I'm SO frustrated DX
what do you mean open in your thing
did you follow instructions and click the link
insert FNAF cheer sound
I am going to CRY.
ezInstaller W
oh god
send the crash log
use amulet instead of talisman
Is that a requirement...?
its just better coded
Not required, but at this point, it's worth it.
this is unrelated in this case though
Amulet is Talisman but without the jank.
Where do I download it :0
i think it might be a good idea to solve the issue at hand before going after other stuff
but whatevr
Found it :3
oh okay
-# dear god, please let this work.
Crash log?
Same thing...
its going to be the same yeah
because as i said talisman is entirely unrelated to the issue at hand
I'll check
The weirder part is that this error is so rare that there's no other time this has been seen in the wild and submitted in the server.
i mean
WHAT
i wouldn't call it "rare"
My mind is an enigma
moreso just. likely an issue with some mod
which people dont tend to play a lot
or a combination of mods after a specific version of steamodded
My head hurts
But something like this would be from a bad hook in a mod, yes?
engine/controller.lua:774: attempt to index field 'locks' (a nil value)```
or by itself
IT'S HERE
IT'S HERE
GET TO THE GUn
LIGHT HIM UP
LIIIGHT HIM UP
CAREFUL, DON'T LET THE GUN OVERHEAT
HE'S NOT TAKING ENOUGH DAMAGE, GET SOME HEADSHOTS!
Anyway
So if my mod does the hooks and a mod like DebugPlus or TMJ is also loaded..?
I'm going to VERY delicately put my mods BACK into the folder
And it will WORK
Correct?
i mean like that depends entirely on what both of those mods are doing
Add mods in batches until you encounter a crash, then work backwards from there.
though hooks almost never cause incompatibilities
show code
My mod hooks the controller functions so that on a specific blind, all keys / mouse inputs cause a random sound to be played (except for T, 1, 2, 3, and Tab for DebugPlus & TMJ compat).
show code first
Which would be the end of the story except I keep getting #💻・modding-dev message
Well, what all does your mod add currently?
Yeah, let's start there.
A single Joker
So either the main file or jokers.lua if you're doing it in a modular-like way.
this ain't right
why is SMODS just randomly there
💀💀
in the middle of the joker
but main file please
Random ahh SMODS 💀
you messed up somewhere
bro put SMODS instead of a comma
probably autocomplete being dum
#define SMODS ,
STOP BULLYING MEEEEEE
smods is a revolutionary
,.Joker
This is who you're bullying btw
tfym bullying
maybe u should stop coding on a hpone
how would i go around getting the list of cards played in an ante, i need a list
😭
#define , SMODS
wtf
please refer to the pillar code
HelloWorld!("print")
