#đ»ă»modding-dev
1 messages · Page 156 of 1
I seeeee
Yeah that's how I'm using it.
holy shit huge?
vscode users discovering region folding
cant wait for vscode users to discover ctrl shit l
What Ctrl shit l do
stool softener
wehtn ehf bukcet shit hits fan the
how can i make a custom suit appear below the default ones instead of above
Actually I wonder if regions even work with nvim
and also not appear in the starting decks
I got bored decompiled the APK for balatro
Wonder if it's possible to mod balatro on Android to
you can't decompile the apk unfortunately
not possible
and you can't talk about modding non-pc platforms ;-)
I got it to decompile just can't get it to recompile with APK tool
hint hint
those are the rules unfortunately
it would be a pretty bad look if breaking apple's and google's TOS was allowed here
Google's probably only did that because of the modded YouTube app lol
Apple just apple
But I guess business is business
Dude gotta make money so
Understandable
yep! it's pretty configurable too
im adding a new rank and a new suit but i dont want them to appear in the decks at the start, how can i disable that?
and how can i move the suit below the other suits so it's not the first one
(no texture for the new rank its just a 2)
you have to specifically remove them from the deck yourself
...where's the soul_pos under card.children to target for :set_sprite_pos?
I have made 2 seperate mods, and wnt to give myself a joker from another mod, evertime i load that deck it crashes, but works fine when I dont try to give myself the other joker
tried using add_joker() with the key for the joker I made, the joker appears in the collection correctly as well
nvm still dont know what im doing lol
renaming every joker to joper (jopa - ass in russian) is pretty tiring work but it worth wasted time
floatingSprite, not sure of the case though
might be floating_sprite
Yeah, found a bit earlier with enough digging. Got some stuff to do with that later.
How do I go adding a joker to a deck that I created, I created the deck and it works fine, but when I go to add the new joker to the deck at start of the game it crashes, I can add other jokers fine, and the new joker does show up in the collection screen correctly
Local variables:
joker = string: "LeapfrogDeck_overunderjoker"
edition = nil
silent = boolean: true
eternal = boolean: false
(*temporary) = nil
(*temporary) = table: 0x2bd38020 {x:4.7573170731707, w:10.039024390244, y:0, h:2.6136585365854, scale:1, r:0 (more...)}
(*temporary) = table: 0x2bb1b9e0 {click_offset:table: 0x2ba78e08, children:table: 0x2ba42870, ambient_tilt:0.2 (more...)}
(*temporary) = nil
(*temporary) = table: 0x2b7831c8 {click_offset:table: 0x2b947ad0, children:table: 0x2ba40088, shuffle_amt:0 (more...)}
(*temporary) = table: 0x2bb1b9e0 {click_offset:table: 0x2ba78e08, children:table: 0x2ba42870, ambient_tilt:0.2 (more...)}
(*temporary) = nil
(*temporary) = nil
(*temporary) = table: 0x2bc7a258 {click_offset:table: 0x2b84a9f8, children:table: 0x2b81ef80, shuffle_amt:0 (more...)}
(*temporary) = number: 3.47432e-99
(*temporary) = table: 0x2be572b8 {type:modify_jokers}
(*temporary) = string: "attempt to index a nil value"```
Am I able to access the Global GAME? or can I only do it through specific functions?
G
i think you want G.GAME
I'll do some more testing, I'm attempting to get comfortable with Lovely patches since I want to make another "Currency" of sorts to micromanage. Basically I'm adding in globals and just making sure they're put in the game. I'll see if that works
if youre making a smods mod you can define globals w/o the need of a lovely patch
since its a run global you'd just need to hook the function that sets the run globals
Okie dokie, thank you
im trying to create a similar joker in the way of working to misprint, is there a way i can make the text work like that card? ive tried using the dynatext but i cant seem to make it apply
How would I go along editing the hud? I want to set the money box's width to the same size as the hands/discards and add another for my "Currency".
Try digging for how the card works in the vanilla game
And modify it from there
It's usually what I do when a card I got does something similar to a vanilla game card
Hello everyone, I'm trying to create my first mod with Steamodded.
The goal is to create a joker that scales every time the money increases during a round.
Looking at the way money is managed I have the impression that the only entry point is G.GAME.dollar_buffer but I have no idea how to manipulate that. Does anyone have any ideas? Thanks!
Something like Bootstraps?
Not really, my joker description is here: https://discord.com/channels/1116389027176787968/1230094975539089428
It's more like Campfire but is also sensitive to obtaining currency when cards are played (Gold seal, Golden Ticket, Rough Gem etc...)
A bad idea I have is to save the current money you have in your joker and with an updatefunction, if your money ever increase, modify said saved value in your joker and increase the Xmult
You just hook ease dollars
Alright, first question from me of the day: How the heck do I make these checkboxes? (how to make them appear, how to make them actually do something)
It might be because I'm exhausted so forgive my stupid questions today
In regards to the chariot, is there a straightforward way I can make it so on use it applies steel to another card at random in the deck?
create_toggle()
its in UI_definitions.lua
np
and where do I place it inside my menu?
jancky af but idk
I don't know how else one makes vertically stacked text.
Insides your nodes
Here's an example:
...
{n = G.UIT.R, config = {align = "cl", padding = 0}, nodes = {
{n = G.UIT.C, config = { align = "cl", padding = 0.05 }, nodes = {
create_toggle{ col = true, label = "", scale = 1, w = 0, shadow = true, ref_table = SDM_0s_Stuff_Config, ref_value = "limit_moon_base" },
}},
{n = G.UIT.C, config = { align = "c", padding = 0 }, nodes = {
{ n = G.UIT.T, config = { text = "Limit Moon Base", scale = 0.45, colour = G.C.UI.TEXT_LIGHT }},
}},
}},
...
thanks
hey im working on a joker mod with a couple of my friends and i cant figure out how rng works
pseudorandom returns a number between 0 and 1 based on the runs seed and the key you give it
yeah ive figured that out by looking at the example code but i cant figure out how i compare that to a whole number
(ss taken from joker example)
you dont compare it to a whole number
?
G.GAME.probabilities.normal is your "luck" factor
its normally 1 but gets doubled by oops all sixeses
im not really used to lua lol sorry, its all a little confusing
If I decide to monitor the variable G.GAME.dollars, the calculation of the mult is done before the actual update of the money so the mult cannot be taken into account for the current hand.
If I decide to use the variable G.GAME.dollar_buffer I do not get all the occurrences of change (ex: Gold Seal + Gold Card with Golden Ticker = +7 dollars and not +3 and +4).
So I do not know if it is possible to realize my Joker...
so "G.GAME.probabilities.normal / card.ability.extra.odds" here can be better written as "1 in 6"
got it
since extra.odds is 6
Try what Eremel said
you check if the pseudorandom is less than 1/6th etc
theoretically if i set the odds to 1 in 1000 this would still work right
yep
you could set the odds to 1000 in 1 too, its just usually pointless to do so
Try what Eremel said
one more question
my textures arent working correctly
and im not sure why
im pretty sure my atlas is set up correctly
Anyone know the easiest way to check if a particular instance of a joker is NOT in the overlay menu?
I'm sure there is an array somewhere that includes all the generations of the colleciton jokers I just can't find it, smh
You need a 1x and 2x atlas
do i need to add both to the atlas because i have 1x and 2x versions of the file
The 2x needs to be twice the size
it is twice the size
bocchi
make sure they're named properly maybe
Itâs not twice the size if youâre getting that issue
yeah mb i misremembered or smthn
Morning to all of you who was asleep when i was working on something cursed
You are cooking indeed
why does it look so blurry fucks sake
Meanwhile Iâm making cursed content
how would you handle should_draw_shadow with enhancements?
seems like ignore_shadow is exclusive to edition stuff
Should be able to set the property on the card in set ability iirc
Kâ ïž got real
did you put your 1x sprite in the 2x folder
after years of Baron trauma he finally decided to get real
i forgot to double the size
ah
btw if the double size sprite looks wrong
there's a script that helps make it look better iirc
Hi, i am having an error when I'm making a new deck
SMODS.Back {
key = 'poker',
loc_txt = {
name = "Poker Deck",
text = {
"No modifiers"
}
},
atlas = 'CardBacks',
pos = {
x = 0,
y = 0
}
}
this is the deck^
Thatâs a lovely deck
return {
descriptions = {
Back = {
b_poker = {
name = "Poker Deck",
text = {
"No modifiers"
}
}
},
Blind = {},
Edition = {},
Enhanced = {},
Joker = {},
Other = {},
Planet = {},
Spectral = {},
Stake = {},
Tag = {},
Tarot = {},
Voucher = {},
},
misc = {
achievement_descriptions = {},
achievement_names = {},
blind_states = {},
challenge_names = {},
collabs = {},
dictionary = {
b_joker_spaces = "Joker Spaces"
},
high_scores = {},
labels = {},
poker_hand_descriptions = {},
poker_hands = {},
quips = {},
ranks = {},
suits_plural = {},
suits_singular = {},
tutorial = {},
v_dictionary = {},
v_text = {},
},
}
this is my en-us file
I want to use my localized text at 'b_poker' in the deck code
but it errors when i put localize('b_poker")
You also donât need the loc_txt if youâre using a file
true yeah
if i have my en-us file i dont have to put the loc_txt?
now how do i make custom music for a booster pack
that sounds cool i have no idea
are you going to match the chord progression
so that in blends in
bc thatd be sick
yayyy
i found some stuff for controlling music changes at G.SETTINGS.music_control
in misc_functinos.lua there is some functions like play_sound and modulate_sound as well
i shorted the file to just what you probably care about
my music sucks LMAO
i kinda like it
is that full res lmao
Itâs the same size as any 2x texture
to make mine i just messed around in aseprite for like 30 minutes
LOL
im trying to make a multiplayer game mode
poker rules
Oh so not balatro multiplayer, just straight up poker
đ
yeah straight up poker, except each player gets a shop after each hand + they have their own jokers and stuff
wah
all players will share the deck and the levels of each hand
and to win a hand you have to beat score of the other players' hands
wuh oh
wtf
This is HARDLY done
easiest spectrum deck
Idk if i wanna add spectrum or not again
Only reason i did the stars and moons from 6-suit is because i originally did the sprites
And a lot of concepts
boss blind you have to guess the word
yeeeessss
proxima centauri b my beloved
heya, apologies if this has already been asked however many times before, but i just now joined this Discord since i was interested in making a small non-serious mod for personal use. i saw somewhere that there are maybe 3 or so different modding frameworks/APIs/injectors available for use with Balatro but i wanted to ask if there was any sort of (at least unofficial) standard among those that everyone gravitates towards and would be best to start with or stick to overall. if i wanted to make a mod, then, which one of those should i be using above any others?
i ask this from the perspective of someone who already develops and maintains a bunch of publicly-available mods for another game (Minecraft) where there is more or less an agreed-upon standard as such for what loaders/APIs to use (really only a choice between NeoForge and Fabric at the moment)
steamodded + lovely + reading comprehension
cool, so Steamodded is basically the go-to then?
yea pretty much
balamod is pretty barren
and uhhhh whats the third one
i guess just lovely on its own but you need to use lovely to use steamodded anyway
i think i might be thinking of Lovely already as the "third" option even though that seems to be a requirement anyway to inject Steamodded
at least some GitHub repo i found for cursory info listed it as such, seems odd for them to have done so
it wasnt always required
yes
Maybe the third is that weird one that cropped up last week
no
hm?
lol i like this idea for like "tarot" cards
i like the to-do list
yeah, i should do it tomorrow
attempting to add info_queue to some cards, they show the name properly but not the text. this is the setup of my localization file, it matches both the base game and cryptid localization files.
something im missing?
:3
do i need to lovely patch the game if i want to do something everytime you enter shop or is there an easier way?
god
Q is for Quagsire
how do i check which round it is
Hey, very nooby question but is there a guide for setting up the dev environment for modding? couldnt find anything in google/pins. I've never modded a game before so i really dont know where to start đ
install steamodded
cool! will do this when i get home after work đ
where can i find the info for the boss blind effect triggers? like the G.GAME.blind.triggered thing
see im there now but where do i find the contexts they use? like for example, matador looks for the debuffed hand context. where can i find the other contexts the blinds use?
ill look here too
thanks to you as well
nvm blinds don't have a calculate
oh ok
yea blinds are wacky
would it help if i explained what im trying to do?
yea
so basically im trying to have this gain chips each time a boss blind is triggered, and once you beat a boss blind without triggering it's effect the chips reset
guys how do i set something to happen at the end of the round?
Why context.destroying_hand was made to only work on scored cards? This is so sad đ
wouldn't make sense if glass cards played but not scored had a chance to break
I mean just check for the scored ones đ€·
thats how it was accomplished
that context is for sixth sense
and the other one
if context.end_of_round iirc
you can also use it on card enhancements to destroy the card
it's different in vanilla isn't it
not sure
i tried that but its not working
base game isnt exactly the same to modded
can i put it in the calculate function of a consumable?
tarot cards dont have a calculate iirc? or maybe ive set mine up wrong
but that only applies when the consumable is used i think
makes sense
isnt use the one that gets applied when used?
yea
ye
the mult comes from the calculate being called on the voucher
iirc
Thanks to smods calculate work on consumables now
Ive never seen it used
how would I apply any changes that I made to the game files after unzipping the .exe?
lovely patches
calculate is called for all consumeables and all jokers and all vouchers (that implement it) whenever any calculation necessary occurance happens
so i want to make a potion that gives luck until the end of the round and i cant seem to find how i could do that
example patch:
[patches.pattern]
target = "game.lua"
pattern = "STOP_USE = 0,"
position = "after"
payload = 'select_more = 0,'
match_indent = true```
adds a new property to G.GAME
if context.end_of_round then
card.ability.givesLuck = false
sendDebugMessage("End of round","MyDebugLogger")
end
end,```
i don't think thunderstore has 0.7.1 does it
this should be working right?
you shouldn't use thunderstore anyways but meh
ty!
Im not getting it from there
its just got the user guide
0.7.1 you can get here
https://github.com/ethangreen-dev/lovely-injector
it's almost exactly the same as the github readme tho
yea
just more outdated
can someone please help me
calculate function on consumable is not getting called
or i dont understand how it works
if context.end_of_round then
card.ability.givesLuck = false
sendDebugMessage("End of round","MyDebugLogger")
end
end,```
shouldnt this send a debug message at the end of the round?
Only if youâre holding it
What smods version are you on?
how do i check that?
Itâll tell you in the top right of the main menu
oh
you need cool epic new and improved awesome calc.....
should i update?
yes
i can just download the new one and replace it and thats all right?
ye
or do i need to change my code a bit?
been trying to figure this out still and for some reason playing a debuffed hand isnt triggering the chip gain?
ok great
so in my code if i am searching for a mod is it just find_mod?
nvm im just foolish
i downloaded the "1.0.0~ALPHA-1326a-STEAMODDED" version so this code should work now?
i mean for some reason its not triggering
do i need to have the consumable selected or something?
No it should just work
you should use SMODS.find_mod to account for provides and mods being disabled
are there any other mods that do something at the end of the round i could check out and try to fix my problem?
Can you screenshot the full consumable code for me?
What on earth is this loading system youâre using
its a custom consumable
thank you
is that maybe it?
i just saw it on another mod that had custom consumables
and tried to replicate it
and i use SMODS.find_mod in an if statment?
it works for the other consumables
not the calc function but everything else is good
Can I see where you actual define them as consumables?
look at these amazing artwork i made
gdog?
and what d othe letters do?
can't figure out how to patch the game, trying to make a test patch and it doesnt do anything (attempting to make all decks remove face cards)
oh my god abbie mindwave
i mean what does that do
Look in Mods/lovely/dump/game.lua to see if your changes are applied
My beloved (I'm not posting the sillies convention gif again I don't wanna spam)
lmao fair
oh my god
That's amazing
how fucking smart is this
no changes
thats incredible lol
this is still my proudest joker rn
Double check your pattern then
copied and pasted from the lua, dont know why it wouldnt match
Oh do they go in a different area?
Copied and pasted from the dump right
yes
No, if the pattern is correct it should work the way you have it
Thatâs why then
its in Balatro\Mods\MillionStars\lovely\game.toml is that correct
Youâll have to add your new area to the calculation loop
Welp. You know youâre making cursed content if Jimbo tells you your stuff is cursed.
and where is the calculation loop coded? which file
Yes, anything in that folder will be loaded
In smods utils.lua
hm
so in order to do that i will have to lovely patch smods?
You shouldnât need to patch iirc
You should be able to hook the necessary stuff or add to certain tables, Iâve not looked at it since aure made some changes
oh okay thanks
Okay this is probably not it, but I'm out of ideas, put a new line after priority
Oh actually itâs super easy with a lovely patch
i actually already did that after sending the screenshot just bc it looked nicer
You want to target line 1525 and add your area to the table
oh ill do that then great
so yeah not that either đ
That should make it work fully
Can you send a ss of the original code you want to inject to
before means it places the line before, you want to replace the line so put at
anyone remember how retriggering jokers work
as in what was the values i had to return
wouldnt it work either way? also i dont want my actual patch to remove face cards from all decks, im just doing that as a test
No
at least i dont think so, i dont exactly know the context of ur code and the patch
yes
anyway i did "at" and it still has no effect
does it appear in the dump
nope
Balatro\Mods\MillionStars\lovely\game.toml
try increasing priority to 15
some smods lovely patches are prio 10
and yours is 0
so
Smods is -10
idk eremel might have to double check that one
np :3
In that case you probably have another mod that's replacing that line
all other mods are disabled it's just this one mod i'm making
I guess that specific smods patch has thw wrong priority then
They're all supposed to be -10
they're 0 -5 and -10
i assume what happened here was a priority 0 patch getting applied before an SMODS priority 0 patch
what smods patches are prio 0?
imo it should be -1 not 0 so default priority is always after steamodded but w/e
joker retriggers and joker size
joker size was missed in review, oops
speaking of joker retriggers how do i do that stuff đ„Č
magic
thanks
When in doubt check the wiki
No donât do this
Joker retriggers should be moved back to -10 too
@atomic edge You target the target comment line and use a before patch
how would one fetch a table of all jokers sold in your current run
by target you mean literally target = "" or just to put the target comment into the pattern?
i believe you'd have to track this yourself
well its for a card for a mod
ok
Then your payload will just be like t[#t+1] = G.drink_area
Okay I looked and didn't find it either, but there's this #đ»ă»modding-dev message
this
Retriggers are on the calculate functions page
And apparently retriggering jokers is an optional feature now?
Yes
yeah i think you would have to track every single sold joker to make this possible
I looked but didn't find it, could you point me to where it's mentioned
i've been looking at that page for 15 minutes i mustve missed it
Oh maybe it is missing đ€
what's the base game equivalent to loc_vars? i cant figure out where the game returns stuff like max_highlighted to the localization systems
The art is sick
Its on generate_card_ui I think
In one of the function files
lemme look
Yeah retriggers checks are missing, Iâll add them to docs later tonight
Thank youuu
thanks!!
I've never touch Lua and want to start modding, any tips on what to learn to start?
This is the context though, and you just return repetitions = X
{retrigger_joker_check = true, other_card = card, other_context = context, other_ret = _ret}
Are you familiar with other languages
i love programming
learning java rn in school, but I learn pretty fast, just any concepts that I need to learn to start modding would be fine (I think/hope)
oops!
holy hell it works
absolutely hilarious that it also retriggers the destroy check on the banana
how can i make my new suit display below the default suits instead of above
To start modding I'd recommend looking at these examples https://github.com/Steamodded/examples
Steamodded example mods. Contribute to Steamodded/examples development by creating an account on GitHub.
Thanks đ
All you'll need is to get used to lua syntax if you know java
Will probably just search up some tutorials or smth
you can change money without ease dollars
im also trying to get started
trying to make it so first hand scored turns to aces
im not sure im selecting card right?
the argument for rank passed into change base should be the rank key, not any sort of suffix (which would also be incorrect in terms of what you have)
so just "Ace"
how could i change the chances of getting rare jokers / soul
also context.first_hand isn't a thing here
do lovely patches work on only segments of lines, or do you have to give them the full line?
i have this patch:
[patches.pattern]
target = 'functions/common_events.lua'
pattern = '{_c.config.max_highlighted,'
position = 'at'
payload = '{_c.config.max_highlighted + G.GAME.select_more,'
#death cannot be allowed to select 3 cards.
match_indent = true```
set up but it does not work
the targeted lines are pretty much these
pattern patches match any amount of full lines
full lines got it
you need a regex patch to partially match a line
a big block?
get the full list of all tarot cards
nah
and patch each line individually
[[patches]]
[patches.regex]
target = 'functions/common_events.lua'
pattern = '\{_c\.config\.max_highlighted,'
position = 'at'
payload = '{_c.config.max_highlighted + G.GAME.select_more,'
just use a regex
... no?
context.before uniquely identifies the context
if this is the first hand is additional information that's not passed into context
you can check if this is the first hand with G.GAME.current_round.hands_played == 0
yup, im just slow
is there a way to keep track of sold jokers in a similar way as to how stuff checks for used consumables or specific consumables
Regex '\{_c\.config\.max_highlighted,' on target 'functions/common_events.lua' for regex patch from problematic/lovely.toml resulted in no matches
hold up
lemme make sure im looking at the right game src version
you talking to me?
[[patches]]
[patches.regex]
target = 'functions/common_events.lua'
pattern = '\{cfg\.max_highlighted,'
position = 'at'
payload = '{cfg.max_highlighted + G.GAME.select_more,'
this should do on neutral prio
no
oh ok
yes, you'd have to patch/hook the function for selling a card
worked perfect thank u so much
[patches.pattern]
target = "card.lua"
pattern = 'self:calculate_joker{selling_self = true}'
position = "before"
payload = '''
if self.config.center.set == 'Joker' then
if G.GAME.jokers_sold then
local contained = false
for i = 1, #G.GAME.jokers_sold do
if self.config.center.key == G.GAME.jokers_sold[i] then contained = true end
end
if not contained then table.insert(G.GAME.jokers_sold, self.config.center.key) end
else
G.GAME.jokers_sold = {self.config.center.key}
end
end
'''
match_indent = true``` so this should work then right?
only thing left then is info_queue not working for some reason
hm actually there's something better you can do
if you take this line
localization file is set up like so and im applying it to my tarot card like this
info_queue[#info_queue + 1] = { set = "Forget", key = "m_TWT_tower" }
but it just does this
is it defined in the localization files
Yes
you can just modify max_highlighted on cfg if that exists. but it only covers vanilla anyways so this is fine either way
see first screenshot which is en-us.lua
yea i dont intend for this to work with other mods
too much variability
that's because that's not how you're supposed to make an info_queue
i copied my structure from cryptid
how would i do it for custom ones then
or is that not possible
it should work but I don't agree with the way you're structuring the data here
info_queue[#info_queue + 1] = { key = "r_mtg_reanimate", set = "Other", config = {extra = 1}} thats the info_queue
then why it no work?
object_type = "Consumable",
set = "Magic",
name = "mtg-reanimate",
key = "reanimate",
pos = {
x = 7,
y = 4
},
atlas = 'mtg_atlas',
cost = 3,
order = 8,
config = { },
loc_vars = function(self, info_queue, card)
info_queue[#info_queue + 1] = { key = "r_mtg_reanimate", set = "Other", config = {extra = 1}}
return { vars = {} }
end,
can_use = function(self, card)
return (G.GAME.jokers_sold and #G.GAME.jokers_sold) and (#G.jokers.cards < G.jokers.config.card_limit or self.area == G.jokers)
end,
use = function(self, card, area, copier)
local used_tarot = copier or card
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.4, func = function()
play_sound('timpani')
reanimate()
used_tarot:juice_up(0.3, 0.5)
return true end }))
card_eval_status_text(card, 'extra', nil, nil, nil, {message = localize("mtg_reanimate_ex"), colour = G.C.BLACK})
end,
}```
Try putting it into Other instead
or wherever a reference to the prototype object is
and yes reanimate is defined
Its definitely fine to do it this way
To put custom text rather than a specific object
that's not what I'm saying, with Other set this is fine if there's not an object the description is tied to
but passing the prototype is the encouraged way for every vanilla set, even seals
Ah I see, I didn't notice they were trying to put an object
what am I even supposed to make of that
you're just throwing code at me at telling me something isn't working
sorry my bad ```function reanimate()
if #G.jokers.cards >= G.jokers.config.card_limit then
--Maybe tell the user there was no space?
else
local created_card = create_card('Joker', G.jokers, nil, nil, nil, nil, pseudorandom_element(G.GAME.jokers_sold, pseudoseed("mtg-reanimate")))
--Previously, it also made the joker negative, but I think this is too strong
--created_card:set_edition({negative = true}, true)
created_card:add_to_deck()
G.jokers:emplace(created_card)
created_card:start_materialize()
end
end```
thats the function that does not seem to be working
i still don't know what about it isn't working
it is not creating any jokers even sold ones, as thats what the function is doing
where are you calling the function
here
assuming i am understanding your question right
does it reach the else block?
it was working before even in new calc, and now it doesnt
i have not ever touched it
Hmmm what effects do that?
Not sure if anything in the vanilla game does but DebugPlus's money command doesn't use it, and some mod might want to manually ease it for a nicer effect
Eh, I wouldnât expect debug commands to trigger joker scaling
I guess thatâs true, though a slightly different use case
but at quick glance I don't belive anything in the vanilla game, debug or not sets the dollars manually
but I would worry more about mods doing stuff incorrectly
I wonder if there are any mods that donât use ease dollars right now
other than me
looking through a quick github search seems like noone is setting the value manually other than a couple of people patching ease_dollars
Hooking would probably be the ideal way then rather than clogging up update with a constant check
actually looks like betmma does it in a voucher
although it's a weird case
oh looks like one of our example mods uses it for a cheat
Thatâs an interesting effect
I think we need to have a clean up of the example mods at some point tbh
yeah
some probably should be removed and all should be migrated to json metadata
oh found another mod using it manually https://github.com/Aigengoku/Othermod/blob/7afa32688e9955c5ba2a2efe583e89b01f7ab5a1/Othermod/Others/Othermod_Tarots.lua#L156
anOthermod. Contribute to Aigengoku/Othermod development by creating an account on GitHub.
in a couple of the consumeables
I donât think other mod even works xD
Another mod (looks like it's at round creation so probably won't matter here) https://github.com/kjossul/NeowBlessings/blob/51da84d65c42bc63631a12683374e3dd02d7ad9d/neow_blessings.lua#L204
but yeah that seems to be the entirety of uses of G.GAME.dollars across github
so yeah hooking ease_dollars is probably a good method
I think all those ways could be rewritten to use ease dollars too if necessary
yeah
Apart from the betmma one which should probably just lovely patch the interest calculation
iirc there was a few weird behavious with ease_dollars I didn't want with DebugPlus
ease dollars has an instant option for betmma's use case
hey, I'm wondering if there's a way to give myself a joker in a run for testing purposes
Maybe the high score parts?
(specifically if money becomes infinite then ease_dollars cannot get it out of that)
DebugPlus lets you do this
okay thanks!
Anyone know why this is running twice?
calculate = function(self, card, context)
if not context.game_over and context.end_of_round and context.cardarea == G.jokers then
if pseudorandom("boingular_roulette") < 1 / (G.GAME.probabilities.normal * card.ability.extra.odds) then
ease_dollars(-G.GAME.dollars, true)
extinct(card, "Blam!", nil)
else
return {
message = localize('$')..card.ability.extra.reward,
dollars = card.ability.extra.reward,
colour = G.C.MONEY
}
end
end
end
Add context.main_eval
Instead of the area check
Area checks are only really useful on playing card effects
Got it, what's weird is it only applies once now but it still shows the message twice
Interesting
You just need the dollars in the return, no message
Like jokers will always be evaluated with the cardarea being jokers
So itâs kind of a redundant check unless youâre moving them around to new places
hello! i dont mean to interrupt, but i still have a problem with my joker's text boxes
i managed to create an event that blocks the event queue which is what i needed to do in order for the text boxes not to be interrupted, however even though the text boxes are in a different queue, they still dont show up. heres a video to show what the issue is
its so close to working, i just keep having this same strange issue
show code
There's so many things I need to consider right now, remove/changing some calculate return, changing the area check by context.main_eval. Makes me wonder if I'm missing anything else.
what does jcbb_add_speech_bubble and jcbb_say_stuff look like?
does context.after support context.open_booster or is there another way to do something AFTER a booster is opened?
apologies for the hastebins, i dont have nitro so i cant fit the code in one message
pretty sure after is just for jokers, but maybe you can do it with the event manager?
oh sure sure, so set an event to trigger after an open_booster check?
I ask because context.after added support for seals recently
wondered if it extended to other events
i think
granted my knowledge is pretty limited
hastebin is goated
Say stuff is making an event in the base queue so it's being blocked
I'll have a read of the events manager api
oh shit is that it?
does anyone free know how i would set a variable to true ONLY after a boss blind's effect is triggered? like it stays false if it wasnt
look into matador
It has a special context
i was there already but i dont know where i'd change the variable's state
i think it's context.debuffed_hand
no ik i have it already like
calculate = function (self, card, context)
if context.joker_main then
SMODS.eval_this(context.blueprint_card or card, {
chip_mod = card.ability.extra.chips,
message = localize{
type = 'variable',
key = 'a_chips',
vars = {card.ability.extra.chips}
},
card = card
})
end
if context.debuffed_hand then
if G.GAME.blind.triggered then
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain
return {
message = 'Silver!',
colour = G.C.CHIPS,
card = card
},
end
end
end
how does SMODS.find_mod work and for example lets use a mod prefix of abcd
in the debuffed_hand branch just set your variable to true
have it default to false no?
im trying to have this so it can trigger a chip reset if the boss blind isnt triggered
ah so you have to trigger the boss blind's effect every hand otherwise the chip gain goes back to nought
you
maybe have an else underneath that
what do you mean by 'can' - randomly or through some other effect?
it either will reset or it won't based on what you design
rn it's just adding chips everytime you trigger a boss Matador style
so under what circumstances do you want it to reset?
when you trigger a boss blind set one of its abilities to true eg. card.ability.triggeredBlind, and then make another context.end_of_round and check if card.ability.triggeredBlind then give chips else reset
imo
oh sorry I might have misread, you want a boss to have been triggered at least once
yeah then this sounds logical
remember to set the bool at the end to false again
yea fact
If you need to talk through some stuff Iâm more than happy to help
bc loc_vars don't reset to defaults on repeated calculate calls
i suppose you could just make it local
if context.debuffed_hand then
local iscareset = false
if G.GAME.blind.triggered then
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain
return {
message = 'Silver!',
colour = G.C.CHIPS,
card = card
},
else
iscareset = true
end
end
this is what i have so far, something like this?
like
defining a variable = global by default
writing to a variable = local by default
accessing a variable = local by default
defining a variable in a for loop = local by default ????
make it make sense
it is weird
This will only ever trigger if the boss blind debuffs the hand
but at the same time i get it?
i want to have celestial packs always contain the planet of your most used hand if a global variable is true, i applied a patch to the place in card.lua where it creates the planets and checks for telescope and added it but it doesnt seem to work, can anyone tell me why pls?
well it's for debuffed hands
- for loops
doesn't context.debuffed_hand trigger on every boss blind effect regardless of actual debuffs, like if you play 4 cards agaisnt the psychic that triggers it
the 'debuffed' nomenclature is a bit confusing
Triggers when a boss disallows a hand yeah
Nothing to do with debuffs in the sense of debuffed cards
it was originally gonna be for whenever one is triggered at all but i dont think thats possible
at least with how this is setup idk
There isnât a âboss triggeredâ state so youâd have to hard code it manually like matador does
but matador only does it for played hands?
you'd probably want the local outside the if context.debuffed_hand branch and then just set true inside if it is entered and then you'll need an extra bit after that actaully does the resetting of the chips
i see
if you declare the variable and don't define it it will return nil which is falsy
so the check later on will skip it
So you want it to scale if you play a hand thatâs not allowed by the boss, and reset if you donât?
yes
Youâll have to set two flags within your extra table then, one for whether itâs a valid boss and one for if youâve triggered it
but not like an immediate reset like play at least one hand that triggered it (so youre not just screwed)
i see i seee
how would i start going about that?
Youâd want the valid boss flag to be false unless youâre playing a boss you can trigger in this way, so you can set that in context.setting_blind, use context.debuffed_hand to set the triggered flag, and then context.end_of_round to check that if the valid boss flag is true that youâve triggered or not to reset
`local triggeredBlind
if context.debuffed_hand then
if G.GAME.blind.triggered then
card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_gain
return {
message = 'Silver!',
colour = G.C.CHIPS,
card = card
},
end
triggeredBlind = true
end
if context.end_of_round and triggeredBlind then
card.ability.extra.chips = 0
end
`
shouldn't this just work
You could maybe drop the valid boss flag if you just do the check in end of round
sorry should have the last check be end of round as well
if anyone has free time i would appreciate a quick look
Not at all, that final block will never be entered
i edited it
i might have missed an end
I know
but you get the idea
Itâll never be entered because youâre checking a local value that starts as false
I also donât think you can ever get it set to true like that
Debuffed hand should only ever be called when the blind is triggered
iirc
so including the one i already have, i need to set up a different variable that will toggle depending on whether or not the boss is able to apply to the joker? and that'll go in a different context? (context.setting_blind)
then the flag that i set in that setting gets checked at the end of the round? or am i misunderstanding?
@sonic cedar you get the idea though, the valid boss check is important aswell bc otherwise bosses that can't access context.debuffed_hand just unfairly reset you
qwa
Yea thatâs one way of doing it, you can also just check that the boss was valid in end of round if youâd prefer
is SMODS.find_mod formated like if SMODS.find_mod("mods id") then ?
that sounds way easier actually
is there an example i can look at, or is this more of a figure it out situation?
can global variables declared in my mod code be seen by functions of the games code, or do i need to add a prefix or something
stuff about it here
https://github.com/Steamodded/smods/wiki/Utility#mod-facing-utilities
js does thisntoo
is this updated to account for new calc
you should use your mod prefix
thanks
if you're not using const/let people will SCREAM at you
i believe so?
â€ïž
i dont think new calc does mess with this stuff, but there have been stuff where things were messed with and i didnt think it would
yeah new calc doesn't mess with that
it's if next(SMODS.find_mod('id')) then as it's always been since that util was added
ok
i see i see
my mistake i apologize
can someone please help me here im dying
i even put debug messages above the ingame code to see and it seems like it doesnt even come there
if only i knew anything about patches
maybe you have it routed wrong somewhere?
i have no idea why it wont work
i did the simplest thing in the world
just add another bool to an if
you spell âtiltâ and it skews the screen slightly
not like i coded anything
is forced luck the variable?
yes
what if it said forced_luck = true itâs something
Probably just a figure it out yourself
but for some reason its like the game isnt even going through the code i changed
alrightyighty
does it work with the voucher still?
yes
but even with the voucher
it doesnt send the debug message i put after the if
so i think some other mod is changing the behaviour here or idk
Are you looking at the lovely dumps to make sure your patch applied?
does info_queue not work on decks...? im getting a crash when i try to use it
name = "Filmmaker's Deck",
key = "film_deck",
pos = {x = 0, y = 0},
atlas = "atlas_decks",
config = {
voucher = "v_directors_cut"
},
loc_txt = {
name = "Filmmaker's Deck",
text ={
"Start with {C:red}Director's Cut{}.",
"{C:attention}Boss Blind{} reroll cost is",
"reduced to {C:money}$5{}.",
"Any {C:attention}Boss Blind{} can appear",
"on any {C:attention}Ante{}."
},
},
loc_vars = function(self, info_queue, card)
info_queue[#info_queue+1] = G.P_CENTERS.v_directors_cut
return {}
end,
apply = function()
G.E_MANAGER:add_event(Event({
func = function()
return true
end
}))
end
}```
i am and it did
I donât believe it does, you have to use {T:key} in your loc txt
if you see here i have two debug messages one in and one out
and even if i buy the voucher
the effect of it applies
but the debugs dont trigger
why is that
and btw this is the lovely dump one
What do you mean by the effect applies?
i mean the voucher works
in game
i thought if i buy the telescope voucher and open a celestial pack it would have to send me a debug message beccause it does all the things under that
idk if thats imporant but the console does spam "etperpoll1"
Oh smods takes ownership of packs so itâll never reach that stage
You need to patch into game_object.lua
oh my god
thank you so much
the wizard of coding haha
wait how do i lovely patch into code that isnt in balatro archive?
do i set the target for the full path on my pc?
i dont check this discord much anymore, but when i accidentally clicked, i saw this, im actively sobbing? weeping, crying. im grovelling. a true scribblenaut
no, there's a specific format
target = '=[SMODS _ "src/game_object.lua"]' in this case
thanks bro
_ is for steamodded itself, for other mods it'd be the respective mod id
okay so since the event happens when not_first is false, i thought to make not_first true
this causes the say_stuff to happen at the correct time, but it also causes text boxes to not be displayed at all, regardless of if theyre being blocked or not
very strange
had to read that message over again, woops
how to check the information about the consumeable here like tarot or spectral?
context.consumeable is the card used
so for example context.consumeable.ability.set will give you what kind of consumable was used
ah thank you!
i understand, its because said event is what causes self.children.speech_bubble.states.visible to be true
without that event, it remains false, thus the speech bubbles do not become visible
just try puttin them in a different queue
so what is the issue?
this
i think i might have a solution though
so put it in a different queue
already tried that, doesnt work
which queue did you put it in?
"other"
well that queue is currently being blocked as well by your other events
ohh, i didnt think of that
either make your other events not blocking (they don't seem to need to block anything) or use another queue
for testing the tutorial queue should be fine
you should be able to make your own queue if you need it
lemme see if this works, i also thought of something that seemed to work as well so this is very promising
i might finally get over this problem thats taken me a full week to find a solution to
oh my fucking gooooooooooooood it WOOOOOOORKS
this might be one of my proudest creations in this game
what the hell is that đ đ đ đ
balscrabble
you spell polychrome and all those are polychrome
set_ability(G.P_CENTERS['string'])
do i need a prefix
G.P_CENTERS.string
or do i need prefix either way
or more or less set it from name
let's see if this works
:/
i mesed u lmao
yeah string.split isn't real
hello smart people of balatro is this correct blueprint code because the last few times i tested it it retriggered the joker once as if it were a normal retrigger then retriggered it again but correctly doing the blueprint animation
i wish
i think you can use string.match with lua patterns
or
i've found this somewhere
function string:split(pPattern)
local Table = {} -- NOTE: use {n = 0} in Lua-5.0
local fpat = "(.-)" .. pPattern
local last_end = 1
local s, e, cap = self:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(Table,cap)
end
last_end = e+1
s, e, cap = self:find(fpat, last_end)
end
if last_end <= #self then
cap = self:sub(last_end)
table.insert(Table, cap)
end
return Table
end
pretend the functions are real
if it's not real, just pretend it is
speaking of string methods I have a string.trim method in DebugPlus's util
let's go
https://github.com/cg-223/toomanyjokers/blob/c290c4ab71dbfaff08187d779f6ec9511ee7217b/TMJ/1utils.lua#L1
i use this, only comma for delimiter but can easily be modified
scribblenauts behaviour
Lemme know when the repo is updated w/ this, really want to give it a try
this son of a bitch has been making me feel like a completely incompetent moron for the last 5 days and i don't know how much longer i can take it
i need to know something else real quick!
i saw someone post how to scale delay with game speed but i cant find it again, so does anyone know how to do it? i think it involves multiplying the delay by the game speed but im not sure how its done
delay scales with game speed by default iirc
Something like this? delay = G.SETTINGS.GAMESPEED*0.05
you'd use a timer value
if it's not by default
so i had to do a few things but ive returned
tried a few things
are the variables in the context on the guide required or just examples?
if context.setting_blind then
{
cardarea = G.jokers, -- G.hand, (G.deck and G.discard optionally enabled)
setting_blind = true,
blind = G.GAME.round_resets.blind
}
if so how do they work exactly?
They asked for a delay with game speed đ€·
er, i meant scale so that it remains the same regardless of game speed!
Well here you go
ah yeah you use timer
hang on
timer - string: The name of the timer to use. Default is "REAL" of created while paused (or with force_pause) otherwise "TOTAL". Can take any of the keys in G.TIMERS.
i tried setting that up in my calculate function but apparently lua really doesnt like that for some reason
so use timer = "REAL" in your event
wait did I make that spelling mistake in my guide?
(you can also use force_pause)
true chat
also i thought eremel wrote that one
They're not required, it's to explain which variable are available in said context
nah eremel put it on the wiki but its just copy pasted from my gist
weird question: as someone who took a beginner java class 5 years ago and retained almost no knowledge of programming, where can I get started if I want to make a Balatro Mod?
No no, the table is just all the values that the context has
ah gotcha
ohhhh okay
im pretty sure cardarea pertains to which cards to focus on
but what about the other 2?
Learning lua is a good step and checkout https://github.com/Steamodded/smods/wiki/Your-First-Mod
(I should link the lua manual in this wiki page)
in an hour.
thank you 
So in that one, cardarea is the area in which the evaluated card is, setting_blind is always true (and is how you identify this specific context) and then blind will contain a reference to the blind
can't wait to spell negative
Totally not making real playing cards in balatro
apparently holo is not a real word
it's slang
why7 is everyone just flexing on my ass bro đ
i thought i sent this already but here
I might've missed it
thanks!!!!
np
nvm ignore me lua programming is destroying my fucking brain
lua my beloved
lua will do that to ya
so if i wanted to set mine up, the evaluated cards would still be jokers, and a reference to the blind would just be a storage of which bossblinds apply to the joker?
I don't blame you. I'm over here creating my own 600 suits at this rate
can someone help me fix this piece of shit i am going to lose my fucking mind dear god
is that not correct behavior? it looks like it's triggering ok
i mean it DID wait until all cards were scored
in fact i just updated it rn
Crap just launched a game, will try after in a bit
Send code pls
the problem is that it's retriggering the guy on the left 2 times and the one on the right 0 times
ohhhh
i will be going to sleep please report bugs in #1326135270759993364
this is the whole thing i think im gonna go take a break before my brain melts and drips off my left ear
you just need to check if context.setting_blind and then you can use context.blind to access the blind if you need to, but you can also access it directly in different contexts
when is it supposed to switch?
basically it should switch after all cards are scored and then again at the end of the main joker stage
except i think i simplified it to just switch when it itself is triggered during the main stage
and forgot to change the desc
and forgot i did that entirely because my brain is dying
so it retriggers the joker to the left during card individual scoring and the joker to the right in joker scoring?
you'd have to patch the sprite switching into the scoring play loop
i
oh god
otherwise the timing would be incorrect
patching is so scary i have never done any kind of significant patch
the actual calculation though is pretty simple I think,
me who patches every time i see the game code i can't hook:
you can do it!
it's not that scary
well the regex patches are scary but you probably don't need those
from what i understand, G.GAME.round_resets.ante is just a number with the current ante, right?
patching is so easy i patch way too much
my only balatro modding experience is making a few mediocre jokers with occasional and very messy use of the event system
i did one of those
is there an explanation of this that doesn't hurt my head trying to wrap my 3 brain cells around it possibly
patching easier in some ways (but more risky) because you can just hijack Balatro instead of being nice to it with smods
bumping this
personally id find the code for the red seal and do a lil bit of ctrl c ctrl v
goated program
being nice to it with... the mod that famously frankensteins the insides of Balatro?
The facade pattern (also spelled façade) is a software design pattern commonly used in object-oriented programming. Analogous to a façade in architecture, it is an object that serves as a front-facing interface masking more complex underlying or structural code. A facade can:
improve the readability and usability of a software library by maskin...
trying to be nice with smods but I'm at my limit
I say give smods a taste of its own medicine
tbh lovely only is super tempting for some stuff
sometime I just want to say screw all other mods I will modify balatro how I liike
Okay so, calculation happens at lots of different times, and your calculate function is called everytime the game tries to calculate something. For the game to differentiate between the different timings, it uses the context table. This table is made up of 2 types of things generally, flags to help identify the timing of the calculation, and objects that are relevant to that calculation. The docs you're referencing cover all the contexts that are called in the game, set out as a condition you can copy to identify that context, and then the structure of the context table in that timing.
as the main developer of the most widely used lovely-only mod, i agree
I wonder what the second most widely used lovely-only mod is
no
do mods that have some amount of support for smods but work without it count?
but also theres a repo in there