#💻・modding-dev
1 messages · Page 673 of 1
yeah but if those can appear in the shop for example you would need logic for that
ohhh
for it to like
go into that spot?
that makes sense okay
ill figure it out trust
i have that in my mod but its pretty spread out between a bunch of files so its not easy to link to as an example lol
would there be any way for an achievement to track how many times check_for_unlock has run? and then the achievement only pops if the tracker reaches a certain number?
you can hook it to add a counter to it probably
actually on second thought, there's probably an easier way to make my idea
just an achievement that only unlocks after all other achievements are collected
would prolly still need hooks one way or another but i feel like i'm thinking about the achievement tracker all wrong
what's the best way to have a pool other mods can add onto if the object isnt part of smods.center?
is there anything specific you want to do with it? pools are just tables, other mods could just add to the table
most of the time you want to make some kind of function that initializes the object like smods does so your mod handles all of that and other mods can just define new stuff
like how smods does?
does smods do something specific outside of just defining a table? i was just thinking it would be used as a restriction of like "if this is true, only this type of tag/blind can appear"
the only other thing i would want is that if it's possible to have a variable in the object and it's added to the table automatically like pools
Does anyone know a mod/reference with a UI aligned on the bottom like the shops and blind selects? aligning always seems to put the top of the ui peeking out the bottom but growing it vertically seems to grow it downwards?
the tagged cards are added to G.O_CENTER_POOLS.pool for example
yeah you can look into how smods.center does it but it's just adding the card to the table on inject iirc
is there any way for a blind to destroy a held card?
yeah, at what timing?
after a hand/discard is used, like the Wheel
well the problem is that the wheel has its own context for flipping cards lol
what's the exact effect?
well i want a 1 in 4 chance for held cards to get destroyed after a hand or discard is used
you would need to loop through G.hand.cards and check the probability for each card
idk what context tho, there isn't really a good context for after a hand or discard is used, the closest is context.hand_drawn but that only happens if a card is drawn
what about context.destroy_card?
could you get behind it happening as soon as you click discard?
i mean, i could
but it's better imo for the player to watch it burn away infront of them
to really sell the fact that it's gone for good
the discard animation would be too fast for you to even notice
actually i think i did something similar but with discarding cards instead of destroying, let me check
How do I cap the -score requirement on a rekoj that scales it to -50%
if card.ability.extra.minus_score < 0.5 then
-- scale code
end
it's basic programming logic
if i wanted to make a joker effect that does something like give bonus chips to cards converted by a specific tarot, how would i go about doing that
i imagine i could do something with context.using_consumeable...? or however it was called, i forget. i haven't messed with this context in a while
i mean i dunno how you have it actually implemented
but i assumed the stored value was a decimal that equated to a percentage. if it's not that then your coder should know what to do
whatever corresponds to -50%
ok yes so 0.5 does equate to 50%
you'll need some extra code when it actually scales to make sure that it doesn't go over 0.5
put some critical thinking to use
it's currently scaling by 0.2, or 20% each time
so it can jump straight from 40% to 60%
how do you prevent that
It scales by -0.2% for every $ spent during the ante
oh so it's literally the percentage
ok so you don't need the extra code, but you should cap the variable at 50
<@&1133519078540185692>
I don't need much critical thinking for that do I
interesting, i've never heard of a balatro mod called 'girls' before
it's called "replacing the 0.5 with 50 in the code snippet i gave you"
Alright
i'd imagine you havent, it's quite "riske" so it doesnt get publicity much lol
I wonder if riske is a misspelling or a regional spelling cuz it looks like it could be both
regional variant from upstate new york
Alright I actually fell for that one
i will say the origins are from the french /gen
oh not in utica, no, it's an albany expression
I learned it as 'risque'
its risqué
riske doesnt exist in the english language
bump
its unaccented version though "risque" is
spelling is often not my forte, forgive me lol
It would've been funny if you spelled it as fortay on purpose
it would be very funny
i'd argue it's funnier to write it correctly cause of irony
[Insert bizarro hack emoji]
ngl bro, im still a lil confused with that explanation
you want it to give bonus chips to cards that have been affected by tarot cards??
is that right?
as an example, yes
the important part is specific tarot cards. so going by consumable key, not type
context.using_consumeable on refers to a consumeable and its area, not the card its used on
damn.
i was hoping it would have the cards used on
G.hand.highlighted
oh true
ooooh
-# ...i also forgot how to get the consumable itself in context.using_consumeable
context.consumeable
...or i could look at the calculate functions wiki tab that i've had open for the past week. that'd be good if i did that
did you know that the smods wiki has really useful info?
is it normal that when I change a seal through the before context it doesnt update like it keep the effect of the previous seal
are you doing it in an event
yeah but I though that it will update between before and the next context
the entire calculation cycle happens before any event is ran
so anything you put in an event happens after calculation, putting an event in context before only makes it play the animation before events in later contexts
yeah its working if I remove the event but my animation is wacky
do u know how I could fix this
im pretty sure theres a way to delay the application of the seal for that like there's for enhancements and editions but idk what it is sorry
@daring fern he could probably know that since Seals On Every ?
Yes, you would just do card:set_seal('modprefix_key')
yeah I know but like I change a seal during the context.before like its effect need to happen during the main scoring and like after it change back to its original seal in the context.after but I cant use event cause the effect wont happen and its just the previous seal effect that will trigger and by not using an event my animation isnt working
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.4,
func = function()
_card:juice_up(0.3, 0.5)
return true
end
}))
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.15,
func = function()
_card:flip()
_card:juice_up(0.3, 0.3)
return true
end
}))
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.2,
func = function()
_card:set_seal(G.P_SEALS[_card:get_seal()].giga_data.seal_upgrade, true)
return true
end
}))
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.15,
func = function()
_card:flip()
_card:juice_up(0.3, 0.3)
return true
end
}))
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.2,
func = function()
G.hand:unhighlight_all()
return true
end
}))
delay(0.5)
end```thats my original animation
Yes, it would just be card:set_seal('modprefix_key') without any extra inputs.
oh
ok lets try it out
ok its near its just that the previous seal disappear before setting the new one
Yes, you would have to hook SMODS.DrawSteps.seal.func if you want to fix that.
i wouldn't bother with that
just set up some events to flip the card while the seal gets changed, like how the spectral cards do it
No, the spectrals don't flip the card when setting the seal.
ok
point still stands
yeah thats the problem
my animation when upgrading a seal is that its flipping the card
cause just setting a new seal when upgrading isnt cool
hm, ok
do you think I should just change the animation entirely
is there an SMODS method i should be using instead of the vanilla Tag(key) to create a new tag?
that suggests no
i agree with whoever wrote that website
thanks. i think it would have been nice to find info about what related methods exist in the relevant SMODS wiki pages. i've seen often someone will say something like "you should use this SMODS method instead" but the method isn't mentioned in the wiki for that type of card or object
does anybody know the background colour of the vanilla cardareas
i want to start adding some stuff about vanilla on the wiki but recently i tried to add all the smods methods to the wiki so if something isnt in the specific class page or Utility then it doesn't have one
black
:3
0.1 alpha
oh peak ok
i dont recall offhand at the moment which ones it was. but if i notice a method missing in the future ill bring it up then so we can get it in there. (not trying to step on any toes, i just like being able to reference the wiki instead of bothering y'all)
now that im an smods team member wiki things will get merged so dont be afraid to post an issue or PR there :3
add_tag{key = "tag_modprefix_key"}
that too
thanks, i actually needed to store the tag first to modify it's config. but i am using that to add it once its ready :)
lowk
how do i use this im so genuinely lost
bg_colour = {0,0,0,0.1} does not work as expected
well then its just displaying wrong 😭
why are you not clear
😭
well that is neither 000000 or 0.1 alpha
and the code is just a direct copy of the code here wiuth the bg_colour = G.C.RED line removed, and the position changed
this is how that exact code with that line removed shows up for me
what
yo let me try it
did you restart the run?
yeah
function SMODS.DrawSteps.seal.func(self, layer)
if self.ability.delay_seal then return end
return drawing_insanity(self, layer)
end```
like I tried this but it doesnt work
i fixed it!!!
what was the issue
works on your machine
wait, isn't that already done
yo now that i made a card area, is there a way to hide it
my_card_area.states.visible = false
You would have to set the seal back to the old one before running the function then change it back.
oh ok
Using self.seal = seal not self:set_seal(seal)
like so
No, seal would be the seal that it had, which you would get by setting a variable on the card before you set the seal, and you would use that.
oh ok yeah mb i am dumb
when defining a collection page, how do i apply a shader to every object in that page, like vouchers?
Currently i'm just using SMODS.card_collection_UIBox to define the page
take a look at joker collection
I tried that but it doesnt
like .prev_seal is set to :get_seal of the card at start
i am curious about the upcoming additions/changes to smods' custom cardarea support in respect to where multiple mods all decide to put cardareas in the same or overlapping locations
i dont know how smods could solve that tbh
my opinion is that anyone playing more than one mod at the time should be excommunicated
Vouchers use an SMODS.DrawStep to draw the shader on every voucher.
Yeah that makes sense
i will probably restrict the totem cardarea to certain decks anyways
running jokerdisplay and cartomancer at the same time: straight to jail
where does that put me with like 70 mods enabled at the same time?
hell
does that mean anyone using lovely AND steamodded at the same time should go to jail?
oh dw, i plan to add so many more tmrw :)
did you add mine
which one is urs
i dont think ive gotten to tht one yet
handy and unblind? also jail
steamodded, lovely, galdur, joker display, carto, handy, and unblind? go to hell
ooo nice, that should add a lot more to the 3000 jokers i already have downloaded
how do you keep track of how much money is spent
From the entire run or just when you obtain it?
trying to make a joker wherein if you spend enough money, it gives you an item from the price tower.
5 = tarot, 8 = planet, 10 = spectral, 12 = common, 15 = uncommon, 20 = rare, 50 = dreamy, 100 = legendary, 1000 = rare consumable.
if context.money_altered and context.amount < 0 then
card.ability.extra.money_spent = card.ability.extra.money_spent - context.amount
end
<@&1460584319486791871>
Hey folks, are there any resources for learning to mess with Balatro's existing UI? I've practiced in Config but I want to be able to add stuff to the existing ui, in particular at the moment I want to add a row above the scoring area and below the blind/shop sign
I see there's a replace_ui variable but I haven't looked into it yet
https://github.com/Steamodded/smods/wiki/UI-Guide#creating-a-uibox
other than that just reading the code and figuring stuff out
there's no API for it, you would need to either patch or hook the functions that create the ui and insert your stuff there
chat, how the heck do I utilize this function?
-# I am certainly not understanding the documentation.
Alright, I'll look into hooking as I'm not familiar, thank you
Would it be a viable plan to copy an existing UI and save it to a variable, delete the original for the rest of the session, add a node under where (haha underwear) I need it, and load mine in for the rest of the session?
I don't know how to do the node-adding to an existing structure but it gives me a goal to work around
function SMODS.debuff_card(card, debuff, source)
debuff = debuff or nil
source = source and tostring(source) or nil
if debuff == 'reset' then
sendWarnMessage("SMODS.debuff_card(card, 'reset', source) is deprecated")
card.ability.debuff_sources = {};
return
end
card.ability.debuff_sources = card.ability.debuff_sources or {}
card.ability.debuff_sources[source] = debuff
SMODS.recalc_debuff(card)
end```Here is the source code
Looks like you input the card you want to debuff in card, debuff seems to be a true or false as in whether it should be debuffed or not, source is what debuffed the card, probably used for checks
you can do that but I wouldn't say it's any easier than patching
What would patching be in this context, sorry
What is the source for blind debuffs?
Depends on the blind I'd wager
Check Balatro's source code
source is just a unique string
it's basically a password, if you want to remove the debuff you need to use it
It could be anything you like, yeah
same but you would have 'prevent_debuff' as the second argument
you would need the source to remove that prevent_debuff too
any and all debuffs, regardless of its source.
ah
what's the goal?
because if you want to prevent blinds from debuffing the better way is to use the context
Chitotty
what i said is probably the easiest but you need to remove the prevent_debuff after the hand is played
so like
-- before play
SMODS.debuff_card(card, 'prevent_debuff', "source")
-- after
SMODS.debuff_card(card, nil, "source")
kk
localize { type = 'name_text', set = "Other", key = 'modprefix_[key in lowercase]_seal"}
what about vanilla seals?
same but without the prefix
do i have to convert Blue to blue_seal manually?
yes
okay... 😔
earlier someone mention i can make a vanilla pool by iterating through all loaded jokers and see if it has no mod associated
how would i check if a joker has a mod or not, how do i iterate through the jokers, and should i do it that way instead of just going with a hardcoded list
since the more mods a player has the worse this approach get
are you iterating through a list once to get vanilla pool? then it wont be resource intensive
SMODS.ObjectType({
key = "vanilla",
default = "j_joker",
cards = {},
})
local SMODS_injectItems_ref = SMODS.injectItems
function SMODS.injectItems()
SMODS_injectItems_ref()
for i, v in ipairs(G.P_CENTER_POOLS.Joker) do
if not v.original_mod or v.original_mod.id == "Balatro" then
SMODS.ObjectTypes.vanilla:inject_card(v)
end
end
end
A hard coded list would also work
yeah i just need a pool with the keys of every vanilla joker
which i guess isnt a readily available class in smod
taglist when
#1477838185919807620
if anyone's willing to help program this (and by help i mean be the sole programmer because i cant code for shit lmao)
whats a good way to store global utility functions? I previously just stored them in some files and assigned them to MOD_SINGLETON.UTIL, but i understand that that makes them scattered.
im not sure if there is a header-like thing in lua to store them all in one file? should i look into Lua LSP and somehow autogenerate a file with all MAP.UTIL functions?
that's not how you store a function
usually if you have utility functions you just write them all in one file and load that file first
saving them to the mods singleton like you did is usually what most people do
this is mine for example but i also have like a trillion other functions in their respective files
https://github.com/nh6574/JoyousSpring/blob/main/src/utils.lua
ok to select a random card from the pool, can i just use psuedorandom_element on the pool
like not spawning a card from the pool, just grabbing a key from the pool
checking for if sold card is a joker
actually wait, what if eggman got the sell value of the joker i sold?
if you use get_current_pool() it returns key
if you use G.P_CENTER_POOLS it returns the center
so get_current_pool is the door, G.P_CENTER_POOLS is the house?
can say so
more clarification
does owning jokers affect what can be pulled from the "custom" pool
it's fine if it does but for my purpose it would be funnier if it didnt
if you use get_current_pool yes
i think
also get_current_pool returns a lot of UNAVAILABLE strings so i recommend using SMODS.get_clean_pool with the same args
you generally shouldnt use get_clean_pool
there is a very good reason thet vanilla uses UNAVAILABLE strings
so the pool size doesnt actually change and the outcome only changes if the roll wouldve been something unavailable and it has to reroll
with get_clean_pool the pool size varies and a completely unrelated joker being in the pool or not could affect spawns
i understand there are best practices, but for my purpose i really just need something to get a random vanilla key from a not hardcoded list
honestly I can't find a good use case for get_clean_pool
so i believe i will be fine???
i mean
get_current_pool allows for that
but also youre using a custom SMODS.ObjectType for the pool so idk why you would need get_current_pool
oh wait grabbing a key
slightly related question, is there a way to grab the atlas x and y value of a joker from its key
or maybe centre
from the center it's center.pos
local pool = get_current_pool('pool_key')
local selected_key = pseudorandom_element(pool, 'modprefix_seed')
local it = 1
while selected_key == 'UNAVAILABLE' do
it = it + 1
selected_key = pseudorandom_element(pool, 'modprefix_seed_resample'..it)
end
``` its just this
from the key its G.P_CENTERS[key].pos
i might sneak this as a util function into smods so people dont get enticed into using get clean pool everywhere
ah wait
nvm eremel is doing the weight stuff
i recall eremel adding a util function for that already
and also why was get clean pool ever a thing
dunno
ok one last unrelated question
how do you change which loc key a card is using with code again
like changing its name and description
i think its trying to turn text into a number
did you accidentally use a string instead of a number somewhere?
ok this is line 178 from theSuite
set_sprites = function(self, card, front)
G.E_MANAGER:add_event(Event({
blockable = false,
func = function()
if card.ability then card.children.center:set_sprite_pos({x = card.ability.extra.spriteX[card.ability.extra.anchorSuit .. card.ability.extra.followSuit], y = card.ability.extra.spriteY[card.ability.extra.anchorSuit .. card.ability.extra.followSuit]}) end
return true
end
}))
end
it's the func of this event
spriteX and spriteY are key based dictionaries
idk its something to do with the x = and y =
so it worked fine before, but maybe the order it define things are different?
i just copied the code from earlier into this event
i even checked card.ability exists
why cant you just if card.ability then card.children.center:set_sprite_pos( card.ability.extra.spriteX[card.ability.extra.anchorSuit .. card.ability.extra.followSuit], card.ability.extra.spriteY[card.ability.extra.anchorSuit .. card.ability.extra.followSuit]) end
wait you dont need to assign them to x and y resperctively?
unrelated but for debugplus is there a command to spawn a joker into the shop
i dont think so, i think that may solve the problem because it says the problem is at x
No?
I think you have to just do add_card but set the area to G.shop.cards?
that won't give it the shop ui
if context.selling_self and card.ability.extra.extra_value == 0 then
local newegg = SMODS.add_card{ key = "j_busterb_eggman" }
newegg.sell_cost = 0
end```
wtf
ok there
so
i hope this thing actually gets 0 sell value
sell value is hardcoded to be 1 if less than 1
why? i have no clue
because voucher half buy prices, and sell price is directly half of buy price
ah right
so basically prevents it being /8 into rounding down to selling for 0
herelua if context.selling_self and card.ability.extra.extra_value == 0 then local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_busterb_eggman", "eggman") card.sell_cost = 0 card:add_to_deck() G.jokers:emplace(card) end
So I believe quantum enhancement used to have some infinite recursion prevention but it's no longer the case? because as long as the card is highlighted it's pilling up events
is this in latest dev?
latest release
i know there are some things fixed in dev
hmm ok
because i've seen multiple reports of quantum enhancements being broken in different ways (which all make the game very slow in general) since the 1503 release
yeah that is known
if it's fixed in dev that's cool, tho we'll have to wait for a release for most people to actually get the fix
still, you should try it out yourself in dev
maybe that specifically didn't get fixed
sure
fuck i never thought about this
if theres no way to force spawn a joker in shop
how tf am i gonna test
an "easy" way is to get all jokers of the same rarity in your joker lineup, then reroll the shop until it spawns
make a temporary tag that makes that joekr spawn in shop, then spawn that tag
you can also install #1458048711799079034
there's a reroll shop feature to reroll until a chosen card appears
i have some custom code in my mod to spawn a tag for that lol
how to check if sell value is 0 or at the very least lowest possible
Can confirm this is fixed in 1514a
bro, i think half the things you're asking about, you can recreate in jokerforge and see how jokerforge does it
or just check vanillaremade code
that too
like here you can just check how swashbuckler gets other jokers sell value
or temperance
rip
is my joker borken or is my luck just ass
i've done 200 rerolls and it hasnt showed up once for my testing
ah, i finally got it to show up
IVO ROBOTNIK?!?
and of course it didnt work
ok how do you make it so that if the sell value is 0, it actually disappears for good and doesn't clone itselflua if context.selling_self and card.ability.extra.extra_value ~= 0 then local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_busterb_eggman", "eggman") card.sell_cost = 0 card:add_to_deck() G.jokers:emplace(card) end
same question as yestderday i think
what's the """""proper""""" way to have a card run something when it appears in shop
What did I miss? Sorry about that, I just woke up.
One of those gamling ads idk
gamblin is a peglin themed mod for this game
if anybody could help me out, tell me```lua
SMODS.Joker {
key = "eggman",
unlocked = false,
atlas = "bb_legendary",
blueprint_compat = true,
pools = { ["bustjokers"] = true },
rarity = 4,
cost = 0,
pos = { x = 0, y = 4 },
soul_pos = { x = 0, y = 5 },
config = { extra = { start = 0, gain = 3 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.start, card.ability.extra.gain } }
end,
add_to_deck = function(self, card, from_debuff)
for k, v in ipairs(G.jokers.cards) do
if v.key == "j_busterb_eggman" then
card.ability.extra_value = 0
end
end
end,
calculate = function(self, card, context)
if context.selling_self then
if to_big(card.ability.extra.extra_value) ~= to_big(0) then
local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_busterb_eggman", "eggman")
card.sell_cost = 0
card:add_to_deck()
G.jokers:emplace(card)
end
end
if context.selling_card and context.card.ability.set == "Joker" then
card.ability.extra_value = card.ability.extra_value + card.ability.extra.gain
card:set_cost()
return {
message = localize('k_val_up'),
colour = G.C.MONEY
}
end
end
}
extra value isn't in the extra table, so that check will always be true (nil ~= 0)
you also shouldn't have to do to_big anymore, now that amulet is available
(i mean if you want to be backwards compatible with talisman, you can, but people really should be using amulet these days)
I thought it would be easy to make a joker that does what it’s ability would say
This joker specifically
It’s 12 AM… I don’t wanna work on the mod tonight… or today idk.
try starting from 1$ if 0$ doesn't work
hmmmm
that's not supposed to happen
Honestly that's even better lol
For an ante 8 boss lol
i mean sure, i cant deny it fuckin rocks!!
but i'm tryna think balanced here lmao
but then again, it is a great punisher
the bigger your hand size, the worse you get it
you can also deckfix on ante 8 lol
it also hard counters things like Steel Cards or Shoot the Moon/Baron builds
which i think is neat
you're passing the whole cards table to destroy cards
when you only want the selected one by pesudorandom
also, you need to remove the card from the _cards list after picking or it might pick the same card more than once
also while it probably does nothing you should remove the discard cards from highlighted bit in case it tries to discard a destroyed card and you end up with ghost cards
Good idea, thx
where would i be able to edit the ui of the hands and discards exactly?
or would i have to go around and search via nodes
How do you force a crash?
that would do it, thank you
ngl, im not sure how to do that one
local value, index = pseudorandom_element(...)
if selected then table.remove(_cards, index) end
tyy
what is that line in the lovely dump?
I'm guessing G.playing_cards doesn't exist at the point this is called?
can someone tell me what ive done please? Im really knew to modding, so i have no clue
This joker is supposed to give 8 mult then make another version of itself at the end of the round, but it crashes every time i do it. If i use a vanilla joker it works, if i use smods.create_card with a modded joker it works, but smods.add_card with a modded joker just causes it to crash. Whats weirder as well is that it doesnt crash like usual and give a report, it just freezes and doesnt respond.
heres the code:
SMODS.Joker {
key = "tatoo_you",
config = { extra = { mult = 8, odds = 2 } },
loc_vars = function(self, info_queue, card)
return {
vars = { card.ability.extra.mult, card.ability.extra.odds, G.GAME.probabilities.normal or 1 }
}
end,
calculate = function(self, card, context)
if context.joker_main then
return {
mult = card.ability.extra.mult
}
end
if context.end_of_round and not (context.individual or context.repetition) then
SMODS.add_card({ set = 'Joker', area = G.jokers, key = "j_jojo_tatoo_you" })
end
end
}
(odds bit it still there cause i plan to make it a 1 in 2 when i get this working)
Anyone know what function i can hook into for a function to trigger when the first hand is drawn? Trying to do something similar to the idol but only for cards in the first hand
okay at this point it is just trolling
like fuck do you mean attempt to index in to nil
you can use context.first_hand_drawn in calculate
you wrote abilty
😭
if it adds itself then it will do infinitely
what you should do is save the card added with add_card in a variable and add a flag to it like added_card.modprefix_created_by_me = true and if it has that flag then it doesn't add anything
-# or use an event
also yeah
that makes so much sense, thank you
ill look into how to do that lol
an event is probably better because you also need to clear the flag
i didnt think it would trigger after being added
yeah i could but i wanna make this run so that if you randomly got the joker after the first hand is drawn it would still work even if you didnt have it at the time
so you want the first card drawn for the blind or the first after it gets added?
first for the blind
then what did you mean here
i didn't mean this as a one or the other btw
i meant if you want it to do both
Basically i want it work where a card in the first drawn hand is selected regardless of if the joker is there so that if you get the joker a hand into the round it doesnt check again but knows what card was selected from that first hand drawn
ah i understand
use mod calculate
SMODS.current_mod.calculate = function(self, context)
ahh didnt know that was a thing, thought only cards ran calculates. thanks!
cards, blinds, decks, stakes, modifiers, challenges, and the mod all have a calculate
i think the only thing that doesn't is tags (they have apply_to_run instead)
soon(tm)
what about adding inject_card to undiscovered sprites?
or just any way to add custom sizes lol
i dont remember there being anything for that
idk exactly how undiscovered stuff works since i always make all my cards discovered but i could take a look
how do i make a joker hide modtag but temporarily
exactly, there isnt anything for it, not in UndiscoveredSprite at least -w-
i meant i dont remember there being anything in the pipeline to fix that
ah, i see
to be clear, you mean the label at the bottom with the mod's name?
ye
hmmmm
i cant think of any way you could tbh
Before I post it, I know some communities feel strongly about ai assisted dev, so is an ai made qol mod ok? One to update mods and one to sort mods, no ai art used.
at least you asked respectfully
Understood I'll refrain 🙂
how do i grab the loc var return of a joker
like for example i want to grab the var Popcorn is returning
but like to use with my joker
G.P_CENTERS[key]:loc_vars({}, card)
and just discard the info queue table
though I'm not 100% on if that'll work on a vanilla joker, with how thunk defined everything in one big if-then statement
it's worth a shot tbh
first half of the hard part is almost there
better to try and fail than to not try at all
given that it's a known joker, you can probably dig the relevant variable out of the center config
yeah problem is that it's not known
or the card ability, if you want the decayed version
which one do you think it is
SMODS.find_card("j_popcorn")[1]
not the second one that's from my mod
though that wouldn't find cards still in the shop, if you care about that
what are you planning to do with this return value anyway?
just feed it into loc var
you can also probably invoke the vanilla loc vars function, if you dig it out of the vanilla source
for what purpose?
yeah probably just find a way to invoke vanilla loc_vars
rip
i don't recall what the function is called and I'm at work rn but it's in the vanilla code and searching for j_diet_cola should bring you to it
(along with like every other joker related function but yk)
Since its vanilla its most likely "Diet Cola" in the loc vars
ok but i would like to also not do 150 checks like vanilla
Because we love hardcoded self.ability.name checks
that's true
you'd want to pass the center instead of your joker, i think?
ideally if possible
so instead of Card:whatever vanilla loc vars is called(card, etc) it's like Card.whatever it is(G.P_CENTERS[key], fake card?, etc)
i don't know the parameters the function takes lol
answer : ||real Diet Cola is not full to the brim||
actually I'm almost sure the vanilla function runs on the card directly without passing the center
argh this is hard to think about without access to vanilla code
if even cryptid threw a concept away then im fucked i think
i don't think it's impossible to do, i just can't give very specific advice without code access
like, have you looked at the vanilla loc vars function?
trying to find where it is
like i understand you cant have a code dump on a decent site like github because then that is just piracy but also arg
too bad balatro isn't structured like doom, where you could release the engine source code but keep the game content proprietary
||diet cola if the packagers WERENT COWARDS||
oof
What is the concept?
Prototype of the Bear 5 card
i think i have to hook into the bit that generates the tooltip ui for jokers
which is
worrying
how do i check the number of remaining hands the player has again?
i want to check for when this hits 0 and then manually cause a game over
question how do i fix this so that people with amulet can still use the mod since it provides talisman?
Update talismen
read the entire message again 😭
amulet supposedly provides talisman
i have to imagine its due to the version dependency
Maybe amulet doesn't have the correct version?
doesnt work .w.
Try the official version of talisman see what happens
nah that didn't work either
Amulet says 3.5.0
Thats definitely higher than 1.7.0
like im told amulet is better talisman and whatever and that it should just work?
-# header jank maybe?
but it doesn't?
^
It could be maybe the mod is looking for the official version of tailsman and not amulet
i have to imagine it's just the fact that youre using legacy headers
No
Thats
because i have made mods that depend on talisman and amulet works fine for them
how do new headers work?
See mod metadata page on steamodded wiki
there should be a section about it on the
yeah
You are not calling the reference
instead of local ret = hangedman_imposterous_generate_card_ui_hook (holy long name)
you should do local ret = hangedman_imposterous_generate_card_ui_hook(self)
And also thats. Not how you create the reference
nvm, it's correct, i just wrote the if statement wrong lol
You shouldnt be calling the function when creating it
^
the goal is for it to overwrite the ui if it's this specific joker
no i know
This just isnt how you hook in general
im just stating my goal to make it easier for you to point me toward doing it correct
you should
set the original reference to the function, not the results of the function
make sure you call the original function
also should probably not call the original function if it is that special card, since otherwise youre leaving a ton of probably-orphaned ui
also don't use card or Card to refer to the card that's calling the function, use self
lua's method calls (:) implicitly define self as a variable which refers to the table calling the function
im basing on the guide on vanillaremade but yeah that was a func with args and this doesnt, so i guess i can see why it doesnt work the same
is it this???
the args aren't what's wrong
ya basically
say youre hooking some function thats a part of a card, to replace it with no side effects it'd look like this
local ref = Card.func
function Card:func()
return ref(self)
end
you still need to refer to the original function properly (Card.generate_UIBox_ability_table)
hooking works because functions in lua are literally variables
eh???
stop calling the function to define your ref!!!
You shouldnt call it when creating the reference
how many lightbulbs does it take to hook one function
two brights one and a dim one
"calling" a function is when you () it
calling it means that you don't get a reference to the original function, you get the results of it, which means you can't access the original function itself
local ret = function(parameters) -- Calling the function with the parameters and putting the return value in "ret"
local ref = function -- Putting the *actual function* into "ref"
i dont actually know if this would work but thats just because this is being called on a card and youre calling it on a center when it's disgusied
normally a card is passed into generate_uibox_ability_wtv
but in this case its passing in the center (basically the prototype object)
yeah i think this might just be a different way to do the thing that turned out not to work before
ag
though i know fake cards are a thing, you might be able to use those
so id do this and just throw it in here?
the collection uses them
yep
and make sure to remove the legacy header info from the top of your lua file
its not necessary iirc but its just useless now
Not removing the header can make it load twice iirc?
smods might have implemented a measure against that at some point but there's no reason to leave the header in
Think of the 0.9.8 players /j
0.9.8 compat is like making sure that your country's due process is still compatible with people who have passports from 1776
frankly I'm surprised smods itself keeps backwards compatibility for 0.9.8 mods
so why isn't this working?
send the code
check the logs in the lovely folder, there's probably a relevant error message
if it's the hook part
local hangedman_imposterous_generate_card_ui_hook = Card.generate_UIBox_ability_table
function Card:generate_UIBox_ability_table()
local target = self
if self.config.center_key == "j_hangedman_imposterous" and self.ability and self.ability.extra.disguisingAs then
target = G.P_CENTERS[self.ability.extra.disguisingAs]
end
local ret = hangedman_imposterous_generate_card_ui_hook(target)
return ret
end```
the entire thing
ignore the backticsk thats discord markdown getting flushed in
you didn't do the hook wrong
but as ophelia said, the intercepted version calls the function on a center instead of a card, which doesn't seem to work
how do i convert it to card
INFO - [G] 2026-03-15 14:30:37 :: ERROR :: Loader :: Found invalid metadata JSON file at C:/Users/EricT/AppData/Roaming/Balatro/Mods/Fortlatro/Fortlatro.json, ignoring: [lovely json "libs/json/json.lua"]:185: expected ']' or ',' at line 16 col 4
look for the function that makes fake cards for the collection
Is there a way to see if a joker has any sticker? I see how to get specific ones, but I'm not sure about just in general
iterate over SMODS.Stickers and check each one individually
centers don't contain cards
cards contain centers
ah i see it wanted commas here
okay then i have bigger problems
so the card object has to remain the imposterous, but i have to somehow feed it the fake key/name
hm
well fortlatro supports amulet now w for the people using that
heck
i dont think this is what i wanted
i mean i passed the card into it but uhh
it is a funny effect but not what i wanted to do with it
if im desperate enough i might keep it
woe, obstructions be upon ye
lol
how could you check if a joker can have stickers like eternal or perishable applied or not?
card.config.center.sticker_key_compat ~= false
if SMODS.Stickers['modprefix_key']:should_apply(card, card.config.center, card.area, true)
does that work with vanilla stickers? i was getting some mixed messages if it does
Yes, it does.
I keep getting this error when this function runs. I just have it running in an if check, so I'm not sure what is going on exactly
Code?
use = function(self, card, area, copier)
local eternal_check = card.ability.eternal or false
local eternal_compat = SMODS.Stickers['eternal']:should_apply(card, card.config.center, card.area, true) or false
local joker = G.jokers.highlighted[1]
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.4,
func = function()
for k, v in pairs(SMODS.Stickers) do
-- print(v)
if v ~= SMODS.Stickers.eternal then
v:apply(joker, nil)
end
end
if eternal_check then
SMODS.Stickers.eternal:apply(joker, nil)
elseif eternal_compat then
SMODS.Stickers.eternal:apply(joker, true)
end
return true
end
}))
end,
can_use = function(self, card)
if #G.jokers.highlighted ~= 1 then
return false
end
local sticker_check = false
for _, sticker in pairs(SMODS.Stickers) do
if G.jokers.highlighted[1].ability[sticker.key] then
sticker_check = true
end
end
if sticker_check then
return true
elseif SMODS.Stickers['eternal']:should_apply(card, card.config.center, card.area, true) then
return true
else
return false
end
end
If should be: ```lua
local eternal_compat
if type(SMODS.Stickers['eternal'].should_apply) == 'function' then
eternal_compat = SMODS.Stickers['eternal']:should_apply(joker, joker.config.center, joker.area, true)
elseif joker.config.center.eternal_compat then
eternal_compat = joker.config.center.eternal_compat
else
eternal_compat = false
end
whats the issue with this hand?
key = "house_down",
visible = true,
mult = 15,
chips = 150,
l_mult = 7,
l_chips = 75,
loc_txt = {
name = "House Down",
description = {
"Both a Full House and a Down"
}
},
example = {
{ 'S_A', true },
{ 'S_A', true },
{ 'C_A', true, enhancement = 'm_wild' },
{ 'D_K', true },
{ 'D_K', true }
},
evaluate = function(parts)
local down = parts.djvxx_down
if not next(down) then
return {}
end
if #parts._3 < 1 or #parts._2 < 2 then
return {}
end
return {SMODS.merge_lists(parts._all_pairs, down)}
end
})```
Nothing, this always comes ups false. I tried with a few jokers and it looks like the second SMODS.Stickers['eternal'].should_apply == false statement always triggers, leading to eternal_compatalways being false
SMODS.merge_lists takes a table of tables
i.e.
local table1 = { bla, bla1, bla2 }
local table2 = { bla3, bla4, bla5 }
local merged = SMODS.merge_lists{ table1, table2 }
so you could get away with turning it into a table call, but if that still causes issues, try returning just the function result as it returns a table and as is, that will be a nested table
i have no experience with custom hands though, that's all i notice
Hey I'm pretty new to Lua and wanted to try out something simple to get a understanding of balatro modding (Since I want to make a mod), so I decided the first step would be taking one of the example mods and turning it into something new... can someone explain why even when I dumbed it down to effectively the exact same text as the Deck of 4s from the example mod it crashes the game on start up?
SMODS.Back{
name = "Deck of Faces",
key = "faces",
pos = {x = 1, y = 3},
config = {Jack = "4", Queen = "Queen", King = "King"},
rng = random.math(0,3),
loc_txt = {
name ="Deck of Faces",
text={
"Start with a Deck",
"full of {C:attention}random{} Face Cards",
},
},
apply = function(self)
G.E_MANAGER:add_event(Event({
func = function()
for _, card in ipairs(G.playing_cards) do
assert(SMODS.change_base(card, nil, self.config.Jack))
end
return true
end
}))
end
}```
(I'm probably going to be frequenting here a lot tbh since I'm very new and have little experience...)
can you post the crash log?
Oh sure
I think this should be it
ah it's math.random
honestly i would not do random faces but try to spread them out eveenly
idk what that line is trying to do however
It was there before I dumbed down the line
That was the plan but I wanted to just
Get the logic to change the faces through a variable
So I can later edit said variable to be based on the value of the cards themselves
Rather then
Random
in the smods example?
No it was before I tried to retrace my steps to see what was crahing everything
Thank you
ah ok
and you can check how checkered deck changes the deck
-- Checkered Deck
SMODS.Back {
key = "checkered",
pos = { x = 1, y = 3 },
unlocked = false,
apply = function(self, back)
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
if v.base.suit == 'Clubs' then
v:change_suit('Spades')
end
if v.base.suit == 'Diamonds' then
v:change_suit('Hearts')
end
end
return true
end
}))
end,
locked_loc_vars = function(self, info_queue, back)
local other_name = localize('k_unknown')
if G.P_CENTERS['b_black'].unlocked then
other_name = localize { type = 'name_text', set = 'Back', key = 'b_black' }
end
return { vars = { other_name } }
end,
check_for_unlock = function(self, args)
return args.type == 'win_deck' and get_deck_win_stake('b_black') > 1
end
}
but instead of checking for suits you check for ranks
the deck of fours example is fine too
you can check the rank by doing this
v:get_id() == 13 -- Ranks 2-10 are IDs 2-10, Ace is 14.
Would something like this work or is the syntax wrong?```lua
-- Checkered Deck
SMODS.Back {
key = "checkered",
pos = { x = 1, y = 3 },
unlocked = false,
apply = function(self, back)
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
if v.base.value == ('1', '2', '3') then
v:change_value('Jack') --editted part
end
if v.base.suit == 'Diamonds' then
v:change_suit('Hearts')
end
end
return true
end
}))
end,
locked_loc_vars = function(self, info_queue, back)
local other_name = localize('k_unknown')
if G.P_CENTERS['b_black'].unlocked then
other_name = localize { type = 'name_text', set = 'Back', key = 'b_black' }
end
return { vars = { other_name } }
end,
check_for_unlock = function(self, args)
return args.type == 'win_deck' and get_deck_win_stake('b_black') > 1
end
}```
Oh
Id not value
Oh wait yeah value is set based on id right? I remember seeing that in the "Cards.Lua" code
if v:get_id() == 2 or v:get_id() == 5 or v:get_id() == 8 or v:get_id() == 14 then
assert(SMODS.change_base(v, nil, 'Jack'))
end
if v:get_id() == 3 or v:get_id() == 6 or v:get_id() == 9 then
assert(SMODS.change_base(v, nil, 'Queen'))
end
if v:get_id() == 4 or v:get_id() == 7 or v:get_id() == 10 then
assert(SMODS.change_base(v, nil, 'King'))
end
something like this
theres probably a more elegant and mathematic way to do this but eh
Ah ok
i commented the change_value thing because i'm unsure how to do it
right
name
i changed the above snippet
since its in a event function i guess you could put in in assert hold on
So put all together it would be:
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
if v.get_id == 1 then
v:SMODS.change_base(v, nil, 'Jack')
end ```
to change the value of all 1s into jacks
1 doesn't exist, if you want Ace it's 14
Do you think there is a way to put a card sprite on top of another? I dont want to make sprites for each possible Totem (consumable) combination
Oh right
canvassprites might also work but im bad at those to explain
I thought it would just default to 2
-- Checkered Deck
SMODS.Back {
key = "deck_of_faces",
pos = { x = 1, y = 3 },
unlocked = true,
apply = function(self, back)
G.E_MANAGER:add_event(Event({
func = function()
for k, v in pairs(G.playing_cards) do
if v:get_id() == 2 or v:get_id() == 5 or v:get_id() == 8 or v:get_id() == 14 then
assert(SMODS.change_base(v, nil, 'Jack'))
end
if v:get_id() == 3 or v:get_id() == 6 or v:get_id() == 9 then
assert(SMODS.change_base(v, nil, 'Queen'))
end
if v:get_id() == 4 or v:get_id() == 7 or v:get_id() == 10 then
assert(SMODS.change_base(v, nil, 'King'))
end
end
return true
end
}))
end,
}
i mean i guess i could put a empty soul pos
thats one of the ways i thought of
you should remove the locked loc vars and check for unlock
yea
wdym?
like a soul pos with a blank sprite, until its "combined" then soul pos changes to the head sprite
ah yeah i do that for one of my mods
and i guess to merge and separate them i'd use consumables
I assume it's because it needs a back texture since it only crashes when I click to it in the deck selection
remove locked loc vars and check for unlock functions
those are incorrect here
also i recommend installing the release version of smods instead of the latest commit
I'm looking into context.modify_shop_card and I want to use it to change the first card in a shop line up but I'm not sure how to go about it. G.shop_jokers.cards[1] doesn't seem to work
what's the goal?
Having specific jokers or Tarots appear at certain shops
do you want it to work like tags where they replace the first card of the set or always the first in the shop?
first card no matter the set (so a joker could replace a planet, for example)
you should probably use create_shop_card instead and return the card you want the first time it's called
fuck
you can check context.starting_shop to set a flag and context.ending_shop to remove it
it seems like create_shop_card is checked before starting_shop shop. i don't see the modified shop card until i reroll (which is not ideal)
if i'm using a smods hold keybind, how do i get when it's released?
My workaround for now will be using context.blind_defeated for now. Somewhat serves the same purpose for what I need
for anyone that uses jokerforge, would you be able to explain the variables to me? i am trying to make a joker that prevents a blind from ending until all hands are played but i cant figure out how to work it
the basic thing i want to do is say "when hand is scored, if total score would exceed the blind (i.e. end the blind) & hands remaining are > 1 (so that you can actually still leave the blind once hands are gone), then reset the target blind to be your total score +1"
but it seems like the Blind Requirement condition and the Modify Blind Requirement effect are not working properly and not really letting me set the right numbers
for realskies?
yes
like the .lua file?
yes
coming right up
i will just make the code work but not clean it up to normal coder standards, you will still have forgeslop
yeah of course, i want the slop
ew
fuck when i set the blind requirement it does it before it finishes scoring despite me putting in context.after
yeah thats weird
just throwing ideas out there, would it maybe be possible to calculate the score before the hand is actually played, and then if the hand is played and before the cards are scored, increase blind to calculated value +1?
definitely clunky but idk if that would solve the problem
omg it works thank you
yay! success?
wait
okay tyt! thank you so much again
why u saying ty and thank you
SMODS.Joker{ --Walter White
key = "walterwhite",
loc_txt = {
['name'] = 'Walter White',
['text'] = {
[1] = 'Does not exit a {C:attention}Blind{}',
[2] = 'until all hands are played'
},
['unlock'] = {
[1] = 'Unlocked by default.'
}
},
pos = {
x = 0,
y = 0
},
display_size = {
w = 71 * 1,
h = 95 * 1
},
cost = 6,
rarity = 2,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = true,
atlas = 'Joker',
pools = { ["modprefix_mycustom_jokers"] = true },
loc_vars = function(self, info_queue, card)
return {vars = {(G.GAME.chips or 0)}}
end,
calculate = function(self, card, context)
if context.after and context.cardarea == G.jokers and not context.blueprint then
return {
func = function()
G.E_MANAGER:add_event(Event({
func = function()
if (SMODS.last_hand_oneshot or G.GAME.chips >= G.GAME.blind.chips ) and G.GAME.current_round.hands_left > 0 then
card_eval_status_text(card, 'extra', nil, nil, nil, {message = "Not Done Yet.", colour = G.C.GREEN})
G.GAME.blind.chips = math.floor(G.GAME.chips + 1)
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
end
return true
end
}))
end
}
end
end
}
tyt is take your time
oh
yeah minimum hands had to me > 0 because the hands get substracter before context.after is calculated
will do, thank you for the help
@wanton jolt how would you normally add this in outside of jokerforge?
Ok nothing’s working.
well i would just not have the loc_txt in the joker file
because i handle loc in a separate file
ok why tf am i not allowed to add or subtract the set value 0?
wdym start is a nil value?
What's your code and what's the exact error?
i wrote card.ability.start instead of card.ability.extra.start, otherwise it's still not working as intended
eggman either ignores the "if sell value is 0" argument or is permanently sold even when the sell value is not 0
What's your code for that joker?
SMODS.Joker {
key = "eggman",
unlocked = false,
atlas = "bb_legendary",
blueprint_compat = true,
pools = { ["bustjokers"] = true },
rarity = 4,
cost = 1,
pos = { x = 0, y = 4 },
soul_pos = { x = 0, y = 5 },
config = { extra = { start = 0, gain = 3 } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.start, card.ability.extra.gain } }
end,
add_to_deck = function(self, card, from_debuff)
for k, v in ipairs(G.jokers.cards) do
if v.key == "j_busterb_eggman" then
card.ability.extra_value = 0
card.ability.extra.start = 0
end
end
end,
calculate = function(self, card, context)
if context.selling_card and context.card.ability.set == "Joker" then
card.ability.extra_value = card.ability.extra_value + card.ability.extra.gain
card.ability.extra.start = card.ability.extra.start + card.ability.extra.gain
card:set_cost()
return {
message = localize('k_val_up'),
colour = G.C.MONEY
}
end
end,
remove_from_deck = function(self, card, from_debuff)
if G.jokers then
if card.ability.extra.start < 1 then
return true
else
local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_busterb_eggman", "eggman")
card.sell_cost = 0
card:add_to_deck()
G.jokers:emplace(card)
end
end
end,
}```
i forgot to remove the comment, i stole this from egg
I don't think the remove_from_deck function allows you to prevent destruction? I think it's just a "do things in response to being destroyed" type of function.
Try using context.joker_type_destroyed in your calculate instead. This does let you return {no_destroy = true} when you want to prevent the destruction. Just check to make sure context.card == card alongside everything else.
i was thinking of selling_self but idk if this also works
No clue. The smods wiki page on calculate functions only mentions joker_type_destroyed having any way to prevent destruction, but it's also not necessarily the most up-to-date thing in the world.
somethingcom save me
it is the only way
wait, context.card == card?
what are you trying to do? i didn't understand your description very well
Because joker_type_removed responds to everything gettin destroyed (except playing cards), whereas what you were using before, remove_from_deck was only called for the joker itself being removed.
ok so, dr. eggman, legendary, he always starts at 0 sell value, it increases by 3 each time a joker is sold, and when you sell him, he reverts back to 0 sell value. if you sell him at 0 sell value, he disappears completely.
ah ok, i don't think this is something you can do with only the api
you would probably need to hook the sell function
ah
i'll have to change his ability then
-# To be fair that looked kinda weak for a legendary anyways
-# went with the egg route and made him an econ joker. maybe i can give the old ability of ultra greed and give it to eggman instead.
either that or you can suggest a different ability altogether
the original ability was supposed to take from wario.
instead of selling a joker, it's when a joker is triggered
how do i make it so a joker can't be debuffed at all when/if a certain sticker is applied on it
local old_set_debuff = Card.set_debuff
function Card:set_debuff(should_debuff)
old_set_debuff(self, should_debuff)
if self.ability.yourmodprefix_stickerkey then
self.debuff = false
self.perma_debuff = false
end
end
My mod has the exact same idea, this is what I did for it.
awesome thanks
you can also use SMODS.debuff_card
Hey guys, do you know how I could make one of the tags that appears on ante 2+ appear on ante 1?
I've been trying this, but it doesn't quite work.
return (G.GAME.round_resets.ante >= 1)
end,```
Use > not >=
>= means "greater than or equal" meaning 1 and above
> just means "greater than" so anything above 1, but not including 1.
Wouldn't that make it not appear on ante 1? that's what I want.
vanilla tags use min_ante to limit spawning
you want to remove that field when taking ownership
Oh I just misread, sorry.
I don't know been trying it and it just doesn't show up
probably some vanilla jank
I'm trying to change the meteor tag
<@&1133519078540185692>
bam
epic lolhappy win
Is the game hard coded to do Xmult after +mult
Aight, got it working. For posterity:
min_ante = nil, doesn't work. min_ante = 1, does.
or use events?
I'm wanting a rekoj that does +mult after ÷mult (Xmult below X1)
But my coder said it's impossible without changing the inherent order for mult calculation
could you do just x1/divisor mult
oh
you can use like
SMODS.calculate_effect
Are you talking about the ÷mult or the mult order
The ÷mult is already handled
÷1.2 just equates to approximately X0.83333 so I just had it do that
mult order
you just order it how you want
For context, is it that the vanilla process favors +mult over Xmult and the smods one allows complete freedom over the order applied?
is there a limit on how many animated jokers you can have
I added another one but the spirte sheet is invisible
everything is in the correct spot
return { xmult = val, extra = { mult = otherval } }
why not
local old_set_debuff = Card.set_debuff
function Card:set_debuff(should_debuff)
if self.ability.yourmodprefix_stickerkey then
return
end
old_set_debuff(self, should_debuff)
end
oh, thanks for leaving me scrolled up discord, very cool
debuff_card is probably also better for it, yeah
what does the atlas look like
It's the same size as the normal vouchers, I would know since I made them
However I didn't code them in, so I know it's a code thing
Oh whoopsie
The size issue is persistent across both the tier 1 and 2 versions so I'm just sending the tier 1
thats just the voucher code
I'm out of it today istg
also you should change unlcocked to unlocked
They have a habit of misspelling things
In fact they accidentally gave 2 rekojes the same name
I don't know where to access the atlas code
I only know about the atlas graphic sheet
i guess yeah
No, it should be 71
So it's 61 px instead of 71 px
SMODS.Atlas({
key = "Vouchers",
path = "bzr_vouchers.png",
px = 71,
py = 95,
})
its 71 instead of 61
Yeah, I meant it as it currently being 61
I have no idea
I didn't even know that until now
If you want point out any more errors for me to fix, I can send them the updated lua file
i mean most things that should be 71 * 95 arent
Such as what
Ok so bizarro misprint is a special case, it's supposed to have a mini rekoj inside of a display window
wait no consumables just doesnt have the border
?
the consumable file itself is similar to the atlas size given so its fine for now
and its the same for misprint
i know i already tried to do something for you about that
The whole grade 10 ordeal has been solved already, at least I hope
So the consumables and "bzr_misprint" are supposed to be 71x95?
no its fine
because the atlas size is the same as their actual image sizes
so there should not be any stretching issues
as far as i am aware
anyway i need to rly do my totems lol
I want to be on the safe side and have it be the standard measurements
All I need to know is if they're meant to be that
for it to be in the standard measurements (idk for misprint and how its coded exactly
the consumables should be in a similar grid size than a joker so 71*95
while the card itself is 63*93
so there should be a left and right margin of 4px and a top and bottom margin of 1px
So while the smods measurement has it be the same grid size as jokers, the atlas sheet can still be the standard 1 px margin on all sides?
well in the case of your consumables
the current smods measurement is the same as your actual sheet file
both are not standard
now you only have one consumable so its not that much of an issue yet
Well 2 really, a tier 1 and a tier 2
i only see morality here
yeah for vouchers you need to add some left and right margin
So instead of 1 px on all sides it's 4 px horizontally and 1 px vertically
And this accounts for both parrallel sides?
just overlay your vouchers on this pic tbh
And the consumables are 4 px horizontally
I just realized, bzr_misprint might just not have the 1px margins, seeing as each measurement is 2 below standard
So it shouldn't matter, seeing as they're to be stuffed inside a card sleeve
Ok I changed the consumable size on both the atlas code and atlass sheet and this is what I got
did u add a margin
Atlas px I made 71x95 as well
It matches the canvas size
The voucher issue is fixed though
did you reload the game or just the atlas
Whole game, but I saved everything before closing

did you also change the 2x? i know that question could be stupid
did you do the 2x for the vouchers?
And I have the game with art smoothing on
No, it's weird
What are you trying to sell me
I have aseprite I can do it on my own
Alright everything is fixed
👍

why is it evil
key = 'effect_give',
primary_colour = G.C.RED,
secondary_colour = G.C.RED,
default = 'PLACEHOLDER',
collection_rows = {4,4},
}
SMODS.Atlas {
key = "effect_give",
path = "../../source/assets/1x/PLACEHOLDER.png",
px = 34,
py = 34
}
SMODS.Consumable{
key = 'PLACEHOLDER',
set = 'effect_give',
pos = {x = 0, y = 0},
}```
you forgot to localise the name

whats the syntax for that 
b_modname_key in dictionary i'm sure
what? 😭
sorry im really bad at this i wont understand unelss its handed to me on a silver platter
do you have a localisation lua
tough
i honestly dont know how to do localisation in the same file as the consumable
lol
but if u end up making a language lua its in
return{
...
misc={
...
dictionary ={
...
k_modname_key = "effect give",
...
},
...
},
}
and k_modname_key is k_[MODNAME]_key?
ah got it okay
in my case felijo
No, it should be b_key_cards
what
what did you put in the dictionnary
k_embr_effectgive_cards = "Effects",
your key is effect_give not effectgive
"prefix": "embr",
is whats in my json
